summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp1
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputadaptor.cpp25
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputadaptor_p.h25
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h2
-rw-r--r--src/3rdparty/webkit/WebCore/WebCore.pro17
-rw-r--r--src/3rdparty/zlib/gzguts.h3
-rw-r--r--src/3rdparty/zlib/zconf.h2
-rw-r--r--src/3rdparty/zlib/zutil.h3
-rw-r--r--src/activeqt/shared/qaxtypes.cpp2
-rw-r--r--src/corelib/animation/qabstractanimation.cpp3
-rw-r--r--src/corelib/animation/qabstractanimation_p.h3
-rw-r--r--src/corelib/concurrent/qtconcurrentfilter.h554
-rw-r--r--src/corelib/concurrent/qtconcurrentfunctionwrappers.h119
-rw-r--r--src/corelib/concurrent/qtconcurrentmap.h632
-rw-r--r--src/corelib/global/qglobal.cpp25
-rw-r--r--src/corelib/global/qglobal.h16
-rw-r--r--src/corelib/global/qnamespace.h4
-rw-r--r--src/corelib/global/qnamespace.qdoc1
-rw-r--r--src/corelib/io/qdiriterator.cpp28
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp1
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp1
-rw-r--r--src/corelib/io/qprocess.cpp97
-rw-r--r--src/corelib/io/qprocess_p.h104
-rw-r--r--src/corelib/io/qprocess_unix.cpp66
-rw-r--r--src/corelib/io/qprocess_win.cpp45
-rw-r--r--src/corelib/io/qsettings.cpp29
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp67
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h1
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp11
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp37
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h5
-rw-r--r--src/corelib/kernel/qpointer.cpp10
-rw-r--r--src/corelib/plugin/qlibrary.cpp13
-rw-r--r--src/corelib/thread/qmutex_unix.cpp13
-rw-r--r--src/corelib/thread/qthread_symbian.cpp12
-rw-r--r--src/corelib/thread/qthread_win.cpp2
-rw-r--r--src/corelib/tools/qbytearray.h11
-rw-r--r--src/corelib/tools/qdatetime.cpp21
-rw-r--r--src/corelib/tools/qelapsedtimer_symbian.cpp2
-rw-r--r--src/corelib/tools/qlocale.cpp16
-rw-r--r--src/corelib/tools/qlocale_icu.cpp224
-rw-r--r--src/corelib/tools/qlocale_mac.mm2
-rw-r--r--src/corelib/tools/qlocale_symbian.cpp167
-rw-r--r--src/corelib/tools/qsharedpointer.cpp22
-rw-r--r--src/corelib/tools/qstring.cpp35
-rw-r--r--src/corelib/tools/qstring.h14
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp4
-rw-r--r--src/corelib/tools/tools.pri5
-rw-r--r--src/dbus/dbus.pro6
-rw-r--r--src/dbus/qdbus_symbols_p.h26
-rw-r--r--src/dbus/qdbusabstractinterface.cpp9
-rw-r--r--src/dbus/qdbusargument.cpp28
-rw-r--r--src/dbus/qdbusargument.h4
-rw-r--r--src/dbus/qdbusargument_p.h8
-rw-r--r--src/dbus/qdbusconnection.cpp93
-rw-r--r--src/dbus/qdbusconnection.h2
-rw-r--r--src/dbus/qdbusconnection_p.h2
-rw-r--r--src/dbus/qdbusconnectionmanager_p.h88
-rw-r--r--src/dbus/qdbusdemarshaller.cpp17
-rw-r--r--src/dbus/qdbusintegrator.cpp119
-rw-r--r--src/dbus/qdbusmarshaller.cpp24
-rw-r--r--src/dbus/qdbusmetatype.cpp16
-rw-r--r--src/dbus/qdbusmetatype_p.h1
-rw-r--r--src/dbus/qdbusserver.cpp25
-rw-r--r--src/dbus/qdbusserver.h3
-rw-r--r--src/dbus/qdbusunixfiledescriptor.cpp316
-rw-r--r--src/dbus/qdbusunixfiledescriptor.h103
-rw-r--r--src/dbus/qdbusutil.cpp100
-rw-r--r--src/dbus/qdbusutil_p.h4
-rw-r--r--src/declarative/debugger/qdeclarativedebug.cpp46
-rw-r--r--src/declarative/debugger/qdeclarativedebughelper.cpp2
-rw-r--r--src/declarative/debugger/qdeclarativedebugserver.cpp30
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp237
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p_p.h16
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview.cpp25
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp20
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp12
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp49
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea.cpp16
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea_p.h3
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea_p_p.h17
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext.cpp23
-rw-r--r--src/declarative/graphicsitems/qdeclarativetext_p_p.h1
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp16
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp58
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p.h5
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput_p_p.h11
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout.cpp15
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextlayout_p.h2
-rw-r--r--src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp5
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal.cpp28
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp21
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h1
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp16
-rw-r--r--src/declarative/qml/qdeclarativeenginedebug.cpp12
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp37
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h2
-rw-r--r--src/declarative/qml/qmetaobjectbuilder.cpp57
-rw-r--r--src/declarative/qml/qmetaobjectbuilder_p.h4
-rw-r--r--src/declarative/util/qdeclarativebehavior.cpp5
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp3
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp4
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel.cpp69
-rw-r--r--src/gui/accessible/qaccessible.h36
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp4
-rw-r--r--src/gui/dialogs/qcolordialog_mac.mm5
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp12
-rw-r--r--src/gui/egl/qegl_symbian.cpp11
-rw-r--r--src/gui/embedded/qvfbhdr.h41
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicslayout.cpp143
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.cpp9
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp8
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp3
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp105
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp4
-rw-r--r--src/gui/gui.pro8
-rw-r--r--src/gui/image/qimagereader.cpp3
-rw-r--r--src/gui/image/qimagewriter.cpp3
-rw-r--r--src/gui/image/qpixmap.cpp8
-rw-r--r--src/gui/image/qpixmapcache.cpp4
-rw-r--r--src/gui/image/qvolatileimage.cpp5
-rw-r--r--src/gui/image/qvolatileimage_p.h1
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp69
-rw-r--r--src/gui/itemviews/itemviews.pri2
-rw-r--r--src/gui/itemviews/qabstractproxymodel.cpp24
-rw-r--r--src/gui/itemviews/qabstractproxymodel.h3
-rw-r--r--src/gui/itemviews/qdatawidgetmapper.cpp2
-rw-r--r--src/gui/itemviews/qidentityproxymodel.cpp587
-rw-r--r--src/gui/itemviews/qidentityproxymodel.h120
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp7
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp2
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp5
-rw-r--r--src/gui/itemviews/qtableview.cpp22
-rw-r--r--src/gui/itemviews/qtableview.h1
-rw-r--r--src/gui/kernel/kernel.pri5
-rw-r--r--src/gui/kernel/qapplication.cpp17
-rw-r--r--src/gui/kernel/qapplication.h6
-rw-r--r--src/gui/kernel/qapplication_qpa.cpp19
-rw-r--r--src/gui/kernel/qapplication_s60.cpp282
-rw-r--r--src/gui/kernel/qapplication_win.cpp54
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h14
-rw-r--r--src/gui/kernel/qcursor_x11.cpp3
-rw-r--r--src/gui/kernel/qdesktopwidget_qpa.cpp12
-rw-r--r--src/gui/kernel/qdesktopwidget_qpa_p.h1
-rw-r--r--src/gui/kernel/qgesturemanager.cpp1
-rw-r--r--src/gui/kernel/qplatformglcontext_qpa.cpp18
-rw-r--r--src/gui/kernel/qplatformglcontext_qpa.h5
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.cpp11
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.h4
-rw-r--r--src/gui/kernel/qplatformnativeinterface_qpa.cpp2
-rw-r--r--src/gui/kernel/qplatformnativeinterface_qpa.h2
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp2
-rw-r--r--src/gui/kernel/qplatformwindowformat_qpa.cpp13
-rw-r--r--src/gui/kernel/qplatformwindowformat_qpa.h11
-rw-r--r--src/gui/kernel/qsessionmanager_qpa.cpp174
-rw-r--r--src/gui/kernel/qt_s60_p.h98
-rw-r--r--src/gui/kernel/qwidget.cpp4
-rw-r--r--src/gui/kernel/qwidget_mac.mm14
-rw-r--r--src/gui/kernel/qwidget_s60.cpp46
-rw-r--r--src/gui/kernel/qwidget_x11.cpp13
-rw-r--r--src/gui/painting/qbezier.cpp49
-rw-r--r--src/gui/painting/qblendfunctions_p.h8
-rw-r--r--src/gui/painting/qbrush.cpp199
-rw-r--r--src/gui/painting/qbrush.h12
-rw-r--r--src/gui/painting/qcolor.cpp128
-rw-r--r--src/gui/painting/qcolormap_qpa.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp306
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp44
-rw-r--r--src/gui/painting/qdrawhelper_p.h256
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp56
-rw-r--r--src/gui/painting/qpaintbuffer.cpp33
-rw-r--r--src/gui/painting/qpaintengine_mac.cpp3
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp81
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp3
-rw-r--r--src/gui/painting/qpaintengineex.cpp46
-rw-r--r--src/gui/painting/qpainter.cpp95
-rw-r--r--src/gui/painting/qpainter.h3
-rw-r--r--src/gui/painting/qpainter_p.h10
-rw-r--r--src/gui/painting/qpainterpath.cpp5
-rw-r--r--src/gui/painting/qprintengine_pdf.cpp5
-rw-r--r--src/gui/painting/qstroker.cpp1
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp2
-rw-r--r--src/gui/painting/qunifiedtoolbarsurface_mac.cpp3
-rw-r--r--src/gui/s60framework/qs60mainappui.cpp9
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp16
-rw-r--r--src/gui/styles/qcommonstyle.cpp16
-rw-r--r--src/gui/styles/qgtkpainter.cpp5
-rw-r--r--src/gui/styles/qgtkstyle.cpp3
-rw-r--r--src/gui/styles/qmacstyle_mac.mm2
-rw-r--r--src/gui/styles/qplastiquestyle.cpp11
-rw-r--r--src/gui/styles/qs60style.cpp55
-rw-r--r--src/gui/styles/qs60style_s60.cpp56
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp7
-rw-r--r--src/gui/styles/qwindowsstyle.cpp6
-rw-r--r--src/gui/styles/qwindowsvistastyle.cpp9
-rw-r--r--src/gui/styles/qwindowsxpstyle.cpp10
-rw-r--r--src/gui/text/qfont.cpp26
-rw-r--r--src/gui/text/qfont.h2
-rw-r--r--src/gui/text/qfont_win.cpp17
-rw-r--r--src/gui/text/qfontdatabase.cpp27
-rw-r--r--src/gui/text/qfontdatabase_mac.cpp7
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp32
-rw-r--r--src/gui/text/qfontdatabase_win.cpp90
-rw-r--r--src/gui/text/qfontengine.cpp18
-rw-r--r--src/gui/text/qfontengine_coretext.mm365
-rw-r--r--src/gui/text/qfontengine_coretext_p.h32
-rw-r--r--src/gui/text/qfontengine_ft.cpp97
-rw-r--r--src/gui/text/qfontengine_ft_p.h18
-rw-r--r--src/gui/text/qfontengine_mac.mm23
-rw-r--r--src/gui/text/qfontengine_mac_p.h4
-rw-r--r--src/gui/text/qfontengine_p.h7
-rw-r--r--src/gui/text/qfontengine_win.cpp17
-rw-r--r--src/gui/text/qfontengine_win_p.h3
-rw-r--r--src/gui/text/qfontengine_x11.cpp14
-rw-r--r--src/gui/text/qfontengine_x11_p.h3
-rw-r--r--src/gui/text/qfontenginedirectwrite.cpp65
-rw-r--r--src/gui/text/qfontenginedirectwrite_p.h13
-rw-r--r--src/gui/text/qfragmentmap_p.h5
-rw-r--r--src/gui/text/qglyphs.cpp99
-rw-r--r--src/gui/text/qglyphs.h19
-rw-r--r--src/gui/text/qglyphs_p.h25
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp10
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.h2
-rw-r--r--src/gui/text/qrawfont.cpp675
-rw-r--r--src/gui/text/qrawfont.h144
-rw-r--r--src/gui/text/qrawfont_ft.cpp138
-rw-r--r--src/gui/text/qrawfont_mac.cpp83
-rw-r--r--src/gui/text/qrawfont_p.h128
-rw-r--r--src/gui/text/qrawfont_qpa.cpp69
-rw-r--r--src/gui/text/qrawfont_win.cpp707
-rw-r--r--src/gui/text/qtextcontrol.cpp19
-rw-r--r--src/gui/text/qtextcursor.cpp42
-rw-r--r--src/gui/text/qtextcursor.h4
-rw-r--r--src/gui/text/qtextdocument.cpp23
-rw-r--r--src/gui/text/qtextdocument.h5
-rw-r--r--src/gui/text/qtextdocument_p.cpp32
-rw-r--r--src/gui/text/qtextdocument_p.h4
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp14
-rw-r--r--src/gui/text/qtextengine.cpp339
-rw-r--r--src/gui/text/qtextengine_mac.cpp4
-rw-r--r--src/gui/text/qtextengine_p.h60
-rw-r--r--src/gui/text/qtextformat.h3
-rw-r--r--src/gui/text/qtextlayout.cpp458
-rw-r--r--src/gui/text/qtextlayout.h11
-rw-r--r--src/gui/text/qtextobject.cpp7
-rw-r--r--src/gui/text/qtextobject.h4
-rw-r--r--src/gui/text/text.pri28
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp2
-rw-r--r--src/gui/util/qflickgesture.cpp4
-rw-r--r--src/gui/util/qscroller.cpp27
-rw-r--r--src/gui/util/qscroller_p.h4
-rw-r--r--src/gui/widgets/qcombobox.cpp6
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp41
-rw-r--r--src/gui/widgets/qdatetimeedit_p.h10
-rw-r--r--src/gui/widgets/qdockarealayout.cpp5
-rw-r--r--src/gui/widgets/qdockwidget.cpp1
-rw-r--r--src/gui/widgets/qlinecontrol.cpp31
-rw-r--r--src/gui/widgets/qlinecontrol_p.h10
-rw-r--r--src/gui/widgets/qlineedit.cpp28
-rw-r--r--src/gui/widgets/qlineedit.h4
-rw-r--r--src/gui/widgets/qlineedit_p.cpp1
-rw-r--r--src/gui/widgets/qlineedit_p.h1
-rw-r--r--src/gui/widgets/qmenu.cpp103
-rw-r--r--src/gui/widgets/qmenu_p.h4
-rw-r--r--src/gui/widgets/qplaintextedit.cpp6
-rw-r--r--src/gui/widgets/qtextedit.cpp1
-rw-r--r--src/gui/widgets/qworkspace.cpp1
-rw-r--r--src/multimedia/audio/qaudioinput.cpp17
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp1
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp9
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h4
-rw-r--r--src/network/access/qnetworkaccesscachebackend.cpp9
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp25
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp2
-rw-r--r--src/network/access/qnetworkcookie.cpp11
-rw-r--r--src/network/access/qnetworkrequest.cpp2
-rw-r--r--src/network/bearer/qnetworkconfigmanager.cpp3
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp14
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.h2
-rw-r--r--src/network/kernel/qhostinfo.cpp2
-rw-r--r--src/network/socket/qabstractsocket.cpp4
-rw-r--r--src/network/socket/qlocalsocket_win.cpp5
-rw-r--r--src/network/ssl/qsslconfiguration.cpp6
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h18
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp39
-rw-r--r--src/opengl/opengl.pro2
-rw-r--r--src/opengl/qgl.cpp11
-rw-r--r--src/opengl/qgl.h32
-rw-r--r--src/opengl/qgl_p.h3
-rw-r--r--src/opengl/qgl_qpa.cpp3
-rw-r--r--src/opengl/qgl_x11egl.cpp10
-rw-r--r--src/opengl/qglextensions_p.h8
-rw-r--r--src/opengl/qpaintengine_opengl.cpp73
-rw-r--r--src/opengl/qpixmapdata_poolgl.cpp13
-rw-r--r--src/opengl/qwindowsurface_gl.cpp83
-rw-r--r--src/opengl/qwindowsurface_gl_p.h4
-rw-r--r--src/openvg/qpaintengine_vg.cpp131
-rw-r--r--src/openvg/qpixmapdata_vg.cpp2
-rw-r--r--src/openvg/qwindowsurface_vg.cpp11
-rw-r--r--src/openvg/qwindowsurface_vgegl.cpp9
-rw-r--r--src/plugins/accessible/widgets/complexwidgets.cpp6
-rw-r--r--src/plugins/accessible/widgets/qaccessiblewidgets.cpp17
-rw-r--r--src/plugins/accessible/widgets/simplewidgets.cpp33
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp4
-rw-r--r--src/plugins/platforms/directfb/qdirectfbglcontext.cpp2
-rw-r--r--src/plugins/platforms/eglconvenience/eglconvenience.pri7
-rw-r--r--src/plugins/platforms/eglconvenience/qeglconvenience.cpp4
-rw-r--r--src/plugins/platforms/eglconvenience/qeglconvenience.h6
-rw-r--r--src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp5
-rw-r--r--src/plugins/platforms/eglconvenience/qeglplatformcontext.h2
-rw-r--r--src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp4
-rw-r--r--src/plugins/platforms/eglconvenience/qxlibeglintegration.h2
-rw-r--r--src/plugins/platforms/eglconvenience/xlibeglintegration.pri7
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp1
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h1
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.h3
-rw-r--r--src/plugins/platforms/fontdatabases/genericunix/genericunix.pri4
-rw-r--r--src/plugins/platforms/glxconvenience/glxconvenience.pri7
-rw-r--r--src/plugins/platforms/glxconvenience/qglxconvenience.cpp243
-rw-r--r--src/plugins/platforms/glxconvenience/qglxconvenience.h56
-rw-r--r--src/plugins/platforms/openkode/qopenkodeintegration.cpp10
-rw-r--r--src/plugins/platforms/openkode/qopenkodeintegration.h6
-rw-r--r--src/plugins/platforms/openkode/qopenkodewindow.cpp10
-rw-r--r--src/plugins/platforms/uikit/README4
-rw-r--r--src/plugins/platforms/uikit/examples/qmltest/main.mm32
-rwxr-xr-xsrc/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj28
-rw-r--r--src/plugins/platforms/uikit/quikiteventloop.h4
-rw-r--r--src/plugins/platforms/uikit/quikiteventloop.mm34
-rw-r--r--src/plugins/platforms/uikit/quikitintegration.mm2
-rw-r--r--src/plugins/platforms/uikit/quikitscreen.mm21
-rw-r--r--src/plugins/platforms/uikit/quikitsoftwareinputhandler.h61
-rw-r--r--src/plugins/platforms/uikit/quikitwindow.h63
-rw-r--r--src/plugins/platforms/uikit/quikitwindow.mm317
-rw-r--r--src/plugins/platforms/uikit/quikitwindowsurface.h23
-rw-r--r--src/plugins/platforms/uikit/quikitwindowsurface.mm209
-rw-r--r--src/plugins/platforms/uikit/uikit.pro4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/gl_integration.pri57
-rw-r--r--src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp52
-rw-r--r--src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h62
-rw-r--r--src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp (renamed from src/plugins/platforms/wayland/qwaylanddrmsurface.cpp)21
-rw-r--r--src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h (renamed from src/plugins/platforms/wayland/qwaylanddrmsurface.h)9
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp174
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h80
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp112
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h82
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp76
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h66
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri14
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp163
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h79
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp97
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h80
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp73
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h65
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri12
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglinclude.h (renamed from src/plugins/platforms/wayland/qwaylandinclude.h)18
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp89
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h70
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp (renamed from src/plugins/platforms/wayland/qwaylandeglwindow.cpp)15
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h (renamed from src/plugins/platforms/wayland/qwaylandeglwindow.h)6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp (renamed from src/plugins/platforms/wayland/qwaylandglcontext.cpp)55
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h (renamed from src/plugins/platforms/wayland/qwaylandglcontext.h)11
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri11
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp169
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h82
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp139
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h98
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp77
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h65
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri15
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp150
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h85
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp126
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h93
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp77
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h65
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri13
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp59
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h62
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h123
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c59
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri9
-rw-r--r--src/plugins/platforms/wayland/qwaylandbuffer.h3
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp239
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.h55
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.cpp31
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.h1
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.cpp31
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.h5
-rw-r--r--src/plugins/platforms/wayland/qwaylandnativeinterface.cpp72
-rw-r--r--src/plugins/platforms/wayland/qwaylandnativeinterface.h60
-rw-r--r--src/plugins/platforms/wayland/qwaylandscreen.cpp1
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmsurface.cpp21
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmsurface.h3
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmwindow.cpp26
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmwindow.h7
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.cpp65
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.h17
-rw-r--r--src/plugins/platforms/wayland/wayland.pro25
-rw-r--r--src/plugins/platforms/xcb/README3
-rw-r--r--src/plugins/platforms/xcb/qdri2context.cpp2
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp238
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp251
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h39
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp39
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp257
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbwindowsurface.cpp64
-rw-r--r--src/plugins/platforms/xcb/qxcbwindowsurface.h2
-rw-r--r--src/plugins/platforms/xcb/xcb.pro3
-rw-r--r--src/plugins/platforms/xlib/qglxintegration.cpp225
-rw-r--r--src/plugins/platforms/xlib/qglxintegration.h9
-rw-r--r--src/plugins/platforms/xlib/qxlibintegration.cpp20
-rw-r--r--src/plugins/platforms/xlib/qxlibintegration.h7
-rw-r--r--src/plugins/platforms/xlib/qxlibnativeinterface.cpp133
-rw-r--r--src/plugins/platforms/xlib/qxlibnativeinterface.h75
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.cpp5
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.h8
-rw-r--r--src/plugins/platforms/xlib/qxlibwindow.cpp15
-rw-r--r--src/plugins/platforms/xlib/xlib.pro7
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro21
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp143
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h81
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp180
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/qostdevice.h75
-rw-r--r--src/plugins/qmltooling/qmldbg_ost/usbostcomm.h191
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro (renamed from src/plugins/qmltooling/tcpserver/tcpserver.pro)4
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp (renamed from src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp)11
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h (renamed from src/plugins/qmltooling/tcpserver/qtcpserverconnection.h)0
-rw-r--r--src/plugins/qmltooling/qmltooling.pro4
-rw-r--r--src/qt3support/text/q3richtext.cpp1
-rw-r--r--src/s60installs/qt.iby20
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp8
-rw-r--r--src/svg/qsvghandler.cpp2
-rw-r--r--src/xmlpatterns/data/qitem_p.h4
-rw-r--r--src/xmlpatterns/expr/qdynamiccontextstore.cpp8
-rw-r--r--src/xmlpatterns/expr/qdynamiccontextstore_p.h2
-rw-r--r--src/xmlpatterns/expr/qevaluationcache.cpp2
-rw-r--r--src/xmlpatterns/expr/qevaluationcache_p.h2
-rw-r--r--src/xmlpatterns/expr/qletclause.cpp2
-rw-r--r--src/xmlpatterns/schema/qxsdattribute.cpp4
-rw-r--r--src/xmlpatterns/schema/qxsdattribute_p.h2
-rw-r--r--src/xmlpatterns/schema/qxsdcomplextype.cpp4
-rw-r--r--src/xmlpatterns/schema/qxsdcomplextype_p.h2
-rw-r--r--src/xmlpatterns/schema/qxsdelement.cpp8
-rw-r--r--src/xmlpatterns/schema/qxsdelement_p.h8
-rw-r--r--src/xmlpatterns/schema/qxsdparticlechecker.cpp6
-rw-r--r--src/xmlpatterns/schema/qxsdsimpletype.cpp4
-rw-r--r--src/xmlpatterns/schema/qxsdsimpletype_p.h2
-rw-r--r--src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp10
464 files changed, 15532 insertions, 4773 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index c202e1f..3410782 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -655,6 +655,7 @@ void HB_GetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
const HB_ScriptItem *items, hb_uint32 numItems,
HB_CharAttributes *attributes)
{
+ memset(attributes, 0, stringLength * sizeof(HB_CharAttributes));
calcLineBreaks(string, stringLength, attributes);
for (hb_uint32 i = 0; i < numItems; ++i) {
diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp
index 2c01773..959172d 100644
--- a/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp
+++ b/src/3rdparty/phonon/phonon/audiooutputadaptor.cpp
@@ -1,3 +1,28 @@
+/* This file is part of the KDE project
+ The following license applies to the edits made to the generated
+ source code:
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (C) 2009 Matthias Kretz.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
/*
* This file was generated by dbusidl2cpp version 0.4
* when processing input file org.kde.Phonon.AudioOutput.xml
diff --git a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h
index 7178e9b..140a74f 100644
--- a/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h
+++ b/src/3rdparty/phonon/phonon/audiooutputadaptor_p.h
@@ -1,3 +1,28 @@
+/* This file is part of the KDE project
+ The following license applies to the edits made to the generated
+ source code:
+
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ Copyright (C) 2009 Matthias Kretz.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
/*
* This file was generated by dbusidl2cpp version 0.4
* when processing input file org.kde.Phonon.AudioOutput.xml
diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h b/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h
index f8bace4..9349b48 100644
--- a/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h
+++ b/src/3rdparty/webkit/JavaScriptCore/wtf/MathExtras.h
@@ -190,7 +190,7 @@ inline float deg2turn(float d) { return d / 360.0f; }
inline float rad2grad(float r) { return r * 200.0f / piFloat; }
inline float grad2rad(float g) { return g * piFloat / 200.0f; }
-#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(ANDROID) && !COMPILER(WINSCW)
+#if !COMPILER(MSVC) && !OS(ANDROID) && !OS(SYMBIAN)
using std::isfinite;
using std::isinf;
using std::isnan;
diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro
index 2de6961..ccb6707 100644
--- a/src/3rdparty/webkit/WebCore/WebCore.pro
+++ b/src/3rdparty/webkit/WebCore/WebCore.pro
@@ -37,15 +37,14 @@ symbian: {
# Need to guarantee that these come before system includes of /epoc32/include
MMP_RULES += "USERINCLUDE rendering"
MMP_RULES += "USERINCLUDE platform/text"
- symbian-abld|symbian-sbsv2 {
- # RO text (code) section in qtwebkit.dll exceeds allocated space for gcce udeb target.
- # Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000.
- QMAKE_LFLAGS.ARMCC += --rw-base 0xE00000
- MMP_RULES += ALWAYS_BUILD_AS_ARM
- } else {
- QMAKE_CFLAGS -= --thumb
- QMAKE_CXXFLAGS -= --thumb
- }
+
+ # RO text (code) section in qtwebkit.dll exceeds allocated space for gcce udeb target.
+ # Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000.
+ QMAKE_LFLAGS.ARMCC += --rw-base 0xE00000
+ QMAKE_LFLAGS.GCCE += -Tdata 0x1000000
+
+ CONFIG += do_not_build_as_thumb
+
CONFIG(release, debug|release): QMAKE_CXXFLAGS.ARMCC += -OTime -O3
}
diff --git a/src/3rdparty/zlib/gzguts.h b/src/3rdparty/zlib/gzguts.h
index 347af46..c752b57 100644
--- a/src/3rdparty/zlib/gzguts.h
+++ b/src/3rdparty/zlib/gzguts.h
@@ -17,7 +17,8 @@
# endif
#endif
-#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#include "qconfig.h"
+#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) && defined(QT_VISIBILITY_AVAILABLE)
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
diff --git a/src/3rdparty/zlib/zconf.h b/src/3rdparty/zlib/zconf.h
index 0105ca4..806a51e 100644
--- a/src/3rdparty/zlib/zconf.h
+++ b/src/3rdparty/zlib/zconf.h
@@ -356,7 +356,7 @@ typedef uLong FAR uLongf;
typedef Byte *voidp;
#endif
-#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+#if defined(HAVE_UNISTD_H) || !defined(WIN32)
# define Z_HAVE_UNISTD_H
#endif
diff --git a/src/3rdparty/zlib/zutil.h b/src/3rdparty/zlib/zutil.h
index 258fa88..8e535ac 100644
--- a/src/3rdparty/zlib/zutil.h
+++ b/src/3rdparty/zlib/zutil.h
@@ -13,7 +13,8 @@
#ifndef ZUTIL_H
#define ZUTIL_H
-#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#include "qconfig.h"
+#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) && defined(QT_VISIBILITY_AVAILABLE)
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp
index c48b55b..8835caf 100644
--- a/src/activeqt/shared/qaxtypes.cpp
+++ b/src/activeqt/shared/qaxtypes.cpp
@@ -265,7 +265,7 @@ bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &type
return QVariantToVARIANT(var, *arg.pvarVal, typeName, false);
}
- if (out && proptype == QVariant::Invalid && typeName == "QVariant") {
+ if (out && proptype == QVariant::UserType && typeName == "QVariant") {
VARIANT *pVariant = new VARIANT;
QVariantToVARIANT(var, *pVariant, QByteArray(), false);
arg.vt = VT_VARIANT|VT_BYREF;
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 602cf8a..0a1f5d7 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -260,7 +260,8 @@ void QUnifiedTimer::restartAnimationTimer()
} else if (!driver->isRunning() || isPauseTimerActive) {
driver->start();
isPauseTimerActive = false;
- }
+ } else if (runningLeafAnimations == 0)
+ driver->stop();
}
void QUnifiedTimer::setTimingInterval(int interval)
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
index ba92960..0ccc502 100644
--- a/src/corelib/animation/qabstractanimation_p.h
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -184,6 +184,9 @@ public:
void restartAnimationTimer();
void updateAnimationsTime();
+ //useful for profiling/debugging
+ int runningAnimationCount() { return animations.count(); }
+
protected:
void timerEvent(QTimerEvent *);
diff --git a/src/corelib/concurrent/qtconcurrentfilter.h b/src/corelib/concurrent/qtconcurrentfilter.h
index e392212..63dcc4b 100644
--- a/src/corelib/concurrent/qtconcurrentfilter.h
+++ b/src/corelib/concurrent/qtconcurrentfilter.h
@@ -115,19 +115,7 @@ ThreadEngineStarter<void> filterInternal(Sequence &sequence, KeepFunctor keep, T
template <typename Sequence, typename KeepFunctor>
QFuture<void> filter(Sequence &sequence, KeepFunctor keep)
{
- return filterInternal(sequence, keep, &Sequence::push_back);
-}
-
-template <typename Sequence, typename T>
-QFuture<void> filter(Sequence &sequence, bool (keep)(T))
-{
- return filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back);
-}
-
-template <typename Sequence, typename C>
-QFuture<void> filter(Sequence &sequence, bool (C::*keep)() const)
-{
- return filterInternal(sequence, ConstMemberFunctionWrapper<bool, C>(keep), &Sequence::push_back);
+ return filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back);
}
// filteredReduced() on sequences
@@ -137,103 +125,20 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(sequence, keep, reduce, options);
- }
-
-template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(const Sequence &sequence,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<ResultType>(sequence,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
+ return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
-template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(const Sequence &sequence,
- bool (C::*filter)() const,
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return filteredReduced<ResultType>(sequence,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
-QFuture<U> filteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(sequence,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
-QFuture<C> filteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(sequence,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W>
-QFuture<V> filteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<V>(sequence,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename U, typename V>
-QFuture<U> filteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename C, typename V>
-QFuture<C> filteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(sequence,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename D, typename U>
-QFuture<D> filteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<D>(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// filteredReduced() on iterators
@@ -244,184 +149,42 @@ QFuture<ResultType> filteredReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(begin, end, keep, reduce, options);
-}
-
-template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(Iterator begin,
- Iterator end,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<ResultType>(begin,
- end,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
+ return startFilteredReduced<ResultType>(begin, end, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options);
}
-template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
-QFuture<ResultType> filteredReduced(Iterator begin,
+template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filteredReduced(Iterator begin,
Iterator end,
- bool (C::*filter)() const,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return filteredReduced<ResultType>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
-QFuture<U> filteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(begin,
- end,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
-QFuture<C> filteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(begin,
- end,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W>
-QFuture<V> filteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<V>(begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename U, typename V>
-QFuture<U> filteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<U>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename C, typename V>
-QFuture<C> filteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<C>(begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename Iterator, typename C, typename T, typename D, typename U>
-QFuture<D> filteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return filteredReduced<D>(begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
-}
-
-
// filtered() on sequences
template <typename Sequence, typename KeepFunctor>
QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, KeepFunctor keep)
{
- return startFiltered(sequence, keep);
-}
-
-template <typename Sequence, typename T>
-QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (keep)(T))
-{
- return startFiltered(sequence, FunctionWrapper1<bool, T>(keep));
-}
-
-template <typename Sequence, typename C>
-QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, bool (C::*keep)() const)
-{
- return startFiltered(sequence, ConstMemberFunctionWrapper<bool, C>(keep));
+ return startFiltered(sequence, QtPrivate::createFunctionWrapper(keep));
}
// filtered() on iterators
template <typename Iterator, typename KeepFunctor>
QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, KeepFunctor keep)
{
- return startFiltered(begin, end, keep);
+ return startFiltered(begin, end, QtPrivate::createFunctionWrapper(keep));
}
-template <typename Iterator, typename T>
-QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, bool (keep)(T))
-{
- return startFiltered(begin, end, FunctionWrapper1<bool, T>(keep));
-}
-
-template <typename Iterator, typename C>
-QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin,
- Iterator end,
- bool (C::*keep)() const)
-{
- return startFiltered(begin, end, ConstMemberFunctionWrapper<bool, C>(keep));
-}
-
-
// blocking filter() on sequences
template <typename Sequence, typename KeepFunctor>
void blockingFilter(Sequence &sequence, KeepFunctor keep)
{
- filterInternal(sequence, keep, &Sequence::push_back).startBlocking();
-}
-
-template <typename Sequence, typename T>
-void blockingFilter(Sequence &sequence, bool (keep)(T))
-{
- filterInternal(sequence, FunctionWrapper1<bool, T>(keep), &Sequence::push_back)
- .startBlocking();
-}
-
-template <typename Sequence, typename C>
-void blockingFilter(Sequence &sequence, bool (C::*keep)() const)
-{
- filterInternal(sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- &Sequence::push_back)
- .startBlocking();
+ filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back).startBlocking();
}
// blocking filteredReduced() on sequences
@@ -431,111 +194,20 @@ ResultType blockingFilteredReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(sequence, keep, reduce, options)
+ return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options)
.startBlocking();
}
-template <typename ResultType, typename Sequence, typename T, typename ReduceFunctor>
-ResultType blockingFilteredReduced(const Sequence &sequence,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<ResultType>
- (sequence,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
-}
-
-template <typename ResultType, typename Sequence, typename C, typename ReduceFunctor>
-ResultType blockingFilteredReduced(const Sequence &sequence,
- bool (C::*filter)() const,
+template <typename Sequence, typename KeepFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(const Sequence &sequence,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return blockingFilteredReduced<ResultType>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename U, typename V>
-U blockingFilteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (sequence,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename KeepFunctor, typename T, typename C, typename U>
-C blockingFilteredReduced(const Sequence &sequence,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
+ return blockingFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
(sequence,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W>
-V blockingFilteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<V>
- (sequence,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename U, typename V>
-U blockingFilteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename T, typename U, typename C, typename V>
-C blockingFilteredReduced(const Sequence &sequence,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (sequence,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Sequence, typename C, typename T, typename D, typename U>
-D blockingFilteredReduced(const Sequence &sequence,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<D>
- (sequence,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
options);
}
@@ -547,150 +219,34 @@ ResultType blockingFilteredReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startFilteredReduced<ResultType>(begin, end, keep, reduce, options)
+ return startFilteredReduced<ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options)
.startBlocking();
}
-template <typename ResultType, typename Iterator, typename T, typename ReduceFunctor>
-ResultType blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (filter)(T),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<ResultType>
- (begin,
- end,
- FunctionWrapper1<bool, T>(filter),
- reduce,
- options);
-}
-
-template <typename ResultType, typename Iterator, typename C, typename ReduceFunctor>
-ResultType blockingFilteredReduced(Iterator begin,
+template <typename Iterator, typename KeepFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFilteredReduced(Iterator begin,
Iterator end,
- bool (C::*filter)() const,
+ KeepFunctor keep,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return blockingFilteredReduced<ResultType>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(filter),
- reduce,
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename U, typename V>
-U blockingFilteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (begin,
- end,
- keep,
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename KeepFunctor, typename T, typename C, typename U>
-C blockingFilteredReduced(Iterator begin,
- Iterator end,
- KeepFunctor keep,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (begin,
- end,
- keep,
- MemberFunctionWrapper1<T, C, U>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W>
-V blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<V>
- (begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- FunctionWrapper2<U, V &, W>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename U, typename V>
-U blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<U>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- FunctionWrapper2<T, U &, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename T, typename U, typename C, typename V>
-C blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (keep)(T),
- U (C::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<C>
- (begin,
- end,
- FunctionWrapper1<bool, T>(keep),
- MemberFunctionWrapper1<U, C, V>(reduce),
- options);
-}
-
-template <typename Iterator, typename C, typename T, typename D, typename U>
-D blockingFilteredReduced(Iterator begin,
- Iterator end,
- bool (C::*keep)() const,
- T (D::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return blockingFilteredReduced<D>
- (begin,
- end,
- ConstMemberFunctionWrapper<bool, C>(keep),
- MemberFunctionWrapper1<T, D, U>(reduce),
- options);
+ return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(keep),
+ QtPrivate::createFunctionWrapper(reduce),
+ options)
+ .startBlocking();
}
// blocking filtered() on sequences
template <typename Sequence, typename KeepFunctor>
Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep)
{
- return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
-}
-
-template <typename Sequence, typename T>
-Sequence blockingFiltered(const Sequence &sequence, bool (keep)(T))
-{
- return blockingFilteredReduced(sequence, keep, &Sequence::push_back, OrderedReduce);
-}
-
-template <typename Sequence, typename C>
-Sequence blockingFiltered(const Sequence &sequence, bool (C::*filter)() const)
-{
- return blockingFilteredReduced(sequence,
- filter,
- &Sequence::push_back,
- OrderedReduce);
+ return blockingFilteredReduced(sequence, QtPrivate::createFunctionWrapper(keep), &Sequence::push_back, OrderedReduce);
}
// blocking filtered() on iterators
@@ -699,27 +255,7 @@ OutputSequence blockingFiltered(Iterator begin, Iterator end, KeepFunctor keep)
{
return blockingFilteredReduced(begin,
end,
- keep,
- &OutputSequence::push_back,
- OrderedReduce);
-}
-
-template <typename OutputSequence, typename Iterator, typename T>
-OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (keep)(T))
-{
- return blockingFilteredReduced(begin,
- end,
- keep,
- &OutputSequence::push_back,
- OrderedReduce);
-}
-
-template <typename OutputSequence, typename Iterator, typename C>
-OutputSequence blockingFiltered(Iterator begin, Iterator end, bool (C::*filter)() const)
-{
- return blockingFilteredReduced(begin,
- end,
- filter,
+ QtPrivate::createFunctionWrapper(keep),
&OutputSequence::push_back,
OrderedReduce);
}
diff --git a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
index f31f7d2..98506a5 100644
--- a/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
+++ b/src/corelib/concurrent/qtconcurrentfunctionwrappers.h
@@ -163,6 +163,125 @@ private:
} // namespace QtConcurrent.
+namespace QtPrivate {
+
+template <typename T>
+const T& createFunctionWrapper(const T& t)
+{
+ return t;
+}
+
+template <typename T, typename U>
+QtConcurrent::FunctionWrapper1<T, U> createFunctionWrapper(T (*func)(U))
+{
+ return QtConcurrent::FunctionWrapper1<T, U>(func);
+}
+
+template <typename T, typename C>
+QtConcurrent::MemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)())
+{
+ return QtConcurrent::MemberFunctionWrapper<T, C>(func);
+}
+
+template <typename T, typename C, typename U>
+QtConcurrent::MemberFunctionWrapper1<T, C, U> createFunctionWrapper(T (C::*func)(U))
+{
+ return QtConcurrent::MemberFunctionWrapper1<T, C, U>(func);
+}
+
+template <typename T, typename C>
+QtConcurrent::ConstMemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)() const)
+{
+ return QtConcurrent::ConstMemberFunctionWrapper<T, C>(func);
+}
+
+
+template<typename T>
+void *lazyResultType_helper(int, typename T::result_type * = 0);
+template<typename T>
+char lazyResultType_helper(double);
+
+template <typename Functor, bool foo = sizeof(lazyResultType_helper<Functor>(0)) != sizeof(void*)>
+struct LazyResultType { typedef typename Functor::result_type Type; };
+template <typename Functor>
+struct LazyResultType<Functor, true> { typedef void Type; };
+
+
+template <class T>
+struct ReduceResultType;
+
+template <class U, class V>
+struct ReduceResultType<void(*)(U&,V)>
+{
+ typedef U ResultType;
+};
+
+template <class T, class C, class U>
+struct ReduceResultType<T(C::*)(U)>
+{
+ typedef C ResultType;
+};
+
+template <class InputSequence, class MapFunctor>
+struct MapResultType
+{
+ typedef typename LazyResultType<MapFunctor>::Type ResultType;
+};
+
+template <class U, class V>
+struct MapResultType<void, U (*)(V)>
+{
+ typedef U ResultType;
+};
+
+template <class T, class C>
+struct MapResultType<void, T(C::*)() const>
+{
+ typedef T ResultType;
+};
+
+#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
+
+template <template <typename> class InputSequence, typename MapFunctor, typename T>
+struct MapResultType<InputSequence<T>, MapFunctor>
+{
+ typedef InputSequence<typename LazyResultType<MapFunctor>::Type> ResultType;
+};
+
+template <template <typename> class InputSequence, class T, class U, class V>
+struct MapResultType<InputSequence<T>, U (*)(V)>
+{
+ typedef InputSequence<U> ResultType;
+};
+
+template <template <typename> class InputSequence, class T, class U, class C>
+struct MapResultType<InputSequence<T>, U(C::*)() const>
+{
+ typedef InputSequence<U> ResultType;
+};
+
+#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
+
+template <class MapFunctor>
+struct MapResultType<QStringList, MapFunctor>
+{
+ typedef QList<typename LazyResultType<MapFunctor>::Type> ResultType;
+};
+
+template <class U, class V>
+struct MapResultType<QStringList, U (*)(V)>
+{
+ typedef QList<U> ResultType;
+};
+
+template <class U, class C>
+struct MapResultType<QStringList, U(C::*)() const>
+{
+ typedef QList<U> ResultType;
+};
+
+} // namespace QtPrivate.
+
#endif //qdoc
QT_END_NAMESPACE
diff --git a/src/corelib/concurrent/qtconcurrentmap.h b/src/corelib/concurrent/qtconcurrentmap.h
index 80edf7e..a857ab5 100644
--- a/src/corelib/concurrent/qtconcurrentmap.h
+++ b/src/corelib/concurrent/qtconcurrentmap.h
@@ -110,38 +110,14 @@ namespace QtConcurrent {
template <typename Sequence, typename MapFunctor>
QFuture<void> map(Sequence &sequence, MapFunctor map)
{
- return startMap(sequence.begin(), sequence.end(), map);
-}
-
-template <typename Sequence, typename T, typename U>
-QFuture<void> map(Sequence &sequence, T (map)(U))
-{
- return startMap(sequence.begin(), sequence.end(), FunctionWrapper1<T, U>(map));
-}
-
-template <typename Sequence, typename T, typename C>
-QFuture<void> map(Sequence &sequence, T (C::*map)())
-{
- return startMap(sequence.begin(), sequence.end(), MemberFunctionWrapper<T, C>(map));
+ return startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map));
}
// map() on iterators
template <typename Iterator, typename MapFunctor>
QFuture<void> map(Iterator begin, Iterator end, MapFunctor map)
{
- return startMap(begin, end, map);
-}
-
-template <typename Iterator, typename T, typename U>
-QFuture<void> map(Iterator begin, Iterator end, T (map)(U))
-{
- return startMap(begin, end, FunctionWrapper1<T, U>(map));
-}
-
-template <typename Iterator, typename T, typename C>
-QFuture<void> map(Iterator begin, Iterator end, T (C::*map)())
-{
- return startMap(begin, end, MemberFunctionWrapper<T, C>(map));
+ return startMap(begin, end, QtPrivate::createFunctionWrapper(map));
}
// mappedReduced() for sequences.
@@ -151,88 +127,24 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<typename MapFunctor::result_type, ResultType>
- (sequence, map, reduce, options);
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
-QFuture<U> mappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, U>
- (sequence, map, FunctionWrapper2<T, U &, V>(reduce), options);
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
-QFuture<C> mappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, C>
- (sequence, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
-}
-
-template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(const Sequence &sequence,
- T (map)(U),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, ResultType>
- (sequence, FunctionWrapper1<T, U>(map), reduce, options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
+template <typename Sequence, typename MapFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(const Sequence &sequence,
+ MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<T, ResultType>
- (sequence, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
-QFuture<W> mappedReduced(const Sequence &sequence,
- T (map)(U),
- V (reduce)(W &, X),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, W>
- (sequence, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
-QFuture<V> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, V> (sequence, ConstMemberFunctionWrapper<T, C>(map),
- FunctionWrapper2<U, V &, W>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
-QFuture<C> mappedReduced(const Sequence &sequence,
- T (map)(U),
- V (C::*reduce)(W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, C> (sequence, FunctionWrapper1<T, U>(map),
- MemberFunctionWrapper1<V, C, W>(reduce), options);
-}
-
-template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
-QFuture<D> mappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (D::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, D>(sequence, ConstMemberFunctionWrapper<T, C>(map),
- MemberFunctionWrapper1<U, D, V>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// mappedReduced() for iterators
@@ -243,295 +155,85 @@ QFuture<ResultType> mappedReduced(Iterator begin,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<ResultType, typename MapFunctor::result_type>
- (begin, end, map, reduce, options);
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
-QFuture<U> mappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (reduce)(U &, V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, U>
- (begin, end, map, FunctionWrapper2<T, U &, V>(reduce), options);
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
-QFuture<C> mappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (C::*reduce)(U),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<typename MapFunctor::result_type, C>
- (begin, end, map, MemberFunctionWrapper1<T, C, U>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
-template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(Iterator begin,
+template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
+QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedReduced(Iterator begin,
Iterator end,
- T (map)(U),
- ReduceFunctor reduce,
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, ResultType>
- (begin, end, FunctionWrapper1<T, U>(map), reduce, options);
-}
-
-template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
-QFuture<ResultType> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
+ MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return startMappedReduced<T, ResultType>
- (begin, end, ConstMemberFunctionWrapper<T, C>(map), reduce, options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
-QFuture<W> mappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (reduce)(W &, X),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, W>
- (begin, end, FunctionWrapper1<T, U>(map), FunctionWrapper2<V, W &, X>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
-QFuture<V> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (reduce)(V &, W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, V>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
- FunctionWrapper2<U, V &, W>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
-QFuture<C> mappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (C::*reduce)(W),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, C>
- (begin, end, FunctionWrapper1<T, U>(map), MemberFunctionWrapper1<V, C, W>(reduce), options);
-}
-
-template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
-QFuture<D> mappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (D::*reduce)(V),
- ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
-{
- return startMappedReduced<T, D>(begin, end, ConstMemberFunctionWrapper<T, C>(map),
- MemberFunctionWrapper1<U, D, V>(reduce), options);
+ return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
+ options);
}
// mapped() for sequences
template <typename Sequence, typename MapFunctor>
-QFuture<typename MapFunctor::result_type> mapped(const Sequence &sequence, MapFunctor map)
+QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(const Sequence &sequence, MapFunctor map)
{
- return startMapped<typename MapFunctor::result_type>(sequence, map);
-}
-
-template <typename Sequence, typename T, typename U>
-QFuture<T> mapped(const Sequence &sequence, T (map)(U))
-{
- return startMapped<T>(sequence, FunctionWrapper1<T, U>(map));
-}
-
-template <typename Sequence, typename T, typename C>
-QFuture<T> mapped(const Sequence &sequence, T (C::*map)() const)
-{
- return startMapped<T>(sequence, ConstMemberFunctionWrapper<T, C>(map));
+ return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(sequence, QtPrivate::createFunctionWrapper(map));
}
// mapped() for iterator ranges.
template <typename Iterator, typename MapFunctor>
-QFuture<typename MapFunctor::result_type> mapped(Iterator begin, Iterator end, MapFunctor map)
-{
- return startMapped<Q_TYPENAME MapFunctor::result_type>(begin, end, map);
-}
-
-template <typename Iterator, typename T, typename U>
-QFuture<T> mapped(Iterator begin, Iterator end, T (map)(U))
+QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(Iterator begin, Iterator end, MapFunctor map)
{
- return startMapped<T>(begin, end, FunctionWrapper1<T, U>(map));
+ return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(begin, end, QtPrivate::createFunctionWrapper(map));
}
-template <typename Iterator, typename T, typename C>
-QFuture<T> mapped(Iterator begin, Iterator end, T (C::*map)() const)
-{
- return startMapped<T>(begin, end, ConstMemberFunctionWrapper<T, C>(map));
-}
-
-
+// blockingMap() for sequences
template <typename Sequence, typename MapFunctor>
void blockingMap(Sequence &sequence, MapFunctor map)
{
- startMap(sequence.begin(), sequence.end(), map).startBlocking();
-}
-
-template <typename Sequence, typename T, typename U>
-void blockingMap(Sequence &sequence, T (map)(U))
-{
- startMap(sequence.begin(), sequence.end(), QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
-}
-
-template <typename Sequence, typename T, typename C>
-void blockingMap(Sequence &sequence, T (C::*map)())
-{
- startMap(sequence.begin(), sequence.end(), QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+ startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map)).startBlocking();
}
+// blockingMap() for iterator ranges
template <typename Iterator, typename MapFunctor>
void blockingMap(Iterator begin, Iterator end, MapFunctor map)
{
- startMap(begin, end, map).startBlocking();
-}
-
-template <typename Iterator, typename T, typename U>
-void blockingMap(Iterator begin, Iterator end, T (map)(U))
-{
- startMap(begin, end, QtConcurrent::FunctionWrapper1<T, U>(map)).startBlocking();
-}
-
-template <typename Iterator, typename T, typename C>
-void blockingMap(Iterator begin, Iterator end, T (C::*map)())
-{
- startMap(begin, end, QtConcurrent::MemberFunctionWrapper<T, C>(map)).startBlocking();
+ startMap(begin, end, QtPrivate::createFunctionWrapper(map)).startBlocking();
}
+// blockingMappedReduced() for sequences
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor>
ResultType blockingMappedReduced(const Sequence &sequence,
MapFunctor map,
ReduceFunctor reduce,
ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
- (sequence, map, reduce, options).startBlocking();
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename U, typename V>
-U blockingMappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (reduce)(U &, V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
- (sequence,
- map,
- QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename MapFunctor, typename T, typename C, typename U>
-C blockingMappedReduced(const Sequence &sequence,
- MapFunctor map,
- T (C::*reduce)(U),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
- (sequence,
- map,
- QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename ResultType, typename Sequence, typename T, typename U, typename ReduceFunctor>
-ResultType blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
(sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- reduce,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
-template <typename ResultType, typename Sequence, typename T, typename C, typename ReduceFunctor>
-ResultType blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
+template <typename MapFunctor, typename ReduceFunctor, typename Sequence>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(const Sequence &sequence,
+ MapFunctor map,
ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename W, typename X>
-W blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- V (reduce)(W &, X),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, W>
- (sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename C, typename U, typename V, typename W>
-V blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (reduce)(V &, W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, V>
- (sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename U, typename V, typename C, typename W>
-C blockingMappedReduced(const Sequence &sequence,
- T (map)(U),
- V (C::*reduce)(W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, C>
- (sequence,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Sequence, typename T, typename C, typename U,typename D, typename V>
-D blockingMappedReduced(const Sequence &sequence,
- T (C::*map)() const,
- U (D::*reduce)(V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
+ ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
{
- return QtConcurrent::startMappedReduced<T, D>
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
(sequence,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
+// blockingMappedReduced() for iterator ranges
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor>
ResultType blockingMappedReduced(Iterator begin,
Iterator end,
@@ -539,134 +241,25 @@ ResultType blockingMappedReduced(Iterator begin,
ReduceFunctor reduce,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, ResultType>
- (begin, end, map, reduce, options).startBlocking();
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename U, typename V>
-U blockingMappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (reduce)(U &, V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, U>
- (begin,
- end,
- map,
- QtConcurrent::FunctionWrapper2<T, U &, V>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename MapFunctor, typename T, typename C, typename U>
-C blockingMappedReduced(Iterator begin,
- Iterator end,
- MapFunctor map,
- T (C::*reduce)(U),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<typename MapFunctor::result_type, C>
- (begin,
- end,
- map,
- QtConcurrent::MemberFunctionWrapper1<T, C, U>(reduce),
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
-template <typename ResultType, typename Iterator, typename T, typename U, typename ReduceFunctor>
-ResultType blockingMappedReduced(Iterator begin,
+template <typename Iterator, typename MapFunctor, typename ReduceFunctor>
+typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedReduced(Iterator begin,
Iterator end,
- T (map)(U),
- ReduceFunctor reduce,
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename ResultType, typename Iterator, typename T, typename C, typename ReduceFunctor>
-ResultType blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
+ MapFunctor map,
ReduceFunctor reduce,
QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
{
- return QtConcurrent::startMappedReduced<T, ResultType>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- reduce,
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename W, typename X>
-W blockingMappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (reduce)(W &, X),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, W>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::FunctionWrapper2<V, W &, X>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename C, typename U, typename V, typename W>
-V blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (reduce)(V &, W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, V>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::FunctionWrapper2<U, V &, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename U, typename V, typename C, typename W>
-C blockingMappedReduced(Iterator begin,
- Iterator end,
- T (map)(U),
- V (C::*reduce)(W),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, C>
- (begin,
- end,
- QtConcurrent::FunctionWrapper1<T, U>(map),
- QtConcurrent::MemberFunctionWrapper1<V, C, W>(reduce),
- options)
- .startBlocking();
-}
-
-template <typename Iterator, typename T, typename C, typename U,typename D, typename V>
-D blockingMappedReduced(Iterator begin,
- Iterator end,
- T (C::*map)() const,
- U (D::*reduce)(V),
- QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce))
-{
- return QtConcurrent::startMappedReduced<T, D>
- (begin,
- end,
- QtConcurrent::ConstMemberFunctionWrapper<T, C>(map),
- QtConcurrent::MemberFunctionWrapper1<U, D, V>(reduce),
+ return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ QtPrivate::createFunctionWrapper(reduce),
options)
.startBlocking();
}
@@ -675,97 +268,44 @@ D blockingMappedReduced(Iterator begin,
template <typename OutputSequence, typename InputSequence, typename MapFunctor>
OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map)
{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename OutputSequence, typename InputSequence, typename T, typename U>
-OutputSequence blockingMapped(const InputSequence &sequence, T (map)(U))
-{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename OutputSequence, typename InputSequence, typename T, typename C>
-OutputSequence blockingMapped(const InputSequence &sequence, T (C::*map)() const)
-{
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS
-
-// overloads for changing the container value type:
-template <template <typename> class Sequence, typename MapFunctor, typename T>
-Sequence<typename MapFunctor::result_type> blockingMapped(const Sequence<T> &sequence, MapFunctor map)
-{
- typedef Sequence<typename MapFunctor::result_type> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <template <typename> class Sequence, typename T, typename U, typename V>
-Sequence<U> blockingMapped(const Sequence<T> &sequence, U (map)(V))
-{
- typedef Sequence<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <template <typename> class Sequence, typename T, typename U, typename C>
-Sequence<U> blockingMapped(const Sequence<T> &sequence, U (C::*map)() const)
-{
- typedef Sequence<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
-
-// overloads for changing the container value type from a QStringList:
-template <typename MapFunctor>
-QList<typename MapFunctor::result_type> blockingMapped(const QStringList &sequence, MapFunctor map)
-{
- typedef QList<typename MapFunctor::result_type> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename U, typename V>
-QList<U> blockingMapped(const QStringList &sequence, U (map)(V))
-{
- typedef QList<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
+ return blockingMappedReduced<OutputSequence>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
-template <typename U, typename C>
-QList<U> blockingMapped(const QStringList &sequence, U (C::*map)() const)
+template <typename MapFunctor, typename InputSequence>
+typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType blockingMapped(const InputSequence &sequence, MapFunctor map)
{
- typedef QList<U> OutputSequence;
- return blockingMappedReduced(sequence, map, &OutputSequence::push_back,
- QtConcurrent::OrderedReduce);
+ typedef typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType OutputSequence;
+ return blockingMappedReduced<OutputSequence>
+ (sequence,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
// mapped() for iterator ranges
template <typename Sequence, typename Iterator, typename MapFunctor>
Sequence blockingMapped(Iterator begin, Iterator end, MapFunctor map)
{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
-}
-
-template <typename Sequence, typename Iterator, typename T, typename U>
-Sequence blockingMapped(Iterator begin, Iterator end, T (map)(U))
-{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
+ return blockingMappedReduced<Sequence>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ &Sequence::push_back,
+ QtConcurrent::OrderedReduce);
}
-template <typename Sequence, typename Iterator, typename T, typename C>
-Sequence blockingMapped(Iterator begin, Iterator end, T (C::*map)() const)
-{
- return blockingMappedReduced(begin, end, map, &Sequence::push_back,
- QtConcurrent::OrderedReduce);
+template <typename Iterator, typename MapFunctor>
+typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType blockingMapped(Iterator begin, Iterator end, MapFunctor map)
+{
+ typedef typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType OutputSequence;
+ return blockingMappedReduced<OutputSequence>
+ (begin, end,
+ QtPrivate::createFunctionWrapper(map),
+ &OutputSequence::push_back,
+ QtConcurrent::OrderedReduce);
}
} // namespace QtConcurrent
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 97b4407..a6b9bdd 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -1199,10 +1199,12 @@ bool qSharedBuild()
\value SV_9_2 Symbian OS v9.2
\value SV_9_3 Symbian OS v9.3
\value SV_9_4 Symbian OS v9.4
- \value SV_SF_1 Symbian^1
+ \value SV_SF_1 S60 5th Edition (Symbian^1)
\value SV_SF_2 Symbian^2
- \value SV_SF_3 Symbian^3
+ \value SV_SF_3 Symbian^3 or Symbian Anna
\value SV_SF_4 \e{This enum value is deprecated.}
+ \value SV_API_5_3 Symbian/S60 API version 5.3 release
+ \value SV_API_5_4 Symbian/S60 API version 5.4 release
\value SV_Unknown An unknown and currently unsupported platform
\sa S60Version, WinVersion, MacVersion
@@ -1219,9 +1221,10 @@ bool qSharedBuild()
\value SV_S60_3_1 S60 3rd Edition Feature Pack 1
\value SV_S60_3_2 S60 3rd Edition Feature Pack 2
\value SV_S60_5_0 S60 5th Edition
- \value SV_S60_5_1 S60 5th Edition Feature Pack 1
- \value SV_S60_5_2 Symbian^3
- \value SV_S60_5_3 To be determined - FIXME
+ \value SV_S60_5_1 \e{This enum value is deprecated.}
+ \value SV_S60_5_2 Symbian^3 and Symbian Anna
+ \value SV_S60_5_3 Symbian/S60 API version 5.3 release
+ \value SV_S60_5_4 Symbian/S60 API version 5.4 release
\value SV_S60_Unknown An unknown and currently unsupported platform
\omitvalue SV_S60_None
@@ -1866,9 +1869,12 @@ static void symbianInitVersions()
} else if (minor == 2) {
cachedS60Version = QSysInfo::SV_S60_5_2;
cachedSymbianVersion = QSysInfo::SV_SF_3;
- } else if (minor >= 3) {
+ } else if (minor == 3) {
cachedS60Version = QSysInfo::SV_S60_5_3;
- cachedSymbianVersion = QSysInfo::SV_SF_3;
+ cachedSymbianVersion = QSysInfo::SV_API_5_3;
+ } else if (minor >= 4) {
+ cachedS60Version = QSysInfo::SV_S60_5_4;
+ cachedSymbianVersion = QSysInfo::SV_API_5_4;
}
}
}
@@ -1894,7 +1900,10 @@ static void symbianInitVersions()
cachedSymbianVersion = QSysInfo::SV_SF_3;
# elif defined(S60_VERSION_5_3)
cachedS60Version = QSysInfo::SV_S60_5_3;
- cachedSymbianVersion = QSysInfo::SV_SF_3;
+ cachedSymbianVersion = QSysInfo::SV_API_5_3;
+# elif defined(S60_VERSION_5_4)
+ cachedS60Version = QSysInfo::SV_S60_5_4;
+ cachedSymbianVersion = QSysInfo::SV_API_5_4;
# endif
}
# endif
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 6469b46..49f5f98 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1617,7 +1617,9 @@ public:
SV_SF_1 = SV_9_4,
SV_SF_2 = 40,
SV_SF_3 = 50,
- SV_SF_4 = 60 // Deprecated
+ SV_SF_4 = 60, // Deprecated
+ SV_API_5_3 = 70,
+ SV_API_5_4 = 80
};
static SymbianVersion symbianVersion();
enum S60Version {
@@ -1626,9 +1628,10 @@ public:
SV_S60_3_1 = SV_9_2,
SV_S60_3_2 = SV_9_3,
SV_S60_5_0 = SV_9_4,
- SV_S60_5_1 = SV_SF_2,
+ SV_S60_5_1 = SV_SF_2, // Deprecated
SV_S60_5_2 = SV_SF_3,
- SV_S60_5_3 = 70
+ SV_S60_5_3 = SV_API_5_3,
+ SV_S60_5_4 = SV_API_5_4
};
static S60Version s60Version();
#endif
@@ -2750,6 +2753,13 @@ QT_LICENSED_MODULE(DBus)
# endif
#endif
+#if !(defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) \
+ && !(defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)) \
+ && !(defined(Q_WS_X11) && !defined(QT_NO_FREETYPE)) \
+ && !(defined(Q_WS_QPA))
+# define QT_NO_RAWFONT
+#endif
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index f015ed0..75ce68a 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -525,8 +525,8 @@ public:
#endif
WA_X11DoNotAcceptFocus = 132,
-
- WA_MacNoShadow = 133,
+ WA_SymbianNoSystemRotation = 133,
+ WA_MacNoShadow = 134,
// Add new attributes before this line
WA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 07a9503..7cc0814 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1251,6 +1251,7 @@
\omitvalue WA_SetWindowModality
\omitvalue WA_WState_WindowOpacitySet
\omitvalue WA_WState_AcceptedTouchBeginEvent
+ \omitvalue WA_SymbianNoSystemRotation
*/
/*! \typedef Qt::HANDLE
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index c7e56bd..4a538f3 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -316,6 +316,7 @@ void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo)
current entry will be returned as part of the directory iteration);
otherwise, false is returned.
*/
+
bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const
{
Q_ASSERT(!fileName.isEmpty());
@@ -350,6 +351,14 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
return false;
}
#endif
+ // skip symlinks
+ const bool skipSymlinks = (filters & QDir::NoSymLinks);
+ const bool includeSystem = (filters & QDir::System);
+ if(skipSymlinks && fi.isSymLink()) {
+ // The only reason to save this file is if it is a broken link and we are requesting system files.
+ if(!includeSystem || fi.exists())
+ return false;
+ }
// filter hidden
const bool includeHidden = (filters & QDir::Hidden);
@@ -357,27 +366,20 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
return false;
// filter system files
- const bool includeSystem = (filters & QDir::System);
- if (!includeSystem && ((!fi.isFile() && !fi.isDir() && !fi.isSymLink())
+ if (!includeSystem && (!(fi.isFile() || fi.isDir() || fi.isSymLink())
|| (!fi.exists() && fi.isSymLink())))
return false;
// skip directories
const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
- if (skipDirs && fi.isDir()) {
- if (!((includeHidden && !dotOrDotDot && fi.isHidden())
- || (includeSystem && !fi.exists() && fi.isSymLink())))
- return false;
- }
+ if (skipDirs && fi.isDir())
+ return false;
// skip files
const bool skipFiles = !(filters & QDir::Files);
- const bool skipSymlinks = (filters & QDir::NoSymLinks);
- if ((skipFiles && (fi.isFile() || !fi.exists())) || (skipSymlinks && fi.isSymLink())) {
- if (!((includeHidden && !dotOrDotDot && fi.isHidden())
- || (includeSystem && !fi.exists() && fi.isSymLink())))
- return false;
- }
+ if (skipFiles && fi.isFile())
+ // Basically we need a reason not to exclude this file otherwise we just eliminate it.
+ return false;
// filter permissions
const bool filterPermissions = ((filters & QDir::PermissionMask)
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index c9ebaa4..742b05e 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -356,6 +356,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
const QByteArray &path = entry.nativeFilePath();
nativeFilePath = path.constData();
nativeFilePathLength = path.size();
+ Q_UNUSED(nativeFilePathLength);
}
bool entryExists = true; // innocent until proven otherwise
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 82c6eba..1dbc40f 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -583,6 +583,7 @@ QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEng
}
}
#else
+ Q_UNUSED(entry);
Q_UNUSED(own);
#endif
return name;
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index a45225f..c2234e9 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -143,55 +143,13 @@ QT_BEGIN_NAMESPACE
\sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment()
*/
-#ifdef Q_OS_WIN
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
-{ return name.toUpper(); }
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
-{ return QString::fromLocal8Bit(name).toUpper(); }
-static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
-{ return name; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
-{ return value; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
-{ return QString::fromLocal8Bit(value); }
-static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
-{ return value; }
-static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
-{ return value.toLocal8Bit(); }
-#else
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name)
-{ return name; }
-static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name)
-{ return name.toLocal8Bit(); }
-static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name)
-{ return QString::fromLocal8Bit(name); }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value)
-{ return value; }
-static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value)
-{ return value.toLocal8Bit(); }
-static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value)
-{ return QString::fromLocal8Bit(value); }
-static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value)
-{ return value; }
-#endif
-
-template<> void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
-{
- if (d && d->ref == 1)
- return;
- QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
- : new QProcessEnvironmentPrivate);
- x->ref.ref();
- if (d && !d->ref.deref())
- delete d;
- d = x;
-}
QStringList QProcessEnvironmentPrivate::toList() const
{
QStringList result;
- QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
- end = hash.constEnd();
+ result.reserve(hash.size());
+ Hash::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
for ( ; it != end; ++it) {
QString data = nameToString(it.key());
QString value = valueToString(it.value());
@@ -224,19 +182,27 @@ QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list
QStringList QProcessEnvironmentPrivate::keys() const
{
QStringList result;
- QHash<Unit, Unit>::ConstIterator it = hash.constBegin(),
- end = hash.constEnd();
+ result.reserve(hash.size());
+ Hash::ConstIterator it = hash.constBegin(),
+ end = hash.constEnd();
for ( ; it != end; ++it)
result << nameToString(it.key());
return result;
}
-void QProcessEnvironmentPrivate::insert(const Hash &h)
+void QProcessEnvironmentPrivate::insert(const QProcessEnvironmentPrivate &other)
{
- QHash<Unit, Unit>::ConstIterator it = h.constBegin(),
- end = h.constEnd();
+ Hash::ConstIterator it = other.hash.constBegin(),
+ end = other.hash.constEnd();
for ( ; it != end; ++it)
hash.insert(it.key(), it.value());
+
+#ifdef Q_OS_UNIX
+ QHash<QString, Key>::ConstIterator nit = other.nameMap.constBegin(),
+ nend = other.nameMap.constEnd();
+ for ( ; nit != nend; ++nit)
+ nameMap.insert(nit.key(), nit.value());
+#endif
}
/*!
@@ -317,6 +283,8 @@ void QProcessEnvironment::clear()
{
if (d)
d->hash.clear();
+ // Unix: Don't clear d->nameMap, as the environment is likely to be
+ // re-populated with the same keys again.
}
/*!
@@ -331,7 +299,7 @@ void QProcessEnvironment::clear()
*/
bool QProcessEnvironment::contains(const QString &name) const
{
- return d ? d->hash.contains(prepareName(name)) : false;
+ return d ? d->hash.contains(d->prepareName(name)) : false;
}
/*!
@@ -353,7 +321,7 @@ bool QProcessEnvironment::contains(const QString &name) const
void QProcessEnvironment::insert(const QString &name, const QString &value)
{
// d detaches from null
- d->hash.insert(prepareName(name), prepareValue(value));
+ d->hash.insert(d->prepareName(name), d->prepareValue(value));
}
/*!
@@ -370,7 +338,7 @@ void QProcessEnvironment::insert(const QString &name, const QString &value)
void QProcessEnvironment::remove(const QString &name)
{
if (d)
- d->hash.remove(prepareName(name));
+ d->hash.remove(d->prepareName(name));
}
/*!
@@ -389,11 +357,11 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa
if (!d)
return defaultValue;
- QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name));
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(d->prepareName(name));
if (it == d->hash.constEnd())
return defaultValue;
- return valueToString(it.value());
+ return d->valueToString(it.value());
}
/*!
@@ -438,7 +406,7 @@ void QProcessEnvironment::insert(const QProcessEnvironment &e)
return;
// d detaches from null
- d->insert(e.d->hash);
+ d->insert(*e.d);
}
void QProcessPrivate::Channel::clear()
@@ -2321,6 +2289,8 @@ QStringList QProcess::systemEnvironment()
}
/*!
+ \fn QProcessEnvironment QProcessEnvironment::systemEnvironment()
+
\since 4.6
\brief The systemEnvironment function returns the environment of
@@ -2336,21 +2306,6 @@ QStringList QProcess::systemEnvironment()
\sa QProcess::systemEnvironment()
*/
-QProcessEnvironment QProcessEnvironment::systemEnvironment()
-{
- QProcessEnvironment env;
- const char *entry;
- for (int count = 0; (entry = environ[count]); ++count) {
- const char *equal = strchr(entry, '=');
- if (!equal)
- continue;
-
- QByteArray name(entry, equal - entry);
- QByteArray value(equal + 1);
- env.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value));
- }
- return env;
-}
/*!
\typedef Q_PID
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 7bfcb31..54d4936 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -81,23 +81,119 @@ class QTimer;
class RProcess;
#endif
+#ifdef Q_OS_WIN
+class QProcEnvKey : public QString
+{
+public:
+ QProcEnvKey() {}
+ explicit QProcEnvKey(const QString &other) : QString(other) {}
+ QProcEnvKey(const QProcEnvKey &other) : QString(other) {}
+ bool operator==(const QProcEnvKey &other) const { return !compare(other, Qt::CaseInsensitive); }
+};
+inline uint qHash(const QProcEnvKey &key) { return qHash(key.toCaseFolded()); }
+
+typedef QString QProcEnvValue;
+#else
+class QProcEnvKey
+{
+public:
+ QProcEnvKey() : hash(0) {}
+ explicit QProcEnvKey(const QByteArray &other) : key(other), hash(qHash(key)) {}
+ QProcEnvKey(const QProcEnvKey &other) { *this = other; }
+ bool operator==(const QProcEnvKey &other) const { return key == other.key; }
+
+ QByteArray key;
+ uint hash;
+};
+inline uint qHash(const QProcEnvKey &key) { return key.hash; }
+
+class QProcEnvValue
+{
+public:
+ QProcEnvValue() {}
+ QProcEnvValue(const QProcEnvValue &other) { *this = other; }
+ explicit QProcEnvValue(const QString &value) : stringValue(value) {}
+ explicit QProcEnvValue(const QByteArray &value) : byteValue(value) {}
+ bool operator==(const QProcEnvValue &other) const
+ {
+ return byteValue.isEmpty() && other.byteValue.isEmpty()
+ ? stringValue == other.stringValue
+ : bytes() == other.bytes();
+ }
+ QByteArray bytes() const
+ {
+ if (byteValue.isEmpty() && !stringValue.isEmpty())
+ byteValue = stringValue.toLocal8Bit();
+ return byteValue;
+ }
+ QString string() const
+ {
+ if (stringValue.isEmpty() && !byteValue.isEmpty())
+ stringValue = QString::fromLocal8Bit(byteValue);
+ return stringValue;
+ }
+
+ mutable QByteArray byteValue;
+ mutable QString stringValue;
+};
+Q_DECLARE_TYPEINFO(QProcEnvValue, Q_MOVABLE_TYPE);
+#endif
+Q_DECLARE_TYPEINFO(QProcEnvKey, Q_MOVABLE_TYPE);
+
class QProcessEnvironmentPrivate: public QSharedData
{
public:
+ typedef QProcEnvKey Key;
+ typedef QProcEnvValue Value;
#ifdef Q_OS_WIN
- typedef QString Unit;
+ inline Key prepareName(const QString &name) const { return Key(name); }
+ inline QString nameToString(const Key &name) const { return name; }
+ inline Value prepareValue(const QString &value) const { return value; }
+ inline QString valueToString(const Value &value) const { return value; }
#else
- typedef QByteArray Unit;
+ inline Key prepareName(const QString &name) const
+ {
+ Key &ent = nameMap[name];
+ if (ent.key.isEmpty())
+ ent = Key(name.toLocal8Bit());
+ return ent;
+ }
+ inline QString nameToString(const Key &name) const
+ {
+ const QString sname = QString::fromLocal8Bit(name.key);
+ nameMap[sname] = name;
+ return sname;
+ }
+ inline Value prepareValue(const QString &value) const { return Value(value); }
+ inline QString valueToString(const Value &value) const { return value.string(); }
#endif
- typedef QHash<Unit, Unit> Hash;
+
+ typedef QHash<Key, Value> Hash;
Hash hash;
+#ifdef Q_OS_UNIX
+ typedef QHash<QString, Key> NameHash;
+ mutable NameHash nameMap;
+#endif
+
static QProcessEnvironment fromList(const QStringList &list);
QStringList toList() const;
QStringList keys() const;
- void insert(const Hash &hash);
+ void insert(const QProcessEnvironmentPrivate &other);
};
+template<> Q_INLINE_TEMPLATE void QSharedDataPointer<QProcessEnvironmentPrivate>::detach()
+{
+ if (d && d->ref == 1)
+ return;
+ QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d)
+ : new QProcessEnvironmentPrivate);
+ x->ref.ref();
+ if (d && !d->ref.deref())
+ delete d;
+ d = x;
+}
+
class QProcessPrivate : public QIODevicePrivate
{
public:
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index b7505ce..a3c589f 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -120,7 +120,7 @@ static inline char *strdup(const char *data)
#endif
static int qt_qprocess_deadChild_pipe[2];
-static void (*qt_sa_old_sigchld_handler)(int) = 0;
+static struct sigaction qt_sa_old_sigchld_handler;
static void qt_sa_sigchld_handler(int signum)
{
qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
@@ -128,8 +128,10 @@ static void qt_sa_sigchld_handler(int signum)
fprintf(stderr, "*** SIGCHLD\n");
#endif
- if (qt_sa_old_sigchld_handler && qt_sa_old_sigchld_handler != SIG_IGN)
- qt_sa_old_sigchld_handler(signum);
+ // load it as volatile
+ void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
+ if (oldAction && oldAction != SIG_IGN)
+ oldAction(signum);
}
static inline void add_fd(int &nfds, int fd, fd_set *fdset)
@@ -190,14 +192,11 @@ QProcessManager::QProcessManager()
// set up the SIGCHLD handler, which writes a single byte to the dead
// child pipe every time a child dies.
- struct sigaction oldAction;
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_handler = qt_sa_sigchld_handler;
action.sa_flags = SA_NOCLDSTOP;
- ::sigaction(SIGCHLD, &action, &oldAction);
- if (oldAction.sa_handler != qt_sa_sigchld_handler)
- qt_sa_old_sigchld_handler = oldAction.sa_handler;
+ ::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
}
QProcessManager::~QProcessManager()
@@ -217,14 +216,10 @@ QProcessManager::~QProcessManager()
qDeleteAll(children.values());
children.clear();
- struct sigaction oldAction;
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = qt_sa_old_sigchld_handler;
- action.sa_flags = SA_NOCLDSTOP;
- ::sigaction(SIGCHLD, &action, &oldAction);
- if (oldAction.sa_handler != qt_sa_sigchld_handler) {
- ::sigaction(SIGCHLD, &oldAction, 0);
+ struct sigaction currentAction;
+ ::sigaction(SIGCHLD, 0, &currentAction);
+ if (currentAction.sa_handler == qt_sa_sigchld_handler) {
+ ::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
}
}
@@ -458,7 +453,36 @@ bool QProcessPrivate::createChannel(Channel &channel)
}
}
-static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment, int *envc)
+QT_BEGIN_INCLUDE_NAMESPACE
+#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#elif defined(Q_OS_SYMBIAN) || (defined(Q_OS_MAC) && defined(QT_NO_CORESERVICES))
+ static char *qt_empty_environ[] = { 0 };
+#define environ qt_empty_environ
+#else
+ extern char **environ;
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+ const char *entry;
+ for (int count = 0; (entry = environ[count]); ++count) {
+ const char *equal = strchr(entry, '=');
+ if (!equal)
+ continue;
+
+ QByteArray name(entry, equal - entry);
+ QByteArray value(equal + 1);
+ env.d->hash.insert(QProcessEnvironmentPrivate::Key(name),
+ QProcessEnvironmentPrivate::Value(value));
+ }
+ return env;
+}
+
+static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environment, int *envc)
{
*envc = 0;
if (environment.isEmpty())
@@ -474,17 +498,17 @@ static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment
#endif
const QByteArray envLibraryPath = qgetenv(libraryPath);
bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
- !environment.contains(libraryPath);
+ !environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath)));
char **envp = new char *[environment.count() + 2];
envp[environment.count()] = 0;
envp[environment.count() + 1] = 0;
- QHash<QByteArray, QByteArray>::ConstIterator it = environment.constBegin();
- const QHash<QByteArray, QByteArray>::ConstIterator end = environment.constEnd();
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = environment.constBegin();
+ const QProcessEnvironmentPrivate::Hash::ConstIterator end = environment.constEnd();
for ( ; it != end; ++it) {
- QByteArray key = it.key();
- QByteArray value = it.value();
+ QByteArray key = it.key().key;
+ QByteArray value = it.value().bytes();
key.reserve(key.length() + 1 + value.length());
key.append('=');
key.append(value);
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 625ed98..bb23954 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -278,29 +278,55 @@ static QString qt_create_commandline(const QString &program, const QStringList &
return args;
}
-static QByteArray qt_create_environment(const QHash<QString, QString> &environment)
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+#if !defined(Q_OS_WINCE)
+ // Calls to setenv() affect the low-level environment as well.
+ // This is not the case the other way round.
+ if (wchar_t *envStrings = GetEnvironmentStringsW()) {
+ for (const wchar_t *entry = envStrings; *entry; ) {
+ int entryLen = wcslen(entry);
+ if (const wchar_t *equal = wcschr(entry, L'=')) {
+ int nameLen = equal - entry;
+ QString name = QString::fromWCharArray(entry, nameLen);
+ QString value = QString::fromWCharArray(equal + 1, entryLen - nameLen - 1);
+ env.d->hash.insert(QProcessEnvironmentPrivate::Key(name), value);
+ }
+ entry += entryLen + 1;
+ }
+ FreeEnvironmentStringsW(envStrings);
+ }
+#endif
+ return env;
+}
+
+#if !defined(Q_OS_WINCE)
+static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &environment)
{
QByteArray envlist;
if (!environment.isEmpty()) {
- QHash<QString, QString> copy = environment;
+ QProcessEnvironmentPrivate::Hash copy = environment;
// add PATH if necessary (for DLL loading)
- if (!copy.contains(QLatin1String("PATH"))) {
+ QProcessEnvironmentPrivate::Key pathKey(QLatin1String("PATH"));
+ if (!copy.contains(pathKey)) {
QByteArray path = qgetenv("PATH");
if (!path.isEmpty())
- copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path));
+ copy.insert(pathKey, QString::fromLocal8Bit(path));
}
// add systemroot if needed
- if (!copy.contains(QLatin1String("SYSTEMROOT"))) {
- QByteArray systemRoot = qgetenv("SYSTEMROOT");
+ QProcessEnvironmentPrivate::Key rootKey(QLatin1String("SystemRoot"));
+ if (!copy.contains(rootKey)) {
+ QByteArray systemRoot = qgetenv("SystemRoot");
if (!systemRoot.isEmpty())
- copy.insert(QLatin1String("SYSTEMROOT"), QString::fromLocal8Bit(systemRoot));
+ copy.insert(rootKey, QString::fromLocal8Bit(systemRoot));
}
int pos = 0;
- QHash<QString, QString>::ConstIterator it = copy.constBegin(),
- end = copy.constEnd();
+ QProcessEnvironmentPrivate::Hash::ConstIterator it = copy.constBegin(),
+ end = copy.constEnd();
static const wchar_t equal = L'=';
static const wchar_t nul = L'\0';
@@ -335,6 +361,7 @@ static QByteArray qt_create_environment(const QHash<QString, QString> &environme
}
return envlist;
}
+#endif
void QProcessPrivate::startProcess()
{
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index b084ca5..f43fb31 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -981,23 +981,6 @@ QStringList QSettingsPrivate::splitArgs(const QString &s, int idx)
// ************************************************************************
// QConfFileSettingsPrivate
-/*
- If we don't have the permission to read the file, returns false.
- If the file doesn't exist, returns true.
-*/
-static bool checkAccess(const QString &name)
-{
- QFileInfo fileInfo(name);
-
- if (fileInfo.exists()) {
- QFile file(name);
- // if the file exists but we can't open it, report an error
- return file.open(QFile::ReadOnly);
- } else {
- return true;
- }
-}
-
void QConfFileSettingsPrivate::initFormat()
{
extension = (format == QSettings::NativeFormat) ? QLatin1String(".conf") : QLatin1String(".ini");
@@ -1026,18 +1009,13 @@ void QConfFileSettingsPrivate::initFormat()
void QConfFileSettingsPrivate::initAccess()
{
- bool readAccess = false;
if (confFiles[spec]) {
- readAccess = checkAccess(confFiles[spec]->name);
if (format > QSettings::IniFormat) {
if (!readFunc)
- readAccess = false;
+ setStatus(QSettings::AccessError);
}
}
- if (!readAccess)
- setStatus(QSettings::AccessError);
-
sync(); // loads the files the first time
}
@@ -1432,7 +1410,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
We can often optimize the read-only case, if the file on disk
hasn't changed.
*/
- if (readOnly) {
+ if (readOnly && confFile->size > 0) {
QFileInfo fileInfo(confFile->name);
if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified())
return;
@@ -1455,6 +1433,9 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
if (!file.isOpen())
file.open(QFile::ReadOnly);
+ if (!createFile && !file.isOpen())
+ setStatus(QSettings::AccessError);
+
#ifdef Q_OS_WIN
HANDLE readSemaphore = 0;
HANDLE writeSemaphore = 0;
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index e79f87a..2949cd0 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -49,22 +49,51 @@
QT_BEGIN_NAMESPACE
// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
-enum { NumberOfBuckets = 8, FirstBucketSize = 8 };
-
-static const int BucketSize[NumberOfBuckets] =
- { 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216 - 2396744 };
-static const int BucketOffset[NumberOfBuckets] =
- { 0, 8, 72, 584, 4680, 37448, 299592, 2396744 };
-
-static int FirstBucket[FirstBucketSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-static QBasicAtomicPointer<int> timerIds[NumberOfBuckets] =
+static const int TimerIdMask = 0x00ffffff;
+static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
+static const int TimerSerialCounter = TimerIdMask + 1;
+static const int MaxTimerId = TimerIdMask;
+
+static int FirstBucket[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+};
+
+enum {
+ FirstBucketOffset = 0,
+ SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]),
+ ThirdBucketOffset = 0x100,
+ FourthBucketOffset = 0x1000,
+ FifthBucketOffset = 0x10000,
+ SixthBucketOffset = 0x100000
+};
+
+enum {
+ FirstBucketSize = SecondBucketOffset,
+ SecondBucketSize = ThirdBucketOffset - SecondBucketOffset,
+ ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset,
+ FourthBucketSize = FifthBucketOffset - FourthBucketOffset,
+ FifthBucketSize = SixthBucketOffset - FifthBucketOffset,
+ SixthBucketSize = MaxTimerId - SixthBucketOffset
+};
+
+static const int BucketSize[] = {
+ FirstBucketSize, SecondBucketSize, ThirdBucketSize,
+ FourthBucketSize, FifthBucketSize, SixthBucketSize
+};
+enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) };
+
+static const int BucketOffset[] = {
+ FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset,
+ FourthBucketOffset, FifthBucketOffset, SixthBucketOffset
+};
+
+static QBasicAtomicPointer<int> timerIds[] =
{ Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0),
- Q_BASIC_ATOMIC_INITIALIZER(0),
- Q_BASIC_ATOMIC_INITIALIZER(0),
Q_BASIC_ATOMIC_INITIALIZER(0) };
static void timerIdsDestructorFunction()
@@ -77,18 +106,23 @@ Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
-static const int TimerIdMask = 0x00ffffff;
-static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
-static const int TimerSerialCounter = TimerIdMask + 1;
-
// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
{
return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
}
+namespace {
+ template<bool> struct QStaticAssertType;
+ template<> struct QStaticAssertType<true> { enum { Value = 1 }; };
+}
+#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value
+
static inline int bucketOffset(int timerId)
{
+ q_static_assert(sizeof BucketSize == sizeof BucketOffset);
+ q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets);
+
for (int i = 0; i < NumberOfBuckets; ++i) {
if (timerId < BucketSize[i])
return i;
@@ -187,7 +221,8 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
int at = bucketIndex(bucket, which);
int *b = timerIds[bucket];
- Q_ASSERT(b[at] == -timerId);
+ Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
+ "Internal error: timer ID not found");
int freeId, newTimerId;
do {
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
index 6de3bf5..7bed3a2 100644
--- a/src/corelib/kernel/qabstractitemmodel.h
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -162,6 +162,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject
friend class QPersistentModelIndexData;
friend class QAbstractItemViewPrivate;
+ friend class QIdentityProxyModel;
public:
explicit QAbstractItemModel(QObject *parent = 0);
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index be86c58..c0b1748 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -270,6 +270,17 @@ bool QCoreApplicationPrivate::is_app_closing = false;
Q_CORE_EXPORT bool qt_locale_initialized = false;
+/*
+ Create an instance of Trolltech.conf. This ensures that the settings will not
+ be thrown out of QSetting's cache for unused settings.
+ */
+Q_GLOBAL_STATIC_WITH_ARGS(QSettings, staticTrolltechConf, (QSettings::UserScope, QLatin1String("Trolltech")))
+
+QSettings *QCoreApplicationPrivate::trolltechConf()
+{
+ return staticTrolltechConf();
+}
+
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
{
QThreadData *currentThreadData = QThreadData::current();
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index add2a35..eb46ae5 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -55,6 +55,7 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qtranslator.h"
+#include "QtCore/qsettings.h"
#include "private/qobject_p.h"
#ifdef Q_OS_SYMBIAN
@@ -139,6 +140,7 @@ public:
#if defined(QT3_SUPPORT)
static bool useQt3Support;
#endif
+ static QSettings *trolltechConf();
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 7166e7d..bd12726 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -194,6 +194,7 @@ void QActiveObject::reactivateAndComplete()
QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
: QActiveObject(WAKE_UP_PRIORITY, dispatcher)
{
+ m_hostThreadId = RThread().Id();
CActiveScheduler::Add(this);
iStatus = KRequestPending;
SetActive();
@@ -209,6 +210,15 @@ void QWakeUpActiveObject::DoCancel()
if (iStatus.Int() == KRequestPending) {
TRequestStatus *status = &iStatus;
QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ } else if (IsActive() && m_hostThreadId != RThread().Id()) {
+ // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with
+ // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit.
+ // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation
+ // the thread semaphore will be one count down.
+ // It is possible for this problem to affect other active objects. They symptom would be that finished signals
+ // from adopted threads are not sent, or they arrive much later than they should.
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
}
}
@@ -224,8 +234,10 @@ void QWakeUpActiveObject::RunL()
QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
: QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
- m_timerInfo(timerInfo)
+ m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
{
+ // start the timeout timer to ensure initialisation
+ m_timeoutTimer.start();
}
QTimerActiveObject::~QTimerActiveObject()
@@ -269,10 +281,23 @@ void QTimerActiveObject::StartTimer()
m_rTimer.After(iStatus, MAX_SYMBIAN_TIMEOUT_MS * 1000);
m_timerInfo->msLeft -= MAX_SYMBIAN_TIMEOUT_MS;
} else {
- //HighRes gives the 1ms accuracy expected by Qt, the +1 is to ensure that
- //"Timers will never time out earlier than the specified timeout value"
- //condition is always met.
- m_rTimer.HighRes(iStatus, (m_timerInfo->msLeft + 1) * 1000);
+ // this algorithm implements drift correction for repeating timers
+ // calculate how late we are for this event
+ int timeSinceLastEvent = m_timeoutTimer.restart();
+ int overshoot = timeSinceLastEvent - m_expectedTimeSinceLastEvent;
+ if (overshoot > m_timerInfo->msLeft) {
+ // we skipped a whole timeout, restart from here
+ overshoot = 0;
+ }
+ // calculate when the next event should happen
+ int waitTime = m_timerInfo->msLeft - overshoot;
+ m_expectedTimeSinceLastEvent = waitTime;
+ // limit the actual ms wait time to avoid wild corrections
+ // this will cause the real event time to slowly drift back to the expected event time
+ // measurements show that Symbian timers always fire 1 or 2 ms late
+ const int limit = 4;
+ waitTime = qMax(m_timerInfo->msLeft - limit, waitTime);
+ m_rTimer.HighRes(iStatus, waitTime * 1000);
m_timerInfo->msLeft = 0;
}
SetActive();
@@ -319,6 +344,8 @@ void QTimerActiveObject::Start()
if (!m_rTimer.Handle()) {
qt_symbian_throwIfError(m_rTimer.CreateLocal());
}
+ m_timeoutTimer.start();
+ m_expectedTimeSinceLastEvent = 0;
StartTimer();
} else {
iStatus = KRequestPending;
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
index e07d475..6fdd4b2 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian_p.h
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -110,6 +110,9 @@ public:
protected:
void DoCancel();
void RunL();
+
+private:
+ TThreadId m_hostThreadId;
};
struct SymbianTimerInfo : public QSharedData
@@ -147,6 +150,8 @@ private:
private:
SymbianTimerInfo *m_timerInfo;
+ QElapsedTimer m_timeoutTimer;
+ int m_expectedTimeSinceLastEvent;
RTimer m_rTimer;
};
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp
index 7d63088..73f695b 100644
--- a/src/corelib/kernel/qpointer.cpp
+++ b/src/corelib/kernel/qpointer.cpp
@@ -183,6 +183,7 @@
/*!
\fn bool operator==(const T *o, const QPointer<T> &p)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -191,6 +192,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p, const T *o)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -199,6 +201,7 @@
*/
/*!
\fn bool operator==(T *o, const QPointer<T> &p)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -207,6 +210,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p, T *o)
+ \relates QPointer
Equality operator. Returns true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
@@ -215,6 +219,7 @@
*/
/*!
\fn bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
Equality operator. Returns true if the guarded pointers \a p1 and \a p2
are pointing to the same object, otherwise
@@ -225,6 +230,7 @@
/*!
\fn bool operator!=(const T *o, const QPointer<T> &p)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -232,6 +238,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p, const T *o)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -239,6 +246,7 @@
*/
/*!
\fn bool operator!=(T *o, const QPointer<T> &p)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -246,6 +254,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p, T *o)
+ \relates QPointer
Inequality operator. Returns true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
@@ -253,6 +262,7 @@
*/
/*!
\fn bool operator!=(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
Inequality operator. Returns true if the guarded pointers \a p1 and
\a p2 are not pointing to the same object, otherwise
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 80e927b..d9aac00 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -52,6 +52,7 @@
#include <qmap.h>
#include <qsettings.h>
#include <qdatetime.h>
+#include <private/qcoreapplication_p.h>
#ifdef Q_OS_MAC
# include <private/qcore_mac_p.h>
#endif
@@ -408,12 +409,6 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB
typedef QMap<QString, QLibraryPrivate*> LibraryMap;
struct LibraryData {
- LibraryData() : settings(0) { }
- ~LibraryData() {
- delete settings;
- }
-
- QSettings *settings;
LibraryMap libraryMap;
QSet<QLibraryPrivate*> loadedLibs;
};
@@ -711,11 +706,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
QStringList reg;
#ifndef QT_NO_SETTINGS
if (!settings) {
- settings = libraryData()->settings;
- if (!settings) {
- settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
- libraryData()->settings = settings;
- }
+ settings = QCoreApplicationPrivate::trolltechConf();
}
reg = settings->value(regkey).toStringList();
#endif
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 11e2060..b584ae5 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -107,18 +107,21 @@ bool QMutexPrivate::wait(int timeout)
// lock acquired without waiting
return true;
}
- bool returnValue;
+ kern_return_t r;
if (timeout < 0) {
- returnValue = semaphore_wait(mach_semaphore) == KERN_SUCCESS;
+ do {
+ r = semaphore_wait(mach_semaphore);
+ } while (r == KERN_ABORTED);
+ if (r != KERN_SUCCESS)
+ qWarning("QMutex: infinite wait failed, error %d", r);
} else {
mach_timespec_t ts;
ts.tv_nsec = ((timeout % 1000) * 1000) * 1000;
ts.tv_sec = (timeout / 1000);
- kern_return_t r = semaphore_timedwait(mach_semaphore, ts);
- returnValue = r == KERN_SUCCESS;
+ r = semaphore_timedwait(mach_semaphore, ts);
}
contenders.deref();
- return returnValue;
+ return r == KERN_SUCCESS;
}
void QMutexPrivate::wakeUp()
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp
index 15e6898..665aadd 100644
--- a/src/corelib/thread/qthread_symbian.cpp
+++ b/src/corelib/thread/qthread_symbian.cpp
@@ -113,6 +113,7 @@ QThreadData *QThreadData::current()
}
data->deref();
}
+ data->isAdopted = true;
data->threadId = QThread::currentThreadId();
if (!QCoreApplicationPrivate::theMainThread)
QCoreApplicationPrivate::theMainThread = data->thread;
@@ -257,6 +258,13 @@ QCAddAdoptedThread* QCAddAdoptedThread::adoptedThreadAdder = 0;
void QCAdoptedThreadMonitor::RunL()
{
+ if (data->isAdopted) {
+ QThread *thread = data->thread;
+ Q_ASSERT(thread);
+ QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_ASSERT(!thread_p->finished);
+ thread_p->finish(thread);
+ }
data->deref();
QCAddAdoptedThread::threadDied();
delete this;
@@ -321,6 +329,8 @@ void *QThreadPrivate::start(void *arg)
data->quitNow = thr->d_func()->exited;
}
+ CTrapCleanup *cleanup = CTrapCleanup::New();
+
// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);
@@ -329,6 +339,8 @@ void *QThreadPrivate::start(void *arg)
QThreadPrivate::finish(arg);
+ delete cleanup;
+
return 0;
}
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index bab6cf8..bdade1d 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -300,7 +300,7 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
#ifndef QT_NO_THREAD
-unsigned int __stdcall QThreadPrivate::start(void *arg)
+unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg)
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 6957022..0627b4e 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -52,6 +52,17 @@
#error qbytearray.h must be included before any header file that defines truncate
#endif
+#if defined(Q_CC_GNU) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
+//There is a bug in GCC 4.0 that tries to instantiate template of annonymous enum
+# ifdef QT_USE_FAST_OPERATOR_PLUS
+# undef QT_USE_FAST_OPERATOR_PLUS
+# endif
+# ifdef QT_USE_FAST_CONCATENATION
+# undef QT_USE_FAST_CONCATENATION
+# endif
+#endif
+
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index a3a8884..d9a054a 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -2460,7 +2460,11 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
If the \a format is Qt::ISODate, the string format corresponds
to the ISO 8601 extended specification for representations of
- dates and times, taking the form YYYY-MM-DDTHH:MM:SS.
+ dates and times, taking the form YYYY-MM-DDTHH:MM:SS[Z|[+|-]HH:MM],
+ depending on the timeSpec() of the QDateTime. If the timeSpec()
+ is Qt::UTC, Z will be appended to the string; if the timeSpec() is
+ Qt::OffsetFromUTC the offset in hours and minutes from UTC will
+ be appended to the string.
If the \a format is Qt::SystemLocaleShortDate or
Qt::SystemLocaleLongDate, the string format depends on the locale
@@ -2497,6 +2501,21 @@ QString QDateTime::toString(Qt::DateFormat f) const
return QString(); // failed to convert
buf += QLatin1Char('T');
buf += d->time.toString(Qt::ISODate);
+ switch (d->spec) {
+ case QDateTimePrivate::UTC:
+ buf += QLatin1Char('Z');
+ break;
+ case QDateTimePrivate::OffsetFromUTC: {
+ int sign = d->utcOffset >= 0 ? 1: -1;
+ buf += QString::fromLatin1("%1%2:%3").
+ arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')).
+ arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')).
+ arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0'));
+ break;
+ }
+ default:
+ break;
+ }
}
#ifndef QT_NO_TEXTDATE
else if (f == Qt::TextDate) {
diff --git a/src/corelib/tools/qelapsedtimer_symbian.cpp b/src/corelib/tools/qelapsedtimer_symbian.cpp
index b831e03..3667b05 100644
--- a/src/corelib/tools/qelapsedtimer_symbian.cpp
+++ b/src/corelib/tools/qelapsedtimer_symbian.cpp
@@ -95,7 +95,7 @@ qint64 QElapsedTimer::restart()
qint64 oldt1 = t1;
t1 = getMicrosecondFromTick();
t2 = 0;
- return t1 - oldt1;
+ return (t1 - oldt1) / 1000;
}
qint64 QElapsedTimer::nsecsElapsed() const
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index d986b9b..c8ed94b 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -86,6 +86,10 @@ static QLocalePrivate *system_lp = 0;
Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate)
#endif
+#ifdef QT_USE_ICU
+extern bool qt_initIcu(const QString &localeName);
+#endif
+
/******************************************************************************
** Helpers for accessing Qt locale database
*/
@@ -520,6 +524,12 @@ void QLocalePrivate::updateSystemPrivate()
res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
if (!res.isNull())
system_lp->m_plus = res.toString().at(0).unicode();
+
+#ifdef QT_USE_ICU
+ if (!default_lp)
+ qt_initIcu(system_lp->bcp47Name());
+#endif
+
}
#endif
@@ -879,6 +889,10 @@ void QLocale::setDefault(const QLocale &locale)
{
default_lp = locale.d();
default_number_options = locale.numberOptions();
+
+#ifdef QT_USE_ICU
+ qt_initIcu(locale.bcp47Name());
+#endif
}
/*!
@@ -2768,8 +2782,6 @@ bool QLocalePrivate::numberToCLocale(const QString &num,
if (idx == l)
return false;
- const QChar _group = group();
-
while (idx < l) {
const QChar &in = uc[idx];
diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp
new file mode 100644
index 0000000..0e283dd
--- /dev/null
+++ b/src/corelib/tools/qlocale_icu.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+#include "qlibrary.h"
+#include "qdebug.h"
+
+#include "unicode/uversion.h"
+#include "unicode/ucol.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status);
+typedef void (*Ptr_ucol_close)(UCollator *coll);
+typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength);
+typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode);
+
+static Ptr_ucol_open ptr_ucol_open = 0;
+static Ptr_ucol_strcoll ptr_ucol_strcoll = 0;
+static Ptr_ucol_close ptr_ucol_close = 0;
+static Ptr_u_strToCase ptr_u_strToUpper = 0;
+static Ptr_u_strToCase ptr_u_strToLower = 0;
+
+enum LibLoadStatus
+{
+ ErrorLoading = -1,
+ NotLoaded = 0,
+ Loaded = 1
+};
+
+static LibLoadStatus status = NotLoaded;
+
+static UCollator *icuCollator = 0;
+
+#define STRINGIFY2(x) #x
+#define STRINGIFY(x) STRINGIFY2(x)
+
+bool qt_initIcu(const QString &localeString)
+{
+ if (status == ErrorLoading)
+ return false;
+
+ if (status == NotLoaded) {
+
+ // resolve libicui18n
+ QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT));
+ if (!lib.load()) {
+ qWarning() << "Unable to load library icui18n" << lib.errorString();
+ status = ErrorLoading;
+ return false;
+ }
+
+ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open");
+ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close");
+ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll");
+
+ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+ // try again with decorated symbol names
+ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ }
+
+ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
+ ptr_ucol_open = 0;
+ ptr_ucol_close = 0;
+ ptr_ucol_strcoll = 0;
+
+ qWarning("Unable to find symbols in icui18n");
+ status = ErrorLoading;
+ return false;
+ }
+
+ // resolve libicuuc
+ QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT));
+ if (!ucLib.load()) {
+ qWarning() << "Unable to load library icuuc" << ucLib.errorString();
+ status = ErrorLoading;
+ return false;
+ }
+
+ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper");
+ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower");
+
+ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX));
+ }
+
+ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
+ ptr_u_strToUpper = 0;
+ ptr_u_strToLower = 0;
+
+ qWarning("Unable to find symbols in icuuc");
+ status = ErrorLoading;
+ return false;
+ }
+
+ // success :)
+ status = Loaded;
+ }
+
+ if (icuCollator) {
+ ptr_ucol_close(icuCollator);
+ icuCollator = 0;
+ }
+
+ UErrorCode icuStatus = U_ZERO_ERROR;
+ icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus);
+
+ if (!icuCollator) {
+ qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus);
+ return false;
+ }
+
+ return true;
+}
+
+bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result)
+{
+ Q_ASSERT(result);
+ Q_ASSERT(source);
+ Q_ASSERT(target);
+
+ if (!icuCollator)
+ return false;
+
+ *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength),
+ reinterpret_cast<const UChar *>(target), int32_t(targetLength));
+
+ return true;
+}
+
+// caseFunc can either be u_strToUpper or u_strToLower
+static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc)
+{
+ Q_ASSERT(out);
+
+ if (!icuCollator)
+ return false;
+
+ QString result(str.size(), Qt::Uninitialized);
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+ reinterpret_cast<const UChar *>(str.constData()), str.size(),
+ locale.bcp47Name().toLatin1().constData(), &status);
+
+ if (U_FAILURE(status))
+ return false;
+
+ if (size < result.size()) {
+ result.resize(size);
+ } else if (size > result.size()) {
+ // the resulting string is larger than our source string
+ result.resize(size);
+
+ status = U_ZERO_ERROR;
+ size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
+ reinterpret_cast<const UChar *>(str.constData()), str.size(),
+ locale.bcp47Name().toLatin1().constData(), &status);
+
+ if (U_FAILURE(status))
+ return false;
+
+ // if the sizes don't match now, we give up.
+ if (size != result.size())
+ return false;
+ }
+
+ *out = result;
+ return true;
+}
+
+bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale)
+{
+ return qt_u_strToCase(str, out, locale, ptr_u_strToUpper);
+}
+
+bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale)
+{
+ return qt_u_strToCase(str, out, locale, ptr_u_strToLower);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
index 29d9a53..52005e0 100644
--- a/src/corelib/tools/qlocale_mac.mm
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -318,7 +318,7 @@ static QString macFormatCurrency(const QSystemLocale::CurrencyToStringArgument &
break;
}
case QVariant::Double: {
- double v = arg.value.toInt();
+ double v = arg.value.toDouble();
value = CFNumberCreate(NULL, kCFNumberDoubleType, &v);
break;
}
diff --git a/src/corelib/tools/qlocale_symbian.cpp b/src/corelib/tools/qlocale_symbian.cpp
index 09d74d0..5dca7b7 100644
--- a/src/corelib/tools/qlocale_symbian.cpp
+++ b/src/corelib/tools/qlocale_symbian.cpp
@@ -44,6 +44,7 @@
#include <QTime>
#include <QVariant>
#include <QThread>
+#include <QStringList>
#include <e32std.h>
#include <e32const.h>
@@ -86,6 +87,7 @@ static TPtrC defaultFormatSpec(TExtendedLocale&)
struct symbianToISO {
int symbian_language;
char iso_name[8];
+ char uilanguage[8];
};
@@ -94,77 +96,80 @@ struct symbianToISO {
NOTE: This array should be sorted by the first column!
*/
static const symbianToISO symbian_to_iso_list[] = {
- { ELangEnglish, "en_GB" }, // 1
- { ELangFrench, "fr_FR" }, // 2
- { ELangGerman, "de_DE" }, // 3
- { ELangSpanish, "es_ES" }, // 4
- { ELangItalian, "it_IT" }, // 5
- { ELangSwedish, "sv_SE" }, // 6
- { ELangDanish, "da_DK" }, // 7
- { ELangNorwegian, "no_NO" }, // 8
- { ELangFinnish, "fi_FI" }, // 9
- { ELangAmerican, "en_US" }, // 10
- { ELangPortuguese, "pt_PT" }, // 13
- { ELangTurkish, "tr_TR" }, // 14
- { ELangIcelandic, "is_IS" }, // 15
- { ELangRussian, "ru_RU" }, // 16
- { ELangHungarian, "hu_HU" }, // 17
- { ELangDutch, "nl_NL" }, // 18
- { ELangBelgianFlemish, "nl_BE" }, // 19
- { ELangCzech, "cs_CZ" }, // 25
- { ELangSlovak, "sk_SK" }, // 26
- { ELangPolish, "pl_PL" }, // 27
- { ELangSlovenian, "sl_SI" }, // 28
- { ELangTaiwanChinese, "zh_TW" }, // 29
- { ELangHongKongChinese, "zh_HK" }, // 30
- { ELangPrcChinese, "zh_CN" }, // 31
- { ELangJapanese, "ja_JP" }, // 32
- { ELangThai, "th_TH" }, // 33
- { ELangArabic, "ar_AE" }, // 37
- { ELangTagalog, "tl_PH" }, // 39
- { ELangBulgarian, "bg_BG" }, // 42
- { ELangCatalan, "ca_ES" }, // 44
- { ELangCroatian, "hr_HR" }, // 45
- { ELangEstonian, "et_EE" }, // 49
- { ELangFarsi, "fa_IR" }, // 50
- { ELangCanadianFrench, "fr_CA" }, // 51
- { ELangGreek, "el_GR" }, // 54
- { ELangHebrew, "he_IL" }, // 57
- { ELangHindi, "hi_IN" }, // 58
- { ELangIndonesian, "id_ID" }, // 59
- { ELangKorean, "ko_KO" }, // 65
- { ELangLatvian, "lv_LV" }, // 67
- { ELangLithuanian, "lt_LT" }, // 68
- { ELangMalay, "ms_MY" }, // 70
- { ELangNorwegianNynorsk, "nn_NO" }, // 75
- { ELangBrazilianPortuguese, "pt_BR" }, // 76
- { ELangRomanian, "ro_RO" }, // 78
- { ELangSerbian, "sr_RS" }, // 79
- { ELangLatinAmericanSpanish,"es_419" }, // 83
- { ELangUkrainian, "uk_UA" }, // 93
- { ELangUrdu, "ur_PK" }, // 94 - India/Pakistan
- { ELangVietnamese, "vi_VN" }, // 96
+ { ELangEnglish, "en_GB", "en" }, // 1
+ { ELangFrench, "fr_FR", "fr" }, // 2
+ { ELangGerman, "de_DE", "de" }, // 3
+ { ELangSpanish, "es_ES", "es" }, // 4
+ { ELangItalian, "it_IT", "it" }, // 5
+ { ELangSwedish, "sv_SE", "sv" }, // 6
+ { ELangDanish, "da_DK", "da" }, // 7
+ { ELangNorwegian, "nb_NO", "nb" }, // 8
+ { ELangFinnish, "fi_FI", "fi" }, // 9
+ { ELangAmerican, "en_US", "en-US" }, // 10
+ { ELangPortuguese, "pt_PT", "pt" }, // 13
+ { ELangTurkish, "tr_TR", "tr" }, // 14
+ { ELangIcelandic, "is_IS", "is" }, // 15
+ { ELangRussian, "ru_RU", "ru" }, // 16
+ { ELangHungarian, "hu_HU", "hu" }, // 17
+ { ELangDutch, "nl_NL", "nl" }, // 18
+ { ELangCzech, "cs_CZ", "cs" }, // 25
+ { ELangSlovak, "sk_SK", "sk" }, // 26
+ { ELangPolish, "pl_PL", "pl" }, // 27
+ { ELangSlovenian, "sl_SI", "sl" }, // 28
+ { ELangTaiwanChinese, "zh_TW", "zh-TW" }, // 29
+ { ELangHongKongChinese, "zh_HK", "zh-HK" }, // 30
+ { ELangPrcChinese, "zh_CN", "zh" }, // 31
+ { ELangJapanese, "ja_JP", "ja" }, // 32
+ { ELangThai, "th_TH", "th" }, // 33
+ { ELangArabic, "ar_AE", "ar" }, // 37
+ { ELangTagalog, "tl_PH", "tl" }, // 39
+ { ELangBulgarian, "bg_BG", "bg" }, // 42
+ { ELangCatalan, "ca_ES", "ca" }, // 44
+ { ELangCroatian, "hr_HR", "hr" }, // 45
+ { ELangEstonian, "et_EE", "et" }, // 49
+ { ELangFarsi, "fa_IR", "fa" }, // 50
+ { ELangCanadianFrench, "fr_CA", "fr-CA" }, // 51
+ { ELangGreek, "el_GR", "el" }, // 54
+ { ELangHebrew, "he_IL", "he" }, // 57
+ { ELangHindi, "hi_IN", "hi" }, // 58
+ { ELangIndonesian, "id_ID", "id" }, // 59
+ { 63/*ELangKazakh*/, "kk_KZ", "kk" }, // 63
+ { ELangKorean, "ko_KO", "ko" }, // 65
+ { ELangLatvian, "lv_LV", "lv" }, // 67
+ { ELangLithuanian, "lt_LT", "lt" }, // 68
+ { ELangMalay, "ms_MY", "ms" }, // 70
+ { ELangNorwegianNynorsk, "nn_NO", "nn" }, // 75
+ { ELangBrazilianPortuguese, "pt_BR", "pt-BR" }, // 76
+ { ELangRomanian, "ro_RO", "ro" }, // 78
+ { ELangSerbian, "sr_RS", "sr" }, // 79
+ { ELangLatinAmericanSpanish,"es_419", "es-419" },// 83
+ { ELangUkrainian, "uk_UA", "uk" }, // 93
+ { ELangUrdu, "ur_PK", "ur" }, // 94 - India/Pakistan
+ { ELangVietnamese, "vi_VN", "vi" }, // 96
#ifdef __E32LANG_H__
// 5.0
- { ELangBasque, "eu_ES" }, // 102
- { ELangGalician, "gl_ES" }, // 103
+ { ELangBasque, "eu_ES", "eu" }, // 102
+ { ELangGalician, "gl_ES", "gl" }, // 103
#endif
#if !defined(__SERIES60_31__)
- { ELangEnglish_Apac, "en" }, // 129
- { ELangEnglish_Taiwan, "en_TW" }, // 157 ### Not supported by CLDR
- { ELangEnglish_HongKong, "en_HK" }, // 158
- { ELangEnglish_Prc, "en_CN" }, // 159 ### Not supported by CLDR
- { ELangEnglish_Japan, "en_JP"}, // 160 ### Not supported by CLDR
- { ELangEnglish_Thailand, "en_TH" }, // 161 ### Not supported by CLDR
- { ELangMalay_Apac, "ms" }, // 326
+ { ELangEnglish_Apac, "en_GB", "en" }, // 129
+ { ELangEnglish_Taiwan, "en_TW", "en-TW" }, // 157 ### Not supported by CLDR
+ { ELangEnglish_HongKong, "en_HK", "en-HK" }, // 158
+ { ELangEnglish_Prc, "en_CN", "en-CN" }, // 159 ### Not supported by CLDR
+ { ELangEnglish_Japan, "en_JP", "en" }, // 160 ### Not supported by CLDR
+ { ELangEnglish_Thailand, "en_TH", "en" }, // 161 ### Not supported by CLDR
+ { 230/*ELangEnglish_India*/,"en_IN", "en" }, // 230
+ { ELangMalay_Apac, "ms_MY", "ms" }, // 326
#endif
- { 327/*ELangIndonesian_Apac*/,"id_ID" } // 327 - appeared in Symbian^3
+ { 327/*ELangIndonesian_Apac*/, "id_ID", "id" } // 327 - appeared in Symbian^3
};
-/*!
- Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
-*/
-QByteArray qt_symbianLocaleName(int code)
+enum LocaleNameType {
+ ISO,
+ UILanguage
+};
+
+QByteArray qt_resolveSymbianLocaleName(int code, LocaleNameType type)
{
//Number of Symbian to ISO locale mappings
static const int symbian_to_iso_count
@@ -174,8 +179,11 @@ QByteArray qt_symbianLocaleName(int code)
if (cmp < 0)
return 0;
- if (cmp == 0)
- return symbian_to_iso_list[0].iso_name;
+ if (cmp == 0) {
+ if (type == ISO)
+ return symbian_to_iso_list[0].iso_name;
+ return symbian_to_iso_list[0].uilanguage;
+ }
int begin = 0;
int end = symbian_to_iso_count;
@@ -185,17 +193,27 @@ QByteArray qt_symbianLocaleName(int code)
const symbianToISO *elt = symbian_to_iso_list + mid;
int cmp = code - elt->symbian_language;
- if (cmp < 0)
+ if (cmp < 0) {
end = mid;
- else if (cmp > 0)
+ } else if (cmp > 0) {
begin = mid;
- else
- return elt->iso_name;
+ } else {
+ if (type == ISO)
+ return elt->iso_name;
+ return elt->uilanguage;
+ }
}
return 0;
}
+/*!
+ Returns ISO name corresponding to the Symbian locale code \a sys_fmt.
+*/
+QByteArray qt_symbianLocaleName(int code)
+{
+ return qt_resolveSymbianLocaleName(code, ISO);
+}
// order is: normal, abbr, nmode, nmode+abbr
static const char *us_locale_dep[] = {
@@ -822,6 +840,13 @@ QLocale QSystemLocale::fallbackLocale() const
return QLocale(locale);
}
+static QStringList symbianUILanguages()
+{
+ TLanguage lang = User::Language();
+ QString s = QLatin1String(qt_resolveSymbianLocaleName(lang, UILanguage));
+ return QStringList(s);
+}
+
QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
{
switch(type) {
@@ -889,6 +914,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return qt_TDes2QString(TAmPmName(TAmPm(EAm)));
case PMText:
return qt_TDes2QString(TAmPmName(TAmPm(EPm)));
+ case UILanguages:
+ return QVariant(symbianUILanguages());
default:
break;
}
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index b1f77b4..95256fb 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -85,7 +85,7 @@
reference count (i.e., a reference counter placed outside the
object). Like its name indicates, the pointer value is shared
among all instances of QSharedPointer and QWeakPointer. The
- contents of the object pointed to by the pointer should not
+ contents of the object pointed to by the pointer should not be
considered shared, however: there is only one object. For that
reason, QSharedPointer does not provide a way to detach or make
copies of the pointed object.
@@ -151,7 +151,7 @@
QtSharedPointer::ExternalRefCount implements the actual reference
counting and introduces the d-pointer for QSharedPointer. That d-pointer
- itself is shared with with other QSharedPointer objects as well as
+ itself is shared with other QSharedPointer objects as well as
QWeakPointer.
The reason for keeping the pointer value itself outside the d-pointer is
@@ -213,7 +213,7 @@
destroyer field must be set to a valid function that \b will delete the
object tracked.
- This class also adds an operator delete function to ensure that simply
+ This class also adds an operator delete function to ensure that it simply
calls the global operator delete. That should be the behaviour in all
compilers already, but to be on the safe side, this class ensures that no
funny business happens.
@@ -308,7 +308,7 @@
When initialising the parent class, the create() functions pass the
address of the static deleter() member function. That is, when the
virtual destroy() is called by QSharedPointer, the deleter() functions
- are called instead. These functiosn static_cast the ExternalRefCountData*
+ are called instead. These functions static_cast the ExternalRefCountData*
parameter to their own type and execute their deletion: for the
ExternalRefCountWithCustomDeleter::deleter() case, it runs the user's
custom deleter, then destroys the deleter; for
@@ -318,7 +318,7 @@
By not calling the constructor of the derived classes, we avoid
instantiating their virtual tables. Since these classes are
template-based, there would be one virtual table per \tt T and \tt
- Deleter type. (This is what Qt 4.5 did)
+ Deleter type. (This is what Qt 4.5 did.)
Instead, only one non-inline function is required per template, which is
the deleter() static member. All the other functions can be inlined.
@@ -381,7 +381,7 @@
first promote it to QSharedPointer and verify if the resulting object is
null or not. QSharedPointer guarantees that the object isn't deleted, so
if you obtain a non-null object, you may use the pointer. See
- QWeakPointer::toStrongRef() for more an example.
+ QWeakPointer::toStrongRef() for an example.
QWeakPointer also provides the QWeakPointer::data() method that returns
the tracked pointer without ensuring that it remains valid. This function
@@ -395,7 +395,7 @@
\section1 Tracking QObject
- QWeakPointer can be used to track deletion classes that derive from QObject,
+ QWeakPointer can be used to track deletion of classes that derive from QObject,
even if they are not managed by QSharedPointer. When used in that role,
QWeakPointer replaces the older QPointer in all use-cases. QWeakPointer
is also more efficient than QPointer, so it should be preferred in all
@@ -483,9 +483,9 @@
another QSharedPointer object or deleted outside this object.
The \a deleter parameter specifies the custom deleter for this
- object. The custom deleter is called when the strong reference
- count drops to 0 instead of the operator delete(). This is useful,
- for instance, for calling deleteLater() in a QObject instead:
+ object. The custom deleter is called, instead of the operator delete(),
+ when the strong reference count drops to 0. This is useful,
+ for instance, for calling deleteLater() on a QObject instead:
\code
static void doDeleteLater(MyObject *obj)
@@ -754,7 +754,7 @@
\fn QWeakPointer &QWeakPointer::operator=(const QObject *obj)
\since 4.6
- Makes this QWeakPointer hold a weak reference to directly to the QObject
+ Makes this QWeakPointer hold a weak reference directly to the QObject
\a obj. This function is only available if the template type \tt T is
QObject or derives from it.
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b7272ec..5493ba9 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -106,6 +106,14 @@ QTextCodec *QString::codecForCStrings;
static QHash<void *, QByteArray> *asciiCache = 0;
#endif
+#ifdef QT_USE_ICU
+// qlocale_icu.cpp
+extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result);
+extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale);
+extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale);
+#endif
+
+
// internal
int qFindString(const QChar *haystack, int haystackLen, int from,
const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
@@ -431,7 +439,6 @@ const QString::Null QString::null = { };
\ingroup shared
\ingroup string-processing
-
QString stores a string of 16-bit \l{QChar}s, where each QChar
corresponds one Unicode 4.0 character. (Unicode characters
with code values above 65535 are stored using surrogate pairs,
@@ -4829,6 +4836,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2);
return p1.CompareC(p2);
#elif defined(Q_OS_UNIX)
+# if defined(QT_USE_ICU)
+ int res;
+ if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) {
+ if (res == 0)
+ res = ucstrcmp(data1, length1, data2, length2);
+ return res;
+ } // else fall through
+# endif
// declared in <string.h>
int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2));
if (delta == 0)
@@ -4964,6 +4979,15 @@ QString QString::toLower() const
if (!d->size)
return *this;
+#ifdef QT_USE_ICU
+ {
+ QString result;
+ if (qt_u_strToLower(*this, &result, QLocale()))
+ return result;
+ // else fall through and use Qt's toUpper
+ }
+#endif
+
const ushort *e = d->data + d->size;
// this avoids one out of bounds check in the loop
@@ -5055,6 +5079,15 @@ QString QString::toUpper() const
if (!d->size)
return *this;
+#ifdef QT_USE_ICU
+ {
+ QString result;
+ if (qt_u_strToUpper(*this, &result, QLocale()))
+ return result;
+ // else fall through and use Qt's toUpper
+ }
+#endif
+
const ushort *e = d->data + d->size;
// this avoids one out of bounds check in the loop
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 002e516..6418a8c 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -66,16 +66,6 @@ typedef std::basic_string<wchar_t> QStdWString;
#error qstring.h must be included before any header file that defines truncate
#endif
-#if defined(Q_CC_GNU) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
-//There is a bug in GCC 4.0 that tries to instantiate template of annonymous enum
-# ifdef QT_USE_FAST_OPERATOR_PLUS
-# undef QT_USE_FAST_OPERATOR_PLUS
-# endif
-# ifdef QT_USE_FAST_CONCATENATION
-# undef QT_USE_FAST_CONCATENATION
-# endif
-#endif
-
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -705,9 +695,9 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat
inline int QString::length() const
{ return d->size; }
inline const QChar QString::at(int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
inline const QChar QString::operator[](int i) const
-{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; }
+{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; }
inline const QChar QString::operator[](uint i) const
{ Q_ASSERT(i < uint(size())); return d->data[i]; }
inline bool QString::isEmpty() const
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 34bc406..47319d4 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -199,11 +199,11 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
chars = other.chars;
length = other.length;
pos = other.pos;
- freePrivate = true;
QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
- realloc(d, length*sizeof(HB_CharAttributes));
+ realloc(freePrivate ? d : 0, length*sizeof(HB_CharAttributes));
Q_CHECK_PTR(newD);
+ freePrivate = true;
d = newD;
memcpy(d, other.d, length*sizeof(HB_CharAttributes));
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 849dc63..0c2cf16 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -97,6 +97,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp
contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri)
else:include($$PWD/../../3rdparty/zlib_dependency.pri)
+contains(QT_CONFIG,icu) {
+ SOURCES += tools/qlocale_icu.cpp
+ DEFINES += QT_USE_ICU
+}
+
DEFINES += HB_EXPORT=Q_CORE_EXPORT
INCLUDEPATH += ../3rdparty/harfbuzz/src
HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h
diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro
index 52ed217..08c9ea1 100644
--- a/src/dbus/dbus.pro
+++ b/src/dbus/dbus.pro
@@ -59,7 +59,8 @@ HEADERS += $$PUB_HEADERS \
qdbusintegrator_p.h \
qdbuspendingcall_p.h \
qdbus_symbols_p.h \
- qdbusservicewatcher.h
+ qdbusservicewatcher.h \
+ qdbusunixfiledescriptor.h
SOURCES += qdbusconnection.cpp \
qdbusconnectioninterface.cpp \
qdbuserror.cpp \
@@ -85,4 +86,5 @@ SOURCES += qdbusconnection.cpp \
qdbuspendingcall.cpp \
qdbuspendingreply.cpp \
qdbus_symbols.cpp \
- qdbusservicewatcher.cpp
+ qdbusservicewatcher.cpp \
+ qdbusunixfiledescriptor.cpp
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index c5f55af..039657e 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -296,6 +296,12 @@ DEFINEFUNC(dbus_bool_t , dbus_message_set_sender, (DBusMessage *message,
DEFINEFUNC(void , dbus_message_unref, (DBusMessage *message),
(message), )
+/* dbus-misc.h */
+DEFINEFUNC(void , dbus_get_version , (int *major_version_p,
+ int *minor_version_p,
+ int *micro_version_p),
+ (major_version_p, minor_version_p, micro_version_p), )
+
/* dbus-pending-call.h */
DEFINEFUNC(dbus_bool_t , dbus_pending_call_set_notify, (DBusPendingCall *pending,
DBusPendingCallNotifyFunction function,
@@ -352,21 +358,17 @@ DEFINEFUNC(dbus_bool_t , dbus_server_set_watch_functions, (DBusServer
DEFINEFUNC(void , dbus_server_unref, (DBusServer *server),
(server), )
-/* dbus-signature.h */
-DEFINEFUNC(dbus_bool_t , dbus_signature_validate, (const char *signature,
- DBusError *error),
- (signature, error), return)
-DEFINEFUNC(dbus_bool_t , dbus_signature_validate_single, (const char *signature,
- DBusError *error),
- (signature, error), return)
-DEFINEFUNC(dbus_bool_t , dbus_type_is_basic, (int typecode),
- (typecode), return)
-DEFINEFUNC(dbus_bool_t , dbus_type_is_fixed, (int typecode),
- (typecode), return)
-
/* dbus-thread.h */
DEFINEFUNC(dbus_bool_t , dbus_threads_init_default, (), (), return)
+
+/* D-Bus 1.4 symbols */
+#if !defined(QT_LINKED_LIBDBUS) || (DBUS_VERSION >= 0x010400)
+DEFINEFUNC(dbus_bool_t , dbus_connection_can_send_type , (DBusConnection *connection,
+ int type),
+ (connection, type), return)
+#endif
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index e48e1c0..9e82c09 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
static QDBusError checkIfValid(const QString &service, const QString &path,
- const QString &interface, bool isDynamic)
+ const QString &interface, bool isDynamic, bool isPeer)
{
// We should be throwing exceptions here... oh well
QDBusError error;
@@ -69,7 +69,7 @@ static QDBusError checkIfValid(const QString &service, const QString &path,
// use assertion here because this should never happen, at all
Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty");
}
- if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
+ if (!QDBusUtil::checkBusName(service, (isDynamic && !isPeer) ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
@@ -86,7 +86,8 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv
const QDBusConnection& con,
bool isDynamic)
: connection(con), service(serv), path(p), interface(iface),
- lastError(checkIfValid(serv, p, iface, isDynamic)),
+ lastError(checkIfValid(serv, p, iface, isDynamic, (connectionPrivate() &&
+ connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode))),
isValid(!lastError.isValid())
{
if (!isValid)
@@ -107,7 +108,7 @@ bool QDBusAbstractInterfacePrivate::canMakeCalls() const
{
// recheck only if we have a wildcard (i.e. empty) service or path
// if any are empty, set the error message according to QDBusUtil
- if (service.isEmpty())
+ if (service.isEmpty() && connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode)
return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError);
if (path.isEmpty())
return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError);
diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp
index 09f0e82..806b7fe 100644
--- a/src/dbus/qdbusargument.cpp
+++ b/src/dbus/qdbusargument.cpp
@@ -487,6 +487,20 @@ QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg)
/*!
\overload
+ \since 4.8
+ \internal
+ Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix
+ File Descriptor) to the D-Bus stream.
+*/
+QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg)
+{
+ if (QDBusArgumentPrivate::checkWrite(d))
+ d->marshaller()->append(arg);
+ return *this;
+}
+
+/*!
+ \overload
Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
A D-Bus variant type can contain any type, including other
@@ -729,6 +743,20 @@ const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
/*!
\overload
+ \since 4.8
+ \internal
+ Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR}
+ (Unix file descriptor) from the D-Bus stream.
+*/
+const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const
+{
+ if (QDBusArgumentPrivate::checkReadAndDetach(d))
+ arg = d->demarshaller()->toUnixFileDescriptor();
+ return *this;
+}
+
+/*!
+ \overload
Extracts one D-Bus primitive argument of type \c{VARIANT} from the
D-Bus stream.
diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h
index e331d8f..f80723e 100644
--- a/src/dbus/qdbusargument.h
+++ b/src/dbus/qdbusargument.h
@@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(DBus)
+class QDBusUnixFileDescriptor;
+
class QDBusArgumentPrivate;
class QDBusDemarshaller;
class QDBusMarshaller;
@@ -96,6 +98,7 @@ public:
QDBusArgument &operator<<(const QDBusVariant &arg);
QDBusArgument &operator<<(const QDBusObjectPath &arg);
QDBusArgument &operator<<(const QDBusSignature &arg);
+ QDBusArgument &operator<<(const QDBusUnixFileDescriptor &arg);
QDBusArgument &operator<<(const QStringList &arg);
QDBusArgument &operator<<(const QByteArray &arg);
@@ -127,6 +130,7 @@ public:
const QDBusArgument &operator>>(QDBusVariant &arg) const;
const QDBusArgument &operator>>(QDBusObjectPath &arg) const;
const QDBusArgument &operator>>(QDBusSignature &arg) const;
+ const QDBusArgument &operator>>(QDBusUnixFileDescriptor &arg) const;
const QDBusArgument &operator>>(QStringList &arg) const;
const QDBusArgument &operator>>(QByteArray &arg) const;
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index 89a383f..1c713a3 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -54,10 +54,16 @@
//
#include <qdbusargument.h>
+#include "qdbusunixfiledescriptor.h"
#include "qdbus_symbols_p.h"
#ifndef QT_NO_DBUS
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+#endif
+
QT_BEGIN_NAMESPACE
class QDBusMarshaller;
@@ -117,6 +123,7 @@ public:
void append(const QString &arg);
void append(const QDBusObjectPath &arg);
void append(const QDBusSignature &arg);
+ void append(const QDBusUnixFileDescriptor &arg);
void append(const QStringList &arg);
void append(const QByteArray &arg);
bool append(const QDBusVariant &arg); // this one can fail
@@ -172,6 +179,7 @@ public:
QString toString();
QDBusObjectPath toObjectPath();
QDBusSignature toSignature();
+ QDBusUnixFileDescriptor toUnixFileDescriptor();
QDBusVariant toVariant();
QStringList toStringList();
QByteArray toByteArray();
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 4883a4d..c8cf6ea 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -52,6 +52,7 @@
#include "qdbusconnection_p.h"
#include "qdbusinterface_p.h"
#include "qdbusutil_p.h"
+#include "qdbusconnectionmanager_p.h"
#include "qdbusthreaddebug_p.h"
@@ -59,27 +60,6 @@
QT_BEGIN_NAMESPACE
-class QDBusConnectionManager
-{
-public:
- QDBusConnectionManager() {}
- ~QDBusConnectionManager();
-
- QDBusConnectionPrivate *connection(const QString &name) const;
- void removeConnection(const QString &name);
- void setConnection(const QString &name, QDBusConnectionPrivate *c);
-
- QDBusConnectionPrivate *sender() const;
- void setSender(const QDBusConnectionPrivate *s);
-
- mutable QMutex mutex;
-private:
- QHash<QString, QDBusConnectionPrivate *> connectionHash;
-
- mutable QMutex senderMutex;
- QString senderName; // internal; will probably change
-};
-
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
QDBusConnectionPrivate *QDBusConnectionManager::sender() const
@@ -126,6 +106,11 @@ QDBusConnectionManager::~QDBusConnectionManager()
connectionHash.clear();
}
+QDBusConnectionManager* QDBusConnectionManager::instance()
+{
+ return _q_manager();
+}
+
Q_DBUS_EXPORT void qDBusBindToApplication();
void qDBusBindToApplication()
{
@@ -371,7 +356,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
}
/*!
- Opens a peer-to-peer connection on address \a address and associate with it the
+ Opens a connection to a private bus on address \a address and associate with it the
connection name \a name. Returns a QDBusConnection object associated with that connection.
*/
QDBusConnection QDBusConnection::connectToBus(const QString &address,
@@ -379,7 +364,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
{
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
// "Cannot create connection without a Q[Core]Application instance");
- if (!qdbus_loadLibDBus()){
+ if (!qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0;
return QDBusConnection(d);
}
@@ -411,9 +396,43 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
return retval;
}
+/*!
+ \since 4.8
+
+ Opens a peer-to-peer connection on address \a address and associate with it the
+ connection name \a name. Returns a QDBusConnection object associated with that connection.
+*/
+QDBusConnection QDBusConnection::connectToPeer(const QString &address,
+ const QString &name)
+{
+// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
+// "Cannot create connection without a Q[Core]Application instance");
+ if (!qdbus_loadLibDBus()) {
+ QDBusConnectionPrivate *d = 0;
+ return QDBusConnection(d);
+ }
+
+ QMutexLocker locker(&_q_manager()->mutex);
+
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d || name.isEmpty())
+ return QDBusConnection(d);
+
+ d = new QDBusConnectionPrivate;
+ // setPeer does the error handling for us
+ QDBusErrorInternal error;
+ DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
+
+ d->setPeer(c, error);
+ _q_manager()->setConnection(name, d);
+
+ QDBusConnection retval(d);
+
+ return retval;
+}
/*!
- Closes the connection of name \a name.
+ Closes the bus connection of name \a name.
Note that if there are still QDBusConnection objects associated
with the same connection, the connection will not be closed until
@@ -424,6 +443,30 @@ void QDBusConnection::disconnectFromBus(const QString &name)
{
if (_q_manager()) {
QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::ClientMode)
+ return;
+ _q_manager()->removeConnection(name);
+ }
+}
+
+/*!
+ \since 4.8
+
+ Closes the peer connection of name \a name.
+
+ Note that if there are still QDBusConnection objects associated
+ with the same connection, the connection will not be closed until
+ all references are dropped. However, no further references can be
+ created using the QDBusConnection constructor.
+*/
+void QDBusConnection::disconnectFromPeer(const QString &name)
+{
+ if (_q_manager()) {
+ QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::PeerMode)
+ return;
_q_manager()->removeConnection(name);
}
}
@@ -814,7 +857,7 @@ void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
// find the object
while (node) {
- if (pathComponents.count() == i) {
+ if (pathComponents.count() == i || !path.compare(QLatin1String("/"))) {
// found it
node->obj = 0;
node->flags = 0;
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index 6ab0ea2..15e08a7 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -172,7 +172,9 @@ public:
static QDBusConnection connectToBus(BusType type, const QString &name);
static QDBusConnection connectToBus(const QString &address, const QString &name);
+ static QDBusConnection connectToPeer(const QString &address, const QString &name);
static void disconnectFromBus(const QString &name);
+ static void disconnectFromPeer(const QString &name);
static QDBusConnection sessionBus();
static QDBusConnection systemBus();
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 36f7c53..355a6e6 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -216,7 +216,7 @@ public:
inline void serverConnection(const QDBusConnection &connection)
{ emit newServerConnection(connection); }
-
+
private:
void checkThread();
bool handleError(const QDBusErrorInternal &error);
diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h
new file mode 100644
index 0000000..dd8b4aa
--- /dev/null
+++ b/src/dbus/qdbusconnectionmanager_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDBus 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the public API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+//
+
+#ifndef QDBUSCONNECTIONMANAGER_P_H
+#define QDBUSCONNECTIONMANAGER_P_H
+
+#include "qdbusconnection_p.h"
+
+#ifndef QT_NO_DBUS
+
+QT_BEGIN_NAMESPACE
+
+class QDBusConnectionManager
+{
+public:
+ QDBusConnectionManager() {}
+ ~QDBusConnectionManager();
+ static QDBusConnectionManager* instance();
+
+ QDBusConnectionPrivate *connection(const QString &name) const;
+ void removeConnection(const QString &name);
+ void setConnection(const QString &name, QDBusConnectionPrivate *c);
+
+ QDBusConnectionPrivate *sender() const;
+ void setSender(const QDBusConnectionPrivate *s);
+
+ mutable QMutex mutex;
+private:
+ QHash<QString, QDBusConnectionPrivate *> connectionHash;
+
+ mutable QMutex senderMutex;
+ QString senderName; // internal; will probably change
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DBUS
+#endif
diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp
index 111122e..3910381 100644
--- a/src/dbus/qdbusdemarshaller.cpp
+++ b/src/dbus/qdbusdemarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -126,6 +127,13 @@ inline QDBusSignature QDBusDemarshaller::toSignature()
return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator)));
}
+inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor()
+{
+ QDBusUnixFileDescriptor fd;
+ fd.giveFileDescriptor(qIterGet<dbus_int32_t>(&iterator));
+ return fd;
+}
+
inline QDBusVariant QDBusDemarshaller::toVariant()
{
QDBusDemarshaller sub(capabilities);
@@ -173,6 +181,10 @@ QDBusArgument::ElementType QDBusDemarshaller::currentType()
case DBUS_TYPE_DICT_ENTRY:
return QDBusArgument::MapEntryType;
+ case DBUS_TYPE_UNIX_FD:
+ return capabilities & QDBusConnection::UnixFileDescriptorPassing ?
+ QDBusArgument::BasicType : QDBusArgument::UnknownType;
+
case DBUS_TYPE_INVALID:
return QDBusArgument::UnknownType;
@@ -231,6 +243,11 @@ QVariant QDBusDemarshaller::toVariantInternal()
case DBUS_TYPE_STRUCT:
return QVariant::fromValue(duplicate());
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing)
+ return qVariantFromValue(toUnixFileDescriptor());
+ // fall through
+
default:
// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
// q_dbus_message_iter_get_arg_type(&iterator),
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 5f4dadd..b2095c7 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -377,28 +377,23 @@ static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchSt
static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data)
{
- // ### We may want to separate the server from the QDBusConnectionPrivate
+ // ### We may want to separate the server from the QDBusConnectionPrivate
Q_ASSERT(server); Q_UNUSED(server);
Q_ASSERT(connection);
Q_ASSERT(data);
// keep the connection alive
q_dbus_connection_ref(connection);
- QDBusConnectionPrivate *d = new QDBusConnectionPrivate;
-
- // setConnection does the error handling for us
+ QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+
+ // setPeer does the error handling for us
QDBusErrorInternal error;
d->setPeer(connection, error);
QDBusConnection retval = QDBusConnectionPrivate::q(d);
- d->setBusService(retval);
-
- //d->name = QString::number(reinterpret_cast<int>(d));
- //d->setConnection(d->name, d);
// make QDBusServer emit the newConnection signal
- QDBusConnectionPrivate *server_d = static_cast<QDBusConnectionPrivate *>(data);
- server_d->serverConnection(retval);
+ d->serverConnection(retval);
}
} // extern "C"
@@ -435,6 +430,11 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
const QString &fullpath, int &usedLength,
QDBusConnectionPrivate::ObjectTreeNode &result)
{
+ if (!fullpath.compare(QLatin1String("/")) && root->obj) {
+ usedLength = 1;
+ result = *root;
+ return root;
+ }
int start = 0;
int length = fullpath.length();
if (fullpath.at(0) == QLatin1Char('/'))
@@ -1036,11 +1036,10 @@ void QDBusConnectionPrivate::closeConnection()
mode = InvalidMode; // prevent reentrancy
baseService.clear();
- if (oldMode == ServerMode) {
- if (server) {
- q_dbus_server_disconnect(server);
- }
- } else if (oldMode == ClientMode || oldMode == PeerMode) {
+ if (server)
+ q_dbus_server_disconnect(server);
+
+ if (oldMode == ClientMode || oldMode == PeerMode) {
if (connection) {
q_dbus_connection_close(connection);
// send the "close" message
@@ -1629,7 +1628,7 @@ void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &
this, 0);
//qDebug() << "time_functions_set" << time_functions_set;
Q_UNUSED(time_functions_set);
-
+
q_dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);
dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot, this, 0);
@@ -1646,7 +1645,7 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
connection = c;
mode = PeerMode;
-
+
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection,
qDBusAddWatch,
@@ -1666,6 +1665,31 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
}
+static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnection *connection)
+{
+ QDBusConnection::ConnectionCapabilities result = 0;
+
+#if defined(QT_LINKED_LIBDBUS) && DBUS_VERSION < 0x010400
+ // no capabilities are possible
+#else
+# if !defined(QT_LINKED_LIBDBUS)
+ // run-time check if the next functions are available
+ int major, minor, micro;
+ q_dbus_get_version(&major, &minor, &micro);
+ if (major == 1 && minor < 4)
+ return result;
+# endif
+
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+#endif
+ if (q_dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
+ result |= QDBusConnection::UnixFileDescriptorPassing;
+#endif
+
+ return result;
+}
+
void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusErrorInternal &error)
{
if (!dbc) {
@@ -1679,6 +1703,7 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
const char *service = q_dbus_bus_get_unique_name(connection);
Q_ASSERT(service);
baseService = QString::fromUtf8(service);
+ capabilities = connectionCapabilies(connection);
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
@@ -2072,21 +2097,23 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook
matchRefCounts.insert(hook.matchRule, 1);
if (connection) {
- qDBusDebug("Adding rule: %s", hook.matchRule.constData());
- q_dbus_bus_add_match(connection, hook.matchRule, NULL);
-
- // Successfully connected the signal
- // Do we need to watch for this name?
- if (shouldWatchService(hook.service)) {
- WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
- if (++data.refcount == 1) {
- // we need to watch for this service changing
- connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
- data.owner = getNameOwnerNoCache(hook.service);
- qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
- << data.owner << ")";
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Adding rule: %s", hook.matchRule.constData());
+ q_dbus_bus_add_match(connection, hook.matchRule, NULL);
+
+ // Successfully connected the signal
+ // Do we need to watch for this name?
+ if (shouldWatchService(hook.service)) {
+ WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
+ if (++data.refcount == 1) {
+ // we need to watch for this service changing
+ connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
+ data.owner = getNameOwnerNoCache(hook.service);
+ qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
+ << data.owner << ")";
+ }
}
}
}
@@ -2150,18 +2177,20 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
// we don't care about errors here
if (connection && erase) {
- qDBusDebug("Removing rule: %s", hook.matchRule.constData());
- q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
-
- // Successfully disconnected the signal
- // Were we watching for this name?
- WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
- if (sit != watchedServices.end()) {
- if (--sit.value().refcount == 0) {
- watchedServices.erase(sit);
- disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Removing rule: %s", hook.matchRule.constData());
+ q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
+
+ // Successfully disconnected the signal
+ // Were we watching for this name?
+ WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
+ if (sit != watchedServices.end()) {
+ if (--sit.value().refcount == 0) {
+ watchedServices.erase(sit);
+ disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ }
}
}
@@ -2364,7 +2393,7 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName)
bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const
{
- if (serviceName == baseService)
+ if (!serviceName.isEmpty() && serviceName == baseService)
return true;
QStringList copy = serviceNames;
return copy.contains(serviceName);
diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp
index 76d76cc..6dec359 100644
--- a/src/dbus/qdbusmarshaller.cpp
+++ b/src/dbus/qdbusmarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include "qdbusmetatype_p.h"
#include "qdbusutil_p.h"
@@ -138,6 +139,16 @@ inline void QDBusMarshaller::append(const QDBusSignature &arg)
qIterAppend(&iterator, ba, DBUS_TYPE_SIGNATURE, &cdata);
}
+inline void QDBusMarshaller::append(const QDBusUnixFileDescriptor &arg)
+{
+ int fd = arg.fileDescriptor();
+ if (!ba && fd == -1) {
+ error(QLatin1String("Invalid file descriptor passed in arguments"));
+ } else {
+ qIterAppend(&iterator, ba, DBUS_TYPE_UNIX_FD, &fd);
+ }
+}
+
inline void QDBusMarshaller::append(const QByteArray &arg)
{
if (ba) {
@@ -243,7 +254,7 @@ inline QDBusMarshaller *QDBusMarshaller::beginMap(int kid, int vid)
.arg(QLatin1String(QVariant::typeToName(QVariant::Type(kid)))));
return this;
}
- if (ksignature[1] != 0 || !q_dbus_type_is_basic(*ksignature)) {
+ if (ksignature[1] != 0 || !QDBusUtil::isValidBasicType(*ksignature)) {
qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-BUS map.",
QVariant::typeToName( QVariant::Type(kid) ), kid);
error(QString::fromLatin1("Type %1 passed in arguments cannot be used as a key in a map")
@@ -474,6 +485,13 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg)
qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!");
return false;
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing || ba) {
+ append(qvariant_cast<QDBusUnixFileDescriptor>(arg));
+ return true;
+ }
+ // fall through
+
default:
qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-BUS type '%s'",
signature);
@@ -493,7 +511,7 @@ bool QDBusMarshaller::appendRegisteredType(const QVariant &arg)
bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
{
int code = q_dbus_message_iter_get_arg_type(&demarshaller->iterator);
- if (q_dbus_type_is_basic(code)) {
+ if (QDBusUtil::isValidBasicType(code)) {
// easy: just append
// do exactly like the D-BUS docs suggest
// (see apidocs for q_dbus_message_iter_get_basic)
@@ -507,7 +525,7 @@ bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
if (code == DBUS_TYPE_ARRAY) {
int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator);
- if (q_dbus_type_is_fixed(element)) {
+ if (QDBusUtil::isValidFixedType(element) && element != DBUS_TYPE_UNIX_FD) {
// another optimization: fixed size arrays
// code is exactly like QDBusDemarshaller::toByteArray
DBusMessageIter sub;
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index 9f29205..9d9112c 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -50,12 +50,18 @@
#include <qvector.h>
#include "qdbusmessage.h"
+#include "qdbusunixfiledescriptor.h"
#include "qdbusutil_p.h"
#include "qdbusmetatype_p.h"
#include "qdbusargument_p.h"
#ifndef QT_NO_DBUS
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+#endif
+
Q_DECLARE_METATYPE(QList<bool>)
Q_DECLARE_METATYPE(QList<short>)
Q_DECLARE_METATYPE(QList<ushort>)
@@ -96,6 +102,7 @@ int QDBusMetaTypeId::variant;
int QDBusMetaTypeId::objectpath;
int QDBusMetaTypeId::signature;
int QDBusMetaTypeId::error;
+int QDBusMetaTypeId::unixfd;
void QDBusMetaTypeId::init()
{
@@ -110,7 +117,8 @@ void QDBusMetaTypeId::init()
variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
- error = qRegisterMetaType<QDBusError>("QDBusError");
+ error = qRegisterMetaType<QDBusError>("QDBusError");
+ unixfd = qRegisterMetaType<QDBusUnixFileDescriptor>("QDBusUnixFileDescriptor");
#ifndef QDBUS_NO_SPECIALTYPES
// and register QtCore's with us
@@ -139,6 +147,7 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QList<double> >();
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
qDBusRegisterMetaType<QList<QDBusSignature> >();
+ qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
#endif
initialized = true;
@@ -343,6 +352,9 @@ int QDBusMetaType::signatureToType(const char *signature)
case DBUS_TYPE_SIGNATURE:
return QDBusMetaTypeId::signature;
+ case DBUS_TYPE_UNIX_FD:
+ return QDBusMetaTypeId::unixfd;
+
case DBUS_TYPE_VARIANT:
return QDBusMetaTypeId::variant;
@@ -432,6 +444,8 @@ const char *QDBusMetaType::typeToSignature(int type)
return DBUS_TYPE_OBJECT_PATH_AS_STRING;
else if (type == QDBusMetaTypeId::signature)
return DBUS_TYPE_SIGNATURE_AS_STRING;
+ else if (type == QDBusMetaTypeId::unixfd)
+ return DBUS_TYPE_UNIX_FD_AS_STRING;
// try the database
QVector<QDBusCustomTypeInfo> *ct = customTypes();
diff --git a/src/dbus/qdbusmetatype_p.h b/src/dbus/qdbusmetatype_p.h
index 2fce133..b931c75 100644
--- a/src/dbus/qdbusmetatype_p.h
+++ b/src/dbus/qdbusmetatype_p.h
@@ -65,6 +65,7 @@ struct QDBusMetaTypeId
static int objectpath; // QDBusObjectPath
static int signature; // QDBusSignature
static int error; // QDBusError
+ static int unixfd; // QDBusUnixFileDescriptor
static void init();
};
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index 9b61555..abc5cb3 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -41,6 +41,7 @@
#include "qdbusserver.h"
#include "qdbusconnection_p.h"
+#include "qdbusconnectionmanager_p.h"
#ifndef QT_NO_DBUS
@@ -62,24 +63,37 @@ QT_BEGIN_NAMESPACE
QDBusServer::QDBusServer(const QString &address, QObject *parent)
: QObject(parent)
{
+ if (address.isEmpty())
+ return;
+
if (!qdbus_loadLibDBus()) {
d = 0;
return;
}
d = new QDBusConnectionPrivate(this);
- if (address.isEmpty())
- return;
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->setConnection(QLatin1String("QDBusServer-") + QString::number(reinterpret_cast<qulonglong>(d)), d);
QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)),
this, SIGNAL(newConnection(QDBusConnection)));
- // server = q_dbus_server_listen( "unix:tmpdir=/tmp", &error);
QDBusErrorInternal error;
d->setServer(q_dbus_server_listen(address.toUtf8().constData(), error), error);
}
/*!
+ Destructs a QDBusServer
+*/
+QDBusServer::~QDBusServer()
+{
+ if (QDBusConnectionManager::instance()) {
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->removeConnection(d->name);
+ }
+}
+
+/*!
Returns true if this QDBusServer object is connected.
If it isn't connected, you need to call the constructor again.
@@ -113,11 +127,12 @@ QString QDBusServer::address() const
return addr;
}
+
/*!
\fn void QDBusServer::newConnection(const QDBusConnection &connection)
- This signal is currently not used, but if and when it is
- used, \a connection will be the new connection.
+ This signal is emitted when a new client connection \a connection is
+ established to the server.
*/
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h
index f101011..fcb78bd 100644
--- a/src/dbus/qdbusserver.h
+++ b/src/dbus/qdbusserver.h
@@ -61,7 +61,8 @@ class Q_DBUS_EXPORT QDBusServer: public QObject
{
Q_OBJECT
public:
- QDBusServer(const QString &address, QObject *parent = 0);
+ QDBusServer(const QString &address = "unix:tmpdir=/tmp", QObject *parent = 0);
+ virtual ~QDBusServer();
bool isConnected() const;
QDBusError lastError() const;
diff --git a/src/dbus/qdbusunixfiledescriptor.cpp b/src/dbus/qdbusunixfiledescriptor.cpp
new file mode 100644
index 0000000..f45b6cc
--- /dev/null
+++ b/src/dbus/qdbusunixfiledescriptor.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the FOO 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 "qdbusunixfiledescriptor.h"
+#include <QSharedData>
+
+#ifdef Q_OS_UNIX
+# include <private/qcore_unix_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDBusUnixFileDescriptor
+ \inmodule QtDBus
+ \since 4.8
+
+ \brief The QDBusUnixFileDescriptor class holds one Unix file descriptor.
+
+ The QDBusUnixFileDescriptor class is used to hold one Unix file
+ descriptor for use with the QtDBus module. This allows applications to
+ send and receive Unix file descriptors over the D-Bus connection, mapping
+ automatically to the D-Bus type 'h'.
+
+ Objects of type QDBusUnixFileDescriptors can be used also as parameters
+ in signals and slots that get exported to D-Bus by registering with
+ QDBusConnection::registerObject.
+
+ QDBusUnixFileDescriptor does not take ownership of the file descriptor.
+ Instead, it will use the Unix system call \c dup(2) to make a copy of the
+ file descriptor. This file descriptor belongs to the
+ QDBusUnixFileDescriptor object and should not be stored or closed by the
+ user. Instead, you should make your own copy if you need that.
+
+ \section2 Availability
+
+ Unix file descriptor passing is not available in all D-Bus connections.
+ This feature is present with D-Bus library and bus daemon version 1.4 and
+ upwards on Unix systems. QtDBus automatically enables the feature if such
+ a version was found at compile-time and run-time.
+
+ To verify that your connection does support passing file descriptors,
+ check if the QDBusConnection::UnixFileDescriptorPassing capability is set
+ with QDBusConnection::connectionCapabilities(). If the flag is not
+ active, then you will not be able to make calls to methods that have
+ QDBusUnixFileDescriptor as arguments or even embed such a type in a
+ variant. You will also not receive calls containing that type.
+
+ Note also that remote applications may not have support for Unix file
+ descriptor passing. If you make a D-Bus to a remote application that
+ cannot receive such a type, you will receive an error reply. If you try
+ to send a signal containing a D-Bus file descriptor or return one from a
+ method call, the message will be silently dropped.
+
+ Even if the feature is not available, QDBusUnixFileDescriptor will
+ continue to operate, so code need not have compile-time checks for the
+ availability of this feature.
+
+ On non-Unix systems, QDBusUnixFileDescriptor will always report an
+ invalid state and QDBusUnixFileDescriptor::isSupported() will return
+ false.
+
+ \sa QDBusConnection::ConnectionCapabilities, QDBusConnection::connectionCapabilities
+*/
+
+class QDBusUnixFileDescriptorPrivate : public QSharedData {
+public:
+ QDBusUnixFileDescriptorPrivate() : fd(-1) { }
+ QDBusUnixFileDescriptorPrivate(const QDBusUnixFileDescriptorPrivate &other)
+ : QSharedData(other), fd(-1)
+ { }
+ ~QDBusUnixFileDescriptorPrivate();
+
+ QAtomicInt fd;
+};
+
+template<> inline
+QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate>::~QExplicitlySharedDataPointer()
+{ if (d && !d->ref.deref()) delete d; }
+
+/*!
+ Constructs a QDBusUnixFileDescriptor without a wrapped file descriptor.
+ This is equivalent to constructing the object with an invalid file
+ descriptor (like -1).
+
+ \sa fileDescriptor, isValid
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor()
+ : d(0)
+{
+}
+
+/*!
+ Constructs a QDBusUnixFileDescriptor object by copying the \a
+ fileDescriptor parameter. The original file descriptor is not touched and
+ must be closed by the user.
+
+ Note that the value returned by fileDescriptor() will be different from
+ the \a fileDescriptor parameter passed.
+
+ If the \a fileDescriptor parameter is not valid, isValid() will return
+ false and fileDescriptor() will return -1.
+
+ \sa setFileDescriptor, fileDescriptor
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(int fileDescriptor)
+ : d(0)
+{
+ if (fileDescriptor != -1)
+ setFileDescriptor(fileDescriptor);
+}
+
+/*!
+ Constructs a QDBusUnixFileDescriptor object by copying \a other.
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Copies the Unix file descriptor from the \a other QDBusUnixFileDescriptor
+ object. If the current object contained a file descriptor, it will be
+ properly disposed of before.
+*/
+QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(const QDBusUnixFileDescriptor &other)
+{
+ if (this != &other)
+ d.operator=(other.d);
+ return *this;
+}
+
+/*!
+ Destroys this QDBusUnixFileDescriptor object and disposes of the Unix file descriptor that it contained.
+*/
+QDBusUnixFileDescriptor::~QDBusUnixFileDescriptor()
+{
+}
+
+/*!
+ Returns true if this Unix file descriptor is valid. A valid Unix file
+ descriptor is not -1.
+
+ \sa fileDescriptor()
+*/
+bool QDBusUnixFileDescriptor::isValid() const
+{
+ return d ? d->fd != -1 : false;
+}
+
+/*!
+ Returns the Unix file descriptor contained by this
+ QDBusUnixFileDescriptor object. An invalid file descriptor is represented
+ by the value -1.
+
+ Note that the file descriptor returned by this function is owned by the
+ QDBusUnixFileDescriptor object and must not be stored past the lifetime
+ of this object. It is ok to use it while this object is valid, but if one
+ wants to store it for longer use, the file descriptor should be cloned
+ using the Unix \c dup(2), \c dup2(2) or \c dup3(2) functions.
+
+ \sa isValid()
+*/
+int QDBusUnixFileDescriptor::fileDescriptor() const
+{
+ return d ? d->fd.operator int() : -1;
+}
+
+// actual implementation
+#ifdef Q_OS_UNIX
+
+// qdoc documentation is generated on Unix
+
+/*!
+ Returns true if Unix file descriptors are supported on this platform. In
+ other words, this function returns true if this is a Unix platform.
+
+ Note that QDBusUnixFileDescriptor continues to operate even if this
+ function returns false. The only difference is that the
+ QDBusUnixFileDescriptor objects will always be in the isValid() == false
+ state and fileDescriptor() will always return -1. The class will not
+ consume any operating system resources.
+*/
+bool QDBusUnixFileDescriptor::isSupported()
+{
+ return true;
+}
+
+/*!
+ Sets the file descriptor that this QDBusUnixFileDescriptor object holds
+ to a copy of \a fileDescriptor.T he original file descriptor is not
+ touched and must be closed by the user.
+
+ Note that the value returned by fileDescriptor() will be different from
+ the \a fileDescriptor parameter passed.
+
+ If the \a fileDescriptor parameter is not valid, isValid() will return
+ false and fileDescriptor() will return -1.
+
+ \sa isValid(), fileDescriptor()
+*/
+void QDBusUnixFileDescriptor::setFileDescriptor(int fileDescriptor)
+{
+ if (fileDescriptor != -1)
+ giveFileDescriptor(qt_safe_dup(fileDescriptor));
+}
+
+/*!
+ \internal
+ Sets the Unix file descriptor to \a fileDescriptor without copying.
+
+ \sa setFileDescriptor()
+*/
+void QDBusUnixFileDescriptor::giveFileDescriptor(int fileDescriptor)
+{
+ // if we are the sole ref, d remains unchanged
+ // if detaching happens, d->fd will be -1
+ if (d)
+ d.detach();
+ else
+ d = new QDBusUnixFileDescriptorPrivate;
+
+ if (d->fd != -1)
+ qt_safe_close(d->fd);
+
+ if (fileDescriptor != -1)
+ d->fd = fileDescriptor;
+}
+
+/*!
+ \internal
+ Extracts the Unix file descriptor from the QDBusUnixFileDescriptor object
+ and transfers ownership.
+
+ Note: since QDBusUnixFileDescriptor is implicitly shared, this function
+ is inherently racy and should be avoided.
+*/
+int QDBusUnixFileDescriptor::takeFileDescriptor()
+{
+ if (!d)
+ return -1;
+
+ return d->fd.fetchAndStoreRelaxed(-1);
+}
+
+QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
+{
+ if (fd != -1)
+ qt_safe_close(fd);
+}
+
+#else
+bool QDBusUnixFileDescriptor::isSupported()
+{
+ return false;
+}
+
+void QDBusUnixFileDescriptor::setFileDescriptor(int)
+{
+}
+
+void QDBusUnixFileDescriptor::giveFileDescriptor(int)
+{
+}
+
+int QDBusUnixFileDescriptor::takeFileDescriptor()
+{
+ return -1;
+}
+
+QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
+{
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h
new file mode 100644
index 0000000..d0a2f3c
--- /dev/null
+++ b/src/dbus/qdbusunixfiledescriptor.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QDBUSUNIXFILEDESCRIPTOR_H
+#define QDBUSUNIXFILEDESCRIPTOR_H
+
+#include <QtCore/QSharedDataPointer>
+#include <QtDBus/qdbusmacros.h>
+
+#ifndef QT_NO_DBUS
+
+#ifdef Q_COMPILER_RVALUE_REFS
+# include <utility>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(DBus)
+
+class QDBusUnixFileDescriptorPrivate;
+template<> QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate>::~QExplicitlySharedDataPointer();
+
+class Q_DBUS_EXPORT QDBusUnixFileDescriptor
+{
+public:
+ QDBusUnixFileDescriptor();
+ explicit QDBusUnixFileDescriptor(int fileDescriptor);
+ QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other);
+ QDBusUnixFileDescriptor &operator=(const QDBusUnixFileDescriptor &other);
+ ~QDBusUnixFileDescriptor();
+
+ bool isValid() const;
+
+ int fileDescriptor() const;
+ void setFileDescriptor(int fileDescriptor);
+
+ void giveFileDescriptor(int fileDescriptor);
+ int takeFileDescriptor();
+
+ static bool isSupported();
+
+#if defined(Q_COMPILER_RVALUE_REFS)
+ QDBusUnixFileDescriptor(QDBusUnixFileDescriptor &&other) : d(static_cast<Data &&>(other.d))
+ { }
+ inline QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other)
+ { d.swap(other.d); return *this; }
+#endif
+
+protected:
+ typedef QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate> Data;
+ Data d;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDBusUnixFileDescriptor)
+Q_DECLARE_METATYPE(QList<QDBusUnixFileDescriptor>)
+
+QT_END_HEADER
+
+#endif // QT_NO_DBUS
+#endif // QDBUSUNIXFILEDESCRIPTOR_H
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index 9730f54..a4bd168 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -46,6 +46,7 @@
#include <QtCore/qstringlist.h>
#include "qdbusargument.h"
+#include "qdbusunixfiledescriptor.h"
#ifndef QT_NO_DBUS
@@ -130,6 +131,10 @@ static bool variantToString(const QVariant &arg, QString &out)
} else if (argType == qMetaTypeId<QDBusSignature>()) {
out += QLatin1String("[Signature: ") + qvariant_cast<QDBusSignature>(arg).signature();
out += QLatin1Char(']');
+ } else if (argType == qMetaTypeId<QDBusUnixFileDescriptor>()) {
+ out += QLatin1String("[Unix FD: ");
+ out += QLatin1String(qvariant_cast<QDBusUnixFileDescriptor>(arg).isValid() ? "valid" : "not valid");
+ out += QLatin1Char(']');
} else if (argType == qMetaTypeId<QDBusVariant>()) {
const QVariant v = qvariant_cast<QDBusVariant>(arg).variant();
out += QLatin1String("[Variant");
@@ -233,6 +238,68 @@ bool argToString(const QDBusArgument &busArg, QString &out)
return true;
}
+//------- D-Bus Types --------
+static const char oneLetterTypes[] = "vsogybnqiuxtdh";
+static const char basicTypes[] = "sogybnqiuxtdh";
+static const char fixedTypes[] = "ybnqiuxtdh";
+
+static bool isBasicType(int c)
+{
+ return c != DBUS_TYPE_INVALID && strchr(basicTypes, c) != NULL;
+}
+
+static bool isFixedType(int c)
+{
+ return c != DBUS_TYPE_INVALID && strchr(fixedTypes, c) != NULL;
+}
+
+// Returns a pointer to one-past-end of this type if it's valid;
+// returns NULL if it isn't valid.
+static const char *validateSingleType(const char *signature)
+{
+ register char c = *signature;
+ if (c == DBUS_TYPE_INVALID)
+ return false;
+
+ // is it one of the one-letter types?
+ if (strchr(oneLetterTypes, c) != NULL)
+ return signature + 1;
+
+ // is it an array?
+ if (c == DBUS_TYPE_ARRAY) {
+ // then it's valid if the next type is valid
+ // or if it's a dict-entry
+ c = *++signature;
+ if (c == DBUS_DICT_ENTRY_BEGIN_CHAR) {
+ // beginning of a dictionary entry
+ // a dictionary entry has a key which is of basic types
+ // and a free value
+ c = *++signature;
+ if (!isBasicType(c))
+ return 0;
+ signature = validateSingleType(signature + 1);
+ return signature && *signature == DBUS_DICT_ENTRY_END_CHAR ? signature + 1 : 0;
+ }
+
+ return validateSingleType(signature);
+ }
+
+ if (c == DBUS_STRUCT_BEGIN_CHAR) {
+ // beginning of a struct
+ ++signature;
+ while (true) {
+ signature = validateSingleType(signature);
+ if (!signature)
+ return 0;
+ if (*signature == DBUS_STRUCT_END_CHAR)
+ return signature + 1;
+ }
+ }
+
+ // invalid/unknown type
+ return 0;
+}
+
/*!
\namespace QDBusUtil
\inmodule QtDBus
@@ -442,6 +509,25 @@ namespace QDBusUtil
}
/*!
+ \fn bool QDBusUtil::isValidBasicType(int type)
+ Returns true if \a c is a valid, basic D-Bus type.
+ */
+ bool isValidBasicType(int c)
+ {
+ return isBasicType(c);
+ }
+
+ /*!
+ \fn bool QDBusUtil::isValidFixedType(int type)
+ Returns true if \a c is a valid, fixed D-Bus type.
+ */
+ bool isValidFixedType(int c)
+ {
+ return isFixedType(c);
+ }
+
+
+ /*!
\fn bool QDBusUtil::isValidSignature(const QString &signature)
Returns true if \a signature is a valid D-Bus type signature for one or more types.
This function returns true if it can all of \a signature into valid, individual types and no
@@ -451,7 +537,15 @@ namespace QDBusUtil
*/
bool isValidSignature(const QString &signature)
{
- return q_dbus_signature_validate(signature.toUtf8(), 0);
+ QByteArray ba = signature.toLatin1();
+ const char *data = ba.constData();
+ while (true) {
+ data = validateSingleType(data);
+ if (!data)
+ return false;
+ if (*data == '\0')
+ return true;
+ }
}
/*!
@@ -462,7 +556,9 @@ namespace QDBusUtil
*/
bool isValidSingleSignature(const QString &signature)
{
- return q_dbus_signature_validate_single(signature.toUtf8(), 0);
+ QByteArray ba = signature.toLatin1();
+ const char *data = validateSingleType(ba.constData());
+ return data && *data == '\0';
}
} // namespace QDBusUtil
diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
index 3721e98..24b5cea 100644
--- a/src/dbus/qdbusutil_p.h
+++ b/src/dbus/qdbusutil_p.h
@@ -81,6 +81,10 @@ namespace QDBusUtil
Q_DBUS_EXPORT bool isValidObjectPath(const QString &path);
+ Q_DBUS_EXPORT bool isValidFixedType(int c);
+
+ Q_DBUS_EXPORT bool isValidBasicType(int c);
+
Q_DBUS_EXPORT bool isValidSignature(const QString &signature);
Q_DBUS_EXPORT bool isValidSingleSignature(const QString &signature);
diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp
index 62eb8fe..049e05e 100644
--- a/src/declarative/debugger/qdeclarativedebug.cpp
+++ b/src/declarative/debugger/qdeclarativedebug.cpp
@@ -84,6 +84,7 @@ public:
static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugRootContextQuery *);
static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugObjectQuery *);
static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugExpressionQuery *);
+ static void remove(QDeclarativeEngineDebug *, QDeclarativeDebugWatch *);
QHash<int, QDeclarativeDebugEnginesQuery *> enginesQuery;
QHash<int, QDeclarativeDebugRootContextQuery *> rootContextQuery;
@@ -120,6 +121,41 @@ QDeclarativeEngineDebugPrivate::~QDeclarativeEngineDebugPrivate()
{
if (client)
client->priv = 0;
+ delete client;
+
+ QHash<int, QDeclarativeDebugEnginesQuery*>::iterator enginesIter = enginesQuery.begin();
+ for (; enginesIter != enginesQuery.end(); ++enginesIter) {
+ enginesIter.value()->m_client = 0;
+ if (enginesIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ enginesIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugRootContextQuery*>::iterator rootContextIter = rootContextQuery.begin();
+ for (; rootContextIter != rootContextQuery.end(); ++rootContextIter) {
+ rootContextIter.value()->m_client = 0;
+ if (rootContextIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ rootContextIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugObjectQuery*>::iterator objectIter = objectQuery.begin();
+ for (; objectIter != objectQuery.end(); ++objectIter) {
+ objectIter.value()->m_client = 0;
+ if (objectIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ objectIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugExpressionQuery*>::iterator exprIter = expressionQuery.begin();
+ for (; exprIter != expressionQuery.end(); ++exprIter) {
+ exprIter.value()->m_client = 0;
+ if (exprIter.value()->state() == QDeclarativeDebugQuery::Waiting)
+ exprIter.value()->setState(QDeclarativeDebugQuery::Error);
+ }
+
+ QHash<int, QDeclarativeDebugWatch*>::iterator watchIter = watched.begin();
+ for (; watchIter != watched.end(); ++watchIter) {
+ watchIter.value()->m_client = 0;
+ watchIter.value()->setState(QDeclarativeDebugWatch::Dead);
+ }
}
int QDeclarativeEngineDebugPrivate::getId()
@@ -160,6 +196,14 @@ void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclara
}
}
+void QDeclarativeEngineDebugPrivate::remove(QDeclarativeEngineDebug *c, QDeclarativeDebugWatch *w)
+{
+ if (c && w) {
+ QDeclarativeEngineDebugPrivate *p = (QDeclarativeEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->watched.remove(w->m_queryId);
+ }
+}
+
void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugObjectReference &o,
bool simple)
{
@@ -647,6 +691,8 @@ QDeclarativeDebugWatch::QDeclarativeDebugWatch(QObject *parent)
QDeclarativeDebugWatch::~QDeclarativeDebugWatch()
{
+ if (m_client && m_queryId != -1)
+ QDeclarativeEngineDebugPrivate::remove(m_client, this);
}
int QDeclarativeDebugWatch::queryId() const
diff --git a/src/declarative/debugger/qdeclarativedebughelper.cpp b/src/declarative/debugger/qdeclarativedebughelper.cpp
index 0478209..93f7423 100644
--- a/src/declarative/debugger/qdeclarativedebughelper.cpp
+++ b/src/declarative/debugger/qdeclarativedebughelper.cpp
@@ -65,10 +65,12 @@ void QDeclarativeDebugHelper::setAnimationSlowDownFactor(qreal factor)
}
void QDeclarativeDebugHelper::enableDebugging() {
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
qWarning("Qml debugging is enabled. Only use this in a safe environment!");
}
QDeclarativeEnginePrivate::qml_debugging_enabled = true;
+#endif
}
QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp
index 1581675..5112af0 100644
--- a/src/declarative/debugger/qdeclarativedebugserver.cpp
+++ b/src/declarative/debugger/qdeclarativedebugserver.cpp
@@ -91,7 +91,7 @@ public:
QStringList clientPlugins;
bool gotHello;
- static QDeclarativeDebugServerConnection *loadConnectionPlugin();
+ static QDeclarativeDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
};
QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() :
@@ -113,8 +113,10 @@ void QDeclarativeDebugServerPrivate::advertisePlugins()
connection->send(message);
}
-QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin()
+QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin(
+ const QString &pluginName)
{
+#ifndef QT_NO_LIBRARY
QStringList pluginCandidates;
const QStringList paths = QCoreApplication::libraryPaths();
foreach (const QString &libPath, paths) {
@@ -122,7 +124,8 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio
if (dir.exists()) {
QStringList plugins(dir.entryList(QDir::Files));
foreach (const QString &pluginPath, plugins) {
- pluginCandidates << dir.absoluteFilePath(pluginPath);
+ if (QFileInfo(pluginPath).fileName().contains(pluginName))
+ pluginCandidates << dir.absoluteFilePath(pluginPath);
}
}
}
@@ -140,6 +143,7 @@ QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectio
return connection;
loader.unload();
}
+#endif
return 0;
}
@@ -159,14 +163,14 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
if (!commandLineTested) {
commandLineTested = true;
-#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp));
+#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
// ### remove port definition when protocol is changed
int port = 0;
bool block = false;
bool ok = false;
- // format: qmljsdebugger=port:3768[,block]
+ // format: qmljsdebugger=port:3768[,block] OR qmljsdebugger=ost[,block]
if (!appD->qmljsDebugArgumentsString().isEmpty()) {
if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
const QString message =
@@ -177,24 +181,30 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
return 0;
}
+ QString pluginName;
if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) {
int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(','));
port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok);
+ pluginName = QLatin1String("qmldbg_tcp");
+ } else if (appD->qmljsDebugArgumentsString().contains(QLatin1String("ost"))) {
+ pluginName = QLatin1String("qmldbg_ost");
+ ok = true;
}
+
block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block"));
if (ok) {
server = new QDeclarativeDebugServer();
QDeclarativeDebugServerConnection *connection
- = QDeclarativeDebugServerPrivate::loadConnectionPlugin();
+ = QDeclarativeDebugServerPrivate::loadConnectionPlugin(pluginName);
if (connection) {
server->d_func()->connection = connection;
connection->setServer(server);
connection->setPort(port, block);
} else {
- qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring\"-qmljsdebugger=%1\". "
+ qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
"Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString());
}
@@ -204,6 +214,12 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance()
appD->qmljsDebugArgumentsString()).toAscii().constData());
}
}
+#else
+ if (!appD->qmljsDebugArgumentsString().isEmpty()) {
+ qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". "
+ "QtDeclarative is not configured for debugging.").arg(
+ appD->qmljsDebugArgumentsString()).toAscii().constData());
+ }
#endif
}
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
index 566d025..3dd194b 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -45,9 +45,40 @@
#include <QGraphicsSceneMouseEvent>
#include <QPointer>
#include <QTimer>
+#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
+// The maximum number of pixels a flick can overshoot
+#ifndef QML_FLICK_OVERSHOOT
+#define QML_FLICK_OVERSHOOT 200
+#endif
+
+// The number of samples to use in calculating the velocity of a flick
+#ifndef QML_FLICK_SAMPLEBUFFER
+#define QML_FLICK_SAMPLEBUFFER 3
+#endif
+
+// The number of samples to discard when calculating the flick velocity.
+// Touch panels often produce inaccurate results as the finger is lifted.
+#ifndef QML_FLICK_DISCARDSAMPLES
+#define QML_FLICK_DISCARDSAMPLES 1
+#endif
+
+// The default maximum velocity of a flick.
+#ifndef QML_FLICK_DEFAULTMAXVELOCITY
+#define QML_FLICK_DEFAULTMAXVELOCITY 2500
+#endif
+
+// The default deceleration of a flick.
+#ifndef QML_FLICK_DEFAULTDECELERATION
+#define QML_FLICK_DEFAULTDECELERATION 1750
+#endif
+
+// How much faster to decelerate when overshooting
+#ifndef QML_FLICK_OVERSHOOTFRICTION
+#define QML_FLICK_OVERSHOOTFRICTION 8
+#endif
// FlickThreshold determines how far the "mouse" must have moved
// before we perform a flick.
@@ -141,8 +172,9 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate()
, hMoved(false), vMoved(false)
, movingHorizontally(false), movingVertically(false)
, stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
- , deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100)
- , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600)
+ , deceleration(QML_FLICK_DEFAULTDECELERATION)
+ , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100)
+ , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400)
, fixupMode(Normal), vTime(0), visibleArea(0)
, flickableDirection(QDeclarativeFlickable::AutoFlickDirection)
, boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds)
@@ -176,19 +208,39 @@ void QDeclarativeFlickablePrivate::init()
}
/*
- Returns the amount to overshoot by given a velocity.
- Will be roughly in range 0 - size/4
+ Returns the amount to overshoot by given a view size.
+ Will be up to the lesser of 1/3 of the view size or QML_FLICK_OVERSHOOT
*/
-qreal QDeclarativeFlickablePrivate::overShootDistance(qreal velocity, qreal size)
+qreal QDeclarativeFlickablePrivate::overShootDistance(qreal size)
{
if (maxVelocity <= 0)
return 0.0;
- velocity = qAbs(velocity);
- if (velocity > maxVelocity)
- velocity = maxVelocity;
- qreal dist = size / 4 * velocity / maxVelocity;
- return dist;
+ return qMin(qreal(QML_FLICK_OVERSHOOT), size/3);
+}
+
+void QDeclarativeFlickablePrivate::AxisData::addVelocitySample(qreal v, qreal maxVelocity)
+{
+ if (v > maxVelocity)
+ v = maxVelocity;
+ else if (v < -maxVelocity)
+ v = -maxVelocity;
+ velocityBuffer.append(v);
+ if (velocityBuffer.count() > QML_FLICK_SAMPLEBUFFER)
+ velocityBuffer.remove(0);
+}
+
+void QDeclarativeFlickablePrivate::AxisData::updateVelocity()
+{
+ if (velocityBuffer.count() > QML_FLICK_DISCARDSAMPLES) {
+ velocity = 0;
+ int count = velocityBuffer.count()-QML_FLICK_DISCARDSAMPLES;
+ for (int i = 0; i < count; ++i) {
+ qreal v = velocityBuffer.at(i);
+ velocity += v;
+ }
+ velocity /= count;
+ }
}
void QDeclarativeFlickablePrivate::itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeom, const QRectF &oldGeom)
@@ -214,21 +266,18 @@ void QDeclarativeFlickablePrivate::flickY(qreal velocity)
flick(vData, q->minYExtent(), q->maxYExtent(), q->height(), fixupY_callback, velocity);
}
-void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal,
QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
{
Q_Q(QDeclarativeFlickable);
qreal maxDistance = -1;
data.fixingUp = false;
- bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds;
// -ve velocity means list is moving up
if (velocity > 0) {
- if (data.move.value() < minExtent)
- maxDistance = qAbs(minExtent - data.move.value() + (overShoot?overShootDistance(velocity,vSize):0));
+ maxDistance = qAbs(minExtent - data.move.value());
data.flickTarget = minExtent;
} else {
- if (data.move.value() > maxExtent)
- maxDistance = qAbs(maxExtent - data.move.value()) + (overShoot?overShootDistance(velocity,vSize):0);
+ maxDistance = qAbs(maxExtent - data.move.value());
data.flickTarget = maxExtent;
}
if (maxDistance > 0) {
@@ -240,7 +289,10 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal
v = maxVelocity;
}
timeline.reset(data.move);
- timeline.accel(data.move, v, deceleration, maxDistance);
+ if (boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds)
+ timeline.accel(data.move, v, deceleration);
+ else
+ timeline.accel(data.move, v, deceleration, maxDistance);
timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this));
if (!flickingHorizontally && q->xflick()) {
flickingHorizontally = true;
@@ -327,6 +379,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal
}
}
}
+ data.inOvershoot = false;
fixupMode = Normal;
vTime = timeline.time();
}
@@ -706,16 +759,13 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven
q->setKeepMouseGrab(stealMouse);
pressed = true;
timeline.clear();
- hData.velocity = 0;
- vData.velocity = 0;
- hData.dragStartOffset = 0;
- vData.dragStartOffset = 0;
+ hData.reset();
+ vData.reset();
hData.dragMinBound = q->minXExtent();
vData.dragMinBound = q->minYExtent();
hData.dragMaxBound = q->maxXExtent();
vData.dragMaxBound = q->maxYExtent();
- hData.fixingUp = false;
- vData.fixingUp = false;
+ fixupMode = Normal;
lastPos = QPoint();
QDeclarativeItemPrivate::start(lastPosTime);
pressPos = event->pos();
@@ -807,33 +857,33 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent
if (stealMouse)
q->setKeepMouseGrab(true);
- if (!lastPos.isNull()) {
- qreal elapsed = qreal(QDeclarativeItemPrivate::restart(lastPosTime)) / 1000.;
- if (elapsed <= 0)
- elapsed = 1;
- if (q->yflick()) {
- qreal diff = event->pos().y() - lastPos.y();
- // average to reduce the effect of spurious moves
- vData.velocity += diff / elapsed;
- vData.velocity /= 2;
- }
-
- if (q->xflick()) {
- qreal diff = event->pos().x() - lastPos.x();
- // average to reduce the effect of spurious moves
- hData.velocity += diff / elapsed;
- hData.velocity /= 2;
- }
+ if (rejectY) {
+ vData.velocityBuffer.clear();
+ vData.velocity = 0;
+ }
+ if (rejectX) {
+ hData.velocityBuffer.clear();
+ hData.velocity = 0;
}
-
- if (rejectY) vData.velocity = 0;
- if (rejectX) hData.velocity = 0;
if (hMoved || vMoved) {
q->movementStarting();
q->viewportMoved();
}
+ if (!lastPos.isNull()) {
+ qreal elapsed = qreal(QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.;
+ if (elapsed <= 0)
+ return;
+ QDeclarativeItemPrivate::restart(lastPosTime);
+ qreal dy = event->pos().y()-lastPos.y();
+ if (q->yflick() && !rejectY)
+ vData.addVelocitySample(dy/elapsed, maxVelocity);
+ qreal dx = event->pos().x()-lastPos.x();
+ if (q->xflick() && !rejectX)
+ hData.addVelocitySample(dx/elapsed, maxVelocity);
+ }
+
lastPos = event->pos();
}
@@ -846,25 +896,33 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv
if (!lastPosTime.isValid())
return;
- if (QDeclarativeItemPrivate::elapsed(lastPosTime) > 100) {
- // if we drag then pause before release we should not cause a flick.
+ // if we drag then pause before release we should not cause a flick.
+ if (QDeclarativeItemPrivate::elapsed(lastPosTime) < 100) {
+ vData.updateVelocity();
+ hData.updateVelocity();
+ } else {
hData.velocity = 0.0;
vData.velocity = 0.0;
}
vTime = timeline.time();
- if (qAbs(vData.velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold)
- flickY(vData.velocity);
+
+ qreal velocity = vData.velocity;
+ if (vData.atBeginning || vData.atEnd)
+ velocity /= 2;
+ if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold)
+ flickY(velocity);
else
fixupY();
- if (qAbs(hData.velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold)
- flickX(hData.velocity);
+ velocity = hData.velocity;
+ if (hData.atBeginning || hData.atEnd)
+ velocity /= 2;
+ if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold)
+ flickX(velocity);
else
fixupX();
- lastPosTime.invalidate();
-
if (!timeline.isActive())
q->movementEnding();
}
@@ -911,29 +969,41 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event)
if (!d->interactive) {
QDeclarativeItem::wheelEvent(event);
} else if (yflick() && event->orientation() == Qt::Vertical) {
- if (event->delta() > 0)
- d->vData.velocity = qMax(event->delta() - d->vData.smoothVelocity.value(), qreal(250.0));
- else
- d->vData.velocity = qMin(event->delta() - d->vData.smoothVelocity.value(), qreal(-250.0));
- d->flickingVertically = false;
- d->flickY(d->vData.velocity);
- if (d->flickingVertically) {
- d->vMoved = true;
- movementStarting();
+ bool valid = false;
+ if (event->delta() > 0 && contentY() > -minYExtent()) {
+ d->vData.velocity = qMax(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentY() < -maxYExtent()) {
+ d->vData.velocity = qMin(event->delta()*2 - d->vData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->flickingVertically = false;
+ d->flickY(d->vData.velocity);
+ if (d->flickingVertically) {
+ d->vMoved = true;
+ movementStarting();
+ }
+ event->accept();
}
- event->accept();
} else if (xflick() && event->orientation() == Qt::Horizontal) {
- if (event->delta() > 0)
- d->hData.velocity = qMax(event->delta() - d->hData.smoothVelocity.value(), qreal(250.0));
- else
- d->hData.velocity = qMin(event->delta() - d->hData.smoothVelocity.value(), qreal(-250.0));
- d->flickingHorizontally = false;
- d->flickX(d->hData.velocity);
- if (d->flickingHorizontally) {
- d->hMoved = true;
- movementStarting();
+ bool valid = false;
+ if (event->delta() > 0 && contentX() > -minXExtent()) {
+ d->hData.velocity = qMax(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(d->maxVelocity/4));
+ valid = true;
+ } else if (event->delta() < 0 && contentX() < -maxXExtent()) {
+ d->hData.velocity = qMin(event->delta()*2 - d->hData.smoothVelocity.value(), qreal(-d->maxVelocity/4));
+ valid = true;
+ }
+ if (valid) {
+ d->flickingHorizontally = false;
+ d->flickX(d->hData.velocity);
+ if (d->flickingHorizontally) {
+ d->hMoved = true;
+ movementStarting();
+ }
+ event->accept();
}
- event->accept();
} else {
QDeclarativeItem::wheelEvent(event);
}
@@ -1071,6 +1141,27 @@ void QDeclarativeFlickable::viewportMoved()
}
}
+ if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically
+ && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent())
+ && qAbs(d->vData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->vData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(height());
+ d->timeline.reset(d->vData.move);
+ d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarativeTimeLineCallback(&d->vData.move, d->fixupY_callback, d));
+ }
+ if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally
+ && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent())
+ && qAbs(d->hData.smoothVelocity.value()) > 100) {
+ // Increase deceleration if we've passed a bound
+ d->hData.inOvershoot = true;
+ qreal maxDistance = d->overShootDistance(width());
+ d->timeline.reset(d->hData.move);
+ d->timeline.accel(d->hData.move, -d->hData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance);
+ d->timeline.callback(QDeclarativeTimeLineCallback(&d->hData.move, d->fixupX_callback, d));
+ }
+
d->lastFlickablePosition = QPointF(d->hData.move.value(), d->vData.move.value());
d->vTime = d->timeline.time();
@@ -1503,7 +1594,7 @@ bool QDeclarativeFlickable::sceneEventFilter(QGraphicsItem *i, QEvent *e)
\qmlproperty real Flickable::maximumFlickVelocity
This property holds the maximum velocity that the user can flick the view in pixels/second.
- The default is 2000 pixels/s
+ The default value is platform dependent.
*/
qreal QDeclarativeFlickable::maximumFlickVelocity() const
{
@@ -1524,7 +1615,7 @@ void QDeclarativeFlickable::setMaximumFlickVelocity(qreal v)
\qmlproperty real Flickable::flickDeceleration
This property holds the rate at which a flick will decelerate.
- The default is 500.
+ The default value is platform dependent.
*/
qreal QDeclarativeFlickable::flickDeceleration() const
{
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h
index 38a5eb3..1117abb 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h
@@ -94,9 +94,19 @@ public:
struct AxisData {
AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal))
: move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true)
- , fixingUp(false)
+ , fixingUp(false), inOvershoot(false)
{}
+ void reset() {
+ velocityBuffer.clear();
+ dragStartOffset = 0;
+ fixingUp = false;
+ inOvershoot = false;
+ }
+
+ void addVelocitySample(qreal v, qreal maxVelocity);
+ void updateVelocity();
+
QDeclarativeTimeLineValueProxy<QDeclarativeFlickablePrivate> move;
qreal viewSize;
qreal pressPos;
@@ -106,9 +116,11 @@ public:
qreal velocity;
qreal flickTarget;
QDeclarativeFlickablePrivate::Velocity smoothVelocity;
+ QPODVector<qreal,10> velocityBuffer;
bool atEnd : 1;
bool atBeginning : 1;
bool fixingUp : 1;
+ bool inOvershoot : 1;
};
void flickX(qreal velocity);
@@ -129,7 +141,7 @@ public:
void setRoundedViewportX(qreal x);
void setRoundedViewportY(qreal y);
- qreal overShootDistance(qreal velocity, qreal size);
+ qreal overShootDistance(qreal size);
void itemGeometryChanged(QDeclarativeItem *, const QRectF &, const QRectF &);
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index ce47d88..f30831d 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -584,6 +584,26 @@ void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
--i;
modelIndex = visibleItems.at(i)->index + 1;
}
+
+ if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
+ || fillTo < rowPosAt(visibleIndex) - rowSize())) {
+ // We've jumped more than a page. Estimate which items are now
+ // visible and fill from there.
+ int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex += count;
+ if (modelIndex >= model->count())
+ modelIndex = model->count() - 1;
+ else if (modelIndex < 0)
+ modelIndex = 0;
+ modelIndex = modelIndex / columns * columns;
+ visibleIndex = modelIndex;
+ colPos = colPosAt(visibleIndex);
+ rowPos = rowPosAt(visibleIndex);
+ }
+
int colNum = colPos / colSize();
FxGridItem *item = 0;
@@ -1115,6 +1135,7 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m
} else {
QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
}
+ data.inOvershoot = false;
fixupMode = Normal;
}
@@ -1196,7 +1217,7 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
accel = v2 / (2.0f * qAbs(dist));
} else {
data.flickTarget = velocity > 0 ? minExtent : maxExtent;
- overshootDist = overShoot ? overShootDistance(v, vSize) : 0;
+ overshootDist = overShoot ? overShootDistance(vSize) : 0;
}
timeline.reset(data.move);
timeline.accel(data.move, v, accel, maxDistance + overshootDist);
@@ -2229,7 +2250,7 @@ qreal QDeclarativeGridView::maxXExtent() const
qreal extent;
qreal highlightStart;
qreal highlightEnd;
- qreal lastItemPosition;
+ qreal lastItemPosition = 0;
if (d->isRightToLeftTopToBottom()){
highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp
index a62d3d2..b776532 100644
--- a/src/declarative/graphicsitems/qdeclarativeimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp
@@ -136,12 +136,10 @@ void QDeclarativeImagePrivate::setPixmap(const QPixmap &pixmap)
Q_Q(QDeclarativeImage);
pix.setPixmap(pixmap);
- q->setImplicitWidth(pix.width());
- q->setImplicitHeight(pix.height());
+ q->pixmapChange();
status = pix.isNull() ? QDeclarativeImageBase::Null : QDeclarativeImageBase::Ready;
q->update();
- q->pixmapChange();
}
/*!
@@ -390,8 +388,11 @@ void QDeclarativeImage::updatePaintedGeometry()
Q_D(QDeclarativeImage);
if (d->fillMode == PreserveAspectFit) {
- if (!d->pix.width() || !d->pix.height())
+ if (!d->pix.width() || !d->pix.height()) {
+ setImplicitWidth(0);
+ setImplicitHeight(0);
return;
+ }
qreal w = widthValid() ? width() : d->pix.width();
qreal widthScale = w / qreal(d->pix.width());
qreal h = heightValid() ? height() : d->pix.height();
@@ -405,9 +406,13 @@ void QDeclarativeImage::updatePaintedGeometry()
}
if (widthValid() && !heightValid()) {
setImplicitHeight(d->paintedHeight);
+ } else {
+ setImplicitHeight(d->pix.height());
}
if (heightValid() && !widthValid()) {
setImplicitWidth(d->paintedWidth);
+ } else {
+ setImplicitWidth(d->pix.width());
}
} else if (d->fillMode == PreserveAspectCrop) {
if (!d->pix.width() || !d->pix.height())
@@ -566,6 +571,13 @@ void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWi
void QDeclarativeImage::pixmapChange()
{
+ Q_D(QDeclarativeImage);
+ // PreserveAspectFit calculates the implicit size differently so we
+ // don't call our superclass pixmapChange(), since that would
+ // result in the implicit size being set incorrectly, then updated
+ // in updatePaintedGeometry()
+ if (d->fillMode != PreserveAspectFit)
+ QDeclarativeImageBase::pixmapChange();
updatePaintedGeometry();
}
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
index daebac4..81eac78 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
@@ -191,11 +191,9 @@ void QDeclarativeImageBase::load()
d->pix.clear(this);
d->status = Null;
d->progress = 0.0;
- setImplicitWidth(0);
- setImplicitHeight(0);
+ pixmapChange();
emit progressChanged(d->progress);
emit statusChanged(d->status);
- pixmapChange();
update();
} else {
QDeclarativePixmap::Options options;
@@ -246,8 +244,7 @@ void QDeclarativeImageBase::requestFinished()
d->progress = 1.0;
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ pixmapChange();
if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height())
emit sourceSizeChanged();
@@ -256,7 +253,7 @@ void QDeclarativeImageBase::requestFinished()
emit statusChanged(d->status);
if (d->progress != oldProgress)
emit progressChanged(d->progress);
- pixmapChange();
+
update();
}
@@ -279,6 +276,9 @@ void QDeclarativeImageBase::componentComplete()
void QDeclarativeImageBase::pixmapChange()
{
+ Q_D(QDeclarativeImageBase);
+ setImplicitWidth(d->pix.width());
+ setImplicitHeight(d->pix.height());
}
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 39bb429..3190d7e 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -744,6 +744,28 @@ void QDeclarativeListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
if (visibleItems.at(i)->index != -1)
modelIndex = visibleItems.at(i)->index + 1;
}
+
+ if (visibleItems.count() && (fillFrom > itemEnd+averageSize+spacing
+ || fillTo < visiblePos - averageSize - spacing)) {
+ // We've jumped more than a page. Estimate which items are now
+ // visible and fill from there.
+ int count = (fillFrom - itemEnd) / (averageSize + spacing);
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex += count;
+ if (modelIndex >= model->count()) {
+ count -= modelIndex - model->count() + 1;
+ modelIndex = model->count() - 1;
+ } else if (modelIndex < 0) {
+ count -= modelIndex;
+ modelIndex = 0;
+ }
+ visibleIndex = modelIndex;
+ visiblePos = itemEnd + count * (averageSize + spacing) + 1;
+ itemEnd = visiblePos-1;
+ }
+
bool changed = false;
FxListItem *item = 0;
qreal pos = itemEnd + 1;
@@ -1354,6 +1376,7 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m
} else {
QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
}
+ data.inOvershoot = false;
fixupMode = Normal;
}
@@ -1428,10 +1451,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
if (overShoot) {
if (data.flickTarget >= minExtent) {
- overshootDist = overShootDistance(v, vSize);
+ overshootDist = overShootDistance(vSize);
data.flickTarget += overshootDist;
} else if (data.flickTarget <= maxExtent) {
- overshootDist = overShootDistance(v, vSize);
+ overshootDist = overShootDistance(vSize);
data.flickTarget -= overshootDist;
}
}
@@ -1451,10 +1474,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m
} else if (overShoot) {
data.flickTarget = data.move.value() - dist;
if (data.flickTarget >= minExtent) {
- overshootDist = overShootDistance(v, vSize);
+ overshootDist = overShootDistance(vSize);
data.flickTarget += overshootDist;
} else if (data.flickTarget <= maxExtent) {
- overshootDist = overShootDistance(v, vSize);
+ overshootDist = overShootDistance(vSize);
data.flickTarget -= overshootDist;
}
}
@@ -2118,9 +2141,11 @@ void QDeclarativeListView::setOrientation(QDeclarativeListView::Orientation orie
if (d->orient == QDeclarativeListView::Vertical) {
setContentWidth(-1);
setFlickableDirection(VerticalFlick);
+ setContentX(0);
} else {
setContentHeight(-1);
setFlickableDirection(HorizontalFlick);
+ setContentY(0);
}
d->regenerate();
emit orientationChanged();
@@ -2277,11 +2302,19 @@ void QDeclarativeListView::setCacheBuffer(int b)
depending on the "size" property of the model item. The \c sectionHeading
delegate component provides the light blue bar that marks the beginning of
each section.
+
\snippet examples/declarative/modelviews/listview/sections.qml 0
\image qml-listview-sections-example.png
+ \note Adding sections to a ListView does not automatically re-order the
+ list items by the section criteria.
+ If the model is not ordered by section, then it is possible that
+ the sections created will not be unique; each boundary between
+ differing sections will result in a section header being created
+ even if that section exists elsewhere.
+
\sa {declarative/modelviews/listview}{ListView examples}
*/
QDeclarativeViewSection *QDeclarativeListView::sectionCriteria()
@@ -2581,7 +2614,7 @@ void QDeclarativeListView::viewportMoved()
d->inFlickCorrection = true;
// Near an end and it seems that the extent has changed?
// Recalculate the flick so that we don't end up in an odd position.
- if (yflick()) {
+ if (yflick() && !d->vData.inOvershoot) {
if (d->vData.velocity > 0) {
const qreal minY = minYExtent();
if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2)
@@ -2597,7 +2630,7 @@ void QDeclarativeListView::viewportMoved()
}
}
- if (xflick()) {
+ if (xflick() && !d->hData.inOvershoot) {
if (d->hData.velocity > 0) {
const qreal minX = minXExtent();
if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2)
@@ -2767,7 +2800,7 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
return;
if (d->model && d->model->count() && d->interactive) {
- if ((!d->isRightToLeft() && event->key() == Qt::Key_Left)
+ if ((d->orient == QDeclarativeListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left)
|| (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
|| (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Up)) {
if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
@@ -2778,7 +2811,7 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
event->accept();
return;
}
- } else if ((!d->isRightToLeft() && event->key() == Qt::Key_Right)
+ } else if ((d->orient == QDeclarativeListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right)
|| (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
|| (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Down)) {
if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
index f5145d0..d4e7f7b 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp
+++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
@@ -496,6 +496,9 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event)
d->pressAndHoldTimer.start(PressAndHoldDelay, this);
setKeepMouseGrab(d->stealMouse);
event->setAccepted(setPressed(true));
+
+ if(!event->isAccepted() && d->forwardToList.count())
+ d->forwardEvent(event);
}
}
@@ -573,6 +576,9 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
me.setX(d->lastPos.x());
me.setY(d->lastPos.y());
emit positionChanged(&me);
+
+ if(!event->isAccepted() && d->forwardToList.count())
+ d->forwardEvent(event);
}
@@ -594,6 +600,9 @@ void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (s && s->mouseGrabberItem() == this)
ungrabMouse();
setKeepMouseGrab(false);
+
+ if(!event->isAccepted() && d->forwardToList.count())
+ d->forwardEvent(event);
}
d->doubleClick = false;
}
@@ -959,4 +968,11 @@ QDeclarativeDrag *QDeclarativeMouseArea::drag()
*/
+QDeclarativeListProperty<QGraphicsObject> QDeclarativeMouseArea::forwardTo()
+{
+ Q_D(QDeclarativeMouseArea);
+ return d->forwardTo;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h
index 985f27e..351d4de 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h
+++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h
@@ -130,6 +130,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeMouseArea : public QDeclarativeItem
Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
Q_PROPERTY(QDeclarativeDrag *drag READ drag CONSTANT) //### add flicking to QDeclarativeDrag or add a QDeclarativeFlick ???
Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged REVISION 1)
+ Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> forwardTo READ forwardTo);
public:
QDeclarativeMouseArea(QDeclarativeItem *parent=0);
@@ -157,6 +158,8 @@ public:
bool preventStealing() const;
void setPreventStealing(bool prevent);
+ QDeclarativeListProperty<QGraphicsObject> forwardTo();
+
Q_SIGNALS:
void hoveredChanged();
void pressedChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
index 67694fb..7248c92 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h
@@ -70,6 +70,8 @@ public:
: absorb(true), hovered(false), pressed(false), longPress(false),
moved(false), stealMouse(false), doubleClick(false), preventStealing(false), drag(0)
{
+ Q_Q(QDeclarativeMouseArea);
+ forwardTo = QDeclarativeListProperty<QGraphicsObject>(q, forwardToList);
}
~QDeclarativeMouseAreaPrivate();
@@ -89,6 +91,18 @@ public:
lastModifiers = event->modifiers();
}
+ void forwardEvent(QGraphicsSceneMouseEvent* event)
+ {
+ Q_Q(QDeclarativeMouseArea);
+ for(int i=0; i < forwardToList.count(); i++){
+ event->setPos(forwardToList[i]->mapFromScene(event->scenePos()));
+ forwardToList[i]->scene()->sendEvent(forwardToList[i], event);
+ if(event->isAccepted())
+ break;
+ }
+ event->setPos(q->mapFromScene(event->scenePos()));
+ }
+
bool isPressAndHoldConnected() {
Q_Q(QDeclarativeMouseArea);
static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QDeclarativeMouseEvent*)");
@@ -121,6 +135,9 @@ public:
Qt::MouseButtons lastButtons;
Qt::KeyboardModifiers lastModifiers;
QBasicTimer pressAndHoldTimer;
+
+ QDeclarativeListProperty<QGraphicsObject> forwardTo;
+ QList<QGraphicsObject*> forwardToList;
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp
index 778b8b9..aed849b 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp
@@ -1525,6 +1525,8 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count)
} else {
d->regenerate();
d->updateCurrent();
+ if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange)
+ d->snapToCurrent();
}
if (changedOffset)
emit offsetChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp
index 3ab6417..a38152d 100644
--- a/src/declarative/graphicsitems/qdeclarativetext.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetext.cpp
@@ -92,7 +92,8 @@ QDeclarativeTextPrivate::QDeclarativeTextPrivate()
format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1),
lineHeightMode(QDeclarativeText::ProportionalHeight), lineCount(1), truncated(false), maximumLineCount(INT_MAX),
maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false),
- cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true), rightToLeftText(false), naturalWidth(0), doc(0)
+ cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), hAlignImplicit(true),
+ rightToLeftText(false), layoutTextElided(false), naturalWidth(0), doc(0)
{
cacheAllTextAsImage = enableImageCache();
QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton;
@@ -199,6 +200,7 @@ void QDeclarativeTextPrivate::updateLayout()
return;
}
+ layoutTextElided = false;
// Setup instance of QTextLayout for all cases other than richtext
if (!richText) {
layout.clearLayout();
@@ -209,10 +211,13 @@ void QDeclarativeTextPrivate::updateLayout()
singleline = !tmp.contains(QChar::LineSeparator);
if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) {
QFontMetrics fm(font);
- tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...?
- if (tmp != text && !truncated) {
- truncated = true;
- emit q->truncatedChanged();
+ tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width());
+ if (tmp != text) {
+ layoutTextElided = true;
+ if (!truncated) {
+ truncated = true;
+ emit q->truncatedChanged();
+ }
}
}
layout.setText(tmp);
@@ -354,6 +359,12 @@ QRect QDeclarativeTextPrivate::setupTextLayout()
if (requireImplicitWidth && q->widthValid()) {
// requires an extra layout
+ QString elidedText;
+ if (layoutTextElided) {
+ // We have provided elided text to the layout, but we must calculate unelided width.
+ elidedText = layout.text();
+ layout.setText(text);
+ }
layout.beginLayout();
forever {
QTextLine line = layout.createLine();
@@ -367,6 +378,8 @@ QRect QDeclarativeTextPrivate::setupTextLayout()
br = br.united(line.naturalTextRect());
}
naturalWidth = br.width();
+ if (layoutTextElided)
+ layout.setText(elidedText);
}
if (maximumLineCountValid) {
diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
index e3ab62a..6a3d581 100644
--- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h
@@ -116,6 +116,7 @@ public:
bool requireImplicitWidth:1;
bool hAlignImplicit:1;
bool rightToLeftText:1;
+ bool layoutTextElided:1;
QRect layedOutTextRect;
QSize paintedSize;
diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
index 2cb1c94..ca78593 100644
--- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
@@ -273,7 +273,6 @@ void QDeclarativeTextEdit::setText(const QString &text)
\o TextEdit.AutoText
\o TextEdit.PlainText
\o TextEdit.RichText
- \o TextEdit.StyledText
\endlist
The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
@@ -582,6 +581,7 @@ void QDeclarativeTextEdit::setVAlign(QDeclarativeTextEdit::VAlignment alignment)
d->vAlign = alignment;
d->updateDefaultTextOption();
updateSize();
+ moveCursorDelegate();
emit verticalAlignmentChanged(d->vAlign);
}
@@ -870,8 +870,6 @@ void QDeclarativeTextEdit::setCursorDelegate(QDeclarativeComponent* c)
Q_D(QDeclarativeTextEdit);
if(d->cursorComponent){
if(d->cursor){
- disconnect(d->control, SIGNAL(cursorPositionChanged()),
- this, SLOT(moveCursorDelegate()));
d->control->setCursorWidth(-1);
dirtyCache(cursorRectangle());
delete d->cursor;
@@ -897,8 +895,6 @@ void QDeclarativeTextEdit::loadCursorDelegate()
return;
d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this)));
if(d->cursor){
- connect(d->control, SIGNAL(cursorPositionChanged()),
- this, SLOT(moveCursorDelegate()));
d->control->setCursorWidth(0);
dirtyCache(cursorRectangle());
QDeclarative_setParent_noEvent(d->cursor, this);
@@ -1173,7 +1169,7 @@ Qt::TextInteractionFlags QDeclarativeTextEdit::textInteractionFlags() const
QRect QDeclarativeTextEdit::cursorRectangle() const
{
Q_D(const QDeclarativeTextEdit);
- return d->control->cursorRect().toRect().translated(0,-d->yoff);
+ return d->control->cursorRect().toRect().translated(0,d->yoff);
}
@@ -1558,7 +1554,7 @@ void QDeclarativeTextEditPrivate::init()
QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
- QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged()));
+ QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
#ifndef QT_NO_CLIPBOARD
QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
@@ -1583,16 +1579,17 @@ void QDeclarativeTextEdit::q_textChanged()
d->updateDefaultTextOption();
updateSize();
updateTotalLines();
- updateMicroFocus();
emit textChanged(d->text);
}
void QDeclarativeTextEdit::moveCursorDelegate()
{
Q_D(QDeclarativeTextEdit);
+ updateMicroFocus();
+ emit cursorRectangleChanged();
if(!d->cursor)
return;
- QRectF cursorRect = d->control->cursorRect();
+ QRectF cursorRect = cursorRectangle();
d->cursor->setX(cursorRect.x());
d->cursor->setY(cursorRect.y());
}
@@ -1625,7 +1622,6 @@ void QDeclarativeTextEdit::updateSelectionMarkers()
d->lastSelectionEnd = d->control->textCursor().selectionEnd();
emit selectionEndChanged();
}
- updateMicroFocus();
}
QRectF QDeclarativeTextEdit::boundingRect() const
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
index e1c2107..4500a87 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
@@ -862,6 +862,20 @@ bool QDeclarativeTextInput::hasAcceptableInput() const
state.
*/
+void QDeclarativeTextInputPrivate::updateInputMethodHints()
+{
+ Q_Q(QDeclarativeTextInput);
+ Qt::InputMethodHints hints = inputMethodHints;
+ uint echo = control->echoMode();
+ if (echo == QDeclarativeTextInput::Password || echo == QDeclarativeTextInput::NoEcho)
+ hints |= Qt::ImhHiddenText;
+ else if (echo == QDeclarativeTextInput::PasswordEchoOnEdit)
+ hints &= ~Qt::ImhHiddenText;
+ if (echo != QDeclarativeTextInput::Normal)
+ hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ q->setInputMethodHints(hints);
+}
+
/*!
\qmlproperty enumeration TextInput::echoMode
@@ -884,21 +898,27 @@ void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo)
Q_D(QDeclarativeTextInput);
if (echoMode() == echo)
return;
- Qt::InputMethodHints imHints = inputMethodHints();
- if (echo == Password || echo == NoEcho)
- imHints |= Qt::ImhHiddenText;
- else
- imHints &= ~Qt::ImhHiddenText;
- if (echo != Normal)
- imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- else
- imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
- setInputMethodHints(imHints);
d->control->setEchoMode((uint)echo);
+ d->updateInputMethodHints();
q_textChanged();
emit echoModeChanged(echoMode());
}
+Qt::InputMethodHints QDeclarativeTextInput::imHints() const
+{
+ Q_D(const QDeclarativeTextInput);
+ return d->inputMethodHints;
+}
+
+void QDeclarativeTextInput::setIMHints(Qt::InputMethodHints hints)
+{
+ Q_D(QDeclarativeTextInput);
+ if (d->inputMethodHints == hints)
+ return;
+ d->inputMethodHints = hints;
+ d->updateInputMethodHints();
+}
+
/*!
\qmlproperty Component TextInput::cursorDelegate
The delegate for the cursor in the TextInput.
@@ -929,6 +949,8 @@ void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
//note that the components are owned by something else
disconnect(d->control, SIGNAL(cursorPositionChanged(int,int)),
this, SLOT(moveCursor()));
+ disconnect(d->control, SIGNAL(updateMicroFocus()),
+ this, SLOT(moveCursor()));
delete d->cursorItem;
}else{
d->startCreatingCursor();
@@ -941,7 +963,9 @@ void QDeclarativeTextInputPrivate::startCreatingCursor()
{
Q_Q(QDeclarativeTextInput);
q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
- q, SLOT(moveCursor()));
+ q, SLOT(moveCursor()), Qt::UniqueConnection);
+ q->connect(control, SIGNAL(updateMicroFocus()),
+ q, SLOT(moveCursor()), Qt::UniqueConnection);
if(cursorComponent->isReady()){
q->createCursor();
}else if(cursorComponent->isLoading()){
@@ -1144,9 +1168,10 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
}
if (d->selectByMouse) {
setKeepMouseGrab(false);
+ d->selectPressed = true;
d->pressPos = event->pos();
}
- bool mark = event->modifiers() & Qt::ShiftModifier;
+ bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
int cursor = d->xToPos(event->pos().x());
d->control->moveCursor(cursor, mark);
event->setAccepted(true);
@@ -1157,7 +1182,7 @@ void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Q_D(QDeclarativeTextInput);
if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
return;
- if (d->selectByMouse) {
+ if (d->selectPressed) {
if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
setKeepMouseGrab(true);
moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
@@ -1176,8 +1201,10 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Q_D(QDeclarativeTextInput);
if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
return;
- if (d->selectByMouse)
+ if (d->selectPressed) {
+ d->selectPressed = false;
setKeepMouseGrab(false);
+ }
if (!d->showInputPanelOnFocus) { // input panel on click
if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
@@ -1233,8 +1260,10 @@ bool QDeclarativeTextInputPrivate::sendMouseEventToInputContext(
bool QDeclarativeTextInput::sceneEvent(QEvent *event)
{
+ Q_D(QDeclarativeTextInput);
bool rv = QDeclarativeItem::sceneEvent(event);
if (event->type() == QEvent::UngrabMouse) {
+ d->selectPressed = false;
setKeepMouseGrab(false);
}
return rv;
@@ -1847,6 +1876,7 @@ bool QDeclarativeTextInput::isInputMethodComposing() const
void QDeclarativeTextInputPrivate::init()
{
Q_Q(QDeclarativeTextInput);
+ control->setParent(q);
control->setCursorWidth(1);
control->setPasswordCharacter(QLatin1Char('*'));
q->setSmooth(smooth);
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h
index 8c873b3..ec70e43 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h
@@ -86,7 +86,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizeP
Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
#endif
Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
- Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ imHints WRITE setIMHints)
Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
@@ -215,6 +215,9 @@ public:
bool isInputMethodComposing() const;
+ Qt::InputMethodHints imHints() const;
+ void setIMHints(Qt::InputMethodHints hints);
+
Q_SIGNALS:
void textChanged();
void cursorPositionChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
index fd4da2e..7595b36 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h
@@ -70,13 +70,14 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInputPrivate : public QDeclarativeImplic
{
Q_DECLARE_PUBLIC(QDeclarativeTextInput)
public:
- QDeclarativeTextInputPrivate() : control(new QLineControl(QString())),
+ QDeclarativeTextInputPrivate() : control(new QLineControl),
color((QRgb)0), style(QDeclarativeText::Normal),
styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft),
- mouseSelectionMode(QDeclarativeTextInput::SelectCharacters),
+ mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), inputMethodHints(Qt::ImhNone),
hscroll(0), oldScroll(0), oldValidity(false), focused(false), focusOnPress(true),
showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false),
- autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true)
+ autoScroll(true), selectByMouse(false), canPaste(false), hAlignImplicit(true),
+ selectPressed(false)
{
#ifdef Q_OS_SYMBIAN
if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) {
@@ -88,7 +89,6 @@ public:
~QDeclarativeTextInputPrivate()
{
- delete control;
}
int xToPos(int x, QTextLine::CursorPosition betweenOrOn = QTextLine::CursorBetweenCharacters) const
@@ -108,6 +108,7 @@ public:
void mirrorChange();
int calculateTextWidth();
bool sendMouseEventToInputContext(QGraphicsSceneMouseEvent *event, QEvent::Type eventType);
+ void updateInputMethodHints();
QLineControl* control;
@@ -120,6 +121,7 @@ public:
QColor styleColor;
QDeclarativeTextInput::HAlignment hAlign;
QDeclarativeTextInput::SelectionMode mouseSelectionMode;
+ Qt::InputMethodHints inputMethodHints;
QPointer<QDeclarativeComponent> cursorComponent;
QPointer<QDeclarativeItem> cursorItem;
QPointF pressPos;
@@ -140,6 +142,7 @@ public:
bool selectByMouse:1;
bool canPaste:1;
bool hAlignImplicit:1;
+ bool selectPressed:1;
static inline QDeclarativeTextInputPrivate *get(QDeclarativeTextInput *t) {
return t->d_func();
diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp
index 987aa23..1e6db3f 100644
--- a/src/declarative/graphicsitems/qdeclarativetextlayout.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextlayout.cpp
@@ -296,7 +296,7 @@ void QDeclarativeTextLayout::clearLayout()
QTextLayout::clearLayout();
}
-void QDeclarativeTextLayout::prepare()
+void QDeclarativeTextLayout::prepare(QPainter *painter)
{
if (!d || !d->cached) {
@@ -305,6 +305,7 @@ void QDeclarativeTextLayout::prepare()
InertTextPainter *itp = inertTextPainter();
itp->device.begin(d);
+ itp->painter.setPen(painter->pen());
QTextLayout::draw(&itp->painter, QPointF(0, 0));
glyph_t *glyphPool = d->glyphs.data();
@@ -323,6 +324,12 @@ void QDeclarativeTextLayout::prepare()
}
}
+// Defined in qpainter.cpp
+extern Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
+ const QFixedPoint *positions, int glyphCount,
+ QFontEngine *fontEngine, const QFont &font,
+ const QTextCharFormat &charFormat);
+
void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p)
{
QPainterPrivate *priv = QPainterPrivate::get(painter);
@@ -337,7 +344,7 @@ void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p)
return;
}
- prepare();
+ prepare(painter);
int itemCount = d->items.count();
@@ -368,6 +375,10 @@ void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p)
currentColor = item.color;
}
priv->extended->drawStaticTextItem(&item);
+
+ qt_draw_decoration_for_glyphs(painter, item.glyphs, item.glyphPositions,
+ item.numGlyphs, item.fontEngine(), painter->font(),
+ QTextCharFormat());
}
if (currentColor != oldPen.color())
painter->setPen(oldPen);
diff --git a/src/declarative/graphicsitems/qdeclarativetextlayout_p.h b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h
index 2c9264e..23b22a6 100644
--- a/src/declarative/graphicsitems/qdeclarativetextlayout_p.h
+++ b/src/declarative/graphicsitems/qdeclarativetextlayout_p.h
@@ -61,7 +61,7 @@ public:
void beginLayout();
void clearLayout();
- void prepare();
+ void prepare(QPainter *);
void draw(QPainter *, const QPointF & = QPointF());
private:
diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp
index 97ce059..4c839a1 100644
--- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp
+++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp
@@ -1398,7 +1398,12 @@ void QDeclarativeVisualDataModel::_q_layoutChanged()
void QDeclarativeVisualDataModel::_q_modelReset()
{
+ Q_D(QDeclarativeVisualDataModel);
+ d->m_root = QModelIndex();
emit modelReset();
+ emit rootIndexChanged();
+ if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
+ d->m_abstractItemModel->fetchMore(d->m_root);
}
void QDeclarativeVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package)
diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp
index 28dfea9..47a15cb 100644
--- a/src/declarative/qml/qdeclarativeboundsignal.cpp
+++ b/src/declarative/qml/qdeclarativeboundsignal.cpp
@@ -225,9 +225,35 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta
QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
prop.setWritable(false);
} else {
+ QByteArray propType = type;
+ if (t >= QVariant::UserType || t == QVariant::Invalid) {
+ //copy of QDeclarativeObjectScriptClass::enumType()
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = propType.lastIndexOf("::");
+ if (scopeIdx != -1) {
+ scope = propType.left(scopeIdx);
+ name = propType.mid(scopeIdx + 2);
+ } else {
+ name = propType;
+ }
+ const QMetaObject *meta;
+ if (scope == "Qt")
+ meta = &QObject::staticQtMetaObject;
+ else
+ meta = parent->parent()->metaObject(); //### assumes parent->parent()
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
+ t = QVariant::Int;
+ propType = "int";
+ break;
+ }
+ }
+ }
if (QDeclarativeMetaType::canCopy(t)) {
types[ii] = t;
- QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ QMetaPropertyBuilder prop = mob.addProperty(name, propType);
prop.setWritable(false);
} else {
types[ii] = 0x80000000 | t;
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index c284307..8238252 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -643,11 +643,11 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
The \a properties argument is specified as a map of property-value items. For example, the code
below creates an object with initial \c x and \c y values of 100 and 200, respectively:
- \qml
+ \js
var component = Qt.createComponent("Button.qml");
if (component.status == Component.Ready)
component.createObject(parent, {"x": 100, "y": 100});
- \endqml
+ \endjs
Dynamically created instances can be deleted with the \c destroy() method.
See \l {Dynamic Object Management in QML} for more information.
@@ -880,6 +880,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon
state->bindValues = enginePriv->bindValues;
state->parserStatus = enginePriv->parserStatus;
+ state->finalizedParserStatus = enginePriv->finalizedParserStatus;
state->componentAttached = enginePriv->componentAttached;
if (state->componentAttached)
state->componentAttached->prev = &state->componentAttached;
@@ -887,6 +888,7 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon
enginePriv->componentAttached = 0;
enginePriv->bindValues.clear();
enginePriv->parserStatus.clear();
+ enginePriv->finalizedParserStatus.clear();
state->completePending = true;
enginePriv->inProgressCreations++;
}
@@ -917,6 +919,7 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi
state->bindValues = enginePriv->bindValues;
state->parserStatus = enginePriv->parserStatus;
+ state->finalizedParserStatus = enginePriv->finalizedParserStatus;
state->componentAttached = enginePriv->componentAttached;
if (state->componentAttached)
state->componentAttached->prev = &state->componentAttached;
@@ -924,6 +927,7 @@ void QDeclarativeComponentPrivate::beginDeferred(QDeclarativeEnginePrivate *engi
enginePriv->componentAttached = 0;
enginePriv->bindValues.clear();
enginePriv->parserStatus.clear();
+ enginePriv->finalizedParserStatus.clear();
state->completePending = true;
enginePriv->inProgressCreations++;
}
@@ -961,6 +965,18 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri
QDeclarativeEnginePrivate::clear(ps);
}
+ for (int ii = 0; ii < state->finalizedParserStatus.count(); ++ii) {
+ QPair<QDeclarativeGuard<QObject>, int> status = state->finalizedParserStatus.at(ii);
+ QObject *obj = status.first;
+ if (obj) {
+ void *args[] = { 0 };
+ QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod,
+ status.second, args);
+ }
+ }
+
+ //componentComplete() can register additional finalization objects
+ //that are then never handled. Handle them manually here.
if (1 == enginePriv->inProgressCreations) {
for (int ii = 0; ii < enginePriv->finalizedParserStatus.count(); ++ii) {
QPair<QDeclarativeGuard<QObject>, int> status = enginePriv->finalizedParserStatus.at(ii);
@@ -986,6 +1002,7 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri
state->bindValues.clear();
state->parserStatus.clear();
+ state->finalizedParserStatus.clear();
state->completePending = false;
enginePriv->inProgressCreations--;
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index 020c5e0..f8bec2b 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -101,6 +101,7 @@ public:
ConstructionState() : componentAttached(0), completePending(false) {}
QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> > bindValues;
QList<QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> > parserStatus;
+ QList<QPair<QDeclarativeGuard<QObject>, int> > finalizedParserStatus;
QDeclarativeComponentAttached *componentAttached;
QList<QDeclarativeError> errors;
bool completePending;
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
index bb4ece4..3abd787 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
@@ -227,6 +227,7 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindConte
if (data) {
lastData = data;
lastContext = bindContext;
+ lastScopeObject = scopeObject;
return QScriptClass::HandlesReadAccess;
}
}
@@ -268,17 +269,12 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- if (lastScopeObject) {
-
- return ep->objectClass->property(lastScopeObject, name);
-
- } else if (lastData) {
+ if (lastData) {
if (lastData->type) {
- return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->type));
+ return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->type));
} else if (lastData->typeNamespace) {
- return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject,
- lastData->typeNamespace));
+ return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->typeNamespace));
} else {
int index = lastData->importedScriptIndex;
if (index < bindContext->importedScripts.count()) {
@@ -288,6 +284,10 @@ QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
}
}
+ } else if (lastScopeObject) {
+
+ return ep->objectClass->property(lastScopeObject, name);
+
} else if (lastPropertyIndex != -1) {
QScriptValue rv;
diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp
index 31fd516..b2a05c3 100644
--- a/src/declarative/qml/qdeclarativeenginedebug.cpp
+++ b/src/declarative/qml/qdeclarativeenginedebug.cpp
@@ -249,10 +249,16 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message,
return;
}
- message << (object->metaObject()->propertyCount() + fakeProperties.count());
+ QList<int> propertyIndexes;
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
+ if (object->metaObject()->property(ii).isScriptable())
+ propertyIndexes << ii;
+ }
+
+ message << propertyIndexes.size() + fakeProperties.count();
- for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii)
- message << propertyData(object, ii);
+ for (int ii = 0; ii < propertyIndexes.size(); ++ii)
+ message << propertyData(object, propertyIndexes.at(ii));
for (int ii = 0; ii < fakeProperties.count(); ++ii)
message << fakeProperties[ii];
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
index dc3ecca..edc1755 100644
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
@@ -54,7 +54,15 @@
#include <QtCore/qvarlengtharray.h>
#include <QtScript/qscriptcontextinfo.h>
-Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QScriptValue)
+
+#if defined(__GNUC__)
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
+// The code in this file does not violate strict aliasing, but GCC thinks it does
+// so turn off the warnings for us to have a clean build
+# pragma GCC diagnostic ignored "-Wstrict-aliasing"
+# endif
+#endif
QT_BEGIN_NAMESPACE
@@ -395,6 +403,33 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
} else if (value.isFunction() && !value.isRegExp()) {
// this is handled by the binding creation above
} else {
+ //### expand optimization for other known types
+ if (lastData->propType == QMetaType::Int && value.isNumber()) {
+ int rawValue = qRound(value.toNumber());
+ int status = -1;
+ int flags = 0;
+ void *a[] = { (void *)&rawValue, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty,
+ lastData->coreIndex, a);
+ return;
+ } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
+ qreal rawValue = qreal(value.toNumber());
+ int status = -1;
+ int flags = 0;
+ void *a[] = { (void *)&rawValue, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty,
+ lastData->coreIndex, a);
+ return;
+ } else if (lastData->propType == QMetaType::QString && value.isString()) {
+ const QString &rawValue = value.toString();
+ int status = -1;
+ int flags = 0;
+ void *a[] = { (void *)&rawValue, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty,
+ lastData->coreIndex, a);
+ return;
+ }
+
QVariant v;
if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 6938892..7f487a0 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -79,7 +79,7 @@ public:
Loading, // Prior to data being received and dataReceived() being called
WaitingForDependencies, // While there are outstanding addDependency()s
Complete, // Finished
- Error, // Error
+ Error // Error
};
enum Type {
diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp
index dc941e2..a63656b 100644
--- a/src/declarative/qml/qmetaobjectbuilder.cpp
+++ b/src/declarative/qml/qmetaobjectbuilder.cpp
@@ -101,7 +101,7 @@ bool isVariantType(const char* type)
return qvariant_nameToType(type) != 0;
}
-// copied from qmetaobject.cpp
+// copied from qmetaobject_p.h
// do not touch without touching the moc as well
enum PropertyFlags {
Invalid = 0x00000000,
@@ -111,6 +111,8 @@ enum PropertyFlags {
EnumOrFlag = 0x00000008,
StdCppSet = 0x00000100,
// Override = 0x00000200,
+ Constant = 0x00000400,
+ Final = 0x00000800,
Designable = 0x00001000,
ResolveDesignable = 0x00002000,
Scriptable = 0x00004000,
@@ -618,6 +620,8 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
property.setUser(prototype.isUser());
property.setStdCppSet(prototype.hasStdCppSet());
property.setEnumOrFlag(prototype.isEnumType());
+ property.setConstant(prototype.isConstant());
+ property.setFinal(prototype.isFinal());
if (prototype.hasNotifySignal()) {
// Find an existing method for the notify signal, or add a new one.
QMetaMethod method = prototype.notifySignal();
@@ -2278,6 +2282,32 @@ bool QMetaPropertyBuilder::isEnumOrFlag() const
}
/*!
+ Returns true if the property is constant; otherwise returns false.
+ The default value is false.
+*/
+bool QMetaPropertyBuilder::isConstant() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Constant);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is final; otherwise returns false.
+ The default value is false.
+*/
+bool QMetaPropertyBuilder::isFinal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Final);
+ else
+ return false;
+}
+
+/*!
Sets this property to readable if \a value is true.
\sa isReadable(), setWritable()
@@ -2401,6 +2431,31 @@ void QMetaPropertyBuilder::setEnumOrFlag(bool value)
}
/*!
+ Sets the \c CONSTANT flag on this property to \a value.
+
+ \sa isConstant()
+*/
+void QMetaPropertyBuilder::setConstant(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Constant, value);
+}
+
+/*!
+ Sets the \c FINAL flag on this property to \a value.
+
+ \sa isFinal()
+*/
+void QMetaPropertyBuilder::setFinal(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Final, value);
+}
+
+
+/*!
\class QMetaEnumBuilder
\internal
\brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h
index d7085f8..335a825 100644
--- a/src/declarative/qml/qmetaobjectbuilder_p.h
+++ b/src/declarative/qml/qmetaobjectbuilder_p.h
@@ -258,6 +258,8 @@ public:
bool isUser() const;
bool hasStdCppSet() const;
bool isEnumOrFlag() const;
+ bool isConstant() const;
+ bool isFinal() const;
void setReadable(bool value);
void setWritable(bool value);
@@ -269,6 +271,8 @@ public:
void setUser(bool value);
void setStdCppSet(bool value);
void setEnumOrFlag(bool value);
+ void setConstant(bool value);
+ void setFinal(bool value);
private:
const QMetaObjectBuilder *_mobj;
diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp
index 41f8fe5..a1321e2 100644
--- a/src/declarative/util/qdeclarativebehavior.cpp
+++ b/src/declarative/util/qdeclarativebehavior.cpp
@@ -72,7 +72,7 @@ public:
/*!
\qmlclass Behavior QDeclarativeBehavior
- \ingroup qml-animation-transition
+ \ingroup qml-animation-transition
\since 4.7
\brief The Behavior element allows you to specify a default animation for a property change.
@@ -91,7 +91,8 @@ public:
If a \l{QML States}{state change} has a \l Transition that matches the same property as a
Behavior, the \l Transition animation overrides the Behavior for that
- state change.
+ state change. For general advice on using Behaviors to animate state changes, see
+ \l{Using QML Behaviors with States}.
\sa {QML Animation and Transitions}, {declarative/animation/behaviors}{Behavior example}, QtDeclarative
*/
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index fb77ec3..61b2d34 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -1301,9 +1301,6 @@ int NestedListModel::count() const
void NestedListModel::clear()
{
- _rolesOk = false;
- roleStrings.clear();
-
if (_root)
_root->clear();
}
diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp
index 9221d78..a29854f 100644
--- a/src/declarative/util/qdeclarativepixmapcache.cpp
+++ b/src/declarative/util/qdeclarativepixmapcache.cpp
@@ -72,9 +72,7 @@ QT_BEGIN_NAMESPACE
// The cache limit describes the maximum "junk" in the cache.
// These are the same defaults as QPixmapCache
-#if defined(Q_OS_SYMBIAN)
-static int cache_limit = 1024 * 1024; // 1048 KB cache limit for symbian
-#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240 * 1024; // 10 MB cache limit for desktop
diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index d5c7d1b..0a39ca8 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -144,6 +144,7 @@ struct XmlQueryJob
QList<void*> roleQueryErrorId; // the ptr to send back if there is an error
QStringList keyRoleQueries;
QStringList keyRoleResultsCache;
+ QString prefix;
};
class QDeclarativeXmlQuery : public QObject
@@ -172,6 +173,12 @@ public:
}
int doQuery(QString query, QString namespaces, QByteArray data, QList<QDeclarativeXmlListModelRole *>* roleObjects, QStringList keyRoleResultsCache) {
+ {
+ QMutexLocker m1(&m_mutex);
+ m_queryIds.ref();
+ if (m_queryIds <= 0)
+ m_queryIds = 1;
+ }
XmlQueryJob job;
job.queryId = m_queryIds;
@@ -194,9 +201,6 @@ public:
{
QMutexLocker ml(&m_mutex);
m_jobs.insert(m_queryIds, job);
- m_queryIds++;
- if (m_queryIds <= 0)
- m_queryIds = 1;
}
QMetaObject::invokeMethod(this, "processQuery", Qt::QueuedConnection, Q_ARG(int, job.queryId));
@@ -214,20 +218,15 @@ private slots:
job = m_jobs.value(queryId);
}
- QDeclarativeXmlQueryResult r;
- doQueryJob(&job);
- doSubQueryJob(&job);
- r.queryId = job.queryId;
- r.size = m_size;
- r.data = m_modelData;
- r.inserted = m_insertedItemRanges;
- r.removed = m_removedItemRanges;
- r.keyRoleResultsCache = job.keyRoleResultsCache;
+ QDeclarativeXmlQueryResult result;
+ result.queryId = job.queryId;
+ doQueryJob(&job, &result);
+ doSubQueryJob(&job, &result);
{
QMutexLocker ml(&m_mutex);
if (m_jobs.contains(queryId)) {
- emit queryCompleted(r);
+ emit queryCompleted(result);
m_jobs.remove(queryId);
}
}
@@ -241,8 +240,8 @@ protected:
private:
- void doQueryJob(XmlQueryJob* job);
- void doSubQueryJob(XmlQueryJob* job);
+ void doQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult);
+ void doSubQueryJob(XmlQueryJob *job, QDeclarativeXmlQueryResult *currentResult);
void getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const;
void addIndexToRangeList(QList<QDeclarativeXmlListRange> *ranges, int index) const;
@@ -250,17 +249,12 @@ private:
QMutex m_mutex;
QThread m_thread;
QMap<int, XmlQueryJob> m_jobs;
- int m_queryIds;
- QString m_prefix;
- int m_size;
- QList<QList<QVariant> > m_modelData;
- QList<QDeclarativeXmlListRange> m_insertedItemRanges;
- QList<QDeclarativeXmlListRange> m_removedItemRanges;
+ QAtomicInt m_queryIds;
};
Q_GLOBAL_STATIC(QDeclarativeXmlQuery, globalXmlQuery)
-void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob)
+void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
{
Q_ASSERT(currentJob->queryId != -1);
@@ -295,10 +289,8 @@ void QDeclarativeXmlQuery::doQueryJob(XmlQueryJob* currentJob)
}
currentJob->data = xml;
- m_prefix = namespaces + prefix + QLatin1Char('/');
- m_size = 0;
- if (count > 0)
- m_size = count;
+ currentJob->prefix = namespaces + prefix + QLatin1Char('/');
+ currentResult->size = (count > 0 ? count : 0);
}
void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QStringList *values, QXmlQuery *query) const
@@ -306,9 +298,9 @@ void QDeclarativeXmlQuery::getValuesOfKeyRoles(const XmlQueryJob& currentJob, QS
const QStringList &keysQueries = currentJob.keyRoleQueries;
QString keysQuery;
if (keysQueries.count() == 1)
- keysQuery = m_prefix + keysQueries[0];
+ keysQuery = currentJob.prefix + keysQueries[0];
else if (keysQueries.count() > 1)
- keysQuery = m_prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")");
+ keysQuery = currentJob.prefix + QLatin1String("concat(") + keysQueries.join(QLatin1String(",")) + QLatin1String(")");
if (!keysQuery.isEmpty()) {
query->setQuery(keysQuery);
@@ -331,10 +323,9 @@ void QDeclarativeXmlQuery::addIndexToRangeList(QList<QDeclarativeXmlListRange> *
ranges->append(qMakePair(index, 1));
}
-void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob)
+void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob *currentJob, QDeclarativeXmlQueryResult *currentResult)
{
Q_ASSERT(currentJob->queryId != -1);
- m_modelData.clear();
QBuffer b(&currentJob->data);
b.open(QIODevice::ReadOnly);
@@ -347,16 +338,14 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob)
// See if any values of key roles have been inserted or removed.
- m_insertedItemRanges.clear();
- m_removedItemRanges.clear();
if (currentJob->keyRoleResultsCache.isEmpty()) {
- m_insertedItemRanges << qMakePair(0, m_size);
+ currentResult->inserted << qMakePair(0, currentResult->size);
} else {
if (keyRoleResults != currentJob->keyRoleResultsCache) {
QStringList temp;
for (int i=0; i<currentJob->keyRoleResultsCache.count(); i++) {
if (!keyRoleResults.contains(currentJob->keyRoleResultsCache[i]))
- addIndexToRangeList(&m_removedItemRanges, i);
+ addIndexToRangeList(&currentResult->removed, i);
else
temp << currentJob->keyRoleResultsCache[i];
}
@@ -364,12 +353,12 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob)
for (int i=0; i<keyRoleResults.count(); i++) {
if (temp.count() == i || keyRoleResults[i] != temp[i]) {
temp.insert(i, keyRoleResults[i]);
- addIndexToRangeList(&m_insertedItemRanges, i);
+ addIndexToRangeList(&currentResult->inserted, i);
}
}
}
}
- currentJob->keyRoleResultsCache = keyRoleResults;
+ currentResult->keyRoleResultsCache = keyRoleResults;
// Get the new values for each role.
//### we might be able to condense even further (query for everything in one go)
@@ -377,7 +366,7 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob)
for (int i = 0; i < queries.size(); ++i) {
QList<QVariant> resultList;
if (!queries[i].isEmpty()) {
- subquery.setQuery(m_prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")"));
+ subquery.setQuery(currentJob->prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")"));
if (subquery.isValid()) {
QXmlResultItems resultItems;
subquery.evaluateTo(&resultItems);
@@ -391,9 +380,9 @@ void QDeclarativeXmlQuery::doSubQueryJob(XmlQueryJob* currentJob)
}
}
//### should warn here if things have gone wrong.
- while (resultList.count() < m_size)
+ while (resultList.count() < currentResult->size)
resultList << QVariant();
- m_modelData << resultList;
+ currentResult->data << resultList;
b.seek(0);
}
@@ -919,7 +908,7 @@ void QDeclarativeXmlListModel::reload()
} else {
d->notifyQueryStarted(true);
QNetworkRequest req(d->src);
- req.setRawHeader("Accept", "application/xml");
+ req.setRawHeader("Accept", "application/xml,*/*");
d->reply = qmlContext(this)->engine()->networkAccessManager()->get(req);
QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished()));
QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)),
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index c714173..1e9e55e 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -83,6 +83,42 @@ public:
MenuCommand = 0x0018,
+ // Values from IAccessible2
+ ActionChanged = 0x0101,
+ ActiveDescendantChanged,
+ AttributeChanged,
+ DocumentContentChanged,
+ DocumentLoadComplete,
+ DocumentLoadStopped,
+ DocumentReload,
+ HyperlinkEndIndexChanged,
+ HyperlinkNumberOfAnchorsChanged,
+ HyperlinkSelectedLinkChanged,
+ HypertextLinkActivated,
+ HypertextLinkSelected,
+ HyperlinkStartIndexChanged,
+ HypertextChanged,
+ HypertextNLinksChanged,
+ ObjectAttributeChanged,
+ PageChanged,
+ SectionChanged,
+ TableCaptionChanged,
+ TableColumnDescriptionChanged,
+ TableColumnHeaderChanged,
+ TableModelChanged,
+ TableRowDescriptionChanged,
+ TableRowHeaderChanged,
+ TableSummaryChanged,
+ TextAttributeChanged,
+ TextCaretMoved,
+ // TextChanged, deprecated, use TextUpdated
+ TextColumnChanged = TextCaretMoved + 2,
+ TextInserted,
+ TextRemoved,
+ TextUpdated,
+ TextSelectionChanged,
+ VisibleDataChanged,
+
ObjectCreated = 0x8000,
ObjectDestroyed = 0x8001,
ObjectShow = 0x8002,
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index 1d2d1da..0cb2c08 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -322,9 +322,7 @@ QString QAccessibleApplication::text(Text t, int) const
{
switch (t) {
case Name:
- if (QApplication::activeWindow())
- return QApplication::activeWindow()->windowTitle();
- break;
+ return QApplication::applicationName();
case Description:
return QApplication::applicationFilePath();
default:
diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm
index ee9b19a..9daf595 100644
--- a/src/gui/dialogs/qcolordialog_mac.mm
+++ b/src/gui/dialogs/qcolordialog_mac.mm
@@ -343,6 +343,7 @@ QT_USE_NAMESPACE
mDialogIsExecuting = true;
bool modalEnded = false;
while (!modalEnded) {
+#ifndef QT_NO_EXCEPTIONS
@try {
[NSApp runModalForWindow:mColorPanel];
modalEnded = true;
@@ -351,6 +352,10 @@ QT_USE_NAMESPACE
// clicking on 'SelectedMenuItemColor' from the 'Developer'
// palette (tab three).
}
+#else
+ [NSApp runModalForWindow:mColorPanel];
+ modalEnded = true;
+#endif
}
QAbstractEventDispatcher::instance()->interrupt();
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index cb8eb6a..ff4410d 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -1977,13 +1977,14 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
const bool hideHidden = !(filters & QDir::Hidden);
const bool hideSystem = !(filters & QDir::System);
const bool hideSymlinks = (filters & QDir::NoSymLinks);
- const bool hideDotAndDotDot = (filters & QDir::NoDotAndDotDot);
+ const bool hideDot = (filters & QDir::NoDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
+ const bool hideDotDot = (filters & QDir::NoDotDot) || (filters & QDir::NoDotAndDotDot); // ### Qt5: simplify (because NoDotAndDotDot=NoDot|NoDotDot)
// Note that we match the behavior of entryList and not QFileInfo on this and this
// incompatibility won't be fixed until Qt 5 at least
- bool isDotOrDot = ( (node->fileName == QLatin1String(".")
- || node->fileName == QLatin1String("..")));
- if ( (hideHidden && (!isDotOrDot && node->isHidden()))
+ bool isDot = (node->fileName == QLatin1String("."));
+ bool isDotDot = (node->fileName == QLatin1String(".."));
+ if ( (hideHidden && !(isDot || isDotDot) && node->isHidden())
|| (hideSystem && node->isSystem())
|| (hideDirs && node->isDir())
|| (hideFiles && node->isFile())
@@ -1991,7 +1992,8 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
|| (hideReadable && node->isReadable())
|| (hideWritable && node->isWritable())
|| (hideExecutable && node->isExecutable())
- || (hideDotAndDotDot && isDotOrDot))
+ || (hideDot && isDot)
+ || (hideDotDot && isDotDot))
return false;
return nameFilterDisables || passNameFilters(node);
diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp
index 6533d11..fabf9d1 100644
--- a/src/gui/egl/qegl_symbian.cpp
+++ b/src/gui/egl/qegl_symbian.cpp
@@ -42,6 +42,7 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+#include <QtGui/private/qapplication_p.h>
#include "qegl_p.h"
#include "qeglcontext_p.h"
@@ -73,10 +74,14 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
return;
int devType = dev->devType();
- if (devType == QInternal::Image)
+ if (devType == QInternal::Image) {
setPixelFormat(static_cast<QImage *>(dev)->format());
- else
- setPixelFormat(QImage::Format_RGB32);
+ } else {
+ QImage::Format format = QImage::Format_RGB32;
+ if (QApplicationPrivate::instance() && QApplicationPrivate::instance()->useTranslucentEGLSurfaces)
+ format = QImage::Format_ARGB32_Premultiplied;
+ setPixelFormat(format);
+ }
}
diff --git a/src/gui/embedded/qvfbhdr.h b/src/gui/embedded/qvfbhdr.h
index 31704b3..84f82ac 100644
--- a/src/gui/embedded/qvfbhdr.h
+++ b/src/gui/embedded/qvfbhdr.h
@@ -53,36 +53,37 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
#ifndef QT_QWS_TEMP_DIR
-#define QT_QWS_TEMP_DIR "/tmp"
+# define QT_QWS_TEMP_DIR QLatin1String("/tmp")
#endif
#ifdef QT_PRIVATE_QWS
-#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2-%3") \
- .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY)
-
+#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2-%3") \
+ .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY)
#define QT_VFB_MOUSE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/qtvfb_mouse")
+ .append(QLatin1String("/qtvfb_mouse"))
#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/qtvfb_keyboard")
+ .append(QLatin1String("/qtvfb_keyboard"))
#define QT_VFB_MAP(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/qtvfb_map")
+ .append(QLatin1String("/qtvfb_map"))
#define QT_VFB_SOUND_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/qt_soundserver")
+ .append(QLatin1String("/qt_soundserver"))
#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/QtEmbedded")
+ .append(QLatin1String("/QtEmbedded"))
#define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY)
#else
-#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2") \
- .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
-#define QT_VFB_MOUSE_PIPE(DISPLAY) QString("/tmp/.qtvfb_mouse-%1").arg(DISPLAY)
-#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString("/tmp/.qtvfb_keyboard-%1").arg(DISPLAY)
-#define QT_VFB_MAP(DISPLAY) QString("/tmp/.qtvfb_map-%1").arg(DISPLAY)
-#define QT_VFB_SOUND_PIPE(DISPLAY) QString("/tmp/.qt_soundserver-%1").arg(DISPLAY)
-#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
- .append("/QtEmbedded-%1") \
- .arg(DISPLAY)
-#define QTE_PIPE_QVFB(DISPLAY) QString("/tmp/qtembedded-%1/QtEmbedded-%1") \
- .arg(DISPLAY)
+#define QT_VFB_DATADIR(DISPLAY) QString::fromLatin1("%1/qtembedded-%2") \
+ .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
+#define QT_VFB_MOUSE_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_mouse-%2") \
+ .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
+#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QString::fromLatin1("%1/.qtvfb_keyboard-%2") \
+ .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
+#define QT_VFB_MAP(DISPLAY) QString::fromLatin1("%1/.qtvfb_map-%2") \
+ .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
+#define QT_VFB_SOUND_PIPE(DISPLAY) QString::fromLatin1("%1/.qt_soundserver-%2") \
+ .arg(QT_QWS_TEMP_DIR).arg(DISPLAY)
+#define QTE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \
+ .append(QLatin1String("/QtEmbedded-%1")).arg(DISPLAY)
+#define QTE_PIPE_QVFB(DISPLAY) QTE_PIPE(DISPLAY)
#endif
struct QVFbHeader
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index 48cbec3..78918cc 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -451,8 +451,8 @@ static QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> getFactor(qreal valu
static qreal interpolate(const QPair<QGraphicsAnchorLayoutPrivate::Interval, qreal> &factor,
qreal min, qreal minPref, qreal pref, qreal maxPref, qreal max)
{
- qreal lower;
- qreal upper;
+ qreal lower = 0;
+ qreal upper = 0;
switch (factor.first) {
case QGraphicsAnchorLayoutPrivate::MinimumToMinPreferred:
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index e342783..e67fe82 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -421,7 +421,7 @@
\omitvalue ItemStopsFocusHandling \omit Same as
ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
allows you to completely take over focus handling.
- This flag was introduced in Qt 4.7.
+ This flag was introduced in Qt 4.7. \endomit
*/
/*!
diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp
index 904a3de..a67ae48 100644
--- a/src/gui/graphicsview/qgraphicslayout.cpp
+++ b/src/gui/graphicsview/qgraphicslayout.cpp
@@ -167,7 +167,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent)
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
@@ -188,7 +188,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutPrivate &dd, QGraphicsLayoutItem
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
@@ -269,12 +269,20 @@ void QGraphicsLayout::activate()
return;
Q_ASSERT(!parentItem->isLayout());
- setGeometry(parentItem->contentsRect()); // relayout children
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ QGraphicsWidget *parentWidget = static_cast<QGraphicsWidget*>(parentItem);
+ if (!parentWidget->parentLayoutItem()) {
+ // we've reached the topmost widget, resize it
+ bool wasResized = parentWidget->testAttribute(Qt::WA_Resized);
+ parentWidget->resize(parentWidget->size());
+ parentWidget->setAttribute(Qt::WA_Resized, wasResized);
+ }
- // ### bug, should be parentItem ?
- parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false
- // ### too many resizes? maybe we should walk up the chain to the
- // ### top-level layouted layoutItem and call activate there.
+ setGeometry(parentItem->contentsRect()); // relayout children
+ } else {
+ setGeometry(parentItem->contentsRect()); // relayout children
+ parentLayoutItem()->updateGeometry();
+ }
}
/*!
@@ -300,32 +308,36 @@ bool QGraphicsLayout::isActivated() const
*/
void QGraphicsLayout::invalidate()
{
- // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event.
- QGraphicsLayoutItem *layoutItem = this;
- while (layoutItem && layoutItem->isLayout()) {
- // we could call updateGeometry(), but what if that method
- // does not call the base implementation? In addition, updateGeometry()
- // does more than we need.
- layoutItem->d_func()->sizeHintCacheDirty = true;
- layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
- layoutItem = layoutItem->parentLayoutItem();
- }
- if (layoutItem) {
- layoutItem->d_func()->sizeHintCacheDirty = true;
- layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
- }
-
- bool postIt = layoutItem ? !layoutItem->isLayout() : false;
- if (postIt) {
- layoutItem = this;
- while (layoutItem && layoutItem->isLayout()
- && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) {
- static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false;
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ updateGeometry();
+ } else {
+ // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event.
+ QGraphicsLayoutItem *layoutItem = this;
+ while (layoutItem && layoutItem->isLayout()) {
+ // we could call updateGeometry(), but what if that method
+ // does not call the base implementation? In addition, updateGeometry()
+ // does more than we need.
+ layoutItem->d_func()->sizeHintCacheDirty = true;
+ layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
layoutItem = layoutItem->parentLayoutItem();
}
- if (layoutItem && !layoutItem->isLayout()) {
- // If a layout has a parent that is not a layout it must be a QGraphicsWidget.
- QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest));
+ if (layoutItem) {
+ layoutItem->d_func()->sizeHintCacheDirty = true;
+ layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
+ }
+
+ bool postIt = layoutItem ? !layoutItem->isLayout() : false;
+ if (postIt) {
+ layoutItem = this;
+ while (layoutItem && layoutItem->isLayout()
+ && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) {
+ static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false;
+ layoutItem = layoutItem->parentLayoutItem();
+ }
+ if (layoutItem && !layoutItem->isLayout()) {
+ // If a layout has a parent that is not a layout it must be a QGraphicsWidget.
+ QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest));
+ }
}
}
}
@@ -335,12 +347,27 @@ void QGraphicsLayout::invalidate()
*/
void QGraphicsLayout::updateGeometry()
{
- QGraphicsLayoutItem::updateGeometry();
- if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) {
- if (parentItem->isLayout()) {
+ Q_D(QGraphicsLayout);
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ d->activated = false;
+ QGraphicsLayoutItem::updateGeometry();
+
+ QGraphicsLayoutItem *parentItem = parentLayoutItem();
+ if (!parentItem)
+ return;
+
+ if (parentItem->isLayout())
+ static_cast<QGraphicsLayout *>(parentItem)->invalidate();
+ else
parentItem->updateGeometry();
- } else {
- invalidate();
+ } else {
+ QGraphicsLayoutItem::updateGeometry();
+ if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) {
+ if (parentItem->isLayout()) {
+ parentItem->updateGeometry();
+ } else {
+ invalidate();
+ }
}
}
}
@@ -446,6 +473,50 @@ void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
d->addChildLayoutItem(layoutItem);
}
+static bool g_instantInvalidatePropagation = false;
+
+/*!
+ \internal
+ \since 4.8
+ \see instantInvalidatePropagation
+
+ Calling this function with \a enable set to true will enable a feature that
+ makes propagation of invalidation up to ancestor layout items to be done in
+ one go. It will propagate up the parentLayoutItem() hierarchy until it has
+ reached the root. If the root item is a QGraphicsWidget, it will *post* a
+ layout request to it. When the layout request is consumed it will traverse
+ down the hierarchy of layouts and widgets and activate all layouts that is
+ invalid (not activated). This is the recommended behaviour.
+
+ If not set it will also propagate up the parentLayoutItem() hierarchy, but
+ it will stop at the \i first \i widget it encounters, and post a layout
+ request to the widget. When the layout request is consumed, this might
+ cause it to continue propagation up to the parentLayoutItem() of the
+ widget. It will continue in this fashion until it has reached a widget with
+ no parentLayoutItem(). This strategy might cause drawing artifacts, since
+ it is not done in one go, and the consumption of layout requests might be
+ interleaved by consumption of paint events, which might cause significant
+ flicker.
+ Note, this is not the recommended behavior, but for compatibility reasons
+ this is the default behaviour.
+*/
+void QGraphicsLayout::setInstantInvalidatePropagation(bool enable)
+{
+ g_instantInvalidatePropagation = enable;
+}
+
+/*!
+ \internal
+ \since 4.8
+ \see setInstantInvalidatePropagation
+
+ returns true if the complete widget/layout hierarchy is rearranged in one go.
+*/
+bool QGraphicsLayout::instantInvalidatePropagation()
+{
+ return g_instantInvalidatePropagation;
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index c622fb8..6031174 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -76,6 +76,8 @@ public:
virtual QGraphicsLayoutItem *itemAt(int i) const = 0;
virtual void removeAt(int index) = 0;
+ static void setInstantInvalidatePropagation(bool enable);
+ static bool instantInvalidatePropagation();
protected:
QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *);
void addChildLayoutItem(QGraphicsLayoutItem *layoutItem);
diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp
index c325602..f73fb6a 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicslayout_p.cpp
@@ -180,8 +180,13 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item)
{
if (item->isLayout()) {
QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item);
- if (layout->d_func()->activated)
- layout->invalidate();
+ if (layout->d_func()->activated) {
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ return;
+ } else {
+ layout->invalidate(); // ### LOOKS SUSPICIOUSLY WRONG!!???
+ }
+ }
for (int i = layout->count() - 1; i >= 0; --i) {
QGraphicsLayoutItem *childItem = layout->itemAt(i);
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 5591638..40f9b1d 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -275,17 +275,13 @@ void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *item)
qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself");
return;
}
- Q_ASSERT(item);
-
- //the order of the following instructions is very important because
- //invalidating the layout before adding the child item will make the layout happen
- //before we try to paint the item
- invalidate();
d->addChildLayoutItem(item);
+ Q_ASSERT(item);
d->fixIndex(&index);
d->engine.insertRow(index, d->orientation);
new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index);
+ invalidate();
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index faa29e5..0713d09 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5979,9 +5979,6 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve
}
if (item && item->isPanel())
break;
- if (item && (item->d_ptr->flags
- & (QGraphicsItem::ItemStopsClickFocusPropagation | QGraphicsItem::ItemStopsFocusHandling)))
- break;
}
touchEvent->setAccepted(eventAccepted);
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
index 92e4a55..4688fa0 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -50,14 +50,14 @@
QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning)
implementation to discover items quickly. This implementation is
- very efficient for static scene. It has a depth that you can set.
+ very efficient for static scenes. It has a depth that you can set.
The depth directly affects performance and memory usage; the latter
growing exponentially with the depth of the tree. With an optimal tree
depth, the index can instantly determine the locality of items, even
for scenes with thousands or millions of items. This also greatly improves
rendering performance.
- By default, the value is 0, in which case Qt will guess a reasonable
+ By default, the depth value is 0, in which case Qt will guess a reasonable
default depth based on the size, location and number of items in the
scene. If these parameters change frequently, however, you may experience
slowdowns as the index retunes the depth internally. You can avoid
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 675a5c5..141e305 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -354,8 +354,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
newGeom = rect;
newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize))
.boundedTo(effectiveSizeHint(Qt::MaximumSize)));
- if (newGeom == d->geom)
- return;
+
+ if (newGeom == d->geom) {
+ goto relayoutChildrenAndReturn;
+ }
// setPos triggers ItemPositionChange, which can adjust position
wd->inSetGeometry = 1;
@@ -363,8 +365,9 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
wd->inSetGeometry = 0;
newGeom.moveTopLeft(pos());
- if (newGeom == d->geom)
- return;
+ if (newGeom == d->geom) {
+ goto relayoutChildrenAndReturn;
+ }
// Update and prepare to change the geometry (remove from index) if the size has changed.
if (wd->scene) {
@@ -375,35 +378,54 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
}
// Update the layout item geometry
- bool moved = oldPos != pos();
- if (moved) {
- // Send move event.
- QGraphicsSceneMoveEvent event;
- event.setOldPos(oldPos);
- event.setNewPos(pos());
- QApplication::sendEvent(this, &event);
- if (wd->inSetPos) {
- //set the new pos
- d->geom.moveTopLeft(pos());
- emit geometryChanged();
- return;
+ {
+ bool moved = oldPos != pos();
+ if (moved) {
+ // Send move event.
+ QGraphicsSceneMoveEvent event;
+ event.setOldPos(oldPos);
+ event.setNewPos(pos());
+ QApplication::sendEvent(this, &event);
+ if (wd->inSetPos) {
+ //set the new pos
+ d->geom.moveTopLeft(pos());
+ emit geometryChanged();
+ goto relayoutChildrenAndReturn;
+ }
+ }
+ QSizeF oldSize = size();
+ QGraphicsLayoutItem::setGeometry(newGeom);
+ // Send resize event
+ bool resized = newGeom.size() != oldSize;
+ if (resized) {
+ QGraphicsSceneResizeEvent re;
+ re.setOldSize(oldSize);
+ re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
+ QGraphicsLayout *lay = wd->layout;
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ if (!lay || lay->isActivated()) {
+ QApplication::sendEvent(this, &re);
+ }
+ } else {
+ QApplication::sendEvent(this, &re);
+ }
}
}
- QSizeF oldSize = size();
- QGraphicsLayoutItem::setGeometry(newGeom);
- // Send resize event
- bool resized = newGeom.size() != oldSize;
- if (resized) {
- QGraphicsSceneResizeEvent re;
- re.setOldSize(oldSize);
- re.setNewSize(newGeom.size());
- if (oldSize.width() != newGeom.size().width())
- emit widthChanged();
- if (oldSize.height() != newGeom.size().height())
- emit heightChanged();
- QApplication::sendEvent(this, &re);
- }
+
emit geometryChanged();
+relayoutChildrenAndReturn:
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ if (QGraphicsLayout *lay = wd->layout) {
+ if (!lay->isActivated()) {
+ QEvent layoutRequest(QEvent::LayoutRequest);
+ QApplication::sendEvent(this, &layoutRequest);
+ }
+ }
+ }
}
/*!
@@ -1052,16 +1074,31 @@ void QGraphicsWidget::updateGeometry()
QGraphicsLayoutItem *parentItem = parentLayoutItem();
if (parentItem && parentItem->isLayout()) {
- parentItem->updateGeometry();
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ static_cast<QGraphicsLayout *>(parentItem)->invalidate();
+ } else {
+ parentItem->updateGeometry();
+ }
} else {
if (parentItem) {
+ // This is for custom layouting
QGraphicsWidget *parentWid = parentWidget(); //###
if (parentWid->isVisible())
QApplication::postEvent(parentWid, new QEvent(QEvent::LayoutRequest));
+ } else {
+ /**
+ * If this is the topmost widget, post a LayoutRequest event to the widget.
+ * When the event is received, it will start flowing all the way down to the leaf
+ * widgets in one go. This will make a relayout flicker-free.
+ */
+ if (QGraphicsLayout::instantInvalidatePropagation())
+ QApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest));
+ }
+ if (!QGraphicsLayout::instantInvalidatePropagation()) {
+ bool wasResized = testAttribute(Qt::WA_Resized);
+ resize(size()); // this will restrict the size
+ setAttribute(Qt::WA_Resized, wasResized);
}
- bool wasResized = testAttribute(Qt::WA_Resized);
- resize(size()); // this will restrict the size
- setAttribute(Qt::WA_Resized, wasResized);
}
}
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 4580055..63d7298 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -857,8 +857,6 @@ void QGraphicsWidgetPrivate::setWidth(qreal w)
if (q->geometry().width() == w)
return;
- QRectF oldGeom = q->geometry();
-
q->setGeometry(QRectF(q->x(), q->y(), w, height()));
}
@@ -882,8 +880,6 @@ void QGraphicsWidgetPrivate::setHeight(qreal h)
if (q->geometry().height() == h)
return;
- QRectF oldGeom = q->geometry();
-
q->setGeometry(QRectF(q->x(), q->y(), width(), h));
}
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index fda76a2..8f72fea 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -55,11 +55,9 @@ DEFINES += Q_INTERNAL_QAPP_SRC
symbian {
TARGET.UID3=0x2001B2DD
- symbian-abld|symbian-sbsv2 {
- # ro-section in gui can exceed default allocated space, so move rw-section a little further
- QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
- QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
- }
+ # ro-section in gui can exceed default allocated space, so move rw-section a little further
+ QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
+ QMAKE_LFLAGS.GCCE += -Tdata 0x800000
}
neon:*-g++* {
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index ab05bf1..0a0dc35 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1482,6 +1482,9 @@ QByteArray QImageReader::imageFormat(QIODevice *device)
configure script or check the appropriate option in the graphical
installer.
+ Note that the QApplication instance must be created before this function is
+ called.
+
\sa setFormat(), QImageWriter::supportedImageFormats(), QImageIOPlugin
*/
QList<QByteArray> QImageReader::supportedImageFormats()
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 8a65ac0..504260a 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -679,6 +679,9 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
Reading and writing SVG files is supported through Qt's
\l{QtSvg Module}{SVG Module}.
+ Note that the QApplication instance must be created before this function is
+ called.
+
\sa setFormat(), QImageReader::supportedImageFormats(), QImageIOPlugin
*/
QList<QByteArray> QImageWriter::supportedImageFormats()
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 34804e5..c34f6ac 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1224,12 +1224,8 @@ Qt::HANDLE QPixmap::handle() const
{
#if defined(Q_WS_X11)
const QPixmapData *pd = pixmapData();
- if (pd) {
- if (pd->classId() == QPixmapData::X11Class)
- return static_cast<const QX11PixmapData*>(pd)->handle();
- else
- qWarning("QPixmap::handle(): Pixmap is not an X11 class pixmap");
- }
+ if (pd && pd->classId() == QPixmapData::X11Class)
+ return static_cast<const QX11PixmapData*>(pd)->handle();
#endif
return 0;
}
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 41fc6e9..ae772d8 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -91,9 +91,7 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap
*/
-#if defined(Q_OS_SYMBIAN)
-static int cache_limit = 1024; // 1048 KB cache limit for symbian
-#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240; // 10 MB cache limit for desktop
diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp
index 098e9a1..f5076e1 100644
--- a/src/gui/image/qvolatileimage.cpp
+++ b/src/gui/image/qvolatileimage.cpp
@@ -103,6 +103,11 @@ QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs)
return *this;
}
+bool QVolatileImage::paintingActive() const
+{
+ return d->pengine && d->pengine->isActive();
+}
+
bool QVolatileImage::isNull() const
{
return d->image.isNull();
diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h
index fc5d6b1..d835f45 100644
--- a/src/gui/image/qvolatileimage_p.h
+++ b/src/gui/image/qvolatileimage_p.h
@@ -71,6 +71,7 @@ public:
~QVolatileImage();
QVolatileImage &operator=(const QVolatileImage &rhs);
+ bool paintingActive() const;
bool isNull() const;
QImage::Format format() const;
int width() const;
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
index 2c70ade..06dc25c 100644
--- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -77,6 +77,15 @@ QT_BEGIN_NAMESPACE
Q_GUI_EXPORT void qt_s60_setPartialScreenInputMode(bool enable)
{
S60->partial_keyboard = enable;
+
+ QInputContext *ic = 0;
+ if (QApplication::focusWidget()) {
+ ic = QApplication::focusWidget()->inputContext();
+ } else if (qApp && qApp->inputContext()) {
+ ic = qApp->inputContext();
+ }
+ if (ic)
+ ic->update();
}
QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
@@ -108,7 +117,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
m_fepState->SetDefaultCase( EAknEditorTextCase );
m_fepState->SetPermittedCases( EAknEditorAllCaseModes );
m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG);
- m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap );
+ m_fepState->SetNumericKeymap(EAknEditorAlphanumericNumberModeKeymap);
}
QCoeFepInputContext::~QCoeFepInputContext()
@@ -231,7 +240,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
// It ignores the mouse event, so we need to commit and send a selection event (which will get triggered
// after the commit)
if (!m_preeditString.isEmpty()) {
- commitCurrentString(false);
+ commitCurrentString(true);
int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
@@ -246,9 +255,13 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
// fall through intended
case QEvent::KeyRelease:
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
+ //If proxy exists, always use hints from proxy.
+ QWidget *proxy = focusWidget()->focusProxy();
+ Qt::InputMethodHints currentHints = proxy ? proxy->inputMethodHints() : focusWidget()->inputMethodHints();
+
switch (keyEvent->key()) {
case Qt::Key_F20:
- Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
+ Q_ASSERT(m_lastImHints == currentHints);
if (m_lastImHints & Qt::ImhHiddenText) {
// Special case in Symbian. On editors with secret text, F20 is for some reason
// considered to be a backspace.
@@ -278,7 +291,7 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event)
}
if (keyEvent->type() == QEvent::KeyPress
- && focusWidget()->inputMethodHints() & Qt::ImhHiddenText
+ && currentHints & Qt::ImhHiddenText
&& !keyEvent->text().isEmpty()) {
// Send some temporary preedit text in order to make text visible for a moment.
m_preeditString = keyEvent->text();
@@ -410,12 +423,14 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget)
windowToMove->setUpdatesEnabled(false);
if (!alwaysResize) {
- if (gv->scene() && gv->scene()->focusItem()) {
- // Check if the widget contains cursorPositionChanged signal and disconnect from it.
- QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged()));
- int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
- if (index != -1)
- disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
+ if (gv->scene()) {
+ if (gv->scene()->focusItem()) {
+ // Check if the widget contains cursorPositionChanged signal and disconnect from it.
+ QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged()));
+ int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1));
+ if (index != -1)
+ disconnect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget()));
+ }
QGraphicsItem *rootItem = 0;
foreach (QGraphicsItem *item, gv->scene()->items()) {
@@ -529,28 +544,32 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget)
// and greatly reduces event passing in orientation switch cases,
// as the statuspane size is not changing.
+ if (alwaysResize)
+ windowToMove->setUpdatesEnabled(false);
+
if (!(windowToMove->windowState() & Qt::WindowFullScreen)) {
windowToMove->setWindowState(
(windowToMove->windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowFullScreen);
}
if (alwaysResize) {
- windowToMove->setUpdatesEnabled(false);
- if (!moveWithinVisibleArea)
+ if (!moveWithinVisibleArea) {
m_splitViewResizeBy = widget->height();
-
- windowTop = widget->geometry().top();
- widget->resize(widget->width(), splitViewRect.height() - windowTop);
+ windowTop = widget->geometry().top();
+ widget->resize(widget->width(), splitViewRect.height() - windowTop);
+ }
if (gv->scene()) {
const QRectF microFocusRect = gv->scene()->inputMethodQuery(Qt::ImMicroFocus).toRectF();
gv->ensureVisible(microFocusRect);
}
- windowToMove->setUpdatesEnabled(true);
} else {
translateInputWidget();
}
+ if (alwaysResize)
+ windowToMove->setUpdatesEnabled(true);
+
widget->setAttribute(Qt::WA_Resized, userResize); //not a user resize
}
@@ -573,7 +592,21 @@ void QCoeFepInputContext::updateHints(bool mustUpdateInputCapabilities)
{
QWidget *w = focusWidget();
if (w) {
- Qt::InputMethodHints hints = w->inputMethodHints();
+ QWidget *proxy = w->focusProxy();
+ Qt::InputMethodHints hints = proxy ? proxy->inputMethodHints() : w->inputMethodHints();
+
+ // Since splitview support works like an input method hint, yet it is private flag,
+ // we need to update its state separately.
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) {
+ TInt currentFlags = m_fepState->Flags();
+ if (S60->partial_keyboard)
+ currentFlags |= QT_EAknEditorFlagEnablePartialScreen;
+ else
+ currentFlags &= ~QT_EAknEditorFlagEnablePartialScreen;
+ if (currentFlags != m_fepState->Flags())
+ m_fepState->SetFlags(currentFlags);
+ }
+
if (hints != m_lastImHints) {
m_lastImHints = hints;
applyHints(hints);
@@ -726,6 +759,8 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG);
} else if (needsCharMap) {
m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG);
+ } else if ((hints & ImhFormattedNumbersOnly) || (hints & ImhDialableCharactersOnly)) {
+ m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG);
} else {
m_fepState->SetSpecialCharacterTableResourceId(0);
}
diff --git a/src/gui/itemviews/itemviews.pri b/src/gui/itemviews/itemviews.pri
index bbc1e98..149bfd6 100644
--- a/src/gui/itemviews/itemviews.pri
+++ b/src/gui/itemviews/itemviews.pri
@@ -4,6 +4,7 @@ HEADERS += \
itemviews/qabstractitemview.h \
itemviews/qabstractitemview_p.h \
itemviews/qheaderview.h \
+ itemviews/qidentityproxymodel.h \
itemviews/qlistview.h \
itemviews/qlistview_p.h \
itemviews/qbsptree_p.h \
@@ -44,6 +45,7 @@ HEADERS += \
SOURCES += \
itemviews/qabstractitemview.cpp \
itemviews/qheaderview.cpp \
+ itemviews/qidentityproxymodel.cpp \
itemviews/qlistview.cpp \
itemviews/qbsptree.cpp \
itemviews/qtableview.cpp \
diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp
index 34ca7df..82b6c8d 100644
--- a/src/gui/itemviews/qabstractproxymodel.cpp
+++ b/src/gui/itemviews/qabstractproxymodel.cpp
@@ -121,15 +121,12 @@ QAbstractProxyModel::~QAbstractProxyModel()
void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
Q_D(QAbstractProxyModel);
- if (d->model) {
+ if (d->model)
disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
- disconnect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
- }
if (sourceModel) {
d->model = sourceModel;
connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
- connect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
} else {
d->model = QAbstractItemModelPrivate::staticEmptyModel();
}
@@ -383,25 +380,6 @@ Qt::DropActions QAbstractProxyModel::supportedDropActions() const
return d->model->supportedDropActions();
}
-/*
- \since 4.8
-
- This slot is called just after the internal data of a model is cleared
- while it is being reset.
-
- This slot is provided the convenience of subclasses of concrete proxy
- models, such as subclasses of QSortFilterProxyModel which maintain extra
- data.
-
- \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 10
-
- \sa modelAboutToBeReset(), modelReset()
-*/
-void QAbstractProxyModel::resetInternalData()
-{
-
-}
-
QT_END_NAMESPACE
#include "moc_qabstractproxymodel.cpp"
diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h
index 6e485ae..4f3bc18 100644
--- a/src/gui/itemviews/qabstractproxymodel.h
+++ b/src/gui/itemviews/qabstractproxymodel.h
@@ -95,9 +95,6 @@ public:
QStringList mimeTypes() const;
Qt::DropActions supportedDropActions() const;
-protected Q_SLOTS:
- void resetInternalData();
-
protected:
QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent);
diff --git a/src/gui/itemviews/qdatawidgetmapper.cpp b/src/gui/itemviews/qdatawidgetmapper.cpp
index 745ef5a..dac4613 100644
--- a/src/gui/itemviews/qdatawidgetmapper.cpp
+++ b/src/gui/itemviews/qdatawidgetmapper.cpp
@@ -291,7 +291,7 @@ void QDataWidgetMapperPrivate::_q_modelDestroyed()
\snippet doc/src/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp 0
After the call to toFirst(), \c mySpinBox displays the value \c{1}, \c myLineEdit
- displays \c {Nokia Corporation and/or its subsidiary(-ies)} and \c myCountryChooser displays \c{Oslo}. The
+ displays \c{Qt Norway} and \c myCountryChooser displays \c{Oslo}. The
navigational functions toFirst(), toNext(), toPrevious(), toLast() and setCurrentIndex()
can be used to navigate in the model and update the widgets with contents from
the model.
diff --git a/src/gui/itemviews/qidentityproxymodel.cpp b/src/gui/itemviews/qidentityproxymodel.cpp
new file mode 100644
index 0000000..60f7d98
--- /dev/null
+++ b/src/gui/itemviews/qidentityproxymodel.cpp
@@ -0,0 +1,587 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** 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 "qidentityproxymodel.h"
+
+#ifndef QT_NO_IDENTITYPROXYMODEL
+
+#include "qitemselectionmodel.h"
+#include <private/qabstractproxymodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIdentityProxyModelPrivate : public QAbstractProxyModelPrivate
+{
+ QIdentityProxyModelPrivate()
+ : ignoreNextLayoutAboutToBeChanged(false),
+ ignoreNextLayoutChanged(false)
+ {
+
+ }
+
+ Q_DECLARE_PUBLIC(QIdentityProxyModel)
+
+ bool ignoreNextLayoutAboutToBeChanged;
+ bool ignoreNextLayoutChanged;
+ QList<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QModelIndexList proxyIndexes;
+
+ void _q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void _q_sourceRowsInserted(const QModelIndex &parent, int start, int end);
+ void _q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void _q_sourceRowsRemoved(const QModelIndex &parent, int start, int end);
+ void _q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
+ void _q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
+
+ void _q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void _q_sourceColumnsInserted(const QModelIndex &parent, int start, int end);
+ void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void _q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end);
+ void _q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
+ void _q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
+
+ void _q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last);
+
+ void _q_sourceLayoutAboutToBeChanged();
+ void _q_sourceLayoutChanged();
+ void _q_sourceModelAboutToBeReset();
+ void _q_sourceModelReset();
+
+};
+
+/*!
+ \since 4.8
+ \class QIdentityProxyModel
+ \brief The QIdentityProxyModel class proxies its source model unmodified
+
+ \ingroup model-view
+
+ QIdentityProxyModel can be used to forward the structure of a source model exactly, with no sorting, filtering or other transformation.
+ This is similar in concept to an identity matrix where A.I = A.
+
+ Because it does no sorting or filtering, this class is most suitable to proxy models which transform the data() of the source model.
+ For example, a proxy model could be created to define the font used, or the background colour, or the tooltip etc. This removes the
+ need to implement all data handling in the same class that creates the structure of the model, and can also be used to create
+ re-usable components.
+
+ This also provides a way to change the data in the case where a source model is supplied by a third party which can not be modified.
+
+ \snippet doc/src/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp 0
+
+ \sa QAbstractProxyModel, {Model/View Programming}, QAbstractItemModel
+
+*/
+
+/*!
+ Constructs an identity model with the given \a parent.
+*/
+QIdentityProxyModel::QIdentityProxyModel(QObject* parent)
+ : QAbstractProxyModel(*new QIdentityProxyModelPrivate, parent)
+{
+
+}
+
+/*! \internal
+ */
+QIdentityProxyModel::QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent)
+ : QAbstractProxyModel(dd, parent)
+{
+
+}
+
+/*!
+ Destroys this identity model.
+*/
+QIdentityProxyModel::~QIdentityProxyModel()
+{
+}
+
+/*!
+ \reimp
+ */
+int QIdentityProxyModel::columnCount(const QModelIndex& parent) const
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(const QIdentityProxyModel);
+ return d->model->columnCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+bool QIdentityProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->dropMimeData(data, action, row, column, mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+QModelIndex QIdentityProxyModel::index(int row, int column, const QModelIndex& parent) const
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(const QIdentityProxyModel);
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+ const QModelIndex sourceParent = mapToSource(parent);
+ const QModelIndex sourceIndex = d->model->index(row, column, sourceParent);
+ Q_ASSERT(sourceIndex.isValid());
+ return mapFromSource(sourceIndex);
+}
+
+/*!
+ \reimp
+ */
+bool QIdentityProxyModel::insertColumns(int column, int count, const QModelIndex& parent)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->insertColumns(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+bool QIdentityProxyModel::insertRows(int row, int count, const QModelIndex& parent)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->insertRows(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+QModelIndex QIdentityProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
+{
+ Q_D(const QIdentityProxyModel);
+ if (!d->model || !sourceIndex.isValid())
+ return QModelIndex();
+
+ Q_ASSERT(sourceIndex.model() == d->model);
+ return createIndex(sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer());
+}
+
+/*!
+ \reimp
+ */
+QItemSelection QIdentityProxyModel::mapSelectionFromSource(const QItemSelection& selection) const
+{
+ Q_D(const QIdentityProxyModel);
+ QItemSelection proxySelection;
+
+ if (!d->model)
+ return proxySelection;
+
+ QItemSelection::const_iterator it = selection.constBegin();
+ const QItemSelection::const_iterator end = selection.constEnd();
+ for ( ; it != end; ++it) {
+ Q_ASSERT(it->model() == d->model);
+ const QItemSelectionRange range(mapFromSource(it->topLeft()), mapFromSource(it->bottomRight()));
+ proxySelection.append(range);
+ }
+
+ return proxySelection;
+}
+
+/*!
+ \reimp
+ */
+QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& selection) const
+{
+ Q_D(const QIdentityProxyModel);
+ QItemSelection sourceSelection;
+
+ if (!d->model)
+ return sourceSelection;
+
+ QItemSelection::const_iterator it = selection.constBegin();
+ const QItemSelection::const_iterator end = selection.constEnd();
+ for ( ; it != end; ++it) {
+ Q_ASSERT(it->model() == this);
+ const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight()));
+ sourceSelection.append(range);
+ }
+
+ return sourceSelection;
+}
+
+/*!
+ \reimp
+ */
+QModelIndex QIdentityProxyModel::mapToSource(const QModelIndex& proxyIndex) const
+{
+ Q_D(const QIdentityProxyModel);
+ if (!d->model || !proxyIndex.isValid())
+ return QModelIndex();
+ Q_ASSERT(proxyIndex.model() == this);
+ return d->model->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());
+}
+
+/*!
+ \reimp
+ */
+QModelIndexList QIdentityProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const
+{
+ Q_D(const QIdentityProxyModel);
+ Q_ASSERT(start.isValid() ? start.model() == this : true);
+ if (!d->model)
+ return QModelIndexList();
+
+ const QModelIndexList sourceList = d->model->match(mapToSource(start), role, value, hits, flags);
+ QModelIndexList::const_iterator it = sourceList.constBegin();
+ const QModelIndexList::const_iterator end = sourceList.constEnd();
+ QModelIndexList proxyList;
+ for ( ; it != end; ++it)
+ proxyList.append(mapFromSource(*it));
+ return proxyList;
+}
+
+/*!
+ \reimp
+ */
+QModelIndex QIdentityProxyModel::parent(const QModelIndex& child) const
+{
+ Q_ASSERT(child.isValid() ? child.model() == this : true);
+ const QModelIndex sourceIndex = mapToSource(child);
+ const QModelIndex sourceParent = sourceIndex.parent();
+ return mapFromSource(sourceParent);
+}
+
+/*!
+ \reimp
+ */
+bool QIdentityProxyModel::removeColumns(int column, int count, const QModelIndex& parent)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->removeColumns(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+bool QIdentityProxyModel::removeRows(int row, int count, const QModelIndex& parent)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(QIdentityProxyModel);
+ return d->model->removeRows(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+int QIdentityProxyModel::rowCount(const QModelIndex& parent) const
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == this : true);
+ Q_D(const QIdentityProxyModel);
+ return d->model->rowCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+void QIdentityProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
+{
+ beginResetModel();
+
+ if (sourceModel) {
+ disconnect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceRowsInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceRowsRemoved(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ this, SLOT(_q_sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ disconnect(sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ this, SLOT(_q_sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ disconnect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceColumnsAboutToBeInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceColumnsInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(_q_sourceColumnsRemoved(const QModelIndex &, int, int)));
+ disconnect(sourceModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ this, SLOT(_q_sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ disconnect(sourceModel, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ this, SLOT(_q_sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ disconnect(sourceModel, SIGNAL(modelAboutToBeReset()),
+ this, SLOT(_q_sourceModelAboutToBeReset()));
+ disconnect(sourceModel, SIGNAL(modelReset()),
+ this, SLOT(_q_sourceModelReset()));
+ disconnect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(_q_sourceDataChanged(const QModelIndex &, const QModelIndex &)));
+ disconnect(sourceModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
+ this, SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
+ disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged()),
+ this, SLOT(_q_sourceLayoutAboutToBeChanged()));
+ disconnect(sourceModel, SIGNAL(layoutChanged()),
+ this, SLOT(_q_sourceLayoutChanged()));
+ }
+
+ QAbstractProxyModel::setSourceModel(sourceModel);
+
+ if (sourceModel) {
+ connect(sourceModel, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
+ SLOT(_q_sourceRowsAboutToBeInserted(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ SLOT(_q_sourceRowsInserted(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
+ SLOT(_q_sourceRowsAboutToBeRemoved(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ SLOT(_q_sourceRowsRemoved(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ SLOT(_q_sourceRowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ connect(sourceModel, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ SLOT(_q_sourceRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ connect(sourceModel, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
+ SLOT(_q_sourceColumnsAboutToBeInserted(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
+ SLOT(_q_sourceColumnsInserted(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
+ SLOT(_q_sourceColumnsAboutToBeRemoved(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
+ SLOT(_q_sourceColumnsRemoved(const QModelIndex &, int, int)));
+ connect(sourceModel, SIGNAL(columnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ SLOT(_q_sourceColumnsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ connect(sourceModel, SIGNAL(columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)),
+ SLOT(_q_sourceColumnsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ connect(sourceModel, SIGNAL(modelAboutToBeReset()),
+ SLOT(_q_sourceModelAboutToBeReset()));
+ connect(sourceModel, SIGNAL(modelReset()),
+ SLOT(_q_sourceModelReset()));
+ connect(sourceModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
+ SLOT(_q_sourceDataChanged(const QModelIndex &, const QModelIndex &)));
+ connect(sourceModel, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
+ SLOT(_q_sourceHeaderDataChanged(Qt::Orientation,int,int)));
+ connect(sourceModel, SIGNAL(layoutAboutToBeChanged()),
+ SLOT(_q_sourceLayoutAboutToBeChanged()));
+ connect(sourceModel, SIGNAL(layoutChanged()),
+ SLOT(_q_sourceLayoutChanged()));
+ }
+
+ endResetModel();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginInsertColumns(q->mapFromSource(parent), start, end);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
+ Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginRemoveColumns(q->mapFromSource(parent), start, end);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(parent)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ q->endInsertColumns();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
+ Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(sourceParent)
+ Q_UNUSED(sourceStart)
+ Q_UNUSED(sourceEnd)
+ Q_UNUSED(destParent)
+ Q_UNUSED(dest)
+ q->endMoveColumns();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceColumnsRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(parent)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ q->endRemoveColumns();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ Q_ASSERT(topLeft.isValid() ? topLeft.model() == model : true);
+ Q_ASSERT(bottomRight.isValid() ? bottomRight.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight));
+}
+
+void QIdentityProxyModelPrivate::_q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last)
+{
+ Q_Q(QIdentityProxyModel);
+ q->headerDataChanged(orientation, first, last);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
+{
+ if (ignoreNextLayoutAboutToBeChanged)
+ return;
+
+ Q_Q(QIdentityProxyModel);
+
+ foreach(const QPersistentModelIndex &proxyPersistentIndex, q->persistentIndexList()) {
+ proxyIndexes << proxyPersistentIndex;
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
+
+ q->layoutAboutToBeChanged();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceLayoutChanged()
+{
+ if (ignoreNextLayoutChanged)
+ return;
+
+ Q_Q(QIdentityProxyModel);
+
+ for (int i = 0; i < proxyIndexes.size(); ++i) {
+ q->changePersistentIndex(proxyIndexes.at(i), q->mapFromSource(layoutChangePersistentIndexes.at(i)));
+ }
+
+ layoutChangePersistentIndexes.clear();
+ proxyIndexes.clear();
+
+ q->layoutChanged();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceModelAboutToBeReset()
+{
+ Q_Q(QIdentityProxyModel);
+ q->beginResetModel();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceModelReset()
+{
+ Q_Q(QIdentityProxyModel);
+ q->endResetModel();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginInsertRows(q->mapFromSource(parent), start, end);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
+ Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ q->beginRemoveRows(q->mapFromSource(parent), start, end);
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(parent)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ q->endInsertRows();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
+{
+ Q_ASSERT(sourceParent.isValid() ? sourceParent.model() == model : true);
+ Q_ASSERT(destParent.isValid() ? destParent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(sourceParent)
+ Q_UNUSED(sourceStart)
+ Q_UNUSED(sourceEnd)
+ Q_UNUSED(destParent)
+ Q_UNUSED(dest)
+ q->endMoveRows();
+}
+
+void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(parent.isValid() ? parent.model() == model : true);
+ Q_Q(QIdentityProxyModel);
+ Q_UNUSED(parent)
+ Q_UNUSED(start)
+ Q_UNUSED(end)
+ q->endRemoveRows();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qidentityproxymodel.cpp"
+
+#endif // QT_NO_IDENTITYPROXYMODEL
diff --git a/src/gui/itemviews/qidentityproxymodel.h b/src/gui/itemviews/qidentityproxymodel.h
new file mode 100644
index 0000000..4b3176a
--- /dev/null
+++ b/src/gui/itemviews/qidentityproxymodel.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QIDENTITYPROXYMODEL_H
+#define QIDENTITYPROXYMODEL_H
+
+#include <QtGui/qabstractproxymodel.h>
+
+#ifndef QT_NO_IDENTITYPROXYMODEL
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QIdentityProxyModelPrivate;
+
+class Q_GUI_EXPORT QIdentityProxyModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+public:
+ explicit QIdentityProxyModel(QObject* parent = 0);
+ ~QIdentityProxyModel();
+
+ int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
+ QModelIndex mapFromSource(const QModelIndex& sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex& proxyIndex) const;
+ QModelIndex parent(const QModelIndex& child) const;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
+
+ QItemSelection mapSelectionFromSource(const QItemSelection& selection) const;
+ QItemSelection mapSelectionToSource(const QItemSelection& selection) const;
+ QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
+ void setSourceModel(QAbstractItemModel* sourceModel);
+
+ bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex());
+ bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex());
+ bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex());
+ bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex());
+
+protected:
+ QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent);
+
+private:
+ Q_DECLARE_PRIVATE(QIdentityProxyModel)
+ Q_DISABLE_COPY(QIdentityProxyModel)
+
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsRemoved(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))
+
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeInserted(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(QModelIndex,int,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int))
+
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceDataChanged(QModelIndex,QModelIndex))
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int first, int last))
+
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelAboutToBeReset())
+ Q_PRIVATE_SLOT(d_func(), void _q_sourceModelReset())
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_IDENTITYPROXYMODEL
+
+#endif // QIDENTITYPROXYMODEL_H
+
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index 27a4a40..0b64452 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -1145,11 +1145,8 @@ void QItemSelectionModel::clearSelection()
Q_D(QItemSelectionModel);
if (d->ranges.count() == 0 && d->currentSelection.count() == 0)
return;
- QItemSelection selection = d->ranges;
- selection.merge(d->currentSelection, d->currentCommand);
- d->ranges.clear();
- d->currentSelection.clear();
- emit selectionChanged(QItemSelection(), selection);
+
+ select(QItemSelection(), Clear);
}
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index eb56f56..f73607b 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -1502,7 +1502,7 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved(
\l{Model Subclassing Reference}.
\sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming},
- {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}
+ {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel
*/
/*!
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index 33293f7..4989c05 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -263,6 +263,11 @@ QStyledItemDelegate::~QStyledItemDelegate()
The default implementation uses the QLocale::toString to convert \a value into
a QString.
+
+ This function is not called for empty model indices, i.e., indices for which
+ the model returns an invalid QVariant.
+
+ \sa QAbstractItemModel::data()
*/
QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
{
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index e494ee5..e70f356 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -1104,6 +1104,21 @@ void QTableView::setRootIndex(const QModelIndex &index)
/*!
\reimp
*/
+void QTableView::doItemsLayout()
+{
+ Q_D(QTableView);
+ QAbstractItemView::doItemsLayout();
+ if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
+ d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
+ else
+ d->verticalHeader->setOffset(verticalScrollBar()->value());
+ if (!d->verticalHeader->updatesEnabled())
+ d->verticalHeader->setUpdatesEnabled(true);
+}
+
+/*!
+ \reimp
+*/
void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
{
Q_D(QTableView);
@@ -1285,7 +1300,6 @@ void QTableView::paintEvent(QPaintEvent *event)
const QPen gridPen = QPen(gridColor, 0, d->gridStyle);
const QHeaderView *verticalHeader = d->verticalHeader;
const QHeaderView *horizontalHeader = d->horizontalHeader;
- const QStyle::State state = option.state;
const bool alternate = d->alternatingColors;
const bool rightToLeft = isRightToLeft();
@@ -1975,9 +1989,13 @@ QModelIndexList QTableView::selectedIndexes() const
previous number of rows is specified by \a oldCount, and the new
number of rows is specified by \a newCount.
*/
-void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
+void QTableView::rowCountChanged(int oldCount, int newCount )
{
Q_D(QTableView);
+ //when removing rows, we need to disable updates for the header until the geometries have been
+ //updated and the offset has been adjusted, or we risk calling paintSection for all the sections
+ if (newCount < oldCount)
+ d->verticalHeader->setUpdatesEnabled(false);
d->doDelayedItemsLayout();
}
diff --git a/src/gui/itemviews/qtableview.h b/src/gui/itemviews/qtableview.h
index d4be086..7ab9d08 100644
--- a/src/gui/itemviews/qtableview.h
+++ b/src/gui/itemviews/qtableview.h
@@ -71,6 +71,7 @@ public:
void setModel(QAbstractItemModel *model);
void setRootIndex(const QModelIndex &index);
void setSelectionModel(QItemSelectionModel *selectionModel);
+ void doItemsLayout();
QHeaderView *horizontalHeader() const;
QHeaderView *verticalHeader() const;
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 32fa3d3..3c57368 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -108,6 +108,8 @@ win32 {
}
symbian {
+ exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h): DEFINES += QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H
+
SOURCES += \
kernel/qapplication_s60.cpp \
kernel/qeventdispatcher_s60.cpp \
@@ -248,7 +250,8 @@ qpa {
kernel/qplatformglcontext_qpa.cpp \
kernel/qplatformcursor_qpa.cpp \
kernel/qplatformclipboard_qpa.cpp \
- kernel/qplatformnativeinterface_qpa.cpp
+ kernel/qplatformnativeinterface_qpa.cpp \
+ kernel/qsessionmanager_qpa.cpp
contains(QT_CONFIG, glib) {
SOURCES += \
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index e91fe04..4096bf3 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -128,6 +128,10 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
//#define ALIEN_DEBUG
+#if defined(Q_OS_SYMBIAN)
+#include "qt_s60_p.h"
+#endif
+
static void initResources()
{
#if defined(Q_WS_WINCE)
@@ -2438,6 +2442,11 @@ bool QApplication::event(QEvent *e)
{
Q_D(QApplication);
if(e->type() == QEvent::Close) {
+#if defined(Q_OS_SYMBIAN)
+ // In order to have proper application-exit effects on Symbian, certain
+ // native APIs have to be called _before_ closing/destroying the widgets.
+ bool effectStarted = qt_beginFullScreenEffect();
+#endif
QCloseEvent *ce = static_cast<QCloseEvent*>(e);
ce->accept();
closeAllWindows();
@@ -2451,8 +2460,14 @@ bool QApplication::event(QEvent *e)
break;
}
}
- if(ce->isAccepted())
+ if (ce->isAccepted()) {
return true;
+ } else {
+#if defined(Q_OS_SYMBIAN)
+ if (effectStarted)
+ qt_abortFullScreenEffect();
+#endif
+ }
} else if(e->type() == QEvent::LanguageChange) {
#ifndef QT_NO_TRANSLATION
setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index aa62518..fb61d36 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -79,6 +79,8 @@ template <typename T> class QList;
class QLocale;
#if defined(Q_WS_QWS)
class QDecoration;
+#elif defined(Q_WS_QPA)
+class QPlatformNativeInterface;
#endif
#if defined(Q_OS_SYMBIAN)
class QSymbianEvent;
@@ -254,6 +256,10 @@ public:
#endif
#endif
+#if defined(Q_WS_QPA)
+ static QPlatformNativeInterface *platformNativeInterface();
+#endif
+
#if defined(Q_WS_WIN)
void winFocus(QWidget *, bool);
diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp
index cb5439c..b754cf7 100644
--- a/src/gui/kernel/qapplication_qpa.cpp
+++ b/src/gui/kernel/qapplication_qpa.cpp
@@ -444,6 +444,12 @@ void QApplication::alert(QWidget *, int)
{
}
+QPlatformNativeInterface *QApplication::platformNativeInterface()
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ return pi->nativeInterface();
+}
+
static void init_platform(const QString &name, const QString &platformPluginPath)
{
QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, platformPluginPath);
@@ -514,7 +520,14 @@ void qt_init(QApplicationPrivate *priv, int type)
QList<QByteArray> pluginList;
QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
- QString platformName = QLatin1String(qgetenv("QT_QPA_PLATFORM"));
+ QByteArray platformName;
+#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
+ platformName = QT_QPA_DEFAULT_PLATFORM_NAME;
+#endif
+ QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM");
+ if (!platformNameEnv.isEmpty()) {
+ platformName = platformNameEnv;
+ }
// Get command line params
@@ -533,7 +546,7 @@ void qt_init(QApplicationPrivate *priv, int type)
platformPluginPath = QLatin1String(argv[i]);
} else if (arg == "-platform") {
if (++i < argc)
- platformName = QLatin1String(argv[i]);
+ platformName = argv[i];
} else if (arg == "-plugin") {
if (++i < argc)
pluginList << argv[i];
@@ -554,7 +567,7 @@ void qt_init(QApplicationPrivate *priv, int type)
}
#endif
- init_platform(platformName, platformPluginPath);
+ init_platform(QLatin1String(platformName), platformPluginPath);
init_plugins(pluginList);
QColormap::initialize();
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 769b136..2221500 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -142,6 +142,60 @@ void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, boo
// Ensure that control rectangle is updated
static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange();
}
+
+bool QS60Data::setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState)
+{
+ // Show statusbar:
+ // Topmost parent: Show unless fullscreen/minimized.
+ // Child windows: Follow topmost parent, unless fullscreen, in which case do not show statusbar
+ // Show CBA:
+ // Topmost parent: Show unless fullscreen/minimized.
+ // Exception: Show if fullscreen with Qt::WindowSoftkeysVisibleHint.
+ // Child windows:
+ // Minimized: Unclear if there is an use case for having focused minimized window at all.
+ // Always follow topmost parent just to be safe.
+ // Maximized and normal: follow topmost parent.
+ // Exception: If topmost parent is not showing CBA, show CBA if any softkey actions are
+ // defined.
+ // Fullscreen: Show only if Qt::WindowSoftkeysVisibleHint set.
+
+ Qt::WindowStates comparisonState = newState;
+ QWidget *parentWindow = window->parentWidget();
+ if (parentWindow) {
+ while (parentWindow->parentWidget())
+ parentWindow = parentWindow->parentWidget();
+ comparisonState = parentWindow->windowState();
+ } else {
+ parentWindow = window;
+ }
+
+ bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen;
+ const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint));
+
+ // Do extra checking for child windows
+ if (window->parentWidget()) {
+ if (newState & Qt::WindowFullScreen) {
+ decorationsVisible = false;
+ if (window->windowFlags() & Qt::WindowSoftkeysVisibleHint)
+ buttonGroupVisibility = true;
+ else
+ buttonGroupVisibility = false;
+ } else if (!(newState & Qt::WindowMinimized) && !buttonGroupVisibility) {
+ for (int i = 0; i < window->actions().size(); ++i) {
+ if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) {
+ buttonGroupVisibility = true;
+ break;
+ }
+ }
+ }
+ }
+
+ S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility);
+
+ return decorationsVisible;
+}
#endif
void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible)
@@ -161,6 +215,12 @@ void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible)
widget->repaint();
}
} else {
+ // In certain special scenarios we may get an ENotVisible event
+ // without a previous EPartiallyVisible. The backingstore must
+ // still be destroyed, hence the registerWidget() call below.
+ if (backingStore.data() && widget->internalWinId()
+ && qt_widget_private(widget)->maybeBackingStore() == backingStore.data())
+ backingStore.registerWidget(widget);
backingStore.unregisterWidget(widget);
// In order to ensure that any resources used by the window surface
// are immediately freed, we flush the WSERV command buffer.
@@ -405,6 +465,7 @@ QSymbianControl::QSymbianControl(QWidget *w)
, m_ignoreFocusChanged(0)
, m_symbianPopupIsOpen(0)
, m_inExternalScreenOverride(false)
+ , m_lastStatusPaneVisibility(0)
{
}
@@ -491,11 +552,52 @@ void QSymbianControl::setWidget(QWidget *w)
{
qwidget = w;
}
+
+QPoint QSymbianControl::translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const
+{
+ QPoint pos(pointerEventPos.iX, pointerEventPos.iY);
+ if (qwidget->d_func()->fixNativeOrientationCalled) {
+ QSize wsize = qwidget->size();
+ TSize size = Size();
+ if (size.iWidth == wsize.height() && size.iHeight == wsize.width()) {
+ qreal x = pos.x();
+ qreal y = pos.y();
+ pos.setX(size.iHeight - y);
+ pos.setY(x);
+ }
+ }
+ return pos;
+}
+
+TRect QSymbianControl::translateRectForFixedNativeOrientation(const TRect &controlRect) const
+{
+ TRect rect = controlRect;
+ if (qwidget->d_func()->fixNativeOrientationCalled) {
+ QPoint a = translatePointForFixedNativeOrientation(rect.iTl);
+ QPoint b = translatePointForFixedNativeOrientation(rect.iBr);
+ if (a.x() < b.x()) {
+ rect.iTl.iX = a.x();
+ rect.iBr.iX = b.x();
+ } else {
+ rect.iTl.iX = b.x();
+ rect.iBr.iX = a.x();
+ }
+ if (a.y() < b.y()) {
+ rect.iTl.iY = a.y();
+ rect.iBr.iY = b.y();
+ } else {
+ rect.iTl.iY = b.y();
+ rect.iBr.iY = a.y();
+ }
+ }
+ return rect;
+}
+
void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation )
{
QWidget *alienWidget;
- QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
- QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
+ QPoint widgetPos = translatePointForFixedNativeOrientation(aPenEventLocation);
+ QPoint globalPos = translatePointForFixedNativeOrientation(aPenEventScreenLocation);
alienWidget = qwidget->childAt(widgetPos);
if (!alienWidget)
alienWidget = qwidget;
@@ -510,7 +612,7 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons
void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event)
{
QApplicationPrivate *d = QApplicationPrivate::instance();
- QPointF screenPos = qwidget->mapToGlobal(QPoint(event->iPosition.iX, event->iPosition.iY));
+ QPointF screenPos = qwidget->mapToGlobal(translatePointForFixedNativeOrientation(event->iPosition));
qreal pressure;
if(d->pressureSupported
&& event->Pressure() > 0) //workaround for misconfigured HAL
@@ -611,7 +713,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent)
mapS60MouseEventTypeToQt(&type, &button, &pEvent);
Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers);
- QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
+ QPoint widgetPos = translatePointForFixedNativeOrientation(pEvent.iPosition);
TPoint controlScreenPos = PositionRelativeToScreen();
QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
S60->lastCursorPos = globalPos;
@@ -1077,6 +1179,9 @@ void QSymbianControl::Draw(const TRect& controlRect) const
Q_ASSERT(window);
QTLWExtra *topExtra = window->d_func()->maybeTopData();
Q_ASSERT(topExtra);
+
+ TRect wcontrolRect = translateRectForFixedNativeOrientation(controlRect);
+
if (!topExtra->inExpose) {
topExtra->inExpose = true;
if (!qwidget->isWindow()) {
@@ -1087,7 +1192,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const
gc.SetBrushColor(TRgb(0, 0, 0, 0));
gc.Clear(controlRect);
}
- QRect exposeRect = qt_TRect2QRect(controlRect);
+ QRect exposeRect = qt_TRect2QRect(wcontrolRect);
qwidget->d_func()->syncBackingStore(exposeRect);
topExtra->inExpose = false;
}
@@ -1100,7 +1205,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const
const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents;
if (sendNativePaintEvents) {
- const QRect r = qt_TRect2QRect(controlRect);
+ const QRect r = qt_TRect2QRect(wcontrolRect);
QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r));
}
@@ -1155,7 +1260,7 @@ void QSymbianControl::Draw(const TRect& controlRect) const
}
if (sendNativePaintEvents) {
- const QRect r = qt_TRect2QRect(controlRect);
+ const QRect r = qt_TRect2QRect(wcontrolRect);
// The draw ops aren't actually sent to WSERV until the graphics
// context is deactivated, which happens in the function calling
// this one. We therefore delay the delivery of endNativePaintEvent,
@@ -1168,14 +1273,45 @@ void QSymbianControl::Draw(const TRect& controlRect) const
}
}
+void QSymbianControl::qwidgetResize_helper(const QSize &newSize)
+{
+ QRect cr = qwidget->geometry();
+ QSize oldSize(cr.size());
+ cr.setSize(newSize);
+ qwidget->data->crect = cr;
+ if (qwidget->isVisible()) {
+ QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
+ bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = true;
+ QResizeEvent e(newSize, oldSize);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ if (!qwidget->testAttribute(Qt::WA_StaticContents))
+ qwidget->d_func()->syncBackingStore();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = false;
+ } else {
+ if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) {
+ QResizeEvent *e = new QResizeEvent(newSize, oldSize);
+ QApplication::postEvent(qwidget, e);
+ }
+ }
+}
+
void QSymbianControl::SizeChanged()
{
CCoeControl::SizeChanged();
+ // When FixNativeOrientation had been called, the RWindow/CCoeControl size
+ // and the surface/QWidget size have nothing to do with each other.
+ if (qwidget->d_func()->fixNativeOrientationCalled)
+ return;
+
QSize oldSize = qwidget->size();
QSize newSize(Size().iWidth, Size().iHeight);
if (oldSize != newSize) {
+ // Enforce the proper size for fullscreen widgets on the secondary screen.
const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
const int screenNumber = S60->screenNumberForWidget(qwidget);
if (!m_inExternalScreenOverride && isFullscreen && screenNumber > 0) {
@@ -1188,26 +1324,8 @@ void QSymbianControl::SizeChanged()
return;
}
}
- QRect cr = qwidget->geometry();
- cr.setSize(newSize);
- qwidget->data->crect = cr;
- if (qwidget->isVisible()) {
- QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
- bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
- if (!slowResize && tlwExtra)
- tlwExtra->inTopLevelResize = true;
- QResizeEvent e(newSize, oldSize);
- qt_sendSpontaneousEvent(qwidget, &e);
- if (!qwidget->testAttribute(Qt::WA_StaticContents))
- qwidget->d_func()->syncBackingStore();
- if (!slowResize && tlwExtra)
- tlwExtra->inTopLevelResize = false;
- } else {
- if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) {
- QResizeEvent *e = new QResizeEvent(newSize, oldSize);
- QApplication::postEvent(qwidget, e);
- }
- }
+
+ qwidgetResize_helper(newSize);
}
m_inExternalScreenOverride = false;
@@ -1271,37 +1389,8 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
#ifdef Q_WS_S60
- if (qwidget->isWindow()) {
- QWidget *const window = qwidget->window();
- QWidget *parentWindow = window->parentWidget();
- if (parentWindow) {
- while (parentWindow->parentWidget())
- parentWindow = parentWindow->parentWidget();
- } else {
- parentWindow = window;
- }
-
- const bool parentDecorationsVisible = !(parentWindow->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
- const bool parentIsFullscreen = parentWindow->windowState() & Qt::WindowFullScreen;
- const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint;
- bool buttonGroupVisibility = (parentDecorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint));
-
- // For non-toplevel normal and maximized windows, show cba if window has softkey
- // actions even if topmost parent is not showing cba. Do the same for fullscreen
- // windows that request it.
- if (!buttonGroupVisibility
- && window->parentWidget()
- && !(window->windowState() & Qt::WindowMinimized)
- && ((window->windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(window->windowState() & Qt::WindowFullScreen))) {
- for (int i = 0; i < window->actions().size(); ++i) {
- if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) {
- buttonGroupVisibility = true;
- break;
- }
- }
- }
- S60->setStatusPaneAndButtonGroupVisibility(parentDecorationsVisible, buttonGroupVisibility);
- }
+ if (qwidget->isWindow())
+ S60->setRecursiveDecorationsVisibility(qwidget, qwidget->windowState());
#endif
} else if (QApplication::activeWindow() == qwidget->window()) {
bool focusedControlFound = false;
@@ -1402,7 +1491,13 @@ void QSymbianControl::HandleResourceChange(int resourceType)
}
break;
case KInternalStatusPaneChange:
- handleClientAreaChange();
+ // When status pane is not visible, only handle client area change if status pane was
+ // previously visible, as size changes to hidden status pane should not affect
+ // client area.
+ if (S60->statusPane() && (S60->statusPane()->IsVisible() || m_lastStatusPaneVisibility)) {
+ m_lastStatusPaneVisibility = S60->statusPane()->IsVisible();
+ handleClientAreaChange();
+ }
if (IsFocused() && IsVisible()) {
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
@@ -1416,8 +1511,10 @@ void QSymbianControl::HandleResourceChange(int resourceType)
{
handleClientAreaChange();
// Send resize event to trigger desktopwidget workAreaResized signal
- QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size());
- QApplication::sendEvent(qt_desktopWidget, &e);
+ if (qt_desktopWidget) {
+ QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size());
+ QApplication::sendEvent(qt_desktopWidget, &e);
+ }
break;
}
#endif
@@ -1479,29 +1576,49 @@ bool QSymbianControl::isControlActive()
void QSymbianControl::ensureFixNativeOrientation()
{
#if defined(Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION)
- // Call FixNativeOrientation() for fullscreen QDeclarativeViews that
- // have a locked orientation matching the native orientation of the device.
- // This avoids unnecessary window rotation on wserv level.
- if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop
- || !qwidget->inherits("QDeclarativeView")
- || S60->screenNumberForWidget(qwidget) > 0)
+ if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop)
+ return;
+ if (S60->screenNumberForWidget(qwidget) > 0)
return;
- const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen);
const bool isFixed = qwidget->d_func()->fixNativeOrientationCalled;
- const bool matchesNative = qwidget->testAttribute(
- S60->nativeOrientationIsPortrait ? Qt::WA_LockPortraitOrientation
- : Qt::WA_LockLandscapeOrientation);
- if (isFullScreen && matchesNative) {
- if (!isFixed) {
- Window().FixNativeOrientation();
- qwidget->d_func()->fixNativeOrientationCalled = true;
+ const bool isFixEnabled = qwidget->testAttribute(Qt::WA_SymbianNoSystemRotation);
+ const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen);
+ if (isFullScreen && isFixEnabled) {
+ const bool surfaceBasedGs =
+ QApplicationPrivate::graphics_system_name == QLatin1String("openvg")
+ || QApplicationPrivate::graphics_system_name == QLatin1String("opengl");
+ if (!surfaceBasedGs)
+ qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false);
+ if (!isFixed && surfaceBasedGs) {
+ if (Window().FixNativeOrientation() == KErrNone) {
+ qwidget->d_func()->fixNativeOrientationCalled = true;
+ // The EGL window surface is now fixed to the native orientation
+ // of the device, no matter what size we pass when creating it.
+ // Enforce the same size for the QWidget too. For the underlying
+ // CCoeControl and RWindow it is up to the system to resize them
+ // when the standard auto-rotation mechanism is in use, we must not
+ // change that behavior by forcing any size for those. In practice
+ // this means that the QWidget and the underlying native control
+ // dimensions will be out of sync when FixNativeOrientation was
+ // called and the device is turned to the non-native (typically
+ // landscape) orientation. The pointer event handling and certain
+ // functions like Draw() will need to compensate for this.
+ QSize newSize(S60->nativeScreenWidthInPixels, S60->nativeScreenHeightInPixels);
+ if (qwidget->size() != newSize)
+ qwidgetResize_helper(newSize);
+ } else {
+ qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false);
+ }
}
} else if (isFixed) {
+ qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false);
qwidget->d_func()->fixNativeOrientationCalled = false;
qwidget->hide();
qwidget->d_func()->create_sys(0, false, true);
qwidget->show();
}
+#else
+ qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false);
#endif
}
@@ -1713,9 +1830,7 @@ void qt_init(QApplicationPrivate * /* priv */, int)
systemFont.setFamily(systemFont.defaultFamily());
QApplicationPrivate::setSystemFont(systemFont);
-#ifdef Q_SYMBIAN_TRANSITION_EFFECTS
QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit()));
-#endif
#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE
QApplicationPrivate::instance()->useTranslucentEGLSurfaces = true;
@@ -1740,6 +1855,8 @@ void qt_init(QApplicationPrivate * /* priv */, int)
} else {
QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false;
}
+ if (QApplicationPrivate::graphics_system_name == QLatin1String("raster"))
+ QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false;
#else
QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false;
#endif
@@ -1811,6 +1928,9 @@ void qt_cleanup()
S60->setButtonGroupContainer(0);
#endif
+ // Call EndFullScreen() to prevent confusing the system effect state machine.
+ qt_endFullScreenEffect();
+
if (S60->qtOwnsS60Environment) {
// Restore the S60 framework trap handler. See qt_init().
User::SetTrapHandler(S60->s60InstalledTrapHandler);
@@ -2182,7 +2302,8 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent
}
#endif
#ifdef QT_SOFTKEYS_ENABLED
- QSoftKeyManager::updateSoftKeys();
+ if (!CEikonEnv::Static()->EikAppUi()->IsDisplayingMenuOrDialog())
+ QSoftKeyManager::updateSoftKeys();
#endif
break;
case EEventFocusLost:
@@ -2555,6 +2676,8 @@ void QApplication::restoreOverrideCursor()
void QApplicationPrivate::_q_aboutToQuit()
{
+ qt_beginFullScreenEffect();
+
#ifdef Q_SYMBIAN_TRANSITION_EFFECTS
// Send the shutdown tfx command
S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown);
@@ -2580,6 +2703,9 @@ QS60ThreadLocalData::QS60ThreadLocalData()
QS60ThreadLocalData::~QS60ThreadLocalData()
{
+ for (int i = 0; i < releaseFuncs.count(); ++i)
+ releaseFuncs[i]();
+ releaseFuncs.clear();
if (!usingCONEinstances) {
delete screenDevice;
wsSession.Close();
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 5f5da59..63e2319 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -237,6 +237,7 @@ static void resolveAygLibs()
# define FE_FONTSMOOTHINGCLEARTYPE 0x0002
#endif
+Q_GUI_EXPORT qreal qt_fontsmoothing_gamma;
Q_GUI_EXPORT bool qt_cleartype_enabled;
Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default
@@ -653,8 +654,18 @@ static void qt_win_read_cleartype_settings()
if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0))
qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
#endif
-}
+ int winSmooth;
+ if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) {
+ qt_fontsmoothing_gamma = winSmooth / qreal(1000.0);
+ } else {
+ qt_fontsmoothing_gamma = 1.0;
+ }
+
+ // Safeguard ourselves against corrupt registry values...
+ if (qt_fontsmoothing_gamma > 5 || qt_fontsmoothing_gamma < 1)
+ qt_fontsmoothing_gamma = qreal(1.4);
+}
static void qt_set_windows_resources()
{
@@ -2361,8 +2372,13 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa
#ifndef QT_NO_ACCESSIBILITY
case WM_GETOBJECT:
{
+ /* On Win64, lParam can be 0x00000000fffffffc or 0xfffffffffffffffc (!),
+ but MSDN says that lParam should be converted to a DWORD
+ before its compared against OBJID_CLIENT
+ */
+ const DWORD dwObjId = (DWORD)lParam;
// Ignoring all requests while starting up
- if (QApplication::startingUp() || QApplication::closingDown() || lParam != (LPARAM)OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || dwObjId != OBJID_CLIENT) {
result = false;
break;
}
@@ -3815,16 +3831,32 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QApplication::sendSpontaneousEvent(this, &e);
hideChildren(true);
}
- } else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) {
+ } else if (msg.wParam != SIZE_MINIMIZED) {
+ bool window_state_changed = false;
+ Qt::WindowStates oldstate = Qt::WindowStates(dataPtr()->window_state);
+ if (isMinimized()) {
#ifndef Q_WS_WINCE
- const QString title = windowTitle();
- if (!title.isEmpty())
- d_func()->setWindowTitle_helper(title);
+ const QString title = windowTitle();
+ if (!title.isEmpty())
+ d_func()->setWindowTitle_helper(title);
#endif
- data->window_state &= ~Qt::WindowMinimized;
- showChildren(true);
- QShowEvent e;
- QApplication::sendSpontaneousEvent(this, &e);
+ data->window_state &= ~Qt::WindowMinimized;
+ showChildren(true);
+ QShowEvent e;
+ QApplication::sendSpontaneousEvent(this, &e);
+ // Capture SIZE_MAXIMIZED and SIZE_RESTORED without preceding WM_SYSCOMMAND
+ // (Aero Snap on Win7)
+ } else if (msg.wParam == SIZE_MAXIMIZED && !isMaximized()) {
+ data->window_state |= Qt::WindowMaximized;
+ window_state_changed = true;
+ } else if (msg.wParam == SIZE_RESTORED && isMaximized()) {
+ data->window_state &= ~(Qt::WindowMaximized);
+ window_state_changed = true;
+ }
+ if (window_state_changed) {
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendSpontaneousEvent(this, &e);
+ }
}
}
if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) {
@@ -3856,7 +3888,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QApplication::postEvent(this, e);
}
}
-} else if (msg.message == WM_MOVE) { // move event
+ } else if (msg.message == WM_MOVE) { // move event
int a = (int) (short) LOWORD(msg.lParam);
int b = (int) (short) HIWORD(msg.lParam);
QPoint oldPos = geometry().topLeft();
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index 7d41f3d..ee1115b 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -146,6 +146,20 @@ QT_END_NAMESPACE
[NSApp terminate:sender];
}
+- (void)setLevel:(NSInteger)windowLevel
+{
+ // Cocoa will upon activating/deactivating applications level modal
+ // windows up and down, regardsless of any explicit set window level.
+ // To ensure that modal stays-on-top dialogs actually stays on top after
+ // the application is activated (and therefore stacks in front of
+ // other stays-on-top windows), we need to add this little special-case override:
+ QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ if (widget && widget->isModal() && (widget->windowFlags() & Qt::WindowStaysOnTopHint))
+ [super setLevel:NSPopUpMenuWindowLevel];
+ else
+ [super setLevel:windowLevel];
+}
+
- (void)sendEvent:(NSEvent *)event
{
[self retain];
diff --git a/src/gui/kernel/qcursor_x11.cpp b/src/gui/kernel/qcursor_x11.cpp
index d0ed98e..0bc7250 100644
--- a/src/gui/kernel/qcursor_x11.cpp
+++ b/src/gui/kernel/qcursor_x11.cpp
@@ -55,6 +55,9 @@
#endif // QT_NO_XCURSOR
#ifndef QT_NO_XFIXES
+#ifndef Status
+#define Status int
+#endif
# include <X11/extensions/Xfixes.h>
#endif // QT_NO_XFIXES
diff --git a/src/gui/kernel/qdesktopwidget_qpa.cpp b/src/gui/kernel/qdesktopwidget_qpa.cpp
index cff05f5..6257a8b 100644
--- a/src/gui/kernel/qdesktopwidget_qpa.cpp
+++ b/src/gui/kernel/qdesktopwidget_qpa.cpp
@@ -51,6 +51,8 @@ QT_USE_NAMESPACE
void QDesktopWidgetPrivate::updateScreenList()
{
+ Q_Q(QDesktopWidget);
+
QList<QPlatformScreen *> screenList = QApplicationPrivate::platformIntegration()->screens();
int targetLength = screenList.length();
int currentLength = screens.length();
@@ -72,19 +74,15 @@ void QDesktopWidgetPrivate::updateScreenList()
}
QRegion virtualGeometry;
- bool doVirtualGeometry = QApplicationPrivate::platformIntegration()->isVirtualDesktop();
// update the geometry of each screen widget
for (int i = 0; i < screens.length(); i++) {
QRect screenGeometry = screenList.at(i)->geometry();
screens.at(i)->setGeometry(screenGeometry);
- if (doVirtualGeometry)
- virtualGeometry += screenGeometry;
+ virtualGeometry += screenGeometry;
}
- virtualScreen.setGeometry(virtualGeometry.boundingRect());
- Q_Q(QDesktopWidget);
- q->setGeometry(virtualScreen.geometry());
+ q->setGeometry(virtualGeometry.boundingRect());
}
QDesktopWidget::QDesktopWidget()
@@ -118,8 +116,6 @@ int QDesktopWidget::numScreens() const
QWidget *QDesktopWidget::screen(int screen)
{
Q_D(QDesktopWidget);
- if (QApplicationPrivate::platformIntegration()->isVirtualDesktop())
- return &d->virtualScreen;
if (screen < 0 || screen >= d->screens.length())
return d->screens.at(0);
return d->screens.at(screen);
diff --git a/src/gui/kernel/qdesktopwidget_qpa_p.h b/src/gui/kernel/qdesktopwidget_qpa_p.h
index abee8a1..d6ed686 100644
--- a/src/gui/kernel/qdesktopwidget_qpa_p.h
+++ b/src/gui/kernel/qdesktopwidget_qpa_p.h
@@ -76,7 +76,6 @@ public:
void updateScreenList();
QList<QDesktopScreenWidget *> screens;
- QDesktopScreenWidget virtualScreen;
};
#endif // QDESKTOPWIDGET_QPA_P_H
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 5359fb3..7aa7dffd 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -566,7 +566,6 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
= w->d_func()->gestureContext.find(type);
if (it != w->d_func()->gestureContext.end()) {
// i.e. 'w' listens to gesture 'type'
- Qt::GestureFlags flags = it.value();
if (!(it.value() & Qt::DontStartGestureOnChildren) && w != widget) {
// conflicting gesture!
(*conflicts)[widget].append(gestures[widget]);
diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp
index 86740e8..1810532 100644
--- a/src/gui/kernel/qplatformglcontext_qpa.cpp
+++ b/src/gui/kernel/qplatformglcontext_qpa.cpp
@@ -125,24 +125,6 @@ QPlatformGLContext::~QPlatformGLContext()
}
-
-/*!
- Makes it possible to set the context which can be the default for making new contexts.
-*/
-void QPlatformGLContext::setDefaultSharedContext(QPlatformGLContext *sharedContext)
-{
- QPlatformGLContextPrivate::staticSharedContext = sharedContext;
-}
-
-/*!
- Default shared context is intended to be a globally awailable pointer to a context which can
- be used for sharing resources when creating new contexts. Its default value is 0;
-*/
-QPlatformGLContext *QPlatformGLContext::defaultSharedContext()
-{
- return QPlatformGLContextPrivate::staticSharedContext;
-}
-
/*!
Reimplement in subclass to do makeCurrent on native GL context
*/
diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformglcontext_qpa.h
index a680c85..28923a9 100644
--- a/src/gui/kernel/qplatformglcontext_qpa.h
+++ b/src/gui/kernel/qplatformglcontext_qpa.h
@@ -69,13 +69,10 @@ public:
virtual QPlatformWindowFormat platformWindowFormat() const = 0;
const static QPlatformGLContext *currentContext();
- static QPlatformGLContext *defaultSharedContext();
protected:
-
- static void setDefaultSharedContext(QPlatformGLContext *sharedContext);
-
QScopedPointer<QPlatformGLContextPrivate> d_ptr;
+
private:
//hack to make it work with QGLContext::CurrentContext
friend class QGLContext;
diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp
index c45a953..8ff12eb 100644
--- a/src/gui/kernel/qplatformintegration_qpa.cpp
+++ b/src/gui/kernel/qplatformintegration_qpa.cpp
@@ -69,16 +69,6 @@ QPlatformEventLoopIntegration *QPlatformIntegration::createEventLoopIntegration(
}
/*!
- Returns whether the given platform integration supports OpenGL.
-
- Default implementation returns false,
-*/
-bool QPlatformIntegration::hasOpenGL() const
-{
- return false;
-}
-
-/*!
Accessor for the platform integrations fontdatabase.
Default implementation returns a default QPlatformFontDatabase.
@@ -224,6 +214,7 @@ QPlatformNativeInterface * QPlatformIntegration::nativeInterface() const
bool QPlatformIntegration::hasCapability(Capability cap) const
{
+ Q_UNUSED(cap);
return false;
}
diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h
index 0aacefa..d06272c 100644
--- a/src/gui/kernel/qplatformintegration_qpa.h
+++ b/src/gui/kernel/qplatformintegration_qpa.h
@@ -67,6 +67,7 @@ class Q_GUI_EXPORT QPlatformIntegration
public:
enum Capability {
ThreadedPixmaps = 1,
+ OpenGL = 2
};
virtual ~QPlatformIntegration() { }
@@ -95,9 +96,6 @@ public:
// the gui thread. All of the functions in QWindowSystemInterface are thread safe.
virtual QPlatformEventLoopIntegration *createEventLoopIntegration() const;
-//jl:XXX should it be hasGLContext and do we need it at all?
- virtual bool hasOpenGL() const;
-
// Access native handles. The window handle is already available from Wid;
virtual QPlatformNativeInterface *nativeInterface() const;
};
diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.cpp b/src/gui/kernel/qplatformnativeinterface_qpa.cpp
index ace4a7b..281aeba 100644
--- a/src/gui/kernel/qplatformnativeinterface_qpa.cpp
+++ b/src/gui/kernel/qplatformnativeinterface_qpa.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.h b/src/gui/kernel/qplatformnativeinterface_qpa.h
index 5ea2c13..b9d0619 100644
--- a/src/gui/kernel/qplatformnativeinterface_qpa.h
+++ b/src/gui/kernel/qplatformnativeinterface_qpa.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
index 19bf7a9..f3654b6 100644
--- a/src/gui/kernel/qplatformwindow_qpa.cpp
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -150,7 +150,7 @@ void QPlatformWindow::setParent(const QPlatformWindow *parent)
/*!
Reimplement to set the window title to \a title
*/
-void QPlatformWindow::setWindowTitle(const QString &title) {}
+void QPlatformWindow::setWindowTitle(const QString &) {}
/*!
Reimplement to be able to let Qt rais windows to the top of the desktop
diff --git a/src/gui/kernel/qplatformwindowformat_qpa.cpp b/src/gui/kernel/qplatformwindowformat_qpa.cpp
index ddc6239..c165c85 100644
--- a/src/gui/kernel/qplatformwindowformat_qpa.cpp
+++ b/src/gui/kernel/qplatformwindowformat_qpa.cpp
@@ -53,7 +53,7 @@ public:
, opts(QPlatformWindowFormat::DoubleBuffer | QPlatformWindowFormat::DepthBuffer
| QPlatformWindowFormat::Rgba | QPlatformWindowFormat::DirectRendering
| QPlatformWindowFormat::StencilBuffer | QPlatformWindowFormat::DeprecatedFunctions
- | QPlatformWindowFormat::UseDefaultSharedContext | QPlatformWindowFormat::HasWindowSurface)
+ | QPlatformWindowFormat::HasWindowSurface)
, depthSize(-1)
, accumSize(-1)
, stencilSize(-1)
@@ -525,16 +525,6 @@ void QPlatformWindowFormat::setSampleBuffers(bool enable)
setOption(enable ? QPlatformWindowFormat::SampleBuffers : QPlatformWindowFormat::NoSampleBuffers);
}
-void QPlatformWindowFormat::setUseDefaultSharedContext(bool enable)
-{
- if (enable) {
- setOption(QPlatformWindowFormat::UseDefaultSharedContext);
- d->sharedContext = 0;
- } else {
- setOption(QPlatformWindowFormat::NoDefaultSharedContext);
- }
-}
-
/*!
Returns the number of samples per pixel when multisampling is
enabled. By default, the highest number of samples that is
@@ -613,7 +603,6 @@ QPlatformWindowFormat::WindowApi QPlatformWindowFormat::windowApi() const
void QPlatformWindowFormat::setSharedContext(QPlatformGLContext *context)
{
- setUseDefaultSharedContext(false);
d->sharedContext = context;
}
diff --git a/src/gui/kernel/qplatformwindowformat_qpa.h b/src/gui/kernel/qplatformwindowformat_qpa.h
index fa01a8a..ba21ba4 100644
--- a/src/gui/kernel/qplatformwindowformat_qpa.h
+++ b/src/gui/kernel/qplatformwindowformat_qpa.h
@@ -66,8 +66,7 @@ public:
HasOverlay = 0x0100,
SampleBuffers = 0x0200,
DeprecatedFunctions = 0x0400,
- UseDefaultSharedContext = 0x0800,
- HasWindowSurface = 0x1000,
+ HasWindowSurface = 0x0800,
SingleBuffer = DoubleBuffer << 16,
NoDepthBuffer = DepthBuffer << 16,
ColorIndex = Rgba << 16,
@@ -79,7 +78,6 @@ public:
NoOverlay = HasOverlay << 16,
NoSampleBuffers = SampleBuffers << 16,
NoDeprecatedFunctions = DeprecatedFunctions << 16,
- NoDefaultSharedContext = UseDefaultSharedContext << 16,
NoWindowSurface = HasWindowSurface << 16
};
@@ -149,8 +147,6 @@ public:
void setStereo(bool enable);
bool directRendering() const;
void setDirectRendering(bool enable);
- bool useDefaultSharedContext() const;
- void setUseDefaultSharedContext(bool enable);
bool hasWindowSurface() const;
void setWindowSurface(bool enable);
@@ -231,11 +227,6 @@ inline bool QPlatformWindowFormat::sampleBuffers() const
return testOption(QPlatformWindowFormat::SampleBuffers);
}
-inline bool QPlatformWindowFormat::useDefaultSharedContext() const
-{
- return testOption(QPlatformWindowFormat::UseDefaultSharedContext);
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qsessionmanager_qpa.cpp b/src/gui/kernel/qsessionmanager_qpa.cpp
new file mode 100644
index 0000000..68685b4
--- /dev/null
+++ b/src/gui/kernel/qsessionmanager_qpa.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qsessionmanager.h>
+
+#include <private/qobject_p.h>
+#include <qapplication.h>
+
+#ifndef QT_NO_SESSIONMANAGER
+
+QT_BEGIN_NAMESPACE
+
+class QSessionManagerPrivate : public QObjectPrivate
+{
+public:
+ QSessionManagerPrivate(QSessionManager *m, const QString &id,
+ const QString &key);
+
+ QStringList restartCommand;
+ QStringList discardCommand;
+ const QString sessionId;
+ const QString sessionKey;
+ QSessionManager::RestartHint restartHint;
+};
+
+QSessionManagerPrivate::QSessionManagerPrivate(QSessionManager*,
+ const QString &id,
+ const QString &key)
+ : QObjectPrivate(), sessionId(id), sessionKey(key)
+{
+}
+
+QSessionManager::QSessionManager(QApplication *app, QString &id, QString &key)
+ : QObject(*(new QSessionManagerPrivate(this, id, key)), app)
+{
+ Q_D(QSessionManager);
+ d->restartHint = RestartIfRunning;
+}
+
+QSessionManager::~QSessionManager()
+{
+}
+
+QString QSessionManager::sessionId() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionId;
+}
+
+QString QSessionManager::sessionKey() const
+{
+ Q_D(const QSessionManager);
+ return d->sessionKey;
+}
+
+
+bool QSessionManager::allowsInteraction()
+{
+ return false;
+}
+
+bool QSessionManager::allowsErrorInteraction()
+{
+ return false;
+}
+
+void QSessionManager::release()
+{
+}
+
+void QSessionManager::cancel()
+{
+}
+
+void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
+{
+ Q_D(QSessionManager);
+ d->restartHint = hint;
+}
+
+QSessionManager::RestartHint QSessionManager::restartHint() const
+{
+ Q_D(const QSessionManager);
+ return d->restartHint;
+}
+
+void QSessionManager::setRestartCommand(const QStringList &command)
+{
+ Q_D(QSessionManager);
+ d->restartCommand = command;
+}
+
+QStringList QSessionManager::restartCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->restartCommand;
+}
+
+void QSessionManager::setDiscardCommand(const QStringList &command)
+{
+ Q_D(QSessionManager);
+ d->discardCommand = command;
+}
+
+QStringList QSessionManager::discardCommand() const
+{
+ Q_D(const QSessionManager);
+ return d->discardCommand;
+}
+
+void QSessionManager::setManagerProperty(const QString &name,
+ const QString &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+void QSessionManager::setManagerProperty(const QString &name,
+ const QStringList &value)
+{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+bool QSessionManager::isPhase2() const
+{
+ return false;
+}
+
+void QSessionManager::requestPhase2()
+{
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SESSIONMANAGER
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index 102c0ca..02977ce 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -77,6 +77,10 @@
#include <akncontext.h> // CAknContextPane
#include <eikspane.h> // CEikStatusPane
#include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader
+#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen
+#ifdef QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H
+#include <akntranseffect.h> // BeginFullScreen
+#endif
#endif
QT_BEGIN_NAMESPACE
@@ -85,11 +89,18 @@ QT_BEGIN_NAMESPACE
// system events seems to start with 0x10
const TInt KInternalStatusPaneChange = 0x50000000;
+// For BeginFullScreen().
+const TUint KQtAppExitFlag = 0x400;
+
static const int qt_symbian_max_screens = 4;
//this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2
#define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13)
+class QSymbianTypeFaceExtras;
+typedef QHash<QString, const QSymbianTypeFaceExtras *> QSymbianTypeFaceExtrasHash;
+typedef void (*QThreadLocalReleaseFunc)();
+
class Q_AUTOTEST_EXPORT QS60ThreadLocalData
{
public:
@@ -98,6 +109,8 @@ public:
bool usingCONEinstances;
RWsSession wsSession;
CWsScreenDevice *screenDevice;
+ QSymbianTypeFaceExtrasHash fontData;
+ QVector<QThreadLocalReleaseFunc> releaseFuncs;
};
class QS60Data
@@ -168,6 +181,8 @@ public:
inline CWsScreenDevice* screenDevice(const QWidget *widget);
inline CWsScreenDevice* screenDevice(int screenNumber);
static inline int screenNumberForWidget(const QWidget *widget);
+ inline QSymbianTypeFaceExtrasHash& fontData();
+ inline void addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func);
static inline CCoeAppUi* appUi();
static inline CEikMenuBar* menuBar();
#ifdef Q_WS_S60
@@ -178,6 +193,7 @@ public:
static inline CEikButtonGroupContainer* buttonGroupContainer();
static inline void setButtonGroupContainer(CEikButtonGroupContainer* newCba);
static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible);
+ static bool setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState);
#endif
static void controlVisibilityChanged(CCoeControl *control, bool visible);
@@ -190,7 +206,11 @@ public:
int screenWidthInTwipsForScreen[qt_symbian_max_screens];
int screenHeightInTwipsForScreen[qt_symbian_max_screens];
- bool nativeOrientationIsPortrait;
+ int nativeScreenWidthInPixels;
+ int nativeScreenHeightInPixels;
+
+ int beginFullScreenCalled : 1;
+ int endFullScreenCalled : 1;
};
Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data();
@@ -236,6 +256,8 @@ public:
bool isControlActive();
void ensureFixNativeOrientation();
+ QPoint translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const;
+ TRect translateRectForFixedNativeOrientation(const TRect &controlRect) const;
#ifdef Q_WS_S60
void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); }
@@ -255,6 +277,9 @@ protected:
void PositionChanged();
void FocusChanged(TDrawNow aDrawNow);
+protected:
+ void qwidgetResize_helper(const QSize &newSize);
+
private:
void HandlePointerEvent(const TPointerEvent& aPointerEvent);
TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType);
@@ -294,6 +319,7 @@ private:
#endif
bool m_inExternalScreenOverride : 1;
+ bool m_lastStatusPaneVisibility : 1;
};
inline QS60Data::QS60Data()
@@ -326,6 +352,8 @@ inline QS60Data::QS60Data()
#ifdef Q_OS_SYMBIAN
,s60InstalledTrapHandler(0)
#endif
+ ,beginFullScreenCalled(0),
+ endFullScreenCalled(0)
{
}
@@ -361,18 +389,15 @@ inline void QS60Data::updateScreenSize()
// Look for a screen mode with rotation 0
// in order to decide what the native orientation is.
- int nativeScreenWidthInPixels = 0;
- int nativeScreenHeightInPixels = 0;
for (mode = 0; mode < screenModeCount; ++mode) {
TPixelsAndRotation sizeAndRotation;
dev->GetScreenModeSizeAndRotation(mode, sizeAndRotation);
if (sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal) {
- nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth;
- nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight;
+ S60->nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth;
+ S60->nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight;
break;
}
}
- S60->nativeOrientationIsPortrait = nativeScreenWidthInPixels <= nativeScreenHeightInPixels;
}
inline RWsSession& QS60Data::wsSession()
@@ -453,6 +478,24 @@ inline int QS60Data::screenNumberForWidget(const QWidget *widget)
return qt_widget_private(const_cast<QWidget *>(w))->symbianScreenNumber;
}
+inline QSymbianTypeFaceExtrasHash& QS60Data::fontData()
+{
+ if (!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ return tls.localData()->fontData;
+}
+
+inline void QS60Data::addThreadLocalReleaseFunc(QThreadLocalReleaseFunc func)
+{
+ if (!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ QS60ThreadLocalData *data = tls.localData();
+ if (!data->releaseFuncs.contains(func))
+ data->releaseFuncs.append(func);
+}
+
inline CCoeAppUi* QS60Data::appUi()
{
return CCoeEnv::Static()-> AppUi();
@@ -560,6 +603,49 @@ void qt_symbian_set_cursor_visible(bool visible);
bool qt_symbian_is_cursor_visible();
#endif
+static inline bool qt_beginFullScreenEffect()
+{
+#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H)
+ // Only for post-S^3. On earlier versions the system transition effects
+ // may not be able to capture the non-Avkon content, leading to confusing
+ // looking effects, so just skip the whole thing.
+ if (S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2)
+ return false;
+ S60->beginFullScreenCalled = true;
+ // For Avkon apps the app-exit effect is triggered from CAknAppUi::PrepareToExit().
+ // That is good for Avkon apps, but in case of Qt the RWindows are destroyed earlier.
+ // Therefore we call BeginFullScreen() ourselves.
+ GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit,
+ TRect(0, 0, 0, 0),
+ AknTransEffect::EParameterType,
+ AknTransEffect::GfxTransParam(S60->uid,
+ AknTransEffect::TParameter::EAvkonCheck | KQtAppExitFlag));
+ return true;
+#else
+ return false;
+#endif
+}
+
+static inline void qt_abortFullScreenEffect()
+{
+#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H)
+ if (!S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2)
+ return;
+ GfxTransEffect::AbortFullScreen();
+ S60->beginFullScreenCalled = S60->endFullScreenCalled = false;
+#endif
+}
+
+static inline void qt_endFullScreenEffect()
+{
+#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H)
+ if (S60->endFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2)
+ return;
+ S60->endFullScreenCalled = true;
+ GfxTransEffect::EndFullScreen();
+#endif
+}
+
QT_END_NAMESPACE
#endif // QT_S60_P_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 3cc3e65..80d7b85 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -613,7 +613,6 @@ void QWidget::setAutoFillBackground(bool enabled)
\ingroup basicwidgets
-
The widget is the atom of the user interface: it receives mouse, keyboard
and other events from the window system, and paints a representation of
itself on the screen. Every widget is rectangular, and they are sorted in a
@@ -1589,6 +1588,7 @@ QWidget::~QWidget()
// delete layout while we still are a valid widget
delete d->layout;
+ d->layout = 0;
// Remove myself from focus list
Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
@@ -11206,6 +11206,7 @@ void QWidget::setAccessibleName(const QString &name)
{
Q_D(QWidget);
d->accessibleName = name;
+ QAccessible::updateAccessibility(this, 0, QAccessible::NameChanged);
}
QString QWidget::accessibleName() const
@@ -11227,6 +11228,7 @@ void QWidget::setAccessibleDescription(const QString &description)
{
Q_D(QWidget);
d->accessibleDescription = description;
+ QAccessible::updateAccessibility(this, 0, QAccessible::DescriptionChanged);
}
QString QWidget::accessibleDescription() const
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 34918e4..354f05b 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -2849,6 +2849,11 @@ void QWidgetPrivate::transferChildren()
#ifdef QT_MAC_USE_COCOA
void QWidgetPrivate::setSubWindowStacking(bool set)
{
+ // After hitting too many unforeseen bugs trying to put Qt on top of the cocoa child
+ // window API, we have decided to revert this behaviour as much as we can. We
+ // therefore now only allow child windows to exist for children of modal dialogs.
+ static bool use_behaviour_qt473 = !qgetenv("QT_MAC_USE_CHILDWINDOWS").isEmpty();
+
// This will set/remove a visual relationship between parent and child on screen.
// The reason for doing this is to ensure that a child always stacks infront of
// its parent. Unfortunatly is turns out that [NSWindow addChildWindow] has
@@ -2877,7 +2882,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set)
if (NSWindow *pwin = [qt_mac_nativeview_for(parent) window]) {
if (set) {
Qt::WindowType ptype = parent->window()->windowType();
- if ([pwin isVisible] && (ptype == Qt::Window || ptype == Qt::Dialog) && ![qwin parentWindow]) {
+ if ([pwin isVisible]
+ && (ptype == Qt::Window || ptype == Qt::Dialog)
+ && ![qwin parentWindow]
+ && (use_behaviour_qt473 || parent->windowModality() == Qt::ApplicationModal)) {
NSInteger level = [qwin level];
[pwin addChildWindow:qwin ordered:NSWindowAbove];
if ([qwin level] < level)
@@ -2889,6 +2897,10 @@ void QWidgetPrivate::setSubWindowStacking(bool set)
}
}
+ // Only set-up child windows for q if q is modal:
+ if (set && !use_behaviour_qt473 && q->windowModality() != Qt::ApplicationModal)
+ return;
+
QObjectList widgets = q->children();
for (int i=0; i<widgets.size(); ++i) {
QWidget *child = qobject_cast<QWidget *>(widgets.at(i));
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index c74c7eb..12bcc4b 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -239,7 +239,16 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (w != oldSize.width() || h != oldSize.height())
data.window_state &= ~Qt::WindowMaximized;
- if (extra) { // any size restrictions?
+ bool checkExtra = true;
+ if (q->isWindow() && (data.window_state & Qt::WindowFullScreen)) {
+ // Do not modity window size for fullscreen windows, if requested
+ // size is already equal to clientRect.
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ if (w == r.Width() && h == r.Height())
+ checkExtra = false;
+ }
+
+ if (checkExtra && extra) { // any size restrictions?
w = qMin(w,extra->maxw);
h = qMin(h,extra->maxh);
w = qMax(w,extra->minw);
@@ -842,6 +851,8 @@ void QWidgetPrivate::s60UpdateIsOpaque()
// recreate backing store to get translucent surface (raster surface).
extra->topextra->backingStore.create(q);
extra->topextra->backingStore.registerWidget(q);
+ // FixNativeOrientation() will not work without an EGL surface.
+ q->setAttribute(Qt::WA_SymbianNoSystemRotation, false);
}
}
} else if (extra->topextra->nativeWindowTransparencyEnabled) {
@@ -1210,41 +1221,10 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
}
#ifdef Q_WS_S60
- // Hide window decoration when switching to fullscreen / minimized otherwise show decoration.
// The window decoration visibility has to be changed before doing actual window state
// change since in that order the availableGeometry will return directly the right size and
// we will avoid unnecessary redraws
- Qt::WindowStates comparisonState = newstate;
- QWidget *parentWindow = parentWidget();
- if (parentWindow) {
- while (parentWindow->parentWidget())
- parentWindow = parentWindow->parentWidget();
- comparisonState = parentWindow->windowState();
- } else {
- parentWindow = this;
- }
-
- const bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized));
- const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen;
- const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint;
- bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint));
-
- // For non-toplevel normal and maximized windows, show cba if window has softkey
- // actions even if topmost parent is not showing cba. Do the same for fullscreen
- // windows that request it.
- if (!buttonGroupVisibility
- && parentWidget()
- && !(newstate & Qt::WindowMinimized)
- && ((windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(newstate & Qt::WindowFullScreen))) {
- for (int i = 0; i < actions().size(); ++i) {
- if (actions().at(i)->softKeyRole() != QAction::NoSoftKey) {
- buttonGroupVisibility = true;
- break;
- }
- }
- }
- S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility);
-
+ bool decorationsVisible = S60->setRecursiveDecorationsVisibility(this, newstate);
#endif // Q_WS_S60
// Ensure the initial size is valid, since we store it as normalGeometry below.
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 5ece7d6..3eec5c7 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -486,8 +486,6 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
bool topLevel = (flags & Qt::Window);
bool popup = (type == Qt::Popup);
- bool dialog = (type == Qt::Dialog
- || type == Qt::Sheet);
bool desktop = (type == Qt::Desktop);
bool tool = (type == Qt::Tool || type == Qt::SplashScreen
|| type == Qt::ToolTip || type == Qt::Drawer);
@@ -553,7 +551,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
int sh = DisplayHeight(dpy,scr);
if (desktop) { // desktop widget
- dialog = popup = false; // force these flags off
+ popup = false; // force these flags off
data.crect.setRect(0, 0, sw, sh);
} else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
QDesktopWidget *desktopWidget = qApp->desktop();
@@ -954,8 +952,13 @@ static void qt_x11_recreateWidget(QWidget *widget)
// recreate their GL context, which in turn causes them to choose
// their visual again. Now that WA_TranslucentBackground is set,
// QGLContext::chooseVisual will select an ARGB visual.
- QEvent e(QEvent::ParentChange);
- QApplication::sendEvent(widget, &e);
+
+ // QGLWidget expects a ParentAboutToChange to be sent first
+ QEvent aboutToChangeEvent(QEvent::ParentAboutToChange);
+ QApplication::sendEvent(widget, &aboutToChangeEvent);
+
+ QEvent parentChangeEvent(QEvent::ParentChange);
+ QApplication::sendEvent(widget, &parentChangeEvent);
} else {
// For regular widgets, reparent them with their parent which
// also triggers a recreation of the native window
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index 119cf1c..a2f0edd 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -65,13 +65,6 @@ QT_BEGIN_NAMESPACE
#define M_SQRT2 1.41421356237309504880
#endif
-#define log2(x) (qLn(x)/qLn(2.))
-
-static inline qreal log4(qreal x)
-{
- return qreal(0.5) * log2(x);
-}
-
/*!
\internal
*/
@@ -184,7 +177,7 @@ static inline bool findInflections(qreal a, qreal b, qreal c,
*t2 = r1;
}
if (!qFuzzyIsNull(a))
- *tCups = 0.5 * (-b / a);
+ *tCups = qreal(0.5) * (-b / a);
else
*tCups = 2;
@@ -274,8 +267,8 @@ static ShiftResult good_offset(const QBezier *b1, const QBezier *b2, qreal offse
const qreal o2 = offset*offset;
const qreal max_dist_line = threshold*offset*offset;
const qreal max_dist_normal = threshold*offset;
- const qreal spacing = 0.25;
- for (qreal i = spacing; i < 0.99; i += spacing) {
+ const qreal spacing = qreal(0.25);
+ for (qreal i = spacing; i < qreal(0.99); i += spacing) {
QPointF p1 = b1->pointAt(i);
QPointF p2 = b2->pointAt(i);
qreal d = (p1.x() - p2.x())*(p1.x() - p2.x()) + (p1.y() - p2.y())*(p1.y() - p2.y());
@@ -284,7 +277,7 @@ static ShiftResult good_offset(const QBezier *b1, const QBezier *b2, qreal offse
QPointF normalPoint = b1->normalVector(i);
qreal l = qAbs(normalPoint.x()) + qAbs(normalPoint.y());
- if (l != 0.) {
+ if (l != qreal(0.0)) {
d = qAbs( normalPoint.x()*(p1.y() - p2.y()) - normalPoint.y()*(p1.x() - p2.x()) ) / l;
if (d > max_dist_normal)
return Split;
@@ -350,7 +343,7 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr
QPointF normal_sum = prev_normal + next_normal;
- qreal r = 1.0 + prev_normal.x() * next_normal.x()
+ qreal r = qreal(1.0) + prev_normal.x() * next_normal.x()
+ prev_normal.y() * next_normal.y();
if (qFuzzyIsNull(r)) {
@@ -374,7 +367,7 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr
// This value is used to determine the length of control point vectors
// when approximating arc segments as curves. The factor is multiplied
// with the radius of the circle.
-#define KAPPA 0.5522847498
+#define KAPPA qreal(0.5522847498)
static bool addCircle(const QBezier *b, qreal offset, QBezier *o)
@@ -417,11 +410,11 @@ static bool addCircle(const QBezier *b, qreal offset, QBezier *o)
QPointF circle[3];
circle[0] = QPointF(b->x1, b->y1) + normals[0]*offset;
- circle[1] = QPointF(0.5*(b->x1 + b->x4), 0.5*(b->y1 + b->y4)) + normals[1]*offset;
+ circle[1] = QPointF(qreal(0.5)*(b->x1 + b->x4), qreal(0.5)*(b->y1 + b->y4)) + normals[1]*offset;
circle[2] = QPointF(b->x4, b->y4) + normals[2]*offset;
for (int i = 0; i < 2; ++i) {
- qreal kappa = 2.*KAPPA * sign * offset * angles[i];
+ qreal kappa = qreal(2.0) * KAPPA * sign * offset * angles[i];
o->x1 = circle[i].x();
o->y1 = circle[i].y();
@@ -456,8 +449,8 @@ redo:
while (b >= beziers) {
int stack_segments = b - beziers + 1;
if ((stack_segments == 10) || (o - curveSegments == maxSegments - stack_segments)) {
- threshold *= 1.5;
- if (threshold > 2.)
+ threshold *= qreal(1.5);
+ if (threshold > qreal(2.0))
goto give_up;
goto redo;
}
@@ -535,7 +528,7 @@ static inline void splitBezierAt(const QBezier &bez, qreal t,
qreal QBezier::length(qreal error) const
{
- qreal length = 0.0;
+ qreal length = qreal(0.0);
addIfClose(&length, error);
@@ -546,8 +539,8 @@ void QBezier::addIfClose(qreal *length, qreal error) const
{
QBezier left, right; /* bez poly splits */
- qreal len = 0.0; /* arc length */
- qreal chord; /* chord length */
+ qreal len = qreal(0.0); /* arc length */
+ qreal chord; /* chord length */
len = len + QLineF(QPointF(x1, y1),QPointF(x2, y2)).length();
len = len + QLineF(QPointF(x2, y2),QPointF(x3, y3)).length();
@@ -589,7 +582,7 @@ qreal QBezier::tForY(qreal t0, qreal t1, qreal y) const
qreal lt = t0;
qreal dt;
do {
- qreal t = 0.5 * (t0 + t1);
+ qreal t = qreal(0.5) * (t0 + t1);
qreal a, b, c, d;
QBezier::coefficients(t, a, b, c, d);
@@ -604,7 +597,7 @@ qreal QBezier::tForY(qreal t0, qreal t1, qreal y) const
}
dt = lt - t;
lt = t;
- } while (qAbs(dt) > 1e-7);
+ } while (qAbs(dt) > qreal(1e-7));
return t0;
}
@@ -661,15 +654,15 @@ int QBezier::stationaryYPoints(qreal &t0, qreal &t1) const
qreal QBezier::tAtLength(qreal l) const
{
qreal len = length();
- qreal t = 1.0;
- const qreal error = (qreal)0.01;
+ qreal t = qreal(1.0);
+ const qreal error = qreal(0.01);
if (l > len || qFuzzyCompare(l, len))
return t;
- t *= 0.5;
+ t *= qreal(0.5);
//int iters = 0;
//qDebug()<<"LEN is "<<l<<len;
- qreal lastBigger = 1.;
+ qreal lastBigger = qreal(1.0);
while (1) {
//qDebug()<<"\tt is "<<t;
QBezier right = *this;
@@ -680,10 +673,10 @@ qreal QBezier::tAtLength(qreal l) const
break;
if (lLen < l) {
- t += (lastBigger - t)*.5;
+ t += (lastBigger - t) * qreal(0.5);
} else {
lastBigger = t;
- t -= t*.5;
+ t -= t * qreal(0.5);
}
//++iters;
}
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
index 8aff912..81f8b70 100644
--- a/src/gui/painting/qblendfunctions_p.h
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -275,8 +275,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
int dx_l = int(leftSlope * 0x10000);
int dx_r = int(rightSlope * 0x10000);
- int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000);
- int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000);
+ int x_l = int((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
+ int x_r = int((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
int fromX, toX, x1, x2, u, v, i, ii;
DestT *line;
@@ -471,8 +471,8 @@ void qt_transform_image(DestT *destPixels, int dbpl,
int dvdx = int(m21 * 0x10000);
int dudy = int(m12 * 0x10000);
int dvdy = int(m22 * 0x10000);
- int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1;
- int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1;
+ int u0 = qCeil((qreal(0.5) * m11 + qreal(0.5) * m12 + mdx) * 0x10000) - 1;
+ int v0 = qCeil((qreal(0.5) * m21 + qreal(0.5) * m22 + mdy) * 0x10000) - 1;
int x1 = qFloor(sourceRect.left());
int y1 = qFloor(sourceRect.top());
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 811f3ae..3ff7eb8 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -49,6 +49,7 @@
#include "qdebug.h"
#include <QtCore/qcoreapplication.h>
#include "private/qstylehelper_p.h"
+#include <QtCore/qnumeric.h>
QT_BEGIN_NAMESPACE
@@ -839,6 +840,22 @@ const QGradient *QBrush::gradient() const
return 0;
}
+Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush)
+{
+ if (brush.style() == Qt::RadialGradientPattern) {
+ const QGradient *g = brush.gradient();
+ const QRadialGradient *rg = static_cast<const QRadialGradient *>(g);
+
+ if (!qFuzzyIsNull(rg->focalRadius()))
+ return true;
+
+ QPointF delta = rg->focalPoint() - rg->center();
+ if (delta.x() * delta.x() + delta.y() * delta.y() > rg->radius() * rg->radius())
+ return true;
+ }
+
+ return false;
+}
/*!
Returns true if the brush is fully opaque otherwise false. A brush
@@ -848,6 +865,7 @@ const QGradient *QBrush::gradient() const
\i The alpha component of the color() is 255.
\i Its texture() does not have an alpha channel and is not a QBitmap.
\i The colors in the gradient() all have an alpha component that is 255.
+ \i It is an extended radial gradient.
\endlist
*/
@@ -859,6 +877,9 @@ bool QBrush::isOpaque() const
if (d->style == Qt::SolidPattern)
return opaqueColor;
+ if (qt_isExtendedRadialGradient(*this))
+ return false;
+
if (d->style == Qt::LinearGradientPattern
|| d->style == Qt::RadialGradientPattern
|| d->style == Qt::ConicalGradientPattern) {
@@ -1208,8 +1229,10 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
\list
\o \e Linear gradients interpolate colors between start and end points.
- \o \e Radial gradients interpolate colors between a focal point and end
- points on a circle surrounding it.
+ \o \e Simple radial gradients interpolate colors between a focal point
+ and end points on a circle surrounding it.
+ \o \e Extended radial gradients interpolate colors between a center and
+ a focal circle.
\o \e Conical gradients interpolate colors around a center point.
\endlist
@@ -1369,13 +1392,14 @@ QGradient::QGradient()
void QGradient::setColorAt(qreal pos, const QColor &color)
{
- if (pos > 1 || pos < 0) {
+ if ((pos > 1 || pos < 0) && !qIsNaN(pos)) {
qWarning("QGradient::setColorAt: Color position must be specified in the range 0 to 1");
return;
}
int index = 0;
- while (index < m_stops.size() && m_stops.at(index).first < pos) ++index;
+ if (!qIsNaN(pos))
+ while (index < m_stops.size() && m_stops.at(index).first < pos) ++index;
if (index < m_stops.size() && m_stops.at(index).first == pos)
m_stops[index].second = color;
@@ -1504,8 +1528,6 @@ void QGradient::setInterpolationMode(InterpolationMode mode)
dummy = p;
}
-#undef Q_DUMMY_ACCESSOR
-
/*!
\fn bool QGradient::operator!=(const QGradient &gradient) const
\since 4.2
@@ -1539,7 +1561,7 @@ bool QGradient::operator==(const QGradient &gradient) const
|| m_data.radial.cy != gradient.m_data.radial.cy
|| m_data.radial.fx != gradient.m_data.radial.fx
|| m_data.radial.fy != gradient.m_data.radial.fy
- || m_data.radial.radius != gradient.m_data.radial.radius)
+ || m_data.radial.cradius != gradient.m_data.radial.cradius)
return false;
} else { // m_type == ConicalGradient
if (m_data.conical.cx != gradient.m_data.conical.cx
@@ -1745,10 +1767,17 @@ void QLinearGradient::setFinalStop(const QPointF &stop)
\brief The QRadialGradient class is used in combination with QBrush to
specify a radial gradient brush.
- Radial gradients interpolate colors between a focal point and end
- points on a circle surrounding it. Outside the end points the
- gradient is either padded, reflected or repeated depending on the
- currently set \l {QGradient::Spread}{spread} method:
+ Qt supports both simple and extended radial gradients.
+
+ Simple radial gradients interpolate colors between a focal point and end
+ points on a circle surrounding it. Extended radial gradients interpolate
+ colors between a focal circle and a center circle. Points outside the cone
+ defined by the two circles will be transparent. For simple radial gradients
+ the focal point is adjusted to lie inside the center circle, whereas the
+ focal point can have any position in an extended radial gradient.
+
+ Outside the end points the gradient is either padded, reflected or repeated
+ depending on the currently set \l {QGradient::Spread}{spread} method:
\table
\row
@@ -1785,7 +1814,7 @@ static QPointF qt_radial_gradient_adapt_focal_point(const QPointF &center,
// We have a one pixel buffer zone to avoid numerical instability on the
// circle border
//### this is hacky because technically we should adjust based on current matrix
- const qreal compensated_radius = radius - radius * 0.001;
+ const qreal compensated_radius = radius - radius * qreal(0.001);
QLineF line(center, focalPoint);
if (line.length() > (compensated_radius))
line.setLength(compensated_radius);
@@ -1793,9 +1822,14 @@ static QPointF qt_radial_gradient_adapt_focal_point(const QPointF &center,
}
/*!
- Constructs a radial gradient with the given \a center, \a
+ Constructs a simple radial gradient with the given \a center, \a
radius and \a focalPoint.
+ \note If the given focal point is outside the circle defined by the
+ center (\a cx, \a cy) and the \a radius it will be re-adjusted to
+ the intersection between the line from the center to the focal point
+ and the circle.
+
\sa QGradient::setColorAt(), QGradient::setStops()
*/
@@ -1805,7 +1839,7 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPoi
m_spread = PadSpread;
m_data.radial.cx = center.x();
m_data.radial.cy = center.y();
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(center, radius, focalPoint);
m_data.radial.fx = adapted_focal.x();
@@ -1813,7 +1847,7 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPoi
}
/*!
- Constructs a radial gradient with the given \a center, \a
+ Constructs a simple radial gradient with the given \a center, \a
radius and the focal point in the circle center.
\sa QGradient::setColorAt(), QGradient::setStops()
@@ -1824,16 +1858,21 @@ QRadialGradient::QRadialGradient(const QPointF &center, qreal radius)
m_spread = PadSpread;
m_data.radial.cx = center.x();
m_data.radial.cy = center.y();
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
m_data.radial.fx = center.x();
m_data.radial.fy = center.y();
}
/*!
- Constructs a radial gradient with the given center (\a cx, \a cy),
+ Constructs a simple radial gradient with the given center (\a cx, \a cy),
\a radius and focal point (\a fx, \a fy).
+ \note If the given focal point is outside the circle defined by the
+ center (\a cx, \a cy) and the \a radius it will be re-adjusted to
+ the intersection between the line from the center to the focal point
+ and the circle.
+
\sa QGradient::setColorAt(), QGradient::setStops()
*/
@@ -1843,7 +1882,7 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qre
m_spread = PadSpread;
m_data.radial.cx = cx;
m_data.radial.cy = cy;
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(QPointF(cx, cy),
radius,
@@ -1854,7 +1893,7 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qre
}
/*!
- Constructs a radial gradient with the center at (\a cx, \a cy) and the
+ Constructs a simple radial gradient with the center at (\a cx, \a cy) and the
specified \a radius. The focal point lies at the center of the circle.
\sa QGradient::setColorAt(), QGradient::setStops()
@@ -1865,14 +1904,14 @@ QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius)
m_spread = PadSpread;
m_data.radial.cx = cx;
m_data.radial.cy = cy;
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
m_data.radial.fx = cx;
m_data.radial.fy = cy;
}
/*!
- Constructs a radial gradient with the center and focal point at
+ Constructs a simple radial gradient with the center and focal point at
(0, 0) with a radius of 1.
*/
QRadialGradient::QRadialGradient()
@@ -1881,11 +1920,51 @@ QRadialGradient::QRadialGradient()
m_spread = PadSpread;
m_data.radial.cx = 0;
m_data.radial.cy = 0;
- m_data.radial.radius = 1;
+ m_data.radial.cradius = 1;
m_data.radial.fx = 0;
m_data.radial.fy = 0;
}
+/*!
+ \since 4.8
+
+ Constructs an extended radial gradient with the given \a center, \a
+ centerRadius, \a focalPoint, and \a focalRadius.
+*/
+QRadialGradient::QRadialGradient(const QPointF &center, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius)
+{
+ m_type = RadialGradient;
+ m_spread = PadSpread;
+ m_data.radial.cx = center.x();
+ m_data.radial.cy = center.y();
+ m_data.radial.cradius = centerRadius;
+
+ m_data.radial.fx = focalPoint.x();
+ m_data.radial.fy = focalPoint.y();
+ setFocalRadius(focalRadius);
+}
+
+/*!
+ \since 4.8
+
+ Constructs an extended radial gradient with the given \a center, \a
+ centerRadius, \a focalPoint, and \a focalRadius.
+ Constructs a radial gradient with the given center (\a cx, \a cy),
+ center radius \a centerRadius, focal point (\a fx, \a fy), and
+ focal radius \a focalRadius.
+*/
+QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius)
+{
+ m_type = RadialGradient;
+ m_spread = PadSpread;
+ m_data.radial.cx = cx;
+ m_data.radial.cy = cy;
+ m_data.radial.cradius = centerRadius;
+
+ m_data.radial.fx = fx;
+ m_data.radial.fy = fy;
+ setFocalRadius(focalRadius);
+}
/*!
Returns the center of this radial gradient in logical coordinates.
@@ -1930,13 +2009,15 @@ void QRadialGradient::setCenter(const QPointF &center)
/*!
Returns the radius of this radial gradient in logical coordinates.
+ Equivalent to centerRadius()
+
\sa QGradient::stops()
*/
qreal QRadialGradient::radius() const
{
Q_ASSERT(m_type == RadialGradient);
- return m_data.radial.radius;
+ return m_data.radial.cradius;
}
@@ -1945,13 +2026,81 @@ qreal QRadialGradient::radius() const
Sets the radius of this radial gradient in logical coordinates
to \a radius
+
+ Equivalent to setCenterRadius()
*/
void QRadialGradient::setRadius(qreal radius)
{
Q_ASSERT(m_type == RadialGradient);
- m_data.radial.radius = radius;
+ m_data.radial.cradius = radius;
+}
+
+/*!
+ \since 4.8
+
+ Returns the center radius of this radial gradient in logical
+ coordinates.
+
+ \sa QGradient::stops()
+*/
+qreal QRadialGradient::centerRadius() const
+{
+ Q_ASSERT(m_type == RadialGradient);
+ return m_data.radial.cradius;
+}
+
+/*
+ \since 4.8
+
+ Sets the center radius of this radial gradient in logical coordinates
+ to \a radius
+*/
+void QRadialGradient::setCenterRadius(qreal radius)
+{
+ Q_ASSERT(m_type == RadialGradient);
+ m_data.radial.cradius = radius;
+}
+
+/*!
+ \since 4.8
+
+ Returns the focal radius of this radial gradient in logical
+ coordinates.
+
+ \sa QGradient::stops()
+*/
+qreal QRadialGradient::focalRadius() const
+{
+ Q_ASSERT(m_type == RadialGradient);
+ Q_DUMMY_ACCESSOR
+
+ // mask away low three bits
+ union { float f; quint32 i; } u;
+ u.i = i & ~0x07;
+ return u.f;
}
+/*
+ \since 4.8
+
+ Sets the focal radius of this radial gradient in logical coordinates
+ to \a radius
+*/
+void QRadialGradient::setFocalRadius(qreal radius)
+{
+ Q_ASSERT(m_type == RadialGradient);
+ Q_DUMMY_ACCESSOR
+
+ // Since there's no QGradientData, we only have the dummy void * to
+ // store additional data in. The three lowest bits are already
+ // taken, thus we cut the three lowest bits from the significand
+ // and store the radius as a float.
+ union { float f; quint32 i; } u;
+ u.f = float(radius);
+ // add 0x04 to round up when we drop the three lowest bits
+ i |= (u.i + 0x04) & ~0x07;
+ dummy = p;
+}
/*!
Returns the focal point of this radial gradient in logical
@@ -2191,4 +2340,6 @@ void QConicalGradient::setAngle(qreal angle)
\sa setTransform()
*/
+#undef Q_DUMMY_ACCESSOR
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index 8b31319..d914c8c 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -255,6 +255,7 @@ private:
friend class QLinearGradient;
friend class QRadialGradient;
friend class QConicalGradient;
+ friend class QBrush;
Type m_type;
Spread m_spread;
@@ -264,7 +265,7 @@ private:
qreal x1, y1, x2, y2;
} linear;
struct {
- qreal cx, cy, fx, fy, radius;
+ qreal cx, cy, fx, fy, cradius;
} radial;
struct {
qreal cx, cy, angle;
@@ -303,6 +304,9 @@ public:
QRadialGradient(const QPointF &center, qreal radius);
QRadialGradient(qreal cx, qreal cy, qreal radius);
+ QRadialGradient(const QPointF &center, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius);
+ QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius);
+
QPointF center() const;
void setCenter(const QPointF &center);
inline void setCenter(qreal x, qreal y) { setCenter(QPointF(x, y)); }
@@ -313,6 +317,12 @@ public:
qreal radius() const;
void setRadius(qreal radius);
+
+ qreal centerRadius() const;
+ void setCenterRadius(qreal radius);
+
+ qreal focalRadius() const;
+ void setFocalRadius(qreal radius);
};
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 73a6ed8..ff6c24e 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -629,7 +629,7 @@ void QColor::getHsvF(qreal *h, qreal *s, qreal *v, qreal *a) const
return;
}
- *h = ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
+ *h = ct.ahsv.hue == USHRT_MAX ? qreal(-1.0) : ct.ahsv.hue / qreal(36000.0);
*s = ct.ahsv.saturation / qreal(USHRT_MAX);
*v = ct.ahsv.value / qreal(USHRT_MAX);
@@ -676,17 +676,17 @@ void QColor::getHsv(int *h, int *s, int *v, int *a) const
*/
void QColor::setHsvF(qreal h, qreal s, qreal v, qreal a)
{
- if (((h < 0.0 || h > 1.0) && h != -1.0)
- || (s < 0.0 || s > 1.0)
- || (v < 0.0 || v > 1.0)
- || (a < 0.0 || a > 1.0)) {
+ if (((h < qreal(0.0) || h > qreal(1.0)) && h != qreal(-1.0))
+ || (s < qreal(0.0) || s > qreal(1.0))
+ || (v < qreal(0.0) || v > qreal(1.0))
+ || (a < qreal(0.0) || a > qreal(1.0))) {
qWarning("QColor::setHsvF: HSV parameters out of range");
return;
}
cspec = Hsv;
ct.ahsv.alpha = qRound(a * USHRT_MAX);
- ct.ahsv.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
+ ct.ahsv.hue = h == qreal(-1.0) ? USHRT_MAX : qRound(h * 36000);
ct.ahsv.saturation = qRound(s * USHRT_MAX);
ct.ahsv.value = qRound(v * USHRT_MAX);
ct.ahsv.pad = 0;
@@ -740,7 +740,7 @@ void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const
return;
}
- *h = ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+ *h = ct.ahsl.hue == USHRT_MAX ? qreal(-1.0) : ct.ahsl.hue / qreal(36000.0);
*s = ct.ahsl.saturation / qreal(USHRT_MAX);
*l = ct.ahsl.lightness / qreal(USHRT_MAX);
@@ -790,17 +790,17 @@ void QColor::getHsl(int *h, int *s, int *l, int *a) const
*/
void QColor::setHslF(qreal h, qreal s, qreal l, qreal a)
{
- if (((h < 0.0 || h > 1.0) && h != -1.0)
- || (s < 0.0 || s > 1.0)
- || (l < 0.0 || l > 1.0)
- || (a < 0.0 || a > 1.0)) {
+ if (((h < qreal(0.0) || h > qreal(1.0)) && h != qreal(-1.0))
+ || (s < qreal(0.0) || s > qreal(1.0))
+ || (l < qreal(0.0) || l > qreal(1.0))
+ || (a < qreal(0.0) || a > qreal(1.0))) {
qWarning("QColor::setHsvF: HSV parameters out of range");
return;
}
cspec = Hsl;
ct.ahsl.alpha = qRound(a * USHRT_MAX);
- ct.ahsl.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
+ ct.ahsl.hue = h == qreal(-1.0) ? USHRT_MAX : qRound(h * 36000);
ct.ahsl.saturation = qRound(s * USHRT_MAX);
ct.ahsl.lightness = qRound(l * USHRT_MAX);
ct.ahsl.pad = 0;
@@ -909,10 +909,10 @@ void QColor::getRgb(int *r, int *g, int *b, int *a) const
*/
void QColor::setRgbF(qreal r, qreal g, qreal b, qreal a)
{
- if (r < 0.0 || r > 1.0
- || g < 0.0 || g > 1.0
- || b < 0.0 || b > 1.0
- || a < 0.0 || a > 1.0) {
+ if (r < qreal(0.0) || r > qreal(1.0)
+ || g < qreal(0.0) || g > qreal(1.0)
+ || b < qreal(0.0) || b > qreal(1.0)
+ || a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::setRgbF: RGB parameters out of range");
invalidate();
return;
@@ -1322,7 +1322,7 @@ qreal QColor::hsvHueF() const
{
if (cspec != Invalid && cspec != Hsv)
return toHsv().hueF();
- return ct.ahsv.hue == USHRT_MAX ? -1.0 : ct.ahsv.hue / 36000.0;
+ return ct.ahsv.hue == USHRT_MAX ? qreal(-1.0) : ct.ahsv.hue / qreal(36000.0);
}
/*!
@@ -1418,7 +1418,7 @@ qreal QColor::hslHueF() const
{
if (cspec != Invalid && cspec != Hsl)
return toHsl().hslHueF();
- return ct.ahsl.hue == USHRT_MAX ? -1.0 : ct.ahsl.hue / 36000.0;
+ return ct.ahsl.hue == USHRT_MAX ? qreal(-1.0) : ct.ahsl.hue / qreal(36000.0);
}
/*!
@@ -1584,10 +1584,10 @@ QColor QColor::toRgb() const
const qreal v = ct.ahsv.value / qreal(USHRT_MAX);
const int i = int(h);
const qreal f = h - i;
- const qreal p = v * (1.0 - s);
+ const qreal p = v * (qreal(1.0) - s);
if (i & 1) {
- const qreal q = v * (1.0 - (s * f));
+ const qreal q = v * (qreal(1.0) - (s * f));
switch (i) {
case 1:
@@ -1607,7 +1607,7 @@ QColor QColor::toRgb() const
break;
}
} else {
- const qreal t = v * (1.0 - (s * (1.0 - f)));
+ const qreal t = v * (qreal(1.0) - (s * (qreal(1.0) - f)));
switch (i) {
case 0:
@@ -1683,9 +1683,9 @@ QColor QColor::toRgb() const
const qreal y = ct.acmyk.yellow / qreal(USHRT_MAX);
const qreal k = ct.acmyk.black / qreal(USHRT_MAX);
- color.ct.argb.red = qRound((1.0 - (c * (1.0 - k) + k)) * USHRT_MAX);
- color.ct.argb.green = qRound((1.0 - (m * (1.0 - k) + k)) * USHRT_MAX);
- color.ct.argb.blue = qRound((1.0 - (y * (1.0 - k) + k)) * USHRT_MAX);
+ color.ct.argb.red = qRound((qreal(1.0) - (c * (qreal(1.0) - k) + k)) * USHRT_MAX);
+ color.ct.argb.green = qRound((qreal(1.0) - (m * (qreal(1.0) - k) + k)) * USHRT_MAX);
+ color.ct.argb.blue = qRound((qreal(1.0) - (y * (qreal(1.0) - k) + k)) * USHRT_MAX);
break;
}
default:
@@ -1737,15 +1737,15 @@ QColor QColor::toHsv() const
if (qFuzzyCompare(r, max)) {
hue = ((g - b) /delta);
} else if (qFuzzyCompare(g, max)) {
- hue = (2.0 + (b - r) / delta);
+ hue = (qreal(2.0) + (b - r) / delta);
} else if (qFuzzyCompare(b, max)) {
- hue = (4.0 + (r - g) / delta);
+ hue = (qreal(4.0) + (r - g) / delta);
} else {
Q_ASSERT_X(false, "QColor::toHsv", "internal error");
}
- hue *= 60.0;
- if (hue < 0.0)
- hue += 360.0;
+ hue *= qreal(60.0);
+ if (hue < qreal(0.0))
+ hue += qreal(360.0);
color.ct.ahsv.hue = qRound(hue * 100);
}
@@ -1793,15 +1793,15 @@ QColor QColor::toHsl() const
if (qFuzzyCompare(r, max)) {
hue = ((g - b) /delta);
} else if (qFuzzyCompare(g, max)) {
- hue = (2.0 + (b - r) / delta);
+ hue = (qreal(2.0) + (b - r) / delta);
} else if (qFuzzyCompare(b, max)) {
- hue = (4.0 + (r - g) / delta);
+ hue = (qreal(4.0) + (r - g) / delta);
} else {
Q_ASSERT_X(false, "QColor::toHsv", "internal error");
}
- hue *= 60.0;
- if (hue < 0.0)
- hue += 360.0;
+ hue *= qreal(60.0);
+ if (hue < qreal(0.0))
+ hue += qreal(360.0);
color.ct.ahsl.hue = qRound(hue * 100);
}
@@ -1829,17 +1829,17 @@ QColor QColor::toCmyk() const
const qreal r = ct.argb.red / qreal(USHRT_MAX);
const qreal g = ct.argb.green / qreal(USHRT_MAX);
const qreal b = ct.argb.blue / qreal(USHRT_MAX);
- qreal c = 1.0 - r;
- qreal m = 1.0 - g;
- qreal y = 1.0 - b;
+ qreal c = qreal(1.0) - r;
+ qreal m = qreal(1.0) - g;
+ qreal y = qreal(1.0) - b;
// cmy -> cmyk
const qreal k = qMin(c, qMin(m, y));
if (!qFuzzyIsNull(k - 1)) {
- c = (c - k) / (1.0 - k);
- m = (m - k) / (1.0 - k);
- y = (y - k) / (1.0 - k);
+ c = (c - k) / (qreal(1.0) - k);
+ m = (m - k) / (qreal(1.0) - k);
+ y = (y - k) / (qreal(1.0) - k);
}
color.ct.acmyk.cyan = qRound(c * USHRT_MAX);
@@ -1942,10 +1942,10 @@ QColor QColor::fromRgb(int r, int g, int b, int a)
*/
QColor QColor::fromRgbF(qreal r, qreal g, qreal b, qreal a)
{
- if (r < 0.0 || r > 1.0
- || g < 0.0 || g > 1.0
- || b < 0.0 || b > 1.0
- || a < 0.0 || a > 1.0) {
+ if (r < qreal(0.0) || r > qreal(1.0)
+ || g < qreal(0.0) || g > qreal(1.0)
+ || b < qreal(0.0) || b > qreal(1.0)
+ || a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::fromRgbF: RGB parameters out of range");
return QColor();
}
@@ -2005,10 +2005,10 @@ QColor QColor::fromHsv(int h, int s, int v, int a)
*/
QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a)
{
- if (((h < 0.0 || h > 1.0) && h != -1.0)
- || (s < 0.0 || s > 1.0)
- || (v < 0.0 || v > 1.0)
- || (a < 0.0 || a > 1.0)) {
+ if (((h < qreal(0.0) || h > qreal(1.0)) && h != qreal(-1.0))
+ || (s < qreal(0.0) || s > qreal(1.0))
+ || (v < qreal(0.0) || v > qreal(1.0))
+ || (a < qreal(0.0) || a > qreal(1.0))) {
qWarning("QColor::fromHsvF: HSV parameters out of range");
return QColor();
}
@@ -2016,7 +2016,7 @@ QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a)
QColor color;
color.cspec = Hsv;
color.ct.ahsv.alpha = qRound(a * USHRT_MAX);
- color.ct.ahsv.hue = h == -1.0 ? USHRT_MAX : qRound(h * 36000);
+ color.ct.ahsv.hue = h == qreal(-1.0) ? USHRT_MAX : qRound(h * 36000);
color.ct.ahsv.saturation = qRound(s * USHRT_MAX);
color.ct.ahsv.value = qRound(v * USHRT_MAX);
color.ct.ahsv.pad = 0;
@@ -2069,10 +2069,10 @@ QColor QColor::fromHsl(int h, int s, int l, int a)
*/
QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
{
- if (((h < 0.0 || h > 1.0) && h != -1.0)
- || (s < 0.0 || s > 1.0)
- || (l < 0.0 || l > 1.0)
- || (a < 0.0 || a > 1.0)) {
+ if (((h < qreal(0.0) || h > qreal(1.0)) && h != qreal(-1.0))
+ || (s < qreal(0.0) || s > qreal(1.0))
+ || (l < qreal(0.0) || l > qreal(1.0))
+ || (a < qreal(0.0) || a > qreal(1.0))) {
qWarning("QColor::fromHsvF: HSV parameters out of range");
return QColor();
}
@@ -2080,7 +2080,7 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a)
QColor color;
color.cspec = Hsl;
color.ct.ahsl.alpha = qRound(a * USHRT_MAX);
- color.ct.ahsl.hue = (h == -1.0) ? USHRT_MAX : qRound(h * 36000);
+ color.ct.ahsl.hue = (h == qreal(-1.0)) ? USHRT_MAX : qRound(h * 36000);
if (color.ct.ahsl.hue == 36000)
color.ct.ahsl.hue = 0;
color.ct.ahsl.saturation = qRound(s * USHRT_MAX);
@@ -2189,11 +2189,11 @@ void QColor::setCmyk(int c, int m, int y, int k, int a)
*/
void QColor::setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a)
{
- if (c < 0.0 || c > 1.0
- || m < 0.0 || m > 1.0
- || y < 0.0 || y > 1.0
- || k < 0.0 || k > 1.0
- || a < 0.0 || a > 1.0) {
+ if (c < qreal(0.0) || c > qreal(1.0)
+ || m < qreal(0.0) || m > qreal(1.0)
+ || y < qreal(0.0) || y > qreal(1.0)
+ || k < qreal(0.0) || k > qreal(1.0)
+ || a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::setCmykF: CMYK parameters out of range");
return;
}
@@ -2251,11 +2251,11 @@ QColor QColor::fromCmyk(int c, int m, int y, int k, int a)
*/
QColor QColor::fromCmykF(qreal c, qreal m, qreal y, qreal k, qreal a)
{
- if (c < 0.0 || c > 1.0
- || m < 0.0 || m > 1.0
- || y < 0.0 || y > 1.0
- || k < 0.0 || k > 1.0
- || a < 0.0 || a > 1.0) {
+ if (c < qreal(0.0) || c > qreal(1.0)
+ || m < qreal(0.0) || m > qreal(1.0)
+ || y < qreal(0.0) || y > qreal(1.0)
+ || k < qreal(0.0) || k > qreal(1.0)
+ || a < qreal(0.0) || a > qreal(1.0)) {
qWarning("QColor::fromCmykF: CMYK parameters out of range");
return QColor();
}
diff --git a/src/gui/painting/qcolormap_qpa.cpp b/src/gui/painting/qcolormap_qpa.cpp
index 1f4fea8..f66607b 100644
--- a/src/gui/painting/qcolormap_qpa.cpp
+++ b/src/gui/painting/qcolormap_qpa.cpp
@@ -70,7 +70,7 @@ void QColormap::initialize()
QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
QList<QPlatformScreen*> screens = pi->screens();
- screenMap->depth = screens[0]->depth();
+ screenMap->depth = screens.at(0)->depth();
if (screenMap->depth < 8) {
screenMap->mode = QColormap::Indexed;
screenMap->numcolors = 256;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 5904296..360292c 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -75,43 +75,9 @@ enum {
fixed_scale = 1 << 16,
half_point = 1 << 15
};
-static const int buffer_size = 2048;
-
-struct LinearGradientValues
-{
- qreal dx;
- qreal dy;
- qreal l;
- qreal off;
-};
-
-struct RadialGradientValues
-{
- qreal dx;
- qreal dy;
- qreal a;
-};
-
-struct Operator;
-typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
-typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
-typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
-
-struct Operator
-{
- QPainter::CompositionMode mode;
- DestFetchProc dest_fetch;
- DestStoreProc dest_store;
- SourceFetchProc src_fetch;
- CompositionFunctionSolid funcSolid;
- CompositionFunction func;
- union {
- LinearGradientValues linear;
- RadialGradientValues radial;
-// TextureValues texture;
- };
-};
+// must be multiple of 4 for easier SIMD implementations
+static const int buffer_size = 2048;
/*
Destination fetch. This is simple as we don't have to do bounds checks or
@@ -570,8 +536,8 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const
int image_width = data->texture.width;
int image_height = data->texture.height;
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
const uint *end = buffer + length;
uint *b = buffer;
@@ -792,8 +758,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
int image_x2 = data->texture.x2 - 1;
int image_y2 = data->texture.y2 - 1;
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
uint *end = buffer + length;
uint *b = buffer;
@@ -1188,8 +1154,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *
while (b < end) {
const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal px = fx * iw - 0.5;
- const qreal py = fy * iw - 0.5;
+ const qreal px = fx * iw - qreal(0.5);
+ const qreal py = fy * iw - qreal(0.5);
int x1 = int(px) - (px < 0);
int x2;
@@ -1346,64 +1312,13 @@ static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
},
};
-
-static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
-{
- int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + 0.5);
-
- // calculate the actual offset.
- if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
- if (data->spread == QGradient::RepeatSpread) {
- ipos = ipos % GRADIENT_STOPTABLE_SIZE;
- ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
-
- } else if (data->spread == QGradient::ReflectSpread) {
- const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1;
- ipos = ipos % limit;
- ipos = ipos < 0 ? limit + ipos : ipos;
- ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
-
- } else {
- if (ipos < 0) ipos = 0;
- else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1;
- }
- }
-
- Q_ASSERT(ipos >= 0);
- Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
-
- return data->colorTable[ipos];
-}
-
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos)
{
int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS;
-
- // calculate the actual offset.
- if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
- if (data->spread == QGradient::RepeatSpread) {
- ipos = ipos % GRADIENT_STOPTABLE_SIZE;
- ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
-
- } else if (data->spread == QGradient::ReflectSpread) {
- const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1;
- ipos = ipos % limit;
- ipos = ipos < 0 ? limit + ipos : ipos;
- ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos;
-
- } else {
- if (ipos < 0) ipos = 0;
- else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1;
- }
- }
-
- Q_ASSERT(ipos >= 0);
- Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
-
- return data->colorTable[ipos];
+ return data->colorTable[qt_gradient_clamp(data, ipos)];
}
static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data)
@@ -1419,8 +1334,8 @@ static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const Q
}
}
-static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
+static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
{
const uint *b = buffer;
qreal t, inc;
@@ -1430,8 +1345,8 @@ static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator
if (op->linear.l == 0) {
t = inc = 0;
} else {
- rx = data->m21 * (y + 0.5) + data->m11 * (x + 0.5) + data->dx;
- ry = data->m22 * (y + 0.5) + data->m12 * (x + 0.5) + data->dy;
+ rx = data->m21 * (y + qreal(0.5)) + data->m11 * (x + qreal(0.5)) + data->dx;
+ ry = data->m22 * (y + qreal(0.5)) + data->m12 * (x + qreal(0.5)) + data->dy;
t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off;
inc = op->linear.dx * data->m11 + op->linear.dy * data->m12;
affine = !data->m13 && !data->m23;
@@ -1444,7 +1359,7 @@ static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator
const uint *end = buffer + length;
if (affine) {
- if (inc > -1e-5 && inc < 1e-5) {
+ if (inc > qreal(-1e-5) && inc < qreal(1e-5)) {
QT_MEMFILL_UINT(buffer, length, qt_gradient_pixel_fixed(&data->gradient, int(t * FIXPT_SIZE)));
} else {
if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) &&
@@ -1467,7 +1382,7 @@ static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator
}
}
} else { // fall back to float math here as well
- qreal rw = data->m23 * (y + 0.5) + data->m13 * (x + 0.5) + data->m33;
+ qreal rw = data->m23 * (y + qreal(0.5)) + data->m13 * (x + qreal(0.5)) + data->m33;
while (buffer < end) {
qreal x = rx/rw;
qreal y = ry/rw;
@@ -1487,116 +1402,71 @@ static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator
return b;
}
-static inline qreal determinant(qreal a, qreal b, qreal c)
-{
- return (b * b) - (4 * a * c);
-}
-
-// function to evaluate real roots
-static inline qreal realRoots(qreal a, qreal b, qreal detSqrt)
-{
- return (-b + detSqrt)/(2 * a);
-}
-
-static inline qreal qSafeSqrt(qreal x)
-{
- return x > 0 ? qSqrt(x) : 0;
-}
-
static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data)
{
v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x;
v->dy = data->gradient.radial.center.y - data->gradient.radial.focal.y;
- v->a = data->gradient.radial.radius*data->gradient.radial.radius - v->dx*v->dx - v->dy*v->dy;
-}
-
-static const uint * QT_FASTCALL fetchRadialGradient(uint *buffer, const Operator *op, const QSpanData *data,
- int y, int x, int length)
-{
- const uint *b = buffer;
- qreal rx = data->m21 * (y + 0.5)
- + data->dx + data->m11 * (x + 0.5);
- qreal ry = data->m22 * (y + 0.5)
- + data->dy + data->m12 * (x + 0.5);
- bool affine = !data->m13 && !data->m23;
- //qreal r = data->gradient.radial.radius;
-
- const uint *end = buffer + length;
- if (affine) {
- rx -= data->gradient.radial.focal.x;
- ry -= data->gradient.radial.focal.y;
-
- qreal inv_a = 1 / qreal(2 * op->radial.a);
-
- const qreal delta_rx = data->m11;
- const qreal delta_ry = data->m12;
- qreal b = 2*(rx * op->radial.dx + ry * op->radial.dy);
- qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy);
- const qreal b_delta_b = 2 * b * delta_b;
- const qreal delta_b_delta_b = 2 * delta_b * delta_b;
+ v->dr = data->gradient.radial.center.radius - data->gradient.radial.focal.radius;
+ v->sqrfr = data->gradient.radial.focal.radius * data->gradient.radial.focal.radius;
- const qreal bb = b * b;
- const qreal delta_bb = delta_b * delta_b;
+ v->a = v->dr * v->dr - v->dx*v->dx - v->dy*v->dy;
+ v->inv2a = 1 / (2 * v->a);
- b *= inv_a;
- delta_b *= inv_a;
-
- const qreal rxrxryry = rx * rx + ry * ry;
- const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
- const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
- const qreal delta_rx_plus_ry = 2 * delta_rxrxryry;
-
- inv_a *= inv_a;
-
- qreal det = (bb + 4 * op->radial.a * rxrxryry) * inv_a;
- qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
- const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a;
+ v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0;
+}
- while (buffer < end) {
- *buffer = qt_gradient_pixel(&data->gradient, qSafeSqrt(det) - b);
+class RadialFetchPlain
+{
+public:
+ static inline void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
+ qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
+ {
+ if (op->radial.extended) {
+ while (buffer < end) {
+ quint32 result = 0;
+ if (det >= 0) {
+ qreal w = qSqrt(det) - b;
+ if (data->gradient.radial.focal.radius + op->radial.dr * w >= 0)
+ result = qt_gradient_pixel(&data->gradient, w);
+ }
- det += delta_det;
- delta_det += delta_delta_det;
- b += delta_b;
+ *buffer = result;
- ++buffer;
- }
- } else {
- qreal rw = data->m23 * (y + 0.5)
- + data->m33 + data->m13 * (x + 0.5);
- if (!rw)
- rw = 1;
- while (buffer < end) {
- qreal gx = rx/rw - data->gradient.radial.focal.x;
- qreal gy = ry/rw - data->gradient.radial.focal.y;
- qreal b = 2*(gx*op->radial.dx + gy*op->radial.dy);
- qreal det = determinant(op->radial.a, b , -(gx*gx + gy*gy));
- qreal s = realRoots(op->radial.a, b, qSafeSqrt(det));
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
- *buffer = qt_gradient_pixel(&data->gradient, s);
+ ++buffer;
+ }
+ } else {
+ while (buffer < end) {
+ *buffer++ = qt_gradient_pixel(&data->gradient, qSqrt(det) - b);
- rx += data->m11;
- ry += data->m12;
- rw += data->m13;
- if (!rw) {
- rw += data->m13;
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
}
- ++buffer;
}
}
+};
- return b;
+const uint * QT_FASTCALL qt_fetch_radial_gradient_plain(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<RadialFetchPlain>(buffer, op, data, y, x, length);
}
-static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+static SourceFetchProc qt_fetch_radial_gradient = qt_fetch_radial_gradient_plain;
+
+static const uint * QT_FASTCALL qt_fetch_conical_gradient(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
const uint *b = buffer;
- qreal rx = data->m21 * (y + 0.5)
- + data->dx + data->m11 * (x + 0.5);
- qreal ry = data->m22 * (y + 0.5)
- + data->dy + data->m12 * (x + 0.5);
+ qreal rx = data->m21 * (y + qreal(0.5))
+ + data->dx + data->m11 * (x + qreal(0.5));
+ qreal ry = data->m22 * (y + qreal(0.5))
+ + data->dy + data->m12 * (x + qreal(0.5));
bool affine = !data->m13 && !data->m23;
const uint *end = buffer + length;
@@ -1613,8 +1483,8 @@ static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operato
++buffer;
}
} else {
- qreal rw = data->m23 * (y + 0.5)
- + data->m33 + data->m13 * (x + 0.5);
+ qreal rw = data->m23 * (y + qreal(0.5))
+ + data->m33 + data->m13 * (x + qreal(0.5));
if (!rw)
rw = 1;
while (buffer < end) {
@@ -2819,7 +2689,7 @@ static inline int soft_light_op(int dst, int src, int da, int sa)
# ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2
return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025;
# else
- return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
+ return (dst * sa * 255 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
# endif
}
}
@@ -3347,16 +3217,16 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
case QSpanData::LinearGradient:
solidSource = !data->gradient.alphaColor;
getLinearGradientValues(&op.linear, data);
- op.src_fetch = fetchLinearGradient;
+ op.src_fetch = qt_fetch_linear_gradient;
break;
case QSpanData::RadialGradient:
solidSource = !data->gradient.alphaColor;
getRadialGradientValues(&op.radial, data);
- op.src_fetch = fetchRadialGradient;
+ op.src_fetch = qt_fetch_radial_gradient;
break;
case QSpanData::ConicalGradient:
solidSource = !data->gradient.alphaColor;
- op.src_fetch = fetchConicalGradient;
+ op.src_fetch = qt_fetch_conical_gradient;
break;
case QSpanData::Texture:
op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format];
@@ -5928,8 +5798,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s
uint *target = ((uint *)t) + spans->x;
uint *image_bits = (uint *)data->texture.imageData;
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
+ const qreal cx = spans->x + qreal(0.5);
+ const qreal cy = spans->y + qreal(0.5);
int x = int((data->m21 * cy
+ data->m11 * cx + data->dx) * fixed_scale);
@@ -5976,8 +5846,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s
uint *target = ((uint *)t) + spans->x;
uint *image_bits = (uint *)data->texture.imageData;
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
+ const qreal cx = spans->x + qreal(0.5);
+ const qreal cy = spans->y + qreal(0.5);
qreal x = data->m21 * cy + data->m11 * cx + data->dx;
qreal y = data->m22 * cy + data->m12 * cx + data->dy;
@@ -6328,8 +6198,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QS
uint *target = ((uint *)t) + spans->x;
uint *image_bits = (uint *)data->texture.imageData;
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
+ const qreal cx = spans->x + qreal(0.5);
+ const qreal cy = spans->y + qreal(0.5);
int x = int((data->m21 * cy
+ data->m11 * cx + data->dx) * fixed_scale);
@@ -6380,8 +6250,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QS
uint *target = ((uint *)t) + spans->x;
uint *image_bits = (uint *)data->texture.imageData;
- const qreal cx = spans->x + 0.5;
- const qreal cy = spans->y + 0.5;
+ const qreal cx = spans->x + qreal(0.5);
+ const qreal cy = spans->y + qreal(0.5);
qreal x = data->m21 * cy + data->m11 * cx + data->dx;
qreal y = data->m22 * cy + data->m12 * cx + data->dy;
@@ -7067,7 +6937,7 @@ static void qt_gradient_quint32(int count, const QSpan *spans, void *userData)
*/
const int gss = GRADIENT_STOPTABLE_SIZE - 1;
int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
while (count--) {
int y = spans->y;
@@ -7115,7 +6985,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData)
*/
const int gss = GRADIENT_STOPTABLE_SIZE - 1;
int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+ int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
uint oldColor = data->solid.color;
while (count--) {
@@ -7194,18 +7064,12 @@ void qt_build_pow_tables() {
#ifdef Q_WS_MAC
// decided by testing a few things on an iMac, should probably get this from the
// system...
- smoothing = 2.0;
+ smoothing = qreal(2.0);
#endif
#ifdef Q_WS_WIN
- int winSmooth;
- if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
- smoothing = winSmooth / 1000.0;
-
- // Safeguard ourselves against corrupt registry values...
- if (smoothing > 5 || smoothing < 1)
- smoothing = 1.4;
-
+ extern qreal qt_fontsmoothing_gamma; // qapplication_win.cpp
+ smoothing = qt_fontsmoothing_gamma;
#endif
#ifdef Q_WS_X11
@@ -7226,7 +7090,7 @@ void qt_build_pow_tables() {
for (int i=0; i<256; ++i)
qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
for (int i=0; i<2048; ++i)
- qt_pow_invgamma[i] = uchar(qRound(qPow(i / 2047.0, 1 / gray_gamma) * 255));
+ qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255));
#endif
}
@@ -7888,6 +7752,11 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2;
}
#ifdef QT_HAVE_SSSE3
@@ -7983,6 +7852,11 @@ void qInitDrawhelperAsm()
qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon;
qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon;
qt_memfill32 = qt_memfill32_neon;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
}
#endif
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index 00b103d..e673dd9 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -327,10 +327,8 @@ void qt_blend_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
blend_8_pixels_argb32_on_rgb16_neon(dstBuffer, srcBuffer, const_alpha);
- for (int j = 0; j < tail; ++j) {
+ for (int j = 0; j < tail; ++j)
dst[i + j] = dstBuffer[j];
- src[i + j] = srcBuffer[j];
- }
}
dst = (quint16 *)(((uchar *) dst) + dbpl);
@@ -957,6 +955,46 @@ void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h,
}
}
+class QSimdNeon
+{
+public:
+ typedef int32x4_t Int32x4;
+ typedef float32x4_t Float32x4;
+
+ union Vect_buffer_i { Int32x4 v; int i[4]; };
+ union Vect_buffer_f { Float32x4 v; float f[4]; };
+
+ static inline Float32x4 v_dup(float x) { return vdupq_n_f32(x); }
+ static inline Int32x4 v_dup(int x) { return vdupq_n_s32(x); }
+ static inline Int32x4 v_dup(uint x) { return vdupq_n_s32(x); }
+
+ static inline Float32x4 v_add(Float32x4 a, Float32x4 b) { return vaddq_f32(a, b); }
+ static inline Int32x4 v_add(Int32x4 a, Int32x4 b) { return vaddq_s32(a, b); }
+
+ static inline Float32x4 v_max(Float32x4 a, Float32x4 b) { return vmaxq_f32(a, b); }
+ static inline Float32x4 v_min(Float32x4 a, Float32x4 b) { return vminq_f32(a, b); }
+ static inline Int32x4 v_min_16(Int32x4 a, Int32x4 b) { return vminq_s32(a, b); }
+
+ static inline Int32x4 v_and(Int32x4 a, Int32x4 b) { return vandq_s32(a, b); }
+
+ static inline Float32x4 v_sub(Float32x4 a, Float32x4 b) { return vsubq_f32(a, b); }
+ static inline Int32x4 v_sub(Int32x4 a, Int32x4 b) { return vsubq_s32(a, b); }
+
+ static inline Float32x4 v_mul(Float32x4 a, Float32x4 b) { return vmulq_f32(a, b); }
+
+ static inline Float32x4 v_sqrt(Float32x4 x) { Float32x4 y = vrsqrteq_f32(x); y = vmulq_f32(y, vrsqrtsq_f32(x, vmulq_f32(y, y))); return vmulq_f32(x, y); }
+
+ static inline Int32x4 v_toInt(Float32x4 x) { return vcvtq_s32_f32(x); }
+
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b) { return vcge_f32(a, b); }
+};
+
+const uint * QT_FASTCALL qt_fetch_radial_gradient_neon(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdNeon> >(buffer, op, data, y, x, length);
+}
+
QT_END_NAMESPACE
#endif // QT_HAVE_NEON
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index d4e731b..fa6ad0b 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -63,6 +63,7 @@
#endif
#include "private/qrasterdefs_p.h"
#include <private/qsimd_p.h>
+#include <private/qmath_p.h>
#ifdef Q_WS_QWS
#include "QtGui/qscreen_qws.h"
@@ -178,6 +179,44 @@ void qBlendTextureCallback(int count, const QSpan *spans, void *userData);
typedef void (QT_FASTCALL *CompositionFunction)(uint *dest, const uint *src, int length, uint const_alpha);
typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha);
+struct LinearGradientValues
+{
+ qreal dx;
+ qreal dy;
+ qreal l;
+ qreal off;
+};
+
+struct RadialGradientValues
+{
+ qreal dx;
+ qreal dy;
+ qreal dr;
+ qreal sqrfr;
+ qreal a;
+ qreal inv2a;
+ bool extended;
+};
+
+struct Operator;
+typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length);
+typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length);
+typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length);
+
+struct Operator
+{
+ QPainter::CompositionMode mode;
+ DestFetchProc dest_fetch;
+ DestStoreProc dest_store;
+ SourceFetchProc src_fetch;
+ CompositionFunctionSolid funcSolid;
+ CompositionFunction func;
+ union {
+ LinearGradientValues linear;
+ RadialGradientValues radial;
+ };
+};
+
void qInitDrawhelperAsm();
class QRasterPaintEngine;
@@ -204,12 +243,13 @@ struct QRadialGradientData
struct {
qreal x;
qreal y;
+ qreal radius;
} center;
struct {
qreal x;
qreal y;
+ qreal radius;
} focal;
- qreal radius;
};
struct QConicalGradientData
@@ -233,8 +273,10 @@ struct QGradientData
#ifdef Q_WS_QWS
#define GRADIENT_STOPTABLE_SIZE 256
+#define GRADIENT_STOPTABLE_SIZE_SHIFT 8
#else
#define GRADIENT_STOPTABLE_SIZE 1024
+#define GRADIENT_STOPTABLE_SIZE_SHIFT 10
#endif
uint* colorTable; //[GRADIENT_STOPTABLE_SIZE];
@@ -308,6 +350,218 @@ struct QSpanData
void adjustSpanMethods();
};
+static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
+{
+ if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
+ if (data->spread == QGradient::RepeatSpread) {
+ ipos = ipos % GRADIENT_STOPTABLE_SIZE;
+ ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos;
+ } else if (data->spread == QGradient::ReflectSpread) {
+ const int limit = GRADIENT_STOPTABLE_SIZE * 2;
+ ipos = ipos % limit;
+ ipos = ipos < 0 ? limit + ipos : ipos;
+ ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - 1 - ipos : ipos;
+ } else {
+ if (ipos < 0)
+ ipos = 0;
+ else if (ipos >= GRADIENT_STOPTABLE_SIZE)
+ ipos = GRADIENT_STOPTABLE_SIZE-1;
+ }
+ }
+
+ Q_ASSERT(ipos >= 0);
+ Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE);
+
+ return ipos;
+}
+
+static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos)
+{
+ int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5));
+ return data->colorTable[qt_gradient_clamp(data, ipos)];
+}
+
+static inline qreal qRadialDeterminant(qreal a, qreal b, qreal c)
+{
+ return (b * b) - (4 * a * c);
+}
+
+template <class RadialFetchFunc>
+const uint * QT_FASTCALL qt_fetch_radial_gradient_template(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ // avoid division by zero
+ if (qFuzzyIsNull(op->radial.a)) {
+ extern void (*qt_memfill32)(quint32 *dest, quint32 value, int count);
+ qt_memfill32(buffer, 0, length);
+ return buffer;
+ }
+
+ const uint *b = buffer;
+ qreal rx = data->m21 * (y + qreal(0.5))
+ + data->dx + data->m11 * (x + qreal(0.5));
+ qreal ry = data->m22 * (y + qreal(0.5))
+ + data->dy + data->m12 * (x + qreal(0.5));
+ bool affine = !data->m13 && !data->m23;
+
+ uint *end = buffer + length;
+ if (affine) {
+ rx -= data->gradient.radial.focal.x;
+ ry -= data->gradient.radial.focal.y;
+
+ qreal inv_a = 1 / qreal(2 * op->radial.a);
+
+ const qreal delta_rx = data->m11;
+ const qreal delta_ry = data->m12;
+
+ qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + rx * op->radial.dx + ry * op->radial.dy);
+ qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy);
+ const qreal b_delta_b = 2 * b * delta_b;
+ const qreal delta_b_delta_b = 2 * delta_b * delta_b;
+
+ const qreal bb = b * b;
+ const qreal delta_bb = delta_b * delta_b;
+
+ b *= inv_a;
+ delta_b *= inv_a;
+
+ const qreal rxrxryry = rx * rx + ry * ry;
+ const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry;
+ const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry);
+ const qreal delta_rx_plus_ry = 2 * delta_rxrxryry;
+
+ inv_a *= inv_a;
+
+ qreal det = (bb - 4 * op->radial.a * (op->radial.sqrfr - rxrxryry)) * inv_a;
+ qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a;
+ const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a;
+
+ RadialFetchFunc::fetch(buffer, end, op, data, det, delta_det, delta_delta_det, b, delta_b);
+ } else {
+ qreal rw = data->m23 * (y + qreal(0.5))
+ + data->m33 + data->m13 * (x + qreal(0.5));
+
+ while (buffer < end) {
+ if (rw == 0) {
+ *buffer = 0;
+ } else {
+ qreal invRw = 1 / rw;
+ qreal gx = rx * invRw - data->gradient.radial.focal.x;
+ qreal gy = ry * invRw - data->gradient.radial.focal.y;
+ qreal b = 2*(op->radial.dr*data->gradient.radial.focal.radius + gx*op->radial.dx + gy*op->radial.dy);
+ qreal det = qRadialDeterminant(op->radial.a, b, op->radial.sqrfr - (gx*gx + gy*gy));
+
+ quint32 result = 0;
+ if (det >= 0) {
+ qreal detSqrt = qSqrt(det);
+
+ qreal s0 = (-b - detSqrt) * op->radial.inv2a;
+ qreal s1 = (-b + detSqrt) * op->radial.inv2a;
+
+ qreal s = qMax(s0, s1);
+
+ if (data->gradient.radial.focal.radius + op->radial.dr * s >= 0)
+ result = qt_gradient_pixel(&data->gradient, s);
+ }
+
+ *buffer = result;
+ }
+
+ rx += data->m11;
+ ry += data->m12;
+ rw += data->m13;
+
+ ++buffer;
+ }
+ }
+
+ return b;
+}
+
+template <class Simd>
+class QRadialFetchSimd
+{
+public:
+ static void fetch(uint *buffer, uint *end, const Operator *op, const QSpanData *data, qreal det,
+ qreal delta_det, qreal delta_delta_det, qreal b, qreal delta_b)
+ {
+ typename Simd::Vect_buffer_f det_vec;
+ typename Simd::Vect_buffer_f delta_det4_vec;
+ typename Simd::Vect_buffer_f b_vec;
+
+ for (int i = 0; i < 4; ++i) {
+ det_vec.f[i] = det;
+ delta_det4_vec.f[i] = 4 * delta_det;
+ b_vec.f[i] = b;
+
+ det += delta_det;
+ delta_det += delta_delta_det;
+ b += delta_b;
+ }
+
+ const typename Simd::Float32x4 v_delta_delta_det16 = Simd::v_dup(16 * delta_delta_det);
+ const typename Simd::Float32x4 v_delta_delta_det6 = Simd::v_dup(6 * delta_delta_det);
+ const typename Simd::Float32x4 v_delta_b4 = Simd::v_dup(4 * delta_b);
+
+ const typename Simd::Float32x4 v_r0 = Simd::v_dup(data->gradient.radial.focal.radius);
+ const typename Simd::Float32x4 v_dr = Simd::v_dup(op->radial.dr);
+
+ const typename Simd::Float32x4 v_min = Simd::v_dup(0.0f);
+ const typename Simd::Float32x4 v_max = Simd::v_dup(float(GRADIENT_STOPTABLE_SIZE-1));
+ const typename Simd::Float32x4 v_half = Simd::v_dup(0.5f);
+
+ const typename Simd::Int32x4 v_repeat_mask = Simd::v_dup(~(uint(0xffffff) << GRADIENT_STOPTABLE_SIZE_SHIFT));
+ const typename Simd::Int32x4 v_reflect_mask = Simd::v_dup(~(uint(0xffffff) << (GRADIENT_STOPTABLE_SIZE_SHIFT+1)));
+
+ const typename Simd::Int32x4 v_reflect_limit = Simd::v_dup(2 * GRADIENT_STOPTABLE_SIZE - 1);
+
+ const int extended_mask = op->radial.extended ? 0x0 : ~0x0;
+
+#define FETCH_RADIAL_LOOP_PROLOGUE \
+ while (buffer < end) { \
+ typename Simd::Vect_buffer_i v_buffer_mask; \
+ v_buffer_mask.v = Simd::v_greaterOrEqual(det_vec.v, v_min); \
+ const typename Simd::Float32x4 v_index_local = Simd::v_sub(Simd::v_sqrt(Simd::v_max(v_min, det_vec.v)), b_vec.v); \
+ const typename Simd::Float32x4 v_index = Simd::v_add(Simd::v_mul(v_index_local, v_max), v_half); \
+ v_buffer_mask.v = Simd::v_and(v_buffer_mask.v, Simd::v_greaterOrEqual(Simd::v_add(v_r0, Simd::v_mul(v_dr, v_index_local)), v_min)); \
+ typename Simd::Vect_buffer_i index_vec;
+#define FETCH_RADIAL_LOOP_CLAMP_REPEAT \
+ index_vec.v = Simd::v_and(v_repeat_mask, Simd::v_toInt(v_index));
+#define FETCH_RADIAL_LOOP_CLAMP_REFLECT \
+ const typename Simd::Int32x4 v_index_i = Simd::v_and(v_reflect_mask, Simd::v_toInt(v_index)); \
+ const typename Simd::Int32x4 v_index_i_inv = Simd::v_sub(v_reflect_limit, v_index_i); \
+ index_vec.v = Simd::v_min_16(v_index_i, v_index_i_inv);
+#define FETCH_RADIAL_LOOP_CLAMP_PAD \
+ index_vec.v = Simd::v_toInt(Simd::v_min(v_max, Simd::v_max(v_min, v_index)));
+#define FETCH_RADIAL_LOOP_EPILOGUE \
+ det_vec.v = Simd::v_add(Simd::v_add(det_vec.v, delta_det4_vec.v), v_delta_delta_det6); \
+ delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \
+ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \
+ for (int i = 0; i < 4; ++i) \
+ *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \
+ }
+
+#define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \
+ FETCH_RADIAL_LOOP_PROLOGUE \
+ FETCH_RADIAL_LOOP_CLAMP \
+ FETCH_RADIAL_LOOP_EPILOGUE
+
+ switch (data->gradient.spread) {
+ case QGradient::RepeatSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REPEAT)
+ break;
+ case QGradient::ReflectSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_REFLECT)
+ break;
+ case QGradient::PadSpread:
+ FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD)
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ }
+};
+
#if defined(Q_CC_RVCT)
# pragma push
# pragma arm
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index aad6bc9..75bb619 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -112,8 +112,6 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
// First, align dest to 16 bytes:
ALIGNMENT_PROLOGUE_16BYTES(dst, x, w) {
- quint32 s = src[x];
- s = BYTE_MUL(s, const_alpha);
dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
}
@@ -127,8 +125,6 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl,
}
}
for (; x<w; ++x) {
- quint32 s = src[x];
- s = BYTE_MUL(s, const_alpha);
dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
@@ -491,6 +487,58 @@ void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y,
}
}
+class QSimdSse2
+{
+public:
+ typedef __m128i Int32x4;
+ typedef __m128 Float32x4;
+
+ union Vect_buffer_i { Int32x4 v; int i[4]; };
+ union Vect_buffer_f { Float32x4 v; float f[4]; };
+
+ static inline Float32x4 v_dup(float x) { return _mm_set1_ps(x); }
+ static inline Float32x4 v_dup(double x) { return _mm_set1_ps(x); }
+ static inline Int32x4 v_dup(int x) { return _mm_set1_epi32(x); }
+ static inline Int32x4 v_dup(uint x) { return _mm_set1_epi32(x); }
+
+ static inline Float32x4 v_add(Float32x4 a, Float32x4 b) { return _mm_add_ps(a, b); }
+ static inline Int32x4 v_add(Int32x4 a, Int32x4 b) { return _mm_add_epi32(a, b); }
+
+ static inline Float32x4 v_max(Float32x4 a, Float32x4 b) { return _mm_max_ps(a, b); }
+ static inline Float32x4 v_min(Float32x4 a, Float32x4 b) { return _mm_min_ps(a, b); }
+ static inline Int32x4 v_min_16(Int32x4 a, Int32x4 b) { return _mm_min_epi16(a, b); }
+
+ static inline Int32x4 v_and(Int32x4 a, Int32x4 b) { return _mm_and_si128(a, b); }
+
+ static inline Float32x4 v_sub(Float32x4 a, Float32x4 b) { return _mm_sub_ps(a, b); }
+ static inline Int32x4 v_sub(Int32x4 a, Int32x4 b) { return _mm_sub_epi32(a, b); }
+
+ static inline Float32x4 v_mul(Float32x4 a, Float32x4 b) { return _mm_mul_ps(a, b); }
+
+ static inline Float32x4 v_sqrt(Float32x4 x) { return _mm_sqrt_ps(x); }
+
+ static inline Int32x4 v_toInt(Float32x4 x) { return _mm_cvttps_epi32(x); }
+
+ // pre-VS 2008 doesn't have cast intrinsics, whereas 2008 and later requires it
+#if defined(Q_CC_MSVC) && _MSC_VER < 1500
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b)
+ {
+ union Convert { Int32x4 vi; Float32x4 vf; } convert;
+ convert.vf = _mm_cmpgt_ps(a, b);
+ return convert.vi;
+ }
+#else
+ static inline Int32x4 v_greaterOrEqual(Float32x4 a, Float32x4 b) { return _mm_castps_si128(_mm_cmpgt_ps(a, b)); }
+#endif
+};
+
+const uint * QT_FASTCALL qt_fetch_radial_gradient_sse2(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length)
+{
+ return qt_fetch_radial_gradient_template<QRadialFetchSimd<QSimdSse2> >(buffer, op, data, y, x, length);
+}
+
+
QT_END_NAMESPACE
#endif // QT_HAVE_SSE2
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index dd4b3db..51171c5 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -47,6 +47,7 @@
#include <private/qimage_p.h>
#include <qstatictext.h>
#include <private/qstatictext_p.h>
+#include <private/qrawfont_p.h>
#include <QDebug>
@@ -534,16 +535,6 @@ QString QPaintBuffer::commandDescription(int command) const
QTextItemInt &ti = (*tiCopy)();
QString text(ti.text());
- QFont font(ti.font());
- font.setUnderline(false);
- font.setStrikeOut(false);
- font.setOverline(false);
-
- const QTextItemInt &si = static_cast<const QTextItemInt &>(ti);
- qreal justificationWidth = 0;
- if (si.justified)
- justificationWidth = si.width.toReal();
-
debug << "Cmd_DrawTextItem:" << pos << " " << text;
break; }
case QPaintBufferPrivate::Cmd_SystemStateChanged: {
@@ -1754,26 +1745,38 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
painter->setClipRegion(region, Qt::ClipOperation(cmd.extra));
break; }
+#if !defined(QT_NO_RAWFONT)
case QPaintBufferPrivate::Cmd_DrawStaticText: {
QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
QFont font = variants.at(0).value<QFont>();
- QVector<quint32> glyphs;
+ QVector<quint32> glyphIndexes;
QVector<QPointF> positions;
for (int i=0; i<(variants.size() - 1) / 2; ++i) {
- glyphs.append(variants.at(i*2 + 1).toUInt());
+ glyphIndexes.append(variants.at(i*2 + 1).toUInt());
positions.append(variants.at(i*2 + 2).toPointF());
}
painter->setFont(font);
- qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
-
- break;
+ QRawFont rawFont;
+ QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont);
+ QFontPrivate *fontD = QFontPrivate::get(font);
+ rawFontD->fontEngine = fontD->engineForScript(QUnicodeTables::Common);
+ rawFontD->fontEngine->ref.ref();
+
+ QGlyphs glyphs;
+ glyphs.setFont(rawFont);
+ glyphs.setGlyphIndexes(glyphIndexes);
+ glyphs.setPositions(positions);
+
+ painter->drawGlyphs(QPointF(), glyphs);
+ break;
}
+#endif
case QPaintBufferPrivate::Cmd_DrawText: {
QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp
index 8aab7c7..cc75b86 100644
--- a/src/gui/painting/qpaintengine_mac.cpp
+++ b/src/gui/painting/qpaintengine_mac.cpp
@@ -1544,8 +1544,9 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
QPointF center(radialGrad->center());
QPointF focal(radialGrad->focalPoint());
qreal radius = radialGrad->radius();
+ qreal focalRadius = radialGrad->focalRadius();
shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()),
- 0.0, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
+ focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true);
}
CGFunctionRelease(fill_func);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 6902543..2119e30 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -5033,6 +5033,84 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
+ if (stopCount == 2) {
+ uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
+ uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity);
+
+ qreal first_stop = stops[0].first;
+ qreal second_stop = stops[1].first;
+
+ if (second_stop < first_stop) {
+ qSwap(first_color, second_color);
+ qSwap(first_stop, second_stop);
+ }
+
+ if (colorInterpolation) {
+ first_color = PREMUL(first_color);
+ second_color = PREMUL(second_color);
+ }
+
+ int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1));
+ int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1));
+
+ uint red_first = qRed(first_color) << 16;
+ uint green_first = qGreen(first_color) << 16;
+ uint blue_first = qBlue(first_color) << 16;
+ uint alpha_first = qAlpha(first_color) << 16;
+
+ uint red_second = qRed(second_color) << 16;
+ uint green_second = qGreen(second_color) << 16;
+ uint blue_second = qBlue(second_color) << 16;
+ uint alpha_second = qAlpha(second_color) << 16;
+
+ int i = 0;
+ for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) {
+ if (colorInterpolation)
+ colorTable[i] = first_color;
+ else
+ colorTable[i] = PREMUL(first_color);
+ }
+
+ if (i < second_index) {
+ qreal reciprocal = qreal(1) / (second_index - first_index);
+
+ int red_delta = qRound(int(red_second - red_first) * reciprocal);
+ int green_delta = qRound(int(green_second - green_first) * reciprocal);
+ int blue_delta = qRound(int(blue_second - blue_first) * reciprocal);
+ int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal);
+
+ // rounding
+ red_first += 1 << 15;
+ green_first += 1 << 15;
+ blue_first += 1 << 15;
+ alpha_first += 1 << 15;
+
+ for (; i < qMin(GRADIENT_STOPTABLE_SIZE, second_index); ++i) {
+ red_first += red_delta;
+ green_first += green_delta;
+ blue_first += blue_delta;
+ alpha_first += alpha_delta;
+
+ const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000)
+ | ((green_first >> 8) & 0xff00) | (blue_first >> 16);
+
+ if (colorInterpolation)
+ colorTable[i] = color;
+ else
+ colorTable[i] = PREMUL(color);
+ }
+ }
+
+ for (; i < GRADIENT_STOPTABLE_SIZE; ++i) {
+ if (colorInterpolation)
+ colorTable[i] = second_color;
+ else
+ colorTable[i] = PREMUL(second_color);
+ }
+
+ return;
+ }
+
uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity);
if (stopCount == 1) {
current_color = PREMUL(current_color);
@@ -5204,10 +5282,11 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
QPointF center = g->center();
radialData.center.x = center.x();
radialData.center.y = center.y();
+ radialData.center.radius = g->centerRadius();
QPointF focal = g->focalPoint();
radialData.focal.x = focal.x();
radialData.focal.y = focal.y();
- radialData.radius = g->radius();
+ radialData.focal.radius = g->focalRadius();
}
break;
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index 94828fb..6ba9a99 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -1611,8 +1611,6 @@ void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int p
&& (fill.style() != Qt::NoBrush)
&& ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush))
{
- QRect br = tessellator->tessellate((QPointF *)clippedPoints, clippedCount,
- mode == QPaintEngine::WindingMode);
if (tessellator->size > 0) {
XRenderPictureAttributes attrs;
attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp;
@@ -1771,7 +1769,6 @@ void QX11PaintEngine::drawPath(const QPainterPath &path)
Q_D(QX11PaintEngine);
if (path.isEmpty())
return;
- QTransform old_matrix = d->matrix;
if (d->has_brush)
d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true);
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 509fb77..7f601eb 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1012,4 +1012,50 @@ void QPaintEngineEx::updateState(const QPaintEngineState &)
// do nothing...
}
+Q_GUI_EXPORT QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path)
+{
+ const qreal *points = path.points();
+ const QPainterPath::ElementType *types = path.elements();
+
+ QPainterPath p;
+ if (types) {
+ int id = 0;
+ for (int i=0; i<path.elementCount(); ++i) {
+ switch(types[i]) {
+ case QPainterPath::MoveToElement:
+ p.moveTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ break;
+ case QPainterPath::LineToElement:
+ p.lineTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ break;
+ case QPainterPath::CurveToElement: {
+ QPointF p1(points[id], points[id+1]);
+ QPointF p2(points[id+2], points[id+3]);
+ QPointF p3(points[id+4], points[id+5]);
+ p.cubicTo(p1, p2, p3);
+ id+=6;
+ break;
+ }
+ case QPainterPath::CurveToDataElement:
+ ;
+ break;
+ }
+ }
+ } else {
+ p.moveTo(QPointF(points[0], points[1]));
+ int id = 2;
+ for (int i=1; i<path.elementCount(); ++i) {
+ p.lineTo(QPointF(points[id], points[id+1]));
+ id+=2;
+ }
+ }
+ if (path.hints() & QVectorPath::WindingFill)
+ p.setFillRule(Qt::WindingFill);
+
+ return p;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 50d65e6..9e28102 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -75,6 +75,7 @@
#include <private/qstatictext_p.h>
#include <private/qglyphs_p.h>
#include <private/qstylehelper_p.h>
+#include <private/qrawfont_p.h>
QT_BEGIN_NAMESPACE
@@ -97,10 +98,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat);
// Helper function to calculate left most position, width and flags for decoration drawing
-static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
- const QFixedPoint *positions, int glyphCount,
- QFontEngine *fontEngine, const QFont &font,
- const QTextCharFormat &charFormat);
+Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
+ const QFixedPoint *positions, int glyphCount,
+ QFontEngine *fontEngine, const QFont &font,
+ const QTextCharFormat &charFormat);
static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush)
{
@@ -155,7 +156,8 @@ static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
{
return type == QPaintEngine::OpenGL2
|| type == QPaintEngine::OpenVG
- || type == QPaintEngine::OpenGL;
+ || type == QPaintEngine::OpenGL
+ || type == QPaintEngine::CoreGraphics;
}
#ifndef QT_NO_DEBUG
@@ -502,8 +504,12 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
q->save();
state->matrix = QTransform();
- state->dirtyFlags |= QPaintEngine::DirtyTransform;
- updateState(state);
+ if (extended) {
+ extended->transformChanged();
+ } else {
+ state->dirtyFlags |= QPaintEngine::DirtyTransform;
+ updateState(state);
+ }
engine->drawImage(absPathRect,
image,
QRectF(0, 0, absPathRect.width(), absPathRect.height()),
@@ -686,11 +692,14 @@ void QPainterPrivate::updateInvMatrix()
invMatrix = state->matrix.inverted();
}
+extern bool qt_isExtendedRadialGradient(const QBrush &brush);
+
void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
{
bool alpha = false;
bool linearGradient = false;
bool radialGradient = false;
+ bool extendedRadialGradient = false;
bool conicalGradient = false;
bool patternBrush = false;
bool xform = false;
@@ -722,6 +731,7 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
(brushStyle == Qt::LinearGradientPattern));
radialGradient = ((penBrushStyle == Qt::RadialGradientPattern) ||
(brushStyle == Qt::RadialGradientPattern));
+ extendedRadialGradient = radialGradient && (qt_isExtendedRadialGradient(penBrush) || qt_isExtendedRadialGradient(s->brush));
conicalGradient = ((penBrushStyle == Qt::ConicalGradientPattern) ||
(brushStyle == Qt::ConicalGradientPattern));
patternBrush = (((penBrushStyle > Qt::SolidPattern
@@ -805,7 +815,7 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
s->emulationSpecifier &= ~QPaintEngine::LinearGradientFill;
// Radial gradient emulation
- if (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill))
+ if (extendedRadialGradient || (radialGradient && !engine->hasFeature(QPaintEngine::RadialGradientFill)))
s->emulationSpecifier |= QPaintEngine::RadialGradientFill;
else
s->emulationSpecifier &= ~QPaintEngine::RadialGradientFill;
@@ -5790,12 +5800,14 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
\sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
*/
+#if !defined(QT_NO_RAWFONT)
void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
{
Q_D(QPainter);
- QFont oldFont = d->state->font;
- d->state->font = glyphs.font();
+ QRawFont font = glyphs.font();
+ if (!font.isValid())
+ return;
QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
QVector<QPointF> glyphPositions = glyphs.positions();
@@ -5806,7 +5818,7 @@ void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
bool paintEngineSupportsTransformations =
d->extended != 0
? qt_paintengine_supports_transformations(d->extended->type())
- : false;
+ : qt_paintengine_supports_transformations(d->engine->type());
for (int i=0; i<count; ++i) {
QPointF processedPosition = position + glyphPositions.at(i);
if (!paintEngineSupportsTransformations)
@@ -5814,39 +5826,20 @@ void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
}
- d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count);
-
- d->state->font = oldFont;
-}
-
-void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
- int glyphCount)
-{
- QVarLengthArray<QFixedPoint, 128> positions(glyphCount);
- for (int i=0; i<glyphCount; ++i)
- positions[i] = QFixedPoint::fromPointF(positionArray[i]);
-
- QPainterPrivate *painter_d = QPainterPrivate::get(painter);
- painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount);
+ d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count, font, glyphs.overline(),
+ glyphs.underline(), glyphs.strikeOut());
}
-void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount)
+void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount,
+ const QRawFont &font, bool overline, bool underline,
+ bool strikeOut)
{
Q_Q(QPainter);
updateState(state);
- QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
-
- while (fontEngine->type() == QFontEngine::Multi) {
- // Pick engine based on first glyph in array if we are using a multi engine.
- // (all glyphs must be for same font)
- int engineIdx = 0;
- if (glyphCount > 0)
- engineIdx = glyphArray[0] >> 24;
-
- fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
- }
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ QFontEngine *fontEngine = fontD->fontEngine;
QFixed leftMost;
QFixed rightMost;
@@ -5881,7 +5874,6 @@ void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, in
extended->drawStaticTextItem(&staticTextItem);
} else {
QTextItemInt textItem;
- textItem.f = &state->font;
textItem.fontEngine = fontEngine;
QVarLengthArray<QFixed, 128> advances(glyphCount);
@@ -5903,20 +5895,21 @@ void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, in
}
QTextItemInt::RenderFlags flags;
- if (state->font.underline())
+ if (underline)
flags |= QTextItemInt::Underline;
- if (state->font.overline())
+ if (overline)
flags |= QTextItemInt::Overline;
- if (state->font.strikeOut())
+ if (strikeOut)
flags |= QTextItemInt::StrikeOut;
drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
fontEngine,
- (state->font.underline()
- ? QTextCharFormat::SingleUnderline
- : QTextCharFormat::NoUnderline),
+ (underline
+ ? QTextCharFormat::SingleUnderline
+ : QTextCharFormat::NoUnderline),
flags, width.toReal(), QTextCharFormat());
}
+#endif // QT_NO_RAWFONT
/*!
@@ -6076,9 +6069,9 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
}
d->extended->drawStaticTextItem(item);
- drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions,
- item->numGlyphs, item->fontEngine(), staticText_d->font,
- QTextCharFormat());
+ qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions,
+ item->numGlyphs, item->fontEngine(), staticText_d->font,
+ QTextCharFormat());
}
if (currentColor != oldPen.color())
setPen(oldPen);
@@ -6523,10 +6516,10 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const
painter->setBrush(oldBrush);
}
-static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
- const QFixedPoint *positions, int glyphCount,
- QFontEngine *fontEngine, const QFont &font,
- const QTextCharFormat &charFormat)
+Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray,
+ const QFixedPoint *positions, int glyphCount,
+ QFontEngine *fontEngine, const QFont &font,
+ const QTextCharFormat &charFormat)
{
if (!(font.underline() || font.strikeOut() || font.overline()))
return;
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index ae2fdf2..1a432e6 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -399,7 +399,9 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
+#if !defined(QT_NO_RAWFONT)
void drawGlyphs(const QPointF &position, const QGlyphs &glyphs);
+#endif
void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
@@ -551,6 +553,7 @@ private:
friend class QPaintEngine;
friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
+ friend class QVGPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
friend class QWin32PaintEngine;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 26d8fc3..205c10a 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -184,6 +184,7 @@ struct QPainterDummyState
QTransform transform;
};
+class QRawFont;
class QPainterPrivate
{
Q_DECLARE_PUBLIC(QPainter)
@@ -229,7 +230,12 @@ public:
void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
- void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount);
+
+#if !defined(QT_NO_RAWFONT)
+ void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount,
+ const QRawFont &font, bool overline = false, bool underline = false,
+ bool strikeOut = false);
+#endif
void updateMatrix();
void updateInvMatrix();
@@ -259,8 +265,6 @@ public:
};
Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
-Q_GUI_EXPORT void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray,
- const QPointF *positionArray, int glyphCount);
QString qt_generate_brush_key(const QBrush &brush);
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 2058040..9fbac13 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1126,6 +1126,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
QTextEngine *eng = layout.engine();
layout.beginLayout();
QTextLine line = layout.createLine();
+ Q_UNUSED(line);
layout.endLayout();
const QScriptLine &sl = eng->lines[0];
if (!sl.length || !eng->layoutData)
@@ -1904,7 +1905,7 @@ static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1,
if (y >= bounds.top() && y < bounds.bottom()
&& bounds.right() >= x1 && bounds.left() < x2) {
const qreal lower_bound = qreal(.01);
- if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound)
+ if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
return true;
QBezier first_half, second_half;
@@ -1923,7 +1924,7 @@ static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qr
if (x >= bounds.left() && x < bounds.right()
&& bounds.bottom() >= y1 && bounds.top() < y2) {
const qreal lower_bound = qreal(.01);
- if (depth == 32 || bounds.width() < lower_bound && bounds.height() < lower_bound)
+ if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
return true;
QBezier first_half, second_half;
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index b7f5160..353869f 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -534,7 +534,10 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
QImage image = img;
QImage::Format format = image.format();
- if (image.depth() == 1 && *bitmap && img.colorTable().size() == 0) {
+ if (image.depth() == 1 && *bitmap && img.colorTable().size() == 2
+ && img.colorTable().at(0) == QColor(Qt::black).rgba()
+ && img.colorTable().at(1) == QColor(Qt::white).rgba())
+ {
if (format == QImage::Format_MonoLSB)
image = image.convertToFormat(QImage::Format_Mono);
format = QImage::Format_Mono;
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index fca46b4..dd723ed 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -552,6 +552,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine
// // line to the beginning of the arc segment, (should not be needed).
// emitLineTo(qt_real_to_fixed(curve_start.x()), qt_real_to_fixed(curve_start.y()));
+ Q_UNUSED(curve_start);
for (int i=0; i<point_count; i+=3) {
emitCubicTo(qt_real_to_fixed(curves[i].x()),
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 53f025f..e9e56a2 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -296,7 +296,7 @@ void QTextureGlyphCache::fillInPendingGlyphs()
QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const
{
#if defined(Q_WS_X11)
- if (m_transform.type() > QTransform::TxTranslate) {
+ if (m_transform.type() > QTransform::TxTranslate && m_current_fontengine->type() == QFontEngine::Freetype) {
QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None;
QImage::Format imageFormat = QImage::Format_Invalid;
switch (m_type) {
diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp
index 3876c3d..2fda6b9 100644
--- a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp
+++ b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp
@@ -152,7 +152,8 @@ void QUnifiedToolbarSurface::beginPaint(const QRegion &rgn)
void QUnifiedToolbarSurface::updateToolbarOffset(QWidget *widget)
{
QMainWindowLayout *mlayout = qobject_cast<QMainWindowLayout*> (widget->window()->layout());
- mlayout->updateUnifiedToolbarOffset();
+ if (mlayout)
+ mlayout->updateUnifiedToolbarOffset();
}
void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp
index 0c99f80..f591fcb 100644
--- a/src/gui/s60framework/qs60mainappui.cpp
+++ b/src/gui/s60framework/qs60mainappui.cpp
@@ -62,6 +62,7 @@
//Animated wallpapers in Qt applications are not supported.
const TInt KAknDisableAnimationBackground = 0x02000000;
+const TInt KAknSingleClickCompatible = 0x01000000;
QT_BEGIN_NAMESPACE
@@ -118,8 +119,12 @@ void QS60MainAppUi::ConstructL()
// After 5th Edition S60, native side supports animated wallpapers.
// However, there is no support for that feature on Qt side, so indicate to
// native UI framework that this application will not support background animations.
- if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0)
- flags |= KAknDisableAnimationBackground;
+
+ // Also, add support for single touch for post 5th edition platforms.
+ // This has only impact when launching native dialogs/menus from inside QApplication.
+ if (QSysInfo::s60Version() > QSysInfo::SV_S60_5_0) {
+ flags |= (KAknDisableAnimationBackground | KAknSingleClickCompatible);
+ }
#endif
BaseConstructL(flags);
}
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index cc5fe10..786aab3 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -841,7 +841,6 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
case PE_PanelButtonTool:
painter->save();
if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) {
- QRect rect = option->rect;
QPen oldPen = painter->pen();
if (widget && widget->inherits("QDockWidgetTitleButton")) {
@@ -1241,7 +1240,6 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
QColor borderColor = darkOutline.lighter(110);
QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color());
- QColor innerShadow = mergedColors(borderColor, option->palette.base().color());
int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
@@ -1879,7 +1877,6 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
} else {
alphaCornerColor = mergedColors(option->palette.background().color(), borderColor);
}
- QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color());
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
painter->fillRect(menuItem->rect, menuBackground);
int w = 0;
@@ -2220,7 +2217,6 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
&& tabBarAlignment == Qt::AlignLeft);
QColor light = tab->palette.light().color();
- QColor midlight = tab->palette.midlight().color();
QColor background = tab->palette.background().color();
int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
@@ -2444,14 +2440,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QColor gradientStartColor = option->palette.button().color().lighter(108);
QColor gradientStopColor = mergedColors(option->palette.button().color().darker(108), dark.lighter(150), 70);
- QColor highlightedGradientStartColor = option->palette.button().color();
- QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
-
- QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35);
- QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
-
- QColor buttonShadowAlpha = option->palette.background().color().darker(105);
-
QPalette palette = option->palette;
switch (control) {
@@ -3437,7 +3425,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -3539,8 +3526,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QRect pixmapRect(0, 0, handle.width(), handle.height());
QPainter handlePainter(&cache);
- QColor highlightedGradientStartColor = option->palette.button().color();
- QColor highlightedGradientStopColor = option->palette.light().color();
QColor gradientStartColor = mergedColors(option->palette.button().color().lighter(155),
dark.lighter(155), 50);
QColor gradientStopColor = gradientStartColor.darker(108);
@@ -3557,7 +3542,6 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
// gradient fill
- QRect innerBorder = gradRect;
QRect r = pixmapRect.adjusted(1, 1, -1, -1);
qt_cleanlooks_draw_gradient(&handlePainter, gradRect,
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 8f99d6a..95ebdb4 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -223,16 +223,13 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
--yy;
}
if (!(opt->state & State_Enabled) && !(opt->state & State_On)) {
- int pnt;
- p->setPen(opt->palette.highlightedText().color());
- QPoint offset(1, 1);
- for (pnt = 0; pnt < a.size(); ++pnt)
- a[pnt].translate(offset.x(), offset.y());
+ p->save();
+ p->translate(1, 1);
+ p->setPen(opt->palette.light().color());
p->drawLines(a);
- for (pnt = 0; pnt < a.size(); ++pnt)
- a[pnt].translate(offset.x(), offset.y());
+ p->restore();
}
- p->setPen(opt->palette.text().color());
+ p->setPen((opt->state & State_On) ? opt->palette.highlightedText().color() : opt->palette.text().color());
p->drawLines(a);
break; }
case PE_Frame:
@@ -919,6 +916,7 @@ static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth)
return QSizeF(widthUsed, height);
}
+
void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const
{
Q_Q(const QCommonStyle);
@@ -936,7 +934,7 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
textLayout.setFont(option->font);
textLayout.setText(option->text);
- QSizeF textLayoutSize = viewItemTextLayout(textLayout, textRect.width());
+ viewItemTextLayout(textLayout, textRect.width());
QString elidedText;
qreal height = 0;
diff --git a/src/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp
index 68ade04..6258fe4 100644
--- a/src/gui/styles/qgtkpainter.cpp
+++ b/src/gui/styles/qgtkpainter.cpp
@@ -586,7 +586,6 @@ void QGtkPainter::paintShadow(GtkWidget *gtkWidget, const gchar* part,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
@@ -605,7 +604,6 @@ void QGtkPainter::paintFlatBox(GtkWidget *gtkWidget, const gchar* part,
{
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) % pmKey;
if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
@@ -632,7 +630,6 @@ void QGtkPainter::paintExtention(GtkWidget *gtkWidget,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget)
% HexString<uchar>(gap_pos);
@@ -660,7 +657,6 @@ void QGtkPainter::paintOption(GtkWidget *gtkWidget, const QRect &radiorect,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(detail, state, shadow, rect.size());
GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
@@ -692,7 +688,6 @@ void QGtkPainter::paintCheckbox(GtkWidget *gtkWidget, const QRect &checkrect,
if (!rect.isValid())
return;
- QRect r = rect;
QPixmap cache;
QString pixmapName = uniqueName(detail, state, shadow, rect.size());
GdkRectangle gtkCliprect = {0, 0, rect.width(), rect.height()};
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index 277e302..d6dd527 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -782,7 +782,6 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
GtkStateType state = gtkPainter.gtkState(option);
style = gtkTreeHeader->style;
GtkArrowType type = GTK_ARROW_UP;
- QRect r = header->rect;
QImage arrow;
// This sorting indicator inversion is intentional, and follows the GNOME HIG.
// See http://library.gnome.org/devel/hig-book/stable/controls-lists.html.en#controls-lists-sortable
@@ -1857,7 +1856,6 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
editArea.setRight(upRect.left());
}
if (spinBox->frame) {
- GtkShadowType shadow = GTK_SHADOW_OUT;
GtkStateType state = gtkPainter.gtkState(option);
if (!(option->state & State_Enabled))
@@ -1867,7 +1865,6 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else if (state == GTK_STATE_PRELIGHT)
state = GTK_STATE_NORMAL;
- shadow = GTK_SHADOW_IN;
style = gtkPainter.getStyle(gtkSpinButton);
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 2d21628..18003ce 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -4707,7 +4707,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
HIThemeFrameDrawInfo fdi;
fdi.version = qt_mac_hitheme_version;
- fdi.state = kThemeStateInactive;
+ fdi.state = tds;
fdi.kind = kHIThemeFrameTextFieldSquare;
fdi.isFocused = false;
HIRect hirect = qt_hirectForQRect(lineeditRect);
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 02ce60e..1d33212 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -2007,14 +2007,10 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
} else {
alphaCornerColor = mergedColors(option->palette.background().color(), borderColor);
}
- QColor alphaTextColor = mergedColors(option->palette.background().color(), option->palette.text().color());
QColor gradientStartColor = option->palette.button().color().lighter(104);
QColor gradientStopColor = option->palette.button().color().darker(105);
- QColor shadowGradientStartColor = option->palette.button().color().darker(115);
- QColor shadowGradientStopColor = option->palette.button().color().darker(120);
-
QColor highlightedGradientStartColor = option->palette.button().color().lighter(101);
QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
@@ -2025,8 +2021,6 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
QColor alphaInnerColor = mergedColors(highlightedDarkInnerBorderColor, option->palette.base().color());
- QColor lightShadow = lightShadowGradientStartColor;
- QColor shadow = shadowGradientStartColor;
switch (element) {
#ifndef QT_NO_TABBAR
@@ -3786,10 +3780,6 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
QColor gradientStartColor = option->palette.button().color().lighter(104);
QColor gradientStopColor = option->palette.button().color().darker(105);
- QColor highlightedGradientStartColor = option->palette.button().color().lighter(101);
- QColor highlightedGradientStopColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 85);
- QColor highlightedDarkInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 35);
- QColor highlightedLightInnerBorderColor = mergedColors(option->palette.button().color(), option->palette.highlight().color(), 58);
switch (control) {
#ifndef QT_NO_SLIDER
@@ -3797,7 +3787,6 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect grooveRegion = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index 680e007..fa6eeb7 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -72,6 +72,7 @@
#include "qcheckbox.h"
#include "qdesktopwidget.h"
#include "qprogressbar.h"
+#include "qlabel.h"
#include "private/qtoolbarextension_p.h"
#include "private/qcombobox_p.h"
@@ -681,6 +682,13 @@ void QS60StylePrivate::setThemePalette(QWidget *widget)
if (header->viewport())
header->viewport()->setPalette(widgetPalette);
QApplication::setPalette(widgetPalette, "QHeaderView");
+ } else if (qobject_cast<QLabel *>(widget)) {
+ if (widget->window() && widget->window()->windowType() == Qt::Dialog) {
+ QPalette widgetPalette = widget->palette();
+ widgetPalette.setColor(QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 19, 0));
+ widget->setPalette(widgetPalette);
+ }
}
}
@@ -955,6 +963,17 @@ bool QS60StylePrivate::isWidgetPressed(const QWidget *widget)
return (widget && widget == m_pressedWidget);
}
+// Generates 1*1 white pixmap as a placeholder for real texture.
+// The actual theme texture is drawn in qt_s60_fill_background().
+QPixmap QS60StylePrivate::placeHolderTexture()
+{
+ if (!m_placeHolderTexture) {
+ m_placeHolderTexture = new QPixmap(1,1);
+ m_placeHolderTexture->fill(Qt::green);
+ }
+ return *m_placeHolderTexture;
+}
+
/*!
\class QS60Style
\brief The QS60Style class provides a look and feel suitable for applications on S60.
@@ -1540,8 +1559,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
skinElement==QS60StylePrivate::SE_TabBarTabWestActive) {
const int borderThickness =
QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
- const int tabOverlap =
- QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness;
+ int tabOverlap = pixelMetric(PM_TabBarTabOverlap);
+ if (tabOverlap > borderThickness)
+ tabOverlap -= borderThickness;
+
const bool usesScrollButtons =
(widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false;
const int roomForScrollButton =
@@ -1580,9 +1601,11 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
QStyleOptionTabV3 optionTab = *tab;
QRect tr = optionTab.rect;
const bool directionMirrored = (optionTab.direction == Qt::RightToLeft);
- const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
- const int tabOverlap =
- QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness;
+ const int borderThickness =
+ QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ int tabOverlap = pixelMetric(PM_TabBarTabOverlap);
+ if (tabOverlap > borderThickness)
+ tabOverlap -= borderThickness;
const bool usesScrollButtons =
(widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false;
const int roomForScrollButton =
@@ -2531,6 +2554,11 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const
//without having to define custom pixel metric
metricValue *= 2;
+#if defined(Q_WS_S60)
+ if (metric == PM_TabBarTabOverlap && (QSysInfo::s60Version() > QSysInfo::SV_S60_5_2))
+ metricValue = 0;
+#endif
+
return metricValue;
}
@@ -2645,8 +2673,6 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
}
sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
- //native items have small empty areas at the beginning and end of menu item
- sz.setWidth(sz.width() + 2 * pixelMetric(PM_MenuHMargin) + 2 * QS60StylePrivate::pixelMetric(PM_FrameCornerWidth));
if (QS60StylePrivate::isTouchSupported()) {
//Make itemview easier to use in touch devices
sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin));
@@ -3005,10 +3031,11 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
ret = QCommonStyle::subElementRect(element, opt, widget);
if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
- const int tabOverlapNoBorder =
- QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap);
- const int tabOverlap =
- tabOverlapNoBorder - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ const int borderThickness =
+ QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ int tabOverlap = pixelMetric(PM_TabBarTabOverlap);
+ if (tabOverlap > borderThickness)
+ tabOverlap -= borderThickness;
const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget);
int gain = (tab) ? tabOverlap * tab->count() : 0;
switch (twf->shape) {
@@ -3026,7 +3053,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
if ((ret.right() + gain) > widget->rect().right())
gain = widget->rect().right() - ret.right();
ret.adjust(0, 0, gain, 0);
- }
+ }
}
break;
}
@@ -3114,7 +3141,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
}
break;
case SE_ItemViewItemCheckIndicator:
- if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) {
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
const QAbstractItemView *listItem = qobject_cast<const QAbstractItemView *>(widget);
const bool singleSelection = listItem &&
@@ -3122,7 +3149,7 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
listItem->selectionMode() == QAbstractItemView::NoSelection);
const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) &&
listItem &&
- singleSelection;
+ singleSelection && vopt->text.isEmpty() && vopt->icon.isNull();
// Selection check mark rect.
const int indicatorWidth = QS60StylePrivate::pixelMetric(PM_IndicatorWidth);
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 6a7158c..1e374cb 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -89,17 +89,25 @@ enum TSupportRelease {
ES60_5_0 = 0x0004,
ES60_5_1 = 0x0008,
ES60_5_2 = 0x0010,
+ ES60_5_3 = 0x0020,
ES60_3_X = ES60_3_1 | ES60_3_2,
// Releases before Symbian Foundation
ES60_PreSF = ES60_3_1 | ES60_3_2 | ES60_5_0,
+ // Releases before the S60 5.2
+ ES60_Pre52 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1,
+ // Releases before S60 5.3
+ ES60_Pre53 = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2,
// Add all new releases here
- ES60_All = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2
+ ES60_All = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2 | ES60_5_3
};
typedef struct {
- const TAknsItemID &skinID;
- TDrawType drawType;
- int supportInfo;
+ const TAknsItemID &skinID; // Determines default theme graphics ID.
+ TDrawType drawType; // Determines which native drawing routine is used to draw this item.
+ int supportInfo; // Defines the S60 versions that use the default graphics.
+ // These two, define new graphics that are used in releases other than partMapEntry.supportInfo defined releases.
+ // In general, these are given in numeric form to allow style compilation in earlier
+ // native releases that do not contain the new graphics.
int newMajorSkinId;
int newMinorSkinId;
} partMapEntry;
@@ -188,12 +196,14 @@ const partMapEntry QS60StyleModeSpecifics::m_partMap[] = {
/* SP_QgnGrafScrollArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawGulIcon, ES60_All, -1,-1},
/* SP_QgnGrafScrollArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawGulIcon, ES60_All, -1,-1},
/* SP_QgnGrafScrollArrowUp */ {KAknsIIDQgnGrafScrollArrowUp, EDrawGulIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_All, -1,-1},
- /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_All, -1,-1},
+
+ // In S60 5.3 there is a new tab graphic
+ /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2219}, //KAknsIIDQtgFrTabActiveNormalL
+ /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221b}, //KAknsIIDQtgFrTabActiveNormalC
+ /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x221a}, //KAknsIIDQtgFrTabActiveNormalR
+ /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2221}, //KAknsIIDQtgFrTabPassiveNormalL
+ /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2223}, //KAknsIIDQtgFrTabPassiveNormalC
+ /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_Pre53, EAknsMajorSkin, 0x2222}, //KAknsIIDQtgFrTabPassiveNormalR
// In 3.1 there is no slider groove.
/* SP_QgnGrafNsliderEndLeft */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x19cf /* KAknsIIDQgnGrafNsliderEndLeft */},
@@ -776,16 +786,8 @@ QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
{
CCoeControl *control = targetWidget->effectiveWinId();
TPoint pos(0,0);
- if (control) {
- // FIXME properly: S60 3.1 has a bug that CCoeControl::PositionRelativeToScreen sometimes
- // freezes the device, possibly in cases where we run out of memory.
- // We use CCoeControl::Position instead in S60 3.1, which returns same values
- // in most cases.
- if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1)
- pos = control->Position();
- else
- pos = control->PositionRelativeToScreen();
- }
+ if (control)
+ pos = control->PositionRelativeToScreen();
return QPoint(pos.iX, pos.iY);
}
@@ -1140,7 +1142,8 @@ bool QS60StyleModeSpecifics::checkSupport(const int supportedRelease)
(currentRelease == QSysInfo::SV_S60_3_2 && supportedRelease & ES60_3_2) ||
(currentRelease == QSysInfo::SV_S60_5_0 && supportedRelease & ES60_5_0) ||
(currentRelease == QSysInfo::SV_S60_5_1 && supportedRelease & ES60_5_1) ||
- (currentRelease == QSysInfo::SV_S60_5_2 && supportedRelease & ES60_5_2));
+ (currentRelease == QSysInfo::SV_S60_5_2 && supportedRelease & ES60_5_2) ||
+ (currentRelease == QSysInfo::SV_S60_5_3 && supportedRelease & ES60_5_3) );
}
TAknsItemID QS60StyleModeSpecifics::partSpecificThemeId(int part)
@@ -1429,17 +1432,6 @@ QPixmap QS60StylePrivate::backgroundTexture(bool skipCreation)
return *m_background;
}
-// Generates 1*1 white pixmap as a placeholder for real texture.
-// The actual theme texture is drawn in qt_s60_fill_background().
-QPixmap QS60StylePrivate::placeHolderTexture()
-{
- if (!m_placeHolderTexture) {
- m_placeHolderTexture = new QPixmap(1,1);
- m_placeHolderTexture->fill(Qt::white);
- }
- return *m_placeHolderTexture;
-}
-
QSize QS60StylePrivate::screenSize()
{
return QSize(S60->screenWidthInPixels, S60->screenHeightInPixels);
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index ecf924c..faa929e 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -3323,6 +3323,13 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
}
break;
+ case CE_FocusFrame:
+ if (!rule.hasNativeBorder()) {
+ rule.drawBorder(p, opt->rect);
+ return;
+ }
+ break;
+
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
if (rule.hasDrawable() || rule.hasBox() || rule.hasPosition() || rule.hasPalette() ||
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 44f3f92..754486e 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -1858,8 +1858,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
}
QRect vCheckRect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
- if (checked) {
- if (act && !dis) {
+ if (!menuitem->icon.isNull() && checked) {
+ if (act) {
qDrawShadePanel(p, vCheckRect,
menuitem->palette, true, 1,
&menuitem->palette.brush(QPalette::Button));
@@ -2028,10 +2028,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
&& tabBarAlignment == Qt::AlignLeft);
QColor light = tab->palette.light().color();
- QColor midlight = tab->palette.midlight().color();
QColor dark = tab->palette.dark().color();
QColor shadow = tab->palette.shadow().color();
- QColor background = tab->palette.background().color();
int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp
index 7f1a3ab..123741e 100644
--- a/src/gui/styles/qwindowsvistastyle.cpp
+++ b/src/gui/styles/qwindowsvistastyle.cpp
@@ -969,7 +969,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
{
- if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
+ QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+ if (anim && (btn->state & State_Enabled)) {
anim->paint(painter, option);
} else {
name = QLatin1String("BUTTON");
@@ -996,7 +997,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
!(state & (State_Sunken | State_On)) && !(state & State_MouseOver) &&
(state & State_Enabled) && (state & State_Active))
{
- QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
if (!anim && widget) {
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
startImage.fill(0);
@@ -1074,8 +1074,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
}
if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
- if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) {
- if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) {
+ if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) {
+ if (!d->widgetAnimation(progressbar)) {
QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
a->setWidget(const_cast<QWidget*>(widget));
a->setStartTime(QTime::currentTime());
@@ -2502,7 +2502,6 @@ void QWindowsVistaStylePrivate::timerEvent()
animations[i]->widget()->update();
if (!animations[i]->widget() ||
- !animations[i]->widget()->isEnabled() ||
!animations[i]->widget()->isVisible() ||
animations[i]->widget()->window()->isMinimized() ||
!animations[i]->running() ||
diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp
index 74a20fc..4b2c3a5 100644
--- a/src/gui/styles/qwindowsxpstyle.cpp
+++ b/src/gui/styles/qwindowsxpstyle.cpp
@@ -1196,8 +1196,14 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option))
{
rect = QWindowsStyle::subElementRect(sr, option, widget);
- if (sr == SE_TabWidgetTabContents)
- rect.adjust(0, 0, -2, -2);
+ if (sr == SE_TabWidgetTabContents) {
+ if (const QTabWidget *tabWidget = qobject_cast<const QTabWidget *>(widget)) {
+ if (tabWidget->documentMode())
+ break;
+ }
+
+ rect.adjust(0, 0, -2, -2);
+ }
}
break;
case SE_TabWidgetTabBar: {
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index f77e237..b8cfb1f 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -282,27 +282,16 @@ QFontPrivate::~QFontPrivate()
scFont = 0;
}
-#if !defined(Q_WS_MAC)
extern QMutex *qt_fontdatabase_mutex();
-QFontEngine *QFontPrivate::engineForScript(int script) const
-{
- QMutexLocker locker(qt_fontdatabase_mutex());
- if (script >= QUnicodeTables::Inherited)
- script = QUnicodeTables::Common;
- if (engineData && engineData->fontCache != QFontCache::instance()) {
- // throw out engineData that came from a different thread
- engineData->ref.deref();
- engineData = 0;
- }
- if (!engineData || !engineData->engines[script])
- QFontDatabase::load(this, script);
- return engineData->engines[script];
-}
+#if !defined(Q_WS_MAC)
+#define QT_FONT_ENGINE_FROM_DATA(data, script) data->engines[script]
#else
+#define QT_FONT_ENGINE_FROM_DATA(data, script) data->engine
+#endif
+
QFontEngine *QFontPrivate::engineForScript(int script) const
{
- extern QMutex *qt_fontdatabase_mutex();
QMutexLocker locker(qt_fontdatabase_mutex());
if (script >= QUnicodeTables::Inherited)
script = QUnicodeTables::Common;
@@ -311,11 +300,10 @@ QFontEngine *QFontPrivate::engineForScript(int script) const
engineData->ref.deref();
engineData = 0;
}
- if (!engineData || !engineData->engine)
+ if (!engineData || !QT_FONT_ENGINE_FROM_DATA(engineData, script))
QFontDatabase::load(this, script);
- return engineData->engine;
+ return QT_FONT_ENGINE_FROM_DATA(engineData, script);
}
-#endif
void QFontPrivate::alterCharForCapitalization(QChar &c) const {
switch (capital) {
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 8dbc746..0c7b6f8 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -239,7 +239,7 @@ public:
bool isCopyOf(const QFont &) const;
#ifdef Q_COMPILER_RVALUE_REFS
inline QFont &operator=(QFont &&other)
- { qSwap(d, other.d); return *this; }
+ { qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); return *this; }
#endif
#ifdef Q_WS_WIN
diff --git a/src/gui/text/qfont_win.cpp b/src/gui/text/qfont_win.cpp
index 7d710ea..3ef761b 100644
--- a/src/gui/text/qfont_win.cpp
+++ b/src/gui/text/qfont_win.cpp
@@ -58,6 +58,7 @@
QT_BEGIN_NAMESPACE
extern HDC shared_dc(); // common dc for all fonts
+extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp
// ### maybe move to qapplication_win
QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/)
@@ -65,20 +66,8 @@ QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/)
QString family = QString::fromWCharArray(lf.lfFaceName);
QFont qf(family);
qf.setItalic(lf.lfItalic);
- if (lf.lfWeight != FW_DONTCARE) {
- int weight;
- if (lf.lfWeight < 400)
- weight = QFont::Light;
- else if (lf.lfWeight < 600)
- weight = QFont::Normal;
- else if (lf.lfWeight < 700)
- weight = QFont::DemiBold;
- else if (lf.lfWeight < 800)
- weight = QFont::Bold;
- else
- weight = QFont::Black;
- qf.setWeight(weight);
- }
+ if (lf.lfWeight != FW_DONTCARE)
+ qf.setWeight(weightFromInteger(lf.lfWeight));
int lfh = qAbs(lf.lfHeight);
qf.setPointSizeF(lfh * 72.0 / GetDeviceCaps(shared_dc(),LOGPIXELSY));
qf.setUnderline(false);
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 94f21b8..36b0ea9 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -136,6 +136,21 @@ static int getFontWeight(const QString &weightString)
return (int) QFont::Normal;
}
+// convert 0 ~ 1000 integer to QFont::Weight
+QFont::Weight weightFromInteger(int weight)
+{
+ if (weight < 400)
+ return QFont::Light;
+ else if (weight < 600)
+ return QFont::Normal;
+ else if (weight < 700)
+ return QFont::DemiBold;
+ else if (weight < 800)
+ return QFont::Bold;
+ else
+ return QFont::Black;
+}
+
struct QtFontEncoding
{
signed int encoding : 16;
@@ -497,8 +512,6 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
// ### copied to tools/makeqpf/qpf2.cpp
-#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
-
// see the Unicode subset bitfields in the MSDN docs
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
// Any,
@@ -576,7 +589,7 @@ static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
#define JapaneseCsbBit 17
#define KoreanCsbBit 21
-static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
+QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2])
{
QList<QFontDatabase::WritingSystem> writingSystems;
bool hasScript = false;
@@ -623,7 +636,6 @@ static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBi
return writingSystems;
}
-#endif
#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
// class with virtual destructor, derived in qfontdatabase_s60.cpp
@@ -873,7 +885,7 @@ QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteA
os2->ulCodePageRange1, os2->ulCodePageRange2
};
- writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ writingSystems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
//for (int i = 0; i < writingSystems.count(); ++i)
// qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
}
@@ -936,6 +948,11 @@ static const int scriptForWritingSystem[] = {
QUnicodeTables::Nko // Nko
};
+int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem)
+{
+ return scriptForWritingSystem[writingSystem];
+}
+
#if defined Q_WS_QWS || (defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)) || defined(Q_WS_WIN)
static inline bool requiresOpenType(int writingSystem)
diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp
index ad2c1b2..5ba236b 100644
--- a/src/gui/text/qfontdatabase_mac.cpp
+++ b/src/gui/text/qfontdatabase_mac.cpp
@@ -72,7 +72,7 @@ static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont)
qFromBigEndian<quint32>(os2Table.data() + 54)
};
quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78), qFromBigEndian<quint32>(os2Table.data() + 82) };
- QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
#if 0
QCFString name;
ATSFontGetName(atsFont, kATSOptionFlagsDefault, &name);
@@ -244,6 +244,11 @@ static const char *styleHint(const QFontDef &request)
return stylehint;
}
+static inline float weightToFloat(unsigned int weight)
+{
+ return (weight - 50) / 100.0;
+}
+
void QFontDatabase::load(const QFontPrivate *d, int script)
{
// sanity checks
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 6d3970e..3ab1ac8 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -152,7 +152,6 @@ public:
COpenFontRasterizer *m_rasterizer;
mutable QList<const QSymbianTypeFaceExtras *> m_extras;
- mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash;
mutable QSet<QString> m_applicationFontFamilies;
};
@@ -255,8 +254,9 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
if (!dbExtras)
return; // initializeDb() has never been called
+ QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) {
- qDeleteAll(dbExtras->m_extrasHash);
+ qDeleteAll(extrasHash);
} else {
typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator;
for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) {
@@ -265,11 +265,16 @@ void QSymbianFontDatabaseExtrasImplementation::clear()
}
dbExtras->m_extras.clear();
}
- dbExtras->m_extrasHash.clear();
+ extrasHash.clear();
}
void qt_cleanup_symbianFontDatabase()
{
+ static bool cleanupDone = false;
+ if (cleanupDone)
+ return;
+ cleanupDone = true;
+
QFontDatabasePrivate *db = privateDb();
if (!db)
return;
@@ -320,9 +325,12 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont)
const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface,
bool bold, bool italic) const
{
+ QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData();
+ if (extrasHash.isEmpty() && QThread::currentThread() != QApplication::instance()->thread())
+ S60->addThreadLocalReleaseFunc(clear);
const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface);
const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic));
- if (!m_extrasHash.contains(searchKey)) {
+ if (!extrasHash.contains(searchKey)) {
TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1);
if (bold)
searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
@@ -336,7 +344,7 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font);
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font);
sFont.take();
- m_extrasHash.insert(searchKey, extras);
+ extrasHash.insert(searchKey, extras);
} else {
const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec);
Q_ASSERT(err == KErrNone && font);
@@ -350,20 +358,20 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib();
const QString foundKey =
QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length());
- if (!m_extrasHash.contains(foundKey)) {
+ if (!extrasHash.contains(foundKey)) {
QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font);
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont);
sFont.take();
m_extras.append(extras);
- m_extrasHash.insert(searchKey, extras);
- m_extrasHash.insert(foundKey, extras);
+ extrasHash.insert(searchKey, extras);
+ extrasHash.insert(foundKey, extras);
} else {
m_store->ReleaseFont(font);
- m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey));
+ extrasHash.insert(searchKey, extrasHash.value(foundKey));
}
}
}
- return m_extrasHash.value(searchKey);
+ return extrasHash.value(searchKey);
}
void QSymbianFontDatabaseExtrasImplementation::removeAppFontData(
@@ -521,7 +529,7 @@ static bool registerScreenDeviceFont(int screenDeviceFontIndex,
qFromBigEndian<quint32>(ulCodePageRange + 4)
};
const QList<QFontDatabase::WritingSystem> writingSystems =
- determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
foreach (const QFontDatabase::WritingSystem system, writingSystems)
family->writingSystems[system] = QtFontFamily::Supported;
return true;
@@ -956,7 +964,7 @@ bool QFontDatabase::removeAllApplicationFonts()
bool QFontDatabase::supportsThreadedFontRendering()
{
- return false;
+ return QSymbianTypeFaceExtras::symbianFontTableApiAvailable();
}
static
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index 8279195..05b7509 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -242,6 +242,8 @@ error:
return i18n_name;
}
+extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp
+
static
void addFontToDatabase(QString familyName, const QString &scriptName,
TEXTMETRIC *textmetric,
@@ -274,16 +276,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName,
if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) {
QtFontStyle::Key styleKey;
styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
- if (weight < 400)
- styleKey.weight = QFont::Light;
- else if (weight < 600)
- styleKey.weight = QFont::Normal;
- else if (weight < 700)
- styleKey.weight = QFont::DemiBold;
- else if (weight < 800)
- styleKey.weight = QFont::Bold;
- else
- styleKey.weight = QFont::Black;
+ styleKey.weight = weightFromInteger(weight);
QtFontFamily *family = privateDb()->family(familyName, true);
@@ -340,7 +333,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName,
quint32 codePageRange[2] = {
signature->fsCsb[0], signature->fsCsb[1]
};
- QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange);
for (int i = 0; i < systems.count(); ++i) {
QFontDatabase::WritingSystem writingSystem = systems.at(i);
@@ -530,26 +523,26 @@ static inline void load(const QString &family = QString(), int = -1)
-static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, const QFontPrivate *fp)
+static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, HDC fontHdc, int dpi)
{
fe->fontDef = request; // most settings are equal
- HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fp->hdc) ? fp->hdc : shared_dc();
+ HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fontHdc) ? fontHdc : shared_dc();
SelectObject(dc, fe->hfont);
wchar_t n[64];
GetTextFace(dc, 64, n);
fe->fontDef.family = QString::fromWCharArray(n);
fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
if (fe->fontDef.pointSize < 0) {
- fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / fp->dpi;
+ fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi;
} else if (fe->fontDef.pixelSize == -1) {
- fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * fp->dpi / 72.);
+ fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.);
}
}
#if !defined(QT_NO_DIRECTWRITE)
static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request,
- const QFontPrivate *fp, IDWriteFont *font)
+ int dpi, IDWriteFont *font)
{
fe->fontDef = request;
@@ -601,9 +594,9 @@ static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request,
qErrnoWarning(hr, "initFontInfo: Failed to get family name");
if (fe->fontDef.pointSize < 0)
- fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / fp->dpi;
+ fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi;
else if (fe->fontDef.pixelSize == -1)
- fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * fp->dpi / 72.);
+ fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.);
}
#endif
@@ -679,20 +672,21 @@ static inline HFONT systemFont()
#define DEFAULT_GUI_FONT 17
#endif
-static
-QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &request, const QtFontDesc *desc,
- const QStringList &family_list)
+static QFontEngine *loadEngine(int script, const QFontDef &request,
+ HDC fontHdc, int dpi, bool rawMode,
+ const QtFontDesc *desc,
+ const QStringList &family_list)
{
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
- bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fp->hdc;
+ bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc;
HDC hdc = shared_dc();
- QString font_name = desc->family->name;
+ QString font_name = desc != 0 ? desc->family->name : request.family;
if (useDevice) {
- hdc = fp->hdc;
+ hdc = fontHdc;
font_name = request.family;
}
@@ -710,9 +704,9 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
bool useDirectWrite = false;
#endif
- if (fp->rawMode) { // will choose a stock font
+ if (rawMode) { // will choose a stock font
int f, deffnt = SYSTEM_FONT;
- QString fam = desc->family->name.toLower();
+ QString fam = desc != 0 ? desc->family->name.toLower() : request.family.toLower();
if (fam == QLatin1String("default"))
f = deffnt;
else if (fam == QLatin1String("system"))
@@ -766,11 +760,11 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
lf.lfWidth = 0;
lf.lfEscapement = 0;
lf.lfOrientation = 0;
- if (desc->style->key.weight == 50)
+ if (desc == 0 || desc->style->key.weight == 50)
lf.lfWeight = FW_DONTCARE;
else
lf.lfWeight = (desc->style->key.weight*900)/99;
- lf.lfItalic = (desc->style->key.style != QFont::StyleNormal);
+ lf.lfItalic = (desc != 0 && desc->style->key.style != QFont::StyleNormal);
lf.lfCharSet = DEFAULT_CHARSET;
int strat = OUT_DEFAULT_PRECIS;
@@ -901,9 +895,11 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
&lf,
&directWriteFont);
if (FAILED(hr)) {
+#ifndef QT_NO_DEBUG
qErrnoWarning("QFontEngine::loadEngine: CreateFontFromLOGFONT failed "
"for %ls (0x%lx)",
lf.lfFaceName, hr);
+#endif
} else {
DeleteObject(hfont);
useDirectWrite = true;
@@ -933,22 +929,27 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
}
}
- initFontInfo(few, request, fp);
+ initFontInfo(few, request, fontHdc, dpi);
fe = few;
}
#if !defined(QT_NO_DIRECTWRITE)
else {
QFontDatabasePrivate *db = privateDb();
- QFontEngineDirectWrite *fedw = new QFontEngineDirectWrite(font_name,
- db->directWriteFactory,
- db->directWriteGdiInterop,
- directWriteFont,
- request.pixelSize);
- initFontInfo(fedw, request, fp, directWriteFont);
+ IDWriteFontFace *directWriteFontFace = NULL;
+ HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace);
+ if (SUCCEEDED(hr)) {
+ QFontEngineDirectWrite *fedw = new QFontEngineDirectWrite(db->directWriteFactory,
+ directWriteFontFace,
+ request.pixelSize);
+
+ initFontInfo(fedw, request, dpi, directWriteFont);
- fe = fedw;
+ fe = fedw;
+ } else {
+ qErrnoWarning(hr, "QFontEngine::loadEngine: CreateFontFace failed");
+ }
}
if (directWriteFont != 0)
@@ -957,6 +958,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
if(script == QUnicodeTables::Common
&& !(request.styleStrategy & QFont::NoFontMerging)
+ && desc != 0
&& !(desc->family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) {
if(!tryFonts) {
LANGID lid = GetUserDefaultLangID();
@@ -993,6 +995,20 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
return fe;
}
+QFontEngine *qt_load_font_engine_win(const QFontDef &request)
+{
+ // From qfont.cpp
+ extern int qt_defaultDpi();
+
+ QFontCache::Key key(request, QUnicodeTables::Common);
+ QFontEngine *fe = QFontCache::instance()->findEngine(key);
+ if (fe != 0)
+ return fe;
+ else
+ return loadEngine(QUnicodeTables::Common, request, 0, qt_defaultDpi(), false, 0,
+ QStringList());
+}
+
const char *styleHint(const QFontDef &request)
{
const char *stylehint = 0;
@@ -1053,7 +1069,7 @@ static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &r
}
if (!desc.family)
break;
- fe = loadEngine(script, d, req, &desc, family_list);
+ fe = loadEngine(script, req, d->hdc, d->dpi, d->rawMode, &desc, family_list);
if (!fe)
blacklistedFamilies.append(desc.familyIndex);
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 3adf4eb..2f76cc6 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -237,24 +237,6 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
return metrics;
}
-QFont QFontEngine::createExplicitFont() const
-{
- return createExplicitFontWithName(fontDef.family);
-}
-
-QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const
-{
- QFont font(familyName);
- font.setStyleStrategy(QFont::NoFontMerging);
- font.setWeight(fontDef.weight);
- font.setItalic(fontDef.style == QFont::StyleItalic);
- if (fontDef.pointSize < 0)
- font.setPixelSize(fontDef.pixelSize);
- else
- font.setPointSizeF(fontDef.pointSize);
- return font;
-}
-
QFixed QFontEngine::xHeight() const
{
QGlyphLayoutArray<8> glyphs;
diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm
index 4d9192e..d4df218 100644
--- a/src/gui/text/qfontengine_coretext.mm
+++ b/src/gui/text/qfontengine_coretext.mm
@@ -52,6 +52,31 @@ QT_BEGIN_NAMESPACE
static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
+static void loadAdvancesForGlyphs(CTFontRef ctfont,
+ QVarLengthArray<CGGlyph> &cgGlyphs,
+ QGlyphLayout *glyphs, int len,
+ QTextEngine::ShaperFlags flags,
+ const QFontDef &fontDef)
+{
+ Q_UNUSED(flags);
+ QVarLengthArray<CGSize> advances(len);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
+
+ for (int i = 0; i < len; ++i) {
+ if (glyphs->glyphs[i] & 0xff000000)
+ continue;
+ glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
+ glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
+ }
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ for (int i = 0; i < len; ++i) {
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = glyphs->advances_y[i].round();
+ }
+ }
+}
+
QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning)
: QFontEngineMulti(0)
{
@@ -83,7 +108,31 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const
ctfont = baseFont;
CFRetain(ctfont);
}
+ init(kerning);
+}
+
+QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning)
+ : QFontEngineMulti(0)
+{
+ this->fontDef = fontDef;
+
+ transform = CGAffineTransformIdentity;
+ if (fontDef.stretch != 100) {
+ transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
+ }
+ ctfont = CTFontCreateWithGraphicsFont(cgFontRef, fontDef.pixelSize, &transform, NULL);
+ init(kerning);
+}
+
+QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
+{
+ CFRelease(ctfont);
+}
+
+void QCoreTextFontEngineMulti::init(bool kerning)
+{
+ Q_ASSERT(ctfont != NULL);
attributeDict = CFDictionaryCreateMutable(0, 2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
@@ -94,33 +143,29 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const
CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern);
}
- QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this);
+ QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef);
fe->ref.ref();
engines.append(fe);
-
}
-QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
-{
- CFRelease(ctfont);
-}
-
-uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef id) const
+uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef font) const
{
for (int i = 0; i < engines.count(); ++i) {
- if (CFEqual(engineAt(i)->ctfont, id))
+ if (CFEqual(engineAt(i)->ctfont, font))
return i;
}
QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
- QCoreTextFontEngine *fe = new QCoreTextFontEngine(id, fontDef, that);
+ QCoreTextFontEngine *fe = new QCoreTextFontEngine(font, fontDef);
fe->ref.ref();
that->engines.append(fe);
return engines.count() - 1;
}
-bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *) const
+bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QTextEngine::ShaperFlags flags,
+ unsigned short *logClusters, const HB_CharAttributes *,
+ QScriptItem *si) const
{
QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0,
reinterpret_cast<const UniChar *>(str),
@@ -137,6 +182,8 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
&kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options);
} else
+#else
+ Q_UNUSED(flags);
#endif
typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
@@ -176,6 +223,25 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
CFRange stringRange = CTRunGetStringRange(run);
+ int prepend = 0;
+#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5
+ UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location);
+ QChar dir = QChar::direction(beginGlyph);
+ bool beginWithOverride = dir == QChar::DirLRO || dir == QChar::DirRLO || dir == QChar::DirLRE || dir == QChar::DirRLE;
+ if (beginWithOverride) {
+ logClusters[stringRange.location] = 0;
+ outGlyphs[0] = 0xFFFF;
+ outAdvances_x[0] = 0;
+ outAdvances_y[0] = 0;
+ outAttributes[0].clusterStart = true;
+ outAttributes[0].dontPrint = true;
+ outGlyphs++;
+ outAdvances_x++;
+ outAdvances_y++;
+ outAttributes++;
+ prepend = 1;
+ }
+#endif
UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1);
bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF;
if (endWithPDF)
@@ -190,7 +256,12 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
if (!runAttribs)
runAttribs = attributeDict;
CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName));
- const uint fontIndex = (fontIndexForFont(runFont) << 24);
+ uint fontIndex = fontIndexForFont(runFont);
+ const QFontEngine *engine = engineAt(fontIndex);
+ fontIndex <<= 24;
+ si->ascent = qMax(engine->ascent(), si->ascent);
+ si->descent = qMax(engine->descent(), si->descent);
+ si->leading = qMax(engine->leading(), si->leading);
//NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
if (endWithPDF)
glyphCount--;
@@ -228,9 +299,9 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CFIndex k = 0;
CFIndex i = 0;
- for (i = stringRange.location;
+ for (i = stringRange.location + prepend;
(i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
- if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) {
+ if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) {
logClusters[i] = k + firstGlyphIndex;
outAttributes[k].clusterStart = true;
++k;
@@ -265,7 +336,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
: QFixed::fromReal(lastGlyphAdvance.width);
if (endWithPDF) {
- logClusters[stringRange.location + stringRange.length - 1] = glyphCount;
+ logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend;
outGlyphs[glyphCount] = 0xFFFF;
outAdvances_x[glyphCount] = 0;
outAdvances_y[glyphCount] = 0;
@@ -317,72 +388,45 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
if (flags & QTextEngine::GlyphIndicesOnly)
return true;
- QVarLengthArray<CGSize> advances(len);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
-
- for (int i = 0; i < len; ++i) {
- if (glyphs->glyphs[i] & 0xff000000)
- continue;
- glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
- glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
- }
-
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- for (int i = 0; i < len; ++i) {
- glyphs->advances_x[i] = glyphs->advances_x[i].round();
- glyphs->advances_y[i] = glyphs->advances_y[i].round();
- }
- }
-
+ loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef);
return true;
}
-void QCoreTextFontEngineMulti::recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
-{
-}
-void QCoreTextFontEngineMulti::doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
-{
-}
-
void QCoreTextFontEngineMulti::loadEngine(int)
{
// Do nothing
Q_ASSERT(false);
}
+extern int qt_antialiasing_threshold; // from qapplication.cpp
+static inline CGAffineTransform transformFromFontDef(const QFontDef &fontDef)
+{
+ CGAffineTransform transform = CGAffineTransformIdentity;
+ if (fontDef.stretch != 100)
+ transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
+ return transform;
+}
-QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
- QCoreTextFontEngineMulti *multiEngine)
+QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def)
{
fontDef = def;
- parentEngine = multiEngine;
- synthesisFlags = 0;
+ transform = transformFromFontDef(fontDef);
ctfont = font;
CFRetain(ctfont);
- cgFont = CTFontCopyGraphicsFont(ctfont, NULL);
- CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
- if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) {
- synthesisFlags |= SynthesizedBold;
- }
-
- if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait)) {
- synthesisFlags |= SynthesizedItalic;
- }
- transform = CGAffineTransformIdentity;
- if (fontDef.stretch != 100) {
- transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
- }
- QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
- if (os2Table.size() >= 10)
- fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8));
+ cgFont = CTFontCopyGraphicsFont(font, NULL);
+ init();
+}
- QSettings appleSettings(QLatin1String("apple.com"));
- QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
- if (appleValue.isValid())
- antialiasing_threshold = appleValue.toInt();
- else
- antialiasing_threshold = -1;
+QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def)
+{
+ fontDef = def;
+ transform = transformFromFontDef(fontDef);
+ cgFont = font;
+ // Keep reference count balanced
+ CFRetain(cgFont);
+ ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, NULL);
+ init();
}
QCoreTextFontEngine::~QCoreTextFontEngine()
@@ -391,9 +435,89 @@ QCoreTextFontEngine::~QCoreTextFontEngine()
CFRelease(ctfont);
}
-bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *, QTextEngine::ShaperFlags) const
+extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp
+
+int getTraitValue(CFDictionaryRef allTraits, CFStringRef trait)
+{
+ if (CFDictionaryContainsKey(allTraits, trait)) {
+ CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait);
+ float v = 0;
+ CFNumberGetValue(traitNum, kCFNumberFloatType, &v);
+ // the value we get from CFNumberRef is from -1.0 to 1.0
+ int value = v * 500 + 500;
+ return value;
+ }
+
+ return 0;
+}
+
+void QCoreTextFontEngine::init()
{
- return false;
+ Q_ASSERT(ctfont != NULL);
+ Q_ASSERT(cgFont != NULL);
+
+ QCFString family = CTFontCopyFamilyName(ctfont);
+ fontDef.family = family;
+
+ synthesisFlags = 0;
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
+ if (traits & kCTFontItalicTrait)
+ fontDef.style = QFont::StyleItalic;
+
+ CFDictionaryRef allTraits = CTFontCopyTraits(ctfont);
+ fontDef.weight = weightFromInteger(getTraitValue(allTraits, kCTFontWeightTrait));
+ int slant = getTraitValue(allTraits, kCTFontSlantTrait);
+ if (slant > 500 && !(traits & kCTFontItalicTrait))
+ fontDef.style = QFont::StyleOblique;
+ CFRelease(allTraits);
+
+ if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait))
+ synthesisFlags |= SynthesizedBold;
+ // XXX: we probably don't need to synthesis italic for oblique font
+ if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait))
+ synthesisFlags |= SynthesizedItalic;
+
+ avgCharWidth = 0;
+ QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ unsigned emSize = CTFontGetUnitsPerEm(ctfont);
+ if (os2Table.size() >= 10) {
+ fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8));
+ // qAbs is a workaround for weird fonts like Lucida Grande
+ qint16 width = qAbs(qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 2)));
+ avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize);
+ } else
+ avgCharWidth = QFontEngine::averageCharWidth();
+
+ ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0;
+ QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ if (hheaTable.size() >= 16) {
+ quint16 width = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 10));
+ ctMaxCharWidth = width * fontDef.pixelSize / emSize;
+ qint16 bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 12));
+ ctMinLeftBearing = bearing * fontDef.pixelSize / emSize;
+ bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 14));
+ ctMinRightBearing = bearing * fontDef.pixelSize / emSize;
+ }
+}
+
+bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QTextEngine::ShaperFlags flags) const
+{
+ *nglyphs = len;
+ QCFType<CFStringRef> cfstring;
+
+ QVarLengthArray<CGGlyph> cgGlyphs(len);
+ CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
+
+ for (int i = 0; i < len; ++i)
+ if (cgGlyphs[i])
+ glyphs->glyphs[i] = cgGlyphs[i];
+
+ if (flags & QTextEngine::GlyphIndicesOnly)
+ return true;
+
+ loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef);
+ return true;
}
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
@@ -407,6 +531,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
}
return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0);
}
+
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
{
glyph_metrics_t ret;
@@ -460,31 +585,29 @@ QFixed QCoreTextFontEngine::xHeight() const
? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
: QFixed::fromReal(CTFontGetXHeight(ctfont));
}
+
QFixed QCoreTextFontEngine::averageCharWidth() const
{
- // ### Need to implement properly and get the information from the OS/2 Table.
return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFontEngine::averageCharWidth().round()
- : QFontEngine::averageCharWidth();
+ ? avgCharWidth.round() : avgCharWidth;
}
qreal QCoreTextFontEngine::maxCharWidth() const
{
- // ### Max Help!
- return 0;
-
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(ctMaxCharWidth) : ctMaxCharWidth;
}
+
qreal QCoreTextFontEngine::minLeftBearing() const
{
- // ### Min Help!
- return 0;
-
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(ctMinLeftBearing) : ctMinLeftBearing;
}
+
qreal QCoreTextFontEngine::minRightBearing() const
{
- // ### Max Help! (even thought it's right)
- return 0;
-
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? qRound(ctMinRightBearing) : ctMinLeftBearing;
}
void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
@@ -602,12 +725,6 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position
}
}
-QFont QCoreTextFontEngine::createExplicitFont() const
-{
- QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont));
- return createExplicitFontWithName(familyName);
-}
-
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa)
{
const glyph_metrics_t br = boundingBox(glyph);
@@ -624,7 +741,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
cgflags);
CGContextSetFontSize(ctx, fontDef.pixelSize);
CGContextSetShouldAntialias(ctx, aa ||
- (fontDef.pointSize > antialiasing_threshold
+ (fontDef.pointSize > qt_antialiasing_threshold
&& !(fontDef.styleStrategy & QFont::NoAntialias)));
CGContextSetShouldSmoothFonts(ctx, aa);
CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
@@ -696,12 +813,19 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo
return im;
}
-void QCoreTextFontEngine::recalcAdvances(int numGlyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
+void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
{
- Q_ASSERT(false);
- Q_UNUSED(numGlyphs);
- Q_UNUSED(glyphs);
- Q_UNUSED(flags);
+ int i, numGlyphs = glyphs->numGlyphs;
+ QVarLengthArray<CGGlyph> cgGlyphs(numGlyphs);
+
+ for (i = 0; i < numGlyphs; ++i) {
+ if (glyphs->glyphs[i] & 0xff000000)
+ cgGlyphs[i] = 0;
+ else
+ cgGlyphs[i] = glyphs->glyphs[i];
+ }
+
+ loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef);
}
QFontEngine::FaceId QCoreTextFontEngine::faceId() const
@@ -711,36 +835,45 @@ QFontEngine::FaceId QCoreTextFontEngine::faceId() const
bool QCoreTextFontEngine::canRender(const QChar *string, int len)
{
- QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
- QCFType<CFStringRef>(CFStringCreateWithCharactersNoCopy(0,
- reinterpret_cast<const UniChar *>(string),
- len, kCFAllocatorNull)),
- CFRangeMake(0, len));
- return retFont != 0;
- return false;
-}
-
- bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
- {
- QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
- if (!table || !length)
- return false;
- CFIndex tableLength = CFDataGetLength(table);
- int availableLength = *length;
- *length = tableLength;
- if (buffer) {
- if (tableLength > availableLength)
- return false;
- CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
- }
- return true;
- }
+ QVarLengthArray<CGGlyph> cgGlyphs(len);
+ return CTFontGetGlyphsForCharacters(ctfont, (const UniChar *) string, cgGlyphs.data(), len);
+}
+
+bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+{
+ QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
+ if (!table || !length)
+ return false;
+ CFIndex tableLength = CFDataGetLength(table);
+ int availableLength = *length;
+ *length = tableLength;
+ if (buffer) {
+ if (tableLength > availableLength)
+ return false;
+ CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
+ }
+ return true;
+}
void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *)
{
// ###
}
+QFixed QCoreTextFontEngine::emSquareSize() const
+{
+ return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
+}
+
+QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
+{
+ QFontDef newFontDef = fontDef;
+ newFontDef.pixelSize = pixelSize;
+ newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi();
+
+ return new QCoreTextFontEngine(cgFont, fontDef);
+}
+
QT_END_NAMESPACE
#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
diff --git a/src/gui/text/qfontengine_coretext_p.h b/src/gui/text/qfontengine_coretext_p.h
index 7d17aef..bb80a9b 100644
--- a/src/gui/text/qfontengine_coretext_p.h
+++ b/src/gui/text/qfontengine_coretext_p.h
@@ -46,15 +46,17 @@
#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+class QRawFontPrivate;
class QCoreTextFontEngineMulti;
class QCoreTextFontEngine : public QFontEngine
{
public:
- QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
- QCoreTextFontEngineMulti *multiEngine = 0);
+ QCoreTextFontEngine(CTFontRef font, const QFontDef &def);
+ QCoreTextFontEngine(CGFontRef font, const QFontDef &def);
~QCoreTextFontEngine();
+
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
- virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
+ virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
virtual glyph_metrics_t boundingBox(glyph_t glyph);
@@ -87,44 +89,50 @@ public:
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
virtual qreal minRightBearing() const;
virtual qreal minLeftBearing() const;
- virtual QFont createExplicitFont() const;
+ virtual QFixed emSquareSize() const;
+
+ virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
private:
+ friend class QRawFontPrivate;
+
+ void init();
QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful);
CTFontRef ctfont;
CGFontRef cgFont;
- QCoreTextFontEngineMulti *parentEngine;
int synthesisFlags;
CGAffineTransform transform;
+ QFixed avgCharWidth;
+ qreal ctMaxCharWidth;
+ qreal ctMinLeftBearing;
+ qreal ctMinRightBearing;
friend class QCoreTextFontEngineMulti;
- int antialiasing_threshold;
};
class QCoreTextFontEngineMulti : public QFontEngineMulti
{
public:
QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning);
+ QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning);
~QCoreTextFontEngineMulti();
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
QTextEngine::ShaperFlags flags) const;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
-
-
- virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
- virtual void doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
+ unsigned short *logClusters, const HB_CharAttributes *charAttributes,
+ QScriptItem *si) const;
virtual const char *name() const { return "CoreText"; }
protected:
virtual void loadEngine(int at);
private:
+ void init(bool kerning);
inline const QCoreTextFontEngine *engineAt(int i) const
{ return static_cast<const QCoreTextFontEngine *>(engines.at(i)); }
- uint fontIndexForFont(CTFontRef id) const;
+ uint fontIndexForFont(CTFontRef font) const;
CTFontRef ctfont;
mutable QCFType<CFMutableDictionaryRef> attributeDict;
CGAffineTransform transform;
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index ffdaaa7..237cde4 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -200,9 +200,10 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
* Returns the freetype face or 0 in case of an empty file or any other problems
* (like not being able to open the file)
*/
-QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
+QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
+ const QByteArray &fontData)
{
- if (face_id.filename.isEmpty())
+ if (face_id.filename.isEmpty() && fontData.isEmpty())
return 0;
QtFreetypeData *freetypeData = qt_getFreetypeData();
@@ -215,21 +216,25 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
} else {
QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
FT_Face face;
- QFile file(QString::fromUtf8(face_id.filename));
- if (face_id.filename.startsWith(":qmemoryfonts/")) {
- // from qfontdatabase.cpp
- extern QByteArray qt_fontdata_from_index(int);
- QByteArray idx = face_id.filename;
- idx.remove(0, 14); // remove ':qmemoryfonts/'
- bool ok = false;
- newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
- if (!ok)
- newFreetype->fontData = QByteArray();
- } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
- if (!file.open(QIODevice::ReadOnly)) {
- return 0;
+ if (!face_id.filename.isEmpty()) {
+ QFile file(QString::fromUtf8(face_id.filename));
+ if (face_id.filename.startsWith(":qmemoryfonts/")) {
+ // from qfontdatabase.cpp
+ extern QByteArray qt_fontdata_from_index(int);
+ QByteArray idx = face_id.filename;
+ idx.remove(0, 14); // remove ':qmemoryfonts/'
+ bool ok = false;
+ newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
+ if (!ok)
+ newFreetype->fontData = QByteArray();
+ } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
+ if (!file.open(QIODevice::ReadOnly)) {
+ return 0;
+ }
+ newFreetype->fontData = file.readAll();
}
- newFreetype->fontData = file.readAll();
+ } else {
+ newFreetype->fontData = fontData;
}
if (!newFreetype->fontData.isEmpty()) {
if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) {
@@ -651,8 +656,21 @@ void QFontEngineFT::freeGlyphSets()
freeServerGlyphSet(transformedGlyphSets.at(i).id);
}
-bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
+bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
+ const QByteArray &fontData)
+{
+ return init(faceId, antialias, format, QFreetypeFace::getFace(faceId, fontData));
+}
+
+bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
+ QFreetypeFace *freetypeFace)
{
+ freetype = freetypeFace;
+ if (!freetype) {
+ xsize = 0;
+ ysize = 0;
+ return false;
+ }
defaultFormat = format;
this->antialias = antialias;
@@ -664,12 +682,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
face_id = faceId;
- freetype = QFreetypeFace::getFace(face_id);
- if (!freetype) {
- xsize = 0;
- ysize = 0;
- return false;
- }
symbol = freetype->symbol_map != 0;
PS_FontInfoRec psrec;
@@ -1511,7 +1523,7 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
mtx->lock();
}
- if (FcCharSetHasChar(freetype->charset, uc)) {
+ if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
#else
if (false) {
#endif
@@ -1546,7 +1558,7 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
mtx->lock();
}
- if (FcCharSetHasChar(freetype->charset, uc))
+ if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
#endif
{
redo:
@@ -1957,6 +1969,41 @@ HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
return result;
}
+bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe)
+{
+ if (!init(fe->faceId(), fe->antialias, fe->defaultFormat, fe->freetype))
+ return false;
+
+ // Increase the reference of this QFreetypeFace since one more QFontEngineFT
+ // will be using it
+ freetype->ref.ref();
+
+ default_load_flags = fe->default_load_flags;
+ default_hint_style = fe->default_hint_style;
+ antialias = fe->antialias;
+ transform = fe->transform;
+ embolden = fe->embolden;
+ subpixelType = fe->subpixelType;
+ lcdFilterType = fe->lcdFilterType;
+ canUploadGlyphsToServer = fe->canUploadGlyphsToServer;
+ embeddedbitmap = fe->embeddedbitmap;
+
+ return true;
+}
+
+QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const
+{
+ QFontDef fontDef;
+ fontDef.pixelSize = pixelSize;
+ QFontEngineFT *fe = new QFontEngineFT(fontDef);
+ if (!fe->initFromFontEngine(this)) {
+ delete fe;
+ return 0;
+ } else {
+ return fe;
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FREETYPE
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 451d26e..a620006 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -74,6 +74,8 @@
QT_BEGIN_NAMESPACE
+class QFontEngineFTRawFont;
+
/*
* This struct represents one font file on disk (like Arial.ttf) and is shared between all the font engines
* that show this font file (at different pixel sizes).
@@ -84,7 +86,8 @@ struct QFreetypeFace
QFontEngine::Properties properties() const;
bool getSfntTable(uint tag, uchar *buffer, uint *length) const;
- static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id);
+ static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id,
+ const QByteArray &fontData = QByteArray());
void release(const QFontEngine::FaceId &face_id);
// locks the struct for usage. Any read/write operations require locking.
@@ -119,6 +122,7 @@ struct QFreetypeFace
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false);
private:
+ friend class QFontEngineFT;
friend class QScopedPointerDeleter<QFreetypeFace>;
QFreetypeFace() : _lock(QMutex::Recursive) {}
~QFreetypeFace() {}
@@ -300,7 +304,10 @@ private:
QFontEngineFT(const QFontDef &fd);
virtual ~QFontEngineFT();
- bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None);
+ bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None,
+ const QByteArray &fontData = QByteArray());
+ bool init(FaceId faceId, bool antialias, GlyphFormat format,
+ QFreetypeFace *freetypeFace);
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
@@ -312,6 +319,11 @@ private:
};
void setDefaultHintStyle(HintStyle style);
+
+ virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
+ bool initFromFontEngine(const QFontEngineFT *fontEngine);
+
+ HintStyle defaultHintStyle() const { return default_hint_style; }
protected:
void freeGlyphSets();
@@ -335,6 +347,8 @@ protected:
bool embeddedbitmap;
private:
+ friend class QFontEngineFTRawFont;
+
int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
GlyphFormat defaultFormat;
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 7751bbe..9f094ad 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -377,7 +377,7 @@ bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *
}
bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *charAttributes) const
+ unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const
{
if (*nglyphs < len) {
*nglyphs = len;
@@ -922,27 +922,6 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint
DisposeATSCubicClosePathUPP(closePath);
}
-QFont QFontEngineMac::createExplicitFont() const
-{
- FMFont fmFont = FMGetFontFromATSFontRef(fontID);
-
- FMFontFamily fmFamily;
- FMFontStyle fmStyle;
- QString familyName;
- if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) {
- ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily);
- QCFString cfFamilyName;;
- ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName);
- familyName = cfFamilyName;
- } else {
- QCFString cfFontName;
- ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName);
- familyName = cfFontName;
- }
-
- return createExplicitFontWithName(familyName);
-}
-
void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path,
QTextItem::RenderFlags)
{
diff --git a/src/gui/text/qfontengine_mac_p.h b/src/gui/text/qfontengine_mac_p.h
index 6967348..292ea98 100644
--- a/src/gui/text/qfontengine_mac_p.h
+++ b/src/gui/text/qfontengine_mac_p.h
@@ -66,8 +66,6 @@ public:
virtual qreal maxCharWidth() const;
virtual QFixed averageCharWidth() const;
- virtual QFont createExplicitFont() const;
-
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
QPainterPath *path, QTextItem::RenderFlags);
@@ -133,7 +131,7 @@ public:
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
+ unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const;
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 7b29993..6db0aa6 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -185,9 +185,6 @@ public:
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
- /* Creates a QFont object to represent this particular QFontEngine */
- virtual QFont createExplicitFont() const;
-
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
@@ -238,6 +235,8 @@ public:
virtual int glyphCount() const;
+ virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return 0; }
+
HB_Font harfbuzzFont() const;
HB_Face harfbuzzFace() const;
@@ -276,7 +275,6 @@ public:
int glyphFormat;
protected:
- QFont createExplicitFontWithName(const QString &familyName) const;
static const QVector<QRgb> &grayPalette();
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
@@ -431,6 +429,7 @@ public:
protected:
friend class QPSPrintEnginePrivate;
friend class QPSPrintEngineFontMulti;
+ friend class QRawFont;
virtual void loadEngine(int at) = 0;
QVector<QFontEngine *> engines;
};
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index 82d9da0..54d7ec2 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -1284,6 +1284,23 @@ QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, co
return rgbMask;
}
+// From qfontdatabase_win.cpp
+extern QFontEngine *qt_load_font_engine_win(const QFontDef &request);
+QFontEngine *QFontEngineWin::cloneWithSize(qreal pixelSize) const
+{
+ QFontDef request = fontDef;
+ QString actualFontName = request.family;
+ if (!uniqueFamilyName.isEmpty())
+ request.family = uniqueFamilyName;
+ request.pixelSize = pixelSize;
+
+ QFontEngine *fontEngine = qt_load_font_engine_win(request);
+ if (fontEngine != NULL)
+ fontEngine->fontDef.family = actualFontName;
+
+ return fontEngine;
+}
+
// -------------------------------------- Multi font engine
QFontEngineMultiWin::QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks)
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index 28d8000..114149d 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -106,6 +106,8 @@ public:
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
+ virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
+
#ifndef Q_CC_MINGW
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
#endif
@@ -118,6 +120,7 @@ public:
#endif
QString _name;
+ QString uniqueFamilyName;
HFONT hfont;
LOGFONT logfont;
uint stockFont : 1;
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index 9f3f8d3..4260b85 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -1196,6 +1196,20 @@ bool QFontEngineX11FT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *
#endif
}
+QFontEngine *QFontEngineX11FT::cloneWithSize(qreal pixelSize) const
+{
+ QFontDef fontDef;
+ fontDef.pixelSize = pixelSize;
+ QFontEngineX11FT *fe = new QFontEngineX11FT(fontDef);
+ if (!fe->initFromFontEngine(this)) {
+ delete fe;
+ return 0;
+ } else {
+ fe->xglyph_format = xglyph_format;
+ return fe;
+ }
+}
+
#endif // QT_NO_FONTCONFIG
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_x11_p.h b/src/gui/text/qfontengine_x11_p.h
index 2a4a9cd..d7eb39d 100644
--- a/src/gui/text/qfontengine_x11_p.h
+++ b/src/gui/text/qfontengine_x11_p.h
@@ -157,9 +157,12 @@ private:
class Q_GUI_EXPORT QFontEngineX11FT : public QFontEngineFT
{
public:
+ explicit QFontEngineX11FT(const QFontDef &fontDef) : QFontEngineFT(fontDef) {}
explicit QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen);
~QFontEngineX11FT();
+ QFontEngine *cloneWithSize(qreal pixelSize) const;
+
#ifndef QT_NO_XRENDER
int xglyph_format;
#endif
diff --git a/src/gui/text/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp
index af5bab2..aab00c0 100644
--- a/src/gui/text/qfontenginedirectwrite.cpp
+++ b/src/gui/text/qfontenginedirectwrite.cpp
@@ -170,17 +170,12 @@ namespace {
}
-QFontEngineDirectWrite::QFontEngineDirectWrite(const QString &name,
- IDWriteFactory *directWriteFactory,
- IDWriteGdiInterop *directWriteGdiInterop,
- IDWriteFont *directWriteFont,
+QFontEngineDirectWrite::QFontEngineDirectWrite(IDWriteFactory *directWriteFactory,
+ IDWriteFontFace *directWriteFontFace,
qreal pixelSize)
- : m_name(name)
- , m_directWriteFont(directWriteFont)
- , m_directWriteFontFace(0)
+ : m_directWriteFontFace(directWriteFontFace)
, m_directWriteFactory(directWriteFactory)
, m_directWriteBitmapRenderTarget(0)
- , m_directWriteGdiInterop(directWriteGdiInterop)
, m_lineThickness(-1)
, m_unitsPerEm(-1)
, m_ascent(-1)
@@ -188,24 +183,17 @@ QFontEngineDirectWrite::QFontEngineDirectWrite(const QString &name,
, m_xHeight(-1)
, m_lineGap(-1)
{
- m_directWriteFont->AddRef();
m_directWriteFactory->AddRef();
- m_directWriteGdiInterop->AddRef();
+ m_directWriteFontFace->AddRef();
fontDef.pixelSize = pixelSize;
-
- HRESULT hr = m_directWriteFont->CreateFontFace(&m_directWriteFontFace);
- if (FAILED(hr))
- qErrnoWarning("QFontEngineDirectWrite: CreateFontFace failed");
-
collectMetrics();
}
QFontEngineDirectWrite::~QFontEngineDirectWrite()
{
- m_directWriteFont->Release();
m_directWriteFactory->Release();
- m_directWriteGdiInterop->Release();
+ m_directWriteFontFace->Release();
if (m_directWriteBitmapRenderTarget != 0)
m_directWriteBitmapRenderTarget->Release();
@@ -213,10 +201,10 @@ QFontEngineDirectWrite::~QFontEngineDirectWrite()
void QFontEngineDirectWrite::collectMetrics()
{
- if (m_directWriteFont != 0) {
+ if (m_directWriteFontFace != 0) {
DWRITE_FONT_METRICS metrics;
- m_directWriteFont->GetMetrics(&metrics);
+ m_directWriteFontFace->GetMetrics(&metrics);
m_unitsPerEm = metrics.designUnitsPerEm;
m_lineThickness = DESIGN_TO_LOGICAL(metrics.underlineThickness);
@@ -616,19 +604,25 @@ const char *QFontEngineDirectWrite::name() const
bool QFontEngineDirectWrite::canRender(const QChar *string, int len)
{
- for (int i=0; i<len; ++i) {
- BOOL exists;
- UINT32 codePoint = getChar(string, i, len);
- HRESULT hr = m_directWriteFont->HasCharacter(codePoint, &exists);
- if (FAILED(hr)) {
- qErrnoWarning("QFontEngineDirectWrite::canRender: HasCharacter failed");
- return false;
- } else if (!exists) {
- return false;
+ QVarLengthArray<UINT32> codePoints(len);
+ int actualLength = 0;
+ for (int i=0; i<len; ++i, actualLength++)
+ codePoints[actualLength] = getChar(string, i, len);
+
+ QVarLengthArray<UINT16> glyphIndices(actualLength);
+ HRESULT hr = m_directWriteFontFace->GetGlyphIndices(codePoints.data(), actualLength,
+ glyphIndices.data());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "QFontEngineDirectWrite::canRender: GetGlyphIndices failed");
+ return false;
+ } else {
+ for (int i=0; i<glyphIndices.size(); ++i) {
+ if (glyphIndices.at(i) == 0)
+ return false;
}
- }
- return true;
+ return true;
+ }
}
QFontEngine::Type QFontEngineDirectWrite::type() const
@@ -636,6 +630,17 @@ QFontEngine::Type QFontEngineDirectWrite::type() const
return QFontEngine::DirectWrite;
}
+QFontEngine *QFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const
+{
+ QFontEngine *fontEngine = new QFontEngineDirectWrite(m_directWriteFactory, m_directWriteFontFace,
+ pixelSize);
+
+ fontEngine->fontDef = fontDef;
+ fontEngine->fontDef.pixelSize = pixelSize;
+
+ return fontEngine;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DIRECTWRITE
diff --git a/src/gui/text/qfontenginedirectwrite_p.h b/src/gui/text/qfontenginedirectwrite_p.h
index 80f90b8..53a4b0a 100644
--- a/src/gui/text/qfontenginedirectwrite_p.h
+++ b/src/gui/text/qfontenginedirectwrite_p.h
@@ -69,10 +69,8 @@ class QFontEngineDirectWrite : public QFontEngine
{
Q_OBJECT
public:
- explicit QFontEngineDirectWrite(const QString &name,
- IDWriteFactory *directWriteFactory,
- IDWriteGdiInterop *directWriteGdiInterop,
- IDWriteFont *directWriteFont,
+ explicit QFontEngineDirectWrite(IDWriteFactory *directWriteFactory,
+ IDWriteFontFace *directWriteFontFace,
qreal pixelSize);
~QFontEngineDirectWrite();
@@ -103,19 +101,20 @@ public:
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin,
const QTransform &xform);
+ QFontEngine *cloneWithSize(qreal pixelSize) const;
+
bool canRender(const QChar *string, int len);
Type type() const;
private:
+ friend class QRawFontPrivate;
+
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
void collectMetrics();
- QString m_name;
- IDWriteFont *m_directWriteFont;
IDWriteFontFace *m_directWriteFontFace;
IDWriteFactory *m_directWriteFactory;
IDWriteBitmapRenderTarget *m_directWriteBitmapRenderTarget;
- IDWriteGdiInterop *m_directWriteGdiInterop;
QFixed m_lineThickness;
int m_unitsPerEm;
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index 501bfff..4057142 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -195,6 +195,10 @@ public:
head->root = new_root;
}
+ inline bool isValid(uint n) const {
+ return n > 0 && n != head->freelist;
+ }
+
union {
Header *head;
Fragment *fragments;
@@ -854,6 +858,7 @@ public:
return data.fragment(index);
}
inline uint position(uint node, uint field = 0) const { return data.position(node, field); }
+ inline bool isValid(uint n) const { return data.isValid(n); }
inline uint next(uint n) const { return data.next(n); }
inline uint previous(uint n) const { return data.previous(n); }
inline uint size(uint node, uint field = 0) const { return data.size(node, field); }
diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp
index affa08a..cfea6ec 100644
--- a/src/gui/text/qglyphs.cpp
+++ b/src/gui/text/qglyphs.cpp
@@ -39,6 +39,10 @@
**
****************************************************************************/
+#include "qglobal.h"
+
+#if !defined(QT_NO_RAWFONT)
+
#include "qglyphs.h"
#include "qglyphs_p.h"
@@ -46,7 +50,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QGlyphs
- \brief the QGlyphs class provides direct access to the internal glyphs in a font
+ \brief The QGlyphs class provides direct access to the internal glyphs in a font.
\since 4.8
\ingroup text
@@ -69,8 +73,14 @@ QT_BEGIN_NAMESPACE
It is the user's responsibility to ensure that the selected font actually contains the
provided glyph indexes.
- QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs
- objects, and QPainter::drawGlyphs() can be used to draw the glyphs.
+ QTextLayout::glyphs() or QTextFragment::glyphs() can be used to convert unicode encoded text
+ into a list of QGlyphs objects, and QPainter::drawGlyphs() can be used to draw the glyphs.
+
+ \note Please note that QRawFont is considered local to the thread in which it is constructed.
+ This in turn means that a new QRawFont will have to be created and set on the QGlyphs if it is
+ moved to a different thread. If the QGlyphs contains a reference to a QRawFont from a different
+ thread than the current, it will not be possible to draw the glyphs using a QPainter, as the
+ QRawFont is considered invalid and inaccessible in this case.
*/
@@ -124,6 +134,9 @@ bool QGlyphs::operator==(const QGlyphs &other) const
return ((d == other.d)
|| (d->glyphIndexes == other.d->glyphIndexes
&& d->glyphPositions == other.d->glyphPositions
+ && d->overline == other.d->overline
+ && d->underline == other.d->underline
+ && d->strikeOut == other.d->strikeOut
&& d->font == other.d->font));
}
@@ -171,18 +184,17 @@ QGlyphs &QGlyphs::operator+=(const QGlyphs &other)
\sa setFont()
*/
-QFont QGlyphs::font() const
+QRawFont QGlyphs::font() const
{
return d->font;
}
/*!
- Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly
- resolvable font which defines glyphs for the specified glyph indexes.
+ Sets the font in which to look up the glyph indexes to \a font.
\sa font(), setGlyphIndexes()
*/
-void QGlyphs::setFont(const QFont &font)
+void QGlyphs::setFont(const QRawFont &font)
{
detach();
d->font = font;
@@ -234,7 +246,78 @@ void QGlyphs::clear()
detach();
d->glyphPositions = QVector<QPointF>();
d->glyphIndexes = QVector<quint32>();
- d->font = QFont();
+ d->font = QRawFont();
+ d->strikeOut = false;
+ d->overline = false;
+ d->underline = false;
+}
+
+/*!
+ Returns true if this QGlyphs should be painted with an overline decoration.
+
+ \sa setOverline()
+*/
+bool QGlyphs::overline() const
+{
+ return d->overline;
+}
+
+/*!
+ Indicates that this QGlyphs should be painted with an overline decoration if \a overline is true.
+ Otherwise the QGlyphs should be painted with no overline decoration.
+
+ \sa overline()
+*/
+void QGlyphs::setOverline(bool overline)
+{
+ detach();
+ d->overline = overline;
+}
+
+/*!
+ Returns true if this QGlyphs should be painted with an underline decoration.
+
+ \sa setUnderline()
+*/
+bool QGlyphs::underline() const
+{
+ return d->underline;
+}
+
+/*!
+ Indicates that this QGlyphs should be painted with an underline decoration if \a underline is
+ true. Otherwise the QGlyphs should be painted with no underline decoration.
+
+ \sa underline()
+*/
+void QGlyphs::setUnderline(bool underline)
+{
+ detach();
+ d->underline = underline;
+}
+
+/*!
+ Returns true if this QGlyphs should be painted with a strike out decoration.
+
+ \sa setStrikeOut()
+*/
+bool QGlyphs::strikeOut() const
+{
+ return d->strikeOut;
+}
+
+/*!
+ Indicates that this QGlyphs should be painted with an strike out decoration if \a strikeOut is
+ true. Otherwise the QGlyphs should be painted with no strike out decoration.
+
+ \sa strikeOut()
+*/
+void QGlyphs::setStrikeOut(bool strikeOut)
+{
+ detach();
+ d->strikeOut = strikeOut;
}
QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h
index 5f37136..4d7dcaf 100644
--- a/src/gui/text/qglyphs.h
+++ b/src/gui/text/qglyphs.h
@@ -45,7 +45,9 @@
#include <QtCore/qsharedpointer.h>
#include <QtCore/qvector.h>
#include <QtCore/qpoint.h>
-#include <QtGui/qfont.h>
+#include <QtGui/qrawfont.h>
+
+#if !defined(QT_NO_RAWFONT)
QT_BEGIN_HEADER
@@ -61,8 +63,8 @@ public:
QGlyphs(const QGlyphs &other);
~QGlyphs();
- QFont font() const;
- void setFont(const QFont &font);
+ QRawFont font() const;
+ void setFont(const QRawFont &font);
QVector<quint32> glyphIndexes() const;
void setGlyphIndexes(const QVector<quint32> &glyphIndexes);
@@ -76,6 +78,15 @@ public:
bool operator==(const QGlyphs &other) const;
bool operator!=(const QGlyphs &other) const;
+ void setOverline(bool overline);
+ bool overline() const;
+
+ void setUnderline(bool underline);
+ bool underline() const;
+
+ void setStrikeOut(bool strikeOut);
+ bool strikeOut() const;
+
private:
friend class QGlyphsPrivate;
friend class QTextLine;
@@ -85,12 +96,12 @@ private:
void detach();
QExplicitlySharedDataPointer<QGlyphsPrivate> d;
-
};
QT_END_NAMESPACE
QT_END_HEADER
+#endif // QT_NO_RAWFONT
#endif // QGLYPHS_H
diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h
index c632e2f..944f777 100644
--- a/src/gui/text/qglyphs_p.h
+++ b/src/gui/text/qglyphs_p.h
@@ -53,8 +53,12 @@
// We mean it.
//
-#include <qfont.h>
#include "qglyphs.h"
+#include "qrawfont.h"
+
+#include <qfont.h>
+
+#if !defined(QT_NO_RAWFONT)
QT_BEGIN_HEADER
@@ -64,17 +68,30 @@ class QGlyphsPrivate: public QSharedData
{
public:
QGlyphsPrivate()
+ : overline(false)
+ , underline(false)
+ , strikeOut(false)
{
}
QGlyphsPrivate(const QGlyphsPrivate &other)
- : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font)
+ : QSharedData(other)
+ , glyphIndexes(other.glyphIndexes)
+ , glyphPositions(other.glyphPositions)
+ , font(other.font)
+ , overline(other.overline)
+ , underline(other.underline)
+ , strikeOut(other.strikeOut)
{
}
QVector<quint32> glyphIndexes;
QVector<QPointF> glyphPositions;
- QFont font;
+ QRawFont font;
+
+ uint overline : 1;
+ uint underline : 1;
+ uint strikeOut : 1;
};
QT_END_NAMESPACE
@@ -82,3 +99,5 @@ QT_END_NAMESPACE
QT_END_HEADER
#endif // QGLYPHS_P_H
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp
index 6fa25e7..82ec279 100644
--- a/src/gui/text/qplatformfontdatabase_qpa.cpp
+++ b/src/gui/text/qplatformfontdatabase_qpa.cpp
@@ -218,6 +218,16 @@ QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicode
return engine;
}
+QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ Q_UNUSED(fontData);
+ Q_UNUSED(pixelSize);
+ Q_UNUSED(hintingPreference);
+ qWarning("This plugin does not support font engines created directly from font data");
+ return 0;
+}
+
/*!
*/
diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h
index e0e4f04..046311f 100644
--- a/src/gui/text/qplatformfontdatabase_qpa.h
+++ b/src/gui/text/qplatformfontdatabase_qpa.h
@@ -92,6 +92,8 @@ public:
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual void releaseHandle(void *handle);
+ virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
+
virtual QString fontDir() const;
//callback
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
new file mode 100644
index 0000000..46c892c
--- /dev/null
+++ b/src/gui/text/qrawfont.cpp
@@ -0,0 +1,675 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#if !defined(QT_NO_RAWFONT)
+
+#include "qrawfont.h"
+#include "qrawfont_p.h"
+
+#include <QtCore/qthread.h>
+#include <QtCore/qendian.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRawFont
+ \brief The QRawFont class provides access to a single physical instance of a font.
+ \since 4.8
+
+ \ingroup text
+ \mainclass
+
+ \note QRawFont is a low level class. For most purposes QFont is a more appropriate class.
+
+ Most commonly, when presenting text in a user interface, the exact fonts used
+ to render the characters is to some extent unknown. This can be the case for several
+ reasons: For instance, the actual, physical fonts present on the target system could be
+ unexpected to the developers, or the text could contain user selected styles, sizes or
+ writing systems that are not supported by font chosen in the code.
+
+ Therefore, Qt's QFont class really represents a query for fonts. When text is interpreted,
+ Qt will do its best to match the text to the query, but depending on the support, different
+ fonts can be used behind the scenes.
+
+ For most use cases, this is both expected and necessary, as it minimizes the possibility of
+ text in the user interface being undisplayable. In some cases, however, more direct control
+ over the process might be useful. It is for these use cases the QRawFont class exists.
+
+ A QRawFont object represents a single, physical instance of a given font in a given pixel size.
+ I.e. in the typical case it represents a set of TrueType or OpenType font tables and uses a
+ user specified pixel size to convert metrics into logical pixel units. In can be used in
+ combination with the QGlyphs class to draw specific glyph indexes at specific positions, and
+ also have accessors to some relevant data in the physical font.
+
+ QRawFont only provides support for the main font technologies: GDI and DirectWrite on Windows
+ platforms, FreeType on Symbian and Linux platforms and CoreText on Mac OS X. For other
+ font back-ends, the APIs will be disabled.
+
+ QRawFont can be constructed in a number of ways:
+ \list
+ \o \l It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The
+ returned QGlyphs objects will contain QRawFont objects which represent the actual fonts
+ used to render each portion of the text.
+ \o \l It can be constructed by passing a QFont object to QRawFont::fromFont(). The function
+ will return a QRawFont object representing the font that will be selected as response to
+ the QFont query and the selected writing system.
+ \o \l It can be constructed by passing a file name or QByteArray directly to the QRawFont
+ constructor, or by calling loadFromFile() or loadFromData(). In this case, the
+ font will not be registered in QFontDatabase, and it will not be available as part of
+ regular font selection.
+ \endlist
+
+ QRawFont is considered local to the thread in which it is constructed (either using a
+ constructor, or by calling loadFromData() or loadFromFile()). The QRawFont cannot be moved to a
+ different thread, but will have to be recreated in the thread in question.
+
+ \note For the requirement of caching glyph indexes and font selections for static text to avoid
+ reshaping and relayouting in the inner loop of an application, a better choice is the QStaticText
+ class, since it optimizes the memory cost of the cache and also provides the possibility of paint
+ engine specific caches for an additional speed-up.
+*/
+
+/*!
+ \enum QRawFont::AntialiasingType
+
+ This enum represents the different ways a glyph can be rasterized in the function
+ alphaMapForGlyph().
+
+ \value PixelAntialiasing Will rasterize by measuring the coverage of the shape on whole pixels.
+ The returned image contains the alpha values of each pixel based on the coverage of
+ the glyph shape.
+ \value SubPixelAntialiasing Will rasterize by measuring the coverage of each subpixel,
+ returning a separate alpha value for each of the red, green and blue components of
+ each pixel.
+*/
+
+/*!
+ Constructs an invalid QRawFont.
+*/
+QRawFont::QRawFont()
+ : d(new QRawFontPrivate)
+{
+}
+
+/*!
+ Constructs a QRawFont representing the font contained in the file referenced by \a fileName,
+ with \a pixelSize size in pixels, and the selected \a hintingPreference.
+
+ \note The referenced file must contain a TrueType or OpenType font.
+*/
+QRawFont::QRawFont(const QString &fileName,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+ : d(new QRawFontPrivate)
+{
+ loadFromFile(fileName, pixelSize, hintingPreference);
+}
+
+/*!
+ Constructs a QRawFont representing the font contained in \a fontData.
+
+ \note The data must contain a TrueType or OpenType font.
+*/
+QRawFont::QRawFont(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+ : d(new QRawFontPrivate)
+{
+ loadFromData(fontData, pixelSize, hintingPreference);
+}
+
+/*!
+ Creates a QRawFont which is a copy of \a other.
+*/
+QRawFont::QRawFont(const QRawFont &other)
+{
+ d = other.d;
+}
+
+/*!
+ Destroys the QRawFont
+*/
+QRawFont::~QRawFont()
+{
+}
+
+/*!
+ Assigns \a other to this QRawFont.
+*/
+QRawFont &QRawFont::operator=(const QRawFont &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if the QRawFont is valid and false otherwise.
+*/
+bool QRawFont::isValid() const
+{
+ Q_ASSERT(d->thread == 0 || d->thread == QThread::currentThread());
+ return d->fontEngine != 0;
+}
+
+/*!
+ Replaces the current QRawFont with the contents of the file references by \a fileName.
+
+ The file must reference a TrueType or OpenType font.
+
+ \sa loadFromData()
+*/
+void QRawFont::loadFromFile(const QString &fileName,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly))
+ loadFromData(file.readAll(), pixelSize, hintingPreference);
+}
+
+/*!
+ Replaces the current QRawFont with the contents of \a fontData.
+
+ The \a fontData must contain a TrueType or OpenType font.
+
+ \sa loadFromFile()
+*/
+void QRawFont::loadFromData(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ detach();
+ d->cleanUp();
+ d->hintingPreference = hintingPreference;
+ d->thread = QThread::currentThread();
+ d->platformLoadFromData(fontData, pixelSize, hintingPreference);
+}
+
+/*!
+ This function returns a rasterized image of the glyph at a given \a glyphIndex in the underlying
+ font, if the QRawFont is valid, otherwise it will return an invalid QImage.
+
+ If \a antialiasingType is set to QRawFont::SubPixelAntialiasing, then the resulting image will be
+ in QImage::Format_RGB32 and the RGB values of each pixel will represent the subpixel opacities of
+ the pixel in the rasterization of the glyph. Otherwise, the image will be in the format of
+ QImage::Format_A8 and each pixel will contain the opacity of the pixel in the rasterization.
+
+ \sa pathForGlyph(), QPainter::drawGlyphs()
+*/
+QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialiasingType,
+ const QTransform &transform) const
+{
+ if (!isValid())
+ return QImage();
+
+ if (antialiasingType == SubPixelAntialiasing)
+ return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), 0, transform);
+ else
+ return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), transform);
+}
+
+/*!
+ This function returns the shape of the glyph at a given \a glyphIndex in the underlying font
+ if the QRawFont is valid. Otherwise, it returns an empty QPainterPath.
+
+ The returned glyph will always be unhinted.
+
+ \sa alphaMapForGlyph(), QPainterPath::addText()
+*/
+QPainterPath QRawFont::pathForGlyph(quint32 glyphIndex) const
+{
+ if (!isValid())
+ return QPainterPath();
+
+ QFixedPoint position;
+ QPainterPath path;
+ d->fontEngine->addGlyphsToPath(&glyphIndex, &position, 1, &path, 0);
+ return path;
+}
+
+/*!
+ Returns true if this QRawFont is equal to \a other. Otherwise, returns false.
+*/
+bool QRawFont::operator==(const QRawFont &other) const
+{
+ return d->fontEngine == other.d->fontEngine;
+}
+
+/*!
+ Returns the ascent of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::ascent()
+*/
+qreal QRawFont::ascent() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->ascent().toReal();
+}
+
+/*!
+ Returns the descent of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::descent()
+*/
+qreal QRawFont::descent() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->descent().toReal();
+}
+
+/*!
+ Returns the xHeight of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::xHeight()
+*/
+qreal QRawFont::xHeight() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->xHeight().toReal();
+}
+
+/*!
+ Returns the leading of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::leading()
+*/
+qreal QRawFont::leading() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->leading().toReal();
+}
+
+/*!
+ Returns the average character width of this QRawFont in pixel units.
+
+ \sa QFontMetricsF::averageCharWidth()
+*/
+qreal QRawFont::averageCharWidth() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->averageCharWidth().toReal();
+}
+
+/*!
+ Returns the width of the widest character in the font.
+
+ \sa QFontMetricsF::maxWidth()
+*/
+qreal QRawFont::maxCharWidth() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->maxCharWidth();
+}
+
+/*!
+ Returns the pixel size set for this QRawFont. The pixel size affects how glyphs are
+ rasterized, the size of glyphs returned by pathForGlyph(), and is used to convert
+ internal metrics from design units to logical pixel units.
+
+ \sa setPixelSize()
+*/
+qreal QRawFont::pixelSize() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->fontDef.pixelSize;
+}
+
+/*!
+ Returns the number of design units define the width and height of the em square
+ for this QRawFont. This value is used together with the pixel size when converting design metrics
+ to pixel units, as the internal metrics are specified in design units and the pixel size gives
+ the size of 1 em in pixels.
+
+ \sa pixelSize(), setPixelSize()
+*/
+qreal QRawFont::unitsPerEm() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->emSquareSize().toReal();
+}
+
+/*!
+ Returns the family name of this QRawFont.
+*/
+QString QRawFont::familyName() const
+{
+ if (!isValid())
+ return QString();
+
+ return d->fontEngine->fontDef.family;
+}
+
+/*!
+ Returns the style of this QRawFont.
+
+ \sa QFont::style()
+*/
+QFont::Style QRawFont::style() const
+{
+ if (!isValid())
+ return QFont::StyleNormal;
+
+ return QFont::Style(d->fontEngine->fontDef.style);
+}
+
+/*!
+ Returns the weight of this QRawFont.
+
+ \sa QFont::weight()
+*/
+int QRawFont::weight() const
+{
+ if (!isValid())
+ return -1;
+
+ return int(d->fontEngine->fontDef.weight);
+}
+
+/*!
+ Converts a string of unicode points to glyph indexes using the CMAP table in the
+ underlying font. Note that in cases where there are other tables in the font that affect the
+ shaping of the text, the returned glyph indexes will not correctly represent the rendering
+ of the text. To get the correctly shaped text, you can use QTextLayout to lay out and shape the
+ text, and then call QTextLayout::glyphs() to get the set of glyph index list and QRawFont pairs.
+
+ \sa advancesForGlyphIndexes(), QGlyphs, QTextLayout::glyphs(), QTextFragment::glyphs()
+*/
+QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
+{
+ if (!isValid())
+ return QVector<quint32>();
+
+ int nglyphs = text.size();
+ QVarLengthGlyphLayoutArray glyphs(nglyphs);
+ if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &nglyphs,
+ QTextEngine::GlyphIndicesOnly)) {
+ glyphs.resize(nglyphs);
+ if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &nglyphs,
+ QTextEngine::GlyphIndicesOnly)) {
+ Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
+ return QVector<quint32>();
+ }
+ }
+
+ QVector<quint32> glyphIndexes;
+ for (int i=0; i<nglyphs; ++i)
+ glyphIndexes.append(glyphs.glyphs[i]);
+
+ return glyphIndexes;
+}
+
+/*!
+ Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances
+ give the distance from the position of a given glyph to where the next glyph should be drawn
+ to make it appear as if the two glyphs are unspaced.
+
+ \sa QTextLine::horizontalAdvance(), QFontMetricsF::width()
+*/
+QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const
+{
+ if (!isValid())
+ return QVector<QPointF>();
+
+ int numGlyphs = glyphIndexes.size();
+ QVarLengthGlyphLayoutArray glyphs(numGlyphs);
+ qMemCopy(glyphs.glyphs, glyphIndexes.data(), numGlyphs * sizeof(quint32));
+
+ d->fontEngine->recalcAdvances(&glyphs, 0);
+
+ QVector<QPointF> advances;
+ for (int i=0; i<numGlyphs; ++i)
+ advances.append(QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal()));
+
+ return advances;
+}
+
+/*!
+ Returns the hinting preference used to construct this QRawFont.
+
+ \sa QFont::hintingPreference()
+*/
+QFont::HintingPreference QRawFont::hintingPreference() const
+{
+ if (!isValid())
+ return QFont::PreferDefaultHinting;
+
+ return d->hintingPreference;
+}
+
+/*!
+ Retrieves the sfnt table named \a tagName from the underlying physical font, or an empty
+ byte array if no such table was found. The returned font table's byte order is Big Endian, like
+ the sfnt format specifies. The \a tagName must be four characters long and should be formatted
+ in the default endianness of the current platform.
+*/
+QByteArray QRawFont::fontTable(const char *tagName) const
+{
+ if (!isValid())
+ return QByteArray();
+
+ const quint32 *tagId = reinterpret_cast<const quint32 *>(tagName);
+ return d->fontEngine->getSfntTable(qToBigEndian(*tagId));
+}
+
+// From qfontdatabase.cpp
+extern QList<QFontDatabase::WritingSystem> qt_determine_writing_systems_from_truetype_bits(quint32 unicodeRange[4], quint32 codePageRange[2]);
+
+/*!
+ Returns a list of writing systems supported by the font according to designer supplied
+ information in the font file. Please note that this does not guarantee support for a
+ specific unicode point in the font. You can use the supportsCharacter() to check support
+ for a single, specific character.
+
+ \note The list is determined based on the unicode ranges and codepage ranges set in the font's
+ OS/2 table and requires such a table to be present in the underlying font file.
+
+ \sa supportsCharacter()
+*/
+QList<QFontDatabase::WritingSystem> QRawFont::supportedWritingSystems() const
+{
+ if (isValid()) {
+ QByteArray os2Table = fontTable("OS/2");
+ if (!os2Table.isEmpty() && os2Table.size() > 86) {
+ char *data = os2Table.data();
+ quint32 *bigEndianUnicodeRanges = reinterpret_cast<quint32 *>(data + 42);
+ quint32 *bigEndianCodepageRanges = reinterpret_cast<quint32 *>(data + 78);
+
+ quint32 unicodeRanges[4];
+ quint32 codepageRanges[2];
+
+ for (int i=0; i<4; ++i) {
+ if (i < 2)
+ codepageRanges[i] = qFromBigEndian(bigEndianCodepageRanges[i]);
+ unicodeRanges[i] = qFromBigEndian(bigEndianUnicodeRanges[i]);
+ }
+
+ return qt_determine_writing_systems_from_truetype_bits(unicodeRanges, codepageRanges);
+ }
+ }
+
+ return QList<QFontDatabase::WritingSystem>();
+}
+
+/*!
+ Returns true if the font has a glyph that corresponds to the given \a character.
+
+ \sa supportedWritingSystems()
+*/
+bool QRawFont::supportsCharacter(const QChar &character) const
+{
+ if (!isValid())
+ return false;
+
+ return d->fontEngine->canRender(&character, 1);
+}
+
+/*!
+ Returns true if the font has a glyph that corresponds to the UCS-4 encoded character \a ucs4.
+
+ \sa supportedWritingSystems()
+*/
+bool QRawFont::supportsCharacter(quint32 ucs4) const
+{
+ if (!isValid())
+ return false;
+
+ QString str = QString::fromUcs4(&ucs4, 1);
+ return d->fontEngine->canRender(str.constData(), str.size());
+}
+
+// qfontdatabase.cpp
+extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSystem);
+
+/*!
+ Fetches the physical representation based on a \a font query. The physical font returned is
+ the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
+*/
+QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
+{
+#if defined(Q_WS_MAC)
+ QTextLayout layout(QFontDatabase::writingSystemSample(writingSystem), font);
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+ QList<QGlyphs> list = layout.glyphs();
+ if (list.size()) {
+ // Pick the one matches the family name we originally requested,
+ // if none of them match, just pick the first one
+ for (int i = 0; i < list.size(); i++) {
+ QGlyphs glyphs = list.at(i);
+ QRawFont rawfont = glyphs.font();
+ if (rawfont.familyName() == font.family())
+ return rawfont;
+ }
+ return list.at(0).font();
+ }
+ return QRawFont();
+#else
+ QFontPrivate *font_d = QFontPrivate::get(font);
+ int script = qt_script_for_writing_system(writingSystem);
+ QFontEngine *fe = font_d->engineForScript(script);
+
+ if (fe != 0 && fe->type() == QFontEngine::Multi) {
+ QFontEngineMulti *multiEngine = static_cast<QFontEngineMulti *>(fe);
+ fe = multiEngine->engine(0);
+ if (fe == 0) {
+ multiEngine->loadEngine(0);
+ fe = multiEngine->engine(0);
+ }
+ }
+
+ if (fe != 0) {
+ QRawFont rawFont;
+ rawFont.d.data()->fontEngine = fe;
+ rawFont.d.data()->fontEngine->ref.ref();
+ rawFont.d.data()->hintingPreference = font.hintingPreference();
+ return rawFont;
+ } else {
+ return QRawFont();
+ }
+#endif
+}
+
+/*!
+ Sets the pixel size with which this font should be rendered to \a pixelSize.
+*/
+void QRawFont::setPixelSize(qreal pixelSize)
+{
+ if (d->fontEngine == 0)
+ return;
+
+ detach();
+ QFontEngine *oldFontEngine = d->fontEngine;
+
+ d->fontEngine = d->fontEngine->cloneWithSize(pixelSize);
+ if (d->fontEngine != 0)
+ d->fontEngine->ref.ref();
+
+ oldFontEngine->ref.deref();
+ if (oldFontEngine->cache_count == 0 && oldFontEngine->ref == 0)
+ delete oldFontEngine;
+}
+
+/*!
+ \internal
+*/
+void QRawFont::detach()
+{
+ if (d->ref != 1)
+ d.detach();
+}
+
+/*!
+ \internal
+*/
+void QRawFontPrivate::cleanUp()
+{
+ platformCleanUp();
+ if (fontEngine != 0) {
+ fontEngine->ref.deref();
+ if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
+ delete fontEngine;
+ fontEngine = 0;
+ }
+ hintingPreference = QFont::PreferDefaultHinting;
+}
+
+#endif // QT_NO_RAWFONT
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
new file mode 100644
index 0000000..900c07a
--- /dev/null
+++ b/src/gui/text/qrawfont.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRAWFONT_H
+#define QRAWFONT_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qfont.h>
+#include <QtGui/qtransform.h>
+#include <QtGui/qfontdatabase.h>
+
+#if !defined(QT_NO_RAWFONT)
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QRawFontPrivate;
+class Q_GUI_EXPORT QRawFont
+{
+public:
+ enum AntialiasingType {
+ PixelAntialiasing,
+ SubPixelAntialiasing
+ };
+
+ QRawFont();
+ QRawFont(const QString &fileName,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
+ QRawFont(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting);
+ QRawFont(const QRawFont &other);
+ ~QRawFont();
+
+ bool isValid() const;
+
+ QRawFont &operator=(const QRawFont &other);
+ bool operator==(const QRawFont &other) const;
+
+ QString familyName() const;
+
+ QFont::Style style() const;
+ int weight() const;
+
+ QVector<quint32> glyphIndexesForString(const QString &text) const;
+ QVector<QPointF> advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const;
+
+ QImage alphaMapForGlyph(quint32 glyphIndex,
+ AntialiasingType antialiasingType = SubPixelAntialiasing,
+ const QTransform &transform = QTransform()) const;
+ QPainterPath pathForGlyph(quint32 glyphIndex) const;
+
+ void setPixelSize(qreal pixelSize);
+ qreal pixelSize() const;
+
+ QFont::HintingPreference hintingPreference() const;
+
+ qreal ascent() const;
+ qreal descent() const;
+ qreal leading() const;
+ qreal xHeight() const;
+ qreal averageCharWidth() const;
+ qreal maxCharWidth() const;
+
+ qreal unitsPerEm() const;
+
+ void loadFromFile(const QString &fileName,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference);
+
+ void loadFromData(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference);
+
+ bool supportsCharacter(quint32 ucs4) const;
+ bool supportsCharacter(const QChar &character) const;
+ QList<QFontDatabase::WritingSystem> supportedWritingSystems() const;
+
+ QByteArray fontTable(const char *tagName) const;
+
+ static QRawFont fromFont(const QFont &font,
+ QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any);
+
+private:
+ friend class QRawFontPrivate;
+
+ void detach();
+
+ QExplicitlySharedDataPointer<QRawFontPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_RAWFONT
+
+#endif // QRAWFONT_H
diff --git a/src/gui/text/qrawfont_ft.cpp b/src/gui/text/qrawfont_ft.cpp
new file mode 100644
index 0000000..23d47eb
--- /dev/null
+++ b/src/gui/text/qrawfont_ft.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_NO_RAWFONT)
+
+#include "qrawfont_p.h"
+#include "qfontengine_ft_p.h"
+
+#if defined(Q_WS_X11)
+# include "qfontengine_x11_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QFontEngineFTRawFont
+
+#if defined(Q_WS_X11)
+ : public QFontEngineX11FT
+#else
+ : public QFontEngineFT
+#endif
+
+{
+public:
+ QFontEngineFTRawFont(const QFontDef &fontDef)
+#if defined(Q_WS_X11)
+ : QFontEngineX11FT(fontDef)
+#else
+ : QFontEngineFT(fontDef)
+#endif
+ {
+ }
+
+ void updateFamilyNameAndStyle()
+ {
+ fontDef.family = QString::fromAscii(freetype->face->family_name);
+
+ if (freetype->face->style_flags & FT_STYLE_FLAG_ITALIC)
+ fontDef.style = QFont::StyleItalic;
+
+ if (freetype->face->style_flags & FT_STYLE_FLAG_BOLD)
+ fontDef.weight = QFont::Bold;
+ }
+
+ bool initFromData(const QByteArray &fontData)
+ {
+ FaceId faceId;
+ faceId.filename = "";
+ faceId.index = 0;
+
+ return init(faceId, true, Format_None, fontData);
+ }
+};
+
+
+void QRawFontPrivate::platformCleanUp()
+{
+ // Font engine handles all resources
+}
+
+void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ Q_ASSERT(fontEngine == 0);
+
+ QFontDef fontDef;
+ fontDef.pixelSize = pixelSize;
+
+ QFontEngineFTRawFont *fe = new QFontEngineFTRawFont(fontDef);
+ if (!fe->initFromData(fontData)) {
+ delete fe;
+ return;
+ }
+
+ fe->updateFamilyNameAndStyle();
+
+ switch (hintingPreference) {
+ case QFont::PreferNoHinting:
+ fe->setDefaultHintStyle(QFontEngineFT::HintNone);
+ break;
+ case QFont::PreferFullHinting:
+ fe->setDefaultHintStyle(QFontEngineFT::HintFull);
+ break;
+ case QFont::PreferVerticalHinting:
+ fe->setDefaultHintStyle(QFontEngineFT::HintLight);
+ break;
+ default:
+ // Leave it as it is
+ break;
+ }
+
+ fontEngine = fe;
+ fontEngine->ref.ref();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qrawfont_mac.cpp b/src/gui/text/qrawfont_mac.cpp
new file mode 100644
index 0000000..1ed4185
--- /dev/null
+++ b/src/gui/text/qrawfont_mac.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite 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/qglobal.h>
+
+#if !defined(QT_NO_RAWFONT)
+
+#include "qrawfont_p.h"
+#include "qfontengine_coretext_p.h"
+
+QT_BEGIN_NAMESPACE
+
+void QRawFontPrivate::platformCleanUp()
+{
+}
+
+extern int qt_defaultDpi();
+
+void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ // Mac OS X ignores it
+ Q_UNUSED(hintingPreference);
+
+ QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(NULL,
+ fontData.constData(), fontData.size(), NULL);
+
+ CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider);
+
+ if (cgFont == NULL) {
+ qWarning("QRawFont::platformLoadFromData: CGFontCreateWithDataProvider failed");
+ } else {
+ QFontDef def;
+ def.pixelSize = pixelSize;
+ def.pointSize = pixelSize * 72.0 / qt_defaultDpi();
+ fontEngine = new QCoreTextFontEngine(cgFont, def);
+ CFRelease(cgFont);
+ fontEngine->ref.ref();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
new file mode 100644
index 0000000..e29ea9c
--- /dev/null
+++ b/src/gui/text/qrawfont_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRAWFONTPRIVATE_P_H
+#define QRAWFONTPRIVATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrawfont.h"
+#include "qfontengine_p.h"
+#include <QtCore/qthreadstorage.h>
+
+#if !defined(QT_NO_RAWFONT)
+
+QT_BEGIN_NAMESPACE
+
+namespace { class CustomFontFileLoader; }
+class Q_AUTOTEST_EXPORT QRawFontPrivate
+{
+public:
+ QRawFontPrivate()
+ : fontEngine(0)
+ , hintingPreference(QFont::PreferDefaultHinting)
+ , thread(0)
+#if defined(Q_WS_WIN)
+ , fontHandle(NULL)
+ , ptrAddFontMemResourceEx(NULL)
+ , ptrRemoveFontMemResourceEx(NULL)
+#endif
+ {}
+
+ QRawFontPrivate(const QRawFontPrivate &other)
+ : hintingPreference(other.hintingPreference)
+ , thread(other.thread)
+#if defined(Q_WS_WIN)
+ , fontHandle(NULL)
+ , ptrAddFontMemResourceEx(other.ptrAddFontMemResourceEx)
+ , ptrRemoveFontMemResourceEx(other.ptrRemoveFontMemResourceEx)
+#endif
+ {
+ fontEngine = other.fontEngine;
+ if (fontEngine != 0)
+ fontEngine->ref.ref();
+ }
+
+ ~QRawFontPrivate()
+ {
+ Q_ASSERT(ref == 0);
+ cleanUp();
+ }
+
+ void cleanUp();
+ void platformCleanUp();
+ void platformLoadFromData(const QByteArray &fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference);
+
+ static QRawFontPrivate *get(const QRawFont &font) { return font.d.data(); }
+
+ QFontEngine *fontEngine;
+ QFont::HintingPreference hintingPreference;
+ QThread *thread;
+ QAtomicInt ref;
+
+#if defined(Q_WS_WIN)
+ HANDLE fontHandle;
+
+ typedef HANDLE (WINAPI *PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *);
+ typedef BOOL (WINAPI *PtrRemoveFontMemResourceEx)(HANDLE);
+
+ PtrAddFontMemResourceEx ptrAddFontMemResourceEx;
+ PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx;
+
+#endif // Q_WS_WIN
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
+
+#endif // QRAWFONTPRIVATE_P_H
diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/gui/text/qrawfont_qpa.cpp
new file mode 100644
index 0000000..103619c
--- /dev/null
+++ b/src/gui/text/qrawfont_qpa.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_NO_RAWFONT)
+
+#include "qrawfont_p.h"
+#include <QtGui/qplatformfontdatabase_qpa.h>
+#include <private/qapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QRawFontPrivate::platformCleanUp()
+{
+}
+
+void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ Q_ASSERT(fontEngine == 0);
+
+ QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase();
+ fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference);
+ if (fontEngine != 0)
+ fontEngine->ref.ref();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qrawfont_win.cpp b/src/gui/text/qrawfont_win.cpp
new file mode 100644
index 0000000..d8acf57
--- /dev/null
+++ b/src/gui/text/qrawfont_win.cpp
@@ -0,0 +1,707 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite 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 "qrawfont_p.h"
+#include <private/qsystemlibrary_p.h>
+
+#if !defined(QT_NO_DIRECTWRITE)
+# include "qfontenginedirectwrite_p.h"
+# include <dwrite.h>
+#endif
+
+#if !defined(QT_NO_RAWFONT)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+ template<typename T>
+ struct BigEndian
+ {
+ quint8 data[sizeof(T)];
+
+ operator T() const
+ {
+ T littleEndian = 0;
+ for (int i=0; i<sizeof(T); ++i) {
+ littleEndian |= data[i] << ((sizeof(T) - i - 1) * 8);
+ }
+
+ return littleEndian;
+ }
+
+ BigEndian<T> &operator=(const T &t)
+ {
+ for (int i=0; i<sizeof(T); ++i) {
+ data[i] = ((t >> (sizeof(T) - i - 1) * 8) & 0xff);
+ }
+
+ return *this;
+ }
+ };
+
+# pragma pack(1)
+
+ // Common structure for all formats of the "name" table
+ struct NameTable
+ {
+ BigEndian<quint16> format;
+ BigEndian<quint16> count;
+ BigEndian<quint16> stringOffset;
+ };
+
+ struct NameRecord
+ {
+ BigEndian<quint16> platformID;
+ BigEndian<quint16> encodingID;
+ BigEndian<quint16> languageID;
+ BigEndian<quint16> nameID;
+ BigEndian<quint16> length;
+ BigEndian<quint16> offset;
+ };
+
+ struct OffsetSubTable
+ {
+ BigEndian<quint32> scalerType;
+ BigEndian<quint16> numTables;
+ BigEndian<quint16> searchRange;
+ BigEndian<quint16> entrySelector;
+ BigEndian<quint16> rangeShift;
+ };
+
+ struct TableDirectory
+ {
+ BigEndian<quint32> identifier;
+ BigEndian<quint32> checkSum;
+ BigEndian<quint32> offset;
+ BigEndian<quint32> length;
+ };
+
+ struct OS2Table
+ {
+ BigEndian<quint16> version;
+ BigEndian<qint16> avgCharWidth;
+ BigEndian<quint16> weightClass;
+ BigEndian<quint16> widthClass;
+ BigEndian<quint16> type;
+ BigEndian<qint16> subscriptXSize;
+ BigEndian<qint16> subscriptYSize;
+ BigEndian<qint16> subscriptXOffset;
+ BigEndian<qint16> subscriptYOffset;
+ BigEndian<qint16> superscriptXSize;
+ BigEndian<qint16> superscriptYSize;
+ BigEndian<qint16> superscriptXOffset;
+ BigEndian<qint16> superscriptYOffset;
+ BigEndian<qint16> strikeOutSize;
+ BigEndian<qint16> strikeOutPosition;
+ BigEndian<qint16> familyClass;
+ quint8 panose[10];
+ BigEndian<quint32> unicodeRanges[4];
+ quint8 vendorID[4];
+ BigEndian<quint16> selection;
+ BigEndian<quint16> firstCharIndex;
+ BigEndian<quint16> lastCharIndex;
+ BigEndian<qint16> typoAscender;
+ BigEndian<qint16> typoDescender;
+ BigEndian<qint16> typoLineGap;
+ BigEndian<quint16> winAscent;
+ BigEndian<quint16> winDescent;
+ BigEndian<quint32> codepageRanges[2];
+ BigEndian<qint16> height;
+ BigEndian<qint16> capHeight;
+ BigEndian<quint16> defaultChar;
+ BigEndian<quint16> breakChar;
+ BigEndian<quint16> maxContext;
+ };
+
+# pragma pack()
+
+ class EmbeddedFont
+ {
+ public:
+ EmbeddedFont(const QByteArray &fontData);
+
+ QString changeFamilyName(const QString &newFamilyName);
+ QByteArray data() const { return m_fontData; }
+ TableDirectory *tableDirectoryEntry(const QByteArray &tagName);
+ QString familyName(TableDirectory *nameTableDirectory = 0);
+
+ private:
+ QByteArray m_fontData;
+ };
+
+ EmbeddedFont::EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData)
+ {
+ }
+
+ TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName)
+ {
+ Q_ASSERT(tagName.size() == 4);
+
+ const BigEndian<quint32> *tagIdPtr =
+ reinterpret_cast<const BigEndian<quint32> *>(tagName.constData());
+ quint32 tagId = *tagIdPtr;
+
+ OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
+ TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
+
+ TableDirectory *nameTableDirectoryEntry = 0;
+ for (int i=0; i<offsetSubTable->numTables; ++i, ++tableDirectory) {
+ if (tableDirectory->identifier == tagId) {
+ nameTableDirectoryEntry = tableDirectory;
+ break;
+ }
+ }
+
+ return nameTableDirectoryEntry;
+ }
+
+ QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
+ {
+ QString name;
+
+ if (nameTableDirectoryEntry == 0)
+ nameTableDirectoryEntry = tableDirectoryEntry("name");
+
+ if (nameTableDirectoryEntry != 0) {
+ NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data()
+ + nameTableDirectoryEntry->offset);
+ NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
+ for (int i=0; i<nameTable->count; ++i, ++nameRecord) {
+ if (nameRecord->nameID == 1
+ && nameRecord->platformID == 3 // Windows
+ && nameRecord->languageID == 0x0409) { // US English
+ const void *ptr = reinterpret_cast<const quint8 *>(nameTable)
+ + nameTable->stringOffset
+ + nameRecord->offset;
+
+ const BigEndian<quint16> *s = reinterpret_cast<const BigEndian<quint16> *>(ptr);
+ for (int j=0; j<nameRecord->length / sizeof(quint16); ++j)
+ name += QChar(s[j]);
+
+ break;
+ }
+ }
+ }
+
+ return name;
+ }
+
+ QString EmbeddedFont::changeFamilyName(const QString &newFamilyName)
+ {
+ TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name");
+ if (nameTableDirectoryEntry == 0)
+ return QString();
+
+ QString oldFamilyName = familyName(nameTableDirectoryEntry);
+
+ // Reserve size for name table header, five required name records and string
+ const int requiredRecordCount = 5;
+ quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 };
+
+ int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount;
+ int newFamilyNameSize = newFamilyName.size() * sizeof(quint16);
+
+ const QString regularString = QString::fromLatin1("Regular");
+ int regularStringSize = regularString.size() * sizeof(quint16);
+
+ // Align table size of table to 32 bits (pad with 0)
+ int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4;
+
+ QByteArray newNameTable(fullSize, char(0));
+
+ {
+ NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data());
+ nameTable->count = requiredRecordCount;
+ nameTable->stringOffset = sizeOfHeader;
+
+ NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1);
+ for (int i=0; i<requiredRecordCount; ++i, nameRecord++) {
+ nameRecord->nameID = nameIds[i];
+ nameRecord->encodingID = 1;
+ nameRecord->languageID = 0x0409;
+ nameRecord->platformID = 3;
+ nameRecord->length = newFamilyNameSize;
+
+ // Special case for sub-family
+ if (nameIds[i] == 4) {
+ nameRecord->offset = newFamilyNameSize;
+ nameRecord->length = regularStringSize;
+ }
+ }
+
+ // nameRecord now points to string data
+ BigEndian<quint16> *stringStorage = reinterpret_cast<BigEndian<quint16> *>(nameRecord);
+ const quint16 *sourceString = newFamilyName.utf16();
+ for (int i=0; i<newFamilyName.size(); ++i)
+ stringStorage[i] = sourceString[i];
+ stringStorage += newFamilyName.size();
+
+ sourceString = regularString.utf16();
+ for (int i=0; i<regularString.size(); ++i)
+ stringStorage[i] = sourceString[i];
+ }
+
+ quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data());
+ quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize);
+
+ quint32 checkSum = 0;
+ while (p < tableEnd)
+ checkSum += *(p++);
+
+ nameTableDirectoryEntry->checkSum = checkSum;
+ nameTableDirectoryEntry->offset = m_fontData.size();
+ nameTableDirectoryEntry->length = fullSize;
+
+ m_fontData.append(newNameTable);
+
+ return oldFamilyName;
+ }
+
+#if !defined(QT_NO_DIRECTWRITE)
+
+ class DirectWriteFontFileStream: public IDWriteFontFileStream
+ {
+ public:
+ DirectWriteFontFileStream(const QByteArray &fontData)
+ : m_fontData(fontData)
+ , m_referenceCount(0)
+ {
+ }
+
+ ~DirectWriteFontFileStream()
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset,
+ UINT64 fragmentSize, OUT void **fragmentContext);
+ void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext);
+ HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize);
+ HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime);
+
+ private:
+ QByteArray m_fontData;
+ ULONG m_referenceCount;
+ };
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object)
+ {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
+ *object = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef()
+ {
+ return InterlockedIncrement(&m_referenceCount);
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release()
+ {
+ ULONG newCount = InterlockedDecrement(&m_referenceCount);
+ if (newCount == 0)
+ delete this;
+ return newCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment(
+ const void **fragmentStart,
+ UINT64 fileOffset,
+ UINT64 fragmentSize,
+ OUT void **fragmentContext)
+ {
+ *fragmentContext = NULL;
+ if (fragmentSize + fileOffset <= m_fontData.size()) {
+ *fragmentStart = m_fontData.data() + fileOffset;
+ return S_OK;
+ } else {
+ *fragmentStart = NULL;
+ return E_FAIL;
+ }
+ }
+
+ void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *)
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize)
+ {
+ *fileSize = m_fontData.size();
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
+ {
+ *lastWriteTime = 0;
+ return E_NOTIMPL;
+ }
+
+ class DirectWriteFontFileLoader: public IDWriteFontFileLoader
+ {
+ public:
+ DirectWriteFontFileLoader() : m_referenceCount(0) {}
+
+ ~DirectWriteFontFileLoader()
+ {
+ }
+
+ inline void addKey(const void *key, const QByteArray &fontData)
+ {
+ Q_ASSERT(!m_fontDatas.contains(key));
+ m_fontDatas.insert(key, fontData);
+ }
+
+ inline void removeKey(const void *key)
+ {
+ m_fontDatas.remove(key);
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ OUT IDWriteFontFileStream **fontFileStream);
+
+ private:
+ ULONG m_referenceCount;
+ QHash<const void *, QByteArray> m_fontDatas;
+ };
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid,
+ void **object)
+ {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
+ *object = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef()
+ {
+ return InterlockedIncrement(&m_referenceCount);
+ }
+
+ ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release()
+ {
+ ULONG newCount = InterlockedDecrement(&m_referenceCount);
+ if (newCount == 0)
+ delete this;
+ return newCount;
+ }
+
+ HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey(
+ void const *fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ IDWriteFontFileStream **fontFileStream)
+ {
+ Q_UNUSED(fontFileReferenceKeySize);
+
+ if (fontFileReferenceKeySize != sizeof(const void *)) {
+ qWarning("DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size");
+ return E_FAIL;
+ }
+
+ const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey);
+ *fontFileStream = NULL;
+ if (!m_fontDatas.contains(key))
+ return E_FAIL;
+
+ QByteArray fontData = m_fontDatas.value(key);
+ DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData);
+ stream->AddRef();
+ *fontFileStream = stream;
+
+ return S_OK;
+ }
+
+ class CustomFontFileLoader
+ {
+ public:
+ CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0)
+ {
+ HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown **>(&m_directWriteFactory));
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "CustomFontFileLoader::CustomFontFileLoader: "
+ "DWriteCreateFactory failed.");
+ } else {
+ m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
+ m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
+ }
+ }
+
+ ~CustomFontFileLoader()
+ {
+ if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0)
+ m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
+
+ if (m_directWriteFactory != 0)
+ m_directWriteFactory->Release();
+ }
+
+ void addKey(const void *key, const QByteArray &fontData)
+ {
+ if (m_directWriteFontFileLoader != 0)
+ m_directWriteFontFileLoader->addKey(key, fontData);
+ }
+
+ void removeKey(const void *key)
+ {
+ if (m_directWriteFontFileLoader != 0)
+ m_directWriteFontFileLoader->removeKey(key);
+ }
+
+ IDWriteFontFileLoader *loader() const
+ {
+ return m_directWriteFontFileLoader;
+ }
+
+ private:
+ IDWriteFactory *m_directWriteFactory;
+ DirectWriteFontFileLoader *m_directWriteFontFileLoader;
+ };
+
+#endif
+
+} // Anonymous namespace
+
+
+// From qfontdatabase_win.cpp
+extern QFontEngine *qt_load_font_engine_win(const QFontDef &request);
+// From qfontdatabase.cpp
+extern QFont::Weight weightFromInteger(int weight);
+
+void QRawFontPrivate::platformCleanUp()
+{
+ if (fontHandle != NULL) {
+ if (ptrRemoveFontMemResourceEx == NULL) {
+ void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ ptrRemoveFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
+ }
+
+ if (ptrRemoveFontMemResourceEx == NULL) {
+ qWarning("QRawFont::platformCleanUp: Can't find RemoveFontMemResourceEx in gdi32");
+ fontHandle = NULL;
+ } else {
+ ptrRemoveFontMemResourceEx(fontHandle);
+ fontHandle = NULL;
+ }
+ }
+}
+
+void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData,
+ int pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ QByteArray fontData(_fontData);
+ EmbeddedFont font(fontData);
+
+#if !defined(QT_NO_DIRECTWRITE)
+ if (hintingPreference == QFont::PreferDefaultHinting
+ || hintingPreference == QFont::PreferFullHinting)
+#endif
+ {
+ GUID guid;
+ CoCreateGuid(&guid);
+
+ QString uniqueFamilyName = QString::fromLatin1("f")
+ + QString::number(guid.Data1, 36) + QLatin1Char('-')
+ + QString::number(guid.Data2, 36) + QLatin1Char('-')
+ + QString::number(guid.Data3, 36) + QLatin1Char('-')
+ + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
+
+ QString actualFontName = font.changeFamilyName(uniqueFamilyName);
+ if (actualFontName.isEmpty()) {
+ qWarning("QRawFont::platformLoadFromData: Can't change family name of font");
+ return;
+ }
+
+ if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) {
+ void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx");
+ ptrRemoveFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func);
+
+ func = QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx");
+ ptrAddFontMemResourceEx =
+ reinterpret_cast<QRawFontPrivate::PtrAddFontMemResourceEx>(func);
+ }
+
+ Q_ASSERT(fontHandle == NULL);
+ if (ptrAddFontMemResourceEx != NULL && ptrRemoveFontMemResourceEx != NULL) {
+ DWORD count = 0;
+ fontData = font.data();
+ fontHandle = ptrAddFontMemResourceEx(fontData.data(), fontData.size(), 0, &count);
+
+ if (count == 0 && fontHandle != NULL) {
+ ptrRemoveFontMemResourceEx(fontHandle);
+ fontHandle = NULL;
+ }
+ }
+
+ if (fontHandle == NULL) {
+ qWarning("QRawFont::platformLoadFromData: AddFontMemResourceEx failed");
+ } else {
+ QFontDef request;
+ request.family = uniqueFamilyName;
+ request.pixelSize = pixelSize;
+ request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch;
+ request.hintingPreference = hintingPreference;
+
+ fontEngine = qt_load_font_engine_win(request);
+ if (request.family != fontEngine->fontDef.family) {
+ qWarning("QRawFont::platformLoadFromData: Failed to load font. "
+ "Got fallback instead: %s", qPrintable(fontEngine->fontDef.family));
+ if (fontEngine->cache_count == 0 && fontEngine->ref == 0)
+ delete fontEngine;
+ fontEngine = 0;
+ } else {
+ Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0);
+
+ // Override the generated font name
+ static_cast<QFontEngineWin *>(fontEngine)->uniqueFamilyName = uniqueFamilyName;
+ fontEngine->fontDef.family = actualFontName;
+ fontEngine->ref.ref();
+ }
+ }
+ }
+#if !defined(QT_NO_DIRECTWRITE)
+ else {
+ CustomFontFileLoader fontFileLoader;
+ fontFileLoader.addKey(this, fontData);
+
+ IDWriteFactory *factory = NULL;
+ HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown **>(&factory));
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: DWriteCreateFactory failed");
+ return;
+ }
+
+ IDWriteFontFile *fontFile = NULL;
+ void *key = this;
+
+ hres = factory->CreateCustomFontFileReference(&key, sizeof(void *),
+ fontFileLoader.loader(), &fontFile);
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: "
+ "CreateCustomFontFileReference failed");
+ factory->Release();
+ return;
+ }
+
+ BOOL isSupportedFontType;
+ DWRITE_FONT_FILE_TYPE fontFileType;
+ DWRITE_FONT_FACE_TYPE fontFaceType;
+ UINT32 numberOfFaces;
+ fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
+ if (!isSupportedFontType) {
+ fontFile->Release();
+ factory->Release();
+ return;
+ }
+
+ IDWriteFontFace *directWriteFontFace = NULL;
+ hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE,
+ &directWriteFontFace);
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "QRawFont::platformLoadFromData: CreateFontFace failed");
+ fontFile->Release();
+ factory->Release();
+ return;
+ }
+
+ fontFile->Release();
+
+ fontEngine = new QFontEngineDirectWrite(factory, directWriteFontFace, pixelSize);
+
+ // Get font family from font data
+ fontEngine->fontDef.family = font.familyName();
+ fontEngine->ref.ref();
+
+ directWriteFontFace->Release();
+ factory->Release();
+ }
+#endif
+
+ // Get style and weight info
+ if (fontEngine != 0) {
+ TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2");
+ if (os2TableEntry != 0) {
+ const OS2Table *os2Table =
+ reinterpret_cast<const OS2Table *>(fontData.constData()
+ + os2TableEntry->offset);
+
+ bool italic = os2Table->selection & 1;
+ bool oblique = os2Table->selection & 128;
+
+ if (italic)
+ fontEngine->fontDef.style = QFont::StyleItalic;
+ else if (oblique)
+ fontEngine->fontDef.style = QFont::StyleOblique;
+ else
+ fontEngine->fontDef.style = QFont::StyleNormal;
+
+ fontEngine->fontDef.weight = weightFromInteger(os2Table->weightClass);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_RAWFONT
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 66ce64b..4396730 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -1519,7 +1519,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con
const QTextCursor oldSelection = cursor;
const int oldCursorPos = cursor.position();
- mousePressed = true;
+ mousePressed = (interactionFlags & Qt::TextSelectableByMouse);
#ifndef QT_NO_DRAGANDDROP
mightStartDrag = false;
#endif
@@ -1608,13 +1608,11 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons
if (!(buttons & Qt::LeftButton))
return;
- const bool selectable = interactionFlags & Qt::TextSelectableByMouse;
const bool editable = interactionFlags & Qt::TextEditable;
- if (!selectable && !editable)
- return;
-
if (!(mousePressed
+ || editable
+ || mightStartDrag
|| selectedWordOnDoubleClick.hasSelection()
|| selectedBlockOnTrippleClick.hasSelection()))
return;
@@ -1628,7 +1626,7 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons
return;
}
- if (!selectable)
+ if (!mousePressed)
return;
const qreal mouseX = qreal(mousePos.x());
@@ -1696,10 +1694,8 @@ void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, c
if (mousePressed) {
mousePressed = false;
#ifndef QT_NO_CLIPBOARD
- if (interactionFlags & Qt::TextSelectableByMouse) {
- setClipboardSelection();
- selectionChanged(true);
- }
+ setClipboardSelection();
+ selectionChanged(true);
} else if (button == Qt::MidButton
&& (interactionFlags & Qt::TextEditable)
&& QApplication::clipboard()->supportsSelection()) {
@@ -1951,6 +1947,7 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
if (isGettingInput)
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
QList<QTextLayout::FormatRange> overrides;
+ const int oldPreeditCursor = preeditCursor;
preeditCursor = e->preeditString().length();
hideCursor = false;
for (int i = 0; i < e->attributes().size(); ++i) {
@@ -1973,6 +1970,8 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
cursor.endEditBlock();
if (cursor.d)
cursor.d->setX();
+ if (oldPreeditCursor != preeditCursor)
+ emit q->microFocusChanged();
}
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index 6ddfdb0..4f6857a 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -362,20 +362,23 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
currentCharFormat = -1;
bool adjustX = true;
QTextBlock blockIt = block();
+ bool visualMovement = priv->defaultCursorMoveStyle == QTextCursor::Visual;
if (!blockIt.isValid())
return false;
- if (op >= QTextCursor::Left && op <= QTextCursor::WordRight
- && blockIt.textDirection() == Qt::RightToLeft) {
- if (op == QTextCursor::Left)
- op = QTextCursor::NextCharacter;
- else if (op == QTextCursor::Right)
- op = QTextCursor::PreviousCharacter;
- else if (op == QTextCursor::WordLeft)
+ if (blockIt.textDirection() == Qt::RightToLeft) {
+ if (op == QTextCursor::WordLeft)
op = QTextCursor::NextWord;
else if (op == QTextCursor::WordRight)
op = QTextCursor::PreviousWord;
+
+ if (!visualMovement) {
+ if (op == QTextCursor::Left)
+ op = QTextCursor::NextCharacter;
+ else if (op == QTextCursor::Right)
+ op = QTextCursor::PreviousCharacter;
+ }
}
const QTextLayout *layout = blockLayout(blockIt);
@@ -418,9 +421,12 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
break;
}
case QTextCursor::PreviousCharacter:
- case QTextCursor::Left:
newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
break;
+ case QTextCursor::Left:
+ newPosition = visualMovement ? priv->leftCursorPosition(position)
+ : priv->previousCursorPosition(position, QTextLayout::SkipCharacters);
+ break;
case QTextCursor::StartOfWord: {
if (relativePos == 0)
break;
@@ -529,9 +535,12 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
break;
}
case QTextCursor::NextCharacter:
- case QTextCursor::Right:
newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
break;
+ case QTextCursor::Right:
+ newPosition = visualMovement ? priv->rightCursorPosition(position)
+ : priv->nextCursorPosition(position, QTextLayout::SkipCharacters);
+ break;
case QTextCursor::NextWord:
case QTextCursor::WordRight:
newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);
@@ -2558,4 +2567,19 @@ QTextDocument *QTextCursor::document() const
return 0; // document went away
}
+/*!
+ \enum QTextCursor::MoveStyle
+
+ This enum describes the movement style available to QTextCursor. The options
+ are:
+
+ \value Logical Within a left-to-right text block, increase cursor position
+ when pressing left arrow key, decrease cursor position when pressing the
+ right arrow key. If the text block is right-to-left, the opposite behavior
+ applies.
+ \value Visual Pressing the left arrow key will always cause the cursor to move
+ left, regardless of the text's writing direction. The same behavior applies to
+ right arrow key.
+*/
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index 4eaeb41..9e4c0b8 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -86,6 +86,10 @@ public:
MoveAnchor,
KeepAnchor
};
+ enum MoveStyle {
+ Logical,
+ Visual
+ };
void setPosition(int pos, MoveMode mode = MoveAnchor);
int position() const;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 6dbd755..36f3c6c 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -586,6 +586,29 @@ void QTextDocument::setDefaultTextOption(const QTextOption &option)
}
/*!
+ \since 4.8
+
+ The default cursor movement style is used by all QTextCursor objects
+ created from the document. The default is QTextCursor::Logical.
+*/
+QTextCursor::MoveStyle QTextDocument::defaultCursorMoveStyle() const
+{
+ Q_D(const QTextDocument);
+ return d->defaultCursorMoveStyle;
+}
+
+/*!
+ \since 4.8
+
+ Set the default cursor movement style.
+*/
+void QTextDocument::setDefaultCursorMoveStyle(QTextCursor::MoveStyle style)
+{
+ Q_D(QTextDocument);
+ d->defaultCursorMoveStyle = style;
+}
+
+/*!
\fn void QTextDocument::markContentsDirty(int position, int length)
Marks the contents specified by the given \a position and \a length
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index f87ccc9..e515b36 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -46,6 +46,7 @@
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
#include <QtGui/qfont.h>
+#include <QtGui/qtextcursor.h>
QT_BEGIN_HEADER
@@ -60,7 +61,6 @@ class QPainter;
class QPrinter;
class QAbstractTextDocumentLayout;
class QPoint;
-class QTextCursor;
class QTextObject;
class QTextFormat;
class QTextFrame;
@@ -269,6 +269,9 @@ public:
QTextOption defaultTextOption() const;
void setDefaultTextOption(const QTextOption &option);
+ QTextCursor::MoveStyle defaultCursorMoveStyle() const;
+ void setDefaultCursorMoveStyle(QTextCursor::MoveStyle style);
+
Q_SIGNALS:
void contentsChange(int from, int charsRemoves, int charsAdded);
void contentsChanged();
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 2172f74..779b1ff 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -209,6 +209,7 @@ QTextDocumentPrivate::QTextDocumentPrivate()
defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ defaultCursorMoveStyle = QTextCursor::Logical;
indentWidth = 40;
documentMargin = 4;
@@ -1382,6 +1383,20 @@ int QTextDocumentPrivate::previousCursorPosition(int position, QTextLayout::Curs
return it.layout()->previousCursorPosition(position-start, mode) + start;
}
+int QTextDocumentPrivate::leftCursorPosition(int position) const
+{
+ QTextBlock it = blocksFind(position);
+ int start = it.position();
+ return it.layout()->leftCursorPosition(position-start) + start;
+}
+
+int QTextDocumentPrivate::rightCursorPosition(int position) const
+{
+ QTextBlock it = blocksFind(position);
+ int start = it.position();
+ return it.layout()->rightCursorPosition(position-start) + start;
+}
+
void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
{
beginEditBlock();
@@ -1406,11 +1421,18 @@ void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
static QTextFrame *findChildFrame(QTextFrame *f, int pos)
{
- // ##### use binary search
- QList<QTextFrame *> children = f->childFrames();
- for (int i = 0; i < children.size(); ++i) {
- QTextFrame *c = children.at(i);
- if (pos >= c->firstPosition() && pos <= c->lastPosition())
+ /* Binary search for frame at pos */
+ const QList<QTextFrame *> children = f->childFrames();
+ int first = 0;
+ int last = children.size() - 1;
+ while (first <= last) {
+ int mid = (first + last) / 2;
+ QTextFrame *c = children.at(mid);
+ if (pos > c->lastPosition())
+ first = mid + 1;
+ else if (pos < c->firstPosition())
+ last = mid - 1;
+ else
return c;
}
return 0;
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index b464f2e..6563920 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -64,6 +64,7 @@
#include "private/qtextformat_p.h"
#include "QtGui/qtextdocument.h"
#include "QtGui/qtextobject.h"
+#include "QtGui/qtextcursor.h"
#include "QtCore/qmap.h"
#include "QtCore/qvariant.h"
#include "QtCore/qurl.h"
@@ -244,6 +245,8 @@ public:
int nextCursorPosition(int position, QTextLayout::CursorMode mode) const;
int previousCursorPosition(int position, QTextLayout::CursorMode mode) const;
+ int leftCursorPosition(int position) const;
+ int rightCursorPosition(int position) const;
void changeObjectFormat(QTextObject *group, int format);
@@ -339,6 +342,7 @@ private:
public:
QTextOption defaultTextOption;
+ QTextCursor::MoveStyle defaultCursorMoveStyle;
#ifndef QT_NO_CSSPARSER
QCss::StyleSheet parsedDefaultStyleSheet;
#endif
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index ce157be..f3dc975 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2996,10 +2996,19 @@ void QTextDocumentLayout::resizeInlineObject(QTextInlineObject item, int posInDo
QSizeF inlineSize = (pos == QTextFrameFormat::InFlow ? intrinsic : QSizeF(0, 0));
item.setWidth(inlineSize.width());
- if (f.verticalAlignment() == QTextCharFormat::AlignMiddle) {
+
+ QFontMetrics m(f.font());
+ switch (f.verticalAlignment())
+ {
+ case QTextCharFormat::AlignMiddle:
item.setDescent(inlineSize.height() / 2);
item.setAscent(inlineSize.height() / 2 - 1);
- } else {
+ break;
+ case QTextCharFormat::AlignBaseline:
+ item.setDescent(m.descent());
+ item.setAscent(inlineSize.height() - m.descent() - 1);
+ break;
+ default:
item.setDescent(0);
item.setAscent(inlineSize.height() - 1);
}
@@ -3081,6 +3090,7 @@ void QTextDocumentLayoutPrivate::ensureLayouted(QFixed y) const
if (currentLazyLayoutPosition == -1)
return;
const QSizeF oldSize = q->dynamicDocumentSize();
+ Q_UNUSED(oldSize);
if (checkPoints.isEmpty())
layoutStep();
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 08d0eca..ff27bc6 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -856,6 +856,21 @@ void QTextEngine::shapeLine(const QScriptLine &line)
}
}
+#if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC)
+static bool enableHarfBuzz()
+{
+ static enum { Yes, No, Unknown } status = Unknown;
+
+ if (status == Unknown) {
+ QByteArray v = qgetenv("QT_ENABLE_HARFBUZZ");
+ bool value = !v.isEmpty() && v != "0" && v != "false";
+ if (value) status = Yes;
+ else status = No;
+ }
+ return status == Yes;
+}
+#endif
+
void QTextEngine::shapeText(int item) const
{
Q_ASSERT(item < layoutData->items.size());
@@ -865,7 +880,24 @@ void QTextEngine::shapeText(int item) const
return;
#if defined(Q_WS_MAC)
- shapeTextMac(item);
+#if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC)
+ if (enableHarfBuzz()) {
+#endif
+ QFontEngine *actualFontEngine = fontEngine(si, &si.ascent, &si.descent, &si.leading);
+ if (actualFontEngine->type() == QFontEngine::Multi)
+ actualFontEngine = static_cast<QFontEngineMulti *>(actualFontEngine)->engine(0);
+
+ HB_Face face = actualFontEngine->harfbuzzFace();
+ HB_Script script = (HB_Script) si.analysis.script;
+ if (face->supported_scripts[script])
+ shapeTextWithHarfbuzz(item);
+ else
+ shapeTextMac(item);
+#if !defined(QT_ENABLE_HARFBUZZ_FOR_MAC)
+ } else {
+ shapeTextMac(item);
+ }
+#endif
#elif defined(Q_WS_WINCE)
shapeTextWithCE(item);
#else
@@ -1242,6 +1274,10 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
actualFontEngine = static_cast<QFontEngineMulti *>(font)->engine(engineIdx);
}
+ si.ascent = qMax(actualFontEngine->ascent(), si.ascent);
+ si.descent = qMax(actualFontEngine->descent(), si.descent);
+ si.leading = qMax(actualFontEngine->leading(), si.leading);
+
shaper_item.font = actualFontEngine->harfbuzzFont();
shaper_item.face = actualFontEngine->harfbuzzFace();
@@ -1304,6 +1340,7 @@ static void init(QTextEngine *e)
e->ignoreBidi = false;
e->cacheGlyphs = false;
e->forceJustification = false;
+ e->visualMovement = false;
e->layoutData = 0;
@@ -1565,6 +1602,8 @@ bool QTextEngine::isRightToLeft() const
default:
break;
}
+ if (!layoutData)
+ itemize();
// this places the cursor in the right position depending on the keyboard layout
if (layoutData->string.isEmpty())
return QApplication::keyboardInputDirection() == Qt::RightToLeft;
@@ -2737,6 +2776,182 @@ QFixed QTextEngine::leadingSpaceWidth(const QScriptLine &line)
return width(line.from + pos, line.length - pos);
}
+QFixed QTextEngine::alignLine(const QScriptLine &line)
+{
+ QFixed x = 0;
+ justify(line);
+ // if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned.
+ if (!line.justified && line.width != QFIXED_MAX) {
+ int align = option.alignment();
+ if (align & Qt::AlignLeft)
+ x -= leadingSpaceWidth(line);
+ if (align & Qt::AlignJustify && isRightToLeft())
+ align = Qt::AlignRight;
+ if (align & Qt::AlignRight)
+ x = line.width - (line.textAdvance + leadingSpaceWidth(line));
+ else if (align & Qt::AlignHCenter)
+ x = (line.width - (line.textAdvance + leadingSpaceWidth(line)))/2;
+ }
+ return x;
+}
+
+QFixed QTextEngine::offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos)
+{
+ unsigned short *logClusters = this->logClusters(si);
+ const QGlyphLayout &glyphs = shapedGlyphs(si);
+
+ int offsetInCluster = 0;
+ for (int i = pos - 1; i >= 0; i--) {
+ if (logClusters[i] == glyph_pos)
+ offsetInCluster++;
+ else
+ break;
+ }
+
+ // in the case that the offset is inside a (multi-character) glyph,
+ // interpolate the position.
+ if (offsetInCluster > 0) {
+ int clusterLength = 0;
+ for (int i = pos - offsetInCluster; i < max; i++) {
+ if (logClusters[i] == glyph_pos)
+ clusterLength++;
+ else
+ break;
+ }
+ if (clusterLength)
+ return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength;
+ }
+
+ return 0;
+}
+
+int QTextEngine::previousLogicalPosition(int oldPos) const
+{
+ const HB_CharAttributes *attrs = attributes();
+ if (!attrs || oldPos < 0)
+ return oldPos;
+
+ if (oldPos <= 0)
+ return 0;
+ oldPos--;
+ while (oldPos && !attrs[oldPos].charStop)
+ oldPos--;
+ return oldPos;
+}
+
+int QTextEngine::nextLogicalPosition(int oldPos) const
+{
+ const HB_CharAttributes *attrs = attributes();
+ int len = block.isValid() ? block.length() - 1
+ : layoutData->string.length();
+ Q_ASSERT(len <= layoutData->string.length());
+ if (!attrs || oldPos < 0 || oldPos >= len)
+ return oldPos;
+
+ oldPos++;
+ while (oldPos < len && !attrs[oldPos].charStop)
+ oldPos++;
+ return oldPos;
+}
+
+int QTextEngine::lineNumberForTextPosition(int pos)
+{
+ if (!layoutData)
+ itemize();
+ if (pos == layoutData->string.length() && lines.size())
+ return lines.size() - 1;
+ for (int i = 0; i < lines.size(); ++i) {
+ const QScriptLine& line = lines[i];
+ if (line.from + line.length > pos)
+ return i;
+ }
+ return -1;
+}
+
+void QTextEngine::insertionPointsForLine(int lineNum, QVector<int> &insertionPoints)
+{
+ QTextLineItemIterator iterator(this, lineNum);
+ bool rtl = isRightToLeft();
+ bool lastLine = lineNum >= lines.size() - 1;
+
+ while (!iterator.atEnd()) {
+ iterator.next();
+ const QScriptItem *si = &layoutData->items[iterator.item];
+ if (si->analysis.bidiLevel % 2) {
+ int i = iterator.itemEnd - 1, min = iterator.itemStart;
+ if (lastLine && (rtl ? iterator.atBeginning() : iterator.atEnd()))
+ i++;
+ for (; i >= min; i--)
+ insertionPoints.push_back(i);
+ } else {
+ int i = iterator.itemStart, max = iterator.itemEnd;
+ if (lastLine && (rtl ? iterator.atBeginning() : iterator.atEnd()))
+ max++;
+ for (; i < max; i++)
+ insertionPoints.push_back(i);
+ }
+ }
+}
+
+int QTextEngine::endOfLine(int lineNum)
+{
+ QVector<int> insertionPoints;
+ insertionPointsForLine(lineNum, insertionPoints);
+
+ if (insertionPoints.size() > 0)
+ return insertionPoints.last();
+ return 0;
+}
+
+int QTextEngine::beginningOfLine(int lineNum)
+{
+ QVector<int> insertionPoints;
+ insertionPointsForLine(lineNum, insertionPoints);
+
+ if (insertionPoints.size() > 0)
+ return insertionPoints.first();
+ return 0;
+}
+
+int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation op)
+{
+ if (!layoutData)
+ itemize();
+
+ bool moveRight = (op == QTextCursor::Right);
+ bool alignRight = isRightToLeft();
+ if (!layoutData->hasBidi)
+ return moveRight ^ alignRight ? nextLogicalPosition(pos) : previousLogicalPosition(pos);
+
+ int lineNum = lineNumberForTextPosition(pos);
+ Q_ASSERT(lineNum >= 0);
+
+ QVector<int> insertionPoints;
+ insertionPointsForLine(lineNum, insertionPoints);
+ int i, max = insertionPoints.size();
+ for (i = 0; i < max; i++)
+ if (pos == insertionPoints[i]) {
+ if (moveRight) {
+ if (i + 1 < max)
+ return insertionPoints[i + 1];
+ } else {
+ if (i > 0)
+ return insertionPoints[i - 1];
+ }
+
+ if (moveRight ^ alignRight) {
+ if (lineNum + 1 < lines.size())
+ return alignRight ? endOfLine(lineNum + 1) : beginningOfLine(lineNum + 1);
+ }
+ else {
+ if (lineNum > 0)
+ return alignRight ? beginningOfLine(lineNum - 1) : endOfLine(lineNum - 1);
+ }
+ }
+
+ return pos;
+}
+
QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f)
: QTextEngine(string, f),
_layoutData(string, _memory, MemSize)
@@ -2841,5 +3056,127 @@ glyph_metrics_t glyph_metrics_t::transformed(const QTransform &matrix) const
return m;
}
+QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, const QPointF &pos,
+ const QTextLayout::FormatRange *_selection)
+ : eng(_eng),
+ line(eng->lines[_lineNum]),
+ si(0),
+ lineNum(_lineNum),
+ lineEnd(line.from + line.length),
+ firstItem(eng->findItem(line.from)),
+ lastItem(eng->findItem(lineEnd - 1)),
+ nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
+ logicalItem(-1),
+ item(-1),
+ visualOrder(nItems),
+ levels(nItems),
+ selection(_selection)
+{
+ pos_x = x = QFixed::fromReal(pos.x());
+
+ x += line.x;
+
+ x += eng->alignLine(line);
+
+ for (int i = 0; i < nItems; ++i)
+ levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
+ QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
+
+ eng->shapeLine(line);
+}
+
+QScriptItem &QTextLineItemIterator::next()
+{
+ x += itemWidth;
+
+ ++logicalItem;
+ item = visualOrder[logicalItem] + firstItem;
+ itemLength = eng->length(item);
+ si = &eng->layoutData->items[item];
+ if (!si->num_glyphs)
+ eng->shape(item);
+
+ if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
+ itemWidth = si->width;
+ return *si;
+ }
+
+ unsigned short *logClusters = eng->logClusters(si);
+ QGlyphLayout glyphs = eng->shapedGlyphs(si);
+
+ itemStart = qMax(line.from, si->position);
+ glyphsStart = logClusters[itemStart - si->position];
+ if (lineEnd < si->position + itemLength) {
+ itemEnd = lineEnd;
+ glyphsEnd = logClusters[itemEnd-si->position];
+ } else {
+ itemEnd = si->position + itemLength;
+ glyphsEnd = si->num_glyphs;
+ }
+ // show soft-hyphen at line-break
+ if (si->position + itemLength >= lineEnd
+ && eng->layoutData->string.at(lineEnd - 1) == 0x00ad)
+ glyphs.attributes[glyphsEnd - 1].dontPrint = false;
+
+ itemWidth = 0;
+ for (int g = glyphsStart; g < glyphsEnd; ++g)
+ itemWidth += glyphs.effectiveAdvance(g);
+
+ return *si;
+}
+
+bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const
+{
+ *selectionX = *selectionWidth = 0;
+
+ if (!selection)
+ return false;
+
+ if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
+ if (si->position >= selection->start + selection->length
+ || si->position + itemLength <= selection->start)
+ return false;
+
+ *selectionX = x;
+ *selectionWidth = itemWidth;
+ } else {
+ unsigned short *logClusters = eng->logClusters(si);
+ QGlyphLayout glyphs = eng->shapedGlyphs(si);
+
+ int from = qMax(itemStart, selection->start) - si->position;
+ int to = qMin(itemEnd, selection->start + selection->length) - si->position;
+ if (from >= to)
+ return false;
+
+ int start_glyph = logClusters[from];
+ int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to];
+ QFixed soff;
+ QFixed swidth;
+ if (si->analysis.bidiLevel %2) {
+ for (int g = glyphsEnd - 1; g >= end_glyph; --g)
+ soff += glyphs.effectiveAdvance(g);
+ for (int g = end_glyph - 1; g >= start_glyph; --g)
+ swidth += glyphs.effectiveAdvance(g);
+ } else {
+ for (int g = glyphsStart; g < start_glyph; ++g)
+ soff += glyphs.effectiveAdvance(g);
+ for (int g = start_glyph; g < end_glyph; ++g)
+ swidth += glyphs.effectiveAdvance(g);
+ }
+
+ // If the starting character is in the middle of a ligature,
+ // selection should only contain the right part of that ligature
+ // glyph, so we need to get the width of the left part here and
+ // add it to *selectionX
+ QFixed leftOffsetInLigature = eng->offsetInLigature(si, from, to, start_glyph);
+ *selectionX = x + soff + leftOffsetInLigature;
+ *selectionWidth = swidth - leftOffsetInLigature;
+ // If the ending character is also part of a ligature, swidth does
+ // not contain that part yet, we also need to find out the width of
+ // that left part
+ *selectionWidth += eng->offsetInLigature(si, to, eng->length(item), end_glyph);
+ }
+ return true;
+}
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp
index 97e8c5b..2c6e579 100644
--- a/src/gui/text/qtextengine_mac.cpp
+++ b/src/gui/text/qtextengine_mac.cpp
@@ -605,11 +605,11 @@ void QTextEngine::shapeTextMac(int item) const
unsigned short *log_clusters = logClusters(&si);
bool stringToCMapFailed = false;
- if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) {
+ if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes(), &si)) {
ensureSpace(num_glyphs);
g = availableGlyphs(&si);
stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters,
- attributes());
+ attributes(), &si);
}
if (!stringToCMapFailed) {
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 366c5c3..c476485 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -64,6 +64,7 @@
#include "QtGui/qpaintengine.h"
#include "QtGui/qtextobject.h"
#include "QtGui/qtextoption.h"
+#include "QtGui/qtextcursor.h"
#include "QtCore/qset.h"
#include "QtCore/qdebug.h"
#ifndef QT_BUILD_COMPAT_LIB
@@ -471,6 +472,7 @@ public:
void shape(int item) const;
void justify(const QScriptLine &si);
+ QFixed alignLine(const QScriptLine &line);
QFixed width(int charFrom, int numChars) const;
glyph_metrics_t boundingBox(int from, int len) const;
@@ -586,12 +588,18 @@ public:
uint cacheGlyphs : 1;
uint stackEngine : 1;
uint forceJustification : 1;
+ uint visualMovement : 1;
int *underlinePositions;
mutable LayoutData *layoutData;
inline bool hasFormats() const { return (block.docHandle() || specialData); }
+ inline bool visualCursorMovement() const
+ {
+ return (visualMovement ||
+ (block.docHandle() ? block.docHandle()->defaultCursorMoveStyle == QTextCursor::Visual : false));
+ }
struct SpecialData {
int preeditPosition;
@@ -611,6 +619,13 @@ public:
void shapeLine(const QScriptLine &line);
QFixed leadingSpaceWidth(const QScriptLine &line);
+ QFixed offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos);
+ int previousLogicalPosition(int oldPos) const;
+ int nextLogicalPosition(int oldPos) const;
+ int lineNumberForTextPosition(int pos);
+ int positionAfterVisualMovement(int oldPos, QTextCursor::MoveOperation op);
+ void insertionPointsForLine(int lineNum, QVector<int> &insertionPoints);
+
private:
void setBoundary(int strPos) const;
void addRequiredBoundaries() const;
@@ -625,6 +640,8 @@ private:
void splitItem(int item, int pos) const;
void resolveAdditionalFormats() const;
+ int endOfLine(int lineNum);
+ int beginningOfLine(int lineNum);
};
class QStackTextEngine : public QTextEngine {
@@ -635,6 +652,49 @@ public:
void *_memory[MemSize];
};
+struct QTextLineItemIterator
+{
+ QTextLineItemIterator(QTextEngine *eng, int lineNum, const QPointF &pos = QPointF(),
+ const QTextLayout::FormatRange *_selection = 0);
+
+ inline bool atEnd() const { return logicalItem >= nItems - 1; }
+ inline bool atBeginning() const { return logicalItem <= 0; }
+ QScriptItem &next();
+
+ bool getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const;
+ inline bool isOutsideSelection() const {
+ QFixed tmp1, tmp2;
+ return !getSelectionBounds(&tmp1, &tmp2);
+ }
+
+ QTextEngine *eng;
+
+ QFixed x;
+ QFixed pos_x;
+ const QScriptLine &line;
+ QScriptItem *si;
+
+ int lineNum;
+ int lineEnd;
+ int firstItem;
+ int lastItem;
+ int nItems;
+ int logicalItem;
+ int item;
+ int itemLength;
+
+ int glyphsStart;
+ int glyphsEnd;
+ int itemStart;
+ int itemEnd;
+
+ QFixed itemWidth;
+
+ QVarLengthArray<int> visualOrder;
+ QVarLengthArray<uchar> levels;
+
+ const QTextLayout::FormatRange *selection;
+};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextEngine::ShaperFlags)
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index ff28eaa..4f4752a 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -378,7 +378,8 @@ public:
AlignSubScript,
AlignMiddle,
AlignTop,
- AlignBottom
+ AlignBottom,
+ AlignBaseline
};
enum UnderlineStyle { // keep in sync with Qt::PenStyle!
NoUnderline,
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index afe6949..01748b9 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -54,35 +54,24 @@
#include "qpainterpath.h"
#include "qglyphs.h"
#include "qglyphs_p.h"
+#include "qrawfont.h"
+#include "qrawfont_p.h"
#include <limits.h>
#include <qdebug.h>
#include "qfontengine_p.h"
+#if !defined(QT_NO_FREETYPE)
+# include "qfontengine_ft_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
#define ObjectSelectionBrush (QTextFormat::ForegroundBrush + 1)
#define SuppressText 0x5012
#define SuppressBackground 0x513
-static QFixed alignLine(QTextEngine *eng, const QScriptLine &line)
-{
- QFixed x = 0;
- eng->justify(line);
- // if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned.
- if (!line.justified && line.width != QFIXED_MAX) {
- int align = eng->option.alignment();
- if (align & Qt::AlignJustify && eng->isRightToLeft())
- align = Qt::AlignRight;
- if (align & Qt::AlignRight)
- x = line.width - (line.textAdvance + eng->leadingSpaceWidth(line));
- else if (align & Qt::AlignHCenter)
- x = (line.width - line.textAdvance)/2;
- }
- return x;
-}
-
/*!
\class QTextLayout::FormatRange
\reentrant
@@ -590,6 +579,30 @@ bool QTextLayout::cacheEnabled() const
}
/*!
+ Set the visual cursor movement style. If the QTextLayout is backed by
+ a document, you can ignore this and use the option in QTextDocument,
+ this option is for widgets like QLineEdit or custom widgets without
+ a QTextDocument. Default value is QTextCursor::Logical.
+
+ \sa setCursorMoveStyle()
+*/
+void QTextLayout::setCursorMoveStyle(QTextCursor::MoveStyle style)
+{
+ d->visualMovement = style == QTextCursor::Visual ? true : false;
+}
+
+/*!
+ The cursor movement style of this QTextLayout. The default is
+ QTextCursor::Logical.
+
+ \sa setCursorMoveStyle()
+*/
+QTextCursor::MoveStyle QTextLayout::cursorMoveStyle() const
+{
+ return d->visualMovement ? QTextCursor::Visual : QTextCursor::Logical;
+}
+
+/*!
Begins the layout process.
\sa endLayout()
@@ -712,6 +725,34 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
}
/*!
+ Returns the cursor position to the right of \a oldPos, next to it.
+ It's dependent on the visual position of characters, after bi-directional
+ reordering.
+
+ \sa leftCursorPosition(), nextCursorPosition()
+*/
+int QTextLayout::rightCursorPosition(int oldPos) const
+{
+ int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Right);
+// qDebug("%d -> %d", oldPos, newPos);
+ return newPos;
+}
+
+/*!
+ Returns the cursor position to the left of \a oldPos, next to it.
+ It's dependent on the visual position of characters, after bi-directional
+ reordering.
+
+ \sa rightCursorPosition(), previousCursorPosition()
+*/
+int QTextLayout::leftCursorPosition(int oldPos) const
+{
+ int newPos = d->positionAfterVisualMovement(oldPos, QTextCursor::Left);
+// qDebug("%d -> %d", oldPos, newPos);
+ return newPos;
+}
+
+/*!/
Returns true if position \a pos is a valid cursor position.
In a Unicode context some positions in the text are not valid
@@ -809,16 +850,8 @@ QTextLine QTextLayout::lineAt(int i) const
*/
QTextLine QTextLayout::lineForTextPosition(int pos) const
{
- for (int i = 0; i < d->lines.size(); ++i) {
- const QScriptLine& line = d->lines[i];
- if (line.from + (int)line.length > pos)
- return QTextLine(i, d);
- }
- if (!d->layoutData)
- d->itemize();
- if (pos == d->layoutData->string.length() && d->lines.size())
- return QTextLine(d->lines.size()-1, d);
- return QTextLine();
+ int lineNum = d->lineNumberForTextPosition(pos);
+ return lineNum >= 0 ? lineAt(lineNum) : QTextLine();
}
/*!
@@ -913,201 +946,6 @@ void QTextLayout::setFlags(int flags)
}
}
-struct QTextLineItemIterator
-{
- QTextLineItemIterator(QTextEngine *eng, int lineNum, const QPointF &pos = QPointF(),
- const QTextLayout::FormatRange *_selection = 0);
-
- inline bool atEnd() const { return logicalItem >= nItems - 1; }
- QScriptItem &next();
-
- bool getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const;
- inline bool isOutsideSelection() const {
- QFixed tmp1, tmp2;
- return !getSelectionBounds(&tmp1, &tmp2);
- }
-
- QTextEngine *eng;
-
- QFixed x;
- QFixed pos_x;
- const QScriptLine &line;
- QScriptItem *si;
-
- int lineEnd;
- int firstItem;
- int lastItem;
- int nItems;
- int logicalItem;
- int item;
- int itemLength;
-
- int glyphsStart;
- int glyphsEnd;
- int itemStart;
- int itemEnd;
-
- QFixed itemWidth;
-
- QVarLengthArray<int> visualOrder;
- QVarLengthArray<uchar> levels;
-
- const QTextLayout::FormatRange *selection;
-};
-
-QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int lineNum, const QPointF &pos,
- const QTextLayout::FormatRange *_selection)
- : eng(_eng),
- line(eng->lines[lineNum]),
- si(0),
- lineEnd(line.from + line.length),
- firstItem(eng->findItem(line.from)),
- lastItem(eng->findItem(lineEnd - 1)),
- nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0),
- logicalItem(-1),
- item(-1),
- visualOrder(nItems),
- levels(nItems),
- selection(_selection)
-{
- pos_x = x = QFixed::fromReal(pos.x());
-
- x += line.x;
-
- x += alignLine(eng, line);
-
- for (int i = 0; i < nItems; ++i)
- levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
- QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
-
- eng->shapeLine(line);
-}
-
-QScriptItem &QTextLineItemIterator::next()
-{
- x += itemWidth;
-
- ++logicalItem;
- item = visualOrder[logicalItem] + firstItem;
- itemLength = eng->length(item);
- si = &eng->layoutData->items[item];
- if (!si->num_glyphs)
- eng->shape(item);
-
- if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
- itemWidth = si->width;
- return *si;
- }
-
- unsigned short *logClusters = eng->logClusters(si);
- QGlyphLayout glyphs = eng->shapedGlyphs(si);
-
- itemStart = qMax(line.from, si->position);
- glyphsStart = logClusters[itemStart - si->position];
- if (lineEnd < si->position + itemLength) {
- itemEnd = lineEnd;
- glyphsEnd = logClusters[itemEnd-si->position];
- } else {
- itemEnd = si->position + itemLength;
- glyphsEnd = si->num_glyphs;
- }
- // show soft-hyphen at line-break
- if (si->position + itemLength >= lineEnd
- && eng->layoutData->string.at(lineEnd - 1) == 0x00ad)
- glyphs.attributes[glyphsEnd - 1].dontPrint = false;
-
- itemWidth = 0;
- for (int g = glyphsStart; g < glyphsEnd; ++g)
- itemWidth += glyphs.effectiveAdvance(g);
-
- return *si;
-}
-
-static QFixed offsetInLigature(const unsigned short *logClusters,
- const QGlyphLayout &glyphs,
- int pos, int max, int glyph_pos)
-{
- int offsetInCluster = 0;
- for (int i = pos - 1; i >= 0; i--) {
- if (logClusters[i] == glyph_pos)
- offsetInCluster++;
- else
- break;
- }
-
- // in the case that the offset is inside a (multi-character) glyph,
- // interpolate the position.
- if (offsetInCluster > 0) {
- int clusterLength = 0;
- for (int i = pos - offsetInCluster; i < max; i++) {
- if (logClusters[i] == glyph_pos)
- clusterLength++;
- else
- break;
- }
- if (clusterLength)
- return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength;
- }
-
- return 0;
-}
-
-bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const
-{
- *selectionX = *selectionWidth = 0;
-
- if (!selection)
- return false;
-
- if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
- if (si->position >= selection->start + selection->length
- || si->position + itemLength <= selection->start)
- return false;
-
- *selectionX = x;
- *selectionWidth = itemWidth;
- } else {
- unsigned short *logClusters = eng->logClusters(si);
- QGlyphLayout glyphs = eng->shapedGlyphs(si);
-
- int from = qMax(itemStart, selection->start) - si->position;
- int to = qMin(itemEnd, selection->start + selection->length) - si->position;
- if (from >= to)
- return false;
-
- int start_glyph = logClusters[from];
- int end_glyph = (to == eng->length(item)) ? si->num_glyphs : logClusters[to];
- QFixed soff;
- QFixed swidth;
- if (si->analysis.bidiLevel %2) {
- for (int g = glyphsEnd - 1; g >= end_glyph; --g)
- soff += glyphs.effectiveAdvance(g);
- for (int g = end_glyph - 1; g >= start_glyph; --g)
- swidth += glyphs.effectiveAdvance(g);
- } else {
- for (int g = glyphsStart; g < start_glyph; ++g)
- soff += glyphs.effectiveAdvance(g);
- for (int g = start_glyph; g < end_glyph; ++g)
- swidth += glyphs.effectiveAdvance(g);
- }
-
- // If the starting character is in the middle of a ligature,
- // selection should only contain the right part of that ligature
- // glyph, so we need to get the width of the left part here and
- // add it to *selectionX
- QFixed leftOffsetInLigature = offsetInLigature(logClusters, glyphs, from,
- to, start_glyph);
- *selectionX = x + soff + leftOffsetInLigature;
- *selectionWidth = swidth - leftOffsetInLigature;
- // If the ending character is also part of a ligature, swidth does
- // not contain that part yet, we also need to find out the width of
- // that left part
- *selectionWidth += offsetInLigature(logClusters, glyphs, to,
- eng->length(item), end_glyph);
- }
- return true;
-}
-
static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPointF &pos, QTextLayout::FormatRange *selection,
QPainterPath *region, QRectF boundingRect)
{
@@ -1158,6 +996,7 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
\sa draw(), QPainter::drawGlyphs()
*/
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> QTextLayout::glyphs() const
{
QList<QGlyphs> glyphs;
@@ -1166,6 +1005,7 @@ QList<QGlyphs> QTextLayout::glyphs() const
return glyphs;
}
+#endif // QT_NO_RAWFONT
/*!
Draws the whole layout on the painter \a p at the position specified by \a pos.
@@ -1220,6 +1060,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
QRectF lineRect(tl.naturalTextRect());
lineRect.translate(position);
+ lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0);
bool isLastLineInBlock = (line == d->lines.size()-1);
int sl_length = sl.length + (isLastLineInBlock? 1 : 0); // the infamous newline
@@ -1370,22 +1211,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
d->itemize();
QPointF position = pos + d->position;
- QFixed pos_x = QFixed::fromReal(position.x());
- QFixed pos_y = QFixed::fromReal(position.y());
cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length());
- int line = 0;
- if (cursorPosition == d->layoutData->string.length()) {
- line = d->lines.size() - 1;
- } else {
- // ### binary search
- for (line = 0; line < d->lines.size(); line++) {
- const QScriptLine &sl = d->lines[line];
- if (sl.from <= cursorPosition && sl.from + (int)sl.length > cursorPosition)
- break;
- }
- }
-
+ int line = d->lineNumberForTextPosition(cursorPosition);
+ if (line < 0)
+ line = 0;
if (line >= d->lines.size())
return;
@@ -1394,7 +1224,15 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
qreal x = position.x() + l.cursorToX(cursorPosition);
- int itm = d->findItem(cursorPosition - 1);
+ int itm;
+
+ if (d->visualCursorMovement()) {
+ if (cursorPosition == sl.from + sl.length)
+ cursorPosition--;
+ itm = d->findItem(cursorPosition);
+ } else
+ itm = d->findItem(cursorPosition - 1);
+
QFixed base = sl.base();
QFixed descent = sl.descent;
bool rightToLeft = d->isRightToLeft();
@@ -1504,7 +1342,7 @@ QRectF QTextLine::rect() const
QRectF QTextLine::naturalTextRect() const
{
const QScriptLine& sl = eng->lines[i];
- QFixed x = sl.x + alignLine(eng, sl);
+ QFixed x = sl.x + eng->alignLine(sl);
QFixed width = sl.textWidth;
if (sl.justified)
@@ -2257,6 +2095,7 @@ namespace {
\sa QTextLayout::glyphs()
*/
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> QTextLine::glyphs(int from, int length) const
{
const QScriptLine &line = eng->lines[i];
@@ -2308,6 +2147,9 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
GlyphInfo(subLayout, pos, flags));
+ for (int i = 0; i < subLayout.numGlyphs; i++)
+ pos += QPointF(subLayout.advances_x[i].toReal(),
+ subLayout.advances_y[i].toReal());
start = end;
which = e;
@@ -2331,7 +2173,35 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
QFontEngine *fontEngine = keys.at(i);
// Make a font for this particular engine
- QFont font = fontEngine->createExplicitFont();
+ QRawFont font;
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ fontD->fontEngine = fontEngine;
+ fontD->fontEngine->ref.ref();
+
+#if defined(Q_WS_WIN)
+ if (fontEngine->supportsSubPixelPositions())
+ fontD->hintingPreference = QFont::PreferVerticalHinting;
+ else
+ fontD->hintingPreference = QFont::PreferFullHinting;
+#elif defined(Q_WS_MAC)
+ fontD->hintingPreference = QFont::PreferNoHinting;
+#elif !defined(QT_NO_FREETYPE)
+ if (fontEngine->type() == QFontEngine::Freetype) {
+ QFontEngineFT *freeTypeEngine = static_cast<QFontEngineFT *>(fontEngine);
+ switch (freeTypeEngine->defaultHintStyle()) {
+ case QFontEngineFT::HintNone:
+ fontD->hintingPreference = QFont::PreferNoHinting;
+ break;
+ case QFontEngineFT::HintLight:
+ fontD->hintingPreference = QFont::PreferVerticalHinting;
+ break;
+ case QFontEngineFT::HintMedium:
+ case QFontEngineFT::HintFull:
+ fontD->hintingPreference = QFont::PreferFullHinting;
+ break;
+ };
+ }
+#endif
QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine);
for (int j=0; j<glyphLayouts.size(); ++j) {
@@ -2339,10 +2209,6 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout;
const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags;
- font.setOverline(flags.testFlag(QTextItem::Overline));
- font.setUnderline(flags.testFlag(QTextItem::Underline));
- font.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
-
QVarLengthArray<glyph_t> glyphsArray;
QVarLengthArray<QFixedPoint> positionsArray;
@@ -2361,19 +2227,22 @@ QList<QGlyphs> QTextLine::glyphs(int from, int length) const
glyphIndexes.setGlyphIndexes(glyphs);
glyphIndexes.setPositions(positions);
- QPair<QFontEngine *, int> key(fontEngine, int(flags));
+ glyphIndexes.setOverline(flags.testFlag(QTextItem::Overline));
+ glyphIndexes.setUnderline(flags.testFlag(QTextItem::Underline));
+ glyphIndexes.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
+ glyphIndexes.setFont(font);
+ QPair<QFontEngine *, int> key(fontEngine, int(flags));
if (!glyphsHash.contains(key))
- glyphsHash.insert(key, QGlyphs());
-
- QGlyphs &target = glyphsHash[key];
- target += glyphIndexes;
- target.setFont(font);
+ glyphsHash.insert(key, glyphIndexes);
+ else
+ glyphsHash[key] += glyphIndexes;
}
}
return glyphsHash.values();
}
+#endif // QT_NO_RAWFONT
/*!
\fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const
@@ -2596,9 +2465,10 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
eng->itemize();
const QScriptLine &line = eng->lines[i];
+ bool lastLine = i >= eng->lines.size() - 1;
QFixed x = line.x;
- x += alignLine(eng, line);
+ x += eng->alignLine(line);
if (!i && !eng->layoutData->items.size()) {
*cursorPos = 0;
@@ -2684,21 +2554,29 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
logClusters = eng->logClusters(si);
glyphs = eng->shapedGlyphs(si);
if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
- if(pos == l)
+ if (pos == (reverse ? 0 : l))
x += si->width;
} else {
+ bool rtl = eng->isRightToLeft();
+ bool visual = eng->visualCursorMovement();
if (reverse) {
int end = qMin(lineEnd, si->position + l) - si->position;
int glyph_end = end == l ? si->num_glyphs : logClusters[end];
- for (int i = glyph_end - 1; i >= glyph_pos; i--)
+ int glyph_start = glyph_pos;
+ if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))
+ glyph_start++;
+ for (int i = glyph_end - 1; i >= glyph_start; i--)
x += glyphs.effectiveAdvance(i);
} else {
int start = qMax(line.from - si->position, 0);
int glyph_start = logClusters[start];
- for (int i = glyph_start; i < glyph_pos; i++)
+ int glyph_end = glyph_pos;
+ if (!visual || !rtl || (lastLine && itm == visualOrder[0] + firstItem))
+ glyph_end--;
+ for (int i = glyph_start; i <= glyph_end; i++)
x += glyphs.effectiveAdvance(i);
}
- x += offsetInLigature(logClusters, glyphs, pos, line.length, glyph_pos);
+ x += eng->offsetInLigature(si, pos, line.length, glyph_pos);
}
*cursorPos = pos + si->position;
@@ -2717,6 +2595,8 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
{
QFixed x = QFixed::fromReal(_x);
const QScriptLine &line = eng->lines[i];
+ bool lastLine = i >= eng->lines.size() - 1;
+ int lineNum = i;
if (!eng->layoutData)
eng->itemize();
@@ -2734,7 +2614,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
return 0;
x -= line.x;
- x -= alignLine(eng, line);
+ x -= eng->alignLine(line);
// qDebug("xToCursor: x=%f, cpos=%d", x.toReal(), cpos);
QVarLengthArray<int> visualOrder(nItems);
@@ -2743,6 +2623,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
+ bool visual = eng->visualCursorMovement();
if (x <= 0) {
// left of first item
int item = visualOrder[0]+firstItem;
@@ -2759,8 +2640,13 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
|| (line.justified && x < line.width)) {
// has to be in one of the runs
QFixed pos;
+ bool rtl = eng->isRightToLeft();
eng->shapeLine(line);
+ QVector<int> insertionPoints;
+ if (visual && rtl)
+ eng->insertionPointsForLine(lineNum, insertionPoints);
+ int nchars = 0;
for (int i = 0; i < nItems; ++i) {
int item = visualOrder[i]+firstItem;
QScriptItem &si = eng->layoutData->items[item];
@@ -2790,6 +2676,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
if (pos + item_width < x) {
pos += item_width;
+ nchars += end;
continue;
}
// qDebug(" inside run");
@@ -2834,27 +2721,60 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
} else {
QFixed dist = INT_MAX/256;
if (si.analysis.bidiLevel % 2) {
- pos += item_width;
- while (gs <= ge) {
- if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
- glyph_pos = gs;
- dist = qAbs(x-pos);
+ if (!visual || rtl || (lastLine && i == nItems - 1)) {
+ pos += item_width;
+ while (gs <= ge) {
+ if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
+ glyph_pos = gs;
+ dist = qAbs(x-pos);
+ }
+ pos -= glyphs.effectiveAdvance(gs);
+ ++gs;
+ }
+ } else {
+ while (ge >= gs) {
+ if (glyphs.attributes[ge].clusterStart && qAbs(x-pos) < dist) {
+ glyph_pos = ge;
+ dist = qAbs(x-pos);
+ }
+ pos += glyphs.effectiveAdvance(ge);
+ --ge;
}
- pos -= glyphs.effectiveAdvance(gs);
- ++gs;
}
} else {
- while (gs <= ge) {
- if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
- glyph_pos = gs;
- dist = qAbs(x-pos);
+ if (!visual || !rtl || (lastLine && i == 0)) {
+ while (gs <= ge) {
+ if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
+ glyph_pos = gs;
+ dist = qAbs(x-pos);
+ }
+ pos += glyphs.effectiveAdvance(gs);
+ ++gs;
}
- pos += glyphs.effectiveAdvance(gs);
- ++gs;
+ } else {
+ QFixed oldPos = pos;
+ while (gs <= ge) {
+ pos += glyphs.effectiveAdvance(gs);
+ if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
+ glyph_pos = gs;
+ dist = qAbs(x-pos);
+ }
+ ++gs;
+ }
+ pos = oldPos;
}
}
- if (qAbs(x-pos) < dist)
+ if (qAbs(x-pos) < dist) {
+ if (visual) {
+ if (!rtl && i < nItems - 1) {
+ nchars += end;
+ continue;
+ }
+ if (rtl && nchars > 0)
+ return insertionPoints[lastLine ? nchars : nchars - 1];
+ }
return si.position + end;
+ }
}
Q_ASSERT(glyph_pos != -1);
int j;
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 0f64c33..6aa81f9 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -50,6 +50,7 @@
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
#include <QtGui/qglyphs.h>
+#include <QtGui/qtextcursor.h>
QT_BEGIN_HEADER
@@ -136,6 +137,9 @@ public:
void setCacheEnabled(bool enable);
bool cacheEnabled() const;
+ void setCursorMoveStyle(QTextCursor::MoveStyle style);
+ QTextCursor::MoveStyle cursorMoveStyle() const;
+
void beginLayout();
void endLayout();
void clearLayout();
@@ -153,6 +157,8 @@ public:
bool isValidCursorPosition(int pos) const;
int nextCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
int previousCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
+ int leftCursorPosition(int oldPos) const;
+ int rightCursorPosition(int oldPos) const;
void draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections = QVector<FormatRange>(),
const QRectF &clip = QRectF()) const;
@@ -167,7 +173,9 @@ public:
qreal minimumWidth() const;
qreal maximumWidth() const;
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> glyphs() const;
+#endif
QTextEngine *engine() const { return d; }
void setFlags(int flags);
@@ -239,7 +247,10 @@ public:
private:
QTextLine(int line, QTextEngine *e) : i(line), eng(e) {}
void layout_helper(int numGlyphs);
+
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> glyphs(int from, int length) const;
+#endif
friend class QTextLayout;
friend class QTextFragment;
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 0081550..5c1c8b9 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -891,6 +891,11 @@ QTextBlockUserData::~QTextBlockUserData()
Returns true if this text block is valid; otherwise returns false.
*/
+bool QTextBlock::isValid() const
+{
+ return p != 0 && p->blockMap().isValid(n);
+}
+
/*!
\fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
@@ -1661,6 +1666,7 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
\sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs()
*/
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> QTextFragment::glyphs() const
{
if (!p || !n)
@@ -1684,6 +1690,7 @@ QList<QGlyphs> QTextFragment::glyphs() const
return ret;
}
+#endif // QT_NO_RAWFONT
/*!
Returns the position of this text fragment in the document.
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index fface3f..ad8e657 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -205,7 +205,7 @@ public:
inline QTextBlock(const QTextBlock &o) : p(o.p), n(o.n) {}
inline QTextBlock &operator=(const QTextBlock &o) { p = o.p; n = o.n; return *this; }
- inline bool isValid() const { return p != 0 && n != 0; }
+ bool isValid() const;
inline bool operator==(const QTextBlock &o) const { return p == o.p && n == o.n; }
inline bool operator!=(const QTextBlock &o) const { return p != o.p || n != o.n; }
@@ -316,7 +316,9 @@ public:
int charFormatIndex() const;
QString text() const;
+#if !defined(QT_NO_RAWFONT)
QList<QGlyphs> glyphs() const;
+#endif
private:
const QTextDocumentPrivate *p;
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index 7fb2783..e5d57d0 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -41,7 +41,9 @@ HEADERS += \
text/qstatictext_p.h \
text/qstatictext.h \
text/qglyphs.h \
- text/qglyphs_p.h
+ text/qglyphs_p.h \
+ text/qrawfont.h \
+ text/qrawfont_p.h
SOURCES += \
text/qfont.cpp \
@@ -72,12 +74,14 @@ SOURCES += \
text/qzip.cpp \
text/qtextodfwriter.cpp \
text/qstatictext.cpp \
- text/qglyphs.cpp
+ text/qglyphs.cpp \
+ text/qrawfont.cpp
win32 {
SOURCES += \
text/qfont_win.cpp \
- text/qfontengine_win.cpp
+ text/qfontengine_win.cpp \
+ text/qrawfont_win.cpp
HEADERS += text/qfontengine_win_p.h
}
@@ -95,7 +99,8 @@ unix:x11 {
SOURCES += \
text/qfont_x11.cpp \
text/qfontengine_x11.cpp \
- text/qfontengine_ft.cpp
+ text/qfontengine_ft.cpp \
+ text/qrawfont_ft.cpp
}
!embedded:!qpa:!x11:mac {
@@ -104,10 +109,14 @@ unix:x11 {
OBJECTIVE_HEADERS += \
text/qfontengine_coretext_p.h
SOURCES += \
- text/qfont_mac.cpp
+ text/qfont_mac.cpp \
+ text/qrawfont_mac.cpp
OBJECTIVE_SOURCES += \
text/qfontengine_coretext.mm \
text/qfontengine_mac.mm
+ contains(QT_CONFIG, harfbuzz) {
+ DEFINES += QT_ENABLE_HARFBUZZ_FOR_MAC
+ }
}
embedded {
@@ -116,7 +125,8 @@ embedded {
text/qfontengine_qws.cpp \
text/qfontengine_ft.cpp \
text/qfontengine_qpf.cpp \
- text/qabstractfontengine_qws.cpp
+ text/qabstractfontengine_qws.cpp \
+ text/qrawfont_ft.cpp
HEADERS += \
text/qfontengine_ft_p.h \
text/qfontengine_qpf_p.h \
@@ -129,7 +139,8 @@ qpa {
SOURCES += \
text/qfont_qpa.cpp \
text/qfontengine_qpa.cpp \
- text/qplatformfontdatabase_qpa.cpp
+ text/qplatformfontdatabase_qpa.cpp \
+ text/qrawfont_qpa.cpp
HEADERS += \
text/qplatformfontdatabase_qpa.h
@@ -143,7 +154,8 @@ symbian {
text/qfont_s60.cpp
contains(QT_CONFIG, freetype) {
SOURCES += \
- text/qfontengine_ft.cpp
+ text/qfontengine_ft.cpp \
+ text/qrawfont_ft.cpp
HEADERS += \
text/qfontengine_ft_p.h
DEFINES += \
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
index 96860df..8caeb74 100644
--- a/src/gui/util/qdesktopservices_s60.cpp
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -314,7 +314,7 @@ static bool handleUrl(const QUrl &url)
if (!url.isValid())
return false;
- QString urlString(url.toString());
+ QString urlString(url.toEncoded());
TPtrC urlPtr(qt_QString2TPtrC(urlString));
TRAPD( err, handleUrlL(urlPtr));
return err ? false : true;
diff --git a/src/gui/util/qflickgesture.cpp b/src/gui/util/qflickgesture.cpp
index fdd2a95..f87c84c 100644
--- a/src/gui/util/qflickgesture.cpp
+++ b/src/gui/util/qflickgesture.cpp
@@ -218,10 +218,10 @@ public:
mouseTarget = 0;
} else if (mouseTarget) {
// we did send a press, so we need to fake a release now
- Qt::MouseButtons mouseButtons = QApplication::mouseButtons();
// release all pressed mouse buttons
- /*for (int i = 0; i < 32; ++i) {
+ /* Qt::MouseButtons mouseButtons = QApplication::mouseButtons();
+ for (int i = 0; i < 32; ++i) {
if (mouseButtons & (1 << i)) {
Qt::MouseButton b = static_cast<Qt::MouseButton>(1 << i);
mouseButtons &= ~b;
diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp
index 9c2d24d..870d56f 100644
--- a/src/gui/util/qscroller.cpp
+++ b/src/gui/util/qscroller.cpp
@@ -279,9 +279,11 @@ private:
\sa QScrollEvent, QScrollPrepareEvent, QScrollerProperties
*/
+typedef QMap<QObject *, QScroller *> ScrollerHash;
+typedef QSet<QScroller *> ScrollerSet;
-QMap<QObject *, QScroller *> QScrollerPrivate::allScrollers;
-QSet<QScroller *> QScrollerPrivate::activeScrollers;
+Q_GLOBAL_STATIC(ScrollerHash, qt_allScrollers)
+Q_GLOBAL_STATIC(ScrollerSet, qt_activeScrollers)
/*!
Returns \c true if a QScroller object was already created for \a target; \c false otherwise.
@@ -290,7 +292,7 @@ QSet<QScroller *> QScrollerPrivate::activeScrollers;
*/
bool QScroller::hasScroller(QObject *target)
{
- return (QScrollerPrivate::allScrollers.value(target));
+ return (qt_allScrollers()->value(target));
}
/*!
@@ -308,11 +310,11 @@ QScroller *QScroller::scroller(QObject *target)
return 0;
}
- if (QScrollerPrivate::allScrollers.contains(target))
- return QScrollerPrivate::allScrollers.value(target);
+ if (qt_allScrollers()->contains(target))
+ return qt_allScrollers()->value(target);
QScroller *s = new QScroller(target);
- QScrollerPrivate::allScrollers.insert(target, s);
+ qt_allScrollers()->insert(target, s);
return s;
}
@@ -332,7 +334,7 @@ const QScroller *QScroller::scroller(const QObject *target)
*/
QList<QScroller *> QScroller::activeScrollers()
{
- return QScrollerPrivate::activeScrollers.toList();
+ return qt_activeScrollers()->toList();
}
/*!
@@ -508,8 +510,8 @@ QScroller::~QScroller()
// do not delete the recognizer. The QGestureManager is doing this.
d->recognizer = 0;
#endif
- QScrollerPrivate::allScrollers.remove(d->target);
- QScrollerPrivate::activeScrollers.remove(this);
+ qt_allScrollers()->remove(d->target);
+ qt_activeScrollers()->remove(this);
delete d_ptr;
}
@@ -1754,9 +1756,9 @@ void QScrollerPrivate::setState(QScroller::State newstate)
firstScroll = true;
}
if (state == QScroller::Dragging || state == QScroller::Scrolling)
- activeScrollers.insert(q);
+ qt_activeScrollers()->insert(q);
else
- activeScrollers.remove(q);
+ qt_activeScrollers()->remove(q);
emit q->stateChanged(state);
}
@@ -1775,10 +1777,7 @@ void QScrollerPrivate::setState(QScroller::State newstate)
*/
void QScrollerPrivate::setContentPositionHelperDragging(const QPointF &deltaPos)
{
- Q_Q(QScroller);
- QPointF ppm = q->pixelPerMeter();
const QScrollerPropertiesPrivate *sp = properties.d.data();
- QPointF v = q->velocity();
if (sp->overshootDragResistanceFactor)
overshootPosition /= sp->overshootDragResistanceFactor;
diff --git a/src/gui/util/qscroller_p.h b/src/gui/util/qscroller_p.h
index 8c5f2e7..c119615 100644
--- a/src/gui/util/qscroller_p.h
+++ b/src/gui/util/qscroller_p.h
@@ -148,10 +148,6 @@ public slots:
void targetDestroyed();
public:
- // static
- static QMap<QObject *, QScroller *> allScrollers;
- static QSet<QScroller *> activeScrollers;
-
// non static
QObject *target;
QScrollerProperties properties;
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 5f00afa..dd1ad9c 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -399,7 +399,7 @@ void QComboBoxPrivateContainer::leaveEvent(QEvent *)
#ifdef Q_WS_MAC
QStyleOptionComboBox opt = comboStyleOption();
if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, combo))
- view->setCurrentIndex(QModelIndex());
+ view->clearSelection();
#endif
}
@@ -672,8 +672,8 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive())
blockMouseReleaseTimer.stop();
QModelIndex indexUnderMouse = view->indexAt(m->pos());
- if (indexUnderMouse.isValid() && indexUnderMouse != view->currentIndex()
- && !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
+ if (indexUnderMouse.isValid()
+ && !QComboBoxDelegate::isSeparator(indexUnderMouse)) {
view->setCurrentIndex(indexUnderMouse);
}
}
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 6337113..a4739a7 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -2538,20 +2538,32 @@ void QDateTimeEditPrivate::syncCalendarWidget()
}
QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
- : QWidget(parent, Qt::Popup), calendar(0)
+ : QWidget(parent, Qt::Popup)
{
setAttribute(Qt::WA_WindowPropagation);
dateChanged = false;
if (!cw) {
- cw = new QCalendarWidget(this);
+ verifyCalendarInstance();
+ } else {
+ setCalendarWidget(cw);
+ }
+}
+
+QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
+{
+ if (calendar.isNull()) {
+ QCalendarWidget *cw = new QCalendarWidget(this);
cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled())
cw->setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);
#endif
+ setCalendarWidget(cw);
+ return cw;
+ } else {
+ return calendar.data();
}
- setCalendarWidget(cw);
}
void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
@@ -2563,28 +2575,29 @@ void QCalendarPopup::setCalendarWidget(QCalendarWidget *cw)
widgetLayout->setMargin(0);
widgetLayout->setSpacing(0);
}
- delete calendar;
- calendar = cw;
- widgetLayout->addWidget(calendar);
+ delete calendar.data();
+ calendar = QWeakPointer<QCalendarWidget>(cw);
+ widgetLayout->addWidget(cw);
- connect(calendar, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
- connect(calendar, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
- connect(calendar, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
+ connect(cw, SIGNAL(activated(QDate)), this, SLOT(dateSelected(QDate)));
+ connect(cw, SIGNAL(clicked(QDate)), this, SLOT(dateSelected(QDate)));
+ connect(cw, SIGNAL(selectionChanged()), this, SLOT(dateSelectionChanged()));
- calendar->setFocus();
+ cw->setFocus();
}
void QCalendarPopup::setDate(const QDate &date)
{
oldDate = date;
- calendar->setSelectedDate(date);
+ verifyCalendarInstance()->setSelectedDate(date);
}
void QCalendarPopup::setDateRange(const QDate &min, const QDate &max)
{
- calendar->setMinimumDate(min);
- calendar->setMaximumDate(max);
+ QCalendarWidget *cw = verifyCalendarInstance();
+ cw->setMinimumDate(min);
+ cw->setMaximumDate(max);
}
void QCalendarPopup::mousePressEvent(QMouseEvent *event)
@@ -2620,7 +2633,7 @@ bool QCalendarPopup::event(QEvent *event)
void QCalendarPopup::dateSelectionChanged()
{
dateChanged = true;
- emit newDateSelected(calendar->selectedDate());
+ emit newDateSelected(verifyCalendarInstance()->selectedDate());
}
void QCalendarPopup::dateSelected(const QDate &date)
{
diff --git a/src/gui/widgets/qdatetimeedit_p.h b/src/gui/widgets/qdatetimeedit_p.h
index acdc878..c85c0fb 100644
--- a/src/gui/widgets/qdatetimeedit_p.h
+++ b/src/gui/widgets/qdatetimeedit_p.h
@@ -148,11 +148,11 @@ class QCalendarPopup : public QWidget
Q_OBJECT
public:
QCalendarPopup(QWidget *parent = 0, QCalendarWidget *cw = 0);
- QDate selectedDate() { return calendar->selectedDate(); }
+ QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); }
void setDate(const QDate &date);
void setDateRange(const QDate &min, const QDate &max);
- void setFirstDayOfWeek(Qt::DayOfWeek dow) { calendar->setFirstDayOfWeek(dow); }
- QCalendarWidget *calendarWidget() const { return calendar; }
+ void setFirstDayOfWeek(Qt::DayOfWeek dow) { verifyCalendarInstance()->setFirstDayOfWeek(dow); }
+ QCalendarWidget *calendarWidget() const { return const_cast<QCalendarPopup*>(this)->verifyCalendarInstance(); }
void setCalendarWidget(QCalendarWidget *cw);
Q_SIGNALS:
void activated(const QDate &date);
@@ -171,7 +171,9 @@ protected:
bool event(QEvent *e);
private:
- QCalendarWidget *calendar;
+ QCalendarWidget *verifyCalendarInstance();
+
+ QWeakPointer<QCalendarWidget> calendar;
QDate oldDate;
bool dateChanged;
};
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 223421d..28c0388 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -2100,7 +2100,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
bool gap = false;
int tab_idx = 0;
- bool changed = false;
for (int i = 0; i < item_list.count(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
if (item.skip())
@@ -2121,7 +2120,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
tabBar->setTabToolTip(tab_idx, title);
#endif
tabBar->setTabData(tab_idx, id);
- changed = true;
} else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
if (tab_idx + 1 < tabBar->count()
&& qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
@@ -2133,7 +2131,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
#endif
tabBar->setTabData(tab_idx, id);
}
- changed = true;
}
if (title != tabBar->tabText(tab_idx)) {
@@ -2141,7 +2138,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
#ifndef QT_NO_TOOLTIP
tabBar->setTabToolTip(tab_idx, title);
#endif
- changed = true;
}
++tab_idx;
@@ -2149,7 +2145,6 @@ bool QDockAreaLayoutInfo::updateTabBar() const
while (tab_idx < tabBar->count()) {
tabBar->removeTab(tab_idx);
- changed = true;
}
tabBar->blockSignals(blocked);
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index 9d1a737..16b60c8 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -161,7 +161,6 @@ void QDockWidgetTitleButton::paintEvent(QPaintEvent *)
{
QPainter p(this);
- QRect r = rect();
QStyleOptionToolButton opt;
opt.init(this);
opt.state |= QStyle::State_AutoRaise;
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 3eac64a..4fb0f0c 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -254,12 +254,20 @@ void QLineControl::setSelection(int start, int length)
m_selstart = start;
m_selend = qMin(start + length, (int)m_text.length());
m_cursor = m_selend;
- } else {
+ } else if (length < 0){
if (start == m_selend && start + length == m_selstart)
return;
m_selstart = qMax(start + length, 0);
m_selend = start;
m_cursor = m_selstart;
+ } else if (m_selstart != m_selend) {
+ m_selstart = 0;
+ m_selend = 0;
+ m_cursor = start;
+ } else {
+ m_cursor = start;
+ emitCursorPositionChanged();
+ return;
}
emit selectionChanged();
emitCursorPositionChanged();
@@ -435,7 +443,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
removeSelectedText();
}
if (!event->commitString().isEmpty()) {
- insert(event->commitString());
+ internalInsert(event->commitString());
cursorPositionChanged = true;
}
@@ -643,7 +651,12 @@ void QLineControl::internalSetText(const QString &txt, int pos, bool edited)
m_modifiedState = m_undoState = 0;
m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
m_textDirty = (oldText != m_text);
- finishChange(-1, true, edited);
+ bool changed = finishChange(-1, true, edited);
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (changed)
+ QAccessible::updateAccessibility(parent(), 0, QAccessible::TextUpdated);
+#endif
}
@@ -1230,6 +1243,9 @@ void QLineControl::emitCursorPositionChanged()
const int oldLast = m_lastCursorPos;
m_lastCursorPos = m_cursor;
cursorPositionChanged(oldLast, m_cursor);
+#ifndef QT_NO_ACCESSIBILITY
+ QAccessible::updateAccessibility(parent(), 0, QAccessible::TextCaretMoved);
+#endif
}
}
@@ -1577,6 +1593,7 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
}
bool unknown = false;
+ bool visual = cursorMoveStyle() == QTextCursor::Visual;
if (false) {
}
@@ -1641,11 +1658,11 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
#endif
moveCursor(selectionEnd(), false);
} else {
- cursorForward(0, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ cursorForward(0, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1));
}
}
else if (event == QKeySequence::SelectNextChar) {
- cursorForward(1, layoutDirection() == Qt::LeftToRight ? 1 : -1);
+ cursorForward(1, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1));
}
else if (event == QKeySequence::MoveToPreviousChar) {
#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER)
@@ -1656,11 +1673,11 @@ void QLineControl::processKeyEvent(QKeyEvent* event)
#endif
moveCursor(selectionStart(), false);
} else {
- cursorForward(0, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ cursorForward(0, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1));
}
}
else if (event == QKeySequence::SelectPreviousChar) {
- cursorForward(1, layoutDirection() == Qt::LeftToRight ? -1 : 1);
+ cursorForward(1, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1));
}
else if (event == QKeySequence::MoveToNextWord) {
if (echoMode() == QLineEdit::Normal)
diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h
index 3c505c8..0655276 100644
--- a/src/gui/widgets/qlinecontrol_p.h
+++ b/src/gui/widgets/qlinecontrol_p.h
@@ -61,10 +61,10 @@
#include "QtGui/qtextlayout.h"
#include "QtGui/qstyleoption.h"
#include "QtCore/qpointer.h"
-#include "QtGui/qlineedit.h"
#include "QtGui/qclipboard.h"
#include "QtCore/qpoint.h"
#include "QtGui/qcompleter.h"
+#include "QtGui/qaccessible.h"
QT_BEGIN_HEADER
@@ -160,6 +160,8 @@ public:
int cursorWidth() const { return m_cursorWidth; }
void setCursorWidth(int value) { m_cursorWidth = value; }
+ QTextCursor::MoveStyle cursorMoveStyle() const { return m_textLayout.cursorMoveStyle(); }
+ void setCursorMoveStyle(QTextCursor::MoveStyle style) { m_textLayout.setCursorMoveStyle(style); }
void moveCursor(int pos, bool mark = false);
void cursorForward(bool mark, int steps)
@@ -167,10 +169,12 @@ public:
int c = m_cursor;
if (steps > 0) {
while (steps--)
- c = m_textLayout.nextCursorPosition(c);
+ c = cursorMoveStyle() == QTextCursor::Visual ? m_textLayout.rightCursorPosition(c)
+ : m_textLayout.nextCursorPosition(c);
} else if (steps < 0) {
while (steps++)
- c = m_textLayout.previousCursorPosition(c);
+ c = cursorMoveStyle() == QTextCursor::Visual ? m_textLayout.leftCursorPosition(c)
+ : m_textLayout.previousCursorPosition(c);
}
moveCursor(c, mark);
}
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index 07bd273..43c3f52 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -1112,6 +1112,34 @@ void QLineEdit::setDragEnabled(bool b)
/*!
+ \property QLineEdit::cursorMoveStyle
+ \brief the movement style of cursor in this line edit
+ \since 4.8
+
+ When this property is set to QTextCursor::Visual, the line edit will use visual
+ movement style. Pressing the left arrow key will always cause the cursor to move
+ left, regardless of the text's writing direction. The same behavior applies to
+ right arrow key.
+
+ When the property is QTextCursor::Logical (the default), within a LTR text block,
+ increase cursor position when pressing left arrow key, decrease cursor position
+ when pressing the right arrow key. If the text block is right to left, the opposite
+ behavior applies.
+*/
+
+QTextCursor::MoveStyle QLineEdit::cursorMoveStyle() const
+{
+ Q_D(const QLineEdit);
+ return d->control->cursorMoveStyle();
+}
+
+void QLineEdit::setCursorMoveStyle(QTextCursor::MoveStyle style)
+{
+ Q_D(QLineEdit);
+ d->control->setCursorMoveStyle(style);
+}
+
+/*!
\property QLineEdit::acceptableInput
\brief whether the input satisfies the inputMask and the
validator.
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index 636cee7..73a736c 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -43,6 +43,7 @@
#define QLINEEDIT_H
#include <QtGui/qframe.h>
+#include <QtGui/qtextcursor.h>
#include <QtCore/qstring.h>
#include <QtCore/qmargins.h>
@@ -158,6 +159,9 @@ public:
void setDragEnabled(bool b);
bool dragEnabled() const;
+ void setCursorMoveStyle(QTextCursor::MoveStyle style);
+ QTextCursor::MoveStyle cursorMoveStyle() const;
+
QString inputMask() const;
void setInputMask(const QString &inputMask);
bool hasAcceptableInput() const;
diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp
index 23ac613..03716d4 100644
--- a/src/gui/widgets/qlineedit_p.cpp
+++ b/src/gui/widgets/qlineedit_p.cpp
@@ -153,6 +153,7 @@ void QLineEditPrivate::init(const QString& txt)
{
Q_Q(QLineEdit);
control = new QLineControl(txt);
+ control->setParent(q);
control->setFont(q->font());
QObject::connect(control, SIGNAL(textChanged(QString)),
q, SIGNAL(textChanged(QString)));
diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h
index 32f6077..3169776 100644
--- a/src/gui/widgets/qlineedit_p.h
+++ b/src/gui/widgets/qlineedit_p.h
@@ -84,7 +84,6 @@ public:
~QLineEditPrivate()
{
- delete control;
}
QLineControl *control;
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index b12e5c5..b0ea00f 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -228,6 +228,12 @@ QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
void QMenuPrivate::updateActionRects() const
{
Q_Q(const QMenu);
+ updateActionRects(popupGeometry(q));
+}
+
+void QMenuPrivate::updateActionRects(const QRect &screen) const
+{
+ Q_Q(const QMenu);
if (!itemsDirty)
return;
@@ -237,20 +243,10 @@ void QMenuPrivate::updateActionRects() const
actionRects.resize(actions.count());
actionRects.fill(QRect());
- //let's try to get the last visible action
- int lastVisibleAction = actions.count() - 1;
- for(;lastVisibleAction >= 0; --lastVisibleAction) {
- const QAction *action = actions.at(lastVisibleAction);
- if (action->isVisible()) {
- //removing trailing separators
- if (action->isSeparator() && collapsibleSeparators)
- continue;
- break;
- }
- }
+ int lastVisibleAction = getLastVisibleAction();
int max_column_width = 0,
- dh = popupGeometry(q).height(),
+ dh = screen.height(),
y = 0;
QStyle *style = q->style();
QStyleOption opt;
@@ -351,7 +347,6 @@ void QMenuPrivate::updateActionRects() const
const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin));
max_column_width = qMax(min_column_width, max_column_width);
-
//calculate position
const int base_y = vmargin + fw + topmargin +
(scroll ? scroll->scrollOffset : 0) +
@@ -382,6 +377,34 @@ void QMenuPrivate::updateActionRects() const
itemsDirty = 0;
}
+QSize QMenuPrivate::adjustMenuSizeForScreen(const QRect &screen)
+{
+ Q_Q(QMenu);
+ QSize ret = screen.size();
+ itemsDirty = true;
+ updateActionRects(screen);
+ const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
+ ret.setWidth(actionRects.at(getLastVisibleAction()).right() + fw);
+ return ret;
+}
+
+int QMenuPrivate::getLastVisibleAction() const
+{
+ //let's try to get the last visible action
+ int lastVisibleAction = actions.count() - 1;
+ for (;lastVisibleAction >= 0; --lastVisibleAction) {
+ const QAction *action = actions.at(lastVisibleAction);
+ if (action->isVisible()) {
+ //removing trailing separators
+ if (action->isSeparator() && collapsibleSeparators)
+ continue;
+ break;
+ }
+ }
+ return lastVisibleAction;
+}
+
+
QRect QMenuPrivate::actionRect(QAction *act) const
{
int index = actions.indexOf(act);
@@ -1813,9 +1836,20 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
else
#endif
screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
-
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+
+ // if the screens have very different geometries and the menu is too big, we have to recalculate
+ if (size.height() > screen.height() || size.width() > screen.width()) {
+ size = d->adjustMenuSizeForScreen(screen);
+ adjustToDesktop = true;
+ }
+ // Layout is not right, we might be able to save horizontal space
+ if (d->ncols >1 && size.height() < screen.height()) {
+ size = d->adjustMenuSizeForScreen(screen);
+ adjustToDesktop = true;
+ }
+
#ifdef QT_KEYPAD_NAVIGATION
if (!atAction && QApplication::keypadNavigationEnabled()) {
// Try to have one item activated
@@ -1909,6 +1943,27 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
}
}
+ const int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this);
+ const QSize menuSize(sizeHint());
+ QMenu *caused = qobject_cast<QMenu*>(d_func()->causedPopup.widget);
+ if (caused && caused->geometry().width() + menuSize.width() + subMenuOffset < screen.width()) {
+ QRect parentActionRect(caused->d_func()->actionRect(caused->d_func()->currentAction));
+ const QPoint actionTopLeft = caused->mapToGlobal(parentActionRect.topLeft());
+ parentActionRect.moveTopLeft(actionTopLeft);
+ if (isRightToLeft()) {
+ if ((pos.x() + menuSize.width() > parentActionRect.left() - subMenuOffset)
+ && (pos.x() < parentActionRect.right()))
+ {
+ pos.rx() = parentActionRect.right();
+ }
+ } else {
+ if ((pos.x() < parentActionRect.right() + subMenuOffset)
+ && (pos.x() + menuSize.width() > parentActionRect.left()))
+ {
+ pos.rx() = parentActionRect.left() - menuSize.width();
+ }
+ }
+ }
setGeometry(QRect(pos, size));
#ifndef QT_NO_EFFECTS
int hGuess = isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
@@ -2941,28 +2996,8 @@ void QMenu::internalDelayedPopup()
const QRect actionRect(d->actionRect(d->currentAction));
const QSize menuSize(d->activeMenu->sizeHint());
const QPoint rightPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
- const QPoint leftPos(mapToGlobal(QPoint(actionRect.left() - subMenuOffset - menuSize.width(), actionRect.top())));
QPoint pos(rightPos);
- QMenu *caused = qobject_cast<QMenu*>(d->activeMenu->d_func()->causedPopup.widget);
-
- const QRect availGeometry(d->popupGeometry(caused));
- if (isRightToLeft()) {
- pos = leftPos;
- if ((caused && caused->x() < x()) || pos.x() < availGeometry.left()) {
- if(rightPos.x() + menuSize.width() < availGeometry.right())
- pos = rightPos;
- else
- pos.rx() = availGeometry.left();
- }
- } else {
- if ((caused && caused->x() > x()) || pos.x() + menuSize.width() > availGeometry.right()) {
- if(leftPos.x() < availGeometry.left())
- pos.rx() = availGeometry.right() - menuSize.width();
- else
- pos = leftPos;
- }
- }
//calc sloppy focus buffer
if (style()->styleHint(QStyle::SH_Menu_SloppySubMenus, 0, this)) {
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index b6efde3..005ce1d 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -194,10 +194,13 @@ public:
mutable QVector<QRect> actionRects;
mutable QHash<QAction *, QWidget *> widgetItems;
void updateActionRects() const;
+ void updateActionRects(const QRect &screen) const;
QRect popupGeometry(const QWidget *widget) const;
QRect popupGeometry(int screen = -1) const;
mutable uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
+ QSize adjustMenuSizeForScreen(const QRect & screen);
+ int getLastVisibleAction() const;
bool activationRecursionGuard;
@@ -296,7 +299,6 @@ public:
void updateLayoutDirection();
-
//menu fading/scrolling effects
bool doChildEffects;
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 7435691..51c4ccb 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -483,6 +483,7 @@ int QPlainTextEditPrivate::verticalOffset(int topBlock, int topLine) const
QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
Q_ASSERT(documentLayout);
QRectF r = documentLayout->blockBoundingRect(currentBlock);
+ Q_UNUSED(r);
QTextLayout *layout = currentBlock.layout();
if (layout && topLine <= layout->lineCount()) {
QTextLine line = layout->lineAt(topLine - 1);
@@ -648,6 +649,11 @@ void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx)
}
control->topBlock = blockNumber;
topLine = lineNumber;
+
+ bool vbarSignalsBlocked = vbar->blockSignals(true);
+ vbar->setValue(block.firstLineNumber() + lineNumber);
+ vbar->blockSignals(vbarSignalsBlocked);
+
if (dx || dy)
viewport->scroll(q->isRightToLeft() ? -dx : dx, dy);
else
diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp
index ff924bf..8df436f 100644
--- a/src/gui/widgets/qtextedit.cpp
+++ b/src/gui/widgets/qtextedit.cpp
@@ -2614,7 +2614,6 @@ Qt::TextFormat QTextEdit::textFormat() const
void QTextEdit::append(const QString &text)
{
Q_D(QTextEdit);
- QTextBlock lastBlock = d->control->document()->lastBlock();
const bool atBottom = isReadOnly() ? d->verticalOffset() >= d->vbar->maximum() :
d->control->textCursor().atEnd();
d->control->append(text);
diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp
index bf50d07..13ef13b 100644
--- a/src/gui/widgets/qworkspace.cpp
+++ b/src/gui/widgets/qworkspace.cpp
@@ -1239,7 +1239,6 @@ QWidget * QWorkspace::addWindow(QWidget *w, Qt::WindowFlags flags)
int x = w->x();
int y = w->y();
bool hasPos = w->testAttribute(Qt::WA_Moved);
- QSize s = w->size().expandedTo(qSmartMinSize(w));
if (!hasSize && w->sizeHint().isValid())
w->adjustSize();
diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp
index 3767b95..77ecf70 100644
--- a/src/multimedia/audio/qaudioinput.cpp
+++ b/src/multimedia/audio/qaudioinput.cpp
@@ -202,7 +202,13 @@ QAudioInput::~QAudioInput()
/*!
Uses the \a device as the QIODevice to transfer data.
Passing a QIODevice allows the data to be transferred without any extra code.
- All that is required is to open the QIODevice.
+ All that is required is to open the QIODevice. QAudioInput does not take
+ ownership of \a device.
+
+ The QAudioInput will write to the device when new data is available. You can
+ subclass QIODevice and reimplement \l{QIODevice::}{writeData()} if you wish to
+ access the data. If you simply want to save data to a file, you can pass a
+ QFile to this function.
If able to successfully get audio data from the systems audio device the
state() is set to either QAudio::ActiveState or QAudio::IdleState,
@@ -222,9 +228,12 @@ void QAudioInput::start(QIODevice* device)
}
/*!
- Returns a pointer to the QIODevice being used to handle the data
- transfer. This QIODevice can be used to read() audio data
- directly.
+
+ Returns a pointer to a new QIODevice that will be used to handle the data transfer.
+ This QIODevice can be used to \l{QIODevice::}{read()} audio data directly.
+ You will typically connect to the \l{QIODevice::}{readyRead()} signal, and
+ read from the device in the slot you connect to. QAudioInput keeps ownership
+ of the device.
If able to access the systems audio device the state() is set to
QAudio::IdleState, error() is set to QAudio::NoError
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 478bef0..a471559 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -117,7 +117,6 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
void QHttpNetworkConnectionPrivate::init()
{
- Q_Q(QHttpNetworkConnection);
for (int i = 0; i < channelCount; i++) {
channels[i].setConnection(this->q_func());
channels[i].ssl = encrypt;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 7a17a7f..0364dac 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -51,6 +51,7 @@
#include "private/qnetworkaccesscache_p.h"
#include "private/qnoncontiguousbytedevice_p.h"
+#ifndef QT_NO_HTTP
QT_BEGIN_NAMESPACE
@@ -137,6 +138,8 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
result = key.toEncoded();
}
}
+#else
+ Q_UNUSED(proxy)
#endif
return "http-connection:" + result;
@@ -247,11 +250,13 @@ void QHttpThreadDelegate::startRequest()
QUrl urlCopy = httpRequest.url();
urlCopy.setPort(urlCopy.port(ssl ? 443 : 80));
+#ifndef QT_NO_NETWORKPROXY
if (transparentProxy.type() != QNetworkProxy::NoProxy)
cacheKey = makeCacheKey(urlCopy, &transparentProxy);
else if (cacheProxy.type() != QNetworkProxy::NoProxy)
cacheKey = makeCacheKey(urlCopy, &cacheProxy);
else
+#endif
cacheKey = makeCacheKey(urlCopy, 0);
@@ -267,7 +272,7 @@ void QHttpThreadDelegate::startRequest()
#endif
#ifndef QT_NO_OPENSSL
// Set the QSslConfiguration from this QNetworkRequest.
- if (ssl) {
+ if (ssl && incomingSslConfiguration != QSslConfiguration::defaultConfiguration()) {
httpConnection->setSslConfiguration(incomingSslConfiguration);
}
#endif
@@ -572,4 +577,6 @@ void QHttpThreadDelegate::synchronousProxyAuthenticationRequiredSlot(const QNet
#endif
+#endif // QT_NO_HTTP
+
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 752bc09..c0f2077 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -68,6 +68,8 @@
#include "private/qnoncontiguousbytedevice_p.h"
#include "qnetworkaccessauthenticationmanager_p.h"
+#ifndef QT_NO_HTTP
+
QT_BEGIN_NAMESPACE
class QAuthenticator;
@@ -285,4 +287,6 @@ signals:
QT_END_NAMESPACE
+#endif // QT_NO_HTTP
+
#endif // QHTTPTHREADDELEGATE_H
diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp
index 13f4cd9..c585848 100644
--- a/src/network/access/qnetworkaccesscachebackend.cpp
+++ b/src/network/access/qnetworkaccesscachebackend.cpp
@@ -66,6 +66,7 @@ void QNetworkAccessCacheBackend::open()
QString msg = QCoreApplication::translate("QNetworkAccessCacheBackend", "Error opening %1")
.arg(this->url().toString());
error(QNetworkReply::ContentNotFoundError, msg);
+ } else {
setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
}
finished();
@@ -85,14 +86,18 @@ bool QNetworkAccessCacheBackend::sendCacheContents()
QNetworkCacheMetaData::AttributesMap attributes = item.attributes();
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, attributes.value(QNetworkRequest::HttpStatusCodeAttribute));
setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
- setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true);
// set the raw headers
QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders();
QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
end = rawHeaders.constEnd();
- for ( ; it != end; ++it)
+ for ( ; it != end; ++it) {
+ if (it->first.toLower() == "cache-control" &&
+ it->second.toLower().contains("must-revalidate")) {
+ return false;
+ }
setRawHeader(it->first, it->second);
+ }
// handle a possible redirect
QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute);
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 9de5d84..a45c2de 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -262,13 +262,11 @@ bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &http
if (lastModified.isValid())
httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified));
- if (CacheLoadControlAttribute == QNetworkRequest::PreferNetwork) {
- it = cacheHeaders.findRawHeader("Cache-Control");
- if (it != cacheHeaders.rawHeaders.constEnd()) {
- QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
- if (cacheControl.contains("must-revalidate"))
- return false;
- }
+ it = cacheHeaders.findRawHeader("Cache-Control");
+ if (it != cacheHeaders.rawHeaders.constEnd()) {
+ QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
+ if (cacheControl.contains("must-revalidate"))
+ return false;
}
QDateTime currentDateTime = QDateTime::currentDateTime();
@@ -1036,14 +1034,11 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo
if (hop_by_hop)
continue;
- // for 4.6.0, we were planning to not store the date header in the
- // cached resource; through that we planned to reduce the number
- // of writes to disk when using a QNetworkDiskCache (i.e. don't
- // write to disk when only the date changes).
- // However, without the date we cannot calculate the age of the page
- // anymore.
- //if (header == "date")
- //continue;
+ // we are currently not using the date header to determine the expiration time of a page,
+ // but only the "Expires", "max-age" and "s-maxage" headers, see
+ // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()").
+ if (header == "date")
+ continue;
// Don't store Warning 1xx headers
if (header == "warning") {
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index ba0fe7b..55d6a7c 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -861,7 +861,7 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess
device will be uploaded to the server; in that case, data must be open for
reading and must remain valid until the finished() signal is emitted for this reply.
- \note This feature is currently available for HTTP only.
+ \note This feature is currently available for HTTP(S) only.
\sa get(), post(), put(), deleteResource()
*/
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index c2a6925..eec8507 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -395,8 +395,8 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
// qdtext = <any TEXT except <">>
// quoted-pair = "\" CHAR
- // If its NAME=VALUE, retain the value as is
- // refer to ttp://bugreports.qt.nokia.com/browse/QTBUG-17746
+ // If it is NAME=VALUE, retain the value as is
+ // refer to http://bugreports.qt.nokia.com/browse/QTBUG-17746
if (isNameValue)
second += '"';
++i;
@@ -432,7 +432,9 @@ static QPair<QByteArray, QByteArray> nextField(const QByteArray &text, int &posi
position = i;
for ( ; i < length; ++i) {
register char c = text.at(i);
- if (c == ',' || c == ';' || isLWS(c))
+ // for name value pairs, we want to parse until reaching the next ';'
+ // and not break when reaching a space char
+ if (c == ',' || c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
break;
}
@@ -487,7 +489,6 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
result += '=';
if ((d->value.contains(';') ||
d->value.contains(',') ||
- d->value.contains(' ') ||
d->value.contains('"')) &&
(!d->value.startsWith('"') &&
!d->value.endsWith('"'))) {
@@ -737,7 +738,7 @@ static QDateTime parseDateString(const QByteArray &dateString)
// 4 digit Year
if (isNum
&& year == -1
- && dateString.length() >= at + 3) {
+ && dateString.length() > at + 3) {
if (isNumber(dateString[at + 1])
&& isNumber(dateString[at + 2])
&& isNumber(dateString[at + 3])) {
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 665ee28..338969a 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -524,7 +524,7 @@ void QNetworkRequest::setAttribute(Attribute code, const QVariant &value)
QSslConfiguration QNetworkRequest::sslConfiguration() const
{
if (!d->sslConfiguration)
- d->sslConfiguration = new QSslConfiguration;
+ d->sslConfiguration = new QSslConfiguration(QSslConfiguration::defaultConfiguration());
return *d->sslConfiguration;
}
diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp
index 9e1eaea..10fe74c 100644
--- a/src/network/bearer/qnetworkconfigmanager.cpp
+++ b/src/network/bearer/qnetworkconfigmanager.cpp
@@ -197,6 +197,9 @@ QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate()
/*!
Constructs a QNetworkConfigurationManager with the given \a parent.
+
+ Note that to ensure a valid list of current configurations immediately available, updating
+ is done during construction which causes some delay.
*/
QNetworkConfigurationManager::QNetworkConfigurationManager(QObject *parent)
: QObject(parent)
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index c108ad3..e9b6703 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -60,7 +60,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
#endif
QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
- : QObject(), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
+ : QObject(), pollTimer(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
{
qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
@@ -442,9 +442,19 @@ void QNetworkConfigurationManagerPrivate::startPolling()
{
QMutexLocker locker(&mutex);
+ if(!pollTimer) {
+ pollTimer = new QTimer(this);
+ pollTimer->setInterval(10000);
+ pollTimer->setSingleShot(true);
+ connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines()));
+ }
+
+ if(pollTimer->isActive())
+ return;
+
foreach (QBearerEngine *engine, sessionEngines) {
if (engine->requiresPolling() && (forcedPolling || engine->configurationsInUse())) {
- QTimer::singleShot(10000, this, SLOT(pollEngines()));
+ pollTimer->start();
break;
}
}
diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h
index 81f38c5..abc4b9b 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.h
+++ b/src/network/bearer/qnetworkconfigmanager_p.h
@@ -64,6 +64,7 @@
QT_BEGIN_NAMESPACE
class QBearerEngine;
+class QTimer;
class Q_NETWORK_EXPORT QNetworkConfigurationManagerPrivate : public QObject
{
@@ -107,6 +108,7 @@ private Q_SLOTS:
private:
void startPolling();
+ QTimer *pollTimer;
private:
mutable QMutex mutex;
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index a16d4ca..c86f510 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -288,7 +288,7 @@ QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointer<QNetwor
#ifndef Q_OS_SYMBIAN
// This function has a special implementation for symbian right now in qhostinfo_symbian.cpp but not on other OS.
-QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetworkSession> networkSession)
+QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetworkSession>)
{
return QHostInfoAgent::fromName(hostName);
}
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 22729a8..fc0bb85 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -1881,7 +1881,7 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
}
Q_ASSERT(d->socketEngine);
- forever {
+ do {
bool readyToRead = false;
bool readyToWrite = false;
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
@@ -1908,7 +1908,7 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
if (state() != ConnectedState)
return false;
- }
+ } while (qt_timeout_value(msecs, stopWatch.elapsed()) > 0);
return false;
}
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 14f5af8..185f574 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -579,10 +579,7 @@ bool QLocalSocket::waitForDisconnected(int msecs)
bool QLocalSocket::isValid() const
{
Q_D(const QLocalSocket);
- if (d->handle == INVALID_HANDLE_VALUE)
- return false;
-
- return PeekNamedPipe(d->handle, NULL, 0, NULL, NULL, NULL);
+ return d->handle != INVALID_HANDLE_VALUE;
}
bool QLocalSocket::waitForReadyRead(int msecs)
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index c8dbaed..ab4d7f1 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -164,7 +164,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->privateKey == other.d->privateKey &&
d->sessionCipher == other.d->sessionCipher &&
d->ciphers == other.d->ciphers &&
- d->caCertificates == d->caCertificates &&
+ d->caCertificates == other.d->caCertificates &&
d->protocol == other.d->protocol &&
d->peerVerifyMode == other.d->peerVerifyMode &&
d->peerVerifyDepth == other.d->peerVerifyDepth;
@@ -233,7 +233,7 @@ void QSslConfiguration::setProtocol(QSsl::SslProtocol protocol)
client), and whether it should require that this certificate is valid.
The default mode is AutoVerifyPeer, which tells QSslSocket to use
- VerifyPeer for clients, QueryPeer for clients.
+ VerifyPeer for clients, QueryPeer for servers.
\sa setPeerVerifyMode()
*/
@@ -249,7 +249,7 @@ QSslSocket::PeerVerifyMode QSslConfiguration::peerVerifyMode() const
client), and whether it should require that this certificate is valid.
The default mode is AutoVerifyPeer, which tells QSslSocket to use
- VerifyPeer for clients, QueryPeer for clients.
+ VerifyPeer for clients, QueryPeer for servers.
\sa peerVerifyMode()
*/
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index 8068aa8..207ab3d 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -495,6 +495,8 @@ GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
"fmp",
"fmp2_m_radius2",
"inverse_2_fmp2_m_radius2",
+ "sqrfr",
+ "bradius",
"invertedTextureSize",
"brushTransform",
"brushTexture",
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
index 7cc9dc3..bf2fe42 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -442,6 +442,8 @@ public:
Fmp,
Fmp2MRadius2,
Inverse2Fmp2MRadius2,
+ SqrFr,
+ BRadius,
InvertedTextureSize,
BrushTransform,
BrushTexture,
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index fc8b9ef..9362c58 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -241,6 +241,7 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp mat3 brushTransform; \n\
uniform highp vec2 fmp; \n\
+ uniform highp vec3 bradius; \n\
varying highp float b; \n\
varying highp vec2 A; \n\
void setPosition(void) \n\
@@ -253,7 +254,7 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
A = hTexCoords.xy * invertedHTexCoordsZ; \n\
- b = 2.0 * dot(A, fmp); \n\
+ b = bradius.x + 2.0 * dot(A, fmp); \n\
}\n";
static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
@@ -263,13 +264,22 @@ static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\
uniform sampler2D brushTexture; \n\
uniform highp float fmp2_m_radius2; \n\
uniform highp float inverse_2_fmp2_m_radius2; \n\
+ uniform highp float sqrfr; \n\
varying highp float b; \n\
varying highp vec2 A; \n\
+ uniform highp vec3 bradius; \n\
lowp vec4 srcPixel() \n\
{ \n\
- highp float c = -dot(A, A); \n\
- highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \n\
- return texture2D(brushTexture, val); \n\
+ highp float c = sqrfr-dot(A, A); \n\
+ highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\
+ lowp vec4 result = vec4(0.0); \n\
+ if (det >= 0.0) { \n\
+ highp float detSqrt = sqrt(det); \n\
+ highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
+ if (bradius.y + w * bradius.z >= 0.0) \n\
+ result = texture2D(brushTexture, vec2(w, 0.5)); \n\
+ } \n\
+ return result; \n\
}\n";
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 18c684f..38bd58d 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -301,7 +301,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient());
QPointF realCenter = g->center();
QPointF realFocal = g->focalPoint();
- qreal realRadius = g->radius();
+ qreal realRadius = g->centerRadius() - g->focalRadius();
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
@@ -311,6 +311,12 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2),
GLfloat(1.0 / (2.0*fmp2_m_radius2)));
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::SqrFr),
+ GLfloat(g->focalRadius() * g->focalRadius()));
+ shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BRadius),
+ GLfloat(2 * (g->centerRadius() - g->focalRadius()) * g->focalRadius()),
+ g->focalRadius(),
+ g->centerRadius() - g->focalRadius());
QVector2D halfViewportSize(width*0.5, height*0.5);
shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
@@ -1548,6 +1554,14 @@ namespace {
}
+#if defined(Q_WS_WIN)
+static bool fontSmoothingApproximately(qreal target)
+{
+ extern Q_GUI_EXPORT qreal qt_fontsmoothing_gamma; // qapplication_win.cpp
+ return (qAbs(qt_fontsmoothing_gamma - target) < 0.2);
+}
+#endif
+
// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO
void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType,
@@ -1786,7 +1800,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
prepareForDraw(false); // Text always causes src pixels to be transparent
}
- //### TODO: Gamma correction
QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
@@ -1809,12 +1822,31 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp
}
}
+ bool srgbFrameBufferEnabled = false;
+ if (ctx->d_ptr->extension_flags & QGLExtensions::SRGBFrameBuffer) {
+#if defined(Q_WS_MAC)
+ if (glyphType == QFontEngineGlyphCache::Raster_RGBMask)
+#elif defined(Q_WS_WIN)
+ if (glyphType != QFontEngineGlyphCache::Raster_RGBMask || fontSmoothingApproximately(2.1))
+#else
+ if (false)
+#endif
+ {
+ glEnable(FRAMEBUFFER_SRGB_EXT);
+ srgbFrameBufferEnabled = true;
+ }
+ }
+
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else
glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
#endif
+
+ if (srgbFrameBufferEnabled)
+ glDisable(FRAMEBUFFER_SRGB_EXT);
+
}
void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
@@ -1986,7 +2018,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
#if !defined(QT_OPENGL_ES_2)
#if defined(Q_WS_WIN)
- if (qt_cleartype_enabled)
+ if (qt_cleartype_enabled
+ && (fontSmoothingApproximately(1.0) || fontSmoothingApproximately(2.1)))
#endif
#if defined(Q_WS_MAC)
if (qt_applefontsmoothing_enabled)
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 5774bef..e7c1c44 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -120,7 +120,7 @@ x11 {
LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
}
-mac {
+mac:!qpa {
OBJECTIVE_SOURCES += qgl_mac.mm \
qglpixelbuffer_mac.mm
LIBS_PRIVATE += -framework AppKit -framework Carbon
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index b3b459d..099cc00 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1423,10 +1423,6 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
}
}
-#ifdef Q_WS_QPA
- hasOpenGL(); // ### I have no idea why this is needed here, but it makes things work for testlite
-#endif
-
QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
if (currentCtx) {
@@ -5494,6 +5490,13 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions()
if (extensions.match("GL_EXT_bgra"))
glExtensions |= BGRATextureFormat;
+ {
+ GLboolean srgbCapableFramebuffers;
+ glGetBooleanv(FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers);
+ if (srgbCapableFramebuffers)
+ glExtensions |= SRGBFrameBuffer;
+ }
+
return glExtensions;
}
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index ff73d88..c57995d 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -61,21 +61,29 @@ QT_BEGIN_HEADER
#if defined(Q_WS_MAC)
# include <OpenGL/gl.h>
#elif defined(QT_OPENGL_ES_1)
-# include <GLES/gl.h>
-#ifndef GL_DOUBLE
-# define GL_DOUBLE GL_FLOAT
-#endif
-#ifndef GLdouble
+# if defined(Q_OS_MAC)
+# include <OpenGLES/ES1/gl.h>
+# else
+# include <GLES/gl.h>
+# endif
+# ifndef GL_DOUBLE
+# define GL_DOUBLE GL_FLOAT
+# endif
+# ifndef GLdouble
typedef GLfloat GLdouble;
-#endif
+# endif
#elif defined(QT_OPENGL_ES_2)
-# include <GLES2/gl2.h>
-#ifndef GL_DOUBLE
-# define GL_DOUBLE GL_FLOAT
-#endif
-#ifndef GLdouble
+# if defined(Q_OS_MAC)
+# include <OpenGLES/ES2/gl.h>
+# else
+# include <GLES2/gl2.h>
+# endif
+# ifndef GL_DOUBLE
+# define GL_DOUBLE GL_FLOAT
+# endif
+# ifndef GLdouble
typedef GLfloat GLdouble;
-#endif
+# endif
#else
# include <GL/gl.h>
#endif
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 50d13c9..ac54e2f 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -288,7 +288,8 @@ public:
PVRTCTextureCompression = 0x00020000,
FragmentShader = 0x00040000,
ElementIndexUint = 0x00080000,
- Depth24 = 0x00100000
+ Depth24 = 0x00100000,
+ SRGBFrameBuffer = 0x00200000
};
Q_DECLARE_FLAGS(Extensions, Extension)
diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp
index 4bac1fb..994344c 100644
--- a/src/opengl/qgl_qpa.cpp
+++ b/src/opengl/qgl_qpa.cpp
@@ -127,7 +127,8 @@ void QGLContextPrivate::setupSharing() {
bool QGLFormat::hasOpenGL()
{
- return QApplicationPrivate::platformIntegration()->hasOpenGL();
+ return QApplicationPrivate::platformIntegration()
+ ->hasCapability(QPlatformIntegration::OpenGL);
}
void qDeleteQGLContext(void *handle)
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 5755067..2ddfd35 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -105,10 +105,18 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
return;
}
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(X11->display, DefaultRootWindow(X11->display), vi->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
0, 0, 1, 1, 0,
vi->depth, InputOutput, vi->visual,
- 0, 0);
+ mask, &attr);
d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index 529c7a1..ac80ce8 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -477,6 +477,14 @@ struct QGLExtensionFuncs
// OpenGL constants
+#ifndef FRAMEBUFFER_SRGB_CAPABLE_EXT
+#define FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif
+
+#ifndef FRAMEBUFFER_SRGB_EXT
+#define FRAMEBUFFER_SRGB_EXT 0x8DB9
+#endif
+
#ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER 0x8892
#endif
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index 2c01ac4..5fa9f32 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -2119,6 +2119,7 @@ void QOpenGLPaintEnginePrivate::fillPath(const QPainterPath &path)
updateGLMatrix();
}
+extern bool qt_isExtendedRadialGradient(const QBrush &brush);
static inline bool needsEmulation(Qt::BrushStyle style)
{
@@ -2129,9 +2130,11 @@ static inline bool needsEmulation(Qt::BrushStyle style)
void QOpenGLPaintEnginePrivate::updateUseEmulation()
{
- use_emulation = !use_fragment_programs
- && ((has_pen && needsEmulation(pen_brush_style))
- || (has_brush && needsEmulation(brush_style)));
+ use_emulation = (!use_fragment_programs
+ && ((has_pen && needsEmulation(pen_brush_style))
+ || (has_brush && needsEmulation(brush_style))))
+ || (has_pen && qt_isExtendedRadialGradient(cpen.brush()))
+ || (has_brush && qt_isExtendedRadialGradient(cbrush));
}
void QOpenGLPaintEngine::updatePen(const QPen &pen)
@@ -4736,7 +4739,7 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
// qDebug() << "new context" << context << font_cache;
qt_context_cache.insert(context, font_cache);
if (context->isValid()) {
- if (context->device()->devType() == QInternal::Widget) {
+ if (context->device() && context->device()->devType() == QInternal::Widget) {
QWidget *widget = static_cast<QWidget *>(context->device());
connect(widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)));
}
@@ -4832,7 +4835,6 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
}
QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i]));
- glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
glyph_width = glyph_im.width();
Q_ASSERT(glyph_width >= 0);
// pad the glyph width to an even number
@@ -4855,15 +4857,21 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
#endif
if (!glyph_im.isNull()) {
-
int idx = 0;
uchar *tex_data = (uchar *) malloc(glyph_width*glyph_im.height()*2);
memset(tex_data, 0, glyph_width*glyph_im.height()*2);
+ bool is8BitGray = false;
+#ifdef Q_WS_QPA
+ if (glyph_im.format() == QImage::Format_Indexed8) {
+ is8BitGray = true;
+ }
+#endif
+ glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
for (int y=0; y<glyph_im.height(); ++y) {
uchar *s = (uchar *) glyph_im.scanLine(y);
for (int x=0; x<glyph_im.width(); ++x) {
- uchar alpha = qAlpha(glyph_im.color(*s));
+ uchar alpha = is8BitGray ? *s : qAlpha(glyph_im.color(*s));
tex_data[idx] = alpha;
tex_data[idx+1] = alpha;
++s;
@@ -5442,50 +5450,7 @@ void QOpenGLPaintEngine::transformChanged()
updateMatrix(state()->matrix);
}
-static QPainterPath painterPathFromVectorPath(const QVectorPath &path)
-{
- const qreal *points = path.points();
- const QPainterPath::ElementType *types = path.elements();
-
- QPainterPath p;
- if (types) {
- int id = 0;
- for (int i=0; i<path.elementCount(); ++i) {
- switch(types[i]) {
- case QPainterPath::MoveToElement:
- p.moveTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::LineToElement:
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::CurveToElement: {
- QPointF p1(points[id], points[id+1]);
- QPointF p2(points[id+2], points[id+3]);
- QPointF p3(points[id+4], points[id+5]);
- p.cubicTo(p1, p2, p3);
- id+=6;
- break;
- }
- case QPainterPath::CurveToDataElement:
- ;
- break;
- }
- }
- } else {
- p.moveTo(QPointF(points[0], points[1]));
- int id = 2;
- for (int i=1; i<path.elementCount(); ++i) {
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- }
- }
- if (path.hints() & QVectorPath::WindingFill)
- p.setFillRule(Qt::WindingFill);
-
- return p;
-}
+extern QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path);
void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
@@ -5494,11 +5459,11 @@ void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
if (brush.style() == Qt::NoBrush)
return;
- if (!d->use_fragment_programs && needsEmulation(brush.style())) {
+ if ((!d->use_fragment_programs && needsEmulation(brush.style())) || qt_isExtendedRadialGradient(brush)) {
QPainter *p = painter();
QBrush oldBrush = p->brush();
p->setBrush(brush);
- qt_draw_helper(p->d_ptr.data(), painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
+ qt_draw_helper(p->d_ptr.data(), qt_painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
p->setBrush(oldBrush);
return;
}
@@ -5515,7 +5480,7 @@ void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
drawRects(&r, 1);
updatePen(old_pen);
} else {
- d->fillPath(painterPathFromVectorPath(path));
+ d->fillPath(qt_painterPathFromVectorPath(path));
}
updateBrush(old_brush, state()->brushOrigin);
diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_poolgl.cpp
index 8310b42..041210d 100644
--- a/src/opengl/qpixmapdata_poolgl.cpp
+++ b/src/opengl/qpixmapdata_poolgl.cpp
@@ -65,19 +65,6 @@ QT_BEGIN_NAMESPACE
Q_OPENGL_EXPORT extern QGLWidget* qt_gl_share_widget();
-/*!
- \class QGLFramebufferObjectPool
- \since 4.6
-
- \brief The QGLFramebufferObject class provides a pool of framebuffer
- objects for offscreen rendering purposes.
-
- When requesting an FBO of a given size and format, an FBO of the same
- format and a size at least as big as the requested size will be returned.
-
- \internal
-*/
-
static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
{
return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 77f6103..49b3dc2 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -181,11 +181,12 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL)
//
// QGLWindowSurface
//
-#ifndef Q_WS_QPA
class QGLGlobalShareWidget
{
public:
- QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {}
+ QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {
+ created = true;
+ }
QGLWidget *shareWidget() {
if (!initializing && !widget && !cleanedUp) {
@@ -224,6 +225,7 @@ public:
}
static bool cleanedUp;
+ static bool created;
QGLPixmapData *firstPixmap;
int widgetRefCount;
@@ -234,6 +236,7 @@ private:
};
bool QGLGlobalShareWidget::cleanedUp = false;
+bool QGLGlobalShareWidget::created = false;
static void qt_cleanup_gl_share_widget();
Q_GLOBAL_STATIC_WITH_INITIALIZER(QGLGlobalShareWidget, _qt_gl_share_widget,
@@ -243,7 +246,8 @@ Q_GLOBAL_STATIC_WITH_INITIALIZER(QGLGlobalShareWidget, _qt_gl_share_widget,
static void qt_cleanup_gl_share_widget()
{
- _qt_gl_share_widget()->cleanup();
+ if (QGLGlobalShareWidget::created)
+ _qt_gl_share_widget()->cleanup();
}
QGLWidget* qt_gl_share_widget()
@@ -255,24 +259,16 @@ QGLWidget* qt_gl_share_widget()
void qt_destroy_gl_share_widget()
{
- _qt_gl_share_widget()->destroy();
+ if (QGLGlobalShareWidget::created)
+ _qt_gl_share_widget()->destroy();
}
-#endif//Q_WS_QPA
const QGLContext *qt_gl_share_context()
{
-#ifdef Q_WS_QPA
- //make it possible to have an assesor to defaultSharedGLContext.
- const QPlatformGLContext *platformContext = QPlatformGLContext::defaultSharedContext();
- if (!platformContext)
- qDebug() << "Please implement a defaultSharedContext for your platformplugin";
- return QGLContext::fromPlatformGLContext(const_cast<QPlatformGLContext *>(platformContext));
-#else
QGLWidget *widget = qt_gl_share_widget();
if (widget)
return widget->context();
return 0;
-#endif
}
#ifdef QGL_USE_TEXTURE_POOL
@@ -427,7 +423,7 @@ QGLWindowSurface::~QGLWindowSurface()
if (!qt_gl_share_widget()->context()->isSharing())
qt_destroy_gl_share_widget();
}
-#endif
+#endif // QGL_USE_TEXTURE_POOL
}
void QGLWindowSurface::deleted(QObject *object)
@@ -620,6 +616,17 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
if (!d_ptr->destructive_swap_buffers && !d_ptr->did_paint)
return;
+#ifdef Q_OS_SYMBIAN
+ if (window() != widget) {
+ // For performance reasons we don't support
+ // flushing native child widgets on Symbian.
+ // It breaks overlapping native child widget
+ // rendering in some cases but we prefer performance.
+ return;
+ }
+#endif
+
+
QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
Q_ASSERT(parent);
@@ -727,7 +734,6 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
} else {
glFlush();
}
-
return;
}
@@ -884,8 +890,22 @@ void QGLWindowSurface::updateGeometry() {
bool hijack(true);
QWidgetPrivate *wd = window()->d_func();
- if (wd->extraData() && wd->extraData()->glContext)
- hijack = false; // we already have gl context for widget
+ if (wd->extraData() && wd->extraData()->glContext) {
+#ifdef Q_OS_SYMBIAN // Symbian needs to recreate the context when native window size changes
+ if (d_ptr->size != geometry().size()) {
+ if (window() != qt_gl_share_widget())
+ --(_qt_gl_share_widget()->widgetRefCount);
+
+ delete wd->extraData()->glContext;
+ wd->extraData()->glContext = 0;
+ d_ptr->ctx = 0;
+ }
+ else
+#endif
+ {
+ hijack = false; // we already have gl context for widget
+ }
+ }
if (hijack)
hijackWindow(window());
@@ -906,35 +926,6 @@ void QGLWindowSurface::updateGeometry() {
d_ptr->size = surfSize;
-#ifdef Q_OS_SYMBIAN
- if (!hijack) { // Symbian needs to recreate EGL surface when native window size changes
- if (ctx->d_func()->eglSurface != EGL_NO_SURFACE) {
- eglDestroySurface(ctx->d_func()->eglContext->display(),
- ctx->d_func()->eglSurface);
- }
-
- ctx->d_func()->eglSurface = QEgl::createSurface(ctx->device(),
- ctx->d_func()->eglContext->config());
-
- eglGetError(); // Clear error state.
- if (!d_ptr->destructive_swap_buffers) {
- eglSurfaceAttrib(ctx->d_func()->eglContext->display(),
- ctx->d_func()->eglSurface,
- EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
-
- if (eglGetError() != EGL_SUCCESS)
- qWarning("QGLWindowSurface: could not enable preserved swap behaviour");
- } else {
- eglSurfaceAttrib(ctx->d_func()->eglContext->display(),
- ctx->d_func()->eglSurface,
- EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
-
- if (eglGetError() != EGL_SUCCESS)
- qWarning("QGLWindowSurface: could not enable destroyed swap behaviour");
- }
- }
-#endif
-
if (d_ptr->ctx) {
#ifndef QT_OPENGL_ES_2
if (d_ptr->destructive_swap_buffers)
diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h
index 4ad8339..c71ce59 100644
--- a/src/opengl/qwindowsurface_gl_p.h
+++ b/src/opengl/qwindowsurface_gl_p.h
@@ -66,12 +66,8 @@ class QRegion;
class QWidget;
struct QGLWindowSurfacePrivate;
-#ifdef Q_WS_QPA
-Q_OPENGL_EXPORT const QGLContext* qt_gl_share_context();
-#else
Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget();
Q_OPENGL_EXPORT void qt_destroy_gl_share_widget();
-#endif
class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice
{
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 3c2b5fd..68a6a0b 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -173,6 +173,9 @@ public:
bool forcePenChange; // Force a pen change, even if the same.
bool forceBrushChange; // Force a brush change, even if the same.
+ bool hasExtendedRadialGradientPen; // Current pen's brush is extended radial gradient.
+ bool hasExtendedRadialGradientBrush; // Current brush is extended radial gradient.
+
VGPaintType penType; // Type of the last pen that was set.
VGPaintType brushType; // Type of the last brush that was set.
@@ -275,6 +278,27 @@ public:
}
}
+ inline bool needsEmulation(const QBrush &brush) const
+ {
+ extern bool qt_isExtendedRadialGradient(const QBrush &brush);
+ return qt_isExtendedRadialGradient(brush);
+ }
+
+ inline bool needsEmulation() const
+ {
+ return hasExtendedRadialGradientPen || hasExtendedRadialGradientBrush;
+ }
+
+ inline bool needsPenEmulation() const
+ {
+ return hasExtendedRadialGradientPen;
+ }
+
+ inline bool needsBrushEmulation() const
+ {
+ return hasExtendedRadialGradientBrush;
+ }
+
// Set various modes, but only if different.
inline void setImageMode(VGImageMode mode);
inline void setRenderingQuality(VGRenderingQuality mode);
@@ -355,6 +379,10 @@ void QVGPaintEnginePrivate::init()
forcePenChange = true;
forceBrushChange = true;
+
+ hasExtendedRadialGradientPen = false;
+ hasExtendedRadialGradientBrush = false;
+
penType = (VGPaintType)0;
brushType = (VGPaintType)0;
@@ -1021,9 +1049,11 @@ static VGImage toVGImage
switch (img.format()) {
case QImage::Format_Mono:
img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ img.invertPixels();
format = VG_BW_1;
break;
case QImage::Format_MonoLSB:
+ img.invertPixels();
format = VG_BW_1;
break;
case QImage::Format_RGB32:
@@ -1528,12 +1558,18 @@ bool QVGPaintEngine::begin(QPaintDevice *pdev)
bool QVGPaintEngine::end()
{
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ vgSeti(VG_MASKING, VG_FALSE);
return true;
}
void QVGPaintEngine::draw(const QVectorPath &path)
{
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::draw(path);
+ return;
+ }
QVGPainterState *s = state();
VGPath vgpath = d->vectorPathToVGPath(path);
if (!path.hasWindingFill())
@@ -1543,9 +1579,19 @@ void QVGPaintEngine::draw(const QVectorPath &path)
vgDestroyPath(vgpath);
}
+extern QPainterPath qt_painterPathFromVectorPath(const QVectorPath &path);
+
void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QVGPaintEngine);
+ if (d->needsEmulation(brush)) {
+ QPainter *p = painter();
+ QBrush oldBrush = p->brush();
+ p->setBrush(brush);
+ qt_draw_helper(p->d_ptr.data(), qt_painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
+ p->setBrush(oldBrush);
+ return;
+ }
VGPath vgpath = d->vectorPathToVGPath(path);
if (!path.hasWindingFill())
d->fill(vgpath, brush, VG_EVEN_ODD);
@@ -1557,6 +1603,10 @@ void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
{
Q_D(QVGPaintEngine);
+ if (d->needsEmulation(pen.brush())) {
+ QPaintEngineEx::stroke(path, pen);
+ return;
+ }
VGPath vgpath = d->vectorPathToVGPath(path);
d->stroke(vgpath, pen);
vgDestroyPath(vgpath);
@@ -2360,12 +2410,17 @@ void QVGPaintEngine::penChanged()
{
Q_D(QVGPaintEngine);
d->dirty |= QPaintEngine::DirtyPen;
+
+ d->hasExtendedRadialGradientPen =
+ state()->pen.style() != Qt::NoPen && d->needsEmulation(state()->pen.brush());
}
void QVGPaintEngine::brushChanged()
{
Q_D(QVGPaintEngine);
d->dirty |= QPaintEngine::DirtyBrush;
+
+ d->hasExtendedRadialGradientPen = d->needsEmulation(state()->brush);
}
void QVGPaintEngine::brushOriginChanged()
@@ -2544,6 +2599,11 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
return;
}
+ if (d->needsEmulation(brush)) {
+ QPaintEngineEx::fillRect(rect, brush);
+ return;
+ }
+
#if !defined(QVG_NO_MODIFY_PATH)
VGfloat coords[8];
if (d->simpleTransform) {
@@ -2621,6 +2681,10 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color)
void QVGPaintEngine::drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, Qt::SizeMode mode)
{
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode);
+ return;
+ }
if (d->simpleTransform) {
QVGPainterState *s = state();
VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode);
@@ -2637,6 +2701,10 @@ void QVGPaintEngine::drawRects(const QRect *rects, int rectCount)
{
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawRects(rects, rectCount);
+ return;
+ }
QVGPainterState *s = state();
for (int i = 0; i < rectCount; ++i, ++rects) {
VGfloat coords[8];
@@ -2678,6 +2746,10 @@ void QVGPaintEngine::drawRects(const QRectF *rects, int rectCount)
{
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawRects(rects, rectCount);
+ return;
+ }
QVGPainterState *s = state();
for (int i = 0; i < rectCount; ++i, ++rects) {
VGfloat coords[8];
@@ -2716,6 +2788,10 @@ void QVGPaintEngine::drawLines(const QLine *lines, int lineCount)
{
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawLines(lines, lineCount);
+ return;
+ }
QVGPainterState *s = state();
for (int i = 0; i < lineCount; ++i, ++lines) {
VGfloat coords[4];
@@ -2744,6 +2820,10 @@ void QVGPaintEngine::drawLines(const QLineF *lines, int lineCount)
{
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawLines(lines, lineCount);
+ return;
+ }
QVGPainterState *s = state();
for (int i = 0; i < lineCount; ++i, ++lines) {
VGfloat coords[4];
@@ -2773,6 +2853,10 @@ void QVGPaintEngine::drawEllipse(const QRectF &r)
// Based on the description of vguEllipse() in the OpenVG specification.
// We don't use vguEllipse(), to avoid unnecessary library dependencies.
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawEllipse(r);
+ return;
+ }
if (d->simpleTransform) {
QVGPainterState *s = state();
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
@@ -2823,6 +2907,10 @@ void QVGPaintEngine::drawPath(const QPainterPath &path)
// Shortcut past the QPainterPath -> QVectorPath conversion,
// converting the QPainterPath directly into a VGPath.
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawPath(path);
+ return;
+ }
QVGPainterState *s = state();
VGPath vgpath = d->painterPathToVGPath(path);
if (path.fillRule() == Qt::OddEvenFill)
@@ -2837,6 +2925,11 @@ void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount)
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsPenEmulation()) {
+ QPaintEngineEx::drawPoints(points, pointCount);
+ return;
+ }
+
// Set up a new pen if necessary.
QPen pen = state()->pen;
if (pen.style() == Qt::NoPen)
@@ -2871,6 +2964,11 @@ void QVGPaintEngine::drawPoints(const QPoint *points, int pointCount)
#if !defined(QVG_NO_MODIFY_PATH)
Q_D(QVGPaintEngine);
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawPoints(points, pointCount);
+ return;
+ }
+
// Set up a new pen if necessary.
QPen pen = state()->pen;
if (pen.style() == Qt::NoPen)
@@ -2903,6 +3001,12 @@ void QVGPaintEngine::drawPoints(const QPoint *points, int pointCount)
void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
{
Q_D(QVGPaintEngine);
+
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawPolygon(points, pointCount, mode);
+ return;
+ }
+
QVGPainterState *s = state();
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
VG_PATH_DATATYPE_F,
@@ -2950,6 +3054,12 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD
void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
{
Q_D(QVGPaintEngine);
+
+ if (d->needsEmulation()) {
+ QPaintEngineEx::drawPolygon(points, pointCount, mode);
+ return;
+ }
+
QVGPainterState *s = state();
VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD,
VG_PATH_DATATYPE_F,
@@ -3186,6 +3296,19 @@ void qt_vg_drawVGImageStencil
bool QVGPaintEngine::canVgWritePixels(const QImage &image) const
{
Q_D(const QVGPaintEngine);
+
+ // qt_vg_image_to_vg_format returns VG_sARGB_8888 as
+ // fallback case if no matching VG format is found.
+ // If given image format is not Format_ARGB32 and returned
+ // format is VG_sARGB_8888, it means that no match was
+ // found. In that case vgWritePixels cannot be used.
+ // Also 1-bit formats cannot be used directly either.
+ if ((image.format() != QImage::Format_ARGB32
+ && qt_vg_image_to_vg_format(image.format()) == VG_sARGB_8888)
+ || image.depth() == 1) {
+ return false;
+ }
+
// vgWritePixels ignores masking, blending and xforms so we can only use it if
// ALL of the following conditions are true:
// - It is a simple translate, or a scale of -1 on the y-axis (inverted)
@@ -3596,6 +3719,11 @@ void QVGPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
return;
}
+ if (d->needsPenEmulation()) {
+ QPaintEngineEx::drawTextItem(p, textItem);
+ return;
+ }
+
// Get the glyphs and positions associated with the text item.
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
@@ -3741,6 +3869,8 @@ void QVGPaintEngine::beginNativePainting()
#if !defined(QVG_NO_DRAW_GLYPHS)
d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, d->pathTransform);
#endif
+ vgSeti(VG_SCISSORING, VG_FALSE);
+ vgSeti(VG_MASKING, VG_FALSE);
d->rawVG = true;
}
@@ -3801,6 +3931,7 @@ void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty)
if ((dirty & QPaintEngine::DirtyBrushOrigin) != 0)
brushOriginChanged();
d->fillRule = 0;
+ d->clearColor = QColor();
if ((dirty & QPaintEngine::DirtyOpacity) != 0)
opacityChanged();
if ((dirty & QPaintEngine::DirtyTransform) != 0)
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index ea93748..e52722d 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -378,7 +378,7 @@ VGImage QVGPixmapData::toVGImage()
QVGImagePool::instance()->useImage(this);
}
- if (!source.isNull() && recreate) {
+ if (!source.isNull() && (recreate || source.paintingActive())) {
source.beginDataAccess();
vgImageSubData
(vgImage,
diff --git a/src/openvg/qwindowsurface_vg.cpp b/src/openvg/qwindowsurface_vg.cpp
index eedfea5..dcc5d6a 100644
--- a/src/openvg/qwindowsurface_vg.cpp
+++ b/src/openvg/qwindowsurface_vg.cpp
@@ -78,6 +78,17 @@ QPaintDevice *QVGWindowSurface::paintDevice()
void QVGWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(offset);
+
+#ifdef Q_OS_SYMBIAN
+ if (window() != widget) {
+ // For performance reasons we don't support
+ // flushing native child widgets on Symbian.
+ // It breaks overlapping native child widget
+ // rendering in some cases but we prefer performance.
+ return;
+ }
+#endif
+
QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
d_ptr->endPaint(parent, region);
}
diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp
index 866453f..3205a11 100644
--- a/src/openvg/qwindowsurface_vgegl.cpp
+++ b/src/openvg/qwindowsurface_vgegl.cpp
@@ -269,19 +269,20 @@ static QEglContext *createContext(QPaintDevice *device)
configProps.setPixelFormat(QImage::Format_ARGB32); // XXX
configProps.setValue(EGL_ALPHA_MASK_SIZE, 1);
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
- EGL_VG_ALPHA_FORMAT_PRE_BIT);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT
+ | EGL_SWAP_BEHAVIOR_PRESERVED_BIT
+ | EGL_VG_ALPHA_FORMAT_PRE_BIT);
configProps.setRenderableType(QEgl::OpenVG);
if (!context->chooseConfig(configProps)) {
// Try again without the "pre" bit.
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
if (!context->chooseConfig(configProps)) {
delete context;
return 0;
}
}
#else
- configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
configProps.setRenderableType(QEgl::OpenVG);
if (!context->chooseConfig(configProps)) {
delete context;
diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/plugins/accessible/widgets/complexwidgets.cpp
index e638413..85be0b0 100644
--- a/src/plugins/accessible/widgets/complexwidgets.cpp
+++ b/src/plugins/accessible/widgets/complexwidgets.cpp
@@ -971,7 +971,11 @@ QString QAccessibleItemView::text(Text t, int child) const
return QAccessibleAbstractScrollArea::text(t, child);
QAccessibleItemRow item(itemView(), childIndex(child));
- return item.text(t, 1);
+ if (item.isValid()) {
+ return item.text(t, 1);
+ } else {
+ return QString();
+ }
} else {
return QAccessibleAbstractScrollArea::text(t, child);
}
diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
index 09b5015..4402932 100644
--- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
+++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp
@@ -401,9 +401,14 @@ int QAccessibleStackedWidget::childCount() const
int QAccessibleStackedWidget::indexOfChild(const QAccessibleInterface *child) const
{
- if (!child || (stackedWidget()->currentWidget() != child->object()))
+ if (!child)
return -1;
- return 1;
+
+ QWidget* widget = qobject_cast<QWidget*>(child->object());
+ int index = stackedWidget()->indexOf(widget);
+ if (index >= 0) // one based counting of children
+ return index + 1;
+ return -1;
}
int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const
@@ -413,9 +418,9 @@ int QAccessibleStackedWidget::navigate(RelationFlag relation, int entry, QAccess
QObject *targetObject = 0;
switch (relation) {
case Child:
- if (entry != 1)
+ if (entry < 1 || entry > stackedWidget()->count())
return -1;
- targetObject = stackedWidget()->currentWidget();
+ targetObject = stackedWidget()->widget(entry-1);
break;
default:
return QAccessibleWidgetEx::navigate(relation, entry, target);
@@ -1334,7 +1339,7 @@ QRect QAccessibleTextEdit::characterRect(int offset, CoordinateType coordType)
QRect r = edit->cursorRect(cursor);
if (cursor.movePosition(QTextCursor::NextCharacter)) {
- r.setWidth(edit->cursorRect(cursor).y() - r.y());
+ r.setWidth(edit->cursorRect(cursor).x() - r.x());
} else {
// we don't know the width of the character - maybe because we're at document end
// in that case, IAccessible2 tells us to return the width of a default character
@@ -1603,7 +1608,7 @@ void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QS
#ifndef QT_NO_MAINWINDOW
QAccessibleMainWindow::QAccessibleMainWindow(QWidget *widget)
- : QAccessibleWidgetEx(widget, Application) { }
+ : QAccessibleWidgetEx(widget, Window) { }
QVariant QAccessibleMainWindow::invokeMethodEx(QAccessible::Method /*method*/, int /*child*/, const QVariantList & /*params*/)
{
diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp
index 21d2d67..aa64630 100644
--- a/src/plugins/accessible/widgets/simplewidgets.cpp
+++ b/src/plugins/accessible/widgets/simplewidgets.cpp
@@ -131,7 +131,7 @@ QString QAccessibleButton::actionText(int action, Text text, int child) const
/*! \reimp */
bool QAccessibleButton::doAction(int action, int child, const QVariantList &params)
{
- if (child || !widget()->isEnabled() || !widget()->isVisible())
+ if (child || !widget()->isEnabled())
return false;
switch (action) {
@@ -155,9 +155,6 @@ bool QAccessibleButton::doAction(int action, int child, const QVariantList &para
QString QAccessibleButton::text(Text t, int child) const
{
QString str;
- if (!widget()->isVisible())
- return str;
-
switch (t) {
case Accelerator:
{
@@ -227,6 +224,9 @@ QString QAccessibleButton::description(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ return QLatin1String("Toggles the button.");
+ }
return QLatin1String("Clicks the button.");
default:
return QString();
@@ -237,6 +237,13 @@ QString QAccessibleButton::name(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ if (button()->isChecked()) {
+ return QLatin1String("Uncheck");
+ } else {
+ return QLatin1String("Check");
+ }
+ }
return QLatin1String("Press");
default:
return QString();
@@ -247,6 +254,13 @@ QString QAccessibleButton::localizedName(int actionIndex)
{
switch (actionIndex) {
case 0:
+ if (button()->isCheckable()) {
+ if (button()->isChecked()) {
+ return tr("Uncheck");
+ } else {
+ return tr("Check");
+ }
+ }
return tr("Press");
default:
return QString();
@@ -380,9 +394,6 @@ QRect QAccessibleToolButton::rect(int child) const
QString QAccessibleToolButton::text(Text t, int child) const
{
QString str;
- if (!toolButton()->isVisible())
- return str;
-
switch (t) {
case Name:
str = toolButton()->text();
@@ -454,7 +465,7 @@ QString QAccessibleToolButton::actionText(int action, Text text, int child) cons
*/
bool QAccessibleToolButton::doAction(int action, int child, const QVariantList &params)
{
- if (!widget()->isEnabled() || !widget()->isVisible())
+ if (!widget()->isEnabled())
return false;
if (action == 1 || child == ButtonDropMenu) {
if(!child)
@@ -513,8 +524,6 @@ QAccessible::Role QAccessibleDisplay::role(int child) const
QString QAccessibleDisplay::text(Text t, int child) const
{
QString str;
- if (!widget()->isVisible())
- return str;
switch (t) {
case Name:
str = widget()->accessibleName();
@@ -674,8 +683,6 @@ QLineEdit *QAccessibleLineEdit::lineEdit() const
QString QAccessibleLineEdit::text(Text t, int child) const
{
QString str;
- if (!lineEdit()->isVisible())
- return str;
switch (t) {
case Value:
if (lineEdit()->echoMode() == QLineEdit::Normal)
@@ -692,8 +699,6 @@ QString QAccessibleLineEdit::text(Text t, int child) const
/*! \reimp */
void QAccessibleLineEdit::setText(Text t, int control, const QString &text)
{
- if (!lineEdit()->isVisible())
- return;
if (t != Value || control) {
QAccessibleWidgetEx::setText(t, control, text);
return;
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
index 3d8cf50..9a94c30 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
@@ -365,10 +365,12 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion &region,
if (!win)
return;
-#ifndef QT_NO_QWS_PROXYSCREEN
+#if !defined(QT_NO_QWS_PROXYSCREEN) && !defined(QT_NO_GRAPHICSVIEW)
QWExtra *extra = qt_widget_private(widget)->extraData();
if (extra && extra->proxyWidget)
return;
+#else
+ Q_UNUSED(widget);
#endif
const quint8 windowOpacity = quint8(win->windowOpacity() * 0xff);
diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp
index ee46691..85effc9 100644
--- a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp
@@ -70,11 +70,13 @@ QDirectFbGLContext::QDirectFbGLContext(IDirectFBGL *glContext)
void QDirectFbGLContext::makeCurrent()
{
+ QPlatformGLContext::makeCurrent();
m_dfbGlContext->Lock(m_dfbGlContext);
}
void QDirectFbGLContext::doneCurrent()
{
+ QPlatformGLContext::doneCurrent();
m_dfbGlContext->Unlock(m_dfbGlContext);
}
diff --git a/src/plugins/platforms/eglconvenience/eglconvenience.pri b/src/plugins/platforms/eglconvenience/eglconvenience.pri
new file mode 100644
index 0000000..322d4e4
--- /dev/null
+++ b/src/plugins/platforms/eglconvenience/eglconvenience.pri
@@ -0,0 +1,7 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qeglconvenience.cpp
+
+HEADERS += \
+ $$PWD/qeglconvenience.h
diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp
index ec4577a..df7abc1 100644
--- a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp
+++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp
@@ -206,12 +206,12 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes)
return false;
}
-EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat)
+EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat, int surfaceType)
{
EGLConfig cfg = 0;
QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format);
configureAttributes.append(EGL_SURFACE_TYPE); //we only support eglconfigs for windows for now
- configureAttributes.append(EGL_WINDOW_BIT);
+ configureAttributes.append(surfaceType);
configureAttributes.append(EGL_RENDERABLE_TYPE);
if (format.windowApi() == QPlatformWindowFormat::OpenVG) {
diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h
index 8668095..c7d3d61 100644
--- a/src/plugins/platforms/eglconvenience/qeglconvenience.h
+++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h
@@ -46,16 +46,12 @@
#include <QtGui/QPlatformWindowFormat>
#include <QtCore/QVector>
-#ifdef Q_PLATFORM_WAYLAND
-#include "qwaylandinclude.h"
-#else
#include <EGL/egl.h>
-#endif
QT_BEGIN_NAMESPACE
QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format);
bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes);
-EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat = false);
+EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat = false, int surfaceType = EGL_WINDOW_BIT);
QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config);
bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp
index 9a2bc61..ae5215f 100644
--- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp
+++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp
@@ -146,11 +146,6 @@ void* QEGLPlatformContext::getProcAddress(const QString& procName)
return (void *)eglGetProcAddress(qPrintable(procName));
}
-void QEGLPlatformContext::makeDefaultSharedContext()
-{
- setDefaultSharedContext(this);
-}
-
QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const
{
return m_windowFormat;
diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h
index d688660..69835d7 100644
--- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h
+++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h
@@ -56,8 +56,6 @@ public:
void swapBuffers();
void* getProcAddress(const QString& procName);
- void makeDefaultSharedContext();
-
QPlatformWindowFormat platformWindowFormat() const;
EGLContext eglContext() const;
diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp
index 7f296c5..45746e9 100644
--- a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp
+++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp
@@ -52,13 +52,11 @@ static int countBits(unsigned long mask)
return count;
}
-VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLConfig config)
+VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
{
VisualID visualId = 0;
EGLint eglValue = 0;
- EGLDisplay eglDisplay = eglGetDisplay(display);
-
EGLint configRedSize = 0;
eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize);
diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h
index 51996da..6c2e266 100644
--- a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h
+++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h
@@ -47,7 +47,7 @@
class QXlibEglIntegration
{
public:
- static VisualID getCompatibleVisualId(Display *display, EGLConfig config);
+ static VisualID getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config);
};
#endif // QTESTLITEEGLINTEGRATION_H
diff --git a/src/plugins/platforms/eglconvenience/xlibeglintegration.pri b/src/plugins/platforms/eglconvenience/xlibeglintegration.pri
new file mode 100644
index 0000000..9404a70
--- /dev/null
+++ b/src/plugins/platforms/eglconvenience/xlibeglintegration.pri
@@ -0,0 +1,7 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qxlibeglintegration.h
+
+SOURCES += \
+ $$PWD/qxlibeglintegration.cpp
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 78981f9..1bc0806 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -44,12 +44,12 @@
#include "qeglfswindow.h"
#include "qeglfswindowsurface.h"
+#include "qgenericunixfontdatabase.h"
+
#include <QtGui/QPlatformWindow>
#include <QtGui/QPlatformWindowFormat>
#include <QtOpenGL/private/qpixmapdata_gl_p.h>
-#include "qgenericunixfontdatabase.h"
-
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index 2200d1d..b6f2805 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -203,7 +203,6 @@ void QEglFSScreen::createAndSetPlatformContext()
attribList[temp++] = EGL_NONE;
QEGLPlatformContext *platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API);
- platformContext->makeDefaultSharedContext();
m_platformContext = platformContext;
EGLint w,h; // screen size detection
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h
index 6a2a504..f300842 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.h
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.h
@@ -44,6 +44,7 @@
#include <QPlatformScreen>
+#include <QtCore/QTextStream>
#include <EGL/egl.h>
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h
index ad51114..f125eab 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.h
+++ b/src/plugins/platforms/eglfs/qeglfswindow.h
@@ -45,12 +45,9 @@
#include "qeglfsintegration.h"
#include "qeglfsscreen.h"
-
#include <QPlatformWindow>
#include <QtGui/QWidget>
-#include <EGL/egl.h>
-
QT_BEGIN_NAMESPACE
class QEglFSWindow : public QPlatformWindow
diff --git a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri
index dbcfbce..1153ab3 100644
--- a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri
+++ b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri
@@ -5,6 +5,6 @@ contains(QT_CONFIG, fontconfig) {
include(../basicunix/basicunix.pri)
}
-INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix
+INCLUDEPATH += $$PWD
HEADERS += \
- $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h
+ $$PWD/qgenericunixfontdatabase.h
diff --git a/src/plugins/platforms/glxconvenience/glxconvenience.pri b/src/plugins/platforms/glxconvenience/glxconvenience.pri
new file mode 100644
index 0000000..d6c9922
--- /dev/null
+++ b/src/plugins/platforms/glxconvenience/glxconvenience.pri
@@ -0,0 +1,7 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qglxconvenience.h
+
+SOURCES += \
+ $$PWD/qglxconvenience.cpp
diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.cpp b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp
new file mode 100644
index 0000000..7cee3e2
--- /dev/null
+++ b/src/plugins/platforms/glxconvenience/qglxconvenience.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qglxconvenience.h"
+
+#include <QtCore/QVector>
+
+enum {
+ XFocusOut = FocusOut,
+ XFocusIn = FocusIn,
+ XKeyPress = KeyPress,
+ XKeyRelease = KeyRelease,
+ XNone = None,
+ XRevertToParent = RevertToParent,
+ XGrayScale = GrayScale,
+ XCursorShape = CursorShape
+};
+#undef FocusOut
+#undef FocusIn
+#undef KeyPress
+#undef KeyRelease
+#undef None
+#undef RevertToParent
+#undef GrayScale
+#undef CursorShape
+
+#ifdef FontChange
+#undef FontChange
+#endif
+
+QVector<int> qglx_buildSpec(const QPlatformWindowFormat &format, int drawableBit)
+{
+ QVector<int> spec(48);
+ int i = 0;
+
+ spec[i++] = GLX_LEVEL;
+ spec[i++] = 0;
+ spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit;
+
+ if (format.rgba()) {
+ spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;
+ spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize();
+ spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize();
+ spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize();
+ if (format.alpha()) {
+ spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize();
+ }
+
+ spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
+ spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
+ spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
+
+ if (format.alpha()) {
+ spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
+ }
+
+ } else {
+ spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works....
+ spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8;
+ }
+
+ spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False;
+ spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False;
+
+ if (format.depth()) {
+ spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize();
+ }
+
+ if (format.stencil()) {
+ spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
+ }
+ if (format.sampleBuffers()) {
+ spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLES_ARB;
+ spec[i++] = format.samples() == -1 ? 4 : format.samples();
+ }
+
+ spec[i++] = XNone;
+ return spec;
+}
+
+GLXFBConfig qglx_findConfig(Display *display, int screen , const QPlatformWindowFormat &format, int drawableBit)
+{
+ bool reduced = true;
+ GLXFBConfig chosenConfig = 0;
+ QPlatformWindowFormat reducedFormat = format;
+ while (!chosenConfig && reduced) {
+ QVector<int> spec = qglx_buildSpec(reducedFormat, drawableBit);
+ int confcount = 0;
+ GLXFBConfig *configs;
+ configs = glXChooseFBConfig(display, screen,spec.constData(),&confcount);
+ if (confcount)
+ {
+ for (int i = 0; i < confcount; i++) {
+ chosenConfig = configs[i];
+ // Make sure we try to get an ARGB visual if the format asked for an alpha:
+ if (reducedFormat.alpha()) {
+ int alphaSize;
+ glXGetFBConfigAttrib(display,configs[i],GLX_ALPHA_SIZE,&alphaSize);
+ if (alphaSize > 0)
+ break;
+ } else {
+ break; // Just choose the first in the list if there's no alpha requested
+ }
+ }
+
+ XFree(configs);
+ }
+ reducedFormat = qglx_reducePlatformWindowFormat(reducedFormat,&reduced);
+ }
+
+ if (!chosenConfig)
+ qWarning("Warning: no suitable glx confiuration found");
+
+ return chosenConfig;
+}
+
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QPlatformWindowFormat &format)
+{
+ GLXFBConfig config = qglx_findConfig(display,screen,format);
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(display,config);
+ return visualInfo;
+}
+
+QPlatformWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx)
+{
+ QPlatformWindowFormat format;
+ int redSize = 0;
+ int greenSize = 0;
+ int blueSize = 0;
+ int alphaSize = 0;
+ int depthSize = 0;
+ int stencilSize = 0;
+ int sampleBuffers = 0;
+ int sampleCount = 0;
+ int level = 0;
+ int rgba = 0;
+ int stereo = 0;
+ int accumSizeA = 0;
+ int accumSizeR = 0;
+ int accumSizeG = 0;
+ int accumSizeB = 0;
+
+ XVisualInfo *vi = glXGetVisualFromFBConfig(display,config);
+ glXGetConfig(display,vi,GLX_RGBA,&rgba);
+ XFree(vi);
+ glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize);
+ glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize);
+ glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize);
+ glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize);
+ glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize);
+ glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
+ glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers);
+ glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level);
+ glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
+ glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA);
+ glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR);
+ glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG);
+ glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB);
+
+ format.setRedBufferSize(redSize);
+ format.setGreenBufferSize(greenSize);
+ format.setBlueBufferSize(blueSize);
+ format.setAlphaBufferSize(alphaSize);
+ format.setDepthBufferSize(depthSize);
+ format.setStencilBufferSize(stencilSize);
+ format.setSampleBuffers(sampleBuffers);
+ if (format.sampleBuffers()) {
+ glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount);
+ format.setSamples(sampleCount);
+ }
+
+ format.setDirectRendering(glXIsDirect(display, ctx));
+ format.setRgba(rgba);
+ format.setStereo(stereo);
+ format.setAccumBufferSize(accumSizeB);
+
+ return format;
+}
+
+QPlatformWindowFormat qglx_reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced)
+{
+ QPlatformWindowFormat retFormat = format;
+ *reduced = true;
+
+ if (retFormat.sampleBuffers()) {
+ retFormat.setSampleBuffers(false);
+ } else if (retFormat.stereo()) {
+ retFormat.setStereo(false);
+ } else if (retFormat.accum()) {
+ retFormat.setAccum(false);
+ }else if (retFormat.stencil()) {
+ retFormat.setStencil(false);
+ }else if (retFormat.alpha()) {
+ retFormat.setAlpha(false);
+ }else if (retFormat.depth()) {
+ retFormat.setDepth(false);
+ }else if (retFormat.doubleBuffer()) {
+ retFormat.setDoubleBuffer(false);
+ }else{
+ *reduced = false;
+ }
+ return retFormat;
+}
diff --git a/src/plugins/platforms/glxconvenience/qglxconvenience.h b/src/plugins/platforms/glxconvenience/qglxconvenience.h
new file mode 100644
index 0000000..2c59dbb
--- /dev/null
+++ b/src/plugins/platforms/glxconvenience/qglxconvenience.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLXCONVENIENCE_H
+#define QGLXCONVENIENCE_H
+
+#include <QPlatformWindowFormat>
+
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, const QPlatformWindowFormat &format);
+GLXFBConfig qglx_findConfig(Display *display, int screen, const QPlatformWindowFormat &format, int drawableBit = GLX_WINDOW_BIT);
+QPlatformWindowFormat qglx_platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context);
+QVector<int> qglx_buildSpec(const QPlatformWindowFormat &format, int drawableBit = GLX_WINDOW_BIT);
+QPlatformWindowFormat qglx_reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced);
+
+#endif // QGLXCONVENIENCE_H
diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp
index 35e744be..703b1a9 100644
--- a/src/plugins/platforms/openkode/qopenkodeintegration.cpp
+++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp
@@ -122,7 +122,9 @@ QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop
}
QOpenKODEIntegration::QOpenKODEIntegration()
- : mEventLoopIntegration(0), mFontDb(new QGenericUnixFontDatabase())
+ : mEventLoopIntegration(0)
+ , mFontDb(new QGenericUnixFontDatabase())
+ , mMainGlContext(0)
{
if (kdInitializeNV() == KD_ENOTINITIALIZED) {
qFatal("Did not manage to initialize openkode");
@@ -190,6 +192,7 @@ bool QOpenKODEIntegration::hasCapability(QPlatformIntegration::Capability cap) c
{
switch (cap) {
case ThreadedPixmaps: return true;
+ case OpenGL: return true;
default: return QPlatformIntegration::hasCapability(cap);
}
}
@@ -226,11 +229,6 @@ QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId)
return returnSurface;
}
-bool QOpenKODEIntegration::hasOpenGL() const
-{
- return true;
-}
-
QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration() const
{
if (!mEventLoopIntegration) {
diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h
index 7582e60..d5aac98 100644
--- a/src/plugins/platforms/openkode/qopenkodeintegration.h
+++ b/src/plugins/platforms/openkode/qopenkodeintegration.h
@@ -96,8 +96,6 @@ public:
QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const;
QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const;
- bool hasOpenGL() const;
-
QPlatformEventLoopIntegration *createEventLoopIntegration() const;
QPlatformFontDatabase *fontDatabase() const;
@@ -106,10 +104,14 @@ public:
static GLuint blitterProgram();
+ void setMainGLContext(QEGLPlatformContext *ctx) { mMainGlContext = ctx; }
+ void mainGLContext() const { return mMainGlContext; }
+
private:
QList<QPlatformScreen *> mScreens;
QOpenKODEEventLoopIntegration *mEventLoopIntegration;
QPlatformFontDatabase *mFontDb;
+ QEGLPlatformContext *mMainGlContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/openkode/qopenkodewindow.cpp b/src/plugins/platforms/openkode/qopenkodewindow.cpp
index 66530a5..d34dff8 100644
--- a/src/plugins/platforms/openkode/qopenkodewindow.cpp
+++ b/src/plugins/platforms/openkode/qopenkodewindow.cpp
@@ -147,9 +147,9 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw)
}
+ QOpenKODEIntegration *integration = static_cast<QOpenKODEIntegration *>(QApplicationPrivate::platformIntegration());
-
- if (!isFullScreen || (isFullScreen && !QPlatformGLContext::defaultSharedContext())) {
+ if (!isFullScreen || (isFullScreen && !integration->mainGLContext())) {
if (kdRealizeWindow(m_kdWindow, &m_eglWindow)) {
qErrnoWarning(kdGetError(), "Could not realize native window");
return;
@@ -158,9 +158,9 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw)
EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData());
m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(), m_eglConfig,
m_eglContextAttrs.data(), surface, m_eglApi);
- m_platformGlContext->makeDefaultSharedContext();
+ integration->setMainGLContext(m_platformGLContext);
} else {
- m_platformGlContext = const_cast<QEGLPlatformContext *>(static_cast<const QEGLPlatformContext *>(QPlatformGLContext::defaultSharedContext()));
+ m_platformGlContext = integration->mainGLContext();
kdDestroyWindow(m_kdWindow);
m_kdWindow = 0;
}
@@ -169,7 +169,7 @@ QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw)
QOpenKODEWindow::~QOpenKODEWindow()
{
- if (m_platformGlContext != QPlatformGLContext::defaultSharedContext()) {
+ if (m_platformGlContext != static_cast<QOpenKODEIntegration *>(QApplicationPrivate::platformIntegration())) {
delete m_platformGlContext;
}
if (m_kdWindow)
diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README
index b2984fc..a101a3a 100644
--- a/src/plugins/platforms/uikit/README
+++ b/src/plugins/platforms/uikit/README
@@ -18,11 +18,11 @@ After configuring and building Qt you need to also build src/plugins/platforms/u
Simulator:
----------
-configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
+configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
Device:
-------
-configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
+configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations
2) XCode setup:
- there are examples in the examples subdirectory of the platform plugin
diff --git a/src/plugins/platforms/uikit/examples/qmltest/main.mm b/src/plugins/platforms/uikit/examples/qmltest/main.mm
index 6fd5629..ea4e90c 100644
--- a/src/plugins/platforms/uikit/examples/qmltest/main.mm
+++ b/src/plugins/platforms/uikit/examples/qmltest/main.mm
@@ -39,36 +39,40 @@
**
****************************************************************************/
-//
-// main.m
-// qmltest
-//
-// Created by Eike Troll on 18.02.11.
-// Copyright 2011 __MyCompanyName__. All rights reserved.
-//
-
#import <UIKit/UIKit.h>
#include "qmlapplicationviewer/qmlapplicationviewer.h"
#include <QtGui/QApplication>
#include <QtCore/QtPlugin>
+#include <QtDeclarative/QDeclarativeEngine>
Q_IMPORT_PLUGIN(UIKit)
+static QString qStringFromNSString(NSString *nsstring)
+{
+ return QString::fromUtf8([nsstring UTF8String]);
+}
+
+static QString documentsDirectory()
+{
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+ return qStringFromNSString(documentsDirectory);
+}
+
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- setenv("QT_QPA_PLATFORM","uikit",1);
-
- QApplication app(argc, argv);
+ QApplication app(argc, argv);
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
- NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
- viewer.setMainQmlFile(QString::fromUtf8([[resourcePath stringByAppendingPathComponent:@"qml/main.qml"] UTF8String]));
+ viewer.engine()->setOfflineStoragePath(documentsDirectory());
+ NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
+ viewer.setMainQmlFile(qStringFromNSString([resourcePath stringByAppendingPathComponent:@"qml/main.qml"]));
viewer.showMaximized();
- int retVal = app.exec();
+ int retVal = app.exec();
[pool release];
return retVal;
}
diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj
index fc4f1df..10bb20f 100755
--- a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj
+++ b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj
@@ -10,6 +10,14 @@
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; };
+ D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659431338B21000760B02 /* libQtXml_debug.a */; };
+ D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */; };
+ D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784231345D8C90046D202 /* libQtOpenGL_debug.a */; };
+ D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; };
+ D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; };
+ D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3578435134A09990046D202 /* libQtOpenGL.a */; };
+ D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; };
+ D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; };
D3CAA7C813264AAD008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; };
D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; };
D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; };
@@ -50,6 +58,12 @@
288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qmltest_Prefix.pch; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* qmltest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "qmltest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+ D31659431338B21000760B02 /* libQtXml_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXml_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXml_debug.a"; sourceTree = SOURCE_ROOT; };
+ D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXmlPatterns_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXmlPatterns_debug.a"; sourceTree = SOURCE_ROOT; };
+ D35784231345D8C90046D202 /* libQtOpenGL_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtOpenGL_debug.a"; sourceTree = "<group>"; };
+ D35784251345D9940046D202 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ D35784271345D9E00046D202 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ D3578435134A09990046D202 /* libQtOpenGL.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtOpenGL.a"; sourceTree = "<group>"; };
D3CAA7C713264AAD008BB877 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_qmlapplicationviewer.cpp; path = qmlapplicationviewer/moc_qmlapplicationviewer.cpp; sourceTree = "<group>"; };
D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qmlapplicationviewer.cpp; path = qmlapplicationviewer/qmlapplicationviewer.cpp; sourceTree = "<group>"; };
@@ -81,9 +95,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */,
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */,
+ D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */,
D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */,
D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */,
D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */,
@@ -92,6 +108,9 @@
D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */,
D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */,
D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */,
+ D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */,
+ D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */,
+ D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -99,6 +118,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */,
+ D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */,
D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */,
D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */,
D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */,
@@ -112,6 +133,7 @@
D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */,
D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */,
D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */,
+ D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -166,6 +188,8 @@
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
1D30AB110D05D00D00671497 /* Foundation.framework */,
288765A40DF7441C002DB57D /* CoreGraphics.framework */,
+ D35784251345D9940046D202 /* OpenGLES.framework */,
+ D35784271345D9E00046D202 /* QuartzCore.framework */,
D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */,
);
name = Frameworks;
@@ -189,6 +213,7 @@
D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */,
D3D817AC132A2CFD00CDE422 /* libQtGui.a */,
D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */,
+ D3578435134A09990046D202 /* libQtOpenGL.a */,
D3D817AE132A2CFD00CDE422 /* libQtScript.a */,
D3D817AF132A2CFD00CDE422 /* libQtSql.a */,
D3D817B0132A2CFD00CDE422 /* libQtXml.a */,
@@ -205,8 +230,11 @@
D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */,
D3CAA81813265056008BB877 /* libQtGui_debug.a */,
D3CAA82713265220008BB877 /* libQtNetwork_debug.a */,
+ D35784231345D8C90046D202 /* libQtOpenGL_debug.a */,
D3CAA81913265056008BB877 /* libQtScript_debug.a */,
D3CAA81A13265056008BB877 /* libQtSql_debug.a */,
+ D31659431338B21000760B02 /* libQtXml_debug.a */,
+ D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */,
);
name = Simulator;
sourceTree = "<group>";
diff --git a/src/plugins/platforms/uikit/quikiteventloop.h b/src/plugins/platforms/uikit/quikiteventloop.h
index cf5c682..b81e0fd 100644
--- a/src/plugins/platforms/uikit/quikiteventloop.h
+++ b/src/plugins/platforms/uikit/quikiteventloop.h
@@ -42,6 +42,9 @@
#ifndef QUIKITEVENTLOOP_H
#define QUIKITEVENTLOOP_H
+#include "quikitsoftwareinputhandler.h"
+
+#include <QtCore/QEvent>
#include <QtGui/QPlatformEventLoopIntegration>
@class EventLoopHelper;
@@ -61,6 +64,7 @@ public:
EventLoopHelper *mHelper;
NSTimer *mTimer;
+ QUIKitSoftwareInputHandler *mInputHandler;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/quikiteventloop.mm b/src/plugins/platforms/uikit/quikiteventloop.mm
index 70757b1..2b9728c 100644
--- a/src/plugins/platforms/uikit/quikiteventloop.mm
+++ b/src/plugins/platforms/uikit/quikiteventloop.mm
@@ -69,19 +69,10 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
Q_UNUSED(launchOptions)
+ Q_UNUSED(application)
foreach (QWidget *widget, qApp->topLevelWidgets()) {
- QRect geom = widget->geometry();
- CGRect bar = application.statusBarFrame;
- if (geom.y() <= bar.size.height) {
- geom.setY(bar.size.height);
- widget->setGeometry(geom);
- }
QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow());
platformWindow->ensureNativeWindow();
- QUIKitWindowSurface *surface = static_cast<QUIKitWindowSurface*>(widget->windowSurface());
- UIView *view = surface->nativeView();
- [platformWindow->nativeWindow() addSubview:view];
- [platformWindow->nativeWindow() makeKeyAndVisible];
}
return YES;
}
@@ -128,6 +119,7 @@ QT_BEGIN_NAMESPACE
QUIKitEventLoop::QUIKitEventLoop()
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ mInputHandler = new QUIKitSoftwareInputHandler;
mHelper = [[EventLoopHelper alloc] initWithEventLoopIntegration:this];
mTimer = [[NSTimer timerWithTimeInterval:0.030 target:mHelper selector:@selector(processEventsAndSchedule) userInfo:nil repeats:YES] retain];
[pool release];
@@ -137,10 +129,12 @@ QUIKitEventLoop::~QUIKitEventLoop()
{
[mTimer release];
[mHelper release];
+ delete mInputHandler;
}
void QUIKitEventLoop::startEventLoop()
{
+ qApp->installEventFilter(mInputHandler);
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[[NSRunLoop currentRunLoop] addTimer:[mTimer autorelease] forMode:NSDefaultRunLoopMode];
UIApplicationMain(qApp->argc(), qApp->argv(), nil, @"QUIKitAppDelegate");
@@ -157,4 +151,24 @@ void QUIKitEventLoop::qtNeedsToProcessEvents()
[mHelper performSelectorOnMainThread:@selector(processEvents) withObject:nil waitUntilDone:NO];
}
+bool QUIKitSoftwareInputHandler::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::RequestSoftwareInputPanel) {
+ QWidget *widget = qobject_cast<QWidget *>(obj);
+ if (widget) {
+ QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow());
+ [platformWindow->nativeView() becomeFirstResponder];
+ return true;
+ }
+ } else if (event->type() == QEvent::CloseSoftwareInputPanel) {
+ QWidget *widget = qobject_cast<QWidget *>(obj);
+ if (widget) {
+ QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow());
+ [platformWindow->nativeView() resignFirstResponder];
+ return true;
+ }
+ }
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/quikitintegration.mm b/src/plugins/platforms/uikit/quikitintegration.mm
index d4b4192..3a432d1 100644
--- a/src/plugins/platforms/uikit/quikitintegration.mm
+++ b/src/plugins/platforms/uikit/quikitintegration.mm
@@ -66,7 +66,7 @@ QUIKitIntegration::~QUIKitIntegration()
QPixmapData *QUIKitIntegration::createPixmapData(QPixmapData::PixelType type) const
{
- return new QRasterPixmapData(type);
+ return new QRasterPixmapData(type);
}
QPlatformWindow *QUIKitIntegration::createPlatformWindow(QWidget *widget, WId winId) const
diff --git a/src/plugins/platforms/uikit/quikitscreen.mm b/src/plugins/platforms/uikit/quikitscreen.mm
index ec94e3a..78389f2 100644
--- a/src/plugins/platforms/uikit/quikitscreen.mm
+++ b/src/plugins/platforms/uikit/quikitscreen.mm
@@ -41,6 +41,8 @@
#include "quikitscreen.h"
+#include <QtGui/QApplication>
+
#include <QtDebug>
QT_BEGIN_NAMESPACE
@@ -51,21 +53,22 @@ QUIKitScreen::QUIKitScreen(int screenIndex)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIndex];
- UIScreenMode *mode = [screen currentMode];
- CGSize size = [mode size];
- m_geometry = QRect(0, 0, size.width, size.height);
- CGRect bounds = [screen bounds]; // in 'points', 1p == 1/160in
-
-// qreal xDpi = size.width * 160. / bounds.size.width;
-// qreal yDpi = size.height * 160. / bounds.size.height;
-// qDebug() << xDpi << yDpi;
+ CGRect bounds = [screen bounds];
+ m_geometry = QRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
m_format = QImage::Format_ARGB32;
m_depth = 24;
const qreal inch = 25.4;
- m_physicalSize = QSize(qRound(bounds.size.width * inch / 160.), qRound(bounds.size.height * inch / 160.));
+ qreal dpi = 160.;
+ int dragDistance = 12;
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
+ dpi = 132.;
+ dragDistance = 10;
+ }
+ m_physicalSize = QSize(qRound(bounds.size.width * inch / dpi), qRound(bounds.size.height * inch / dpi));
+ qApp->setStartDragDistance(dragDistance);
[pool release];
}
diff --git a/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h b/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h
new file mode 100644
index 0000000..629fd13
--- /dev/null
+++ b/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h
@@ -0,0 +1,61 @@
+
+
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUIKITSOFTWAREINPUTHANDLER_H
+#define QUIKITSOFTWAREINPUTHANDLER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QUIKitSoftwareInputHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ bool eventFilter(QObject *obj, QEvent *event);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/uikit/quikitwindow.h b/src/plugins/platforms/uikit/quikitwindow.h
index d5a6690..5c6496a 100644
--- a/src/plugins/platforms/uikit/quikitwindow.h
+++ b/src/plugins/platforms/uikit/quikitwindow.h
@@ -43,7 +43,63 @@
#define QUIKITWINDOW_H
#include <QPlatformWindow>
-#include <UIKit/UIKit.h>
+
+#import <UIKit/UIKit.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+#import <OpenGLES/ES2/gl.h>
+#import <OpenGLES/ES2/glext.h>
+#import <OpenGLES/EAGL.h>
+
+@interface EAGLView : UIView <UIKeyInput>
+{
+ QPlatformWindow *mWindow;
+ EAGLContext *mContext;
+
+ GLint mFramebufferWidth;
+ GLint mFramebufferHeight;
+
+ GLuint mFramebuffer, mColorRenderbuffer, mDepthRenderbuffer;
+
+ id delegate;
+ // ------- Text Input ----------
+ UITextAutocapitalizationType autocapitalizationType;
+ UITextAutocorrectionType autocorrectionType;
+ BOOL enablesReturnKeyAutomatically;
+ UIKeyboardAppearance keyboardAppearance;
+ UIKeyboardType keyboardType;
+ UIReturnKeyType returnKeyType;
+ BOOL secureTextEntry;
+}
+
+- (void)setContext:(EAGLContext *)newContext;
+- (void)presentFramebuffer;
+- (void)deleteFramebuffer;
+- (void)createFramebuffer;
+- (void)makeCurrent;
+- (void)setWindow:(QPlatformWindow *)window;
+- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons;
+
+@property (readonly,getter=fbo) GLint fbo;
+@property (nonatomic, assign) id delegate;
+
+// ------- Text Input ----------
+
+@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
+@property(nonatomic) UITextAutocorrectionType autocorrectionType;
+@property(nonatomic) BOOL enablesReturnKeyAutomatically;
+@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
+@property(nonatomic) UIKeyboardType keyboardType;
+@property(nonatomic) UIReturnKeyType returnKeyType;
+@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
+
+@end
+
+@protocol EAGLViewDelegate
+- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer;
+@end
+
+class EAGLPlatformContext;
QT_BEGIN_NAMESPACE
@@ -56,13 +112,18 @@ public:
~QUIKitWindow();
UIWindow *nativeWindow() const { return mWindow; }
+ EAGLView *nativeView() const { return mView; }
void setGeometry(const QRect &rect);
UIWindow *ensureNativeWindow();
+ QPlatformGLContext *glContext() const;
+
private:
QUIKitScreen *mScreen;
UIWindow *mWindow;
+ EAGLView *mView;
+ mutable EAGLPlatformContext *mContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/quikitwindow.mm b/src/plugins/platforms/uikit/quikitwindow.mm
index ebdee06..1f57baa 100644
--- a/src/plugins/platforms/uikit/quikitwindow.mm
+++ b/src/plugins/platforms/uikit/quikitwindow.mm
@@ -39,34 +39,320 @@
**
****************************************************************************/
+#import <QuartzCore/CAEAGLLayer.h>
+
#include "quikitwindow.h"
#include "quikitscreen.h"
#include <QtDebug>
+#include <QtGui/QApplication>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QPlatformGLContext>
+#include <QtGui/QWindowSystemInterface>
+
+#include <QtDebug>
+
+class EAGLPlatformContext : public QPlatformGLContext
+{
+public:
+ EAGLPlatformContext(EAGLView *view)
+ : mView(view)
+ {
+ mFormat.setWindowApi(QPlatformWindowFormat::OpenGL);
+ mFormat.setDepthBufferSize(24);
+ mFormat.setAccumBufferSize(0);
+ mFormat.setRedBufferSize(8);
+ mFormat.setGreenBufferSize(8);
+ mFormat.setBlueBufferSize(8);
+ mFormat.setAlphaBufferSize(8);
+ mFormat.setStencilBufferSize(8);
+ mFormat.setSampleBuffers(false);
+ mFormat.setSamples(1);
+// mFormat.setSwapInterval(?)
+ mFormat.setDoubleBuffer(true);
+ mFormat.setDepth(true);
+ mFormat.setRgba(true);
+ mFormat.setAlpha(true);
+ mFormat.setAccum(false);
+ mFormat.setStencil(true);
+ mFormat.setStereo(false);
+ mFormat.setDirectRendering(false);
+
+#if defined(QT_OPENGL_ES_2)
+ EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+#else
+ EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+#endif
+ [mView setContext:aContext];
+ }
+
+ ~EAGLPlatformContext() { }
+
+ void makeCurrent()
+ {
+ QPlatformGLContext::makeCurrent();
+ [mView makeCurrent];
+ }
+
+ void doneCurrent()
+ {
+ QPlatformGLContext::doneCurrent();
+ }
+
+ void swapBuffers()
+ {
+ [mView presentFramebuffer];
+ }
+
+ void* getProcAddress(const QString& ) { return 0; }
+
+ QPlatformWindowFormat platformWindowFormat() const
+ {
+ return mFormat;
+ }
+
+private:
+ EAGLView *mView;
+
+ QPlatformWindowFormat mFormat;
+};
+
+@implementation EAGLView
+
+@synthesize delegate;
+
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+ eaglLayer.opaque = TRUE;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
+ nil];
+ autocapitalizationType = UITextAutocapitalizationTypeNone;
+ autocorrectionType = UITextAutocorrectionTypeNo;
+ enablesReturnKeyAutomatically = NO;
+ keyboardAppearance = UIKeyboardAppearanceDefault;
+ keyboardType = UIKeyboardTypeDefault;
+ returnKeyType = UIReturnKeyDone;
+ secureTextEntry = NO;
+ }
+ return self;
+}
+
+- (void)setContext:(EAGLContext *)newContext
+{
+ if (mContext != newContext)
+ {
+ [self deleteFramebuffer];
+ [mContext release];
+ mContext = [newContext retain];
+ [EAGLContext setCurrentContext:nil];
+ }
+}
+
+- (void)presentFramebuffer
+{
+ if (mContext) {
+ [EAGLContext setCurrentContext:mContext];
+ glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
+ [mContext presentRenderbuffer:GL_RENDERBUFFER];
+ }
+}
+
+- (void)deleteFramebuffer
+{
+ if (mContext)
+ {
+ [EAGLContext setCurrentContext:mContext];
+ if (mFramebuffer) {
+ glDeleteFramebuffers(1, &mFramebuffer);
+ mFramebuffer = 0;
+ }
+ if (mColorRenderbuffer) {
+ glDeleteRenderbuffers(1, &mColorRenderbuffer);
+ mColorRenderbuffer = 0;
+ }
+ if (mDepthRenderbuffer) {
+ glDeleteRenderbuffers(1, &mDepthRenderbuffer);
+ mDepthRenderbuffer = 0;
+ }
+ }
+}
+
+- (void)createFramebuffer
+{
+ if (mContext && !mFramebuffer)
+ {
+ [EAGLContext setCurrentContext:mContext];
+ glGenFramebuffers(1, &mFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+ glGenRenderbuffers(1, &mColorRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
+ [mContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &mFramebufferWidth);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &mFramebufferHeight);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer);
+
+ glGenRenderbuffers(1, &mDepthRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, mFramebufferWidth, mFramebufferHeight);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbuffer);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ if (delegate && [delegate respondsToSelector:@selector(eaglView:usesFramebuffer:)]) {
+ [delegate eaglView:self usesFramebuffer:mFramebuffer];
+ }
+ }
+}
+
+- (void)makeCurrent
+{
+ if (mContext)
+ {
+ [EAGLContext setCurrentContext:mContext];
+ if (!mFramebuffer)
+ [self createFramebuffer];
+ glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+ glViewport(0, 0, mFramebufferWidth, mFramebufferHeight);
+ }
+}
+
+- (GLint)fbo
+{
+ return mFramebuffer;
+}
+
+- (void)setWindow:(QPlatformWindow *)window
+{
+ mWindow = window;
+}
+
+- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons
+{
+ UITouch *touch = [touches anyObject];
+ CGPoint locationInView = [touch locationInView:self];
+ QPoint p(locationInView.x, locationInView.y);
+ // TODO handle global touch point? for status bar?
+ QWindowSystemInterface::handleMouseEvent(mWindow->widget(), (ulong)(event.timestamp*1000),
+ p, p, buttons);
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
+}
+
+// ------- Text Input ----------
+
+@synthesize autocapitalizationType;
+@synthesize autocorrectionType;
+@synthesize enablesReturnKeyAutomatically;
+@synthesize keyboardAppearance;
+@synthesize keyboardType;
+@synthesize returnKeyType;
+@synthesize secureTextEntry;
+
+- (BOOL)canBecomeFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)hasText
+{
+ return YES;
+}
+
+- (void)insertText:(NSString *)text
+{
+ QKeyEvent *ev;
+ int key = 0;
+ if ([text isEqualToString:@"\n"])
+ key = (int)Qt::Key_Return;
+ ev = new QKeyEvent(QEvent::KeyPress,
+ key,
+ Qt::NoModifier,
+ QString::fromUtf8([text UTF8String])
+ );
+ qApp->postEvent(qApp->focusWidget(), ev);
+ ev = new QKeyEvent(QEvent::KeyRelease,
+ key,
+ Qt::NoModifier,
+ QString::fromUtf8([text UTF8String])
+ );
+ qApp->postEvent(qApp->focusWidget(), ev);
+}
+
+- (void)deleteBackward
+{
+ QKeyEvent *ev;
+ ev = new QKeyEvent(QEvent::KeyPress,
+ (int)Qt::Key_Backspace,
+ Qt::NoModifier
+ );
+ qApp->postEvent(qApp->focusWidget(), ev);
+ ev = new QKeyEvent(QEvent::KeyRelease,
+ (int)Qt::Key_Backspace,
+ Qt::NoModifier
+ );
+ qApp->postEvent(qApp->focusWidget(), ev);
+}
+
+@end
QT_BEGIN_NAMESPACE
QUIKitWindow::QUIKitWindow(QWidget *tlw) :
QPlatformWindow(tlw),
- mWindow(nil)
+ mWindow(nil),
+ mContext(0)
{
mScreen = static_cast<QUIKitScreen *>(QPlatformScreen::platformScreenForWidget(tlw));
CGRect screenBounds = [mScreen->uiScreen() bounds];
QRect geom(screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.width, screenBounds.size.height);
setGeometry(geom);
+ mView = [[EAGLView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
// TODO ensure the native window if the application is already running
}
QUIKitWindow::~QUIKitWindow()
{
+ delete mContext; mContext = 0;
+ [mView release];
[mWindow release];
}
void QUIKitWindow::setGeometry(const QRect &rect)
{
- if (mWindow) {
+ if (mWindow && rect != geometry()) {
mWindow.frame = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+ mView.frame = CGRectMake(0, 0, rect.width(), rect.height());
+ [mView deleteFramebuffer];
[mWindow setNeedsDisplay];
}
QPlatformWindow::setGeometry(rect);
@@ -75,15 +361,32 @@ void QUIKitWindow::setGeometry(const QRect &rect)
UIWindow *QUIKitWindow::ensureNativeWindow()
{
if (!mWindow) {
- CGRect screenBounds = [mScreen->uiScreen() bounds];
- QRect geom = geometry();
- CGRect frame = CGRectMake(geom.x(), geom.y(), geom.width(), geom.height());
- mWindow = [[UIWindow alloc] initWithFrame:frame];
+ // window
+ CGRect frame = [mScreen->uiScreen() applicationFrame];
+ QRect geom = QRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+ widget()->setGeometry(geom);
+ mWindow = [[UIWindow alloc] init];
mWindow.screen = mScreen->uiScreen();
- mWindow.frame = frame; // for some reason setting the screen resets frame.origin
+ mWindow.frame = frame; // for some reason setting the screen resets frame.origin, so we need to set the frame afterwards
+
+ // view
+ [mView deleteFramebuffer];
+ mView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); // fill
+ [mView setMultipleTouchEnabled:YES];
+ [mView setWindow:this];
+ [mWindow addSubview:mView];
[mWindow setNeedsDisplay];
+ [mWindow makeKeyAndVisible];
}
return mWindow;
}
+QPlatformGLContext *QUIKitWindow::glContext() const
+{
+ if (!mContext) {
+ mContext = new EAGLPlatformContext(mView);
+ }
+ return mContext;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.h b/src/plugins/platforms/uikit/quikitwindowsurface.h
index 50d02b4..ca10a71 100644
--- a/src/plugins/platforms/uikit/quikitwindowsurface.h
+++ b/src/plugins/platforms/uikit/quikitwindowsurface.h
@@ -43,23 +43,6 @@
#define QUIKITWINDOWSURFACE_H
#include <QtGui/QPlatformIntegration>
-#include <QtGui/QImage>
-#include <QtGui/QWindowSystemInterface>
-
-#include <UIKit/UIKit.h>
-
-@interface QImageView : UIView
-{
- CGImageRef m_cgImage;
- QWidget *m_widget;
-}
-
-- (void)setImage:(QImage *)image;
-- (void)setWidget:(QWidget *)widget;
-
-//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches;
-- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons;
-@end
QT_BEGIN_NAMESPACE
@@ -70,12 +53,10 @@ public:
QPaintDevice *paintDevice();
void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
- void resize (const QSize &size);
+ WindowSurfaceFeatures features() const;
- QImageView *nativeView() const { return mView; }
private:
- QImage *mImage;
- QImageView *mView;
+ QPaintDevice *mPaintDevice;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.mm b/src/plugins/platforms/uikit/quikitwindowsurface.mm
index 1274fca..8caa15f 100644
--- a/src/plugins/platforms/uikit/quikitwindowsurface.mm
+++ b/src/plugins/platforms/uikit/quikitwindowsurface.mm
@@ -42,154 +42,65 @@
#include "quikitwindowsurface.h"
#include "quikitwindow.h"
-#include <QtDebug>
-
-@implementation QImageView
+#include <QtOpenGL/private/qgl_p.h>
+#include <QtOpenGL/private/qglpaintdevice_p.h>
-- (void)dealloc
-{
- CGImageRelease(m_cgImage);
- [super dealloc];
-}
+#include <QtDebug>
-- (void)setImage:(QImage *)image
-{
- CGImageRelease(m_cgImage);
-
- const uchar *imageData = image->bits();
- int bitDepth = image->depth();
- int colorBufferSize = 8;
- int bytesPrLine = image->bytesPerLine();
- int width = image->width();
- int height = image->height();
-
- CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB();
-
- CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData(
- NULL,
- imageData,
- image->byteCount(),
- NULL);
-
- m_cgImage = CGImageCreate(width,
- height,
- colorBufferSize,
- bitDepth,
- bytesPrLine,
- cgColourSpaceRef,
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little,
- cgDataProviderRef,
- NULL,
- false,
- kCGRenderingIntentDefault);
-
- CGDataProviderRelease(cgDataProviderRef);
- CGColorSpaceRelease(cgColourSpaceRef);
-}
+class EAGLPaintDevice;
-- (void)setWidget:(QWidget *)widget
-{
- m_widget = widget;
+@interface PaintDeviceHelper : NSObject {
+ EAGLPaintDevice *device;
}
-- (void)drawRect:(CGRect)rect
-{
+@property (nonatomic, assign) EAGLPaintDevice *device;
- if (!m_cgImage)
- return;
+- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer;
- CGContextRef cgContext = UIGraphicsGetCurrentContext();
- CGContextSaveGState( cgContext );
+@end
- int dy = rect.origin.y + CGRectGetMaxY(rect);
- CGContextTranslateCTM(cgContext, 0, dy);
- CGContextScaleCTM(cgContext, 1, -1);
- CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, rect);
- CGContextDrawImage(cgContext,rect,subImage);
- CGImageRelease(subImage);
+class EAGLPaintDevice : public QGLPaintDevice
+{
+public:
+ EAGLPaintDevice(QPlatformWindow *window)
+ :QGLPaintDevice(), mWindow(window)
+ {
+#if defined(QT_OPENGL_ES_2)
+ helper = [[PaintDeviceHelper alloc] init];
+ helper.device = this;
+ EAGLView *view = static_cast<QUIKitWindow *>(window)->nativeView();
+ view.delegate = helper;
+ m_thisFBO = view.fbo;
+#endif
+ }
- CGContextRestoreGState(cgContext);
-}
+ ~EAGLPaintDevice()
+ {
+#if defined(QT_OPENGL_ES_2)
+ [helper release];
+#endif
+ }
-//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches
-//{
-// NSEnumerator *enumerator = [touches objectEnumerator];
-// id touch;
-// int count = 0;
-// QList<struct QWindowSystemInterface::TouchPoint> result;
-// while ((touch = [enumerator nextObject])) {
-// CGPoint locationInView = [touch locationInView:self];
-// CGRect bounds = [self bounds];
-// struct QWindowSystemInterface::TouchPoint p;
-// p.id = count;
-// p.isPrimary = true;
-// p.normalPosition = QPointF(locationInView.x / bounds.size.width,
-// locationInView.y / bounds.size.height);
-// p.area = QRectF(locationInView.x, locationInView.y, 1, 1);
-// p.pressure = 1.;
-// switch ([touch phase]) {
-// case UITouchPhaseBegan:
-// p.state = Qt::TouchPointPressed;
-// break;
-// case UITouchPhaseMoved:
-// p.state = Qt::TouchPointMoved;
-// break;
-// case UITouchPhaseStationary:
-// p.state = Qt::TouchPointStationary;
-// break;
-// case UITouchPhaseEnded:
-// case UITouchPhaseCancelled:
-// p.state = Qt::TouchPointReleased;
-// break;
-// }
-// result << p;
-// qDebug() << p.id << ":" << p.normalPosition << p.area << p.state;
-// ++count;
-// }
-// qDebug() << result.size();
-// return result;
-//}
-
-- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons
-{
- UITouch *touch = [touches anyObject];
- CGPoint locationInView = [touch locationInView:self];
- QPoint p(locationInView.x, locationInView.y);
- // TODO handle global touch point? for status bar?
- QWindowSystemInterface::handleMouseEvent(m_widget, (ulong)(event.timestamp*1000),
- p, p, buttons);
-}
+ void setFramebuffer(GLuint buffer) { m_thisFBO = buffer; }
+ int devType() const { return QInternal::OpenGL; }
+ QSize size() const { return mWindow->geometry().size(); }
+ QGLContext* context() const { return QGLContext::fromPlatformGLContext(mWindow->glContext()); }
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-{
- //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000),
- // QEvent::TouchBegin, QTouchEvent::TouchScreen,
- // [self touchPointsForTouches:touches]);
- [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
-}
+ QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); }
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-{
- //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000),
- // QEvent::TouchUpdate, QTouchEvent::TouchScreen,
- // [self touchPointsForTouches:touches]);
- [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton];
-}
+private:
+ QPlatformWindow *mWindow;
+ PaintDeviceHelper *helper;
+};
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-{
- //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000),
- // QEvent::TouchEnd, QTouchEvent::TouchScreen,
- // [self touchPointsForTouches:touches]);
- [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
-}
+@implementation PaintDeviceHelper
+@synthesize device;
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer
{
- //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000),
- // QEvent::TouchEnd, QTouchEvent::TouchScreen,
- // [self touchPointsForTouches:touches]);
- [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton];
+ Q_UNUSED(view)
+ if (device)
+ device->setFramebuffer(buffer);
}
@end
@@ -197,46 +108,26 @@
QT_BEGIN_NAMESPACE
QUIKitWindowSurface::QUIKitWindowSurface(QWidget *window)
- : QWindowSurface(window)
+ : QWindowSurface(window), mPaintDevice(new EAGLPaintDevice(window->platformWindow()))
{
- QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(window->platformWindow());
- Q_ASSERT(platformWindow);
- const QRect geo = window->geometry();
- mView = [[QImageView alloc] initWithFrame:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())];
- [mView setMultipleTouchEnabled:YES];
- [mView setWidget:window];
- mImage = new QImage(window->size(),QImage::Format_ARGB32_Premultiplied);
- [mView setImage:mImage];
- if (platformWindow->nativeWindow()) {
- [platformWindow->nativeWindow() addSubview:mView];
- [mView setNeedsDisplay];
- }
}
QPaintDevice *QUIKitWindowSurface::paintDevice()
{
- return mImage;
+ return mPaintDevice;
}
void QUIKitWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(widget);
+ Q_UNUSED(region);
Q_UNUSED(offset);
-
- QRect geo = region.boundingRect();
- [mView setNeedsDisplayInRect:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())];
+ widget->platformWindow()->glContext()->swapBuffers();
}
-void QUIKitWindowSurface::resize (const QSize &size)
+QWindowSurface::WindowSurfaceFeatures QUIKitWindowSurface::features() const
{
- QWindowSurface::resize(size);
-
- delete mImage;
- mImage = new QImage(size,QImage::Format_ARGB32_Premultiplied);
- [mView setImage:mImage];
- const QRect geo = geometry();
- [mView setFrame:CGRectMake(geo.x(), geo.y(), size.width(), size.height())];
- [mView setNeedsDisplay];
+ return PartialUpdates;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/uikit/uikit.pro b/src/plugins/platforms/uikit/uikit.pro
index b73c334..6f5947f 100644
--- a/src/plugins/platforms/uikit/uikit.pro
+++ b/src/plugins/platforms/uikit/uikit.pro
@@ -2,6 +2,8 @@ TARGET = quikit
include(../../qpluginbase.pri)
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms
+QT += opengl
+
OBJECTIVE_SOURCES = main.mm \
quikitintegration.mm \
quikitwindow.mm \
@@ -15,6 +17,8 @@ OBJECTIVE_HEADERS = quikitintegration.h \
quikiteventloop.h \
quikitwindowsurface.h
+HEADERS = quikitsoftwareinputhandler.h
+
#add libz for freetype.
LIBS += -lz
diff --git a/src/plugins/platforms/wayland/gl_integration/gl_integration.pri b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri
new file mode 100644
index 0000000..d9b5fa9
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/gl_integration.pri
@@ -0,0 +1,57 @@
+contains(QT_CONFIG, opengl) {
+ DEFINES += QT_WAYLAND_GL_SUPPORT
+ QT += opengl
+
+HEADERS += \
+ $$PWD/qwaylandglintegration.h \
+ $$PWD/qwaylandglwindowsurface.h
+
+SOURCES += \
+ $$PWD/qwaylandglintegration.cpp \
+ $$PWD/qwaylandglwindowsurface.cpp
+
+ QT_WAYLAND_GL_CONFIG = $$(QT_WAYLAND_GL_CONFIG)
+ contains(QT_CONFIG, opengles2) {
+ isEqual(QT_WAYLAND_GL_CONFIG, wayland_egl) {
+ QT_WAYLAND_GL_INTEGRATION = $$QT_WAYLAND_GL_CONFIG
+ CONFIG += wayland_egl
+ } else:isEqual(QT_WAYLAND_GL_CONFIG,readback) {
+ QT_WAYLAND_GL_INTEGRATION = readback_egl
+ CONFIG += readback_egl
+ } else {
+ QT_WAYLAND_GL_INTEGRATION = xcomposite_egl
+ CONFIG += xcomposite_egl
+ }
+ } else {
+ isEqual(QT_WAYLAND_GL_CONFIG, readback) {
+ QT_WAYLAND_GL_INTEGRATION = readback_glx
+ CONFIG += readback_glx
+ } else {
+ QT_WAYLAND_GL_INTEGRATION = xcomposite_glx
+ CONFIG += xcomposite_glx
+ }
+ }
+
+ message("Wayland GL Integration: $$QT_WAYLAND_GL_INTEGRATION")
+}
+
+
+wayland_egl {
+ include ($$PWD/wayland_egl/wayland_egl.pri)
+}
+
+readback_egl {
+ include ($$PWD/readback_egl/readback_egl.pri)
+}
+
+readback_glx {
+ include ($$PWD/readback_glx/readback_glx.pri)
+}
+
+xcomposite_glx {
+ include ($$PWD/xcomposite_glx/xcomposite_glx.pri)
+}
+
+xcomposite_egl {
+ include ($$PWD/xcomposite_egl/xcomposite_egl.pri)
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp
new file mode 100644
index 0000000..9c8ef4e
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandglintegration.h"
+
+QWaylandGLIntegration::QWaylandGLIntegration()
+{
+
+}
+
+QWaylandGLIntegration::~QWaylandGLIntegration()
+{
+
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h
new file mode 100644
index 0000000..ac16039
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDGLINTEGRATION_H
+#define QWAYLANDGLINTEGRATION_H
+
+class QWaylandWindow;
+class QWaylandDisplay;
+class QWidget;
+
+class QWaylandGLIntegration
+{
+public:
+ QWaylandGLIntegration();
+ virtual ~QWaylandGLIntegration();
+
+ virtual void initialize() = 0;
+
+ virtual QWaylandWindow *createEglWindow(QWidget *widget) = 0;
+
+ static QWaylandGLIntegration *createGLIntegration(QWaylandDisplay *waylandDisplay);
+};
+
+#endif // QWAYLANDGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp
index a8bc352..ebe4c7b 100644
--- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qwaylanddrmsurface.h"
+#include "qwaylandglwindowsurface.h"
#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
@@ -52,10 +52,11 @@
QT_BEGIN_NAMESPACE
-
-
static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br)
{
+#if !defined(QT_OPENGL_ES_2)
+ QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
+#endif
const GLenum target = GL_TEXTURE_2D;
QRectF src = br.isEmpty()
? QRectF(QPointF(), texSize)
@@ -132,7 +133,7 @@ static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport,
drawTexture(r, texture, texSize, sourceRect);
}
-QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window)
+QWaylandGLWindowSurface::QWaylandGLWindowSurface(QWidget *window)
: QWindowSurface(window)
, mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display())
, mPaintDevice(0)
@@ -140,24 +141,24 @@ QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window)
}
-QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface()
+QWaylandGLWindowSurface::~QWaylandGLWindowSurface()
{
delete mPaintDevice;
}
-QPaintDevice *QWaylandDrmWindowSurface::paintDevice()
+QPaintDevice *QWaylandGLWindowSurface::paintDevice()
{
return mPaintDevice;
}
-void QWaylandDrmWindowSurface::beginPaint(const QRegion &)
+void QWaylandGLWindowSurface::beginPaint(const QRegion &)
{
window()->platformWindow()->glContext()->makeCurrent();
glClearColor(0,0,0,0xff);
glClear(GL_COLOR_BUFFER_BIT);
}
-void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
+void QWaylandGLWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(offset);
Q_UNUSED(region);
@@ -172,12 +173,12 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion &region, con
ww->glContext()->swapBuffers();
}
-void QWaylandDrmWindowSurface::resize(const QSize &size)
+void QWaylandGLWindowSurface::resize(const QSize &size)
{
QWindowSurface::resize(size);
window()->platformWindow()->glContext()->makeCurrent();
delete mPaintDevice;
- mPaintDevice = new QGLFramebufferObject(size,QGLFramebufferObject::CombinedDepthStencil,GL_TEXTURE_2D,GL_RGBA);
+ mPaintDevice = new QGLFramebufferObject(size);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h
index 78418ee..8d53b42 100644
--- a/src/plugins/platforms/wayland/qwaylanddrmsurface.h
+++ b/src/plugins/platforms/wayland/gl_integration/qwaylandglwindowsurface.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -48,11 +48,11 @@
class QGLFramebufferObject;
-class QWaylandDrmWindowSurface : public QWindowSurface
+class QWaylandGLWindowSurface : public QWindowSurface
{
public:
- QWaylandDrmWindowSurface(QWidget *window);
- ~QWaylandDrmWindowSurface();
+ QWaylandGLWindowSurface(QWidget *window);
+ ~QWaylandGLWindowSurface();
void beginPaint(const QRegion &);
@@ -62,7 +62,6 @@ public:
void resize(const QSize &size);
private:
-
QWaylandDisplay *mDisplay;
QGLFramebufferObject *mPaintDevice;
};
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp
new file mode 100644
index 0000000..d63087d
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackeglcontext.h"
+
+#include "../../../eglconvenience/qeglconvenience.h"
+
+#include <QtOpenGL/QGLContext>
+#include <QtOpenGL/private/qglextensions_p.h>
+
+#include "qwaylandshmsurface.h"
+
+#include <QtCore/QDebug>
+
+static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
+{
+ const int width = img.width();
+ const int height = img.height();
+
+ if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
+ || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
+ {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+ } else {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
+ }
+ }
+}
+
+QWaylandReadbackEglContext::QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window)
+ : mEglIntegration(eglIntegration)
+ , mWindow(window)
+ , mBuffer(0)
+ , mPixmap(0)
+ , mConfig(q_configFromQPlatformWindowFormat(eglIntegration->eglDisplay(),window->widget()->platformWindowFormat(),true,EGL_PIXMAP_BIT))
+ , mPixmapSurface(EGL_NO_SURFACE)
+{
+ QVector<EGLint> eglContextAttrs;
+ eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ eglContextAttrs.append(2);
+ eglContextAttrs.append(EGL_NONE);
+
+ mContext = eglCreateContext(eglIntegration->eglDisplay(),mConfig,0,eglContextAttrs.constData());
+
+ geometryChanged();
+}
+
+QWaylandReadbackEglContext::~QWaylandReadbackEglContext()
+{
+ eglDestroyContext(mEglIntegration->eglDisplay(),mContext);
+}
+
+void QWaylandReadbackEglContext::makeCurrent()
+{
+ QPlatformGLContext::makeCurrent();
+
+ mWindow->waitForFrameSync();
+
+ eglMakeCurrent(mEglIntegration->eglDisplay(),mPixmapSurface,mPixmapSurface,mContext);
+}
+
+void QWaylandReadbackEglContext::doneCurrent()
+{
+ QPlatformGLContext::doneCurrent();
+ eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
+}
+
+void QWaylandReadbackEglContext::swapBuffers()
+{
+ eglSwapBuffers(mEglIntegration->eglDisplay(),mPixmapSurface);
+
+ if (QPlatformGLContext::currentContext() != this) {
+ makeCurrent();
+ }
+
+ QSize size = mWindow->geometry().size();
+
+ QImage img(size,QImage::Format_ARGB32);
+ const uchar *constBits = img.bits();
+ void *pixels = const_cast<uchar *>(constBits);
+
+ glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels);
+
+ img = img.mirrored();
+ qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV);
+ constBits = img.bits();
+
+ const uchar *constDstBits = mBuffer->image()->bits();
+ uchar *dstBits = const_cast<uchar *>(constDstBits);
+ memcpy(dstBits,constBits,(img.width()*4) * img.height());
+
+
+ mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
+}
+
+void * QWaylandReadbackEglContext::getProcAddress(const QString &procName)
+{
+ return (void *) eglGetProcAddress(procName.toLatin1().data());
+}
+
+QPlatformWindowFormat QWaylandReadbackEglContext::platformWindowFormat() const
+{
+ return qt_qPlatformWindowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig);
+}
+
+void QWaylandReadbackEglContext::geometryChanged()
+{
+ QSize size(mWindow->geometry().size());
+ if (size.isEmpty()) {
+ //QGLWidget wants a context for a window without geometry
+ size = QSize(1,1);
+ }
+
+ mWindow->waitForFrameSync();
+
+ delete mBuffer;
+ if (mPixmap)
+ XFreePixmap(mEglIntegration->xDisplay(),mPixmap);
+
+ mBuffer = new QWaylandShmBuffer(mEglIntegration->waylandDisplay(),size,QImage::Format_ARGB32);
+ mWindow->attach(mBuffer);
+ mPixmap = XCreatePixmap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),size.width(),size.height(),mEglIntegration->depth());
+ XSync(mEglIntegration->xDisplay(),False);
+
+ mPixmapSurface = eglCreatePixmapSurface(mEglIntegration->eglDisplay(),mConfig,mPixmap,0);
+ if (mPixmapSurface == EGL_NO_SURFACE) {
+ qDebug() << "Could not make egl surface out of pixmap :(";
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h
new file mode 100644
index 0000000..ac68275
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKEGLGLCONTEXT_H
+#define QWAYLANDREADBACKEGLGLCONTEXT_H
+
+#include <QPlatformGLContext>
+#include <QtGui/QWidget>
+
+#include "qwaylandreadbackeglintegration.h"
+#include "qwaylandreadbackeglwindow.h"
+
+class QWaylandShmBuffer;
+
+class QWaylandReadbackEglContext : public QPlatformGLContext
+{
+public:
+ QWaylandReadbackEglContext(QWaylandReadbackEglIntegration *eglIntegration, QWaylandReadbackEglWindow *window);
+ ~QWaylandReadbackEglContext();
+
+ void makeCurrent();
+ void doneCurrent();
+ void swapBuffers();
+ void* getProcAddress(const QString& procName);
+
+ virtual QPlatformWindowFormat platformWindowFormat() const;
+
+ void geometryChanged();
+
+private:
+ QWaylandReadbackEglIntegration *mEglIntegration;
+ QWaylandReadbackEglWindow *mWindow;
+ QWaylandShmBuffer *mBuffer;
+
+ Pixmap mPixmap;
+
+ EGLConfig mConfig;
+ EGLContext mContext;
+ EGLSurface mPixmapSurface;
+};
+
+#endif // QWAYLANDREADBACKEGLGLCONTEXT_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp
new file mode 100644
index 0000000..20f7ffb
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackeglintegration.h"
+
+#include <QDebug>
+
+#include "qwaylandreadbackeglwindow.h"
+
+QWaylandReadbackEglIntegration::QWaylandReadbackEglIntegration(QWaylandDisplay *display)
+ : QWaylandGLIntegration()
+ , mWaylandDisplay(display)
+{
+ qDebug() << "Using Readback-EGL";
+ char *display_name = getenv("DISPLAY");
+ mDisplay = XOpenDisplay(display_name);
+ mScreen = XDefaultScreen(mDisplay);
+ mRootWindow = XDefaultRootWindow(mDisplay);
+ XSync(mDisplay, False);
+}
+
+QWaylandReadbackEglIntegration::~QWaylandReadbackEglIntegration()
+{
+ XCloseDisplay(mDisplay);
+}
+
+
+QWaylandGLIntegration *QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay)
+{
+ return new QWaylandReadbackEglIntegration(waylandDisplay);
+}
+
+void QWaylandReadbackEglIntegration::initialize()
+{
+ eglBindAPI(EGL_OPENGL_ES_API);
+ mEglDisplay = eglGetDisplay(mDisplay);
+ EGLint major, minor;
+ EGLBoolean initialized = eglInitialize(mEglDisplay,&major,&minor);
+ if (initialized) {
+ qDebug() << "EGL initialized successfully" << major << "," << minor;
+ } else {
+ qDebug() << "EGL could not initialized. All EGL and GL operations will fail";
+ }
+}
+
+QWaylandWindow * QWaylandReadbackEglIntegration::createEglWindow(QWidget *widget)
+{
+ return new QWaylandReadbackEglWindow(widget,this);
+}
+
+EGLDisplay QWaylandReadbackEglIntegration::eglDisplay()
+{
+ return mEglDisplay;
+}
+
+Window QWaylandReadbackEglIntegration::rootWindow() const
+{
+ return mRootWindow;
+}
+
+int QWaylandReadbackEglIntegration::depth() const
+{
+ return XDefaultDepth(mDisplay,mScreen);
+}
+
+Display * QWaylandReadbackEglIntegration::xDisplay() const
+{
+ return mDisplay;
+}
+
+QWaylandDisplay * QWaylandReadbackEglIntegration::waylandDisplay() const
+{
+ return mWaylandDisplay;
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h
new file mode 100644
index 0000000..84fa64f
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKEGLINTEGRATION_H
+#define QWAYLANDREADBACKEGLINTEGRATION_H
+
+#include "gl_integration/qwaylandglintegration.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDataStream>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+
+#include <X11/Xlib.h>
+
+#include <EGL/egl.h>
+
+class QWaylandReadbackEglIntegration : public QWaylandGLIntegration
+{
+public:
+ QWaylandReadbackEglIntegration(QWaylandDisplay *display);
+ ~QWaylandReadbackEglIntegration();
+
+ void initialize();
+ QWaylandWindow *createEglWindow(QWidget *widget);
+
+ QWaylandDisplay *waylandDisplay() const;
+ Display *xDisplay() const;
+ Window rootWindow() const;
+ int depth() const;
+
+ EGLDisplay eglDisplay();
+
+private:
+ QWaylandDisplay *mWaylandDisplay;
+ Display *mDisplay;
+ int mScreen;
+ Window mRootWindow;
+ EGLDisplay mEglDisplay;
+
+};
+
+#endif // QWAYLANDREADBACKEGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp
new file mode 100644
index 0000000..2ae212b
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackeglwindow.h"
+
+#include "qwaylandreadbackeglcontext.h"
+
+QWaylandReadbackEglWindow::QWaylandReadbackEglWindow(QWidget *window, QWaylandReadbackEglIntegration *eglIntegration)
+ : QWaylandShmWindow(window)
+ , mEglIntegration(eglIntegration)
+ , mContext(0)
+{
+}
+
+QWaylandWindow::WindowType QWaylandReadbackEglWindow::windowType() const
+{
+ //We'r lying, maybe we should add a type, but for now it will do
+ //since this is primarly used by the windowsurface.
+ return QWaylandWindow::Egl;
+}
+
+QPlatformGLContext *QWaylandReadbackEglWindow::glContext() const
+{
+ if (!mContext) {
+ QWaylandReadbackEglWindow *that = const_cast<QWaylandReadbackEglWindow *>(this);
+ that->mContext = new QWaylandReadbackEglContext(mEglIntegration,that);
+ }
+ return mContext;
+}
+
+void QWaylandReadbackEglWindow::setGeometry(const QRect &rect)
+{
+ QPlatformWindow::setGeometry(rect);
+
+ if (mContext)
+ mContext->geometryChanged();
+}
+
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h
new file mode 100644
index 0000000..453ad27
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKEGLWINDOW_H
+#define QWAYLANDREADBACKEGLWINDOW_H
+
+#include "qwaylandshmwindow.h"
+#include "qwaylandreadbackeglintegration.h"
+
+class QWaylandReadbackEglContext;
+
+class QWaylandReadbackEglWindow : public QWaylandShmWindow
+{
+public:
+ QWaylandReadbackEglWindow(QWidget *window, QWaylandReadbackEglIntegration *eglIntegration);
+
+ WindowType windowType() const;
+
+ QPlatformGLContext *glContext() const;
+
+ void setGeometry(const QRect &rect);
+
+private:
+ QWaylandReadbackEglIntegration *mEglIntegration;
+ QWaylandReadbackEglContext *mContext;
+};
+
+#endif // QWAYLANDREADBACKEGLWINDOW_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri b/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri
new file mode 100644
index 0000000..0d8e01b
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_egl/readback_egl.pri
@@ -0,0 +1,14 @@
+
+LIBS += -lX11 -lXext -lEGL
+
+HEADERS += \
+ $$PWD/qwaylandreadbackeglintegration.h \
+ $$PWD/qwaylandreadbackeglcontext.h \
+ $$PWD/qwaylandreadbackeglwindow.h \
+ $$PWD/../../../eglconvenience/qeglconvenience.h
+
+SOURCES += \
+ $$PWD/qwaylandreadbackeglintegration.cpp \
+ $$PWD/qwaylandreadbackeglwindow.cpp \
+ $$PWD/qwaylandreadbackeglcontext.cpp \
+ $$PWD/../../../eglconvenience/qeglconvenience.cpp
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp
new file mode 100644
index 0000000..08c5cf6c
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackglxcontext.h"
+
+#include "qwaylandshmsurface.h"
+#include "qwaylandreadbackglxwindow.h"
+
+#include <QtCore/QDebug>
+
+static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
+{
+ const int width = img.width();
+ const int height = img.height();
+
+ if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
+ || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
+ {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+ } else {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
+ }
+ }
+}
+
+QWaylandReadbackGlxContext::QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window)
+ : QPlatformGLContext()
+ , mGlxIntegration(glxIntegration)
+ , mWindow(window)
+ , mBuffer(0)
+ , mPixmap(0)
+ , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->widget()->platformWindowFormat(),GLX_PIXMAP_BIT))
+ , mGlxPixmap(0)
+{
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig);
+ mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE);
+
+ geometryChanged();
+}
+
+void QWaylandReadbackGlxContext::makeCurrent()
+{
+ QPlatformGLContext::makeCurrent();
+
+ glXMakeCurrent(mGlxIntegration->xDisplay(),mGlxPixmap,mContext);
+}
+
+void QWaylandReadbackGlxContext::doneCurrent()
+{
+ QPlatformGLContext::doneCurrent();
+}
+
+void QWaylandReadbackGlxContext::swapBuffers()
+{
+ if (QPlatformGLContext::currentContext() != this) {
+ makeCurrent();
+ }
+
+ QSize size = mWindow->geometry().size();
+
+ QImage img(size,QImage::Format_ARGB32);
+ const uchar *constBits = img.bits();
+ void *pixels = const_cast<uchar *>(constBits);
+
+ glReadPixels(0,0, size.width(), size.height(), GL_RGBA,GL_UNSIGNED_BYTE, pixels);
+
+ img = img.mirrored();
+ qgl_byteSwapImage(img,GL_UNSIGNED_INT_8_8_8_8_REV);
+ constBits = img.bits();
+
+ const uchar *constDstBits = mBuffer->image()->bits();
+ uchar *dstBits = const_cast<uchar *>(constDstBits);
+ memcpy(dstBits,constBits,(img.width()*4) * img.height());
+
+
+ mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
+ mWindow->waitForFrameSync();
+
+}
+
+void * QWaylandReadbackGlxContext::getProcAddress(const QString &procName)
+{
+ return (void *) glXGetProcAddress(reinterpret_cast<GLubyte *>(procName.toLatin1().data()));
+}
+
+QPlatformWindowFormat QWaylandReadbackGlxContext::platformWindowFormat() const
+{
+ return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext);
+}
+
+void QWaylandReadbackGlxContext::geometryChanged()
+{
+ QSize size(mWindow->geometry().size());
+ if (size.isEmpty()) {
+ //QGLWidget wants a context for a window without geometry
+ size = QSize(1,1);
+ }
+
+ mWindow->waitForFrameSync();
+
+ delete mBuffer;
+ //XFreePixmap deletes the glxPixmap as well
+ if (mPixmap) {
+ XFreePixmap(mGlxIntegration->xDisplay(),mPixmap);
+ }
+
+ mBuffer = new QWaylandShmBuffer(mGlxIntegration->waylandDisplay(),size,QImage::Format_ARGB32);
+ mWindow->attach(mBuffer);
+ int depth = XDefaultDepth(mGlxIntegration->xDisplay(),mGlxIntegration->screen());
+ mPixmap = XCreatePixmap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),size.width(),size.height(),depth);
+ XSync(mGlxIntegration->xDisplay(),False);
+
+ mGlxPixmap = glXCreatePixmap(mGlxIntegration->xDisplay(),mConfig,mPixmap,0);
+
+ if (!mGlxPixmap) {
+ qDebug() << "Could not make egl surface out of pixmap :(";
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h
new file mode 100644
index 0000000..5fafcf0
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKGLXCONTEXT_H
+#define QWAYLANDREADBACKGLXCONTEXT_H
+
+#include <QPlatformGLContext>
+
+#include "qwaylandreadbackglxintegration.h"
+
+#include "qglxconvenience.h"
+
+class QWaylandReadbackGlxWindow;
+class QWaylandShmBuffer;
+
+class QWaylandReadbackGlxContext : public QPlatformGLContext
+{
+public:
+ QWaylandReadbackGlxContext(QWaylandReadbackGlxIntegration *glxIntegration, QWaylandReadbackGlxWindow *window);
+
+ void makeCurrent();
+ void doneCurrent();
+ void swapBuffers();
+ void* getProcAddress(const QString& procName);
+
+ QPlatformWindowFormat platformWindowFormat() const;
+
+ void geometryChanged();
+
+private:
+ QWaylandReadbackGlxIntegration *mGlxIntegration;
+ QWaylandReadbackGlxWindow *mWindow;
+ QWaylandShmBuffer *mBuffer;
+
+ Pixmap mPixmap;
+ GLXFBConfig mConfig;
+ GLXContext mContext;
+ GLXPixmap mGlxPixmap;
+};
+
+#endif // QWAYLANDREADBACKGLXCONTEXT_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp
new file mode 100644
index 0000000..4651f0c
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackglxintegration.h"
+
+#include "qwaylandreadbackglxwindow.h"
+
+#include <QtCore/QDebug>
+
+QWaylandReadbackGlxIntegration::QWaylandReadbackGlxIntegration(QWaylandDisplay * waylandDispaly)
+ : QWaylandGLIntegration()
+ , mWaylandDisplay(waylandDispaly)
+{
+ qDebug() << "Using Readback-GLX";
+ char *display_name = getenv("DISPLAY");
+ mDisplay = XOpenDisplay(display_name);
+ mScreen = XDefaultScreen(mDisplay);
+ mRootWindow = XDefaultRootWindow(mDisplay);
+ XSync(mDisplay, False);
+}
+
+QWaylandReadbackGlxIntegration::~QWaylandReadbackGlxIntegration()
+{
+ XCloseDisplay(mDisplay);
+}
+
+void QWaylandReadbackGlxIntegration::initialize()
+{
+}
+
+QWaylandWindow * QWaylandReadbackGlxIntegration::createEglWindow(QWidget *widget)
+{
+ return new QWaylandReadbackGlxWindow(widget,this);
+}
+
+QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay)
+{
+ return new QWaylandReadbackGlxIntegration(waylandDisplay);
+}
+
+Display * QWaylandReadbackGlxIntegration::xDisplay() const
+{
+ return mDisplay;
+}
+
+int QWaylandReadbackGlxIntegration::screen() const
+{
+ return mScreen;
+}
+
+Window QWaylandReadbackGlxIntegration::rootWindow() const
+{
+ return mRootWindow;
+}
+
+QWaylandDisplay * QWaylandReadbackGlxIntegration::waylandDisplay() const
+{
+ return mWaylandDisplay;
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h
new file mode 100644
index 0000000..9056393
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKGLXINTEGRATION_H
+#define QWAYLANDREADBACKGLXINTEGRATION_H
+
+#include "gl_integration/qwaylandglintegration.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDataStream>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+
+#include <X11/Xlib.h>
+
+class QWaylandReadbackGlxIntegration : public QWaylandGLIntegration
+{
+public:
+ QWaylandReadbackGlxIntegration(QWaylandDisplay * waylandDispaly);
+ ~QWaylandReadbackGlxIntegration();
+
+ void initialize();
+
+ QWaylandWindow *createEglWindow(QWidget *widget);
+
+ QWaylandDisplay *waylandDisplay() const;
+
+ Display *xDisplay() const;
+ int screen() const;
+ Window rootWindow() const;
+
+private:
+ QWaylandDisplay *mWaylandDisplay;
+
+ Display *mDisplay;
+ int mScreen;
+ Window mRootWindow;
+
+};
+
+#endif // QWAYLANDREADBACKGLXINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp
new file mode 100644
index 0000000..ca1603c
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandreadbackglxwindow.h"
+
+QWaylandReadbackGlxWindow::QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration)
+ : QWaylandShmWindow(window)
+ , mGlxIntegration(glxIntegration)
+ , mContext(0)
+{
+}
+
+QWaylandWindow::WindowType QWaylandReadbackGlxWindow::windowType() const
+{
+ //yeah. this type needs a new name
+ return QWaylandWindow::Egl;
+}
+
+QPlatformGLContext * QWaylandReadbackGlxWindow::glContext() const
+{
+ if (!mContext) {
+ QWaylandReadbackGlxWindow *that = const_cast<QWaylandReadbackGlxWindow *>(this);
+ that->mContext = new QWaylandReadbackGlxContext(mGlxIntegration,that);
+ }
+ return mContext;
+}
+
+void QWaylandReadbackGlxWindow::setGeometry(const QRect &rect)
+{
+ QWaylandShmWindow::setGeometry(rect);
+
+ if (mContext) {
+ mContext->geometryChanged();
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h
new file mode 100644
index 0000000..4d7bb3e
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxwindow.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDREADBACKGLXWINDOW_H
+#define QWAYLANDREADBACKGLXWINDOW_H
+
+#include "qwaylandshmwindow.h"
+#include "qwaylandreadbackglxintegration.h"
+#include "qwaylandreadbackglxcontext.h"
+
+class QWaylandReadbackGlxWindow : public QWaylandShmWindow
+{
+public:
+ QWaylandReadbackGlxWindow(QWidget *window, QWaylandReadbackGlxIntegration *glxIntegration);
+ WindowType windowType() const;
+
+ QPlatformGLContext *glContext() const;
+
+ void setGeometry(const QRect &rect);
+
+private:
+ QWaylandReadbackGlxIntegration *mGlxIntegration;
+ QWaylandReadbackGlxContext *mContext;
+
+};
+
+#endif // QWAYLANDREADBACKGLXWINDOW_H
diff --git a/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri
new file mode 100644
index 0000000..f8ea005
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/readback_glx/readback_glx.pri
@@ -0,0 +1,12 @@
+include (../../../glxconvenience/glxconvenience.pri)
+HEADERS += \
+ $$PWD/qwaylandreadbackglxintegration.h \
+ $$PWD/qwaylandreadbackglxwindow.h \
+ $$PWD/qwaylandreadbackglxcontext.h
+
+SOURCES += \
+ $$PWD/qwaylandreadbackglxintegration.cpp \
+ $$PWD/qwaylandreadbackglxwindow.cpp \
+ $$PWD/qwaylandreadbackglxcontext.cpp
+
+LIBS += -lX11
diff --git a/src/plugins/platforms/wayland/qwaylandinclude.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglinclude.h
index 0135251..5dc2add 100644
--- a/src/plugins/platforms/wayland/qwaylandinclude.h
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglinclude.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,12 +39,11 @@
**
****************************************************************************/
-#ifndef QWAYLANDINCLUDE_H
-#define QWAYLANDINCLUDE_H
+#ifndef QWAYLANDEGLINCLUDE_H
+#define QWAYLANDEGLINCLUDE_H
#include <wayland-client.h>
-#ifdef QT_WAYLAND_GL_SUPPORT
#include <wayland-egl.h>
#define GL_GLEXT_PROTOTYPES
@@ -52,12 +51,7 @@
#include <GLES2/gl2ext.h>
#define EGL_EGLEXT_PROTOTYPES
- #include <EGL/egl.h>
- #include <EGL/eglext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
-#else
-typedef void* EGLDisplay;
-typedef void* EGLConfig;
-#endif
-
-#endif // QWAYLANDINCLUDE_H
+#endif // QWAYLANDEGLINCLUDE_H
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp
new file mode 100644
index 0000000..ddd1763
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandeglintegration.h"
+
+#include "gl_integration/qwaylandglintegration.h"
+
+#include "qwaylandeglwindow.h"
+
+#include <QtCore/QDebug>
+
+QWaylandEglIntegration::QWaylandEglIntegration(struct wl_display *waylandDisplay)
+ : mWaylandDisplay(waylandDisplay)
+{
+ qDebug() << "Using Wayland-EGL";
+}
+
+
+QWaylandEglIntegration::~QWaylandEglIntegration()
+{
+ eglTerminate(mEglDisplay);
+}
+
+void QWaylandEglIntegration::initialize()
+{
+ EGLint major,minor;
+ mEglDisplay = eglGetDisplay(mWaylandDisplay);
+ if (mEglDisplay == NULL) {
+ qWarning("EGL not available");
+ } else {
+ if (!eglInitialize(mEglDisplay, &major, &minor)) {
+ qWarning("failed to initialize EGL display");
+ return;
+ }
+ }
+}
+
+QWaylandWindow *QWaylandEglIntegration::createEglWindow(QWidget *window)
+{
+ return new QWaylandEglWindow(window);
+}
+
+EGLDisplay QWaylandEglIntegration::eglDisplay() const
+{
+ return mEglDisplay;
+}
+
+QWaylandGLIntegration *QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay)
+{
+ return new QWaylandEglIntegration(waylandDisplay->wl_display());
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h
new file mode 100644
index 0000000..3a26f97
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDEGLINTEGRATION_H
+#define QWAYLANDEGLINTEGRATION_H
+
+#include "gl_integration/qwaylandglintegration.h"
+
+#include "qwaylandeglinclude.h"
+
+class QWaylandWindow;
+class QWidget;
+
+class QWaylandEglIntegration : public QWaylandGLIntegration
+{
+public:
+ QWaylandEglIntegration(struct wl_display *waylandDisplay);
+ ~QWaylandEglIntegration();
+
+ void initialize();
+
+ QWaylandWindow *createEglWindow(QWidget *window);
+
+ EGLDisplay eglDisplay() const;
+ struct wl_egl_display *nativeDisplay() const;
+private:
+ struct wl_display *mWaylandDisplay;
+
+ EGLDisplay mEglDisplay;
+};
+
+#endif // QWAYLANDEGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
index ed54bb9..cf52f39 100644
--- a/src/plugins/platforms/wayland/qwaylandeglwindow.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.cpp
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -43,21 +43,20 @@
#include "qwaylandscreen.h"
#include "qwaylandglcontext.h"
-#include "qwaylandinclude.h"
QWaylandEglWindow::QWaylandEglWindow(QWidget *window)
: QWaylandWindow(window)
, mGLContext(0)
, mWaylandEglWindow(0)
{
+ mEglIntegration = static_cast<QWaylandEglIntegration *>(mDisplay->eglIntegration());
//super creates a new surface
newSurfaceCreated();
}
QWaylandEglWindow::~QWaylandEglWindow()
{
- if (mGLContext)
- delete mGLContext;
+ delete mGLContext;
}
QWaylandWindow::WindowType QWaylandEglWindow::windowType() const
@@ -84,10 +83,10 @@ QPlatformGLContext * QWaylandEglWindow::glContext() const
{
if (!mGLContext) {
QWaylandEglWindow *that = const_cast<QWaylandEglWindow *>(this);
- that->mGLContext = new QWaylandGLContext(that->mDisplay,widget()->platformWindowFormat());
+ that->mGLContext = new QWaylandGLContext(mEglIntegration->eglDisplay(),widget()->platformWindowFormat());
EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow));
- EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL);
+ EGLSurface surface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mGLContext->eglConfig(),window,NULL);
that->mGLContext->setEglSurface(surface);
}
@@ -104,10 +103,10 @@ void QWaylandEglWindow::newSurfaceCreated()
if (!size.isValid())
size = QSize(0,0);
- mWaylandEglWindow = wl_egl_window_create(mDisplay->nativeDisplay(),mSurface,size.width(),size.height(),visual);
+ mWaylandEglWindow = wl_egl_window_create(mSurface,size.width(),size.height(),visual);
if (mGLContext) {
EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow));
- EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL);
+ EGLSurface surface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mGLContext->eglConfig(),window,NULL);
mGLContext->setEglSurface(surface);
}
}
diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h
index 4b3bb5b..856321d 100644
--- a/src/plugins/platforms/wayland/qwaylandeglwindow.h
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglwindow.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -43,6 +43,8 @@
#define QWAYLANDEGLWINDOW_H
#include "qwaylandwindow.h"
+#include "qwaylandeglinclude.h"
+#include "qwaylandeglintegration.h"
class QWaylandGLContext;
@@ -58,9 +60,9 @@ public:
protected:
void newSurfaceCreated();
private:
+ QWaylandEglIntegration *mEglIntegration;
QWaylandGLContext *mGLContext;
struct wl_egl_window *mWaylandEglWindow;
- EGLConfig mConfig;
const QWaylandWindow *mParentWindow;
};
diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp
index 3720567..d293019 100644
--- a/src/plugins/platforms/wayland/qwaylandglcontext.cpp
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp
@@ -43,37 +43,22 @@
#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
-#include "qwaylanddrmsurface.h"
-#include "../eglconvenience/qeglconvenience.h"
+#include "../../../eglconvenience/qeglconvenience.h"
#include <QtGui/QPlatformGLContext>
#include <QtGui/QPlatformWindowFormat>
+#include <QtCore/QMutex>
-Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex)
-
-QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format)
+QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QPlatformWindowFormat &format)
: QPlatformGLContext()
- , mDisplay(wd)
+ , mEglDisplay(eglDisplay)
, mSurface(EGL_NO_SURFACE)
- , mConfig(q_configFromQPlatformWindowFormat(mDisplay->eglDisplay(),format,true))
- , mFormat(qt_qPlatformWindowFormatFromConfig(mDisplay->eglDisplay(),mConfig))
+ , mConfig(q_configFromQPlatformWindowFormat(mEglDisplay,format,true))
+ , mFormat(qt_qPlatformWindowFormatFromConfig(mEglDisplay,mConfig))
{
QPlatformGLContext *sharePlatformContext = 0;
- if (format.useDefaultSharedContext()) {
- if (!QPlatformGLContext::defaultSharedContext()) {
- if (qt_defaultSharedContextMutex()->tryLock()){
- createDefaultSharedContex(wd);
- qt_defaultSharedContextMutex()->unlock();
- } else {
- qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created
- qt_defaultSharedContextMutex()->unlock();
- }
- }
- sharePlatformContext = QPlatformGLContext::defaultSharedContext();
- } else {
- sharePlatformContext = format.sharedGLContext();
- }
+ sharePlatformContext = format.sharedGLContext();
mFormat.setSharedContext(sharePlatformContext);
EGLContext shareEGLContext = EGL_NO_CONTEXT;
if (sharePlatformContext)
@@ -86,13 +71,13 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowF
eglContextAttrs.append(2);
eglContextAttrs.append(EGL_NONE);
- mContext = eglCreateContext(mDisplay->eglDisplay(), mConfig,
+ mContext = eglCreateContext(mEglDisplay, mConfig,
shareEGLContext, eglContextAttrs.constData());
}
QWaylandGLContext::QWaylandGLContext()
: QPlatformGLContext()
- , mDisplay(0)
+ , mEglDisplay(0)
, mContext(EGL_NO_CONTEXT)
, mSurface(EGL_NO_SURFACE)
, mConfig(0)
@@ -100,7 +85,7 @@ QWaylandGLContext::QWaylandGLContext()
QWaylandGLContext::~QWaylandGLContext()
{
- eglDestroyContext(mDisplay->eglDisplay(),mContext);
+ eglDestroyContext(mEglDisplay,mContext);
}
void QWaylandGLContext::makeCurrent()
@@ -109,18 +94,18 @@ void QWaylandGLContext::makeCurrent()
if (mSurface == EGL_NO_SURFACE) {
qWarning("makeCurrent with EGL_NO_SURFACE");
}
- eglMakeCurrent(mDisplay->eglDisplay(), mSurface, mSurface, mContext);
+ eglMakeCurrent(mEglDisplay, mSurface, mSurface, mContext);
}
void QWaylandGLContext::doneCurrent()
{
QPlatformGLContext::doneCurrent();
- eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
void QWaylandGLContext::swapBuffers()
{
- eglSwapBuffers(mDisplay->eglDisplay(),mSurface);
+ eglSwapBuffers(mEglDisplay,mSurface);
}
void *QWaylandGLContext::getProcAddress(const QString &string)
@@ -128,20 +113,6 @@ void *QWaylandGLContext::getProcAddress(const QString &string)
return (void *) eglGetProcAddress(string.toLatin1().data());
}
-void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display)
-{
- QVector<EGLint> eglContextAttrs;
- eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
- eglContextAttrs.append(2);
- eglContextAttrs.append(EGL_NONE);
-
- QWaylandGLContext *defaultSharedContext = new QWaylandGLContext;
- defaultSharedContext->mDisplay = display;
- defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(),mConfig,
- EGL_NO_CONTEXT, eglContextAttrs.constData());
- QPlatformGLContext::setDefaultSharedContext(defaultSharedContext);
-}
-
void QWaylandGLContext::setEglSurface(EGLSurface surface)
{
doneCurrent();
diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h
index dd319fd..76caffa 100644
--- a/src/plugins/platforms/wayland/qwaylandglcontext.h
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h
@@ -46,14 +46,14 @@
#include <QtGui/QPlatformGLContext>
-class QWaylandWindow;
-class QWaylandDrmWindowSurface;
+#include "qwaylandeglinclude.h"
-#include "qwaylandinclude.h"
+class QWaylandWindow;
+class QWaylandGLWindowSurface;
class QWaylandGLContext : public QPlatformGLContext {
public:
- QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format);
+ QWaylandGLContext(EGLDisplay eglDisplay, const QPlatformWindowFormat &format);
~QWaylandGLContext();
void makeCurrent();
void doneCurrent();
@@ -65,14 +65,13 @@ public:
void setEglSurface(EGLSurface surface);
EGLConfig eglConfig() const;
private:
- QWaylandDisplay *mDisplay;
+ EGLDisplay mEglDisplay;
EGLContext mContext;
EGLSurface mSurface;
EGLConfig mConfig;
QPlatformWindowFormat mFormat;
- void createDefaultSharedContex(QWaylandDisplay *display);
QWaylandGLContext();
};
diff --git a/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri
new file mode 100644
index 0000000..cd07011
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/wayland_egl/wayland_egl.pri
@@ -0,0 +1,11 @@
+include (../../../eglconvenience/eglconvenience.pri)
+
+LIBS += -lwayland-egl -lEGL
+INCLUDEPATH += $$PWD
+SOURCES += $$PWD/qwaylandeglintegration.cpp \
+ $$PWD/qwaylandglcontext.cpp \
+ $$PWD/qwaylandeglwindow.cpp
+
+HEADERS += $$PWD/qwaylandeglintegration.h \
+ $$PWD/qwaylandglcontext.h \
+ $$PWD/qwaylandeglwindow.h
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp
new file mode 100644
index 0000000..92acf75
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeeglcontext.h"
+
+#include "qwaylandxcompositeeglwindow.h"
+#include "qwaylandxcompositebuffer.h"
+
+#include "wayland-xcomposite-client-protocol.h"
+#include <QtCore/QDebug>
+
+#include "qeglconvenience.h"
+#include "qxlibeglintegration.h"
+
+#include <X11/extensions/Xcomposite.h>
+
+QWaylandXCompositeEGLContext::QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window)
+ : QPlatformGLContext()
+ , mEglIntegration(glxIntegration)
+ , mWindow(window)
+ , mBuffer(0)
+ , mXWindow(0)
+ , mConfig(q_configFromQPlatformWindowFormat(glxIntegration->eglDisplay(),window->widget()->platformWindowFormat(),true,EGL_WINDOW_BIT))
+ , mWaitingForSync(false)
+{
+ QVector<EGLint> eglContextAttrs;
+ eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); eglContextAttrs.append(2);
+ eglContextAttrs.append(EGL_NONE);
+
+ mContext = eglCreateContext(glxIntegration->eglDisplay(),mConfig,EGL_NO_CONTEXT,eglContextAttrs.constData());
+ if (mContext == EGL_NO_CONTEXT) {
+ qFatal("failed to find context");
+ }
+
+ geometryChanged();
+}
+
+void QWaylandXCompositeEGLContext::makeCurrent()
+{
+ QPlatformGLContext::makeCurrent();
+
+ eglMakeCurrent(mEglIntegration->eglDisplay(),mEglWindowSurface,mEglWindowSurface,mContext);
+}
+
+void QWaylandXCompositeEGLContext::doneCurrent()
+{
+ QPlatformGLContext::doneCurrent();
+ eglMakeCurrent(mEglIntegration->eglDisplay(),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
+}
+
+void QWaylandXCompositeEGLContext::swapBuffers()
+{
+ QSize size = mWindow->geometry().size();
+
+ eglSwapBuffers(mEglIntegration->eglDisplay(),mEglWindowSurface);
+ mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
+ mWindow->waitForFrameSync();
+}
+
+void * QWaylandXCompositeEGLContext::getProcAddress(const QString &procName)
+{
+ return (void *)eglGetProcAddress(qPrintable(procName));
+}
+
+QPlatformWindowFormat QWaylandXCompositeEGLContext::platformWindowFormat() const
+{
+ return qt_qPlatformWindowFormatFromConfig(mEglIntegration->eglDisplay(),mConfig);
+}
+
+void QWaylandXCompositeEGLContext::sync_function(void *data)
+{
+ QWaylandXCompositeEGLContext *that = static_cast<QWaylandXCompositeEGLContext *>(data);
+ that->mWaitingForSync = false;
+}
+
+void QWaylandXCompositeEGLContext::geometryChanged()
+{
+ QSize size(mWindow->geometry().size());
+ if (size.isEmpty()) {
+ //QGLWidget wants a context for a window without geometry
+ size = QSize(1,1);
+ }
+
+ delete mBuffer;
+ //XFreePixmap deletes the glxPixmap as well
+ if (mXWindow) {
+ XDestroyWindow(mEglIntegration->xDisplay(),mXWindow);
+ }
+
+ VisualID visualId = QXlibEglIntegration::getCompatibleVisualId(mEglIntegration->xDisplay(),mEglIntegration->eglDisplay(),mConfig);
+
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ visualInfoTemplate.visualid = visualId;
+
+ int matchingCount = 0;
+ XVisualInfo *visualInfo = XGetVisualInfo(mEglIntegration->xDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount);
+
+ Colormap cmap = XCreateColormap(mEglIntegration->xDisplay(),mEglIntegration->rootWindow(),visualInfo->visual,AllocNone);
+
+ XSetWindowAttributes a;
+ a.colormap = cmap;
+ mXWindow = XCreateWindow(mEglIntegration->xDisplay(), mEglIntegration->rootWindow(),0, 0, size.width(), size.height(),
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWColormap, &a);
+
+ XCompositeRedirectWindow(mEglIntegration->xDisplay(), mXWindow, CompositeRedirectManual);
+ XMapWindow(mEglIntegration->xDisplay(), mXWindow);
+
+ mEglWindowSurface = eglCreateWindowSurface(mEglIntegration->eglDisplay(),mConfig,mXWindow,0);
+ if (mEglWindowSurface == EGL_NO_SURFACE) {
+ qFatal("Could not make eglsurface");
+ }
+
+ XSync(mEglIntegration->xDisplay(),False);
+ mBuffer = new QWaylandXCompositeBuffer(mEglIntegration->waylandXComposite(),
+ (uint32_t)mXWindow,
+ size,
+ mEglIntegration->waylandDisplay()->argbVisual());
+ mWindow->attach(mBuffer);
+ wl_display_sync_callback(mEglIntegration->waylandDisplay()->wl_display(),
+ QWaylandXCompositeEGLContext::sync_function,
+ this);
+
+ mWaitingForSync = true;
+ wl_display_sync(mEglIntegration->waylandDisplay()->wl_display(),0);
+ mEglIntegration->waylandDisplay()->flushRequests();
+ while (mWaitingForSync) {
+ mEglIntegration->waylandDisplay()->readEvents();
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h
new file mode 100644
index 0000000..f0693d4
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEEGLCONTEXT_H
+#define QWAYLANDXCOMPOSITEEGLCONTEXT_H
+
+#include <QtGui/QPlatformGLContext>
+
+#include <QtCore/QWaitCondition>
+
+#include "qwaylandbuffer.h"
+#include "qwaylandxcompositeeglintegration.h"
+
+class QWaylandXCompositeEGLWindow;
+
+class QWaylandXCompositeEGLContext : public QPlatformGLContext
+{
+public:
+ QWaylandXCompositeEGLContext(QWaylandXCompositeEGLIntegration *glxIntegration, QWaylandXCompositeEGLWindow *window);
+
+ void makeCurrent();
+ void doneCurrent();
+ void swapBuffers();
+ void* getProcAddress(const QString& procName);
+
+ QPlatformWindowFormat platformWindowFormat() const;
+
+ void geometryChanged();
+
+private:
+ QWaylandXCompositeEGLIntegration *mEglIntegration;
+ QWaylandXCompositeEGLWindow *mWindow;
+ QWaylandBuffer *mBuffer;
+
+ Window mXWindow;
+ EGLConfig mConfig;
+ EGLContext mContext;
+ EGLSurface mEglWindowSurface;
+
+ static void sync_function(void *data);
+ bool mWaitingForSync;
+};
+
+#endif // QWAYLANDXCOMPOSITEEGLCONTEXT_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp
new file mode 100644
index 0000000..7537b52
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeeglintegration.h"
+
+#include "qwaylandxcompositeeglwindow.h"
+
+#include <QtCore/QDebug>
+
+#include "wayland-xcomposite-client-protocol.h"
+
+QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay)
+{
+ return new QWaylandXCompositeEGLIntegration(waylandDisplay);
+}
+
+QWaylandXCompositeEGLIntegration::QWaylandXCompositeEGLIntegration(QWaylandDisplay * waylandDispaly)
+ : QWaylandGLIntegration()
+ , mWaylandDisplay(waylandDispaly)
+{
+ qDebug() << "Using XComposite-EGL";
+ wl_display_add_global_listener(mWaylandDisplay->wl_display(), QWaylandXCompositeEGLIntegration::wlDisplayHandleGlobal,
+ this);
+}
+
+QWaylandXCompositeEGLIntegration::~QWaylandXCompositeEGLIntegration()
+{
+ XCloseDisplay(mDisplay);
+}
+
+void QWaylandXCompositeEGLIntegration::initialize()
+{
+}
+
+QWaylandWindow * QWaylandXCompositeEGLIntegration::createEglWindow(QWidget *widget)
+{
+ return new QWaylandXCompositeEGLWindow(widget,this);
+}
+
+Display * QWaylandXCompositeEGLIntegration::xDisplay() const
+{
+ return mDisplay;
+}
+
+EGLDisplay QWaylandXCompositeEGLIntegration::eglDisplay() const
+{
+ return mEglDisplay;
+}
+
+int QWaylandXCompositeEGLIntegration::screen() const
+{
+ return mScreen;
+}
+
+Window QWaylandXCompositeEGLIntegration::rootWindow() const
+{
+ return mRootWindow;
+}
+
+QWaylandDisplay * QWaylandXCompositeEGLIntegration::waylandDisplay() const
+{
+ return mWaylandDisplay;
+}
+wl_xcomposite * QWaylandXCompositeEGLIntegration::waylandXComposite() const
+{
+ return mWaylandComposite;
+}
+
+const struct wl_xcomposite_listener QWaylandXCompositeEGLIntegration::xcomposite_listener = {
+ QWaylandXCompositeEGLIntegration::rootInformation
+};
+
+void QWaylandXCompositeEGLIntegration::wlDisplayHandleGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data)
+{
+ Q_UNUSED(version);
+ if (strcmp(interface, "wl_xcomposite") == 0) {
+ QWaylandXCompositeEGLIntegration *integration = static_cast<QWaylandXCompositeEGLIntegration *>(data);
+ integration->mWaylandComposite = wl_xcomposite_create(display,id,1);
+ wl_xcomposite_add_listener(integration->mWaylandComposite,&xcomposite_listener,integration);
+ }
+
+}
+
+void QWaylandXCompositeEGLIntegration::rootInformation(void *data, wl_xcomposite *xcomposite, const char *display_name, uint32_t root_window)
+{
+ Q_UNUSED(xcomposite);
+ QWaylandXCompositeEGLIntegration *integration = static_cast<QWaylandXCompositeEGLIntegration *>(data);
+
+ integration->mDisplay = XOpenDisplay(display_name);
+ integration->mRootWindow = (Window) root_window;
+ integration->mScreen = XDefaultScreen(integration->mDisplay);
+ integration->mEglDisplay = eglGetDisplay(integration->mDisplay);
+ eglBindAPI(EGL_OPENGL_ES_API);
+ EGLint minor,major;
+ if (!eglInitialize(integration->mEglDisplay,&major,&minor)) {
+ qFatal("Failed to initialize EGL");
+ }
+ eglSwapInterval(integration->eglDisplay(),0);
+ qDebug() << "ROOT INFORMATION" << integration->mDisplay << integration->mRootWindow << integration->mScreen;
+}
+
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h
new file mode 100644
index 0000000..590ae37
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEEGLINTEGRATION_H
+#define QWAYLANDXCOMPOSITEEGLINTEGRATION_H
+
+#include "gl_integration/qwaylandglintegration.h"
+#include "wayland-client.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDataStream>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+
+#include <QWaitCondition>
+
+#include <X11/Xlib.h>
+#include <EGL/egl.h>
+
+struct wl_xcomposite;
+
+class QWaylandXCompositeEGLIntegration : public QWaylandGLIntegration
+{
+public:
+ QWaylandXCompositeEGLIntegration(QWaylandDisplay * waylandDispaly);
+ ~QWaylandXCompositeEGLIntegration();
+
+ void initialize();
+
+ QWaylandWindow *createEglWindow(QWidget *widget);
+
+ QWaylandDisplay *waylandDisplay() const;
+ struct wl_xcomposite *waylandXComposite() const;
+
+ Display *xDisplay() const;
+ EGLDisplay eglDisplay() const;
+ int screen() const;
+ Window rootWindow() const;
+
+private:
+ QWaylandDisplay *mWaylandDisplay;
+ struct wl_xcomposite *mWaylandComposite;
+
+ Display *mDisplay;
+ EGLDisplay mEglDisplay;
+ int mScreen;
+ Window mRootWindow;
+
+ static void wlDisplayHandleGlobal(struct wl_display *display, uint32_t id,
+ const char *interface, uint32_t version, void *data);
+
+ static const struct wl_xcomposite_listener xcomposite_listener;
+ static void rootInformation(void *data,
+ struct wl_xcomposite *xcomposite,
+ const char *display_name,
+ uint32_t root_window);
+};
+
+#endif // QWAYLANDXCOMPOSITEEGLINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp
new file mode 100644
index 0000000..1c9d36f
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeeglwindow.h"
+
+#include <QtCore/QDebug>
+
+QWaylandXCompositeEGLWindow::QWaylandXCompositeEGLWindow(QWidget *window, QWaylandXCompositeEGLIntegration *glxIntegration)
+ : QWaylandWindow(window)
+ , mGlxIntegration(glxIntegration)
+ , mContext(0)
+{
+
+}
+
+QWaylandWindow::WindowType QWaylandXCompositeEGLWindow::windowType() const
+{
+ //yeah. this type needs a new name
+ return QWaylandWindow::Egl;
+}
+
+QPlatformGLContext * QWaylandXCompositeEGLWindow::glContext() const
+{
+ if (!mContext) {
+ qDebug() << "creating glcontext;";
+ QWaylandXCompositeEGLWindow *that = const_cast<QWaylandXCompositeEGLWindow *>(this);
+ that->mContext = new QWaylandXCompositeEGLContext(mGlxIntegration,that);
+ }
+ return mContext;
+}
+
+void QWaylandXCompositeEGLWindow::setGeometry(const QRect &rect)
+{
+ QWaylandWindow::setGeometry(rect);
+
+ if (mContext) {
+ mContext->geometryChanged();
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h
new file mode 100644
index 0000000..fc33b32
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEEGLWINDOW_H
+#define QWAYLANDXCOMPOSITEEGLWINDOW_H
+
+#include "qwaylandwindow.h"
+#include "qwaylandxcompositeeglintegration.h"
+#include "qwaylandxcompositeeglcontext.h"
+
+class QWaylandXCompositeEGLWindow : public QWaylandWindow
+{
+public:
+ QWaylandXCompositeEGLWindow(QWidget *window, QWaylandXCompositeEGLIntegration *glxIntegration);
+ WindowType windowType() const;
+
+ QPlatformGLContext *glContext() const;
+
+ void setGeometry(const QRect &rect);
+
+private:
+ QWaylandXCompositeEGLIntegration *mGlxIntegration;
+ QWaylandXCompositeEGLContext *mContext;
+
+};
+
+#endif // QWAYLANDXCOMPOSITEEGLWINDOW_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri
new file mode 100644
index 0000000..c3533f9
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/xcomposite_egl.pri
@@ -0,0 +1,15 @@
+include (../xcomposite_share/xcomposite_share.pri)
+include (../../../eglconvenience/eglconvenience.pri)
+include (../../../eglconvenience/xlibeglintegration.pri)
+
+LIBS += -lXcomposite -lEGL
+
+SOURCES += \
+ $$PWD/qwaylandxcompositeeglcontext.cpp \
+ $$PWD/qwaylandxcompositeeglintegration.cpp \
+ $$PWD/qwaylandxcompositeeglwindow.cpp
+
+HEADERS += \
+ $$PWD/qwaylandxcompositeeglcontext.h \
+ $$PWD/qwaylandxcompositeeglintegration.h \
+ $$PWD/qwaylandxcompositeeglwindow.h
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp
new file mode 100644
index 0000000..caf5117
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeglxcontext.h"
+
+#include "qwaylandxcompositeglxwindow.h"
+#include "qwaylandxcompositebuffer.h"
+
+#include "wayland-xcomposite-client-protocol.h"
+#include <QtCore/QDebug>
+
+#include <X11/extensions/Xcomposite.h>
+
+QWaylandXCompositeGLXContext::QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window)
+ : QPlatformGLContext()
+ , mGlxIntegration(glxIntegration)
+ , mWindow(window)
+ , mBuffer(0)
+ , mXWindow(0)
+ , mConfig(qglx_findConfig(glxIntegration->xDisplay(),glxIntegration->screen(),window->widget()->platformWindowFormat()))
+ , mWaitingForSyncCallback(false)
+{
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(glxIntegration->xDisplay(),mConfig);
+ mContext = glXCreateContext(glxIntegration->xDisplay(),visualInfo,0,TRUE);
+
+ geometryChanged();
+}
+
+void QWaylandXCompositeGLXContext::makeCurrent()
+{
+ QPlatformGLContext::makeCurrent();
+ glXMakeCurrent(mGlxIntegration->xDisplay(),mXWindow,mContext);
+}
+
+void QWaylandXCompositeGLXContext::doneCurrent()
+{
+ glXMakeCurrent(mGlxIntegration->xDisplay(),0,0);
+ QPlatformGLContext::doneCurrent();
+}
+
+void QWaylandXCompositeGLXContext::swapBuffers()
+{
+ QSize size = mWindow->geometry().size();
+
+ glXSwapBuffers(mGlxIntegration->xDisplay(),mXWindow);
+ mWindow->damage(QRegion(QRect(QPoint(0,0),size)));
+ mWindow->waitForFrameSync();
+}
+
+void * QWaylandXCompositeGLXContext::getProcAddress(const QString &procName)
+{
+ return (void *) glXGetProcAddress(reinterpret_cast<GLubyte *>(procName.toLatin1().data()));
+}
+
+QPlatformWindowFormat QWaylandXCompositeGLXContext::platformWindowFormat() const
+{
+ return qglx_platformWindowFromGLXFBConfig(mGlxIntegration->xDisplay(),mConfig,mContext);
+}
+
+void QWaylandXCompositeGLXContext::sync_function(void *data)
+{
+ QWaylandXCompositeGLXContext *that = static_cast<QWaylandXCompositeGLXContext *>(data);
+ that->mWaitingForSyncCallback = false;
+}
+
+void QWaylandXCompositeGLXContext::waitForSync()
+{
+ wl_display_sync_callback(mGlxIntegration->waylandDisplay()->wl_display(),
+ QWaylandXCompositeGLXContext::sync_function,
+ this);
+ mWaitingForSyncCallback = true;
+ wl_display_sync(mGlxIntegration->waylandDisplay()->wl_display(),0);
+ mGlxIntegration->waylandDisplay()->flushRequests();
+ while (mWaitingForSyncCallback) {
+ mGlxIntegration->waylandDisplay()->readEvents();
+ }
+}
+
+void QWaylandXCompositeGLXContext::geometryChanged()
+{
+ QSize size(mWindow->geometry().size());
+ if (size.isEmpty()) {
+ //QGLWidget wants a context for a window without geometry
+ size = QSize(1,1);
+ }
+
+ delete mBuffer;
+ //XFreePixmap deletes the glxPixmap as well
+ if (mXWindow) {
+ XDestroyWindow(mGlxIntegration->xDisplay(),mXWindow);
+ }
+
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(mGlxIntegration->xDisplay(),mConfig);
+ Colormap cmap = XCreateColormap(mGlxIntegration->xDisplay(),mGlxIntegration->rootWindow(),visualInfo->visual,AllocNone);
+
+ XSetWindowAttributes a;
+ a.colormap = cmap;
+ mXWindow = XCreateWindow(mGlxIntegration->xDisplay(), mGlxIntegration->rootWindow(),0, 0, size.width(), size.height(),
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWColormap, &a);
+
+ XCompositeRedirectWindow(mGlxIntegration->xDisplay(), mXWindow, CompositeRedirectManual);
+ XMapWindow(mGlxIntegration->xDisplay(), mXWindow);
+
+ XSync(mGlxIntegration->xDisplay(),False);
+ mBuffer = new QWaylandXCompositeBuffer(mGlxIntegration->waylandXComposite(),
+ (uint32_t)mXWindow,
+ size,
+ mGlxIntegration->waylandDisplay()->argbVisual());
+ mWindow->attach(mBuffer);
+ waitForSync();
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h
new file mode 100644
index 0000000..eb2e5a5
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEGLXCONTEXT_H
+#define QWAYLANDXCOMPOSITEGLXCONTEXT_H
+
+#include <QtGui/QPlatformGLContext>
+
+#include <QtCore/QWaitCondition>
+
+#include "qwaylandbuffer.h"
+#include "qwaylandxcompositeglxintegration.h"
+
+#include "qglxconvenience.h"
+
+class QWaylandXCompositeGLXWindow;
+class QWaylandShmBuffer;
+
+class QWaylandXCompositeGLXContext : public QPlatformGLContext
+{
+public:
+ QWaylandXCompositeGLXContext(QWaylandXCompositeGLXIntegration *glxIntegration, QWaylandXCompositeGLXWindow *window);
+
+ void makeCurrent();
+ void doneCurrent();
+ void swapBuffers();
+ void* getProcAddress(const QString& procName);
+
+ QPlatformWindowFormat platformWindowFormat() const;
+
+ void geometryChanged();
+
+private:
+ QWaylandXCompositeGLXIntegration *mGlxIntegration;
+ QWaylandXCompositeGLXWindow *mWindow;
+ QWaylandBuffer *mBuffer;
+
+ Window mXWindow;
+ GLXFBConfig mConfig;
+ GLXContext mContext;
+
+ static void sync_function(void *data);
+ void waitForSync();
+ bool mWaitingForSyncCallback;
+};
+
+#endif // QWAYLANDXCOMPOSITEGLXCONTEXT_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp
new file mode 100644
index 0000000..5cb6ef3
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeglxintegration.h"
+
+#include "qwaylandxcompositeglxwindow.h"
+
+#include <QtCore/QDebug>
+
+#include "wayland-xcomposite-client-protocol.h"
+
+QWaylandGLIntegration * QWaylandGLIntegration::createGLIntegration(QWaylandDisplay *waylandDisplay)
+{
+ return new QWaylandXCompositeGLXIntegration(waylandDisplay);
+}
+
+QWaylandXCompositeGLXIntegration::QWaylandXCompositeGLXIntegration(QWaylandDisplay * waylandDispaly)
+ : QWaylandGLIntegration()
+ , mWaylandDisplay(waylandDispaly)
+{
+ qDebug() << "Using XComposite-GLX";
+ wl_display_add_global_listener(waylandDispaly->wl_display(), QWaylandXCompositeGLXIntegration::wlDisplayHandleGlobal,
+ this);
+}
+
+QWaylandXCompositeGLXIntegration::~QWaylandXCompositeGLXIntegration()
+{
+ XCloseDisplay(mDisplay);
+}
+
+void QWaylandXCompositeGLXIntegration::initialize()
+{
+}
+
+QWaylandWindow * QWaylandXCompositeGLXIntegration::createEglWindow(QWidget *widget)
+{
+ return new QWaylandXCompositeGLXWindow(widget,this);
+}
+
+Display * QWaylandXCompositeGLXIntegration::xDisplay() const
+{
+ return mDisplay;
+}
+
+int QWaylandXCompositeGLXIntegration::screen() const
+{
+ return mScreen;
+}
+
+Window QWaylandXCompositeGLXIntegration::rootWindow() const
+{
+ return mRootWindow;
+}
+
+QWaylandDisplay * QWaylandXCompositeGLXIntegration::waylandDisplay() const
+{
+ return mWaylandDisplay;
+}
+wl_xcomposite * QWaylandXCompositeGLXIntegration::waylandXComposite() const
+{
+ return mWaylandComposite;
+}
+
+const struct wl_xcomposite_listener QWaylandXCompositeGLXIntegration::xcomposite_listener = {
+ QWaylandXCompositeGLXIntegration::rootInformation
+};
+
+void QWaylandXCompositeGLXIntegration::wlDisplayHandleGlobal(wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data)
+{
+ Q_UNUSED(version);
+ if (strcmp(interface, "wl_xcomposite") == 0) {
+ QWaylandXCompositeGLXIntegration *integration = static_cast<QWaylandXCompositeGLXIntegration *>(data);
+ integration->mWaylandComposite = wl_xcomposite_create(display,id,1);
+ wl_xcomposite_add_listener(integration->mWaylandComposite,&xcomposite_listener,integration);
+ }
+
+}
+
+void QWaylandXCompositeGLXIntegration::rootInformation(void *data, wl_xcomposite *xcomposite, const char *display_name, uint32_t root_window)
+{
+ Q_UNUSED(xcomposite);
+ QWaylandXCompositeGLXIntegration *integration = static_cast<QWaylandXCompositeGLXIntegration *>(data);
+
+ integration->mDisplay = XOpenDisplay(display_name);
+ integration->mRootWindow = (Window) root_window;
+ integration->mScreen = XDefaultScreen(integration->mDisplay);
+}
+
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h
new file mode 100644
index 0000000..24a4016
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEGLXINTEGRATION_H
+#define QWAYLANDXCOMPOSITEGLXINTEGRATION_H
+
+#include "gl_integration/qwaylandglintegration.h"
+#include "wayland-client.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDataStream>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+
+#include <X11/Xlib.h>
+
+struct wl_xcomposite;
+
+class QWaylandXCompositeGLXIntegration : public QWaylandGLIntegration
+{
+public:
+ QWaylandXCompositeGLXIntegration(QWaylandDisplay * waylandDispaly);
+ ~QWaylandXCompositeGLXIntegration();
+
+ void initialize();
+
+ QWaylandWindow *createEglWindow(QWidget *widget);
+
+ QWaylandDisplay *waylandDisplay() const;
+ struct wl_xcomposite *waylandXComposite() const;
+
+ Display *xDisplay() const;
+ int screen() const;
+ Window rootWindow() const;
+
+private:
+ QWaylandDisplay *mWaylandDisplay;
+ struct wl_xcomposite *mWaylandComposite;
+
+ Display *mDisplay;
+ int mScreen;
+ Window mRootWindow;
+
+ static void wlDisplayHandleGlobal(struct wl_display *display, uint32_t id,
+ const char *interface, uint32_t version, void *data);
+
+ static const struct wl_xcomposite_listener xcomposite_listener;
+ static void rootInformation(void *data,
+ struct wl_xcomposite *xcomposite,
+ const char *display_name,
+ uint32_t root_window);
+};
+
+#endif // QWAYLANDXCOMPOSITEGLXINTEGRATION_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp
new file mode 100644
index 0000000..db0f254
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositeglxwindow.h"
+
+#include <QtCore/QDebug>
+
+QWaylandXCompositeGLXWindow::QWaylandXCompositeGLXWindow(QWidget *window, QWaylandXCompositeGLXIntegration *glxIntegration)
+ : QWaylandWindow(window)
+ , mGlxIntegration(glxIntegration)
+ , mContext(0)
+{
+
+}
+
+QWaylandWindow::WindowType QWaylandXCompositeGLXWindow::windowType() const
+{
+ //yeah. this type needs a new name
+ return QWaylandWindow::Egl;
+}
+
+QPlatformGLContext * QWaylandXCompositeGLXWindow::glContext() const
+{
+ if (!mContext) {
+ qDebug() << "creating glcontext;";
+ QWaylandXCompositeGLXWindow *that = const_cast<QWaylandXCompositeGLXWindow *>(this);
+ that->mContext = new QWaylandXCompositeGLXContext(mGlxIntegration,that);
+ }
+ return mContext;
+}
+
+void QWaylandXCompositeGLXWindow::setGeometry(const QRect &rect)
+{
+ QWaylandWindow::setGeometry(rect);
+
+ if (mContext) {
+ mContext->geometryChanged();
+ }
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h
new file mode 100644
index 0000000..536153d
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxwindow.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEGLXWINDOW_H
+#define QWAYLANDXCOMPOSITEGLXWINDOW_H
+
+#include "qwaylandwindow.h"
+#include "qwaylandxcompositeglxintegration.h"
+#include "qwaylandxcompositeglxcontext.h"
+
+class QWaylandXCompositeGLXWindow : public QWaylandWindow
+{
+public:
+ QWaylandXCompositeGLXWindow(QWidget *window, QWaylandXCompositeGLXIntegration *glxIntegration);
+ WindowType windowType() const;
+
+ QPlatformGLContext *glContext() const;
+
+ void setGeometry(const QRect &rect);
+
+private:
+ QWaylandXCompositeGLXIntegration *mGlxIntegration;
+ QWaylandXCompositeGLXContext *mContext;
+
+};
+
+#endif // QWAYLANDXCOMPOSITEGLXWINDOW_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri
new file mode 100644
index 0000000..43295e9
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_glx/xcomposite_glx.pri
@@ -0,0 +1,13 @@
+include (../xcomposite_share/xcomposite_share.pri)
+include (../../../glxconvenience/glxconvenience.pri)
+
+LIBS += -lXcomposite
+SOURCES += \
+ $$PWD/qwaylandxcompositeglxcontext.cpp \
+ $$PWD/qwaylandxcompositeglxintegration.cpp \
+ $$PWD/qwaylandxcompositeglxwindow.cpp
+
+HEADERS += \
+ $$PWD/qwaylandxcompositeglxcontext.h \
+ $$PWD/qwaylandxcompositeglxintegration.h \
+ $$PWD/qwaylandxcompositeglxwindow.h
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp
new file mode 100644
index 0000000..4b0d3a0
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandxcompositebuffer.h"
+
+#include "wayland-client.h"
+
+QWaylandXCompositeBuffer::QWaylandXCompositeBuffer(wl_xcomposite *xcomposite, uint32_t window, const QSize &size, wl_visual *visual)
+ :mSize(size)
+{
+ mBuffer = wl_xcomposite_create_buffer(xcomposite,
+ window,
+ size.width(),
+ size.height(),
+ visual);
+}
+
+QSize QWaylandXCompositeBuffer::size() const
+{
+ return mSize;
+}
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h
new file mode 100644
index 0000000..b346651
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/qwaylandxcompositebuffer.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXCOMPOSITEBUFFER_H
+#define QWAYLANDXCOMPOSITEBUFFER_H
+
+#include "qwaylandbuffer.h"
+
+#include "wayland-xcomposite-client-protocol.h"
+
+class QWaylandXCompositeBuffer : public QWaylandBuffer
+{
+public:
+ QWaylandXCompositeBuffer(struct wl_xcomposite *xcomposite,
+ uint32_t window,
+ const QSize &size,
+ struct wl_visual *visual);
+
+ QSize size() const;
+private:
+ QSize mSize;
+};
+
+#endif // QWAYLANDXCOMPOSITEBUFFER_H
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h
new file mode 100644
index 0000000..85da7a9
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-client-protocol.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef XCOMPOSITE_CLIENT_PROTOCOL_H
+#define XCOMPOSITE_CLIENT_PROTOCOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-util.h"
+
+struct wl_client;
+
+struct wl_xcomposite;
+
+extern const struct wl_interface wl_xcomposite_interface;
+
+struct wl_xcomposite_listener {
+ void (*root)(void *data,
+ struct wl_xcomposite *wl_xcomposite,
+ const char *display_name,
+ uint32_t root_window);
+};
+
+static inline int
+wl_xcomposite_add_listener(struct wl_xcomposite *wl_xcomposite,
+ const struct wl_xcomposite_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) wl_xcomposite,
+ (void (**)(void)) listener, data);
+}
+
+#define WL_XCOMPOSITE_CREATE_BUFFER 0
+
+static inline struct wl_xcomposite *
+wl_xcomposite_create(struct wl_display *display, uint32_t id, uint32_t version)
+{
+ wl_display_bind(display, id, "wl_xcomposite", version);
+
+ return (struct wl_xcomposite *)
+ wl_proxy_create_for_id(display, &wl_xcomposite_interface, id);
+}
+
+static inline void
+wl_xcomposite_set_user_data(struct wl_xcomposite *wl_xcomposite, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) wl_xcomposite, user_data);
+}
+
+static inline void *
+wl_xcomposite_get_user_data(struct wl_xcomposite *wl_xcomposite)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) wl_xcomposite);
+}
+
+static inline void
+wl_xcomposite_destroy(struct wl_xcomposite *wl_xcomposite)
+{
+ wl_proxy_destroy((struct wl_proxy *) wl_xcomposite);
+}
+
+static inline struct wl_buffer *
+wl_xcomposite_create_buffer(struct wl_xcomposite *wl_xcomposite, uint32_t x_window, int width, int height, struct wl_visual *visual)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_create((struct wl_proxy *) wl_xcomposite,
+ &wl_buffer_interface);
+ if (!id)
+ return NULL;
+
+ wl_proxy_marshal((struct wl_proxy *) wl_xcomposite,
+ WL_XCOMPOSITE_CREATE_BUFFER, id, x_window, width, height, visual);
+
+ return (struct wl_buffer *) id;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c
new file mode 100644
index 0000000..a1b6325
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/wayland-xcomposite-protocol.c
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+static const struct wl_message wl_xcomposite_requests[] = {
+ { "create_buffer", "nuiio" },
+};
+
+static const struct wl_message wl_xcomposite_events[] = {
+ { "root", "su" },
+};
+
+WL_EXPORT const struct wl_interface wl_xcomposite_interface = {
+ "wl_xcomposite", 1,
+ ARRAY_LENGTH(wl_xcomposite_requests), wl_xcomposite_requests,
+ ARRAY_LENGTH(wl_xcomposite_events), wl_xcomposite_events,
+};
+
diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri
new file mode 100644
index 0000000..03b3521
--- /dev/null
+++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_share/xcomposite_share.pri
@@ -0,0 +1,9 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/wayland-xcomposite-client-protocol.h \
+ gl_integration/xcomposite_share/qwaylandxcompositebuffer.h
+
+SOURCES += \
+ $$PWD/wayland-xcomposite-protocol.c \
+ gl_integration/xcomposite_share/qwaylandxcompositebuffer.cpp
diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h
index 643e89c..faeb3e8 100644
--- a/src/plugins/platforms/wayland/qwaylandbuffer.h
+++ b/src/plugins/platforms/wayland/qwaylandbuffer.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -44,6 +44,7 @@
#include <QtCore/QSize>
+#include <wayland-client.h>
#include <wayland-client-protocol.h>
class QWaylandBuffer {
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 27f4334..876b46a 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -46,13 +46,23 @@
#include "qwaylandcursor.h"
#include "qwaylandinputdevice.h"
+#ifdef QT_WAYLAND_GL_SUPPORT
+#include "gl_integration/qwaylandglintegration.h"
+#endif
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtGui/QApplication>
+
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
+#include <errno.h>
-struct wl_surface *QWaylandDisplay::createSurface()
+struct wl_surface *QWaylandDisplay::createSurface(void *handle)
{
- return wl_compositor_create_surface(mCompositor);
+ struct wl_surface * surface = wl_compositor_create_surface(mCompositor);
+ wl_surface_set_user_data(surface, handle);
+ return surface;
}
struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd,
@@ -78,10 +88,12 @@ struct wl_visual *QWaylandDisplay::argbPremultipliedVisual()
return wl_display_get_premultiplied_argb_visual(mDisplay);
}
-struct wl_egl_display *QWaylandDisplay::nativeDisplay()
+#ifdef QT_WAYLAND_GL_SUPPORT
+QWaylandGLIntegration * QWaylandDisplay::eglIntegration()
{
- return mNativeEglDisplay;
+ return mEglIntegration;
}
+#endif
void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell,
uint32_t time, uint32_t edges,
@@ -101,147 +113,156 @@ const struct wl_shell_listener QWaylandDisplay::shellListener = {
QWaylandDisplay::shellHandleConfigure,
};
-void QWaylandDisplay::outputHandleGeometry(void *data,
- struct wl_output *output,
- int32_t x, int32_t y,
- int32_t width, int32_t height)
+QWaylandDisplay::QWaylandDisplay(void)
{
- QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data;
+ mDisplay = wl_display_connect(NULL);
+ if (mDisplay == NULL) {
+ qErrnoWarning(errno, "Failed to create display");
+ qFatal("No wayland connection available.");
+ }
- QRect outputRect = QRect(x, y, width, height);
- waylandDisplay->createNewScreen(output, outputRect);
-}
+ wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this);
-const struct wl_output_listener QWaylandDisplay::outputListener = {
- QWaylandDisplay::outputHandleGeometry
-};
+#ifdef QT_WAYLAND_GL_SUPPORT
+ mEglIntegration = QWaylandGLIntegration::createGLIntegration(this);
+#endif
+ blockingReadEvents();
-void QWaylandDisplay::displayHandleGlobal(struct wl_display *display,
- uint32_t id,
- const char *interface,
- uint32_t version, void *data)
-{
- Q_UNUSED(version);
- QWaylandDisplay *qwd = (QWaylandDisplay *) data;
-
- if (strcmp(interface, "compositor") == 0) {
- qwd->mCompositor = wl_compositor_create(display, id);
- } else if (strcmp(interface, "shm") == 0) {
- qwd->mShm = wl_shm_create(display, id);
- } else if (strcmp(interface, "shell") == 0) {
- qwd->mShell = wl_shell_create(display, id);
- wl_shell_add_listener(qwd->mShell, &shellListener, qwd);
- } else if (strcmp(interface, "output") == 0) {
- struct wl_output *output = wl_output_create(display, id);
- wl_output_add_listener(output, &outputListener, qwd);
- } else if (strcmp(interface, "input_device") == 0) {
- QWaylandInputDevice *inputDevice =
- new QWaylandInputDevice(display, id);
- qwd->mInputDevices.append(inputDevice);
- }
+ qRegisterMetaType<uint32_t>("uint32_t");
+
+#ifdef QT_WAYLAND_GL_SUPPORT
+ mEglIntegration->initialize();
+#endif
+
+ connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(flushRequests()));
+
+ mFd = wl_display_get_fd(mDisplay, sourceUpdate, this);
+
+ mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this);
+ connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents()));
+
+ waitForScreens();
}
-void QWaylandDisplay::iterate()
+QWaylandDisplay::~QWaylandDisplay(void)
{
- wl_display_iterate(mDisplay, WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE);
+ close(mFd);
+#ifdef QT_WAYLAND_GL_SUPPORT
+ delete mEglIntegration;
+#endif
+ wl_display_destroy(mDisplay);
}
-void QWaylandDisplay::readEvents(void)
+void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry)
{
- wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+ QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry);
+ mScreens.append(waylandScreen);
}
-int
-QWaylandDisplay::sourceUpdate(uint32_t mask, void *data)
+void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data)
{
- QWaylandDisplay *qwd = (QWaylandDisplay *) data;
-
- /* FIXME: We get a callback here when we ask wl_display for the
- * fd, but at that point we don't have the socket notifier as we
- * need the fd to create that. We'll probably need to split that
- * API into get_fd and set_update_func functions. */
- if (qwd->mWriteNotifier == NULL)
- return 0;
-
- qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE);
+ wl_display_sync_callback(mDisplay, func, data);
+}
- return 0;
+void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data)
+{
+ wl_display_frame_callback(mDisplay, surface, func, data);
}
-void QWaylandDisplay::flushRequests(void)
+void QWaylandDisplay::flushRequests()
{
- wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE);
+ if (mSocketMask & WL_DISPLAY_WRITABLE)
+ wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE);
}
-QWaylandDisplay::QWaylandDisplay(void)
- : mWriteNotifier(0)
+void QWaylandDisplay::readEvents()
{
-#ifdef QT_WAYLAND_GL_SUPPORT
- EGLint major, minor;
-#endif
- mDisplay = wl_display_connect(NULL);
- if (mDisplay == NULL) {
- fprintf(stderr, "failed to create display: %m\n");
+// verify that there is still data on the socket
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(mFd, &fds);
+ fd_set nds;
+ FD_ZERO(&nds);
+ fd_set rs = fds;
+ fd_set ws = nds;
+ fd_set es = nds;
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ int ret = ::select(mFd+1, &rs, &ws, &es, &timeout );
+
+ if (ret <= 0) {
+ //qDebug("QWaylandDisplay::readEvents() No data... blocking avoided");
return;
}
- wl_display_add_global_listener(mDisplay,
- QWaylandDisplay::displayHandleGlobal, this);
-
-#ifdef QT_WAYLAND_GL_SUPPORT
- mNativeEglDisplay = wl_egl_display_create(mDisplay);
-#else
- mNativeEglDisplay = 0;
-#endif
-
- readEvents();
+ wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+}
-#ifdef QT_WAYLAND_GL_SUPPORT
- mEglDisplay = eglGetDisplay((EGLNativeDisplayType)mNativeEglDisplay);
- if (mEglDisplay == NULL) {
- qWarning("EGL not available");
- } else {
- if (!eglInitialize(mEglDisplay, &major, &minor)) {
- qWarning("failed to initialize EGL display");
- return;
- }
- }
-#else
- mEglDisplay = 0;
-#endif
+void QWaylandDisplay::blockingReadEvents()
+{
+ wl_display_iterate(mDisplay, WL_DISPLAY_READABLE);
+}
- int fd = wl_display_get_fd(mDisplay, sourceUpdate, this);
- mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(mReadNotifier,
- SIGNAL(activated(int)), this, SLOT(readEvents()));
+int QWaylandDisplay::sourceUpdate(uint32_t mask, void *data)
+{
+ QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data);
+ waylandDisplay->mSocketMask = mask;
- mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this);
- connect(mWriteNotifier,
- SIGNAL(activated(int)), this, SLOT(flushRequests()));
- mWriteNotifier->setEnabled(false);
+ return 0;
}
-QWaylandDisplay::~QWaylandDisplay(void)
+void QWaylandDisplay::outputHandleGeometry(void *data,
+ struct wl_output *output,
+ int32_t x, int32_t y,
+ int32_t width, int32_t height)
{
- close(mFd);
-#ifdef QT_WAYLAND_GL_SUPPORT
- eglTerminate(mEglDisplay);
-#endif
- wl_display_destroy(mDisplay);
+ QWaylandDisplay *waylandDisplay = static_cast<QWaylandDisplay *>(data);
+ QRect outputRect = QRect(x, y, width, height);
+ waylandDisplay->createNewScreen(output,outputRect);
}
-void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry)
+const struct wl_output_listener QWaylandDisplay::outputListener = {
+ QWaylandDisplay::outputHandleGeometry
+};
+
+void QWaylandDisplay::waitForScreens()
{
- QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry);
- mScreens.append(waylandScreen);
+ flushRequests();
+ while (mScreens.isEmpty())
+ blockingReadEvents();
}
-void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data)
+void QWaylandDisplay::displayHandleGlobal(struct wl_display *display,
+ uint32_t id,
+ const char *interface,
+ uint32_t version,
+ void *data)
{
- wl_display_sync_callback(mDisplay, func, data);
+ Q_UNUSED(display);
+ QWaylandDisplay *that = static_cast<QWaylandDisplay *>(data);
+ that->displayHandleGlobal(id, QByteArray(interface), version);
}
-void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data)
+void QWaylandDisplay::displayHandleGlobal(uint32_t id,
+ const QByteArray &interface,
+ uint32_t version)
{
- wl_display_frame_callback(mDisplay, func, data);
+ Q_UNUSED(version);
+
+ if (interface == "wl_output") {
+ struct wl_output *output = wl_output_create(mDisplay, id, 1);
+ wl_output_add_listener(output, &outputListener, this);
+ } else if (interface == "wl_compositor") {
+ mCompositor = wl_compositor_create(mDisplay, id, 1);
+ } else if (interface == "wl_shm") {
+ mShm = wl_shm_create(mDisplay, id, 1);
+ } else if (interface == "wl_shell"){
+ mShell = wl_shell_create(mDisplay, id, 1);
+ wl_shell_add_listener(mShell, &shellListener, this);
+ } else if (interface == "wl_input_device") {
+ QWaylandInputDevice *inputDevice =
+ new QWaylandInputDevice(mDisplay, id);
+ mInputDevices.append(inputDevice);
+ }
}
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h
index d994ffe..a2cb1b2 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.h
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.h
@@ -44,19 +44,17 @@
#include <QtCore/QObject>
#include <QtCore/QRect>
-#include <QtCore/QDataStream>
-#include <QtCore/QTextStream>
-#include <QtCore/QMetaType>
-#include <QtGui>
-#include "qwaylandinclude.h"
+#include <QtCore/QWaitCondition>
+
+#include <wayland-client.h>
class QWaylandInputDevice;
class QSocketNotifier;
class QWaylandBuffer;
class QPlatformScreen;
class QWaylandScreen;
-
+class QWaylandGLIntegration;
class QWaylandDisplay : public QObject {
Q_OBJECT
@@ -64,61 +62,72 @@ public:
QWaylandDisplay(void);
~QWaylandDisplay(void);
- void createNewScreen(struct wl_output *output, QRect geometry);
QList<QPlatformScreen *> screens() const { return mScreens; }
- struct wl_surface *createSurface();
+ struct wl_surface *createSurface(void *handle);
struct wl_buffer *createShmBuffer(int fd, int width, int height,
uint32_t stride,
struct wl_visual *visual);
struct wl_visual *rgbVisual();
struct wl_visual *argbVisual();
struct wl_visual *argbPremultipliedVisual();
- struct wl_egl_display *nativeDisplay();
- EGLDisplay eglDisplay() { return mEglDisplay; }
+#ifdef QT_WAYLAND_GL_SUPPORT
+ QWaylandGLIntegration *eglIntegration();
+#endif
void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y);
void syncCallback(wl_display_sync_func_t func, void *data);
- void frameCallback(wl_display_frame_func_t func, void *data);
+ void frameCallback(wl_display_frame_func_t func, struct wl_surface *surface, void *data);
- void iterate();
+ struct wl_display *wl_display() const { return mDisplay; }
+
+ QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
public slots:
- void readEvents(void);
- void flushRequests(void);
+ void createNewScreen(struct wl_output *output, QRect geometry);
+ void readEvents();
+ void blockingReadEvents();
+ void flushRequests();
private:
+ void waitForScreens();
+ void displayHandleGlobal(uint32_t id,
+ const QByteArray &interface,
+ uint32_t version);
+
struct wl_display *mDisplay;
struct wl_compositor *mCompositor;
struct wl_shm *mShm;
struct wl_shell *mShell;
- char *mDeviceName;
- int mFd;
QList<QPlatformScreen *> mScreens;
QList<QWaylandInputDevice *> mInputDevices;
+
QSocketNotifier *mReadNotifier;
- QSocketNotifier *mWriteNotifier;
- EGLDisplay mEglDisplay;
- struct wl_egl_display *mNativeEglDisplay;
+ int mFd;
+ bool mScreensInitialized;
+ uint32_t mSocketMask;
+
+ static const struct wl_output_listener outputListener;
+ static int sourceUpdate(uint32_t mask, void *data);
static void displayHandleGlobal(struct wl_display *display,
uint32_t id,
const char *interface,
uint32_t version, void *data);
-
static void outputHandleGeometry(void *data,
struct wl_output *output,
int32_t x, int32_t y,
int32_t width, int32_t height);
+#ifdef QT_WAYLAND_GL_SUPPORT
+ QWaylandGLIntegration *mEglIntegration;
+#endif
+
static void shellHandleConfigure(void *data, struct wl_shell *shell,
uint32_t time, uint32_t edges,
struct wl_surface *surface,
int32_t width, int32_t height);
- static int sourceUpdate(uint32_t mask, void *data);
-
- static const struct wl_output_listener outputListener;
static const struct wl_shell_listener shellListener;
};
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index 47f9c91..f9e7c95 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -61,7 +61,7 @@
QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display,
uint32_t id)
: mDisplay(display)
- , mInputDevice(wl_input_device_create(display, id))
+ , mInputDevice(wl_input_device_create(display, id, 1))
, mPointerFocus(NULL)
, mKeyboardFocus(NULL)
, mButtons(0)
@@ -83,6 +83,14 @@ QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display,
#endif
}
+void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
+{
+ if (window == mPointerFocus)
+ mPointerFocus = 0;
+ if (window == mKeyboardFocus)
+ mKeyboardFocus = 0;
+}
+
void QWaylandInputDevice::inputHandleMotion(void *data,
struct wl_input_device *input_device,
uint32_t time,
@@ -93,6 +101,12 @@ void QWaylandInputDevice::inputHandleMotion(void *data,
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
QWaylandWindow *window = inputDevice->mPointerFocus;
+ if (window == NULL) {
+ /* We destroyed the pointer focus surface, but the server
+ * didn't get the message yet. */
+ return;
+ }
+
inputDevice->mSurfacePos = QPoint(surface_x, surface_y);
inputDevice->mGlobalPos = QPoint(x, y);
inputDevice->mTime = time;
@@ -112,6 +126,12 @@ void QWaylandInputDevice::inputHandleButton(void *data,
QWaylandWindow *window = inputDevice->mPointerFocus;
Qt::MouseButton qt_button;
+ if (window == NULL) {
+ /* We destroyed the pointer focus surface, but the server
+ * didn't get the message yet. */
+ return;
+ }
+
switch (button) {
case 272:
qt_button = Qt::LeftButton;
@@ -221,6 +241,12 @@ void QWaylandInputDevice::inputHandleKey(void *data,
QEvent::Type type;
char s[2];
+ if (window == NULL) {
+ /* We destroyed the keyboard focus surface, but the server
+ * didn't get the message yet. */
+ return;
+ }
+
code = key + inputDevice->mXkb->min_key_code;
level = 0;
@@ -242,9 +268,6 @@ void QWaylandInputDevice::inputHandleKey(void *data,
sym = translateKey(sym, s, sizeof s);
- qWarning("keycode %d, sym %d, string %d, modifiers 0x%x",
- code, sym, s[0], (int) inputDevice->mModifiers);
-
if (window) {
QWindowSystemInterface::handleKeyEvent(window->widget(),
time, type, sym,
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h
index 2328db8..3c83252 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h
@@ -59,6 +59,7 @@ class QWaylandInputDevice {
public:
QWaylandInputDevice(struct wl_display *display, uint32_t id);
void attach(QWaylandBuffer *buffer, int x, int y);
+ void handleWindowDestroyed(QWaylandWindow *window);
private:
struct wl_display *mDisplay;
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
index 267a037..b6401f6 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
@@ -43,9 +43,8 @@
#include "qwaylanddisplay.h"
#include "qwaylandshmsurface.h"
-#include "qwaylanddrmsurface.h"
#include "qwaylandshmwindow.h"
-#include "qwaylandeglwindow.h"
+#include "qwaylandnativeinterface.h"
#include "qgenericunixfontdatabase.h"
@@ -55,6 +54,8 @@
#include <QtGui/private/qpixmap_raster_p.h>
#ifdef QT_WAYLAND_GL_SUPPORT
+#include "gl_integration/qwaylandglintegration.h"
+#include "gl_integration/qwaylandglwindowsurface.h"
#include <QtOpenGL/private/qpixmapdata_gl_p.h>
#endif
@@ -62,9 +63,15 @@ QWaylandIntegration::QWaylandIntegration(bool useOpenGL)
: mFontDb(new QGenericUnixFontDatabase())
, mDisplay(new QWaylandDisplay())
, mUseOpenGL(useOpenGL)
+ , mNativeInterface(new QWaylandNativeInterface)
{
}
+QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
+{
+ return mNativeInterface;
+}
+
QList<QPlatformScreen *>
QWaylandIntegration::screens() const
{
@@ -75,6 +82,7 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co
{
switch (cap) {
case ThreadedPixmaps: return true;
+ case OpenGL: return hasOpenGL();
default: return QPlatformIntegration::hasCapability(cap);
}
}
@@ -91,10 +99,11 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type)
QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const
{
Q_UNUSED(winId);
+#ifdef QT_WAYLAND_GL_SUPPORT
bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL);
if (useOpenGL)
- return new QWaylandEglWindow(widget);
-
+ return mDisplay->eglIntegration()->createEglWindow(widget);
+#endif
return new QWaylandShmWindow(widget);
}
@@ -102,10 +111,11 @@ QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId wi
{
Q_UNUSED(winId);
Q_UNUSED(winId);
+#ifdef QT_WAYLAND_GL_SUPPORT
bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL);
if (useOpenGL)
- return new QWaylandDrmWindowSurface(widget);
-
+ return new QWaylandGLWindowSurface(widget);
+#endif
return new QWaylandShmWindowSurface(widget);
}
@@ -113,3 +123,12 @@ QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
{
return mFontDb;
}
+
+bool QWaylandIntegration::hasOpenGL() const
+{
+#ifdef QT_WAYLAND_GL_SUPPORT
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h
index 067b6e4..71f6d9c 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.h
+++ b/src/plugins/platforms/wayland/qwaylandintegration.h
@@ -63,10 +63,15 @@ public:
QPlatformFontDatabase *fontDatabase() const;
+ QPlatformNativeInterface *nativeInterface() const;
+
private:
+ bool hasOpenGL() const;
+
QPlatformFontDatabase *mFontDb;
QWaylandDisplay *mDisplay;
bool mUseOpenGL;
+ QPlatformNativeInterface *mNativeInterface;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp b/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp
new file mode 100644
index 0000000..c3bfba0
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qwaylandnativeinterface.h"
+
+#include "qwaylanddisplay.h"
+#include "qwaylandwindow.h"
+#include <QtGui/private/qapplication_p.h>
+
+void *QWaylandNativeInterface::nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget)
+{
+ QByteArray lowerCaseResource = resourceString.toLower();
+
+ if (lowerCaseResource == "display")
+ return qPlatformScreenForWidget(widget)->display()->wl_display();
+ if (lowerCaseResource == "surface") {
+ return ((QWaylandWindow *) widget->platformWindow())->wl_surface();
+ }
+
+ return NULL;
+}
+
+
+QWaylandScreen * QWaylandNativeInterface::qPlatformScreenForWidget(QWidget *widget)
+{
+ QWaylandScreen *screen;
+
+ if (widget) {
+ screen = static_cast<QWaylandScreen *>(QPlatformScreen::platformScreenForWidget(widget));
+ } else {
+ screen = static_cast<QWaylandScreen *>(QApplicationPrivate::platformIntegration()->screens()[0]);
+ }
+ return screen;
+}
diff --git a/src/plugins/platforms/wayland/qwaylandnativeinterface.h b/src/plugins/platforms/wayland/qwaylandnativeinterface.h
new file mode 100644
index 0000000..ac4cdb9
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandnativeinterface.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDNATIVEINTERFACE_H
+#define QWAYLANDNATIVEINTERFACE_H
+
+#include "qwaylandscreen.h"
+
+#include <QtGui/QPlatformNativeInterface>
+
+class QWaylandNativeInterface : public QPlatformNativeInterface
+{
+public:
+ void *nativeResourceForWidget(const QByteArray &resourceString,
+ QWidget *widget);
+
+private:
+ static QWaylandScreen *qPlatformScreenForWidget(QWidget *widget);
+};
+
+
+#endif // QWAYLANDNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp
index 35e2532..4f50cb6 100644
--- a/src/plugins/platforms/wayland/qwaylandscreen.cpp
+++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp
@@ -53,6 +53,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output
, mFormat(QImage::Format_ARGB32_Premultiplied)
, mWaylandCursor(new QWaylandCursor(this))
{
+ moveToThread(waylandDisplay->thread());
}
QWaylandScreen::~QWaylandScreen()
diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp
index 54da9a1..34f4436 100644
--- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp
@@ -95,7 +95,6 @@ QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window)
: QWindowSurface(window)
, mBuffer(0)
, mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display())
- , mWaitingForFrameSync(false)
{
}
@@ -110,15 +109,9 @@ QPaintDevice *QWaylandShmWindowSurface::paintDevice()
void QWaylandShmWindowSurface::beginPaint(const QRegion &)
{
- while (mWaitingForFrameSync) {
- mDisplay->iterate();
- }
-}
-
-void QWaylandShmWindowSurface::frameCallback(void *data, uint32_t time)
-{
- QWaylandShmWindowSurface *self = static_cast<QWaylandShmWindowSurface*>(data);
- self->mWaitingForFrameSync = false;
+ QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow());
+ Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
+ waylandWindow->waitForFrameSync();
}
void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
@@ -127,13 +120,7 @@ void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion &region, con
Q_UNUSED(offset);
QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow());
Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
-
- QVector<QRect> rects = region.rects();
- for (int i = 0; i < rects.size(); i++) {
- waylandWindow->damage(rects.at(i));
- }
- mWaitingForFrameSync = true;
- mDisplay->frameCallback(QWaylandShmWindowSurface::frameCallback, this);
+ waylandWindow->damage(region);
}
void QWaylandShmWindowSurface::resize(const QSize &size)
diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h
index 02b324a..b29ceaf 100644
--- a/src/plugins/platforms/wayland/qwaylandshmsurface.h
+++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h
@@ -74,11 +74,8 @@ public:
void beginPaint(const QRegion &);
private:
- static void frameCallback(void *data, uint32_t time);\
-
QWaylandShmBuffer *mBuffer;
QWaylandDisplay *mDisplay;
- bool mWaitingForFrameSync;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp
index cafd2d0..c083e58 100644
--- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp
@@ -43,9 +43,12 @@
#include "qwaylandbuffer.h"
+#include <QtCore/QVector>
+
+#include <QtCore/QDebug>
+
QWaylandShmWindow::QWaylandShmWindow(QWidget *widget)
: QWaylandWindow(widget)
- , mBuffer(0)
{
newSurfaceCreated();
}
@@ -66,24 +69,3 @@ QPlatformGLContext * QWaylandShmWindow::glContext() const
return 0;
}
-void QWaylandShmWindow::attach(QWaylandBuffer *buffer)
-{
- mBuffer = buffer;
- if (mSurface) {
- wl_surface_attach(mSurface, buffer->buffer(),0,0);
- }
-}
-
-
-void QWaylandShmWindow::damage(const QRect &rect)
-{
- wl_surface_damage(mSurface,
- rect.x(), rect.y(), rect.width(), rect.height());
-}
-
-void QWaylandShmWindow::newSurfaceCreated()
-{
- if (mBuffer) {
- wl_surface_attach(mSurface,mBuffer->buffer(),0,0);
- }
-}
diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.h b/src/plugins/platforms/wayland/qwaylandshmwindow.h
index 14a29d2..5dc6351 100644
--- a/src/plugins/platforms/wayland/qwaylandshmwindow.h
+++ b/src/plugins/platforms/wayland/qwaylandshmwindow.h
@@ -43,6 +43,7 @@
#define QWAYLANDSHMWINDOW_H
#include "qwaylandwindow.h"
+#include <QtGui/QRegion>
class QWaylandShmWindow : public QWaylandWindow
{
@@ -52,12 +53,6 @@ public:
WindowType windowType() const;
QPlatformGLContext *glContext() const;
- void attach(QWaylandBuffer *buffer);
- void damage(const QRect &rect);
-protected:
- void newSurfaceCreated();
-private:
- QWaylandBuffer *mBuffer;
};
#endif // QWAYLANDSHMWINDOW_H
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp
index a912a83..53f2f48 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp
@@ -41,7 +41,9 @@
#include "qwaylandwindow.h"
+#include "qwaylandbuffer.h"
#include "qwaylanddisplay.h"
+#include "qwaylandinputdevice.h"
#include "qwaylandscreen.h"
#include <QtGui/QWidget>
@@ -52,15 +54,23 @@
QWaylandWindow::QWaylandWindow(QWidget *window)
: QPlatformWindow(window)
, mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display())
+ , mBuffer(0)
+ , mWaitingForFrameSync(false)
{
static WId id = 1;
mWindowId = id++;
- mSurface = mDisplay->createSurface();
+ mSurface = mDisplay->createSurface(this);
}
QWaylandWindow::~QWaylandWindow()
{
+ if (mSurface)
+ wl_surface_destroy(mSurface);
+
+ QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
+ for (int i = 0; i < inputDevices.size(); ++i)
+ inputDevices.at(i)->handleWindowDestroyed(this);
}
WId QWaylandWindow::winId() const
@@ -71,18 +81,17 @@ WId QWaylandWindow::winId() const
void QWaylandWindow::setParent(const QPlatformWindow *parent)
{
Q_UNUSED(parent);
- qWarning("Trying to add a raster window as a sub-window");
+ qWarning("Sub window is not supported");
}
void QWaylandWindow::setVisible(bool visible)
{
- if (!mSurface) {
- mSurface = mDisplay->createSurface();
+ if (!mSurface && visible) {
+ mSurface = mDisplay->createSurface(this);
newSurfaceCreated();
}
if (visible) {
- wl_surface_set_user_data(mSurface, this);
wl_surface_map_toplevel(mSurface);
} else {
wl_surface_destroy(mSurface);
@@ -102,3 +111,49 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges,
QWindowSystemInterface::handleGeometryChange(widget(), geometry);
}
+
+void QWaylandWindow::attach(QWaylandBuffer *buffer)
+{
+ mBuffer = buffer;
+ if (mSurface) {
+ wl_surface_attach(mSurface, buffer->buffer(),0,0);
+ }
+}
+
+
+void QWaylandWindow::damage(const QRegion &region)
+{
+ //We have to do sync stuff before calling damage, or we might
+ //get a frame callback before we get the timestamp
+ mDisplay->frameCallback(QWaylandWindow::frameCallback, mSurface, this);
+ mWaitingForFrameSync = true;
+
+ QVector<QRect> rects = region.rects();
+ for (int i = 0; i < rects.size(); i++) {
+ const QRect rect = rects.at(i);
+ wl_surface_damage(mSurface,
+ rect.x(), rect.y(), rect.width(), rect.height());
+ }
+}
+
+void QWaylandWindow::newSurfaceCreated()
+{
+ if (mBuffer) {
+ wl_surface_attach(mSurface,mBuffer->buffer(),0,0);
+ }
+}
+
+void QWaylandWindow::frameCallback(struct wl_surface *surface, void *data, uint32_t time)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(surface);
+ QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
+ self->mWaitingForFrameSync = false;
+}
+
+void QWaylandWindow::waitForFrameSync()
+{
+ mDisplay->flushRequests();
+ while (mWaitingForFrameSync)
+ mDisplay->blockingReadEvents();
+}
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h
index 3b51ee7..47d49a7 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.h
+++ b/src/plugins/platforms/wayland/qwaylandwindow.h
@@ -43,8 +43,8 @@
#define QWAYLANDWINDOW_H
#include <QtGui/QPlatformWindow>
+#include <QtCore/QWaitCondition>
-#include <stdint.h>
#include "qwaylanddisplay.h"
class QWaylandDisplay;
@@ -70,11 +70,24 @@ public:
void configure(uint32_t time, uint32_t edges,
int32_t x, int32_t y, int32_t width, int32_t height);
+ void attach(QWaylandBuffer *buffer);
+ void damage(const QRegion &region);
+
+ void waitForFrameSync();
+
+ struct wl_surface *wl_surface() const { return mSurface; }
+
protected:
struct wl_surface *mSurface;
- virtual void newSurfaceCreated() = 0;
+ virtual void newSurfaceCreated();
QWaylandDisplay *mDisplay;
+ QWaylandBuffer *mBuffer;
WId mWindowId;
+ bool mWaitingForFrameSync;
+ QWaitCondition mFrameSyncWait;
+
+private:
+ static void frameCallback(struct wl_surface *surface, void *data, uint32_t time);
};
diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro
index face860..8d2d4b5 100644
--- a/src/plugins/platforms/wayland/wayland.pro
+++ b/src/plugins/platforms/wayland/wayland.pro
@@ -8,6 +8,7 @@ DEFINES += $$QMAKE_DEFINES_WAYLAND
SOURCES = main.cpp \
qwaylandintegration.cpp \
+ qwaylandnativeinterface.cpp \
qwaylandshmsurface.cpp \
qwaylandinputdevice.cpp \
qwaylandcursor.cpp \
@@ -17,40 +18,22 @@ SOURCES = main.cpp \
qwaylandshmwindow.cpp
HEADERS = qwaylandintegration.h \
+ qwaylandnativeinterface.h \
qwaylandcursor.h \
qwaylanddisplay.h \
qwaylandwindow.h \
qwaylandscreen.h \
qwaylandshmsurface.h \
- qwaylanddrmsurface.h \
qwaylandbuffer.h \
- qwaylandinclude.h \
- qwaylandeglwindow.h \
qwaylandshmwindow.h
INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND
LIBS += $$QMAKE_LIBS_WAYLAND
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_WAYLAND
-contains(QT_CONFIG, opengles2) {
- QT += opengl
- LIBS += -lwayland-egl -lEGL
+INCLUDEPATH += $$PWD
- SOURCES += qwaylanddrmsurface.cpp \
- qwaylandglcontext.cpp \
- ../eglconvenience/qeglconvenience.cpp \
- qwaylandeglwindow.cpp
-
- HEADERS += qwaylandglcontext.h \
- ../eglconvenience/qeglconvenience.h \
-
- DEFINES += QT_WAYLAND_GL_SUPPORT
-}
-
-unix:isEmpty(QMAKE_INCDIR_WAYLAND) {
- CONFIG += link_pkgconfig
- PKGCONFIG += libdrm
-}
+include ($$PWD/gl_integration/gl_integration.pri)
include (../fontdatabases/genericunix/genericunix.pri)
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index e88596b..17a86e6 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -1,2 +1,3 @@
Required packages:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev
+
diff --git a/src/plugins/platforms/xcb/qdri2context.cpp b/src/plugins/platforms/xcb/qdri2context.cpp
index 0079f91..dbbfa67 100644
--- a/src/plugins/platforms/xcb/qdri2context.cpp
+++ b/src/plugins/platforms/xcb/qdri2context.cpp
@@ -266,6 +266,6 @@ xcb_dri2_dri2_buffer_t * QDri2Context::backBuffer()
void * QDri2Context::eglContext() const
{
- Q_D(QDri2Context);
+ Q_D(const QDri2Context);
return d->eglContext;
}
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index e94b6a6..190221c 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -51,218 +51,29 @@
#include <GL/glx.h>
#include "qglxintegration.h"
+#include "qglxconvenience.h"
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
#include <dlfcn.h>
#endif
-QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive);
-
-QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format)
-{
- QVector<int> spec(48);
- int i = 0;
-
- spec[i++] = GLX_LEVEL;
- spec[i++] = 0;
- spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT;
-
- if (format.rgba()) {
- spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;
- spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize();
- spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize();
- spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize();
- if (format.alpha()) {
- spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize();
- }
-
- spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
-
- if (format.alpha()) {
- spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- }
-
- } else {
- spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works....
- spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8;
- }
-
- spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False;
- spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False;
-
- if (format.depth()) {
- spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize();
- }
-
- if (format.stencil()) {
- spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
- }
- if (format.sampleBuffers()) {
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = format.samples() == -1 ? 4 : format.samples();
- }
-
- spec[i++] = None;
- return spec;
-}
-
-GLXFBConfig QGLXContext::findConfig(const QXcbScreen *screen, const QPlatformWindowFormat &format)
-{
- bool reduced = true;
- GLXFBConfig chosenConfig = 0;
- QPlatformWindowFormat reducedFormat = format;
- while (!chosenConfig && reduced) {
- QVector<int> spec = buildSpec(reducedFormat);
- int confcount = 0;
- GLXFBConfig *configs;
- configs = glXChooseFBConfig(DISPLAY_FROM_XCB(screen), screen->screenNumber(), spec.constData(), &confcount);
- if (confcount)
- {
- for (int i = 0; i < confcount; i++) {
- chosenConfig = configs[i];
- // Make sure we try to get an ARGB visual if the format asked for an alpha:
- if (reducedFormat.alpha()) {
- int alphaSize;
- glXGetFBConfigAttrib(DISPLAY_FROM_XCB(screen), configs[i], GLX_ALPHA_SIZE, &alphaSize);
- if (alphaSize > 0)
- break;
- } else {
- break; // Just choose the first in the list if there's no alpha requested
- }
- }
-
- XFree(configs);
- }
- reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced);
- }
-
- if (!chosenConfig)
- qWarning("Warning no context created");
-
- return chosenConfig;
-}
-
-XVisualInfo *QGLXContext::findVisualInfo(const QXcbScreen *screen, const QPlatformWindowFormat &format)
-{
- GLXFBConfig config = QGLXContext::findConfig(screen,format);
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
- return visualInfo;
-}
-
-QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx)
-{
- QPlatformWindowFormat format;
- int redSize = 0;
- int greenSize = 0;
- int blueSize = 0;
- int alphaSize = 0;
- int depthSize = 0;
- int stencilSize = 0;
- int sampleBuffers = 0;
- int sampleCount = 0;
- int level = 0;
- int rgba = 0;
- int stereo = 0;
- int accumSizeA = 0;
- int accumSizeR = 0;
- int accumSizeG = 0;
- int accumSizeB = 0;
-
- XVisualInfo *vi = glXGetVisualFromFBConfig(display,config);
- glXGetConfig(display,vi,GLX_RGBA,&rgba);
- XFree(vi);
- glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize);
- glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize);
- glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize);
- glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize);
- glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize);
- glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers);
- glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level);
- glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB);
-
- format.setRedBufferSize(redSize);
- format.setGreenBufferSize(greenSize);
- format.setBlueBufferSize(blueSize);
- format.setAlphaBufferSize(alphaSize);
- format.setDepthBufferSize(depthSize);
- format.setStencilBufferSize(stencilSize);
- format.setSampleBuffers(sampleBuffers);
- if (format.sampleBuffers()) {
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount);
- format.setSamples(sampleCount);
- }
-
- format.setDirectRendering(glXIsDirect(display, ctx));
- format.setRgba(rgba);
- format.setStereo(stereo);
- format.setAccumBufferSize(accumSizeB);
-
- return format;
-}
-
-QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced)
-{
- QPlatformWindowFormat retFormat = format;
- *reduced = true;
-
- if (retFormat.sampleBuffers()) {
- retFormat.setSampleBuffers(false);
- } else if (retFormat.stereo()) {
- retFormat.setStereo(false);
- } else if (retFormat.accum()) {
- retFormat.setAccum(false);
- }else if (retFormat.stencil()) {
- retFormat.setStencil(false);
- }else if (retFormat.alpha()) {
- retFormat.setAlpha(false);
- }else if (retFormat.depth()) {
- retFormat.setDepth(false);
- }else if (retFormat.doubleBuffer()) {
- retFormat.setDoubleBuffer(false);
- }else{
- *reduced = false;
- }
- return retFormat;
-}
-
QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindowFormat &format)
: QPlatformGLContext()
, m_screen(screen)
, m_drawable((Drawable)window)
, m_context(0)
{
-
+ Q_XCB_NOOP(m_screen->connection());
const QPlatformGLContext *sharePlatformContext;
- if (format.useDefaultSharedContext()) {
- if (!QPlatformGLContext::defaultSharedContext()) {
- if (m_defaultSharedContextMutex.tryLock()){
- createDefaultSharedContex(screen);
- m_defaultSharedContextMutex.unlock();
- } else {
- m_defaultSharedContextMutex.lock(); //wait to the the shared context is created
- m_defaultSharedContextMutex.unlock();
- }
- }
- sharePlatformContext = QPlatformGLContext::defaultSharedContext();
- } else {
- sharePlatformContext = format.sharedGLContext();
- }
+ sharePlatformContext = format.sharedGLContext();
GLXContext shareGlxContext = 0;
if (sharePlatformContext)
shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext();
- GLXFBConfig config = findConfig(screen,format);
+ GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),format);
m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE);
- m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context);
+ m_windowFormat = qglx_platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context);
+ Q_XCB_NOOP(m_screen->connection());
}
QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context)
@@ -273,56 +84,39 @@ QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext conte
QGLXContext::~QGLXContext()
{
+ Q_XCB_NOOP(m_screen->connection());
if (m_context)
glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
-}
-
-void QGLXContext::createDefaultSharedContex(QXcbScreen *screen)
-{
- int x = 0;
- int y = 0;
- int w = 3;
- int h = 3;
-
- QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat();
- GLXContext context;
- GLXFBConfig config = findConfig(screen,format);
- if (config) {
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone);
- XSetWindowAttributes a;
- a.colormap = cmap;
- Window sharedWindow = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(), x, y, w, h,
- 0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWColormap, &a);
-
- context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, 0, TRUE);
- QPlatformGLContext *sharedContext = new QGLXContext(screen, sharedWindow, context);
- QPlatformGLContext::setDefaultSharedContext(sharedContext);
- } else {
- qWarning("Warning no shared context created");
- }
+ Q_XCB_NOOP(m_screen->connection());
}
void QGLXContext::makeCurrent()
{
+ Q_XCB_NOOP(m_screen->connection());
QPlatformGLContext::makeCurrent();
glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context);
+ Q_XCB_NOOP(m_screen->connection());
}
void QGLXContext::doneCurrent()
{
+ Q_XCB_NOOP(m_screen->connection());
QPlatformGLContext::doneCurrent();
glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0);
+ Q_XCB_NOOP(m_screen->connection());
}
void QGLXContext::swapBuffers()
{
+ Q_XCB_NOOP(m_screen->connection());
glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable);
+ doneCurrent();
+ Q_XCB_NOOP(m_screen->connection());
}
void* QGLXContext::getProcAddress(const QString& procName)
{
+ Q_XCB_NOOP(m_screen->connection());
typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *);
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
static bool resolved = false;
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index f2e20c4..99b72a0 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -66,22 +66,13 @@ public:
QPlatformWindowFormat platformWindowFormat() const;
- static XVisualInfo *findVisualInfo(const QXcbScreen *xd, const QPlatformWindowFormat &format);
-
private:
- static GLXFBConfig findConfig(const QXcbScreen *xd,const QPlatformWindowFormat &format);
- static QVector<int> buildSpec(const QPlatformWindowFormat &format);
- static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context);
- static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced);
-
QXcbScreen *m_screen;
Drawable m_drawable;
GLXContext m_context;
QPlatformWindowFormat m_windowFormat;
QGLXContext (QXcbScreen *screen, Drawable drawable, GLXContext context);
- static QMutex m_defaultSharedContextMutex;
- static void createDefaultSharedContex(QXcbScreen *xd);
};
#endif
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 191699b..7ad12fe 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -47,6 +47,7 @@
#include <QtAlgorithms>
#include <QSocketNotifier>
#include <QtGui/private/qapplication_p.h>
+#include <QAbstractEventDispatcher>
#include <QtCore/QDebug>
@@ -104,6 +105,8 @@ QXcbConnection::QXcbConnection(const char *displayName)
#endif //XCB_USE_XLIB
m_setup = xcb_get_setup(xcb_connection());
+ initializeAllAtoms();
+
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int screenNumber = 0;
@@ -112,16 +115,19 @@ QXcbConnection::QXcbConnection(const char *displayName)
xcb_screen_next(&it);
}
- QSocketNotifier *socket = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this);
- connect(socket, SIGNAL(activated(int)), this, SLOT(eventDispatcher()));
-
m_keyboard = new QXcbKeyboard(this);
- initializeAllAtoms();
-
#ifdef XCB_USE_DRI2
initializeDri2();
#endif
+
+ QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents()));
+
+ QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread());
+ connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents()));
+
+ sync();
}
QXcbConnection::~QXcbConnection()
@@ -148,8 +154,11 @@ QXcbWindow *platformWindowFromId(xcb_window_t id)
#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, window, handler) \
{ \
event_t *e = (event_t *)event; \
- if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) \
- platformWindow->handler(e); \
+ if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) { \
+ QObjectPrivate *d = QObjectPrivate::get(platformWindow->widget()); \
+ if (!d->wasDeleted) \
+ platformWindow->handler(e); \
+ } \
} \
break;
@@ -166,9 +175,9 @@ break;
void printXcbEvent(const char *message, xcb_generic_event_t *event)
{
#ifdef XCB_EVENT_DEBUG
-#define PRINT_XCB_EVENT(event) \
- case event: \
- printf("%s: %d - %s\n", message, event, #event); \
+#define PRINT_XCB_EVENT(ev) \
+ case ev: \
+ printf("%s: %d - %s - sequence: %d\n", message, int(ev), #ev, event->sequence); \
break;
switch (event->response_type & ~0x80) {
@@ -205,7 +214,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
default:
- printf("%s: %d - %s\n", message, event->response_type, "unknown");
+ printf("%s: unknown event - response_type: %d - sequence: %d\n", message, int(event->response_type & ~0x80), int(event->sequence));
}
#else
Q_UNUSED(message);
@@ -213,11 +222,216 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
#endif
}
-void QXcbConnection::eventDispatcher()
+const char *xcb_errors[] =
+{
+ "Success",
+ "BadRequest",
+ "BadValue",
+ "BadWindow",
+ "BadPixmap",
+ "BadAtom",
+ "BadCursor",
+ "BadFont",
+ "BadMatch",
+ "BadDrawable",
+ "BadAccess",
+ "BadAlloc",
+ "BadColor",
+ "BadGC",
+ "BadIDChoice",
+ "BadName",
+ "BadLength",
+ "BadImplementation",
+ "Unknown"
+};
+
+const char *xcb_protocol_request_codes[] =
+{
+ "Null",
+ "CreateWindow",
+ "ChangeWindowAttributes",
+ "GetWindowAttributes",
+ "DestroyWindow",
+ "DestroySubwindows",
+ "ChangeSaveSet",
+ "ReparentWindow",
+ "MapWindow",
+ "MapSubwindows",
+ "UnmapWindow",
+ "UnmapSubwindows",
+ "ConfigureWindow",
+ "CirculateWindow",
+ "GetGeometry",
+ "QueryTree",
+ "InternAtom",
+ "GetAtomName",
+ "ChangeProperty",
+ "DeleteProperty",
+ "GetProperty",
+ "ListProperties",
+ "SetSelectionOwner",
+ "GetSelectionOwner",
+ "ConvertSelection",
+ "SendEvent",
+ "GrabPointer",
+ "UngrabPointer",
+ "GrabButton",
+ "UngrabButton",
+ "ChangeActivePointerGrab",
+ "GrabKeyboard",
+ "UngrabKeyboard",
+ "GrabKey",
+ "UngrabKey",
+ "AllowEvents",
+ "GrabServer",
+ "UngrabServer",
+ "QueryPointer",
+ "GetMotionEvents",
+ "TranslateCoords",
+ "WarpPointer",
+ "SetInputFocus",
+ "GetInputFocus",
+ "QueryKeymap",
+ "OpenFont",
+ "CloseFont",
+ "QueryFont",
+ "QueryTextExtents",
+ "ListFonts",
+ "ListFontsWithInfo",
+ "SetFontPath",
+ "GetFontPath",
+ "CreatePixmap",
+ "FreePixmap",
+ "CreateGC",
+ "ChangeGC",
+ "CopyGC",
+ "SetDashes",
+ "SetClipRectangles",
+ "FreeGC",
+ "ClearArea",
+ "CopyArea",
+ "CopyPlane",
+ "PolyPoint",
+ "PolyLine",
+ "PolySegment",
+ "PolyRectangle",
+ "PolyArc",
+ "FillPoly",
+ "PolyFillRectangle",
+ "PolyFillArc",
+ "PutImage",
+ "GetImage",
+ "PolyText8",
+ "PolyText16",
+ "ImageText8",
+ "ImageText16",
+ "CreateColormap",
+ "FreeColormap",
+ "CopyColormapAndFree",
+ "InstallColormap",
+ "UninstallColormap",
+ "ListInstalledColormaps",
+ "AllocColor",
+ "AllocNamedColor",
+ "AllocColorCells",
+ "AllocColorPlanes",
+ "FreeColors",
+ "StoreColors",
+ "StoreNamedColor",
+ "QueryColors",
+ "LookupColor",
+ "CreateCursor",
+ "CreateGlyphCursor",
+ "FreeCursor",
+ "RecolorCursor",
+ "QueryBestSize",
+ "QueryExtension",
+ "ListExtensions",
+ "ChangeKeyboardMapping",
+ "GetKeyboardMapping",
+ "ChangeKeyboardControl",
+ "GetKeyboardControl",
+ "Bell",
+ "ChangePointerControl",
+ "GetPointerControl",
+ "SetScreenSaver",
+ "GetScreenSaver",
+ "ChangeHosts",
+ "ListHosts",
+ "SetAccessControl",
+ "SetCloseDownMode",
+ "KillClient",
+ "RotateProperties",
+ "ForceScreenSaver",
+ "SetPointerMapping",
+ "GetPointerMapping",
+ "SetModifierMapping",
+ "GetModifierMapping",
+ "Unknown"
+};
+
+#ifdef Q_XCB_DEBUG
+void QXcbConnection::log(const char *file, int line, int sequence)
+{
+ CallInfo info;
+ info.sequence = sequence;
+ info.file = file;
+ info.line = line;
+ m_callLog << info;
+}
+#endif
+
+void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
+{
+ uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
+ uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
+
+ printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n",
+ int(error->error_code), xcb_errors[clamped_error_code],
+ int(error->sequence), int(error->resource_id),
+ int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
+ int(error->minor_code));
+#ifdef Q_XCB_DEBUG
+ int i = 0;
+ for (; i < m_callLog.size(); ++i) {
+ if (m_callLog.at(i).sequence == error->sequence) {
+ printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
+ break;
+ } else if (m_callLog.at(i).sequence > error->sequence) {
+ printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line);
+ if (i > 0)
+ printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line);
+ break;
+ }
+ }
+ if (i == m_callLog.size() && !m_callLog.isEmpty())
+ printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line);
+#endif
+}
+
+void QXcbConnection::processXcbEvents()
{
while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) {
bool handled = true;
- switch (event->response_type & ~0x80) {
+
+ uint response_type = event->response_type & ~0x80;
+
+ if (!response_type) {
+ handleXcbError((xcb_generic_error_t *)event);
+ continue;
+ }
+
+#ifdef Q_XCB_DEBUG
+ {
+ int i = 0;
+ for (; i < m_callLog.size(); ++i)
+ if (m_callLog.at(i).sequence >= event->sequence)
+ break;
+ m_callLog.remove(0, i);
+ }
+#endif
+
+ switch (response_type) {
case XCB_EXPOSE:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
case XCB_BUTTON_PRESS:
@@ -247,13 +461,15 @@ void QXcbConnection::eventDispatcher()
break;
default:
handled = false;
- return;
+ break;
}
if (handled)
printXcbEvent("Handled XCB event", event);
else
printXcbEvent("Unhandled XCB event", event);
}
+
+ xcb_flush(xcb_connection());
}
static const char * xcb_atomnames = {
@@ -447,6 +663,13 @@ void QXcbConnection::initializeAllAtoms() {
m_allAtoms[i] = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0)->atom;
}
+void QXcbConnection::sync()
+{
+ // from xcb_aux_sync
+ xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
+ free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index e00fbb1..6b5f810 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -46,6 +46,9 @@
#include <QList>
#include <QObject>
+#include <QVector>
+
+#define Q_XCB_DEBUG
class QXcbScreen;
@@ -221,6 +224,8 @@ public:
QXcbConnection(const char *displayName = 0);
~QXcbConnection();
+ QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
+
QList<QXcbScreen *> screens() const { return m_screens; }
int primaryScreen() const { return m_primaryScreen; }
@@ -247,11 +252,15 @@ public:
void *egl_display() const { return m_egl_display; }
#endif
+ void sync();
+ void handleXcbError(xcb_generic_error_t *error);
+
private slots:
- void eventDispatcher();
+ void processXcbEvents();
private:
void initializeAllAtoms();
+ void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
@@ -283,10 +292,38 @@ private:
void *m_egl_display;
bool m_has_egl;
#endif
+#ifdef Q_XCB_DEBUG
+ struct CallInfo {
+ int sequence;
+ QByteArray file;
+ int line;
+ };
+ QVector<CallInfo> m_callLog;
+ void log(const char *file, int line, int sequence);
+ template <typename cookie_t>
+ friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line);
+#endif
};
#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
+#ifdef Q_XCB_DEBUG
+template <typename cookie_t>
+cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file, int line)
+{
+ connection->log(file, line, cookie.sequence);
+ return cookie;
+}
+#define Q_XCB_CALL(x) q_xcb_call_template(x, connection(), __FILE__, __LINE__)
+#define Q_XCB_CALL2(x, connection) q_xcb_call_template(x, connection, __FILE__, __LINE__)
+#define Q_XCB_NOOP(c) q_xcb_call_template(xcb_no_operation(c->xcb_connection()), c, __FILE__, __LINE__);
+#else
+#define Q_XCB_CALL(x) x
+#define Q_XCB_CALL2(x, connection) x
+#define Q_XCB_NOOP(c)
+#endif
+
+
#if defined(XCB_USE_DRI2) || defined(XCB_USE_EGL)
#define EGL_DISPLAY_FROM_XCB(object) ((EGLDisplay)(object->connection()->egl_display()))
#endif //endifXCB_USE_DRI2
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 63c26a1..9df5f14 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -73,6 +73,15 @@ QXcbIntegration::~QXcbIntegration()
delete m_connection;
}
+bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL: return hasOpenGL();
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
QPixmapData *QXcbIntegration::createPixmapData(QPixmapData::PixelType type) const
{
return new QRasterPixmapData(type);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 6c9634e..d27fd71 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -55,6 +55,7 @@ public:
QXcbIntegration();
~QXcbIntegration();
+ bool hasCapability(Capability cap) const;
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const;
QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const;
@@ -65,11 +66,11 @@ public:
QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
QPlatformFontDatabase *fontDatabase() const;
- bool hasOpenGL() const;
QPlatformNativeInterface *nativeInterface()const;
private:
+ bool hasOpenGL() const;
QList<QPlatformScreen *> m_screens;
QXcbConnection *m_connection;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index ec9a009..f501c00 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -921,6 +921,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod
if (state & 128)
col += altGrOffset;
+ Q_XCB_NOOP(connection());
+
#ifdef XCB_KEYBOARD_DEBUG
printf("key code: %d, state: %d, syms: ", code, state);
for (int i = 0; i <= 5; ++i) {
@@ -929,6 +931,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod
printf("\n");
#endif
+ Q_XCB_NOOP(connection());
+
xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col);
if (sym == XCB_NO_SYMBOL)
sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1);
@@ -940,6 +944,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod
sym = toupper(sym);
}
+ Q_XCB_NOOP(connection());
+
QByteArray chars;
Qt::KeyboardModifiers modifiers;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index fffeb2e..1c12ee3 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -60,13 +60,48 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
const quint32 mask = XCB_CW_EVENT_MASK;
const quint32 values[] = {
// XCB_CW_EVENT_MASK
- XCB_EVENT_MASK_KEYMAP_STATE
- | XCB_EVENT_MASK_ENTER_WINDOW
+ XCB_EVENT_MASK_ENTER_WINDOW
| XCB_EVENT_MASK_LEAVE_WINDOW
| XCB_EVENT_MASK_PROPERTY_CHANGE
};
xcb_change_window_attributes(xcb_connection(), screen->root, mask, values);
+
+ xcb_generic_error_t *error;
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(xcb_connection(),
+ xcb_get_property(xcb_connection(), false, screen->root,
+ atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
+ XCB_ATOM_WINDOW, 0, 1024), &error);
+
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
+ xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply));
+
+ if (windowManager != XCB_WINDOW_NONE) {
+ xcb_get_property_reply_t *windowManagerReply =
+ xcb_get_property_reply(xcb_connection(),
+ xcb_get_property(xcb_connection(), false, windowManager,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING), 0, 1024), &error);
+ if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
+ m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
+ printf("Running window manager: %s\n", qPrintable(m_windowManagerName));
+ } else if (error) {
+ connection->handleXcbError(error);
+ free(error);
+ }
+
+ free(windowManagerReply);
+ }
+ } else if (error) {
+ connection->handleXcbError(error);
+ free(error);
+ }
+
+ free(reply);
+
+ m_syncRequestSupported = m_windowManagerName != QLatin1String("KWin");
}
QXcbScreen::~QXcbScreen()
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 6f69fc7..9547d01 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -43,6 +43,7 @@
#define QXCBSCREEN_H
#include <QtGui/QPlatformScreen>
+#include <QtCore/QString>
#include <xcb/xcb.h>
@@ -66,9 +67,14 @@ public:
xcb_screen_t *screen() const { return m_screen; }
xcb_window_t root() const { return m_screen->root; }
+ QString windowManagerName() const { return m_windowManagerName; }
+ bool syncRequestSupported() const { return m_syncRequestSupported; }
+
private:
xcb_screen_t *m_screen;
int m_number;
+ QString m_windowManagerName;
+ bool m_syncRequestSupported;
};
#endif
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index cbf50f7..0456638 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -41,6 +41,8 @@
#include "qxcbwindow.h"
+#include <QtDebug>
+
#include "qxcbconnection.h"
#include "qxcbscreen.h"
#ifdef XCB_USE_DRI2
@@ -63,6 +65,7 @@
#if defined(XCB_USE_GLX)
#include "qglxintegration.h"
+#include "qglxconvenience.h"
#elif defined(XCB_USE_EGL)
#include "../eglconvenience/qeglplatformcontext.h"
#include "../eglconvenience/qeglconvenience.h"
@@ -110,13 +113,14 @@ QXcbWindow::QXcbWindow(QWidget *tlw)
#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
- && QApplicationPrivate::platformIntegration()->hasOpenGL() ) {
+ && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
+ {
#if defined(XCB_USE_GLX)
- XVisualInfo *visualInfo = QGLXContext::findVisualInfo(m_screen, tlw->platformWindowFormat());
+ XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat());
#elif defined(XCB_USE_EGL)
- EGLDisplay eglDisplay = eglGetDisplay(DISPLAY_FROM_XCB(this));
+ EGLDisplay eglDisplay = connection()->egl_display();
EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true);
- VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this),eglConfig);
+ VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
@@ -126,42 +130,42 @@ QXcbWindow::QXcbWindow(QWidget *tlw)
int matchingCount = 0;
visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
#endif //XCB_USE_GLX
- if (visualInfo) {
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone);
-
- XSetWindowAttributes a;
- a.colormap = cmap;
- m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(),
- 0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWColormap, &a);
-
- printf("created GL window: %d\n", m_window);
- } else {
- qFatal("no window!");
- }
+ if (visualInfo) {
+ Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone);
+
+ XSetWindowAttributes a;
+ a.colormap = cmap;
+ m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(),
+ 0, visualInfo->depth, InputOutput, visualInfo->visual,
+ CWColormap, &a);
+
+ printf("created GL window: %d\n", m_window);
+ } else {
+ qFatal("no window!");
+ }
} else
#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
{
m_window = xcb_generate_id(xcb_connection());
- xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- m_window, // window id
- m_screen->root(), // parent window id
- tlw->x(),
- tlw->y(),
- tlw->width(),
- tlw->height(),
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- m_screen->screen()->root_visual, // visual
- 0, // value mask
- 0); // value list
+ Q_XCB_CALL(xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_window, // window id
+ m_screen->root(), // parent window id
+ tlw->x(),
+ tlw->y(),
+ tlw->width(),
+ tlw->height(),
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ m_screen->screen()->root_visual, // visual
+ 0, // value mask
+ 0)); // value list
printf("created regular window: %d\n", m_window);
}
- xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
+ Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
xcb_atom_t properties[4];
int propertyCount = 0;
@@ -169,32 +173,60 @@ QXcbWindow::QXcbWindow(QWidget *tlw)
properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
+ if (m_screen->syncRequestSupported())
+ properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
+
if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::WM_PROTOCOLS),
- 4,
- 32,
- propertyCount,
- properties);
+ Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::WM_PROTOCOLS),
+ XCB_ATOM_ATOM,
+ 32,
+ propertyCount,
+ properties));
+ m_syncValue.hi = 0;
+ m_syncValue.lo = 0;
+
+ if (m_screen->syncRequestSupported()) {
+ m_syncCounter = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));
+
+ Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
+ XCB_ATOM_CARDINAL,
+ 32,
+ 1,
+ &m_syncCounter));
+ }
if (isTransient(tlw) && tlw->parentWidget()) {
// ICCCM 4.1.2.6
QWidget *p = tlw->parentWidget()->window();
xcb_window_t parentWindow = p->winId();
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
- 1, &parentWindow);
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
+ 1, &parentWindow));
}
+
+ // set the PID to let the WM kill the application if unresponsive
+ long pid = getpid();
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
+ 1, &pid));
}
QXcbWindow::~QXcbWindow()
{
- xcb_destroy_window(xcb_connection(), m_window);
+ delete m_context;
+ if (m_screen->syncRequestSupported())
+ Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
+ Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
}
void QXcbWindow::setGeometry(const QRect &rect)
@@ -204,7 +236,7 @@ void QXcbWindow::setGeometry(const QRect &rect)
const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const quint32 values[] = { rect.x(), rect.y(), rect.width(), rect.height() };
- xcb_configure_window(xcb_connection(), m_window, mask, values);
+ Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
}
void QXcbWindow::setVisible(bool visible)
@@ -216,9 +248,10 @@ void QXcbWindow::setVisible(bool visible)
else
xcb_wm_hints_set_normal(&hints);
xcb_set_wm_hints(xcb_connection(), m_window, &hints);
- xcb_map_window(xcb_connection(), m_window);
+ Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
+ connection()->sync();
} else {
- xcb_unmap_window(xcb_connection(), m_window);
+ Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
// send synthetic UnmapNotify event according to icccm 4.1.4
xcb_unmap_notify_event_t event;
@@ -227,8 +260,8 @@ void QXcbWindow::setVisible(bool visible)
event.event = m_screen->root();
event.window = m_window;
event.from_configure = false;
- xcb_send_event(xcb_connection(), false, m_screen->root(),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event);
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(),
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
xcb_flush(xcb_connection());
}
@@ -271,6 +304,8 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
+ setNetWmWindowTypes(flags);
+
if (type == Qt::ToolTip)
flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
if (type == Qt::Popup)
@@ -352,28 +387,64 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
}
if (mwmhints.flags != 0l) {
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_MOTIF_WM_HINTS),
- atom(QXcbAtom::_MOTIF_WM_HINTS),
- 32,
- 5,
- &mwmhints);
+ Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_MOTIF_WM_HINTS),
+ atom(QXcbAtom::_MOTIF_WM_HINTS),
+ 32,
+ 5,
+ &mwmhints));
} else {
- xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS));
+ Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)));
}
if (popup || tooltip) {
const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
const quint32 values[] = { true, true };
- xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
+ Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
}
return QPlatformWindow::setWindowFlags(flags);
}
+void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
+{
+ // in order of decreasing priority
+ QVector<uint> windowTypes;
+
+ Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
+
+ switch (type) {
+ case Qt::Dialog:
+ case Qt::Sheet:
+ windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ break;
+ case Qt::Tool:
+ case Qt::Drawer:
+ windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ break;
+ case Qt::ToolTip:
+ windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ break;
+ case Qt::SplashScreen:
+ windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ break;
+ default:
+ break;
+ }
+
+ if (flags & Qt::FramelessWindowHint)
+ windowTypes.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+
+ windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
+ windowTypes.count(), windowTypes.constData()));
+}
+
WId QXcbWindow::winId() const
{
return m_window;
@@ -382,56 +453,54 @@ WId QXcbWindow::winId() const
void QXcbWindow::setParent(const QPlatformWindow *parent)
{
QPoint topLeft = geometry().topLeft();
- xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y());
+ Q_XCB_CALL(xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y()));
}
void QXcbWindow::setWindowTitle(const QString &title)
{
QByteArray ba = title.toUtf8();
- xcb_change_property (xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
+ Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData()));
}
void QXcbWindow::raise()
{
const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
const quint32 values[] = { XCB_STACK_MODE_ABOVE };
- xcb_configure_window(xcb_connection(), m_window, mask, values);
+ Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
}
void QXcbWindow::lower()
{
const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
const quint32 values[] = { XCB_STACK_MODE_BELOW };
- xcb_configure_window(xcb_connection(), m_window, mask, values);
+ Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
}
void QXcbWindow::requestActivateWindow()
{
- xcb_set_input_focus(xcb_connection(), m_window, XCB_INPUT_FOCUS_PARENT, XCB_TIME_CURRENT_TIME);
+ Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME));
+ connection()->sync();
}
QPlatformGLContext *QXcbWindow::glContext() const
{
- if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) {
+ if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
printf("no opengl\n");
return 0;
}
-#if defined(XCB_USE_GLX)
if (!m_context) {
+#if defined(XCB_USE_GLX)
QXcbWindow *that = const_cast<QXcbWindow *>(this);
that->m_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat());
- }
#elif defined(XCB_USE_EGL)
- if (!m_context) {
- EGLDisplay display = eglGetDisplay(DISPLAY_FROM_XCB(this));
-
+ EGLDisplay display = connection()->egl_display();
EGLConfig config = q_configFromQPlatformWindowFormat(display,widget()->platformWindowFormat(),true);
QVector<EGLint> eglContextAttrs;
eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
@@ -441,14 +510,11 @@ QPlatformGLContext *QXcbWindow::glContext() const
EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)m_window,0);
QXcbWindow *that = const_cast<QXcbWindow *>(this);
that->m_context = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API);
- }
#elif defined(XCB_USE_DRI2)
- if (!m_context) {
QXcbWindow *that = const_cast<QXcbWindow *>(this);
that->m_context = new QDri2Context(that);
- }
-
#endif
+ }
return m_context;
}
@@ -467,6 +533,21 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
if (event->format == 32 && event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
QWindowSystemInterface::handleCloseEvent(widget());
+ } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
+ xcb_client_message_event_t reply = *event;
+
+ reply.response_type = XCB_CLIENT_MESSAGE;
+ reply.window = m_screen->root();
+
+ xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
+ xcb_flush(xcb_connection());
+ } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
+ if (!m_hasReceivedSyncRequest) {
+ m_hasReceivedSyncRequest = true;
+ printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n");
+ }
+ m_syncValue.lo = event->data.data32[2];
+ m_syncValue.hi = event->data.data32[3];
}
}
}
@@ -482,8 +563,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
QRect rect(xpos, ypos, event->width, event->height);
- QPlatformWindow::setGeometry(rect);
+ if (rect == geometry())
+ return;
+
+ QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(widget(), rect);
#if XCB_USE_DRI2
@@ -586,3 +670,14 @@ void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
QWindowSystemInterface::handleWindowActivated(0);
}
+void QXcbWindow::updateSyncRequestCounter()
+{
+ if (m_screen->syncRequestSupported() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
+ Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
+ xcb_flush(xcb_connection());
+ connection()->sync();
+
+ m_syncValue.lo = 0;
+ m_syncValue.hi = 0;
+ }
+}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 1e9930d..e049837 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -46,6 +46,7 @@
#include <QtGui/QPlatformWindowFormat>
#include <xcb/xcb.h>
+#include <xcb/sync.h>
#include "qxcbobject.h"
@@ -88,11 +89,20 @@ public:
void handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global);
+ void updateSyncRequestCounter();
+
private:
+ void setNetWmWindowTypes(Qt::WindowFlags flags);
+
QXcbScreen *m_screen;
xcb_window_t m_window;
QPlatformGLContext *m_context;
+
+ xcb_sync_int64_t m_syncValue;
+ xcb_sync_counter_t m_syncCounter;
+
+ bool m_hasReceivedSyncRequest;
};
#endif
diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp
index 7fed230..718f093 100644
--- a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp
@@ -53,6 +53,8 @@
#include <stdio.h>
+#include <qdebug.h>
+
class QXcbShmImage : public QXcbObject
{
public:
@@ -84,6 +86,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size)
, m_gc(0)
, m_gc_window(0)
{
+ Q_XCB_NOOP(connection());
m_xcb_image = xcb_image_create_native(xcb_connection(),
size.width(),
size.height(),
@@ -92,38 +95,49 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size)
0,
~0,
0);
+
m_shm_info.shmid = shmget (IPC_PRIVATE,
m_xcb_image->stride * m_xcb_image->height, IPC_CREAT|0777);
m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat (m_shm_info.shmid, 0, 0);
m_shm_info.shmseg = xcb_generate_id(xcb_connection());
- xcb_shm_attach(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false);
+ xcb_generic_error_t *error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false));
+ if (error) {
+ qWarning() << "QXcbWindowSurface: Unable to attach to shared memory segment";
+ free(error);
+ }
+
+ if (shmctl(m_shm_info.shmid, IPC_RMID, 0) == -1)
+ qWarning() << "QXcbWindowSurface: Error while marking the shared memory segment to be destroyed";
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, screen->format());
}
void QXcbShmImage::destroy()
{
- xcb_shm_detach(xcb_connection(), m_shm_info.shmseg);
+ Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
xcb_image_destroy(m_xcb_image);
shmdt(m_shm_info.shmaddr);
shmctl(m_shm_info.shmid, IPC_RMID, 0);
-
- xcb_free_gc(xcb_connection(), m_gc);
+ if (m_gc)
+ Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
}
void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source)
{
+ Q_XCB_NOOP(connection());
if (m_gc_window != window) {
- xcb_free_gc(xcb_connection(), m_gc);
+ if (m_gc)
+ Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
m_gc = xcb_generate_id(xcb_connection());
- xcb_create_gc(xcb_connection(), m_gc, window, 0, 0);
+ Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, 0, 0));
m_gc_window = window;
}
+ Q_XCB_NOOP(connection());
xcb_image_shm_put(xcb_connection(),
window,
m_gc,
@@ -136,18 +150,19 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s
source.width(),
source.height(),
false);
+ Q_XCB_NOOP(connection());
m_dirty = m_dirty | source;
xcb_flush(xcb_connection());
+ Q_XCB_NOOP(connection());
}
void QXcbShmImage::preparePaint(const QRegion &region)
{
// to prevent X from reading from the image region while we're writing to it
if (m_dirty.intersects(region)) {
- // from xcb_aux_sync
- free(xcb_get_input_focus_reply(xcb_connection(), xcb_get_input_focus(xcb_connection()), 0));
+ connection()->sync();
m_dirty = QRegion();
}
}
@@ -155,16 +170,15 @@ void QXcbShmImage::preparePaint(const QRegion &region)
QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface)
: QWindowSurface(widget, setDefaultSurface)
, m_image(0)
+ , m_syncingResize(false)
{
- setStaticContentsSupport(false);
- setPartialUpdateSupport(true);
-
QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget));
setConnection(screen->connection());
}
QXcbWindowSurface::~QXcbWindowSurface()
{
+ delete m_image;
}
QPaintDevice *QXcbWindowSurface::paintDevice()
@@ -177,10 +191,18 @@ void QXcbWindowSurface::beginPaint(const QRegion &region)
m_image->preparePaint(region);
}
+void QXcbWindowSurface::endPaint(const QRegion &)
+{
+}
+
void QXcbWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &offset)
{
- Q_UNUSED(region);
- Q_UNUSED(offset);
+ QRect bounds = region.boundingRect();
+
+ if (size().isEmpty() || !geometry().contains(bounds))
+ return;
+
+ Q_XCB_NOOP(connection());
QXcbWindow *window = static_cast<QXcbWindow *>(widget->window()->platformWindow());
@@ -190,16 +212,32 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion &region, const QPoi
QVector<QRect> rects = region.rects();
for (int i = 0; i < rects.size(); ++i)
m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset));
+
+ Q_XCB_NOOP(connection());
+
+ if (m_syncingResize) {
+ xcb_flush(xcb_connection());
+ connection()->sync();
+ m_syncingResize = false;
+ window->updateSyncRequestCounter();
+ }
}
void QXcbWindowSurface::resize(const QSize &size)
{
+ if (size == QWindowSurface::size())
+ return;
+
+ Q_XCB_NOOP(connection());
QWindowSurface::resize(size);
QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(window()));
delete m_image;
m_image = new QXcbShmImage(screen, size);
+ Q_XCB_NOOP(connection());
+
+ m_syncingResize = true;
}
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.h b/src/plugins/platforms/xcb/qxcbwindowsurface.h
index 61689b1..23d32ef 100644
--- a/src/plugins/platforms/xcb/qxcbwindowsurface.h
+++ b/src/plugins/platforms/xcb/qxcbwindowsurface.h
@@ -62,9 +62,11 @@ public:
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &);
+ void endPaint(const QRegion &);
private:
QXcbShmImage *m_image;
+ bool m_syncingResize;
};
#endif
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index fdbe2cd..101bdcd 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -55,13 +55,14 @@ contains(QT_CONFIG, opengl) {
LIBS += -lEGL
} else {
DEFINES += XCB_USE_GLX
+ include (../glxconvenience/glxconvenience.pri)
HEADERS += qglxintegration.h
SOURCES += qglxintegration.cpp
}
}
}
-LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm
+LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync
include (../fontdatabases/genericunix/genericunix.pri)
diff --git a/src/plugins/platforms/xlib/qglxintegration.cpp b/src/plugins/platforms/xlib/qglxintegration.cpp
index 80011d9..7a0f36d 100644
--- a/src/plugins/platforms/xlib/qglxintegration.cpp
+++ b/src/plugins/platforms/xlib/qglxintegration.cpp
@@ -51,6 +51,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
+#include "qglxconvenience.h"
#include "qglxintegration.h"
@@ -60,184 +61,6 @@
QT_BEGIN_NAMESPACE
-QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive);
-
-QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format)
-{
- QVector<int> spec(48);
- int i = 0;
-
- spec[i++] = GLX_LEVEL;
- spec[i++] = 0;
- spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT;
-
- if (format.rgba()) {
- spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT;
- spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize();
- spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize();
- spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize();
- if (format.alpha()) {
- spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize();
- }
-
- spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
-
- if (format.alpha()) {
- spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize();
- }
-
- } else {
- spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works....
- spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8;
- }
-
- spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False;
- spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False;
-
- if (format.depth()) {
- spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize();
- }
-
- if (format.stencil()) {
- spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize();
- }
- if (format.sampleBuffers()) {
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = format.samples() == -1 ? 4 : format.samples();
- }
-
- spec[i++] = XNone;
- return spec;
-}
-
-GLXFBConfig QGLXContext::findConfig(const QXlibScreen *screen, const QPlatformWindowFormat &format)
-{
- bool reduced = true;
- GLXFBConfig chosenConfig = 0;
- QPlatformWindowFormat reducedFormat = format;
- while (!chosenConfig && reduced) {
- QVector<int> spec = buildSpec(reducedFormat);
- int confcount = 0;
- GLXFBConfig *configs;
- configs = glXChooseFBConfig(screen->display()->nativeDisplay(),screen->xScreenNumber(),spec.constData(),&confcount);
- if (confcount)
- {
- for (int i = 0; i < confcount; i++) {
- chosenConfig = configs[i];
- // Make sure we try to get an ARGB visual if the format asked for an alpha:
- if (reducedFormat.alpha()) {
- int alphaSize;
- glXGetFBConfigAttrib(screen->display()->nativeDisplay(),configs[i],GLX_ALPHA_SIZE,&alphaSize);
- if (alphaSize > 0)
- break;
- } else {
- break; // Just choose the first in the list if there's no alpha requested
- }
- }
-
- XFree(configs);
- }
- reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced);
- }
-
- if (!chosenConfig)
- qWarning("Warning no context created");
-
- return chosenConfig;
-}
-
-XVisualInfo *QGLXContext::findVisualInfo(const QXlibScreen *screen, const QPlatformWindowFormat &format)
-{
- GLXFBConfig config = QGLXContext::findConfig(screen,format);
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config);
- return visualInfo;
-}
-
-QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx)
-{
- QPlatformWindowFormat format;
- int redSize = 0;
- int greenSize = 0;
- int blueSize = 0;
- int alphaSize = 0;
- int depthSize = 0;
- int stencilSize = 0;
- int sampleBuffers = 0;
- int sampleCount = 0;
- int level = 0;
- int rgba = 0;
- int stereo = 0;
- int accumSizeA = 0;
- int accumSizeR = 0;
- int accumSizeG = 0;
- int accumSizeB = 0;
-
- XVisualInfo *vi = glXGetVisualFromFBConfig(display,config);
- glXGetConfig(display,vi,GLX_RGBA,&rgba);
- XFree(vi);
- glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize);
- glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize);
- glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize);
- glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize);
- glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize);
- glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers);
- glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level);
- glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG);
- glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB);
-
- format.setRedBufferSize(redSize);
- format.setGreenBufferSize(greenSize);
- format.setBlueBufferSize(blueSize);
- format.setAlphaBufferSize(alphaSize);
- format.setDepthBufferSize(depthSize);
- format.setStencilBufferSize(stencilSize);
- format.setSampleBuffers(sampleBuffers);
- if (format.sampleBuffers()) {
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount);
- format.setSamples(sampleCount);
- }
-
- format.setDirectRendering(glXIsDirect(display, ctx));
- format.setRgba(rgba);
- format.setStereo(stereo);
- format.setAccumBufferSize(accumSizeB);
-
- return format;
-}
-
-QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced)
-{
- QPlatformWindowFormat retFormat = format;
- *reduced = true;
-
- if (retFormat.sampleBuffers()) {
- retFormat.setSampleBuffers(false);
- } else if (retFormat.stereo()) {
- retFormat.setStereo(false);
- } else if (retFormat.accum()) {
- retFormat.setAccum(false);
- }else if (retFormat.stencil()) {
- retFormat.setStencil(false);
- }else if (retFormat.alpha()) {
- retFormat.setAlpha(false);
- }else if (retFormat.depth()) {
- retFormat.setDepth(false);
- }else if (retFormat.doubleBuffer()) {
- retFormat.setDoubleBuffer(false);
- }else{
- *reduced = false;
- }
- return retFormat;
-}
-
QGLXContext::QGLXContext(Window window, QXlibScreen *screen, const QPlatformWindowFormat &format)
: QPlatformGLContext()
, m_screen(screen)
@@ -246,27 +69,14 @@ QGLXContext::QGLXContext(Window window, QXlibScreen *screen, const QPlatformWind
{
const QPlatformGLContext *sharePlatformContext;
- if (format.useDefaultSharedContext()) {
- if (!QPlatformGLContext::defaultSharedContext()) {
- if (m_defaultSharedContextMutex.tryLock()){
- createDefaultSharedContex(screen);
- m_defaultSharedContextMutex.unlock();
- } else {
- m_defaultSharedContextMutex.lock(); //wait to the the shared context is created
- m_defaultSharedContextMutex.unlock();
- }
- }
- sharePlatformContext = QPlatformGLContext::defaultSharedContext();
- } else {
- sharePlatformContext = format.sharedGLContext();
- }
+ sharePlatformContext = format.sharedGLContext();
GLXContext shareGlxContext = 0;
if (sharePlatformContext)
shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext();
- GLXFBConfig config = findConfig(screen,format);
+ GLXFBConfig config = qglx_findConfig(screen->display()->nativeDisplay(),screen->xScreenNumber(),format);
m_context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,shareGlxContext,TRUE);
- m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(screen->display()->nativeDisplay(),config,m_context);
+ m_windowFormat = qglx_platformWindowFromGLXFBConfig(screen->display()->nativeDisplay(),config,m_context);
#ifdef MYX11_DEBUG
qDebug() << "QGLXGLContext::create context" << m_context;
@@ -287,33 +97,6 @@ QGLXContext::~QGLXContext()
}
}
-void QGLXContext::createDefaultSharedContex(QXlibScreen *screen)
-{
- int x = 0;
- int y = 0;
- int w = 3;
- int h = 3;
-
- QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat();
- GLXContext context;
- GLXFBConfig config = findConfig(screen,format);
- if (config) {
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config);
- Colormap cmap = XCreateColormap(screen->display()->nativeDisplay(),screen->rootWindow(),visualInfo->visual,AllocNone);
- XSetWindowAttributes a;
- a.colormap = cmap;
- Window sharedWindow = XCreateWindow(screen->display()->nativeDisplay(), screen->rootWindow(),x, y, w, h,
- 0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWColormap, &a);
-
- context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,0,TRUE);
- QPlatformGLContext *sharedContext = new QGLXContext(screen,sharedWindow,context);
- QPlatformGLContext::setDefaultSharedContext(sharedContext);
- } else {
- qWarning("Warning no shared context created");
- }
-}
-
void QGLXContext::makeCurrent()
{
QPlatformGLContext::makeCurrent();
diff --git a/src/plugins/platforms/xlib/qglxintegration.h b/src/plugins/platforms/xlib/qglxintegration.h
index dbb5c2e..57c716b 100644
--- a/src/plugins/platforms/xlib/qglxintegration.h
+++ b/src/plugins/platforms/xlib/qglxintegration.h
@@ -69,22 +69,13 @@ public:
QPlatformWindowFormat platformWindowFormat() const;
- static XVisualInfo *findVisualInfo(const QXlibScreen *xd, const QPlatformWindowFormat &format);
private:
- static GLXFBConfig findConfig(const QXlibScreen *xd,const QPlatformWindowFormat &format);
- static QVector<int> buildSpec(const QPlatformWindowFormat &format);
- static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context);
- static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced);
-
-
QXlibScreen *m_screen;
Drawable m_drawable;
GLXContext m_context;
QPlatformWindowFormat m_windowFormat;
QGLXContext (QXlibScreen *screen, Drawable drawable, GLXContext context);
- static QMutex m_defaultSharedContextMutex;
- static void createDefaultSharedContex(QXlibScreen *xd);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibintegration.cpp b/src/plugins/platforms/xlib/qxlibintegration.cpp
index 6733ed1..78f907a 100644
--- a/src/plugins/platforms/xlib/qxlibintegration.cpp
+++ b/src/plugins/platforms/xlib/qxlibintegration.cpp
@@ -49,6 +49,7 @@
#include "qxlibscreen.h"
#include "qxlibclipboard.h"
#include "qxlibdisplay.h"
+#include "qxlibnativeinterface.h"
#if !defined(QT_NO_OPENGL)
#if !defined(QT_OPENGL_ES_2)
@@ -66,11 +67,21 @@ QXlibIntegration::QXlibIntegration(bool useOpenGL)
: mUseOpenGL(useOpenGL)
, mFontDb(new QGenericUnixFontDatabase())
, mClipboard(0)
+ , mNativeInterface(new QXlibNativeInterface)
{
mPrimaryScreen = new QXlibScreen();
mScreens.append(mPrimaryScreen);
}
+bool QXlibIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL: return hasOpenGL();
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
QPixmapData *QXlibIntegration::createPixmapData(QPixmapData::PixelType type) const
{
#ifndef QT_NO_OPENGL
@@ -130,6 +141,11 @@ QPlatformClipboard * QXlibIntegration::clipboard() const
return mClipboard;
}
+QPlatformNativeInterface * QXlibIntegration::nativeInterface() const
+{
+ return mNativeInterface;
+}
+
bool QXlibIntegration::hasOpenGL() const
{
#if !defined(QT_NO_OPENGL)
@@ -141,11 +157,12 @@ bool QXlibIntegration::hasOpenGL() const
static bool wasEglInitialized = false;
if (!eglHasbeenInitialized) {
eglHasbeenInitialized = true;
- const QXlibScreen *screen = static_cast<const QXlibScreen *>(mScreens.at(0));
+ QXlibScreen *screen = static_cast<QXlibScreen *>(mScreens.at(0));
EGLint major, minor;
eglBindAPI(EGL_OPENGL_ES_API);
EGLDisplay disp = eglGetDisplay(screen->display()->nativeDisplay());
wasEglInitialized = eglInitialize(disp,&major,&minor);
+ screen->setEglDisplay(disp);
}
return wasEglInitialized;
#endif
@@ -153,5 +170,4 @@ bool QXlibIntegration::hasOpenGL() const
return false;
}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibintegration.h b/src/plugins/platforms/xlib/qxlibintegration.h
index 3bbf897..1a2515a 100644
--- a/src/plugins/platforms/xlib/qxlibintegration.h
+++ b/src/plugins/platforms/xlib/qxlibintegration.h
@@ -47,6 +47,7 @@
#include <QtGui/QPlatformIntegration>
#include <QtGui/QPlatformScreen>
+#include <QtGui/QPlatformNativeInterface>
#include "qxlibstatic.h"
@@ -59,6 +60,7 @@ class QXlibIntegration : public QPlatformIntegration
public:
QXlibIntegration(bool useOpenGL = false);
+ bool hasCapability(Capability cap) const;
QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const;
QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const;
@@ -70,14 +72,17 @@ public:
QPlatformFontDatabase *fontDatabase() const;
QPlatformClipboard *clipboard() const;
- bool hasOpenGL() const;
+ QPlatformNativeInterface *nativeInterface() const;
private:
+ bool hasOpenGL() const;
+
bool mUseOpenGL;
QXlibScreen *mPrimaryScreen;
QList<QPlatformScreen *> mScreens;
QPlatformFontDatabase *mFontDb;
QPlatformClipboard *mClipboard;
+ QPlatformNativeInterface *mNativeInterface;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibnativeinterface.cpp b/src/plugins/platforms/xlib/qxlibnativeinterface.cpp
new file mode 100644
index 0000000..4e950ff
--- /dev/null
+++ b/src/plugins/platforms/xlib/qxlibnativeinterface.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 "qxlibnativeinterface.h"
+
+#include "qxlibdisplay.h"
+#include <QtGui/private/qapplication_p.h>
+
+class QXlibResourceMap : public QMap<QByteArray, QXlibNativeInterface::ResourceType>
+{
+public:
+ QXlibResourceMap()
+ :QMap<QByteArray, QXlibNativeInterface::ResourceType>()
+ {
+ insert("display",QXlibNativeInterface::Display);
+ insert("egldisplay",QXlibNativeInterface::EglDisplay);
+ insert("connection",QXlibNativeInterface::Connection);
+ insert("screen",QXlibNativeInterface::Screen);
+ insert("graphicsdevice",QXlibNativeInterface::GraphicsDevice);
+ insert("eglcontext",QXlibNativeInterface::EglContext);
+ }
+};
+
+Q_GLOBAL_STATIC(QXlibResourceMap, qXlibResourceMap)
+
+
+void * QXlibNativeInterface::nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget)
+{
+ QByteArray lowerCaseResource = resourceString.toLower();
+ ResourceType resource = qXlibResourceMap()->value(lowerCaseResource);
+ void *result = 0;
+ switch(resource) {
+ case Display:
+ result = displayForWidget(widget);
+ break;
+ case EglDisplay:
+ result = eglDisplayForWidget(widget);
+ break;
+ case Connection:
+ result = connectionForWidget(widget);
+ break;
+ case Screen:
+ result = reinterpret_cast<void *>(qPlatformScreenForWidget(widget)->xScreenNumber());
+ break;
+ case GraphicsDevice:
+ result = graphicsDeviceForWidget(widget);
+ break;
+ case EglContext:
+ result = eglContextForWidget(widget);
+ break;
+ default:
+ result = 0;
+ }
+ return result;
+}
+
+void * QXlibNativeInterface::displayForWidget(QWidget *widget)
+{
+ return qPlatformScreenForWidget(widget)->display()->nativeDisplay();
+}
+
+void * QXlibNativeInterface::eglDisplayForWidget(QWidget *widget)
+{
+ Q_UNUSED(widget);
+ return 0;
+}
+
+void * QXlibNativeInterface::screenForWidget(QWidget *widget)
+{
+ Q_UNUSED(widget);
+ return 0;
+}
+
+void * QXlibNativeInterface::graphicsDeviceForWidget(QWidget *widget)
+{
+ Q_UNUSED(widget);
+ return 0;
+}
+
+void * QXlibNativeInterface::eglContextForWidget(QWidget *widget)
+{
+ Q_UNUSED(widget);
+ return 0;
+}
+
+QXlibScreen * QXlibNativeInterface::qPlatformScreenForWidget(QWidget *widget)
+{
+ QXlibScreen *screen;
+ if (widget) {
+ screen = static_cast<QXlibScreen *>(QPlatformScreen::platformScreenForWidget(widget));
+ }else {
+ screen = static_cast<QXlibScreen *>(QApplicationPrivate::platformIntegration()->screens()[0]);
+ }
+ return screen;
+}
diff --git a/src/plugins/platforms/xlib/qxlibnativeinterface.h b/src/plugins/platforms/xlib/qxlibnativeinterface.h
new file mode 100644
index 0000000..5ba0768
--- /dev/null
+++ b/src/plugins/platforms/xlib/qxlibnativeinterface.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXLIBNATIVEINTERFACE_H
+#define QXLIBNATIVEINTERFACE_H
+
+#include "qxlibscreen.h"
+
+#include <QtGui/QPlatformNativeInterface>
+
+class QXlibNativeInterface : public QPlatformNativeInterface
+{
+public:
+ enum ResourceType {
+ Display,
+ EglDisplay,
+ Connection,
+ Screen,
+ GraphicsDevice,
+ EglContext
+ };
+
+ void *nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget);
+
+ void *displayForWidget(QWidget *widget);
+ void *eglDisplayForWidget(QWidget *widget);
+ void *connectionForWidget(QWidget *widget);
+ void *screenForWidget(QWidget *widget);
+ void *graphicsDeviceForWidget(QWidget *widget);
+ void *eglContextForWidget(QWidget *widget);
+
+private:
+ static QXlibScreen *qPlatformScreenForWidget(QWidget *widget);
+};
+
+
+#endif // QXLIBNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp
index 23a2d07..7c8a367 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.cpp
+++ b/src/plugins/platforms/xlib/qxlibscreen.cpp
@@ -191,6 +191,9 @@ qDebug() << "qt_x_errhandler" << err->error_code;
QXlibScreen::QXlibScreen()
: mFormat(QImage::Format_RGB32)
+#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2)
+ , mEGLDisplay(0)
+#endif
{
char *display_name = getenv("DISPLAY");
Display *display = XOpenDisplay(display_name);
@@ -467,7 +470,7 @@ int QXlibScreen::xScreenNumber() const
Visual * QXlibScreen::defaultVisual() const
{
- DefaultVisual(display()->nativeDisplay(), xScreenNumber());
+ return DefaultVisual(display()->nativeDisplay(), xScreenNumber());
}
QXlibKeyboard * QXlibScreen::keyboard() const
diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h
index 35c0141..8c04c0f 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.h
+++ b/src/plugins/platforms/xlib/qxlibscreen.h
@@ -82,6 +82,11 @@ public:
QXlibKeyboard *keyboard() const;
+#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2)
+ void *eglDisplay() const { return mEGLDisplay; }
+ void setEglDisplay(void *display) { mEGLDisplay = display; }
+#endif
+
public slots:
void eventDispatcher();
@@ -96,6 +101,9 @@ private:
QXlibKeyboard *mKeyboard;
QXlibDisplay * mDisplay;
+#if !defined(QT_NO_OPENGL) && defined(QT_OPENGL_ES_2)
+ void *mEGLDisplay;
+#endif
int mScreen;
};
diff --git a/src/plugins/platforms/xlib/qxlibwindow.cpp b/src/plugins/platforms/xlib/qxlibwindow.cpp
index a7bc53c..9a05fc6 100644
--- a/src/plugins/platforms/xlib/qxlibwindow.cpp
+++ b/src/plugins/platforms/xlib/qxlibwindow.cpp
@@ -58,6 +58,7 @@
#if !defined(QT_NO_OPENGL)
#if !defined(QT_OPENGL_ES_2)
#include "qglxintegration.h"
+#include "qglxconvenience.h"
#else
#include "../eglconvenience/qeglconvenience.h"
#include "../eglconvenience/qeglplatformcontext.h"
@@ -80,16 +81,16 @@ QXlibWindow::QXlibWindow(QWidget *window)
int h = window->height();
if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
- && QApplicationPrivate::platformIntegration()->hasOpenGL() ) {
+ && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL) ) {
#if !defined(QT_NO_OPENGL)
#if !defined(QT_OPENGL_ES_2)
- XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat());
+ XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(),mScreen->xScreenNumber(),window->platformWindowFormat());
#else
QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat());
- EGLDisplay eglDisplay = eglGetDisplay(mScreen->display()->nativeDisplay());
+ EGLDisplay eglDisplay = mScreen->eglDisplay();
EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat);
- VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(),eglConfig);
+ VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(), eglDisplay, eglConfig);
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
@@ -136,7 +137,7 @@ QXlibWindow::QXlibWindow(QWidget *window)
int n = 0;
protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW); // support del window protocol
protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS); // support take focus window protocol
- protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol
+// protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol
#ifndef QT_NO_XSYNC
protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
#endif // QT_NO_XSYNC
@@ -655,7 +656,7 @@ void QXlibWindow::setCursor(const Cursor &cursor)
QPlatformGLContext *QXlibWindow::glContext() const
{
- if (!QApplicationPrivate::platformIntegration()->hasOpenGL())
+ if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
return 0;
if (!mGLContext) {
QXlibWindow *that = const_cast<QXlibWindow *>(this);
@@ -663,7 +664,7 @@ QPlatformGLContext *QXlibWindow::glContext() const
#if !defined(QT_OPENGL_ES_2)
that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat());
#else
- EGLDisplay display = eglGetDisplay(mScreen->display()->nativeDisplay());
+ EGLDisplay display = mScreen->eglDisplay();
QPlatformWindowFormat windowFormat = correctColorBuffers(widget()->platformWindowFormat());
diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro
index 159fdbe..ea77a29 100644
--- a/src/plugins/platforms/xlib/xlib.pro
+++ b/src/plugins/platforms/xlib/xlib.pro
@@ -14,7 +14,8 @@ SOURCES = \
qxlibclipboard.cpp \
qxlibmime.cpp \
qxlibstatic.cpp \
- qxlibdisplay.cpp
+ qxlibdisplay.cpp \
+ qxlibnativeinterface.cpp
HEADERS = \
qxlibintegration.h \
@@ -26,7 +27,8 @@ HEADERS = \
qxlibclipboard.h \
qxlibmime.h \
qxlibstatic.h \
- qxlibdisplay.h
+ qxlibdisplay.h \
+ qxlibnativeinterface.h
LIBS += -lX11 -lXext
@@ -39,6 +41,7 @@ include (../fontdatabases/genericunix/genericunix.pri)
contains(QT_CONFIG, opengl) {
QT += opengl
!contains(QT_CONFIG, opengles2) {
+ include (../glxconvenience/glxconvenience.pri)
HEADERS += qglxintegration.h
SOURCES += qglxintegration.cpp
} else { # There is no easy way to detect if we'r suppose to use glx or not
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro b/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro
new file mode 100644
index 0000000..2748889
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/qmldbg_ost.pro
@@ -0,0 +1,21 @@
+TARGET = qmldbg_ost
+QT += declarative network
+
+include(../../qpluginbase.pri)
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmltooling
+QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)"
+
+SOURCES += \
+ qmlostplugin.cpp \
+ qostdevice.cpp
+
+HEADERS += \
+ qmlostplugin.h \
+ qostdevice.h \
+ usbostcomm.h
+
+target.path += $$[QT_INSTALL_PLUGINS]/qmltooling
+INSTALLS += target
+
+symbian:TARGET.UID3=0x20031E92
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
new file mode 100644
index 0000000..1c91c34
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qmlostplugin.h"
+#include "qostdevice.h"
+
+#include <private/qdeclarativedebugserver_p.h>
+#include <private/qpacketprotocol_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const TInt KQmlOstProtocolId = 0x94;
+
+class QmlOstPluginPrivate {
+public:
+ QmlOstPluginPrivate();
+
+ QOstDevice *ost;
+ QPacketProtocol *protocol;
+ QDeclarativeDebugServer *debugServer;
+};
+
+QmlOstPluginPrivate::QmlOstPluginPrivate() :
+ ost(0),
+ protocol(0),
+ debugServer(0)
+{
+}
+
+QmlOstPlugin::QmlOstPlugin() :
+ d_ptr(new QmlOstPluginPrivate)
+{
+}
+
+QmlOstPlugin::~QmlOstPlugin()
+{
+ delete d_ptr;
+}
+
+void QmlOstPlugin::setServer(QDeclarativeDebugServer *server)
+{
+ Q_D(QmlOstPlugin);
+ d->debugServer = server;
+}
+
+bool QmlOstPlugin::isConnected() const
+{
+ Q_D(const QmlOstPlugin);
+ return d->ost && d->ost->isOpen();
+}
+
+void QmlOstPlugin::send(const QByteArray &message)
+{
+ Q_D(QmlOstPlugin);
+
+ if (!isConnected())
+ return;
+
+ QPacket pack;
+ pack.writeRawData(message.data(), message.length());
+
+ d->protocol->send(pack);
+ //d->socket->flush();
+}
+
+void QmlOstPlugin::disconnect()
+{
+ Q_D(QmlOstPlugin);
+
+ delete d->protocol;
+ d->protocol = 0;
+}
+
+void QmlOstPlugin::setPort(int port, bool block)
+{
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+
+ Q_D(QmlOstPlugin);
+
+ d->ost = new QOstDevice(this);
+ bool ok = d->ost->open(KQmlOstProtocolId);
+ if (!ok) {
+ if (d->ost->errorString().length())
+ qDebug("Error from QOstDevice: %s", qPrintable(d->ost->errorString()));
+ qWarning("QDeclarativeDebugServer: Unable to listen on OST"); // This message is part of the signalling - do not change the format!
+ return;
+ }
+ d->protocol = new QPacketProtocol(d->ost, this);
+ QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ qWarning("QDeclarativeDebugServer: Waiting for connection via OST"); // This message is part of the signalling - do not change the format!
+}
+
+void QmlOstPlugin::readyRead()
+{
+ Q_D(QmlOstPlugin);
+ QPacket packet = d->protocol->read();
+
+ QByteArray content = packet.data();
+ d->debugServer->receiveMessage(content);
+}
+
+Q_EXPORT_PLUGIN2(qmlostplugin, QmlOstPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
new file mode 100644
index 0000000..eee6ee1
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/qmlostplugin.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOSTPLUGIN_H
+#define QMLOSTPLUGIN_H
+
+#include <QtGui/QStylePlugin>
+#include <QtDeclarative/private/qdeclarativedebugserverconnection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeDebugServer;
+class QmlOstPluginPrivate;
+
+class QmlOstPlugin : public QObject, public QDeclarativeDebugServerConnection
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlOstPlugin)
+ Q_DISABLE_COPY(QmlOstPlugin)
+ Q_INTERFACES(QDeclarativeDebugServerConnection)
+
+
+public:
+ QmlOstPlugin();
+ ~QmlOstPlugin();
+
+ void setServer(QDeclarativeDebugServer *server);
+ void setPort(int port, bool bock);
+
+ bool isConnected() const;
+ void send(const QByteArray &message);
+ void disconnect();
+
+private Q_SLOTS:
+ void readyRead();
+
+private:
+ QmlOstPluginPrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLOSTPLUGIN_H
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
new file mode 100644
index 0000000..21b0169
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 "qostdevice.h"
+#include <e32base.h>
+
+#include "usbostcomm.h"
+
+class QOstDevicePrivate : public CActive
+{
+ QOstDevice* q_ptr;
+ Q_DECLARE_PUBLIC(QOstDevice)
+
+public:
+ QOstDevicePrivate() : CActive(CActive::EPriorityStandard) {
+ CActiveScheduler::Add(this);
+ }
+ ~QOstDevicePrivate() {
+ Cancel();
+ }
+
+private:
+ void RunL();
+ void DoCancel();
+
+private:
+ RUsbOstComm ost;
+ TBuf8<4096> readBuf;
+ QByteArray dataBuf;
+};
+
+QOstDevice::QOstDevice(QObject *parent) :
+ QIODevice(parent), d_ptr(new QOstDevicePrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+QOstDevice::~QOstDevice()
+{
+ close();
+ delete d_ptr;
+}
+
+bool QOstDevice::open(int ostProtocolId)
+{
+ if (isOpen())
+ return false;
+
+ Q_D(QOstDevice);
+ TInt err = d->ost.Connect();
+ if (!err) err = d->ost.Open();
+ const TVersion KRequiredVersion(1,1,0);
+ TVersion version = d->ost.Version();
+ if (version.iMajor < KRequiredVersion.iMajor ||
+ (version.iMajor == KRequiredVersion.iMajor && version.iMinor < KRequiredVersion.iMinor)) {
+ setErrorString("CODA version too old. At least version 4.0.18 (without TRK) is required.");
+ return false;
+ }
+
+ if (!err) err = d->ost.RegisterProtocolID((TOstProtIds)ostProtocolId, EFalse);
+ if (!err) {
+ d->ost.ReadMessage(d->iStatus, d->readBuf);
+ d->SetActive();
+ return QIODevice::open(ReadWrite | Unbuffered);
+ }
+ return false;
+}
+
+void QOstDevicePrivate::RunL()
+{
+ Q_Q(QOstDevice);
+ //qDebug("QOstDevice received %d bytes q=%x", readBuf.Size(), q);
+ if (iStatus == KErrNone) {
+ QByteArray data = QByteArray::fromRawData((const char*)readBuf.Ptr(), readBuf.Size());
+ dataBuf.append(data);
+
+ readBuf.Zero();
+ ost.ReadMessage(iStatus, readBuf);
+ SetActive();
+
+ emit q->readyRead();
+ } else {
+ q->setErrorString(QString("Error %1 from RUsbOstComm::ReadMessage()").arg(iStatus.Int()));
+ }
+ //qDebug("-QOstDevicePrivate RunL");
+}
+
+void QOstDevicePrivate::DoCancel()
+{
+ ost.ReadCancel();
+}
+
+void QOstDevice::close()
+{
+ Q_D(QOstDevice);
+ QIODevice::close();
+ d->Cancel();
+ // RDbgTrcComm::Close isn't safe to call when not open, sigh
+ if (d->ost.Handle()) {
+ d->ost.Close();
+ }
+}
+
+qint64 QOstDevice::readData(char *data, qint64 maxSize)
+{
+ Q_D(QOstDevice);
+ if (d->dataBuf.length() == 0 && !d->IsActive())
+ return -1;
+ qint64 available = qMin(maxSize, (qint64)d->dataBuf.length());
+ memcpy(data, d->dataBuf.constData(), available);
+ d->dataBuf.remove(0, available);
+ return available;
+}
+
+static const TInt KMaxOstPacketLen = 4096;
+
+qint64 QOstDevice::writeData(const char *data, qint64 maxSize)
+{
+ Q_D(QOstDevice);
+ TPtrC8 ptr((const TUint8*)data, (TInt)maxSize);
+ while (ptr.Length()) {
+ TPtrC8 fragment = ptr.Left(qMin(ptr.Length(), KMaxOstPacketLen));
+ //qDebug("QOstDevice writing %d bytes", fragment.Length());
+ TRequestStatus stat;
+ d->ost.WriteMessage(stat, fragment);
+ User::WaitForRequest(stat);
+ if (stat.Int() != KErrNone) {
+ setErrorString(QString("Error %1 from RUsbOstComm::WriteMessage()").arg(stat.Int()));
+ return -1;
+ }
+ ptr.Set(ptr.Mid(fragment.Length()));
+ }
+ emit bytesWritten(maxSize); //TODO does it matter this is emitted synchronously?
+ //qDebug("QOstDevice wrote %d bytes", ptr.Size());
+ return maxSize;
+}
+
+qint64 QOstDevice::bytesAvailable() const
+{
+ Q_D(const QOstDevice);
+ return d->dataBuf.length();
+}
diff --git a/src/plugins/qmltooling/qmldbg_ost/qostdevice.h b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
new file mode 100644
index 0000000..2c26ff7
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/qostdevice.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOSTDEVICE_H
+#define QOSTDEVICE_H
+
+#include <QtCore/QIODevice>
+
+QT_BEGIN_NAMESPACE
+
+class QOstDevicePrivate;
+
+class QOstDevice : public QIODevice
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QOstDevice)
+ Q_DISABLE_COPY(QOstDevice)
+
+public:
+ explicit QOstDevice(QObject *parent=0);
+ ~QOstDevice();
+
+ bool open(int ostProtocolId);
+ void close();
+
+protected:
+ qint64 readData(char *data, qint64 maxSize);
+ qint64 writeData(const char *data, qint64 maxSize);
+ qint64 bytesAvailable() const;
+
+private:
+ QOstDevicePrivate* d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOSTDEVICE_H
diff --git a/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h b/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h
new file mode 100644
index 0000000..48ff7bf
--- /dev/null
+++ b/src/plugins/qmltooling/qmldbg_ost/usbostcomm.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef USBHOSTCOMM_H
+#define USBHOSTCOMM_H
+
+// Based on the official usbostrouter header, modified to remove dependancy on
+// the client DLL
+
+#include <e32base.h>
+
+typedef int TOstProtIds;
+
+class RUsbOstComm : public RSessionBase
+{
+public:
+ RUsbOstComm();
+ TInt Connect();
+ TInt Disconnect();
+ TInt Open();
+ TInt Close();
+ TInt RegisterProtocolID(TOstProtIds aId, TBool aNeedHeader);
+ void ReadMessage(TRequestStatus& aStatus, TDes8& aDes);
+ TInt ReadCancel();
+ void WriteMessage(TRequestStatus& aStatus, const TDesC8& aDes, TBool aHasHeader=EFalse);
+ TVersion Version() const;
+
+private:
+ enum TUsbOstCmdCode
+ {
+ EUsbOstCmdCodeFirst,
+ EUsbOstCmdConnect,
+ EUsbOstCmdDisconnect,
+ EUsbOstCmdCodeGetAcmConfig,
+ EUsbOstCmdCodeSetAcmConfig,
+ EUsbOstCmdCodeOpen,
+ EUsbOstCmdCodeClose,
+ EUsbOstCmdCodeRegisterId,
+ EUsbOstCmdCodeRegisterIds,
+ EUsbOstCmdCodeUnRegisterId,
+ EUsbOstCmdCodeUnRegisterIds,
+ EUsbOstCmdCodeReadMsg,
+ EUsbOstCmdCodeReadCancel,
+ EUsbOstCmdCodeWriteMsg,
+ EUsbOstCmdCodeWriteCancel,
+ EUsbOstCmdCodeLast
+ };
+};
+
+RUsbOstComm::RUsbOstComm()
+{
+}
+
+TInt RUsbOstComm::Connect()
+{
+ _LIT(KUsbOstServerName, "!UsbOstRouter");
+ _LIT(KUsbOstServerImageName, "usbostrouter");
+ const TUid KUsbOstServerUid = { 0x200170BE };
+ TInt startupAttempts = 2;
+ for(;;) {
+ TInt ret = CreateSession(KUsbOstServerName, TVersion(1,0,0));
+ if (ret != KErrNotFound && ret != KErrServerTerminated) {
+ return ret;
+ }
+
+ if (startupAttempts-- == 0) {
+ return ret;
+ }
+
+ RProcess server;
+ ret = server.Create(KUsbOstServerImageName, KNullDesC, KUsbOstServerUid);
+ if (ret != KErrNone)
+ return ret;
+
+ TRequestStatus serverDiedRequestStatus;
+ server.Rendezvous(serverDiedRequestStatus);
+
+ if (serverDiedRequestStatus != KRequestPending) {
+ // Abort startup
+ server.Kill(KErrNone);
+ } else {
+ // Logon OK - start the server
+ server.Resume();
+ }
+ User::WaitForRequest(serverDiedRequestStatus);
+ ret = (server.ExitType() == EExitPanic) ? KErrGeneral : serverDiedRequestStatus.Int();
+ server.Close();
+
+ if (ret != KErrNone && ret != KErrAlreadyExists) {
+ return ret;
+ }
+ }
+}
+
+TInt RUsbOstComm::Disconnect()
+{
+ return SendReceive(EUsbOstCmdDisconnect);
+}
+
+TInt RUsbOstComm::Open()
+{
+ return SendReceive(EUsbOstCmdCodeOpen);
+}
+
+TInt RUsbOstComm::Close()
+{
+ TInt err = SendReceive(EUsbOstCmdCodeClose);
+ RHandleBase::Close();
+ return err;
+}
+
+TInt RUsbOstComm::RegisterProtocolID(const TOstProtIds aId, TBool aNeedHeader)
+{
+ TIpcArgs args(aId, aNeedHeader);
+ return SendReceive(EUsbOstCmdCodeRegisterId, args);
+}
+
+void RUsbOstComm::ReadMessage(TRequestStatus& aStatus, TDes8& aDes)
+{
+ TIpcArgs args(aDes.MaxLength(), &aDes);
+ SendReceive(EUsbOstCmdCodeReadMsg, args, aStatus);
+}
+
+TInt RUsbOstComm::ReadCancel()
+{
+ return SendReceive(EUsbOstCmdCodeReadCancel);
+}
+
+void RUsbOstComm::WriteMessage(TRequestStatus& aStatus, const TDesC8& aDes, TBool aHasHeader)
+{
+ TIpcArgs args(aHasHeader, aDes.Length(), &aDes);
+ SendReceive(EUsbOstCmdCodeWriteMsg, args, aStatus);
+}
+
+typedef TVersion (*TVersionFunction)(const RUsbOstComm*);
+const TInt KVersionOrdinal = 17;
+
+TVersion RUsbOstComm::Version() const
+{
+ // This function has to go to the DLL, unfortunately
+ TVersion result; // Return 0.0.0 on any error
+ RLibrary lib;
+ TInt err = lib.Load(_L("usbostcomm"));
+ if (err) return result;
+
+ TLibraryFunction fn = lib.Lookup(KVersionOrdinal);
+ if (fn)
+ result = ((TVersionFunction)fn)(this);
+ lib.Close();
+ return result;
+}
+
+#endif //USBHOSTCOMM_H
diff --git a/src/plugins/qmltooling/tcpserver/tcpserver.pro b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
index f4f2666..e8ab962 100644
--- a/src/plugins/qmltooling/tcpserver/tcpserver.pro
+++ b/src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
@@ -1,4 +1,4 @@
-TARGET = tcpserver
+TARGET = qmldbg_tcp
QT += declarative network
include(../../qpluginbase.pri)
@@ -15,4 +15,4 @@ HEADERS += \
target.path += $$[QT_INSTALL_PLUGINS]/qmltooling
INSTALLS += target
-symbian:TARGET.UID3=0x20031E90 \ No newline at end of file
+symbian:TARGET.UID3=0x20031E90
diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index e1298e8..85c43e3 100644
--- a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -97,7 +97,8 @@ void QTcpServerConnection::send(const QByteArray &message)
{
Q_D(QTcpServerConnection);
- if (!isConnected())
+ if (!isConnected()
+ || !d->protocol || !d->socket)
return;
QPacket pack;
@@ -111,9 +112,10 @@ void QTcpServerConnection::disconnect()
{
Q_D(QTcpServerConnection);
- delete d->protocol;
+ // protocol might still be processing packages at this point
+ d->protocol->deleteLater();
d->protocol = 0;
- delete d->socket;
+ d->socket->deleteLater();
d->socket = 0;
}
@@ -143,6 +145,9 @@ void QTcpServerConnection::listen()
void QTcpServerConnection::readyRead()
{
Q_D(QTcpServerConnection);
+ if (!d->protocol)
+ return;
+
QPacket packet = d->protocol->read();
QByteArray content = packet.data();
diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index 66a10e1..66a10e1 100644
--- a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index 01cf1a9..9b3346f 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = tcpserver
-
+SUBDIRS = qmldbg_tcp
+symbian:SUBDIRS += qmldbg_ost
diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp
index 668a322..6c77405 100644
--- a/src/qt3support/text/q3richtext.cpp
+++ b/src/qt3support/text/q3richtext.cpp
@@ -63,6 +63,7 @@
#include "qstyleoption.h"
#include "q3stylesheet.h"
#include "qtextstream.h"
+#include <private/qtextdocument_p.h>
#include <private/qtextengine_p.h>
#include <stdlib.h>
diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby
index 4afbf05..d6b36e0 100644
--- a/src/s60installs/qt.iby
+++ b/src/s60installs/qt.iby
@@ -15,7 +15,6 @@ file=ABI_DIR\BUILD_DIR\QtXml.dll SHARED_LIB_DIR\QtXml.dll
file=ABI_DIR\BUILD_DIR\QtNetwork.dll SHARED_LIB_DIR\QtNetwork.dll
file=ABI_DIR\BUILD_DIR\QtScript.dll SHARED_LIB_DIR\QtScript.dll
file=ABI_DIR\BUILD_DIR\QtTest.dll SHARED_LIB_DIR\QtTest.dll
-file=ABI_DIR\BUILD_DIR\QtWebKit.dll SHARED_LIB_DIR\QtWebKit.dll
file=ABI_DIR\BUILD_DIR\phonon.dll SHARED_LIB_DIR\phonon.dll
file=ABI_DIR\BUILD_DIR\QtMultimedia.dll SHARED_LIB_DIR\QtMultimedia.dll
file=ABI_DIR\BUILD_DIR\QtXmlPatterns.dll SHARED_LIB_DIR\QtXmlPatterns.dll
@@ -40,14 +39,8 @@ file=ABI_DIR\BUILD_DIR\qtwcodecs.dll SHARED_LIB_DIR\qtwcodecs.dll
file=ABI_DIR\BUILD_DIR\qsvgicon.dll SHARED_LIB_DIR\qsvgicon.dll
// Phonon MMF backend
-// This is commented out by default, as normally Helix backend will be used.
-// If the Helix backend is present, it will override MMF backend, so make sure to remove it from
-// image creation in addition to uncommenting the following lines if you want to use MMF backend.
-//file=ABI_DIR\BUILD_DIR\phonon_mmf.dll SHARED_LIB_DIR\phonon_mmf.dll
-//data=\epoc32\data\z\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin
-
-// QtMultimedia audio backend
-file=ABI_DIR\BUILD_DIR\qaudio.dll SHARED_LIB_DIR\qaudio.dll
+file=ABI_DIR\BUILD_DIR\phonon_mmf.dll SHARED_LIB_DIR\phonon_mmf.dll
+data=\epoc32\data\z\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin
// graphicssystems
file=ABI_DIR\BUILD_DIR\qvggraphicssystem.dll SHARED_LIB_DIR\qvggraphicssystem.dll
@@ -60,8 +53,6 @@ file=ABI_DIR\BUILD_DIR\qsymbianbearer.dll SHARED_LIB_DIR\qsymbianbearer.dll
// so don't bother including those plugins
file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll
-S60_APP_RESOURCE(s60main)
-
// imageformats stubs
data=\epoc32\data\z\resource\qt\plugins\imageformats\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin
data=\epoc32\data\z\resource\qt\plugins\imageformats\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin
@@ -80,24 +71,18 @@ data=\epoc32\data\z\resource\qt\plugins\codecs\qtwcodecs.qtplugin resou
data=\epoc32\data\z\resource\qt\plugins\iconengines\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin
// qml import plugins
-file=ABI_DIR\BUILD_DIR\qmlwebkitplugin.dll SHARED_LIB_DIR\qmlwebkitplugin.dll
file=ABI_DIR\BUILD_DIR\qmlfolderlistmodelplugin.dll SHARED_LIB_DIR\qmlfolderlistmodelplugin.dll
file=ABI_DIR\BUILD_DIR\qmlgesturesplugin.dll SHARED_LIB_DIR\qmlgesturesplugin.dll
file=ABI_DIR\BUILD_DIR\qmlparticlesplugin.dll SHARED_LIB_DIR\qmlparticlesplugin.dll
-data=\epoc32\data\z\resource\qt\imports\QtWebKit\qmlwebkitplugin.qtplugin resource\qt\imports\QtWebKit\qmlwebkitplugin.qtplugin
data=\epoc32\data\z\resource\qt\imports\Qt\labs\folderlistmodel\qmlfolderlistmodelplugin.qtplugin resource\qt\imports\Qt\labs\folderlistmodel\qmlfolderlistmodelplugin.qtplugin
data=\epoc32\data\z\resource\qt\imports\Qt\labs\gestures\qmlgesturesplugin.qtplugin resource\qt\imports\Qt\labs\gestures\qmlgesturesplugin.qtplugin
data=\epoc32\data\z\resource\qt\imports\Qt\labs\particles\qmlparticlesplugin.qtplugin resource\qt\imports\Qt\labs\particles\qmlparticlesplugin.qtplugin
-data=\epoc32\data\z\resource\qt\imports\QtWebKit\qmldir resource\qt\imports\QtWebKit\qmldir
data=\epoc32\data\z\resource\qt\imports\Qt\labs\folderlistmodel\qmldir resource\qt\imports\Qt\labs\folderlistmodel\qmldir
data=\epoc32\data\z\resource\qt\imports\Qt\labs\gestures\qmldir resource\qt\imports\Qt\labs\gestures\qmldir
data=\epoc32\data\z\resource\qt\imports\Qt\labs\particles\qmldir resource\qt\imports\Qt\labs\particles\qmldir
-// QtMultimedia audio backend
-data=\epoc32\data\qt\qtlibspluginstubs\qaudio.qtplugin resource\qt\plugins\audio\qaudio.qtplugin
-
// graphicssystems
data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin
data=\epoc32\data\z\resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qglgraphicssystem.qtplugin
@@ -107,7 +92,6 @@ data=\epoc32\data\z\resource\qt\plugins\bearer\qsymbianbearer.qtplugin resource\
// Stub sis file
data=ZSYSTEM\install\qt_stub.sis System\Install\qt_stub.sis
-data=ZSYSTEM\install\qtwebkit_stub.sis System\Install\qtwebkit_stub.sis
#endif // __QT_IBY__
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 49e7f13..4250b61 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -1374,12 +1374,16 @@ QStringList QMYSQLDriver::tables(QSql::TableType type) const
} else {
QSqlQuery q(createResult());
if(type & QSql::Tables) {
- q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'BASE TABLE'"));
+ QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'BASE TABLE'");
+ q.exec(sql);
+
while(q.next())
tl.append(q.value(0).toString());
}
if(type & QSql::Views) {
- q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'VIEW'"));
+ QString sql = QLatin1String("select table_name from information_schema.tables where table_schema = '") + QLatin1String(d->mysql->db) + QLatin1String("' and table_type = 'VIEW'");
+ q.exec(sql);
+
while(q.next())
tl.append(q.value(0).toString());
}
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 9698860..3fbc08c 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -584,7 +584,7 @@ static qreal toDouble(const QChar *&str)
++str;
}
bool exponent = false;
- if (*str == QLatin1Char('e') && pos < maxLen) {
+ if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
exponent = true;
temp[pos++] = 'e';
++str;
diff --git a/src/xmlpatterns/data/qitem_p.h b/src/xmlpatterns/data/qitem_p.h
index 8184b25..fb3866e 100644
--- a/src/xmlpatterns/data/qitem_p.h
+++ b/src/xmlpatterns/data/qitem_p.h
@@ -408,6 +408,10 @@ namespace QPatternist
inline void reset()
{
+ /* Delete the atomicValue if necessary*/
+ if(isAtomicValue() && !atomicValue->ref.deref())
+ delete atomicValue;
+
/* Note that this function should be equal to the default
* constructor. */
node.model = 0;
diff --git a/src/xmlpatterns/expr/qdynamiccontextstore.cpp b/src/xmlpatterns/expr/qdynamiccontextstore.cpp
index 762b7d6..7e7ead7 100644
--- a/src/xmlpatterns/expr/qdynamiccontextstore.cpp
+++ b/src/xmlpatterns/expr/qdynamiccontextstore.cpp
@@ -51,24 +51,24 @@ using namespace QPatternist;
DynamicContextStore::DynamicContextStore(const Expression::Ptr &operand,
const DynamicContext::Ptr &context) : SingleContainer(operand),
- m_context(context)
+ m_context(context.data())
{
Q_ASSERT(context);
}
bool DynamicContextStore::evaluateEBV(const DynamicContext::Ptr &) const
{
- return m_operand->evaluateEBV(m_context);
+ return m_operand->evaluateEBV(DynamicContext::Ptr(m_context));
}
Item::Iterator::Ptr DynamicContextStore::evaluateSequence(const DynamicContext::Ptr &) const
{
- return m_operand->evaluateSequence(m_context);
+ return m_operand->evaluateSequence(DynamicContext::Ptr(m_context));
}
Item DynamicContextStore::evaluateSingleton(const DynamicContext::Ptr &) const
{
- return m_operand->evaluateSingleton(m_context);
+ return m_operand->evaluateSingleton(DynamicContext::Ptr(m_context));
}
SequenceType::Ptr DynamicContextStore::staticType() const
diff --git a/src/xmlpatterns/expr/qdynamiccontextstore_p.h b/src/xmlpatterns/expr/qdynamiccontextstore_p.h
index 1d5d035..40bfcd1 100644
--- a/src/xmlpatterns/expr/qdynamiccontextstore_p.h
+++ b/src/xmlpatterns/expr/qdynamiccontextstore_p.h
@@ -86,7 +86,7 @@ namespace QPatternist
virtual const SourceLocationReflection *actualReflection() const;
private:
- const DynamicContext::Ptr m_context;
+ DynamicContext *m_context;
};
}
diff --git a/src/xmlpatterns/expr/qevaluationcache.cpp b/src/xmlpatterns/expr/qevaluationcache.cpp
index 2d1bb56..cb95af6 100644
--- a/src/xmlpatterns/expr/qevaluationcache.cpp
+++ b/src/xmlpatterns/expr/qevaluationcache.cpp
@@ -49,7 +49,7 @@ template<bool IsForGlobal>
EvaluationCache<IsForGlobal>::EvaluationCache(const Expression::Ptr &op,
const VariableDeclaration::Ptr &varDecl,
const VariableSlotID aSlot) : SingleContainer(op)
- , m_declaration(varDecl)
+ , m_declaration(varDecl.constData())
, m_varSlot(aSlot)
{
Q_ASSERT(m_declaration);
diff --git a/src/xmlpatterns/expr/qevaluationcache_p.h b/src/xmlpatterns/expr/qevaluationcache_p.h
index 86aeaf8..af4cfa0 100644
--- a/src/xmlpatterns/expr/qevaluationcache_p.h
+++ b/src/xmlpatterns/expr/qevaluationcache_p.h
@@ -124,7 +124,7 @@ namespace QPatternist
private:
static DynamicContext::Ptr topFocusContext(const DynamicContext::Ptr &context);
- const VariableDeclaration::Ptr m_declaration;
+ const VariableDeclaration* m_declaration;
/**
* This variable must not be called m_slot. If it so, a compiler bug on
* HP-UX-aCC-64 is triggered in the constructor initializor. See the
diff --git a/src/xmlpatterns/expr/qletclause.cpp b/src/xmlpatterns/expr/qletclause.cpp
index d3e939b..b789b48 100644
--- a/src/xmlpatterns/expr/qletclause.cpp
+++ b/src/xmlpatterns/expr/qletclause.cpp
@@ -60,7 +60,7 @@ LetClause::LetClause(const Expression::Ptr &operand1,
DynamicContext::Ptr LetClause::bindVariable(const DynamicContext::Ptr &context) const
{
- context->setExpressionVariable(m_varDecl->slot, Expression::Ptr(new DynamicContextStore(m_operand1, context)));
+ context->setExpressionVariable(m_varDecl->slot, m_operand1);
return context;
}
diff --git a/src/xmlpatterns/schema/qxsdattribute.cpp b/src/xmlpatterns/schema/qxsdattribute.cpp
index 68f9e3d..fb768d4 100644
--- a/src/xmlpatterns/schema/qxsdattribute.cpp
+++ b/src/xmlpatterns/schema/qxsdattribute.cpp
@@ -59,12 +59,12 @@ XsdAttribute::Scope::Variety XsdAttribute::Scope::variety() const
void XsdAttribute::Scope::setParent(const NamedSchemaComponent::Ptr &parent)
{
- m_parent = parent;
+ m_parent = parent.data();
}
NamedSchemaComponent::Ptr XsdAttribute::Scope::parent() const
{
- return m_parent;
+ return NamedSchemaComponent::Ptr(m_parent);
}
void XsdAttribute::ValueConstraint::setVariety(Variety variety)
diff --git a/src/xmlpatterns/schema/qxsdattribute_p.h b/src/xmlpatterns/schema/qxsdattribute_p.h
index d64d335..a21fe70 100644
--- a/src/xmlpatterns/schema/qxsdattribute_p.h
+++ b/src/xmlpatterns/schema/qxsdattribute_p.h
@@ -131,7 +131,7 @@ namespace QPatternist
private:
Variety m_variety;
- NamedSchemaComponent::Ptr m_parent;
+ NamedSchemaComponent *m_parent;
};
diff --git a/src/xmlpatterns/schema/qxsdcomplextype.cpp b/src/xmlpatterns/schema/qxsdcomplextype.cpp
index 42aeb60..0932060 100644
--- a/src/xmlpatterns/schema/qxsdcomplextype.cpp
+++ b/src/xmlpatterns/schema/qxsdcomplextype.cpp
@@ -140,12 +140,12 @@ SchemaType::Ptr XsdComplexType::wxsSuperType() const
void XsdComplexType::setContext(const NamedSchemaComponent::Ptr &component)
{
- m_context = component;
+ m_context = component.data();
}
NamedSchemaComponent::Ptr XsdComplexType::context() const
{
- return m_context;
+ return NamedSchemaComponent::Ptr(m_context);
}
void XsdComplexType::setContentType(const ContentType::Ptr &type)
diff --git a/src/xmlpatterns/schema/qxsdcomplextype_p.h b/src/xmlpatterns/schema/qxsdcomplextype_p.h
index d28d2fc..d02583c 100644
--- a/src/xmlpatterns/schema/qxsdcomplextype_p.h
+++ b/src/xmlpatterns/schema/qxsdcomplextype_p.h
@@ -386,7 +386,7 @@ namespace QPatternist
private:
SchemaType::Ptr m_superType;
- NamedSchemaComponent::Ptr m_context;
+ NamedSchemaComponent *m_context;
DerivationMethod m_derivationMethod;
bool m_isAbstract;
XsdAttributeUse::List m_attributeUses;
diff --git a/src/xmlpatterns/schema/qxsdelement.cpp b/src/xmlpatterns/schema/qxsdelement.cpp
index 1ebec06..b0c5661 100644
--- a/src/xmlpatterns/schema/qxsdelement.cpp
+++ b/src/xmlpatterns/schema/qxsdelement.cpp
@@ -57,12 +57,12 @@ XsdElement::Scope::Variety XsdElement::Scope::variety() const
void XsdElement::Scope::setParent(const NamedSchemaComponent::Ptr &parent)
{
- m_parent = parent;
+ m_parent = parent.data();
}
NamedSchemaComponent::Ptr XsdElement::Scope::parent() const
{
- return m_parent;
+ return NamedSchemaComponent::Ptr(m_parent);
}
void XsdElement::ValueConstraint::setVariety(Variety variety)
@@ -233,10 +233,10 @@ XsdElement::List XsdElement::substitutionGroupAffiliations() const
void XsdElement::addSubstitutionGroup(const XsdElement::Ptr &element)
{
- m_substitutionGroups.insert(element);
+ m_substitutionGroups.insert(element.data());
}
-XsdElement::List XsdElement::substitutionGroups() const
+XsdElement::WeakList XsdElement::substitutionGroups() const
{
return m_substitutionGroups.toList();
}
diff --git a/src/xmlpatterns/schema/qxsdelement_p.h b/src/xmlpatterns/schema/qxsdelement_p.h
index 93c5983..3794c96 100644
--- a/src/xmlpatterns/schema/qxsdelement_p.h
+++ b/src/xmlpatterns/schema/qxsdelement_p.h
@@ -85,7 +85,7 @@ namespace QPatternist
public:
typedef QExplicitlySharedDataPointer<XsdElement> Ptr;
typedef QList<XsdElement::Ptr> List;
-
+ typedef QList<XsdElement *> WeakList;
/**
* Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ed-value_constraint">constraint type</a> of the element.
@@ -138,7 +138,7 @@ namespace QPatternist
private:
Variety m_variety;
- NamedSchemaComponent::Ptr m_parent;
+ NamedSchemaComponent *m_parent;
};
/**
@@ -379,7 +379,7 @@ namespace QPatternist
/**
* Returns the substitution groups of the element.
*/
- XsdElement::List substitutionGroups() const;
+ XsdElement::WeakList substitutionGroups() const;
private:
SchemaType::Ptr m_type;
@@ -392,7 +392,7 @@ namespace QPatternist
SchemaType::DerivationConstraints m_substitutionGroupExclusions;
XsdIdentityConstraint::List m_identityConstraints;
XsdElement::List m_substitutionGroupAffiliations;
- QSet<XsdElement::Ptr> m_substitutionGroups;
+ QSet<XsdElement *> m_substitutionGroups;
};
}
diff --git a/src/xmlpatterns/schema/qxsdparticlechecker.cpp b/src/xmlpatterns/schema/qxsdparticlechecker.cpp
index 15c2afe..d4beae7 100644
--- a/src/xmlpatterns/schema/qxsdparticlechecker.cpp
+++ b/src/xmlpatterns/schema/qxsdparticlechecker.cpp
@@ -309,12 +309,12 @@ static bool hasDuplicatedElementsInternal(const XsdParticle::Ptr &particle, cons
const XsdTerm::Ptr term = particle->term();
if (term->isElement()) {
const XsdElement::Ptr mainElement(term);
- XsdElement::List substGroups = mainElement->substitutionGroups();
+ XsdElement::WeakList substGroups = mainElement->substitutionGroups();
if (substGroups.isEmpty())
- substGroups << mainElement;
+ substGroups << mainElement.data();
for (int i = 0; i < substGroups.count(); ++i) {
- const XsdElement::Ptr element = substGroups.at(i);
+ const XsdElement::Ptr element(substGroups.at(i));
if (hash.contains(element->name(namePool))) {
if (element->type()->name(namePool) != hash.value(element->name(namePool))->type()->name(namePool)) {
conflictingElement = element;
diff --git a/src/xmlpatterns/schema/qxsdsimpletype.cpp b/src/xmlpatterns/schema/qxsdsimpletype.cpp
index 6fd5658..3e77aca 100644
--- a/src/xmlpatterns/schema/qxsdsimpletype.cpp
+++ b/src/xmlpatterns/schema/qxsdsimpletype.cpp
@@ -72,12 +72,12 @@ SchemaType::Ptr XsdSimpleType::wxsSuperType() const
void XsdSimpleType::setContext(const NamedSchemaComponent::Ptr &component)
{
- m_context = component;
+ m_context = component.data();
}
NamedSchemaComponent::Ptr XsdSimpleType::context() const
{
- return m_context;
+ return NamedSchemaComponent::Ptr(m_context);
}
void XsdSimpleType::setPrimitiveType(const AnySimpleType::Ptr &type)
diff --git a/src/xmlpatterns/schema/qxsdsimpletype_p.h b/src/xmlpatterns/schema/qxsdsimpletype_p.h
index 6305fc7..a5b72a7 100644
--- a/src/xmlpatterns/schema/qxsdsimpletype_p.h
+++ b/src/xmlpatterns/schema/qxsdsimpletype_p.h
@@ -202,7 +202,7 @@ namespace QPatternist
private:
SchemaType::Ptr m_superType;
- NamedSchemaComponent::Ptr m_context;
+ NamedSchemaComponent* m_context;
AnySimpleType::Ptr m_primitiveType;
AnySimpleType::Ptr m_itemType;
AnySimpleType::List m_memberTypes;
diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp
index fed8a41..b6c8704 100644
--- a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp
+++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp
@@ -166,14 +166,14 @@ XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::buildTerm(const X
const XsdElement::Ptr element(term);
if (m_mode == CheckingMode) {
- const XsdElement::List substGroups = element->substitutionGroups();
+ const XsdElement::WeakList substGroups = element->substitutionGroups();
for (int i = 0; i < substGroups.count(); ++i)
- m_stateMachine->addTransition(b, substGroups.at(i), endState);
+ m_stateMachine->addTransition(b, XsdElement::Ptr(substGroups.at(i)), endState);
} else if (m_mode == ValidatingMode) {
- const XsdElement::List substGroups = element->substitutionGroups();
+ const XsdElement::WeakList substGroups = element->substitutionGroups();
for (int i = 0; i < substGroups.count(); ++i) {
- if (XsdSchemaHelper::substitutionGroupOkTransitive(element, substGroups.at(i), m_namePool))
- m_stateMachine->addTransition(b, substGroups.at(i), endState);
+ if (XsdSchemaHelper::substitutionGroupOkTransitive(element, XsdElement::Ptr(substGroups.at(i)), m_namePool))
+ m_stateMachine->addTransition(b, XsdElement::Ptr(substGroups.at(i)), endState);
}
}