summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-09-25 14:02:04 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-09-25 14:02:04 +0200
commita1ad9a74ebb3c556c5f70f7e03be68b09598ac53 (patch)
tree615a96db418219a57a745a5899e39a9ac90744ec /src
parent6d78b7a0c46ea04f4bb771d960e2f7dff1362341 (diff)
parent462f355e4fb16cc7a1838fa2dda0f763eee58c84 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts: src/corelib/io/io.pri src/corelib/io/qdatastream.cpp src/corelib/io/qdatastream.h src/network/socket/qabstractsocket.cpp src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h src/widgets/styles/qgtkstyle.cpp tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro tests/auto/dbus/qdbusconnection/qdbusconnection.pro tests/auto/dbus/qdbuspendingcall/tst_qdbuspendingcall.cpp tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp Change-Id: I347549a024eb5bfa986699e0a11f96cc55c797a7
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch35
-rw-r--r--src/3rdparty/pcre/pcre.h6
-rw-r--r--src/3rdparty/pcre/pcre_compile.c271
-rw-r--r--src/3rdparty/pcre/pcre_exec.c3
-rw-r--r--src/3rdparty/pcre/pcre_internal.h17
-rw-r--r--src/3rdparty/pcre/pcre_jit_compile.c58
-rw-r--r--src/3rdparty/pcre/pcre_study.c19
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfig.h9
-rw-r--r--src/3rdparty/pcre/sljit/sljitConfigInternal.h13
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.c10
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.h40
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_32.c27
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_64.c48
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c58
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c15
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativePPC_common.c23
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c19
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c311
-rw-r--r--src/3rdparty/pcre/sljit/sljitNativeX86_common.c59
-rw-r--r--src/3rdparty/sha3/KeccakF-1600-opt32.c6
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java12
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java4
-rw-r--r--src/angle/src/common/common.pri8
-rw-r--r--src/angle/src/compiler/preprocessor/preprocessor.pro6
-rw-r--r--src/angle/src/compiler/translator.pro6
-rw-r--r--src/corelib/arch/arch.pri2
-rw-r--r--src/corelib/arch/qatomic_cxx11.h12
-rw-r--r--src/corelib/codecs/qbig5codec.cpp4
-rw-r--r--src/corelib/codecs/qeucjpcodec.cpp4
-rw-r--r--src/corelib/codecs/qeuckrcodec.cpp4
-rw-r--r--src/corelib/codecs/qgb18030codec.cpp6
-rw-r--r--src/corelib/codecs/qjiscodec.cpp2
-rw-r--r--src/corelib/codecs/qsjiscodec.cpp2
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp27
-rw-r--r--src/corelib/doc/src/containers.qdoc18
-rw-r--r--src/corelib/doc/src/implicit-sharing.qdoc6
-rw-r--r--src/corelib/global/global.pri25
-rw-r--r--src/corelib/global/qglobal.cpp276
-rw-r--r--src/corelib/global/qglobal.h3
-rw-r--r--src/corelib/global/qnamespace.qdoc5
-rw-r--r--src/corelib/global/qnumeric_p.h117
-rw-r--r--src/corelib/global/qsysinfo.h2
-rw-r--r--src/corelib/global/qsystemdetection.h2
-rw-r--r--src/corelib/global/qversiontagging.cpp69
-rw-r--r--src/corelib/io/io.pri2
-rw-r--r--src/corelib/io/qabstractfileengine.cpp1
-rw-r--r--src/corelib/io/qdatastream.cpp4
-rw-r--r--src/corelib/io/qdatastream.h4
-rw-r--r--src/corelib/io/qdebug.cpp2
-rw-r--r--src/corelib/io/qfileinfo.cpp16
-rw-r--r--src/corelib/io/qfilesystemengine.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp161
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h4
-rw-r--r--src/corelib/io/qloggingcategory.cpp1
-rw-r--r--src/corelib/io/qloggingregistry.cpp64
-rw-r--r--src/corelib/io/qloggingregistry_p.h1
-rw-r--r--src/corelib/io/qprocess.cpp23
-rw-r--r--src/corelib/io/qprocess_win.cpp6
-rw-r--r--src/corelib/io/qsettings.cpp29
-rw-r--r--src/corelib/io/qstorageinfo_mac.cpp40
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp6
-rw-r--r--src/corelib/io/qtextstream.cpp8
-rw-r--r--src/corelib/io/qurlidna.cpp2
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp2
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp8
-rw-r--r--src/corelib/json/qjsonarray.cpp12
-rw-r--r--src/corelib/kernel/qcore_mac_p.h4
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp47
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp3
-rw-r--r--src/corelib/kernel/qmetatype.cpp25
-rw-r--r--src/corelib/kernel/qmetatype.h17
-rw-r--r--src/corelib/kernel/qobject.cpp13
-rw-r--r--src/corelib/kernel/qpointer.h5
-rw-r--r--src/corelib/kernel/qvariant.h6
-rw-r--r--src/corelib/kernel/qvariant_p.h2
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp16
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h3
-rw-r--r--src/corelib/plugin/quuid.cpp10
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp20
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h1
-rw-r--r--src/corelib/thread/qmutex.cpp23
-rw-r--r--src/corelib/thread/qthread_unix.cpp3
-rw-r--r--src/corelib/thread/qthread_win.cpp8
-rw-r--r--src/corelib/thread/thread.pri24
-rw-r--r--[-rwxr-xr-x]src/corelib/tools/qalgorithms.h10
-rw-r--r--src/corelib/tools/qbytearray.cpp4
-rw-r--r--src/corelib/tools/qchar.cpp10
-rw-r--r--src/corelib/tools/qcommandlineoption.cpp4
-rw-r--r--src/corelib/tools/qdatetime.cpp29
-rw-r--r--src/corelib/tools/qelapsedtimer_mac.cpp5
-rw-r--r--src/corelib/tools/qhash.cpp50
-rw-r--r--src/corelib/tools/qhash.h3
-rw-r--r--src/corelib/tools/qlocale.cpp4
-rw-r--r--src/corelib/tools/qlocale_win.cpp6
-rw-r--r--src/corelib/tools/qrect.cpp4
-rw-r--r--src/corelib/tools/qregexp.cpp6
-rw-r--r--src/corelib/tools/qregularexpression.cpp45
-rw-r--r--src/corelib/tools/qsimd.cpp292
-rw-r--r--src/corelib/tools/qsimd_p.h178
-rw-r--r--src/corelib/tools/qstring.cpp15
-rw-r--r--src/corelib/tools/qstringbuilder.h2
-rw-r--r--src/corelib/tools/qtimezone.cpp1
-rw-r--r--src/dbus/qdbus_symbols_p.h6
-rw-r--r--src/dbus/qdbusabstractinterface.cpp107
-rw-r--r--src/dbus/qdbusabstractinterface_p.h4
-rw-r--r--src/dbus/qdbusconnection.cpp310
-rw-r--r--src/dbus/qdbusconnection_p.h48
-rw-r--r--src/dbus/qdbusconnectionmanager_p.h26
-rw-r--r--src/dbus/qdbusintegrator.cpp625
-rw-r--r--src/dbus/qdbusintegrator_p.h23
-rw-r--r--src/dbus/qdbusintrospection_p.h1
-rw-r--r--src/dbus/qdbuspendingcall.cpp3
-rw-r--r--src/dbus/qdbuspendingcall_p.h4
-rw-r--r--src/dbus/qdbusserver.cpp25
-rw-r--r--src/dbus/qdbusserver.h3
-rw-r--r--src/dbus/qdbusservicewatcher.cpp36
-rw-r--r--src/dbus/qdbusservicewatcher.h4
-rw-r--r--src/dbus/qdbusthreaddebug_p.h6
-rw-r--r--src/gui/accessible/qaccessible.cpp1
-rw-r--r--src/gui/image/qbmphandler.cpp6
-rw-r--r--src/gui/image/qiconengine.cpp7
-rw-r--r--src/gui/image/qiconengine.h1
-rw-r--r--src/gui/image/qimage.cpp11
-rw-r--r--src/gui/kernel/qevent.cpp2
-rw-r--r--src/gui/kernel/qguiapplication.cpp48
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp8
-rw-r--r--src/gui/kernel/qopenglcontext.cpp16
-rw-r--r--src/gui/kernel/qopenglcontext.h2
-rw-r--r--src/gui/kernel/qopenglcontext_p.h2
-rw-r--r--src/gui/kernel/qplatformcursor.cpp2
-rw-r--r--src/gui/kernel/qplatformcursor.h2
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp5
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h5
-rw-r--r--src/gui/kernel/qplatforminputcontextfactory.cpp46
-rw-r--r--src/gui/kernel/qplatforminputcontextfactory_p.h1
-rw-r--r--src/gui/kernel/qplatformintegration.cpp39
-rw-r--r--src/gui/kernel/qplatformintegration.h4
-rw-r--r--src/gui/kernel/qplatformscreen.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.cpp11
-rw-r--r--src/gui/kernel/qplatformwindow.h1
-rw-r--r--src/gui/kernel/qscreen.cpp2
-rw-r--r--src/gui/kernel/qshortcutmap.cpp12
-rw-r--r--src/gui/kernel/qshortcutmap_p.h4
-rw-r--r--src/gui/kernel/qsimpledrag.cpp6
-rw-r--r--src/gui/kernel/qtouchdevice.cpp11
-rw-r--r--src/gui/kernel/qtouchdevice_p.h1
-rw-r--r--src/gui/kernel/qwindow.cpp2
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp159
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h9
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h3
-rw-r--r--src/gui/opengl/qopenglengineshadermanager.cpp3
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp8
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp165
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp17
-rw-r--r--src/gui/painting/qdrawhelper.cpp6
-rw-r--r--src/gui/painting/qimagescale.cpp5
-rw-r--r--src/gui/painting/qpaintdevice.h2
-rw-r--r--src/gui/painting/qpaintdevice.qdoc8
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp7
-rw-r--r--src/gui/painting/qrasterizer.cpp28
-rw-r--r--src/gui/painting/qrgba64.h65
-rw-r--r--src/gui/painting/qrgba64.qdoc64
-rw-r--r--src/gui/text/qfont.cpp8
-rw-r--r--src/gui/text/qfontengine.cpp308
-rw-r--r--src/gui/text/qfontengine_ft.cpp49
-rw-r--r--src/gui/text/qfontengine_ft_p.h4
-rw-r--r--src/gui/text/qfontengine_p.h10
-rw-r--r--src/gui/text/qfontengine_qpf2.cpp10
-rw-r--r--src/gui/text/qtextengine_p.h16
-rw-r--r--src/gui/text/qtextlayout.cpp90
-rw-r--r--src/gui/text/qzip.cpp6
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp1
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp112
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h1
-rw-r--r--src/network/access/qhttpnetworkreply.cpp2
-rw-r--r--src/network/access/qhttpprotocolhandler.cpp8
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp24
-rw-r--r--src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp3
-rw-r--r--src/network/kernel/kernel.pri5
-rw-r--r--src/network/kernel/qhostaddress.cpp136
-rw-r--r--src/network/kernel/qhostaddress.h2
-rw-r--r--src/network/kernel/qhostinfo.cpp16
-rw-r--r--src/network/kernel/qhostinfo_unix.cpp9
-rw-r--r--src/network/kernel/qhostinfo_win.cpp19
-rw-r--r--src/network/kernel/qhostinfo_winrt.cpp39
-rw-r--r--src/network/kernel/qnetworkinterface.cpp14
-rw-r--r--src/network/kernel/qnetworkinterface.h3
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp52
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp140
-rw-r--r--src/network/kernel/qnetworkinterface_win_p.h262
-rw-r--r--src/network/kernel/qnetworkproxy_mac.cpp1
-rw-r--r--src/network/socket/qabstractsocket.cpp116
-rw-r--r--src/network/socket/qabstractsocket_p.h3
-rw-r--r--src/network/socket/qabstractsocketengine_p.h48
-rw-r--r--src/network/socket/qhttpsocketengine.cpp6
-rw-r--r--src/network/socket/qhttpsocketengine_p.h7
-rw-r--r--src/network/socket/qnativesocketengine.cpp74
-rw-r--r--src/network/socket/qnativesocketengine_p.h126
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp317
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp329
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp25
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h9
-rw-r--r--src/network/socket/qnet_unix_p.h27
-rw-r--r--src/network/socket/qsocks5socketengine.cpp18
-rw-r--r--src/network/socket/qsocks5socketengine_p.h7
-rw-r--r--src/network/socket/qtcpserver.cpp4
-rw-r--r--src/network/socket/qudpsocket.cpp28
-rw-r--r--src/network/ssl/qsslsocket.cpp29
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp74
-rw-r--r--src/network/ssl/qsslsocket_mac_p.h7
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp76
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp30
-rw-r--r--src/opengl/doc/src/qtopengl-index.qdoc2
-rw-r--r--src/opengl/doc/src/qtopengl-module.qdoc2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp3
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm20
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm10
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h2
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp89
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h20
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp27
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h2
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler.cpp6
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard.cpp17
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection.cpp9
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp64
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp51
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.json2
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp3
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp44
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm13
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm31
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp19
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm52
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm5
-rw-r--r--src/plugins/platforms/kms/kms.json3
-rw-r--r--src/plugins/platforms/kms/kms.pro37
-rw-r--r--src/plugins/platforms/kms/main.cpp58
-rw-r--r--src/plugins/platforms/kms/qkmsbackingstore.cpp217
-rw-r--r--src/plugins/platforms/kms/qkmsbackingstore.h72
-rw-r--r--src/plugins/platforms/kms/qkmscontext.cpp136
-rw-r--r--src/plugins/platforms/kms/qkmscontext.h71
-rw-r--r--src/plugins/platforms/kms/qkmscursor.cpp116
-rw-r--r--src/plugins/platforms/kms/qkmscursor.h66
-rw-r--r--src/plugins/platforms/kms/qkmsdevice.cpp118
-rw-r--r--src/plugins/platforms/kms/qkmsdevice.h81
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.cpp204
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.h108
-rw-r--r--src/plugins/platforms/kms/qkmsnativeinterface.cpp135
-rw-r--r--src/plugins/platforms/kms/qkmsnativeinterface.h64
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp275
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h122
-rw-r--r--src/plugins/platforms/kms/qkmswindow.cpp66
-rw-r--r--src/plugins/platforms/kms/qkmswindow.h57
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp31
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp43
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp55
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp114
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp19
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp16
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.cpp30
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp280
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.h12
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.cpp26
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp4
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp26
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp120
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h27
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp115
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp241
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp163
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp17
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp4
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp3
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha.cpp10
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha_p.h6
-rw-r--r--src/sql/drivers/psql/qsql_psql.cpp3
-rw-r--r--src/testlib/qbenchmarkmetric.cpp2
-rw-r--r--src/testlib/qtest.h20
-rw-r--r--src/testlib/qtestcase.cpp67
-rw-r--r--src/testlib/qtestkeyboard.h8
-rw-r--r--src/tools/qdoc/config.cpp2
-rw-r--r--src/tools/qdoc/config.h4
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp15
-rw-r--r--src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc19
-rw-r--r--src/tools/qdoc/generator.cpp6
-rw-r--r--src/tools/qdoc/generator.h4
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp17
-rw-r--r--src/tools/qdoc/htmlgenerator.h2
-rw-r--r--src/tools/qdoc/main.cpp4
-rw-r--r--src/tools/qdoc/node.cpp119
-rw-r--r--src/tools/qdoc/node.h3
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp40
-rw-r--r--src/tools/qdoc/qdocindexfiles.cpp31
-rw-r--r--src/tools/qdoc/qdocindexfiles.h1
-rw-r--r--src/tools/qdoc/tree.cpp11
-rw-r--r--src/widgets/dialogs/qdialog.cpp4
-rw-r--r--src/widgets/dialogs/qsidebar.cpp2
-rw-r--r--src/widgets/dialogs/qwizard.cpp1
-rw-r--r--src/widgets/doc/src/model-view-programming.qdoc2
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/layout.qdoc2
-rw-r--r--src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc2
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsproxywidget.cpp13
-rw-r--r--src/widgets/itemviews/qtreeview.cpp3
-rw-r--r--src/widgets/kernel/qaction.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp15
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp1
-rw-r--r--src/widgets/kernel/qdesktopwidget.h1
-rw-r--r--src/widgets/kernel/qdesktopwidget.qdoc14
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp2
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp22
-rw-r--r--src/widgets/kernel/qwidget.cpp29
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
-rw-r--r--src/widgets/styles/qfusionstyle.cpp8
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm30
-rw-r--r--src/widgets/styles/qstyle.cpp19
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp2
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp11
-rw-r--r--src/widgets/widgets/qcombobox.cpp5
-rw-r--r--src/widgets/widgets/qdockwidget.cpp1
-rw-r--r--src/widgets/widgets/qlineedit.cpp18
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp27
-rw-r--r--src/widgets/widgets/qlineedit_p.h16
-rw-r--r--src/widgets/widgets/qmenu.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.cpp4
-rw-r--r--src/winmain/qtmain_winrt.cpp24
358 files changed, 6389 insertions, 6072 deletions
diff --git a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch b/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch
deleted file mode 100644
index 8cb3c8c608..0000000000
--- a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 121e4d1ad09bdbfeb8a871d4f2c3ffe1acb8e2d6 Mon Sep 17 00:00:00 2001
-From: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-Date: Tue, 30 Jun 2015 09:41:39 +0200
-Subject: [PATCH] Re-fix X86 Wince builds.
-
-eebb8de21ce4845866f15e444a4c78fc2cbb7f3f fixed the PCRE
-build, but was accidentally overwritten by a subsequent
-import of the PCRE tarball.
-
-Now put the same patch also into patches/ so that we don't
-forget it needs to be manually applied.
-
-Change-Id: I93c2ee9c2e2dd1c48d391ce7e16d33208fb2cbbb
----
- src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
-index 22a163f..21b276f 100644
---- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
-+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
-@@ -273,7 +273,9 @@ static sljit_si cpu_has_sse2 = -1;
- #endif
- static sljit_si cpu_has_cmov = -1;
-
--#if defined(_MSC_VER) && _MSC_VER >= 1400
-+#ifdef _WIN32_WCE
-+#include <cmnintrin.h>
-+#elif defined(_MSC_VER) && _MSC_VER >= 1400
- #include <intrin.h>
- #endif
-
---
-1.9.1
-
diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h
index 58ed46a2a3..c2557cf4b1 100644
--- a/src/3rdparty/pcre/pcre.h
+++ b/src/3rdparty/pcre/pcre.h
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE_MAJOR 8
-#define PCRE_MINOR 37
-#define PCRE_PRERELEASE
-#define PCRE_DATE 2015-04-28
+#define PCRE_MINOR 38
+#define PCRE_PRERELEASE -RC1
+#define PCRE_DATE 2015-05-03
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
index 0efad2645d..866aa8c693 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre/pcre_compile.c
@@ -174,7 +174,7 @@ static const short int escapes[] = {
-ESC_Z, CHAR_LEFT_SQUARE_BRACKET,
CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,
CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE,
- CHAR_GRAVE_ACCENT, 7,
+ CHAR_GRAVE_ACCENT, ESC_a,
-ESC_b, 0,
-ESC_d, ESC_e,
ESC_f, 0,
@@ -202,9 +202,9 @@ static const short int escapes[] = {
/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?',
/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"',
-/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
+/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
-/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p,
+/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p,
/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0,
/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0,
@@ -219,6 +219,12 @@ static const short int escapes[] = {
/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0
};
+
+/* We also need a table of characters that may follow \c in an EBCDIC
+environment for characters 0-31. */
+
+static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
+
#endif
@@ -458,7 +464,7 @@ static const char error_texts[] =
"range out of order in character class\0"
"nothing to repeat\0"
/* 10 */
- "operand of unlimited repeat could match the empty string\0" /** DEAD **/
+ "internal error: invalid forward reference offset\0"
"internal error: unexpected repeat\0"
"unrecognized character after (? or (?-\0"
"POSIX named classes are supported only within a class\0"
@@ -527,7 +533,11 @@ static const char error_texts[] =
"different names for subpatterns of the same number are not allowed\0"
"(*MARK) must have an argument\0"
"this version of PCRE is not compiled with Unicode property support\0"
+#ifndef EBCDIC
"\\c must be followed by an ASCII character\0"
+#else
+ "\\c must be followed by a letter or one of [\\]^_?\0"
+#endif
"\\k is not followed by a braced, angle-bracketed, or quoted name\0"
/* 70 */
"internal error: unknown opcode in find_fixedlength()\0"
@@ -1425,7 +1435,16 @@ else
c ^= 0x40;
#else /* EBCDIC coding */
if (c >= CHAR_a && c <= CHAR_z) c += 64;
- c ^= 0xC0;
+ if (c == CHAR_QUESTION_MARK)
+ c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;
+ else
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (c == ebcdic_escape_c[i]) break;
+ }
+ if (i < 32) c = i; else *errorcodeptr = ERR68;
+ }
#endif
break;
@@ -1799,7 +1818,7 @@ for (;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
do cc += GET(cc, 1); while (*cc == OP_ALT);
- cc += PRIV(OP_lengths)[*cc];
+ cc += 1 + LINK_SIZE;
break;
/* Skip over things that don't match chars */
@@ -2487,7 +2506,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
if (c == OP_BRA || c == OP_BRAPOS ||
c == OP_CBRA || c == OP_CBRAPOS ||
c == OP_ONCE || c == OP_ONCE_NC ||
- c == OP_COND)
+ c == OP_COND || c == OP_SCOND)
{
BOOL empty_branch;
if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */
@@ -3886,11 +3905,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:].
The problem in trying to be exactly like Perl is in the handling of escapes. We
have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX
class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code
-below handles the special case of \], but does not try to do any other escape
-processing. This makes it different from Perl for cases such as [:l\ower:]
-where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize
-"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does,
-I think.
+below handles the special cases \\ and \], but does not try to do any other
+escape processing. This makes it different from Perl for cases such as
+[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does
+not recognize "l\ower". This is a lesser evil than not diagnosing bad classes
+when Perl does, I think.
A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not.
It seems that the appearance of a nested POSIX class supersedes an apparent
@@ -3917,21 +3936,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */
terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
for (++ptr; *ptr != CHAR_NULL; ptr++)
{
- if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
+ if (*ptr == CHAR_BACKSLASH &&
+ (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET ||
+ ptr[1] == CHAR_BACKSLASH))
ptr++;
- else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
- else
+ else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||
+ *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
+ else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
{
- if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
- {
- *endptr = ptr;
- return TRUE;
- }
- if (*ptr == CHAR_LEFT_SQUARE_BRACKET &&
- (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
- ptr[1] == CHAR_EQUALS_SIGN) &&
- check_posix_syntax(ptr, endptr))
- return FALSE;
+ *endptr = ptr;
+ return TRUE;
}
}
return FALSE;
@@ -3985,11 +3999,12 @@ have their offsets adjusted. That one of the jobs of this function. Before it
is called, the partially compiled regex must be temporarily terminated with
OP_END.
-This function has been extended with the possibility of forward references for
-recursions and subroutine calls. It must also check the list of such references
-for the group we are dealing with. If it finds that one of the recursions in
-the current group is on this list, it adjusts the offset in the list, not the
-value in the reference (which is a group number).
+This function has been extended to cope with forward references for recursions
+and subroutine calls. It must check the list of such references for the
+group we are dealing with. If it finds that one of the recursions in the
+current group is on this list, it does not adjust the value in the reference
+(which is a group number). After the group has been scanned, all the offsets in
+the forward reference list for the group are adjusted.
Arguments:
group points to the start of the group
@@ -4005,29 +4020,21 @@ static void
adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
size_t save_hwm_offset)
{
+int offset;
+pcre_uchar *hc;
pcre_uchar *ptr = group;
while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
{
- int offset;
- pcre_uchar *hc;
-
- /* See if this recursion is on the forward reference list. If so, adjust the
- reference. */
-
for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
hc += LINK_SIZE)
{
offset = (int)GET(hc, 0);
- if (cd->start_code + offset == ptr + 1)
- {
- PUT(hc, 0, offset + adjust);
- break;
- }
+ if (cd->start_code + offset == ptr + 1) break;
}
- /* Otherwise, adjust the recursion offset if it's after the start of this
- group. */
+ /* If we have not found this recursion on the forward reference list, adjust
+ the recursion's offset if it's after the start of this group. */
if (hc >= cd->hwm)
{
@@ -4037,6 +4044,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
ptr += 1 + LINK_SIZE;
}
+
+/* Now adjust all forward reference offsets for the group. */
+
+for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
+ hc += LINK_SIZE)
+ {
+ offset = (int)GET(hc, 0);
+ PUT(hc, 0, offset + adjust);
+ }
}
@@ -4465,7 +4481,7 @@ const pcre_uchar *tempptr;
const pcre_uchar *nestptr = NULL;
pcre_uchar *previous = NULL;
pcre_uchar *previous_callout = NULL;
-size_t save_hwm_offset = 0;
+size_t item_hwm_offset = 0;
pcre_uint8 classbits[32];
/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
@@ -4767,6 +4783,7 @@ for (;; ptr++)
zeroreqchar = reqchar;
zeroreqcharflags = reqcharflags;
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
break;
@@ -4818,6 +4835,7 @@ for (;; ptr++)
/* Handle a real character class. */
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
/* PCRE supports POSIX class stuff inside a class. Perl gives an error if
they are encountered at the top level, so we'll do that too. */
@@ -5195,9 +5213,9 @@ for (;; ptr++)
cd, PRIV(vspace_list));
continue;
-#ifdef SUPPORT_UCP
case ESC_p:
case ESC_P:
+#ifdef SUPPORT_UCP
{
BOOL negated;
unsigned int ptype = 0, pdata = 0;
@@ -5211,6 +5229,9 @@ for (;; ptr++)
class_has_8bitchar--; /* Undo! */
continue;
}
+#else
+ *errorcodeptr = ERR45;
+ goto FAILED;
#endif
/* Unrecognized escapes are faulted if PCRE is running in its
strict mode. By default, for compatibility with Perl, they are
@@ -5930,7 +5951,7 @@ for (;; ptr++)
{
register int i;
int len = (int)(code - previous);
- size_t base_hwm_offset = save_hwm_offset;
+ size_t base_hwm_offset = item_hwm_offset;
pcre_uchar *bralink = NULL;
pcre_uchar *brazeroptr = NULL;
@@ -5985,7 +6006,7 @@ for (;; ptr++)
if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
{
*code = OP_END;
- adjust_recurse(previous, 1, utf, cd, save_hwm_offset);
+ adjust_recurse(previous, 1, utf, cd, item_hwm_offset);
memmove(previous + 1, previous, IN_UCHARS(len));
code++;
if (repeat_max == 0)
@@ -6009,7 +6030,7 @@ for (;; ptr++)
{
int offset;
*code = OP_END;
- adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset);
+ adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
code += 2 + LINK_SIZE;
*previous++ = OP_BRAZERO + repeat_type;
@@ -6254,6 +6275,12 @@ for (;; ptr++)
while (*scode == OP_ALT);
}
+ /* A conditional group with only one branch has an implicit empty
+ alternative branch. */
+
+ if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)
+ *bracode = OP_SCOND;
+
/* Handle possessive quantifiers. */
if (possessive_quantifier)
@@ -6267,11 +6294,11 @@ for (;; ptr++)
{
int nlen = (int)(code - bracode);
*code = OP_END;
- adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
+ adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
code += 1 + LINK_SIZE;
nlen += 1 + LINK_SIZE;
- *bracode = OP_BRAPOS;
+ *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;
*code++ = OP_KETRPOS;
PUTINC(code, 0, nlen);
PUT(bracode, 1, nlen);
@@ -6401,7 +6428,7 @@ for (;; ptr++)
else
{
*code = OP_END;
- adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
+ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
@@ -6450,7 +6477,7 @@ for (;; ptr++)
default:
*code = OP_END;
- adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset);
+ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
@@ -6623,7 +6650,7 @@ for (;; ptr++)
newoptions = options;
skipbytes = 0;
bravalue = OP_CBRA;
- save_hwm_offset = cd->hwm - cd->start_workspace;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
reset_bracount = FALSE;
/* Deal with the extended parentheses; all are introduced by '?', and the
@@ -6641,6 +6668,7 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
reset_bracount = TRUE;
+ cd->dupgroups = TRUE; /* Record (?| encountered */
/* Fall through */
/* ------------------------------------------------------------ */
@@ -6741,6 +6769,12 @@ for (;; ptr++)
{
while (IS_DIGIT(*ptr))
{
+ if (recno > INT_MAX / 10 - 1) /* Integer overflow */
+ {
+ while (IS_DIGIT(*ptr)) ptr++;
+ *errorcodeptr = ERR61;
+ goto FAILED;
+ }
recno = recno * 10 + (int)(*ptr - CHAR_0);
ptr++;
}
@@ -6769,7 +6803,7 @@ for (;; ptr++)
ptr++;
}
namelen = (int)(ptr - name);
- if (lengthptr != NULL) *lengthptr += IMM2_SIZE;
+ if (lengthptr != NULL) skipbytes += IMM2_SIZE;
}
/* Check the terminator */
@@ -6875,6 +6909,11 @@ for (;; ptr++)
*errorcodeptr = ERR15;
goto FAILED;
}
+ if (recno > INT_MAX / 10 - 1) /* Integer overflow */
+ {
+ *errorcodeptr = ERR61;
+ goto FAILED;
+ }
recno = recno * 10 + name[i] - CHAR_0;
}
if (recno == 0) recno = RREF_ANY;
@@ -7151,7 +7190,8 @@ for (;; ptr++)
if (lengthptr != NULL)
{
named_group *ng;
-
+ recno = 0;
+
if (namelen == 0)
{
*errorcodeptr = ERR62;
@@ -7168,20 +7208,6 @@ for (;; ptr++)
goto FAILED;
}
- /* The name table does not exist in the first pass; instead we must
- scan the list of names encountered so far in order to get the
- number. If the name is not found, set the value to 0 for a forward
- reference. */
-
- ng = cd->named_groups;
- for (i = 0; i < cd->names_found; i++, ng++)
- {
- if (namelen == ng->length &&
- STRNCMP_UC_UC(name, ng->name, namelen) == 0)
- break;
- }
- recno = (i < cd->names_found)? ng->number : 0;
-
/* Count named back references. */
if (!is_recurse) cd->namedrefcount++;
@@ -7191,6 +7217,56 @@ for (;; ptr++)
16-bit data item. */
*lengthptr += IMM2_SIZE;
+
+ /* If this is a forward reference and we are within a (?|...) group,
+ the reference may end up as the number of a group which we are
+ currently inside, that is, it could be a recursive reference. In the
+ real compile this will be picked up and the reference wrapped with
+ OP_ONCE to make it atomic, so we must space in case this occurs. */
+
+ /* In fact, this can happen for a non-forward reference because
+ another group with the same number might be created later. This
+ issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
+ only mode, we finesse the bug by allowing more memory always. */
+
+ *lengthptr += 2 + 2*LINK_SIZE;
+
+ /* It is even worse than that. The current reference may be to an
+ existing named group with a different number (so apparently not
+ recursive) but which later on is also attached to a group with the
+ current number. This can only happen if $(| has been previous
+ encountered. In that case, we allow yet more memory, just in case.
+ (Again, this is fixed "properly" in PCRE2. */
+
+ if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE;
+
+ /* Otherwise, check for recursion here. The name table does not exist
+ in the first pass; instead we must scan the list of names encountered
+ so far in order to get the number. If the name is not found, leave
+ the value of recno as 0 for a forward reference. */
+
+ else
+ {
+ ng = cd->named_groups;
+ for (i = 0; i < cd->names_found; i++, ng++)
+ {
+ if (namelen == ng->length &&
+ STRNCMP_UC_UC(name, ng->name, namelen) == 0)
+ {
+ open_capitem *oc;
+ recno = ng->number;
+ if (is_recurse) break;
+ for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ {
+ if (oc->number == recno)
+ {
+ oc->flag = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
}
/* In the real compile, search the name table. We check the name
@@ -7237,8 +7313,6 @@ for (;; ptr++)
for (i++; i < cd->names_found; i++)
{
if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
-
-
count++;
cslot += cd->name_entry_size;
}
@@ -7247,6 +7321,7 @@ for (;; ptr++)
{
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
PUT2INC(code, 0, index);
PUT2INC(code, 0, count);
@@ -7284,9 +7359,14 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
- case CHAR_R: /* Recursion */
- ptr++; /* Same as (?0) */
- /* Fall through */
+ case CHAR_R: /* Recursion, same as (?0) */
+ recno = 0;
+ if (*(++ptr) != CHAR_RIGHT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR29;
+ goto FAILED;
+ }
+ goto HANDLE_RECURSION;
/* ------------------------------------------------------------ */
@@ -7323,7 +7403,15 @@ for (;; ptr++)
recno = 0;
while(IS_DIGIT(*ptr))
+ {
+ if (recno > INT_MAX / 10 - 1) /* Integer overflow */
+ {
+ while (IS_DIGIT(*ptr)) ptr++;
+ *errorcodeptr = ERR61;
+ goto FAILED;
+ }
recno = recno * 10 + *ptr++ - CHAR_0;
+ }
if (*ptr != (pcre_uchar)terminator)
{
@@ -7360,6 +7448,7 @@ for (;; ptr++)
HANDLE_RECURSION:
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
called = cd->start_code;
/* When we are actually compiling, find the bracket that is being
@@ -7561,7 +7650,11 @@ for (;; ptr++)
previous = NULL;
cd->iscondassert = FALSE;
}
- else previous = code;
+ else
+ {
+ previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
+ }
*code = bravalue;
tempcode = code;
@@ -7809,7 +7902,7 @@ for (;; ptr++)
const pcre_uchar *p;
pcre_uint32 cf;
- save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
+ item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
@@ -7838,7 +7931,7 @@ for (;; ptr++)
if (*p != (pcre_uchar)terminator)
{
*errorcodeptr = ERR57;
- break;
+ goto FAILED;
}
ptr++;
goto HANDLE_NUMERICAL_RECURSION;
@@ -7853,7 +7946,7 @@ for (;; ptr++)
ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET))
{
*errorcodeptr = ERR69;
- break;
+ goto FAILED;
}
is_recurse = FALSE;
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
@@ -7877,6 +7970,7 @@ for (;; ptr++)
HANDLE_REFERENCE:
if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
PUT2INC(code, 0, recno);
cd->backref_map |= (recno < 32)? (1 << recno) : 1;
@@ -7906,6 +8000,7 @@ for (;; ptr++)
if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
goto FAILED;
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
*code++ = ptype;
*code++ = pdata;
@@ -7946,6 +8041,7 @@ for (;; ptr++)
{
previous = (escape > ESC_b && escape < ESC_Z)? code : NULL;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape;
}
}
@@ -7989,6 +8085,7 @@ for (;; ptr++)
ONE_CHAR:
previous = code;
+ item_hwm_offset = cd->hwm - cd->start_workspace;
/* For caseless UTF-8 mode when UCP support is available, check whether
this character has more than one other case. If so, generate a special
@@ -9164,6 +9261,7 @@ cd->names_found = 0;
cd->name_entry_size = 0;
cd->name_table = NULL;
cd->dupnames = FALSE;
+cd->dupgroups = FALSE;
cd->namedrefcount = 0;
cd->start_code = cworkspace;
cd->hwm = cworkspace;
@@ -9198,7 +9296,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN;
DPRINTF(("end pre-compile: length=%d workspace=%d\n", length,
(int)(cd->hwm - cworkspace)));
-
+
if (length > MAX_PATTERN_SIZE)
{
errorcode = ERR20;
@@ -9336,6 +9434,16 @@ if (cd->hwm > cd->start_workspace)
int offset, recno;
cd->hwm -= LINK_SIZE;
offset = GET(cd->hwm, 0);
+
+ /* Check that the hwm handling hasn't gone wrong. This whole area is
+ rewritten in PCRE2 because there are some obscure cases. */
+
+ if (offset == 0 || codestart[offset-1] != OP_RECURSE)
+ {
+ errorcode = ERR10;
+ break;
+ }
+
recno = GET(codestart, offset);
if (recno != prev_recno)
{
@@ -9366,7 +9474,7 @@ used in this code because at least one compiler gives a warning about loss of
"const" attribute if the cast (pcre_uchar *)codestart is used directly in the
function call. */
-if ((options & PCRE_NO_AUTO_POSSESS) == 0)
+if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0)
{
pcre_uchar *temp = (pcre_uchar *)codestart;
auto_possessify(temp, utf, cd);
@@ -9380,7 +9488,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The
exceptional ones forgo this. We scan the pattern to check that they are fixed
length, and set their lengths. */
-if (cd->check_lookbehind)
+if (errorcode == 0 && cd->check_lookbehind)
{
pcre_uchar *cc = (pcre_uchar *)codestart;
@@ -9593,4 +9701,3 @@ return (pcre32 *)re;
}
/* End of pcre_compile.c */
-
diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c
index c021fe1a4c..24b23ca286 100644
--- a/src/3rdparty/pcre/pcre_exec.c
+++ b/src/3rdparty/pcre/pcre_exec.c
@@ -6685,7 +6685,8 @@ if (md->offset_vector != NULL)
register int *iend = iptr - re->top_bracket;
if (iend < md->offset_vector + 2) iend = md->offset_vector + 2;
while (--iptr >= iend) *iptr = -1;
- md->offset_vector[0] = md->offset_vector[1] = -1;
+ if (offsetcount > 0) md->offset_vector[0] = -1;
+ if (offsetcount > 1) md->offset_vector[1] = -1;
}
/* Set up the first character to match, if available. The first_char value is
diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h
index dd0ac7fc91..544d9c0709 100644
--- a/src/3rdparty/pcre/pcre_internal.h
+++ b/src/3rdparty/pcre/pcre_internal.h
@@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
#ifndef EBCDIC
#define HSPACE_LIST \
- CHAR_HT, CHAR_SPACE, 0xa0, \
+ CHAR_HT, CHAR_SPACE, CHAR_NBSP, \
0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \
NOTACHAR
@@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
#define HSPACE_BYTE_CASES \
case CHAR_HT: \
case CHAR_SPACE: \
- case 0xa0 /* NBSP */
+ case CHAR_NBSP
#define HSPACE_CASES \
HSPACE_BYTE_CASES: \
@@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
/* ------ EBCDIC environments ------ */
#else
-#define HSPACE_LIST CHAR_HT, CHAR_SPACE
+#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR
#define HSPACE_BYTE_CASES \
case CHAR_HT: \
- case CHAR_SPACE
+ case CHAR_SPACE: \
+ case CHAR_NBSP
#define HSPACE_CASES HSPACE_BYTE_CASES
@@ -1215,6 +1216,7 @@ same code point. */
#define CHAR_ESC '\047'
#define CHAR_DEL '\007'
+#define CHAR_NBSP '\x41'
#define STR_ESC "\047"
#define STR_DEL "\007"
@@ -1229,6 +1231,7 @@ a positive value. */
#define CHAR_NEL ((unsigned char)'\x85')
#define CHAR_ESC '\033'
#define CHAR_DEL '\177'
+#define CHAR_NBSP ((unsigned char)'\xa0')
#define STR_LF "\n"
#define STR_NL STR_LF
@@ -1606,6 +1609,7 @@ only. */
#define CHAR_VERTICAL_LINE '\174'
#define CHAR_RIGHT_CURLY_BRACKET '\175'
#define CHAR_TILDE '\176'
+#define CHAR_NBSP ((unsigned char)'\xa0')
#define STR_HT "\011"
#define STR_VT "\013"
@@ -1762,6 +1766,10 @@ only. */
/* Escape items that are just an encoding of a particular data value. */
+#ifndef ESC_a
+#define ESC_a CHAR_BEL
+#endif
+
#ifndef ESC_e
#define ESC_e CHAR_ESC
#endif
@@ -2446,6 +2454,7 @@ typedef struct compile_data {
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL check_lookbehind; /* Lookbehinds need later checking */
BOOL dupnames; /* Duplicate names exist */
+ BOOL dupgroups; /* Duplicate groups exist: (?| found */
BOOL iscondassert; /* Next assert is a condition */
int nltype; /* Newline type */
int nllen; /* Newline string length */
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c
index debdf6ef45..868d1d91bf 100644
--- a/src/3rdparty/pcre/pcre_jit_compile.c
+++ b/src/3rdparty/pcre/pcre_jit_compile.c
@@ -1064,6 +1064,7 @@ pcre_uchar *alternative;
pcre_uchar *end = NULL;
int private_data_ptr = *private_data_start;
int space, size, bracketlen;
+BOOL repeat_check = TRUE;
while (cc < ccend)
{
@@ -1071,9 +1072,10 @@ while (cc < ccend)
size = 0;
bracketlen = 0;
if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE)
- return;
+ break;
- if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)
+ if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND))
+ {
if (detect_repeat(common, cc))
{
/* These brackets are converted to repeats, so no global
@@ -1081,6 +1083,8 @@ while (cc < ccend)
if (cc >= end)
end = bracketend(cc);
}
+ }
+ repeat_check = TRUE;
switch(*cc)
{
@@ -1136,6 +1140,13 @@ while (cc < ccend)
bracketlen = 1 + LINK_SIZE + IMM2_SIZE;
break;
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+ case OP_BRAPOSZERO:
+ repeat_check = FALSE;
+ size = 1;
+ break;
+
CASE_ITERATOR_PRIVATE_DATA_1
space = 1;
size = -2;
@@ -1162,12 +1173,17 @@ while (cc < ccend)
size = 1;
break;
- CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
+ case OP_TYPEUPTO:
if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI)
space = 2;
size = 1 + IMM2_SIZE;
break;
+ case OP_TYPEMINUPTO:
+ space = 2;
+ size = 1 + IMM2_SIZE;
+ break;
+
case OP_CLASS:
case OP_NCLASS:
size += 1 + 32 / sizeof(pcre_uchar);
@@ -1316,6 +1332,13 @@ while (cc < ccend)
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
+ case OP_THEN:
+ stack_restore = TRUE;
+ if (common->control_head_ptr != 0)
+ *needs_control_head = TRUE;
+ cc ++;
+ break;
+
default:
stack_restore = TRUE;
/* Fall through. */
@@ -2220,6 +2243,7 @@ while (current != NULL)
SLJIT_ASSERT_STOP();
break;
}
+ SLJIT_ASSERT(current > (sljit_sw*)current[-1]);
current = (sljit_sw*)current[-1];
}
return -1;
@@ -3209,7 +3233,7 @@ bytes[len] = byte;
bytes[0] = len;
}
-static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars)
+static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count)
{
/* Recursive function, which scans prefix literals. */
BOOL last, any, caseless;
@@ -3227,9 +3251,14 @@ pcre_uchar othercase[1];
repeat = 1;
while (TRUE)
{
+ if (*rec_count == 0)
+ return 0;
+ (*rec_count)--;
+
last = TRUE;
any = FALSE;
caseless = FALSE;
+
switch (*cc)
{
case OP_CHARI:
@@ -3291,7 +3320,7 @@ while (TRUE)
#ifdef SUPPORT_UTF
if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
- max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars);
+ max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
last = FALSE;
@@ -3314,7 +3343,7 @@ while (TRUE)
alternative = cc + GET(cc, 1);
while (*alternative == OP_ALT)
{
- max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars);
+ max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count);
if (max_chars == 0)
return consumed;
alternative += GET(alternative, 1);
@@ -3556,6 +3585,7 @@ int i, max, from;
int range_right = -1, range_len = 3 - 1;
sljit_ub *update_table = NULL;
BOOL in_range;
+pcre_uint32 rec_count;
for (i = 0; i < MAX_N_CHARS; i++)
{
@@ -3564,7 +3594,8 @@ for (i = 0; i < MAX_N_CHARS; i++)
bytes[i * MAX_N_BYTES] = 0;
}
-max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS);
+rec_count = 10000;
+max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count);
if (max <= 1)
return FALSE;
@@ -7665,6 +7696,10 @@ while (*cc != OP_KETRPOS)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
}
+ /* Even if the match is empty, we need to reset the control head. */
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
+
if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
@@ -7692,6 +7727,10 @@ while (*cc != OP_KETRPOS)
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0);
}
+ /* Even if the match is empty, we need to reset the control head. */
+ if (needs_control_head)
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
+
if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0));
@@ -7704,9 +7743,6 @@ while (*cc != OP_KETRPOS)
}
}
- if (needs_control_head)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack));
-
JUMPTO(SLJIT_JUMP, loop);
flush_stubs(common);
@@ -9648,6 +9684,7 @@ set_jumps(common->currententry->calls, common->currententry->entry);
sljit_emit_fast_enter(compiler, TMP2, 0);
allocate_stack(common, private_data_size + framesize + alternativesize);
+count_match(common);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0);
copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head);
if (needs_control_head)
@@ -9992,6 +10029,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match));
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
if (mode == JIT_PARTIAL_SOFT_COMPILE)
diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c
index 998fe2325e..932e9a7c4c 100644
--- a/src/3rdparty/pcre/pcre_study.c
+++ b/src/3rdparty/pcre/pcre_study.c
@@ -71,6 +71,7 @@ Arguments:
startcode pointer to start of the whole pattern's code
options the compiling options
recurses chain of recurse_check to catch mutual recursion
+ countptr pointer to call count (to catch over complexity)
Returns: the minimum length
-1 if \C in UTF-8 mode or (*ACCEPT) was encountered
@@ -80,7 +81,8 @@ Returns: the minimum length
static int
find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
- const pcre_uchar *startcode, int options, recurse_check *recurses)
+ const pcre_uchar *startcode, int options, recurse_check *recurses,
+ int *countptr)
{
int length = -1;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
@@ -90,6 +92,8 @@ recurse_check this_recurse;
register int branchlength = 0;
register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
+if ((*countptr)++ > 1000) return -1; /* too complex */
+
if (*code == OP_CBRA || *code == OP_SCBRA ||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;
@@ -131,7 +135,7 @@ for (;;)
case OP_SBRAPOS:
case OP_ONCE:
case OP_ONCE_NC:
- d = find_minlength(re, cc, startcode, options, recurses);
+ d = find_minlength(re, cc, startcode, options, recurses, countptr);
if (d < 0) return d;
branchlength += d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
@@ -415,7 +419,8 @@ for (;;)
int dd;
this_recurse.prev = recurses;
this_recurse.group = cs;
- dd = find_minlength(re, cs, startcode, options, &this_recurse);
+ dd = find_minlength(re, cs, startcode, options, &this_recurse,
+ countptr);
if (dd < d) d = dd;
}
}
@@ -451,7 +456,8 @@ for (;;)
{
this_recurse.prev = recurses;
this_recurse.group = cs;
- d = find_minlength(re, cs, startcode, options, &this_recurse);
+ d = find_minlength(re, cs, startcode, options, &this_recurse,
+ countptr);
}
}
}
@@ -514,7 +520,7 @@ for (;;)
this_recurse.prev = recurses;
this_recurse.group = cs;
branchlength += find_minlength(re, cs, startcode, options,
- &this_recurse);
+ &this_recurse, countptr);
}
}
cc += 1 + LINK_SIZE;
@@ -1453,6 +1459,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
#endif
{
int min;
+int count = 0;
BOOL bits_set = FALSE;
pcre_uint8 start_bits[32];
PUBL(extra) *extra = NULL;
@@ -1539,7 +1546,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
/* Find the minimum length of subject string. */
-switch(min = find_minlength(re, code, code, re->options, NULL))
+switch(min = find_minlength(re, code, code, re->options, NULL, &count))
{
case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h
index 10364c3b60..1c8a521aa8 100644
--- a/src/3rdparty/pcre/sljit/sljitConfig.h
+++ b/src/3rdparty/pcre/sljit/sljitConfig.h
@@ -96,6 +96,15 @@
#define SLJIT_EXECUTABLE_ALLOCATOR 1
#endif
+/* Force cdecl calling convention even if a better calling
+ convention (e.g. fastcall) is supported by the C compiler.
+ If this option is enabled, C functions without
+ SLJIT_CALL can also be called from JIT code. */
+#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION
+/* Disabled by default */
+#define SLJIT_USE_CDECL_CALLING_CONVENTION 0
+#endif
+
/* Return with error when an invalid argument is passed. */
#ifndef SLJIT_ARGUMENT_CHECKS
/* Disabled by default */
diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
index 3284012f19..16e3547c93 100644
--- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h
+++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h
@@ -468,7 +468,12 @@ typedef double sljit_d;
#ifndef SLJIT_CALL
-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION)
+
+/* Force cdecl. */
+#define SLJIT_CALL
+
+#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if defined(__GNUC__) && !defined(__APPLE__)
@@ -608,6 +613,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw))
#endif
+#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
+
+#define SLJIT_NUMBER_OF_REGISTERS 10
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5
+#define SLJIT_LOCALS_OFFSET_BASE 0
+
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define SLJIT_NUMBER_OF_REGISTERS 0
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c
index 5039a7e04e..0f1b1c9cce 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.c
+++ b/src/3rdparty/pcre/sljit/sljitLir.c
@@ -845,8 +845,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
}
static SLJIT_CONST char* op0_names[] = {
- (char*)"breakpoint", (char*)"nop",
- (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv",
+ (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul",
+ (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi"
};
static SLJIT_CONST char* op1_names[] = {
@@ -1036,7 +1036,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL)
- || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV));
+ || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI));
CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@@ -1447,6 +1447,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset)
{
+ SLJIT_UNUSED_ARG(offset);
+
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
@@ -1462,6 +1464,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
{
+ SLJIT_UNUSED_ARG(init_value);
+
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_DST(dst, dstw);
#endif
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h
index 24c0f60399..f0969dac2e 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.h
+++ b/src/3rdparty/pcre/sljit/sljitLir.h
@@ -687,7 +687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
#define SLJIT_OP0_BASE 0
/* Flags: - (never set any flags)
- Note: breakpoint instruction is not supported by all architectures (namely ppc)
+ Note: breakpoint instruction is not supported by all architectures (e.g. ppc)
It falls back to SLJIT_NOP in those cases. */
#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
/* Flags: - (never set any flags)
@@ -696,24 +696,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
/* Flags: - (may destroy flags)
Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
- Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
#define SLJIT_LUMUL (SLJIT_OP0_BASE + 2)
/* Flags: - (may destroy flags)
Signed multiplication of SLJIT_R0 and SLJIT_R1.
- Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */
+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
#define SLJIT_LSMUL (SLJIT_OP0_BASE + 3)
/* Flags: I - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
- The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
- Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
-#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4)
-#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP)
+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined. */
+#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4)
+#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
- The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1.
- Note: if SLJIT_R1 contains 0, the behaviour is undefined. */
-#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5)
-#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP)
+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined.
+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+ the behaviour is undefined. */
+#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5)
+#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP)
+/* Flags: I - (may destroy flags)
+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined.
+ Note: SLJIT_SDIV is single precision divide. */
+#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6)
+#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP)
+/* Flags: I - (may destroy flags)
+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined.
+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+ the behaviour is undefined.
+ Note: SLJIT_SDIV is single precision divide. */
+#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7)
+#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
index aca1d31fdf..5cd4c71a29 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
@@ -1833,18 +1833,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
| (reg_map[SLJIT_R0] << 8)
| reg_map[TMP_REG1]);
#endif
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
- if (compiler->scratches >= 3)
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+ SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping);
+
+ if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */));
+ FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */));
+ }
+ else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
+ FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */));
+
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+ ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
- if (compiler->scratches >= 3)
- return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */);
+
+ if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) {
+ FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */));
+ FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */));
+ }
+ else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3))
+ return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */);
return SLJIT_SUCCESS;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
index b66455f756..044a675eee 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
@@ -1087,14 +1087,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
saved_regs_size += sizeof(sljit_sw);
}
local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET;
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
+ if (saved_regs_size > 0)
+ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
}
tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
prev = -1;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
- prev = i;
+ if (!(offs & (1 << 15))) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+ offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1104,7 +1110,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
- prev = i;
+ if (!(offs & (1 << 15))) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+ offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1112,8 +1123,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
prev = -1;
}
- if (prev != -1)
- FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
+ SLJIT_ASSERT(prev == -1);
if (compiler->local_size > (63 * sizeof(sljit_sw))) {
/* The local_size is already adjusted by the saved registers. */
@@ -1188,7 +1198,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
prev = -1;
for (i = SLJIT_S0; i >= tmp; i--) {
if (prev == -1) {
- prev = i;
+ if (!(offs & (1 << 15))) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+ offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1198,7 +1213,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
if (prev == -1) {
- prev = i;
+ if (!(offs & (1 << 15))) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5)));
+ offs += 1 << 15;
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
@@ -1206,13 +1226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
prev = -1;
}
- if (prev != -1)
- FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));
+ SLJIT_ASSERT(prev == -1);
if (compiler->local_size <= (63 * sizeof(sljit_sw))) {
FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR)
| RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15)));
- } else {
+ } else if (saved_regs_size > 0) {
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10)));
}
@@ -1242,12 +1261,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0)));
- FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
}
return SLJIT_SUCCESS;
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
index 6e38cec899..f9803f5d44 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
@@ -1239,6 +1239,9 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
{
+ sljit_sw saved_reg_list[3];
+ sljit_sw saved_reg_count;
+
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@@ -1255,24 +1258,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
| (reg_map[SLJIT_R0] << 12)
| (reg_map[SLJIT_R0] << 16)
| reg_map[SLJIT_R1]);
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
- if (compiler->scratches >= 4) {
- FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */));
- FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */));
- } else if (compiler->scratches >= 3)
- FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */));
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
+ SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping);
+
+ saved_reg_count = 0;
+ if (compiler->scratches >= 4)
+ saved_reg_list[saved_reg_count++] = 12;
+ if (compiler->scratches >= 3)
+ saved_reg_list[saved_reg_count++] = 2;
+ if (op >= SLJIT_UDIVI)
+ saved_reg_list[saved_reg_count++] = 1;
+
+ if (saved_reg_count > 0) {
+ FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));
+ }
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));
+ }
+ }
+
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+ ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
- if (compiler->scratches >= 4) {
- FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */));
- return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */);
- } else if (compiler->scratches >= 3)
- return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */);
+
+ if (saved_reg_count > 0) {
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));
+ }
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));
+ }
+ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
+ }
return SLJIT_SUCCESS;
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
index 3e2c9f0232..cf3535f81a 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
@@ -1053,8 +1053,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#endif
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
@@ -1062,15 +1065,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (int_op)
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
else
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
#else
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
#endif
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
- return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+ return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
}
return SLJIT_SUCCESS;
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
index 08d5356f5a..b6a043f4e4 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
@@ -1267,22 +1267,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
#endif
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (int_op) {
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
- FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
- } else {
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
- FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
- }
- return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
+ FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
#else
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
+#endif
return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
+#else
+ return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
#endif
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
index 0b1927a824..327c4267be 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
@@ -777,20 +777,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#else
#error "Implementation required"
#endif
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
- if (op == SLJIT_LUDIV)
+ if ((op | 0x2) == SLJIT_UDIVI)
FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS));
else {
FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS));
}
- FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+ if (op <= SLJIT_SDIVMOD)
+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0)));
+ if (op >= SLJIT_UDIVI)
+ return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1)));
- FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)));
- return SLJIT_SUCCESS;
+ return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1));
#else
#error "Implementation required"
#endif
diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
index 1d6aa5a110..4d40392fa8 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
@@ -35,21 +35,21 @@
#define SIMM_16BIT_MIN (-0x8000)
#define SIMM_17BIT_MAX (0xffff)
#define SIMM_17BIT_MIN (-0x10000)
-#define SIMM_32BIT_MIN (-0x80000000)
#define SIMM_32BIT_MAX (0x7fffffff)
-#define SIMM_48BIT_MIN (0x800000000000L)
+#define SIMM_32BIT_MIN (-0x7fffffff - 1)
#define SIMM_48BIT_MAX (0x7fffffff0000L)
+#define SIMM_48BIT_MIN (-0x800000000000L)
#define IMM16(imm) ((imm) & 0xffff)
#define UIMM_16BIT_MAX (0xffff)
-#define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
-#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
-#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
-#define ADDR_TMP (SLJIT_NO_REGISTERS + 4)
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
+#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5)
#define PIC_ADDR_REG TMP_REG2
-static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
+static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7
};
@@ -58,11 +58,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = {
#define TMP_REG2_mapped 16
#define TMP_REG3_mapped 6
#define ADDR_TMP_mapped 7
-#define SLJIT_SAVED_REG1_mapped 30
-#define SLJIT_SAVED_REG2_mapped 31
-#define SLJIT_SAVED_REG3_mapped 32
-#define SLJIT_SAVED_EREG1_mapped 33
-#define SLJIT_SAVED_EREG2_mapped 34
/* Flags are keept in volatile registers. */
#define EQUAL_FLAG 8
@@ -399,6 +394,9 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins)
#define SUB(dst, srca, srcb) \
push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__)
+#define MUL(dst, srca, srcb) \
+ push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__)
+
#define NOR(dst, srca, srcb) \
push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__)
@@ -547,8 +545,8 @@ const struct Format* compute_format()
const struct Format* match = NULL;
const struct Format *b = NULL;
- unsigned int i = 0;
- for (i; i < sizeof formats / sizeof formats[0]; i++) {
+ unsigned int i;
+ for (i = 0; i < sizeof formats / sizeof formats[0]; i++) {
b = &formats[i];
if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) {
match = b;
@@ -625,7 +623,6 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst)
static sljit_si update_buffer(struct sljit_compiler *compiler)
{
- int count;
int i;
int orig_index = inst_buf_index;
struct jit_instr inst0 = inst_buf[0];
@@ -738,8 +735,10 @@ static sljit_si update_buffer(struct sljit_compiler *compiler)
static sljit_si flush_buffer(struct sljit_compiler *compiler)
{
- while (inst_buf_index != 0)
- update_buffer(compiler);
+ while (inst_buf_index != 0) {
+ FAIL_IF(update_buffer(compiler));
+ }
+ return SLJIT_SUCCESS;
}
static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line)
@@ -787,6 +786,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o
case TILEGX_OPC_ADD:
case TILEGX_OPC_AND:
case TILEGX_OPC_SUB:
+ case TILEGX_OPC_MULX:
case TILEGX_OPC_OR:
case TILEGX_OPC_XOR:
case TILEGX_OPC_NOR:
@@ -905,7 +905,6 @@ static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_
sljit_sw diff;
sljit_uw target_addr;
sljit_ins *inst;
- sljit_ins saved_inst;
if (jump->flags & SLJIT_REWRITABLE_JUMP)
return code_ptr;
@@ -1009,7 +1008,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi
struct sljit_const *const_;
CHECK_ERROR_PTR();
- check_sljit_generate_code(compiler);
+ CHECK_PTR(check_sljit_generate_code(compiler));
reverse_buf(compiler);
code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
@@ -1178,13 +1177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
sljit_ins base;
- sljit_ins bundle = 0;
-
+ sljit_si i, tmp;
+
CHECK_ERROR();
- check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
+ CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += (saveds + 1) * sizeof(sljit_sw);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
local_size = (local_size + 7) & ~7;
compiler->local_size = local_size;
@@ -1200,56 +1199,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
local_size = 0;
}
+ /* Save the return address. */
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8));
- if (saveds >= 1)
- FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8));
-
- if (saveds >= 2)
- FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8));
-
- if (saveds >= 3)
- FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8));
-
- if (saveds >= 4)
- FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8));
-
- if (saveds >= 5)
- FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8));
-
- if (args >= 1)
- FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO));
+ /* Save the S registers. */
+ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
+ for (i = SLJIT_S0; i >= tmp; i--) {
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));
+ }
- if (args >= 2)
- FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO));
+ /* Save the R registers that need to be reserved. */
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8));
+ }
- if (args >= 3)
- FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO));
+ /* Move the arguments to S registers. */
+ for (i = 0; i < args; i++) {
+ FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO));
+ }
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler,
sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
- CHECK_ERROR_VOID();
- check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += (saveds + 1) * sizeof(sljit_sw);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
compiler->local_size = (local_size + 7) & ~7;
+
+ return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
sljit_si local_size;
sljit_ins base;
- int addr_initialized = 0;
+ sljit_si i, tmp;
+ sljit_si saveds;
CHECK_ERROR();
- check_sljit_emit_return(compiler, op, src, srcw);
+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
@@ -1263,50 +1258,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
local_size = 0;
}
+ /* Restore the return address. */
FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8));
- FAIL_IF(LD(RA, ADDR_TMP_mapped));
-
- if (compiler->saveds >= 5) {
- FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48));
- addr_initialized = 1;
+ FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8));
- FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8));
+ /* Restore the S registers. */
+ saveds = compiler->saveds;
+ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
+ for (i = SLJIT_S0; i >= tmp; i--) {
+ FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));
}
- if (compiler->saveds >= 4) {
- if (addr_initialized == 0) {
- FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40));
- addr_initialized = 1;
- }
-
- FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8));
- }
-
- if (compiler->saveds >= 3) {
- if (addr_initialized == 0) {
- FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32));
- addr_initialized = 1;
- }
-
- FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8));
- }
-
- if (compiler->saveds >= 2) {
- if (addr_initialized == 0) {
- FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24));
- addr_initialized = 1;
- }
-
- FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8));
- }
-
- if (compiler->saveds >= 1) {
- if (addr_initialized == 0) {
- FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16));
- /* addr_initialized = 1; no need to initialize as it's the last one. */
- }
-
- FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8));
+ /* Restore the R registers that need to be reserved. */
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8));
}
if (compiler->local_size <= SIMM_16BIT_MAX)
@@ -1585,7 +1550,7 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
CHECK_ERROR();
- check_sljit_emit_fast_enter(compiler, dst, dstw);
+ CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
/* For UNUSED dst. Uncommon, but possible. */
@@ -1602,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
- check_sljit_emit_fast_return(compiler, src, srcw);
+ CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
@@ -1636,9 +1601,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
if (op == SLJIT_MOV_SI)
return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
- return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
- } else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
+ } else if (dst != src2) {
+ SLJIT_ASSERT(src2 == 0);
+ return ADD(reg_map[dst], reg_map[src2], ZERO);
+ }
return SLJIT_SUCCESS;
@@ -1650,8 +1617,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
- } else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ } else if (dst != src2) {
+ SLJIT_ASSERT(src2 == 0);
+ return ADD(reg_map[dst], reg_map[src2], ZERO);
+ }
return SLJIT_SUCCESS;
@@ -1663,8 +1632,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
- } else if (dst != src2)
- SLJIT_ASSERT_STOP();
+ } else if (dst != src2) {
+ SLJIT_ASSERT(src2 == 0);
+ return ADD(reg_map[dst], reg_map[src2], ZERO);
+ }
return SLJIT_SUCCESS;
@@ -1811,7 +1782,6 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
else {
/* Rare ocasion. */
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
-
overflow_ra = TMP_EREG2;
}
}
@@ -1903,6 +1873,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
return SLJIT_SUCCESS;
+ case SLJIT_MUL:
+ if (flags & SRC2_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2]));
+
+ return SLJIT_SUCCESS;
+
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \
@@ -1950,8 +1931,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
} else { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
- compiler, op_imm, reg_map[dst], reg_map[src1], \
- src2 & 0x3F, __LINE__)); \
+ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
+ reg_map[src2], __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, reg_map[dst], reg_map[src1], \
@@ -2105,66 +2086,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
{
sljit_si sugg_dst_ar, dst_ar;
sljit_si flags = GET_ALL_FLAGS(op);
+ sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
CHECK_ERROR();
- check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
if (dst == SLJIT_UNUSED)
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
+ if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
+ mem_type = INT_DATA | SIGNED_DATA;
sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2];
compiler->cache_arg = 0;
compiler->cache_argw = 0;
if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
ADJUST_LOCAL_OFFSET(src, srcw);
- FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw));
src = TMP_REG1;
srcw = 0;
}
- switch (type) {
- case SLJIT_C_EQUAL:
- case SLJIT_C_NOT_EQUAL:
+ switch (type & 0xff) {
+ case SLJIT_EQUAL:
+ case SLJIT_NOT_EQUAL:
FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1));
dst_ar = sugg_dst_ar;
break;
- case SLJIT_C_LESS:
- case SLJIT_C_GREATER_EQUAL:
- case SLJIT_C_FLOAT_LESS:
- case SLJIT_C_FLOAT_GREATER_EQUAL:
+ case SLJIT_LESS:
+ case SLJIT_GREATER_EQUAL:
dst_ar = ULESS_FLAG;
break;
- case SLJIT_C_GREATER:
- case SLJIT_C_LESS_EQUAL:
- case SLJIT_C_FLOAT_GREATER:
- case SLJIT_C_FLOAT_LESS_EQUAL:
+ case SLJIT_GREATER:
+ case SLJIT_LESS_EQUAL:
dst_ar = UGREATER_FLAG;
break;
- case SLJIT_C_SIG_LESS:
- case SLJIT_C_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER_EQUAL:
dst_ar = LESS_FLAG;
break;
- case SLJIT_C_SIG_GREATER:
- case SLJIT_C_SIG_LESS_EQUAL:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_SIG_LESS_EQUAL:
dst_ar = GREATER_FLAG;
break;
- case SLJIT_C_OVERFLOW:
- case SLJIT_C_NOT_OVERFLOW:
+ case SLJIT_OVERFLOW:
+ case SLJIT_NOT_OVERFLOW:
dst_ar = OVERFLOW_FLAG;
break;
- case SLJIT_C_MUL_OVERFLOW:
- case SLJIT_C_MUL_NOT_OVERFLOW:
+ case SLJIT_MUL_OVERFLOW:
+ case SLJIT_MUL_NOT_OVERFLOW:
FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1));
dst_ar = sugg_dst_ar;
type ^= 0x1; /* Flip type bit for the XORI below. */
break;
- case SLJIT_C_FLOAT_EQUAL:
- case SLJIT_C_FLOAT_NOT_EQUAL:
- dst_ar = EQUAL_FLAG;
- break;
default:
SLJIT_ASSERT_STOP();
@@ -2180,11 +2156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
if (op >= SLJIT_ADD) {
if (TMP_REG2_mapped != dst_ar)
FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO));
- return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
+ return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
}
if (dst & SLJIT_MEM)
- return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
+ return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
if (sugg_dst_ar != dst_ar)
return ADD(sugg_dst_ar, dst_ar, ZERO);
@@ -2194,7 +2170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) {
CHECK_ERROR();
- check_sljit_emit_op0(compiler, op);
+ CHECK(check_sljit_emit_op0(compiler, op));
op = GET_OPCODE(op);
switch (op) {
@@ -2204,10 +2180,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
case SLJIT_BREAKPOINT:
return PI(BPT);
- case SLJIT_UMUL:
- case SLJIT_SMUL:
- case SLJIT_UDIV:
- case SLJIT_SDIV:
+ case SLJIT_LUMUL:
+ case SLJIT_LSMUL:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
SLJIT_ASSERT_STOP();
}
@@ -2217,7 +2193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw)
{
CHECK_ERROR();
- check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw);
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
@@ -2273,7 +2249,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
case SLJIT_CLZ:
- return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
}
return SLJIT_SUCCESS;
@@ -2282,7 +2258,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w)
{
CHECK_ERROR();
- check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
@@ -2325,7 +2301,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp
flush_buffer(compiler);
CHECK_ERROR_PTR();
- check_sljit_emit_label(compiler);
+ CHECK_PTR(check_sljit_emit_label(compiler));
if (compiler->last_label && compiler->last_label->size == compiler->size)
return compiler->last_label;
@@ -2344,7 +2320,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
flush_buffer(compiler);
CHECK_ERROR();
- check_sljit_emit_ijump(compiler, type, src, srcw);
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src)) {
@@ -2404,8 +2380,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
return SLJIT_SUCCESS;
- } else if (src & SLJIT_MEM)
+ } else if (src & SLJIT_MEM) {
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
+ flush_buffer(compiler);
+ }
FAIL_IF(JR_SOLO(reg_map[src_r]));
@@ -2432,7 +2410,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
flush_buffer(compiler);
CHECK_ERROR_PTR();
- check_sljit_emit_jump(compiler, type);
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
@@ -2440,48 +2418,42 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
type &= 0xff;
switch (type) {
- case SLJIT_C_EQUAL:
- case SLJIT_C_FLOAT_NOT_EQUAL:
+ case SLJIT_EQUAL:
BR_NZ(EQUAL_FLAG);
break;
- case SLJIT_C_NOT_EQUAL:
- case SLJIT_C_FLOAT_EQUAL:
+ case SLJIT_NOT_EQUAL:
BR_Z(EQUAL_FLAG);
break;
- case SLJIT_C_LESS:
- case SLJIT_C_FLOAT_LESS:
+ case SLJIT_LESS:
BR_Z(ULESS_FLAG);
break;
- case SLJIT_C_GREATER_EQUAL:
- case SLJIT_C_FLOAT_GREATER_EQUAL:
+ case SLJIT_GREATER_EQUAL:
BR_NZ(ULESS_FLAG);
break;
- case SLJIT_C_GREATER:
- case SLJIT_C_FLOAT_GREATER:
+ case SLJIT_GREATER:
BR_Z(UGREATER_FLAG);
break;
- case SLJIT_C_LESS_EQUAL:
- case SLJIT_C_FLOAT_LESS_EQUAL:
+ case SLJIT_LESS_EQUAL:
BR_NZ(UGREATER_FLAG);
break;
- case SLJIT_C_SIG_LESS:
+ case SLJIT_SIG_LESS:
BR_Z(LESS_FLAG);
break;
- case SLJIT_C_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
BR_NZ(LESS_FLAG);
break;
- case SLJIT_C_SIG_GREATER:
+ case SLJIT_SIG_GREATER:
BR_Z(GREATER_FLAG);
break;
- case SLJIT_C_SIG_LESS_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
BR_NZ(GREATER_FLAG);
break;
- case SLJIT_C_OVERFLOW:
- case SLJIT_C_MUL_OVERFLOW:
+ case SLJIT_OVERFLOW:
+ case SLJIT_MUL_OVERFLOW:
BR_Z(OVERFLOW_FLAG);
break;
- case SLJIT_C_NOT_OVERFLOW:
- case SLJIT_C_MUL_NOT_OVERFLOW:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_MUL_NOT_OVERFLOW:
BR_NZ(OVERFLOW_FLAG);
break;
default:
@@ -2536,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp
flush_buffer(compiler);
CHECK_ERROR_PTR();
- check_sljit_emit_const(compiler, dst, dstw, init_value);
+ CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -2572,3 +2544,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43);
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(reg));
+ return reg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_si size)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
index 21b276fb8d..e148c34cd1 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
@@ -744,8 +744,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
break;
case SLJIT_LUMUL:
case SLJIT_LSMUL:
- case SLJIT_LUDIV:
- case SLJIT_LSDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_SDIVMOD:
+ case SLJIT_UDIVI:
+ case SLJIT_SDIVI:
compiler->flags_saved = 0;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#ifdef _WIN64
@@ -763,9 +765,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
#endif
compiler->mode32 = op & SLJIT_INT_OP;
#endif
+ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments);
op = GET_OPCODE(op);
- if (op == SLJIT_LUDIV) {
+ if ((op | 0x2) == SLJIT_UDIVI) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);
@@ -776,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
*inst = XOR_r_rm;
}
- if (op == SLJIT_LSDIV) {
+ if ((op | 0x2) == SLJIT_SDIVI) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
#endif
@@ -807,10 +810,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = GROUP_F7;
- *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
+ *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
#else
#ifdef _WIN64
- size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2;
+ size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2;
#else
size = (!compiler->mode32) ? 3 : 2;
#endif
@@ -819,11 +822,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
INC_SIZE(size);
#ifdef _WIN64
if (!compiler->mode32)
- *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0);
- else if (op >= SLJIT_LUDIV)
+ *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0);
+ else if (op >= SLJIT_UDIVMOD)
*inst++ = REX_B;
*inst++ = GROUP_F7;
- *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
+ *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
#else
if (!compiler->mode32)
*inst++ = REX_W;
@@ -838,15 +841,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
case SLJIT_LSMUL:
*inst |= IMUL;
break;
- case SLJIT_LUDIV:
+ case SLJIT_UDIVMOD:
+ case SLJIT_UDIVI:
*inst |= DIV;
break;
- case SLJIT_LSDIV:
+ case SLJIT_SDIVMOD:
+ case SLJIT_SDIVI:
*inst |= IDIV;
break;
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
- EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+ if (op <= SLJIT_SDIVMOD)
+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+#else
+ if (op >= SLJIT_UDIVI)
+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
#endif
break;
}
@@ -1907,60 +1916,62 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler,
return SLJIT_SUCCESS;
}
- if (FAST_IS_REG(src1)) {
+ if (!(src1 & SLJIT_IMM)) {
if (src2 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src2w) || compiler->mode32) {
- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
FAIL_IF(!inst);
*inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
#else
- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
FAIL_IF(!inst);
*inst = GROUP_F7;
#endif
+ return SLJIT_SUCCESS;
}
- else {
+ else if (FAST_IS_REG(src1)) {
inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
+ return SLJIT_SUCCESS;
}
- return SLJIT_SUCCESS;
}
- if (FAST_IS_REG(src2)) {
+ if (!(src2 & SLJIT_IMM)) {
if (src1 & SLJIT_IMM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (IS_HALFWORD(src1w) || compiler->mode32) {
- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);
FAIL_IF(!inst);
*inst = GROUP_F7;
}
else {
FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
}
#else
- inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0);
+ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);
FAIL_IF(!inst);
*inst = GROUP_F7;
#endif
+ return SLJIT_SUCCESS;
}
- else {
+ else if (FAST_IS_REG(src2)) {
inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
FAIL_IF(!inst);
*inst = TEST_rm_r;
+ return SLJIT_SUCCESS;
}
- return SLJIT_SUCCESS;
}
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
diff --git a/src/3rdparty/sha3/KeccakF-1600-opt32.c b/src/3rdparty/sha3/KeccakF-1600-opt32.c
index 4e32dca9cb..7d8ae6e19c 100644
--- a/src/3rdparty/sha3/KeccakF-1600-opt32.c
+++ b/src/3rdparty/sha3/KeccakF-1600-opt32.c
@@ -191,10 +191,10 @@ static UINT64 fromInterleaving(UINT64 x)
return x;
}
-static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd)
+static void setInterleavedWordsInto8bytes(UINT8* dest, const UINT32* evenAndOdd)
{
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
- ((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd);
+ ((UINT64*)dest)[0] = fromInterleaving(*(const UINT64*)evenAndOdd);
#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
// This can be optimized
UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32);
@@ -214,7 +214,7 @@ static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd)
{ \
unsigned i; \
for(i=0; i<(laneCount); i++) \
- setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \
+ setInterleavedWordsInto8bytes(data+i*8, (const UINT32*)state+i*2); \
}
#endif // With or without interleaving tables
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index a1e7dac4d4..0c01e67637 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -42,6 +42,8 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.text.ClipboardManager;
import android.os.Build;
import android.util.Log;
@@ -173,14 +175,14 @@ public class QtNative
m_lostActions.clear();
}
- private static boolean runAction(Runnable action)
+ private static void runAction(Runnable action)
{
synchronized (m_mainActivityMutex) {
- if (m_activity == null)
+ final Looper mainLooper = Looper.getMainLooper();
+ final Handler handler = new Handler(mainLooper);
+ final boolean actionIsQueued = m_activity != null && mainLooper != null && handler.post(action);
+ if (!actionIsQueued)
m_lostActions.add(action);
- else
- m_activity.runOnUiThread(action);
- return m_activity != null;
}
}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 23e08f537a..e5ed690f07 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -243,11 +243,11 @@ public class QtActivity extends Activity
@SuppressWarnings("rawtypes")
Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class
Object qtLoader = loaderClass.newInstance(); // create an instance
- Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication",
+ Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication",
Activity.class,
ClassLoader.class,
Bundle.class);
- if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
+ if (!(Boolean)prepareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
throw new Exception("");
QtApplication.setQtActivityDelegate(qtLoader);
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
index 735c841ad8..8e2333d2ba 100644
--- a/src/angle/src/common/common.pri
+++ b/src/angle/src/common/common.pri
@@ -7,6 +7,8 @@ INCLUDEPATH += \
LIBS_PRIVATE = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI
+TR_EXCLUDE += $$ANGLE_DIR/src/*
+
lib_replace.match = $$[QT_INSTALL_LIBS/get]
lib_replace.replace = \$\$\$\$[QT_INSTALL_LIBS]
lib_replace.CONFIG = path
@@ -46,4 +48,10 @@ winrt|if(msvc:!win32-msvc2005:!win32-msvc2008:!win32-msvc2010) {
}
}
+# static builds should still link ANGLE dynamically when dynamic GL is enabled
+static:contains(QT_CONFIG, dynamicgl) {
+ CONFIG -= static
+ CONFIG += shared
+}
+
static: DEFINES *= LIBGLESV2_EXPORT_H_ ANGLE_EXPORT=
diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro
index 8c5b1555dc..759a3399b4 100644
--- a/src/angle/src/compiler/preprocessor/preprocessor.pro
+++ b/src/angle/src/compiler/preprocessor/preprocessor.pro
@@ -40,15 +40,15 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/preprocessor/Preprocessor.cpp \
$$ANGLE_DIR/src/compiler/preprocessor/Token.cpp
-# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
-flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
+# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin
+flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
flex.output = ${QMAKE_FILE_BASE}.cpp
flex.input = FLEX_SOURCES
flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
-bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
+bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}.cpp
bison.input = BISON_SOURCES
bison.dependency_type = TYPE_C
diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro
index e9d16ca5af..9572a51ad4 100644
--- a/src/angle/src/compiler/translator.pro
+++ b/src/angle/src/compiler/translator.pro
@@ -162,15 +162,15 @@ SOURCES += \
$$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp
-# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin
-flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME}
+# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin
+flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME}
flex.output = ${QMAKE_FILE_BASE}_lex.cpp
flex.input = FLEX_SOURCES
flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
-bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
+bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
--output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}_tab.h
bison.input = BISON_SOURCES
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri
index 5c3b0b78c2..99e313daf7 100644
--- a/src/corelib/arch/arch.pri
+++ b/src/corelib/arch/arch.pri
@@ -11,6 +11,8 @@ HEADERS += \
arch/qatomic_gcc.h \
arch/qatomic_cxx11.h
+atomic64-libatomic: LIBS += -latomic
+
unix {
# fallback implementation when no other appropriate qatomic_*.h exists
HEADERS += arch/qatomic_unix.h
diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h
index 0e06ca951a..4136e09ce2 100644
--- a/src/corelib/arch/qatomic_cxx11.h
+++ b/src/corelib/arch/qatomic_cxx11.h
@@ -78,11 +78,13 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; };
#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE
#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT64_IS_SUPPORTED
-#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
-#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#ifndef QT_NO_STD_ATOMIC64
+# define Q_ATOMIC_INT64_IS_SUPPORTED
+# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE
+# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE
+#endif
template <typename X> struct QAtomicOps
{
diff --git a/src/corelib/codecs/qbig5codec.cpp b/src/corelib/codecs/qbig5codec.cpp
index 6fd87bdfc9..6e6e3143bb 100644
--- a/src/corelib/codecs/qbig5codec.cpp
+++ b/src/corelib/codecs/qbig5codec.cpp
@@ -1794,7 +1794,7 @@ QByteArray QBig5Codec::convertFromUnicode(const QChar *uc, int len, ConverterSta
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
@@ -1916,7 +1916,7 @@ QByteArray QBig5hkscsCodec::convertFromUnicode(const QChar *uc, int len, Convert
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
diff --git a/src/corelib/codecs/qeucjpcodec.cpp b/src/corelib/codecs/qeucjpcodec.cpp
index af218c1ab0..7b9665f1a0 100644
--- a/src/corelib/codecs/qeucjpcodec.cpp
+++ b/src/corelib/codecs/qeucjpcodec.cpp
@@ -92,7 +92,7 @@ QEucJpCodec::QEucJpCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::D
*/
QEucJpCodec::~QEucJpCodec()
{
- delete (QJpUnicodeConv*)conv;
+ delete (const QJpUnicodeConv*)conv;
conv = 0;
}
@@ -139,7 +139,7 @@ QByteArray QEucJpCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
diff --git a/src/corelib/codecs/qeuckrcodec.cpp b/src/corelib/codecs/qeuckrcodec.cpp
index 52776efa4d..9ef9e13ebb 100644
--- a/src/corelib/codecs/qeuckrcodec.cpp
+++ b/src/corelib/codecs/qeuckrcodec.cpp
@@ -108,7 +108,7 @@ QByteArray QEucKrCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
@@ -3421,7 +3421,7 @@ QByteArray QCP949Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt
}
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
diff --git a/src/corelib/codecs/qgb18030codec.cpp b/src/corelib/codecs/qgb18030codec.cpp
index feb485807f..f498072948 100644
--- a/src/corelib/codecs/qgb18030codec.cpp
+++ b/src/corelib/codecs/qgb18030codec.cpp
@@ -138,7 +138,7 @@ QByteArray QGb18030Codec::convertFromUnicode(const QChar *uc, int len, Converter
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
@@ -415,7 +415,7 @@ QByteArray QGbkCodec::convertFromUnicode(const QChar *uc, int len, ConverterStat
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
@@ -566,7 +566,7 @@ QByteArray QGb2312Codec::convertFromUnicode(const QChar *uc, int len, ConverterS
++invalid;
}
}
- rstr.resize(cursor - (uchar*)rstr.constData());
+ rstr.resize(cursor - (const uchar*)rstr.constData());
if (state) {
state->invalidChars += invalid;
diff --git a/src/corelib/codecs/qjiscodec.cpp b/src/corelib/codecs/qjiscodec.cpp
index 25d8cf0cff..ac1b47a944 100644
--- a/src/corelib/codecs/qjiscodec.cpp
+++ b/src/corelib/codecs/qjiscodec.cpp
@@ -97,7 +97,7 @@ QJisCodec::QJisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Defau
*/
QJisCodec::~QJisCodec()
{
- delete (QJpUnicodeConv*)conv;
+ delete (const QJpUnicodeConv*)conv;
conv = 0;
}
diff --git a/src/corelib/codecs/qsjiscodec.cpp b/src/corelib/codecs/qsjiscodec.cpp
index 58b91b9d9d..5164d9e4ce 100644
--- a/src/corelib/codecs/qsjiscodec.cpp
+++ b/src/corelib/codecs/qsjiscodec.cpp
@@ -73,7 +73,7 @@ QSjisCodec::QSjisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Def
*/
QSjisCodec::~QSjisCodec()
{
- delete (QJpUnicodeConv*)conv;
+ delete (const QJpUnicodeConv*)conv;
conv = 0;
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
index 8ff44c9dca..8846437b7c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
@@ -486,6 +486,33 @@ QObject::connect(socket, &QTcpSocket::connected, this, [=] () {
}, Qt::AutoConnection);
//! [51]
+//! [52]
+class MyClass : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MyClass(QWidget *parent = 0);
+ ~MyClass();
+
+ bool event(QEvent* ev)
+ {
+ if (ev->type() == QEvent::PolishRequest) {
+ // overwrite handling of PolishRequest if any
+ doThings();
+ return true;
+ } else if (ev->type() == QEvent::Show) {
+ // complement handling of Show if any
+ doThings2();
+ QWidget::event(ev);
+ return true;
+ }
+ // Make sure the rest of events are handled
+ return QWidget::event(ev);
+ }
+};
+//! [52]
+
//! [meta data]
//: This is a comment for the translator.
//= qtn_foo_bar
diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc
index f8d0d3eb05..0ae3817ac7 100644
--- a/src/corelib/doc/src/containers.qdoc
+++ b/src/corelib/doc/src/containers.qdoc
@@ -169,8 +169,8 @@
convenience, the containers are forward declared in \c
<QtContainerFwd>.
- \keyword assignable data type
- \keyword assignable data types
+ \target assignable data type
+ \target assignable data types
The values stored in the various containers can be of any
\e{assignable data type}. To qualify, a type must provide a
@@ -220,7 +220,7 @@
\codeline
\snippet streaming/main.cpp 2
- \keyword default-constructed value
+ \target default-constructed value
The documentation of certain container class functions refer to
\e{default-constructed values}; for example, QVector
@@ -546,7 +546,7 @@
The above example only shows a problem with QVector, but
the problem exists for all the implicitly shared Qt containers.
- \keyword foreach
+ \target foreach
\section1 The foreach Keyword
If you just want to iterate over all the items in a container
@@ -655,11 +655,11 @@
To describe algorithmic complexity, we use the following
terminology, based on the "big Oh" notation:
- \keyword constant time
- \keyword logarithmic time
- \keyword linear time
- \keyword linear-logarithmic time
- \keyword quadratic time
+ \target constant time
+ \target logarithmic time
+ \target linear time
+ \target linear-logarithmic time
+ \target quadratic time
\list
\li \b{Constant time:} O(1). A function is said to run in constant
diff --git a/src/corelib/doc/src/implicit-sharing.qdoc b/src/corelib/doc/src/implicit-sharing.qdoc
index 57ebf55c17..d5a8e327ac 100644
--- a/src/corelib/doc/src/implicit-sharing.qdoc
+++ b/src/corelib/doc/src/implicit-sharing.qdoc
@@ -71,8 +71,8 @@
data. The shared data is deleted when the reference count becomes
zero.
- \keyword deep copy
- \keyword shallow copy
+ \target deep copy
+ \target shallow copy
When dealing with shared objects, there are two ways of copying an
object. We usually speak about \e deep and \e shallow copies. A deep
@@ -142,6 +142,6 @@
(QMap, QVector, etc.) while you use
\l{STL-style iterators}{STL-style iterator}. See \l{Implicit sharing iterator problem}.
- \keyword implicitly shared classes
+ \target implicitly shared classes
\annotatedlist shared
*/
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 43f3a86544..eb8600f796 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -58,3 +58,28 @@ journald {
syslog {
DEFINES += QT_USE_SYSLOG
}
+
+linux|freebsd {
+ VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
+ ltcg|clang {
+ versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH)
+
+ # Disable LTO, as the global inline assembly may not get processed
+ versiontagging_compiler.commands += -fno-lto
+
+ # Disable the integrated assembler for Clang, since it can't parse with
+ # the alternate macro syntax in use in qversiontagging.cpp
+ clang: versiontagging_compiler.commands += -no-integrated-as
+
+ versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
+ versiontagging_compiler.dependency_type = TYPE_C
+ versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ versiontagging_compiler.input = VERSIONTAGGING_SOURCES
+ versiontagging_compiler.variable_out = OBJECTS
+ versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN}
+ silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands
+ QMAKE_EXTRA_COMPILERS += versiontagging_compiler
+ } else {
+ SOURCES += $$VERSIONTAGGING_SOURCES
+ }
+}
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 775f62d2ae..9019676d24 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -65,12 +65,22 @@
# endif
#endif
-#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
-# include <envLib.h>
+#ifdef Q_OS_WINRT
+#include <wrl.h>
+#include <windows.networking.h>
+#include <windows.networking.sockets.h>
+#include <windows.networking.connectivity.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Networking;
+using namespace ABI::Windows::Networking::Connectivity;
+using namespace ABI::Windows::Networking::Sockets;
#endif
-#if defined(Q_OS_MACX)
-#include <CoreServices/CoreServices.h>
+#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
+# include <envLib.h>
#endif
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
@@ -90,6 +100,10 @@
#include <private/qcore_unix_p.h>
#endif
+#ifdef Q_OS_BSD4
+#include <sys/sysctl.h>
+#endif
+
#include "archdetect.cpp"
QT_BEGIN_NAMESPACE
@@ -1852,25 +1866,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qnamespace.h"
QT_END_INCLUDE_NAMESPACE
-#if defined(Q_OS_OSX)
-
-Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
-{
- return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0);
-}
-
-Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1)
-{
- Q_UNUSED(encoding);
- Q_UNUSED(len);
- CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding());
-}
-
-Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) {
- return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding()));
-}
-#endif // defined(Q_OS_OSX)
-
QSysInfo::MacVersion QSysInfo::macVersion()
{
const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm
@@ -1892,91 +1887,99 @@ QT_END_INCLUDE_NAMESPACE
#ifndef Q_OS_WINRT
-# ifndef Q_OS_WINCE
-
-// Determine Windows versions >= 8 by querying the version of kernel32.dll.
-static inline bool determineWinOsVersionPost8(OSVERSIONINFO *result)
+# ifndef QT_BOOTSTRAPPED
+class QWindowsSockInit
{
- typedef WORD (WINAPI* PtrGetFileVersionInfoSizeW)(LPCWSTR, LPDWORD);
- typedef BOOL (WINAPI* PtrVerQueryValueW)(LPCVOID, LPCWSTR, LPVOID, PUINT);
- typedef BOOL (WINAPI* PtrGetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID);
+public:
+ QWindowsSockInit();
+ ~QWindowsSockInit();
+ int version;
+};
- QSystemLibrary versionLib(QStringLiteral("version"));
- if (!versionLib.load())
- return false;
- PtrGetFileVersionInfoSizeW getFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)versionLib.resolve("GetFileVersionInfoSizeW");
- PtrVerQueryValueW verQueryValueW = (PtrVerQueryValueW)versionLib.resolve("VerQueryValueW");
- PtrGetFileVersionInfoW getFileVersionInfoW = (PtrGetFileVersionInfoW)versionLib.resolve("GetFileVersionInfoW");
- if (!getFileVersionInfoSizeW || !verQueryValueW || !getFileVersionInfoW)
- return false;
+QWindowsSockInit::QWindowsSockInit()
+: version(0)
+{
+ //### should we try for 2.2 on all platforms ??
+ WSAData wsadata;
- const wchar_t kernel32Dll[] = L"kernel32.dll";
- DWORD handle;
- const DWORD size = getFileVersionInfoSizeW(kernel32Dll, &handle);
- if (!size)
- return false;
- QScopedArrayPointer<BYTE> versionInfo(new BYTE[size]);
- if (!getFileVersionInfoW(kernel32Dll, handle, size, versionInfo.data()))
- return false;
- UINT uLen;
- VS_FIXEDFILEINFO *fileInfo = Q_NULLPTR;
- if (!verQueryValueW(versionInfo.data(), L"\\", (LPVOID *)&fileInfo, &uLen))
- return false;
- const DWORD fileVersionMS = fileInfo->dwFileVersionMS;
- const DWORD fileVersionLS = fileInfo->dwFileVersionLS;
- result->dwMajorVersion = HIWORD(fileVersionMS);
- result->dwMinorVersion = LOWORD(fileVersionMS);
- result->dwBuildNumber = HIWORD(fileVersionLS);
- return true;
+ // IPv6 requires Winsock v2.0 or better.
+ if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
+ qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
+ } else {
+ version = 0x20;
+ }
}
-// Fallback for determining Windows versions >= 8 by looping using the
-// version check macros. Note that it will return build number=0 to avoid
-// inefficient looping.
-static inline void determineWinOsVersionFallbackPost8(OSVERSIONINFO *result)
+QWindowsSockInit::~QWindowsSockInit()
{
- result->dwBuildNumber = 0;
- DWORDLONG conditionMask = 0;
- VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
- VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL);
- OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result->dwMajorVersion, 0,
- result->dwBuildNumber, result->dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 };
- for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMajorVersion)
- result->dwMajorVersion = checkVersion.dwMajorVersion;
- conditionMask = 0;
- checkVersion.dwMajorVersion = result->dwMajorVersion;
- checkVersion.dwMinorVersion = 0;
- VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_EQUAL);
- VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
- VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL);
- for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion)
- result->dwMinorVersion = checkVersion.dwMinorVersion;
+ WSACleanup();
}
+Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
+# endif // QT_BOOTSTRAPPED
-# endif // !Q_OS_WINCE
+#endif // !Q_OS_WINRT
+
+#ifdef Q_OS_WINRT
+static inline HMODULE moduleHandleForFunction(LPCVOID address)
+{
+ // This is a widely used, decades-old technique for retrieving the handle
+ // of a module and is effectively equivalent to GetModuleHandleEx
+ // (which is unavailable on WinRT)
+ MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 };
+ if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0)
+ return 0;
+ return reinterpret_cast<HMODULE>(mbi.AllocationBase);
+}
+#endif
static inline OSVERSIONINFO winOsVersion()
{
OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}};
+
+#ifndef Q_OS_WINCE
+#define GetProcAddressA GetProcAddress
+#endif
+
+ // GetModuleHandle is not supported in WinRT and linking to it at load time
+ // will not pass the Windows App Certification Kit... but it exists and is functional,
+ // so use some unusual but widely used techniques to get a pointer to it
+#ifdef Q_OS_WINRT
+ // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL
+ HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery));
+ if (Q_UNLIKELY(!kernelModule))
+ return result;
+
+ // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs)
+ typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR);
+ GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>(
+ GetProcAddressA(kernelModule, "GetModuleHandleW"));
+ if (Q_UNLIKELY(!pGetModuleHandle))
+ return result;
+#else
+#define pGetModuleHandle GetModuleHandleW
+#endif
+
+ HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
+ if (Q_UNLIKELY(!ntdll))
+ return result;
+
+ // NTSTATUS is not defined on WinRT
+ typedef LONG NTSTATUS;
+ typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
+
+ // RtlGetVersion is documented public API but we must load it dynamically
+ // because linking to it at load time will not pass the Windows App Certification Kit
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
+ RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
+ GetProcAddressA(ntdll, "RtlGetVersion"));
+ if (Q_UNLIKELY(!pRtlGetVersion))
+ return result;
+
// GetVersionEx() has been deprecated in Windows 8.1 and will return
- // only Windows 8 from that version on.
-# if defined(_MSC_VER) && _MSC_VER >= 1800
-# pragma warning( push )
-# pragma warning( disable : 4996 )
-# endif
- GetVersionEx(&result);
-# if defined(_MSC_VER) && _MSC_VER >= 1800
-# pragma warning( pop )
-# endif
-# ifndef Q_OS_WINCE
- if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) {
- if (!determineWinOsVersionPost8(&result))
- determineWinOsVersionFallbackPost8(&result);
- }
-# endif // !Q_OS_WINCE
+ // only Windows 8 from that version on, so use the kernel API function.
+ pRtlGetVersion(&result); // always returns STATUS_SUCCESS
return result;
}
-#endif // !Q_OS_WINRT
QSysInfo::WinVersion QSysInfo::windowsVersion()
{
@@ -1996,11 +1999,10 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
static QSysInfo::WinVersion winver;
if (winver)
return winver;
-#ifdef Q_OS_WINRT
- winver = QSysInfo::WV_WINDOWS8_1;
-#else
winver = QSysInfo::WV_NT;
const OSVERSIONINFO osver = winOsVersion();
+ if (osver.dwMajorVersion == 0)
+ return QSysInfo::WV_None;
#ifdef Q_OS_WINCE
DWORD qt_cever = 0;
qt_cever = osver.dwMajorVersion * 100;
@@ -2080,7 +2082,6 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
}
}
#endif
-#endif // !Q_OS_WINRT
return winver;
}
@@ -2551,10 +2552,7 @@ QString QSysInfo::kernelType()
*/
QString QSysInfo::kernelVersion()
{
-#ifdef Q_OS_WINRT
- // TBD
- return QString();
-#elif defined(Q_OS_WIN)
+#ifdef Q_OS_WIN
const OSVERSIONINFO osver = winOsVersion();
return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
+ QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
@@ -2780,6 +2778,82 @@ QString QSysInfo::prettyProductName()
return unknownText();
}
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \since 5.6
+
+ Returns this machine's host name, if one is configured. Note that hostnames
+ are not guaranteed to be globally unique, especially if they were
+ configured automatically.
+
+ This function does not guarantee the returned host name is a Fully
+ Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the
+ returned name to an FQDN.
+
+ This function returns the same as QHostInfo::localHostName().
+
+ \sa QHostInfo::localDomainName
+ */
+QString QSysInfo::machineHostName()
+{
+#if defined(Q_OS_LINUX)
+ // gethostname(3) on Linux just calls uname(2), so do it ourselves
+ // and avoid a memcpy
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLocal8Bit(u.nodename);
+#elif defined(Q_OS_WINRT)
+ ComPtr<INetworkInformationStatics> statics;
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
+
+ ComPtr<IVectorView<HostName *>> hostNames;
+ statics->GetHostNames(&hostNames);
+ if (!hostNames)
+ return QString();
+
+ unsigned int size;
+ hostNames->get_Size(&size);
+ if (size == 0)
+ return QString();
+
+ for (unsigned int i = 0; i < size; ++i) {
+ ComPtr<IHostName> hostName;
+ hostNames->GetAt(i, &hostName);
+ HostNameType type;
+ hostName->get_Type(&type);
+ if (type != HostNameType_DomainName)
+ continue;
+
+ HString name;
+ hostName->get_CanonicalName(name.GetAddressOf());
+ UINT32 length;
+ PCWSTR rawString = name.GetRawBuffer(&length);
+ return QString::fromWCharArray(rawString, length);
+ }
+ ComPtr<IHostName> firstHost;
+ hostNames->GetAt(0, &firstHost);
+
+ HString name;
+ firstHost->get_CanonicalName(name.GetAddressOf());
+ UINT32 length;
+ PCWSTR rawString = name.GetRawBuffer(&length);
+ return QString::fromWCharArray(rawString, length);
+#else
+# ifdef Q_OS_WIN
+ // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
+ winsockInit();
+# endif
+
+ char hostName[512];
+ if (gethostname(hostName, sizeof(hostName)) == -1)
+ return QString();
+ hostName[sizeof(hostName) - 1] = '\0';
+ return QString::fromLocal8Bit(hostName);
+#endif
+ return QString();
+}
+#endif // QT_BOOTSTRAPPED
+
/*!
\macro void Q_ASSERT(bool test)
\relates <QtGlobal>
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index c847e7347f..41580598c7 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -448,6 +448,9 @@ template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qin
template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; };
template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
+#if defined(Q_CC_GNU) && defined(__SIZEOF_INT128__)
+template <> struct QIntegerForSize<16> { __extension__ typedef unsigned __int128 Unsigned; __extension__ typedef __int128 Signed; };
+#endif
template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Signed qregisterint;
typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint;
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index b7c6500831..3edee03a2a 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -787,7 +787,7 @@
\value UI_FadeTooltip Show tooltip fading effects.
\value UI_AnimateToolBox Reserved
- \sa QApplication::setEffectEnabled(), QApplication::setDesktopSettingsAware()
+ \sa QApplication::setEffectEnabled(), QGuiApplication::setDesktopSettingsAware()
*/
/*! \enum Qt::AspectRatioMode
@@ -2458,7 +2458,7 @@
When LayoutDirectionAuto is used in conjunction with text layouting, it will imply that the text
directionality is determined from the content of the string to be layouted.
- \sa QApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft()
+ \sa QGuiApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft()
*/
/*!
@@ -2673,6 +2673,7 @@
\value ItemIsTristate \e{This enum value is deprecated.} Use Qt::ItemIsAutoTristate
instead.
\value ItemNeverHasChildren The item never has child items.
+ This is used for optimization purposes only.
\value ItemIsUserTristate The user can cycle through three separate states.
This value has been added in Qt 5.5.
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 5fa0a881a3..e5f9d8e13e 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -47,6 +48,18 @@
#include "QtCore/qglobal.h"
+#include <limits>
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+# include <intrin.h>
+#elif defined(Q_CC_INTEL)
+# include <immintrin.h> // for _addcarry_u<nn>
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
QT_BEGIN_NAMESPACE
#if !defined(Q_CC_MIPS)
@@ -188,6 +201,110 @@ static inline bool qt_is_finite(float d)
}
}
+//
+// Overflow math
+//
+namespace {
+template <typename T> inline typename QtPrivate::QEnableIf<QtPrivate::is_unsigned<T>::value, bool>::Type
+add_overflow(T v1, T v2, T *r)
+{
+ // unsigned additions are well-defined
+ *r = v1 + v2;
+ return v1 > T(v1 + v2);
+}
+
+template <typename T> inline typename QtPrivate::QEnableIf<QtPrivate::is_unsigned<T>::value, bool>::Type
+mul_overflow(T v1, T v2, T *r)
+{
+ // use the next biggest type
+ // Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
+ // A fallback is present below.
+ typedef typename QIntegerForSize<sizeof(T) * 2>::Unsigned Larger;
+ Larger lr = Larger(v1) * Larger(v2);
+ *r = T(lr);
+ return lr > std::numeric_limits<T>::max();
+}
+
+#if defined(__SIZEOF_INT128__)
+# define HAVE_MUL64_OVERFLOW
+#endif
+
+// GCC 5 and Clang have builtins to detect overflows
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uadd_overflow)
+template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
+{ return __builtin_uadd_overflow(v1, v2, r); }
+#endif
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddl_overflow)
+template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
+{ return __builtin_uaddl_overflow(v1, v2, r); }
+#endif
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddll_overflow)
+template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
+{ return __builtin_uaddll_overflow(v1, v2, r); }
+#endif
+
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umul_overflow)
+template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r)
+{ return __builtin_umul_overflow(v1, v2, r); }
+#endif
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umull_overflow)
+template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
+{ return __builtin_umull_overflow(v1, v2, r); }
+#endif
+#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umulll_overflow)
+template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
+{ return __builtin_umulll_overflow(v1, v2, r); }
+# define HAVE_MUL64_OVERFLOW
+#endif
+
+#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86)
+template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
+{ return _addcarry_u32(0, v1, v2, r); }
+# ifdef Q_CC_MSVC // longs are 32-bit
+template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
+{ return _addcarry_u32(0, v1, v2, reinterpret_cast<unsigned *>(r)); }
+# endif
+#endif
+#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64)
+template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
+{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
+# ifndef Q_CC_MSVC // longs are 64-bit
+template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
+{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
+# endif
+#endif
+
+#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64))
+#pragma intrinsic(_umul128)
+template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
+{
+ // use 128-bit multiplication with the _umul128 intrinsic
+ // https://msdn.microsoft.com/en-us/library/3dayytw9.aspx
+ quint64 high;
+ *r = _umul128(v1, v2, &high);
+ return high;
+}
+# define HAVE_MUL64_OVERFLOW
+#endif
+
+#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__)
+// no 128-bit multiplication, we need to figure out with a slow division
+template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
+{
+ if (v2 && v1 > std::numeric_limits<quint64>::max() / v2)
+ return true;
+ *r = v1 * v2;
+ return false;
+}
+template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
+{
+ return mul_overflow<quint64>(v1, v2, reinterpret_cast<quint64 *>(r));
+}
+#else
+# undef HAVE_MUL64_OVERFLOW
+#endif
+}
+
QT_END_NAMESPACE
#endif // QNUMERIC_P_H
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index d40e6659c7..27a285fd36 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -186,6 +186,8 @@ public:
static QString productType();
static QString productVersion();
static QString prettyProductName();
+
+ static QString machineHostName();
};
QT_END_NAMESPACE
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 8711678f34..f043f6c5c9 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -115,7 +115,7 @@
# else
# error "Qt has not been ported to this Apple platform - see http://www.qt.io/developers"
# endif
-#elif defined(ANDROID)
+#elif defined(__ANDROID__) || defined(ANDROID)
# define Q_OS_ANDROID
# define Q_OS_LINUX
#elif defined(__CYGWIN__)
diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp
new file mode 100644
index 0000000000..66d3f8d00f
--- /dev/null
+++ b/src/corelib/global/qversiontagging.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** 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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglobal.h"
+
+#if defined(Q_CC_GNU) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && defined(Q_PROCESSOR_X86) && !defined(QT_STATIC)
+# define SYM QT_MANGLE_NAMESPACE(qt_version_tag)
+# define SSYM QT_STRINGIFY(SYM)
+
+asm(
+// ASM macro that makes one ELF versioned symbol
+".macro make_versioned_symbol plainsym versionedsym\n"
+".globl plainsym\n"
+".type plainsym, @object\n"
+".size plainsym, 1\n"
+".symver plainsym, versionedsym\n"
+"plainsym :\n"
+".endm\n"
+
+// ASM macro that makes one ELF versioned symbol qt_version_tag{sep}Qt_{major}.{minor}
+// that is an alias to qt_version_tag_{major}_{minor}.
+// The {sep} parameter must be @ for all old versions and @@ for the current version.
+".macro make_one_tag major minor sep\n"
+" make_versioned_symbol " SSYM "_\\major\\()_\\minor, " SSYM "\\sep\\()Qt_\\major\\().\\minor\n"
+".endm\n"
+
+".altmacro\n"
+".bss\n"
+".set qt_version_major, " QT_STRINGIFY(QT_VERSION) " >> 16\n" // set qt_version_major
+".set qt_version_minor, 0\n" // set qt_version_minor to 0 (it will grow to the current)
+".rept (" QT_STRINGIFY(QT_VERSION) " >> 8) & 0xff\n" // repeat minor version times (0 to N-1)
+" make_one_tag %qt_version_major, %qt_version_minor, @\n"
+" .set qt_version_minor, (qt_version_minor + 1)\n"
+".endr\n"
+" make_one_tag %qt_version_major, %qt_version_minor, @@\n" // call the macro for the current version
+" .space 1\n" // variable is 1 byte, value 0
+);
+
+#endif
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index d8cc004168..7be1e5883e 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -155,6 +155,8 @@ win32 {
OBJECTIVE_SOURCES += io/qfilesystemwatcher_fsevents.mm
HEADERS += io/qfilesystemwatcher_fsevents_p.h
LIBS += -framework DiskArbitration -framework IOKit
+ } else:ios {
+ LIBS += -framework MobileCoreServices
}
} else:blackberry {
SOURCES += \
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 07270eb790..2ab789e0af 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -891,7 +891,6 @@ bool QAbstractFileEngine::unmap(uchar *address)
/*!
\typedef QAbstractFileEngine::Iterator
\since 4.3
- \relates QAbstractFileEngine
Synonym for QAbstractFileEngineIterator.
*/
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 1471f10ea6..c32df4c8a6 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -526,8 +526,8 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_3 Same as Qt_5_2
\value Qt_5_4 Version 16 (Qt 5.4)
\value Qt_5_5 Same as Qt_5_4
- \value Qt_5_6 Same as Qt_5_4
- \value Qt_5_7 Same as Qt_5_4
+ \value Qt_5_6 Version 17 (Qt 5.6)
+ \value Qt_5_7 Same as Qt_5_6
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index db6fc5334e..744829c659 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -83,8 +83,8 @@ public:
Qt_5_3 = Qt_5_2,
Qt_5_4 = 16,
Qt_5_5 = Qt_5_4,
- Qt_5_6 = Qt_5_5,
- Qt_5_7 = Qt_5_5,
+ Qt_5_6 = 17,
+ Qt_5_7 = Qt_5_6,
#if QT_VERSION >= 0x050800
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 54a705b72b..13eccce9da 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -697,7 +697,7 @@ QDebug &QDebug::resetFormat()
/*!
\class QDebugStateSaver
-
+ \inmodule QtCore
\brief Convenience class for custom QDebug operators
Saves the settings used by QDebug, and restores them upon destruction,
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 8a86ec5858..51b39b1114 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -263,6 +263,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
groupId(). You can examine a file's permissions and ownership in a
single statement using the permission() function.
+ \target NTFS permissions
\note On NTFS file systems, ownership and permissions checking is
disabled by default for performance reasons. To enable it,
include the following line:
@@ -893,6 +894,9 @@ QDir QFileInfo::absoluteDir() const
/*!
Returns \c true if the user can read the file; otherwise returns \c false.
+ \note If the \l{NTFS permissions} check has not been enabled, the result
+ on Windows will merely reflect whether the file exists.
+
\sa isWritable(), isExecutable(), permission()
*/
bool QFileInfo::isReadable() const
@@ -911,6 +915,9 @@ bool QFileInfo::isReadable() const
/*!
Returns \c true if the user can write to the file; otherwise returns \c false.
+ \note If the \l{NTFS permissions} check has not been enabled, the result on
+ Windows will merely reflect whether the file is marked as Read Only.
+
\sa isReadable(), isExecutable(), permission()
*/
bool QFileInfo::isWritable() const
@@ -1137,7 +1144,8 @@ QString QFileInfo::readLink() const
returned.
This function can be time consuming under Unix (in the order of
- milliseconds).
+ milliseconds). On Windows, it will return an empty string unless
+ the \l{NTFS permissions} check has been enabled.
\sa ownerId(), group(), groupId()
*/
@@ -1217,6 +1225,9 @@ uint QFileInfo::groupId() const
On systems where files do not have permissions this function
always returns \c true.
+ \note The result might be inaccurate on Windows if the
+ \l{NTFS permissions} check has not been enabled.
+
Example:
\snippet code/src_corelib_io_qfileinfo.cpp 10
@@ -1240,6 +1251,9 @@ bool QFileInfo::permission(QFile::Permissions permissions) const
/*!
Returns the complete OR-ed together combination of
QFile::Permissions for the file.
+
+ \note The result might be inaccurate on Windows if the
+ \l{NTFS permissions} check has not been enabled.
*/
QFile::Permissions QFileInfo::permissions() const
{
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index df41457a18..e4dec2b7fb 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -264,7 +264,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
// Attributes
entryFlags |= QFileSystemMetaData::ExistsAttribute;
size_ = statBuffer.st_size;
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
if (statBuffer.st_flags & UF_HIDDEN) {
entryFlags |= QFileSystemMetaData::HiddenAttribute;
knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index 06d5db637a..6db9319836 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -76,7 +76,7 @@ public:
static QString resolveGroupName(uint groupId);
#endif
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
static QString bundleName(const QFileSystemEntry &entry);
#else
static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); }
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 2c9fed530b..7bc2293b0d 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -51,26 +51,38 @@
# include <CoreFoundation/CFBundle.h>
#endif
+#ifdef Q_OS_OSX
+#include <CoreServices/CoreServices.h>
+#endif
+
+#ifdef Q_OS_IOS
+#include <MobileCoreServices/MobileCoreServices.h>
+#endif
+
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_MACX)
-static inline bool _q_isMacHidden(const char *nativePath)
+#if defined(Q_OS_DARWIN)
+static inline bool hasResourcePropertyFlag(const QFileSystemMetaData &data,
+ const QFileSystemEntry &entry,
+ CFStringRef key)
{
- OSErr err;
-
- FSRef fsRef;
- err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath),
- kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
- if (err != noErr)
+ QCFString path = CFStringCreateWithFileSystemRepresentation(0,
+ entry.nativeFilePath().constData());
+ if (!path)
return false;
- FSCatalogInfo catInfo;
- err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL);
- if (err != noErr)
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle,
+ data.hasFlags(QFileSystemMetaData::DirectoryType));
+ if (!url)
return false;
- FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo);
- return (fileInfo->finderFlags & kIsInvisible);
+ CFBooleanRef value;
+ if (CFURLCopyResourcePropertyForKey(url, key, &value, NULL)) {
+ if (value == kCFBooleanTrue)
+ return true;
+ }
+
+ return false;
}
static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry)
@@ -97,6 +109,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
return true;
+#ifdef Q_OS_OSX
// Find if an application other than Finder claims to know how to handle the package
QCFType<CFURLRef> application;
LSGetApplicationForURL(url,
@@ -111,30 +124,11 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
if (applicationId != QLatin1String("com.apple.finder"))
return true;
}
+#endif
}
// Third step: check if the directory has the package bit set
- FSRef packageRef;
- FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &packageRef, NULL);
-
- FSCatalogInfo catalogInfo;
- FSGetCatalogInfo(&packageRef,
- kFSCatInfoFinderInfo,
- &catalogInfo,
- NULL,
- NULL,
- NULL);
-
- FolderInfo *folderInfo = reinterpret_cast<FolderInfo *>(catalogInfo.finderInfo);
- return folderInfo->finderFlags & kHasBundle;
-}
-
-#else
-static inline bool _q_isMacHidden(const char *nativePath)
-{
- Q_UNUSED(nativePath);
- // no-op
- return false;
+ return hasResourcePropertyFlag(data, entry, kCFURLIsPackageKey);
}
#endif
@@ -194,21 +188,34 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
ret.chop(1);
return QFileSystemEntry(ret);
}
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
{
- FSRef fref;
- if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) {
- // TODO get the meta data info from the QFileSystemMetaData object
- Boolean isAlias, isFolder;
- if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) {
- AliasHandle alias;
- if (FSNewAlias(0, &fref, &alias) == noErr && alias) {
- QCFString cfstr;
- if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr)
- return QFileSystemEntry(QCFString::toQString(cfstr));
- }
- }
- }
+ QCFString path = CFStringCreateWithFileSystemRepresentation(0,
+ QFile::encodeName(QDir::cleanPath(link.filePath())).data());
+ if (!path)
+ return QFileSystemEntry();
+
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle,
+ data.hasFlags(QFileSystemMetaData::DirectoryType));
+ if (!url)
+ return QFileSystemEntry();
+
+ QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL);
+ if (!bookmarkData)
+ return QFileSystemEntry();
+
+ QCFType<CFURLRef> resolvedUrl = CFURLCreateByResolvingBookmarkData(0,
+ bookmarkData,
+ (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask
+ | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL);
+ if (!resolvedUrl)
+ return QFileSystemEntry();
+
+ QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle));
+ if (!cfstr)
+ return QFileSystemEntry();
+
+ return QFileSystemEntry(QCFString::toQString(cfstr));
}
#endif
return QFileSystemEntry();
@@ -226,31 +233,14 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
#else
char *ret = 0;
-# if defined(Q_OS_MACX)
- // When using -mmacosx-version-min=10.4, we get the legacy realpath implementation,
- // which does not work properly with the realpath(X,0) form. See QTBUG-28282.
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) {
- ret = (char*)malloc(PATH_MAX + 1);
- if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
- const int savedErrno = errno; // errno is checked below, and free() might change it
- free(ret);
- errno = savedErrno;
- ret = 0;
- }
- } else {
- // on 10.5 we can use FSRef to resolve the file path.
- QString path = QDir::cleanPath(entry.filePath());
- FSRef fsref;
- if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) {
- CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref);
- CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle);
- QString ret = QCFString::toQString(canonicalPath);
- CFRelease(canonicalPath);
- CFRelease(urlref);
- return QFileSystemEntry(ret);
- }
+# if defined(Q_OS_DARWIN)
+ ret = (char*)malloc(PATH_MAX + 1);
+ if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) {
+ const int savedErrno = errno; // errno is checked below, and free() might change it
+ free(ret);
+ errno = savedErrno;
+ ret = 0;
}
-
# elif defined(Q_OS_ANDROID)
// On some Android versions, realpath() will return a path even if it does not exist
// To work around this, we check existence in advance.
@@ -406,7 +396,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
return QString();
}
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
//static
QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
{
@@ -426,7 +416,7 @@ QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry)
bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
{
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::BundleType) {
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
what |= QFileSystemMetaData::DirectoryType;
@@ -435,7 +425,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
// OS X >= 10.5: st_flags & UF_HIDDEN
what |= QFileSystemMetaData::PosixStatFlags;
}
-#endif // defined(Q_OS_MACX)
+#endif // defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::PosixStatFlags)
what |= QFileSystemMetaData::PosixStatFlags;
@@ -496,19 +486,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
| QFileSystemMetaData::ExistsAttribute;
}
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::AliasType)
{
- if (entryExists) {
- FSRef fref;
- if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) {
- Boolean isAlias, isFolder;
- if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) {
- if (isAlias)
- data.entryFlags |= QFileSystemMetaData::AliasType;
- }
- }
- }
+ if (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
+ data.entryFlags |= QFileSystemMetaData::AliasType;
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
}
#endif
@@ -537,12 +519,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
&& !data.isHidden()) {
QString fileName = entry.fileName();
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
- || (entryExists && _q_isMacHidden(nativeFilePath)))
+#if defined(Q_OS_DARWIN)
+ || (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey))
+#endif
+ )
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
}
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
if (what & QFileSystemMetaData::BundleType) {
if (entryExists && isPackage(data, entry))
data.entryFlags |= QFileSystemMetaData::BundleType;
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index da9576b5f8..828b5b329c 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -93,7 +93,7 @@ public:
LinkType = 0x00010000,
FileType = 0x00020000,
DirectoryType = 0x00040000,
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
BundleType = 0x00080000,
AliasType = 0x08000000,
#else
@@ -243,7 +243,7 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags)
-#if defined(Q_OS_MACX)
+#if defined(Q_OS_DARWIN)
inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); }
inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); }
#else
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 1d06e2a912..b51085ef42 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -157,6 +157,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
Order of evaluation:
\list
+ \li [QLibraryInfo::DataPath]/qtlogging.ini
\li QtProject/qtlogging.ini
\li \l setFilterRules()
\li \c QT_LOGGING_CONF
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index f0b72cd9be..b53e251102 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -34,6 +34,7 @@
#include "qloggingregistry_p.h"
#include <QtCore/qfile.h>
+#include <QtCore/qlibraryinfo.h>
#include <QtCore/qstandardpaths.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qdir.h>
@@ -247,6 +248,21 @@ static bool qtLoggingDebug()
return debugEnv;
}
+static QVector<QLoggingRule> loadRulesFromFile(const QString &filePath)
+{
+ QFile file(filePath);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ if (qtLoggingDebug())
+ debugMsg("Loading \"%s\" ...",
+ QDir::toNativeSeparators(file.fileName()).toUtf8().constData());
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
+ return parser.rules();
+ }
+ return QVector<QLoggingRule>();
+}
+
/*!
\internal
Initializes the rules database by loading
@@ -256,18 +272,9 @@ void QLoggingRegistry::init()
{
// get rules from environment
const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF");
- if (!rulesFilePath.isEmpty()) {
- QFile file(QFile::decodeName(rulesFilePath));
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- if (qtLoggingDebug())
- debugMsg("Loading \"%s\" ...",
- QDir::toNativeSeparators(file.fileName()).toUtf8().constData());
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
- envRules = parser.rules();
- }
- }
+ if (!rulesFilePath.isEmpty())
+ envRules = loadRulesFromFile(QFile::decodeName(rulesFilePath));
+
const QByteArray rulesSrc = qgetenv("QT_LOGGING_RULES").replace(';', '\n');
if (!rulesSrc.isEmpty()) {
QTextStream stream(rulesSrc);
@@ -277,23 +284,22 @@ void QLoggingRegistry::init()
envRules += parser.rules();
}
- // get rules from qt configuration
- QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation,
- QStringLiteral("QtProject/qtlogging.ini"));
- if (!envPath.isEmpty()) {
- QFile file(envPath);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- if (qtLoggingDebug())
- debugMsg("Loading \"%s\" ...",
- QDir::toNativeSeparators(envPath).toUtf8().constData());
- QTextStream stream(&file);
- QLoggingSettingsParser parser;
- parser.setContent(stream);
- configRules = parser.rules();
- }
- }
+ const QString configFileName = QStringLiteral("qtlogging.ini");
+
+#if !defined(QT_BOOTSTRAPPED)
+ // get rules from Qt data configuration path
+ const QString qtConfigPath
+ = QDir(QLibraryInfo::location(QLibraryInfo::DataPath)).absoluteFilePath(configFileName);
+ qtConfigRules = loadRulesFromFile(qtConfigPath);
+#endif
+
+ // get rules from user's/system configuration
+ const QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation,
+ QString::fromLatin1("QtProject/") + configFileName);
+ if (!envPath.isEmpty())
+ configRules = loadRulesFromFile(envPath);
- if (!envRules.isEmpty() || !configRules.isEmpty()) {
+ if (!envRules.isEmpty() || !qtConfigRules.isEmpty() || !configRules.isEmpty()) {
QMutexLocker locker(&registryMutex);
updateRules();
}
@@ -356,7 +362,7 @@ void QLoggingRegistry::updateRules()
if (categoryFilter != defaultCategoryFilter)
return;
- rules = configRules + apiRules + envRules;
+ rules = qtConfigRules + configRules + apiRules + envRules;
foreach (QLoggingCategory *cat, categories.keys())
(*categoryFilter)(cat);
diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h
index 718e09d9bb..bb32a4996d 100644
--- a/src/corelib/io/qloggingregistry_p.h
+++ b/src/corelib/io/qloggingregistry_p.h
@@ -122,6 +122,7 @@ private:
QMutex registryMutex;
+ QVector<QLoggingRule> qtConfigRules;
QVector<QLoggingRule> configRules;
QVector<QLoggingRule> envRules;
QVector<QLoggingRule> apiRules;
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 09a471e7db..ecda86a91d 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2014 Intel Corporation
+** Copyright (C) 2015 Intel Corporation
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -139,7 +139,7 @@ QT_BEGIN_NAMESPACE
Unix environment allows both variable names and contents to contain arbitrary
binary data (except for the NUL character). QProcessEnvironment will preserve
such variables, but does not support manipulating variables whose names or
- values are not encodable by the current locale settings (see
+ values cannot be encoded by the current locale settings (see
QTextCodec::codecForLocale).
On Windows, the variable names are case-insensitive, but case-preserving.
@@ -395,8 +395,8 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa
Use with the QProcess::setEnvironment function is not recommended due to
potential encoding problems under Unix, and worse performance.
- \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(),
- QProcess::setEnvironment()
+ \sa systemEnvironment(), QProcess::systemEnvironment(),
+ QProcess::setProcessEnvironment()
*/
QStringList QProcessEnvironment::toStringList() const
{
@@ -545,7 +545,7 @@ void QProcessPrivate::Channel::clear()
QProcess can merge the two output channels, so that standard
output and standard error data from the running process both use
the standard output channel. Call setProcessChannelMode() with
- MergedChannels before starting the process to activative
+ MergedChannels before starting the process to activate
this feature. You also have the option of forwarding the output of
the running process to the calling, main process, by passing
ForwardedChannels as the argument. It is also possible to forward
@@ -556,7 +556,7 @@ void QProcessPrivate::Channel::clear()
Certain processes need special environment settings in order to
operate. You can set environment variables for your process by
- calling setEnvironment(). To set a working directory, call
+ calling setProcessEnvironment(). To set a working directory, call
setWorkingDirectory(). By default, processes are run in the
current working directory of the calling process.
@@ -1328,7 +1328,7 @@ QProcess::InputChannelMode QProcess::inputChannelMode() const
/*!
\since 5.2
- Sets the channel mode of the QProcess standard intput
+ Sets the channel mode of the QProcess standard input
channel to the \a mode specified.
This mode will be used the next time start() is called.
@@ -2195,6 +2195,7 @@ void QProcessPrivate::start(QIODevice::OpenMode mode)
qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
+ stdinChannel.buffer.clear();
stdoutChannel.buffer.clear();
stderrChannel.buffer.clear();
@@ -2393,7 +2394,7 @@ void QProcess::setArguments(const QStringList &arguments)
The process may not exit as a result of calling this function (it is given
the chance to prompt the user for any unsaved files, etc).
- On Windows, terminate() posts a WM_CLOSE message to all toplevel windows
+ On Windows, terminate() posts a WM_CLOSE message to all top-level windows
of the process and then to the main thread of the process itself. On Unix
and OS X the \c SIGTERM signal is sent.
@@ -2589,14 +2590,14 @@ QT_END_INCLUDE_NAMESPACE
This function does not cache the system environment. Therefore, it's
possible to obtain an updated version of the environment if low-level C
- library functions like \tt setenv ot \tt putenv have been called.
+ library functions like \tt setenv or \tt putenv have been called.
However, note that repeated calls to this function will recreate the
list of environment variables, which is a non-trivial operation.
\note For new code, it is recommended to use QProcessEnvironment::systemEnvironment()
- \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
+ \sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment()
*/
QStringList QProcess::systemEnvironment()
{
@@ -2619,7 +2620,7 @@ QStringList QProcess::systemEnvironment()
It is returned as a QProcessEnvironment. This function does not
cache the system environment. Therefore, it's possible to obtain
an updated version of the environment if low-level C library
- functions like \tt setenv ot \tt putenv have been called.
+ functions like \tt setenv or \tt putenv have been called.
However, note that repeated calls to this function will recreate the
QProcessEnvironment object, which is a non-trivial operation.
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 5c9db05eff..e77249975c 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -694,13 +694,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
return true;
// If we wouldn't write anything, check if we can read stdout.
- if (bytesAvailableInChannel(&stdoutChannel) != 0) {
+ if (stdoutChannel.pipe[0] != INVALID_Q_PIPE
+ && bytesAvailableInChannel(&stdoutChannel) != 0) {
tryReadFromChannel(&stdoutChannel);
timer.resetIncrements();
}
// Check if we can read stderr.
- if (bytesAvailableInChannel(&stderrChannel) != 0) {
+ if (stderrChannel.pipe[0] != INVALID_Q_PIPE
+ && bytesAvailableInChannel(&stderrChannel) != 0) {
tryReadFromChannel(&stderrChannel);
timer.resetIncrements();
}
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index d4143c4035..654d688c53 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -453,14 +453,23 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
default: {
#ifndef QT_NO_DATASTREAM
+ QDataStream::Version version;
+ const char *typeSpec;
+ if (v.type() == QVariant::DateTime) {
+ version = QDataStream::Qt_5_6;
+ typeSpec = "@DateTime(";
+ } else {
+ version = QDataStream::Qt_4_0;
+ typeSpec = "@Variant(";
+ }
QByteArray a;
{
QDataStream s(&a, QIODevice::WriteOnly);
- s.setVersion(QDataStream::Qt_4_0);
+ s.setVersion(version);
s << v;
}
- result = QLatin1String("@Variant(");
+ result = QLatin1String(typeSpec);
result += QString::fromLatin1(a.constData(), a.size());
result += QLatin1Char(')');
#else
@@ -480,11 +489,21 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s)
if (s.endsWith(QLatin1Char(')'))) {
if (s.startsWith(QLatin1String("@ByteArray("))) {
return QVariant(s.toLatin1().mid(11, s.size() - 12));
- } else if (s.startsWith(QLatin1String("@Variant("))) {
+ } else if (s.startsWith(QLatin1String("@Variant("))
+ || s.startsWith(QLatin1String("@DateTime("))) {
#ifndef QT_NO_DATASTREAM
- QByteArray a(s.toLatin1().mid(9));
+ QDataStream::Version version;
+ int offset;
+ if (s.at(1) == QLatin1Char('D')) {
+ version = QDataStream::Qt_5_6;
+ offset = 10;
+ } else {
+ version = QDataStream::Qt_4_0;
+ offset = 9;
+ }
+ QByteArray a(s.toLatin1().mid(offset));
QDataStream stream(&a, QIODevice::ReadOnly);
- stream.setVersion(QDataStream::Qt_4_0);
+ stream.setVersion(version);
QVariant result;
stream >> result;
return result;
diff --git a/src/corelib/io/qstorageinfo_mac.cpp b/src/corelib/io/qstorageinfo_mac.cpp
index 1ef9983918..64ca6d7175 100644
--- a/src/corelib/io/qstorageinfo_mac.cpp
+++ b/src/corelib/io/qstorageinfo_mac.cpp
@@ -147,32 +147,24 @@ void QStorageInfoPrivate::retrieveUrlProperties(bool initRootPath)
void QStorageInfoPrivate::retrieveLabel()
{
-#if !defined(Q_OS_IOS)
- // deprecated since 10.8
- FSRef ref;
- FSPathMakeRef(reinterpret_cast<const UInt8*>(QFile::encodeName(rootPath).constData()),
- &ref,
- Q_NULLPTR);
-
- // deprecated since 10.8
- FSCatalogInfo catalogInfo;
- OSErr error;
- error = FSGetCatalogInfo(&ref, kFSCatInfoVolume, &catalogInfo, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR);
- if (error != noErr)
+ QCFString path = CFStringCreateWithFileSystemRepresentation(0,
+ QFile::encodeName(rootPath).constData());
+ if (!path)
return;
- // deprecated (use CFURLCopyResourcePropertiesForKeys for 10.7 and higher)
- HFSUniStr255 volumeName;
- error = FSGetVolumeInfo(catalogInfo.volume,
- 0,
- Q_NULLPTR,
- kFSVolInfoFSInfo,
- Q_NULLPTR,
- &volumeName,
- Q_NULLPTR);
- if (error == noErr)
- name = QCFString(FSCreateStringFromHFSUniStr(Q_NULLPTR, &volumeName));
-#endif
+ QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true);
+ if (!url)
+ return;
+
+ QCFType<CFURLRef> volumeUrl;
+ if (!CFURLCopyResourcePropertyForKey(url, kCFURLVolumeURLKey, &volumeUrl, NULL))
+ return;
+
+ QCFString volumeName;
+ if (!CFURLCopyResourcePropertyForKey(url, kCFURLNameKey, &volumeName, NULL))
+ return;
+
+ name = volumeName;
}
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 83c52dbf2c..54a2855239 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -507,9 +507,9 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
valid = true;
ready = true;
- bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
- bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
- bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
+ bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
+ bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
+ bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
blockSize = statfs_buf.f_bsize;
#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
#if defined(_STATFS_F_FLAGS)
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 8ad1c2852c..ca3be9b7e0 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -121,7 +121,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
digits of the generated number. Some extra number formatting
options are also available through setNumberFlags().
- \keyword QTextStream manipulators
+ \target QTextStream manipulators
Like \c <iostream> in the standard C++ library, QTextStream also
defines several global manipulator functions:
@@ -2800,7 +2800,7 @@ QTextStream &scientific(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft)
on \a stream and returns \a stream.
- \sa right(), center(), {QTextStream manipulators}
+ \sa {QTextStream::}{right()}, {QTextStream::}{center()}, {QTextStream manipulators}
*/
QTextStream &left(QTextStream &stream)
{
@@ -2814,7 +2814,7 @@ QTextStream &left(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight)
on \a stream and returns \a stream.
- \sa left(), center(), {QTextStream manipulators}
+ \sa {QTextStream::}{left()}, {QTextStream::}{center()}, {QTextStream manipulators}
*/
QTextStream &right(QTextStream &stream)
{
@@ -2828,7 +2828,7 @@ QTextStream &right(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter)
on \a stream and returns \a stream.
- \sa left(), right(), {QTextStream manipulators}
+ \sa {QTextStream::}{left()}, {QTextStream::}{right()}, {QTextStream manipulators}
*/
QTextStream &center(QTextStream &stream)
{
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp
index f9a0acf41a..46553d38a5 100644
--- a/src/corelib/io/qurlidna.cpp
+++ b/src/corelib/io/qurlidna.cpp
@@ -1503,7 +1503,7 @@ static bool isMappedToNothing(uint uc)
static bool containsProhibitedOuptut(const QString *str, int from)
{
const ushort *in = reinterpret_cast<const ushort *>(str->begin() + from);
- const ushort *end = (ushort *)str->data() + str->size();
+ const ushort *end = (const ushort *)str->data() + str->size();
for ( ; in < end; ++in) {
uint uc = *in;
if (QChar(uc).isHighSurrogate() && in < end - 1) {
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index add2ac94da..57053f129a 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -85,7 +85,7 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
return -1;
QMutexLocker locker(&lock);
- data.append(QByteArray(ptr, maxlen));
+ data.append(ptr, maxlen);
waitCondition.wakeOne();
return maxlen;
}
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index ba97543c44..51c670f79e 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -729,11 +729,11 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
deselected.append(*it);
it = ranges.erase(it);
} else if (start <= it->top() && it->top() <= end) { // Top intersection
- deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent())));
+ deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->right(), it->parent())));
*it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight());
++it;
} else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection
- deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight()));
+ deselected.append(QItemSelectionRange(model->index(start, it->left(), it->parent()), it->bottomRight()));
*it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent()));
++it;
} else if (it->top() < start && end < it->bottom()) { // Middle intersection
@@ -741,8 +741,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
// and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6].
// [4, 5] is appended to deselected, and [3] and [6] remain part of the selection
// in ranges.
- const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()),
- model->index(end, it->left(), it->parent()));
+ const QItemSelectionRange removedRange(model->index(start, it->left(), it->parent()),
+ model->index(end, it->right(), it->parent()));
deselected.append(removedRange);
QItemSelection::split(*it, removedRange, &newParts);
it = ranges.erase(it);
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp
index dd27603d6d..bb33dbde74 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/json/qjsonarray.cpp
@@ -533,8 +533,8 @@ bool QJsonArray::contains(const QJsonValue &value) const
\a i must be a valid index position in the array (i.e., \c{0 <= i <
size()}).
- The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray
- and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can
+ The return value is of type QJsonValueRef, a helper class for QJsonArray
+ and QJsonObject. When you get an object of type QJsonValueRef, you can
use it as if it were a reference to a QJsonValue. If you assign to it,
the assignment will apply to the character in the QJsonArray of QJsonObject
from which you got the reference.
@@ -739,8 +739,8 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
You can change the value of an item by using operator*() on the
left side of an assignment.
- The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray
- and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can
+ The return value is of type QJsonValueRef, a helper class for QJsonArray
+ and QJsonObject. When you get an object of type QJsonValueRef, you can
use it as if it were a reference to a QJsonValue. If you assign to it,
the assignment will apply to the character in the QJsonArray of QJsonObject
from which you got the reference.
@@ -759,8 +759,8 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
This function is provided to make QJsonArray iterators behave like C++
pointers.
- The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray
- and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can
+ The return value is of type QJsonValueRef, a helper class for QJsonArray
+ and QJsonObject. When you get an object of type QJsonValueRef, you can
use it as if it were a reference to a QJsonValue. If you assign to it,
the assignment will apply to the character in the QJsonArray of QJsonObject
from which you got the reference.
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 4834c14ca8..16156d0f2c 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -57,10 +57,6 @@
#include "qglobal.h"
-#ifdef Q_OS_MACX
-#include <CoreServices/CoreServices.h>
-#endif
-
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#endif
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index f06537923f..3013db8b2e 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -937,18 +937,14 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
/*!
\property QCoreApplication::quitLockEnabled
- Returns \c true if the use of the QEventLoopLocker feature can cause the
- application to quit, otherwise returns \c false.
+ \brief Whether the use of the QEventLoopLocker feature can cause the
+ application to quit.
+
+ The default is \c true.
\sa QEventLoopLocker
*/
-/*!
- Returns \c true if the use of the QEventLoopLocker feature can cause the
- application to quit, otherwise returns \c false.
-
- \sa QEventLoopLocker
- */
bool QCoreApplication::isQuitLockEnabled()
{
return quitLockRefEnabled;
@@ -956,14 +952,6 @@ bool QCoreApplication::isQuitLockEnabled()
static bool doNotify(QObject *, QEvent *);
-/*!
- Enables the ability of the QEventLoopLocker feature to quit
- the application.
-
- If disabled, the use of QEventLoopLocker will not quit the application.
-
- \sa QEventLoopLocker
- */
void QCoreApplication::setQuitLockEnabled(bool enabled)
{
quitLockRefEnabled = enabled;
@@ -1819,7 +1807,7 @@ void QCoreApplicationPrivate::maybeQuit()
Tells the application to exit with return code 0 (success).
Equivalent to calling QCoreApplication::exit(0).
- It's common to connect the QApplication::lastWindowClosed() signal
+ It's common to connect the QGuiApplication::lastWindowClosed() signal
to quit(), and you also often connect e.g. QAbstractButton::clicked() or
signals in QAction, QMenu, or QMenuBar to it.
@@ -1827,7 +1815,7 @@ void QCoreApplicationPrivate::maybeQuit()
\snippet code/src_corelib_kernel_qcoreapplication.cpp 1
- \sa exit(), aboutToQuit(), QApplication::lastWindowClosed()
+ \sa exit(), aboutToQuit(), QGuiApplication::lastWindowClosed()
*/
void QCoreApplication::quit()
@@ -2530,17 +2518,6 @@ QStringList QCoreApplication::libraryPaths()
if (!coreappdata()->app_libpaths) {
QStringList *app_libpaths = new QStringList;
coreappdata()->app_libpaths.reset(app_libpaths);
- QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
- if (QFile::exists(installPathPlugins)) {
- // Make sure we convert from backslashes to slashes.
- installPathPlugins = QDir(installPathPlugins).canonicalPath();
- if (!app_libpaths->contains(installPathPlugins))
- app_libpaths->append(installPathPlugins);
- }
-
- // If QCoreApplication is not yet instantiated,
- // make sure we add the application path when we construct the QCoreApplication
- if (self) self->d_func()->appendApplicationPathToLibraryPaths();
const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
if (!libPathEnv.isEmpty()) {
@@ -2553,6 +2530,18 @@ QStringList QCoreApplication::libraryPaths()
}
}
}
+
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ if (QFile::exists(installPathPlugins)) {
+ // Make sure we convert from backslashes to slashes.
+ installPathPlugins = QDir(installPathPlugins).canonicalPath();
+ if (!app_libpaths->contains(installPathPlugins))
+ app_libpaths->append(installPathPlugins);
+ }
+
+ // If QCoreApplication is not yet instantiated,
+ // make sure we add the application path when we construct the QCoreApplication
+ if (self) self->d_func()->appendApplicationPathToLibraryPaths();
}
return *(coreappdata()->app_libpaths);
}
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index f771974a24..490a7c566a 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -288,7 +288,8 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
}
TimeSpan period;
- period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
+ // TimeSpan is based on 100-nanosecond units
+ period.Duration = qMax(qint64(1), qint64(interval) * 10000);
const HANDLE handle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE);
const HANDLE cancelHandle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE|EVENT_MODIFY_STATE);
HRESULT hr = runOnXamlThread([&]() {
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 3906cdc036..01e2542dfa 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1081,25 +1081,16 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
normalizedTypeName.constData(), idx, previousSize, size);
}
- // Do not compare types higher than 0x100:
- // Ignore WasDeclaredAsMetaType inconsitency, to many users were hitting the problem
- // Ignore IsGadget as it was added in Qt 5.5
- // Ignore all the future flags as well
- if ((previousFlags ^ flags) & 0xff) {
- const int maskForTypeInfo = NeedsConstruction | NeedsDestruction | MovableType;
+ // these flags cannot change in a binary compatible way:
+ const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject
+ | WeakPointerToQObject | TrackingPointerToQObject;
+ if ((previousFlags ^ flags) & binaryCompatibilityFlag) {
+
const char *msg = "QMetaType::registerType: Binary compatibility break. "
"\nType flags for type '%s' [%i] don't match. Previously "
- "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). "
- "This is an ODR break, which means that your application depends on a C++ undefined behavior."
- "\nHint: %s";
- QT_PREPEND_NAMESPACE(QByteArray) hint;
- if ((previousFlags & maskForTypeInfo) != (flags & maskForTypeInfo)) {
- hint += "\nIt seems that the type was registered at least twice in a different translation units, "
- "but Q_DECLARE_TYPEINFO is not visible from all the translations unit or different flags were used."
- "Remember that Q_DECLARE_TYPEINFO should be declared before QMetaType registration, "
- "preferably it should be placed just after the type declaration and before Q_DECLARE_METATYPE";
- }
- qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags), hint.constData());
+ "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). ";
+
+ qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags));
}
return idx;
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 9e3e1e94fa..3b8f8e7166 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1627,7 +1627,7 @@ namespace QtPrivate {
template<typename T>
struct QMetaTypeTypeFlags
{
- enum { Flags = (!QTypeInfo<T>::isStatic ? QMetaType::MovableType : 0)
+ enum { Flags = (QTypeInfoQuery<T>::isRelocatable ? QMetaType::MovableType : 0)
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
| (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
@@ -2244,21 +2244,6 @@ namespace QtPrivate {
};
}
-namespace QtMetaTypePrivate {
-inline Q_DECL_CONSTEXPR bool isBuiltinSequentialType(int typeId)
-{
- return typeId == qMetaTypeId<QStringList>()
- || typeId == qMetaTypeId<QByteArrayList>()
- || typeId == qMetaTypeId<QVariantList>();
-}
-
-inline Q_DECL_CONSTEXPR bool isBuiltinAssociativeType(int typeId)
-{
- return typeId == qMetaTypeId<QVariantHash>()
- || typeId == qMetaTypeId<QVariantMap>();
-}
-} // QtMetaTypePrivate
-
QT_END_NAMESPACE
#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 4d4cccd7b1..d324b6f150 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1219,6 +1219,13 @@ void QObject::setObjectName(const QString &name)
The event() function can be reimplemented to customize the
behavior of an object.
+ Make sure you call the parent event class implementation
+ for all the events you did not handle.
+
+ Example:
+
+ \snippet code/src_corelib_kernel_qobject.cpp 52
+
\sa installEventFilter(), timerEvent(), QCoreApplication::sendEvent(),
QCoreApplication::postEvent()
*/
@@ -1382,7 +1389,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
Signals are not blocked by default.
- \sa blockSignals()
+ \sa blockSignals(), QSignalBlocker
*/
/*!
@@ -1395,7 +1402,9 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
Note that the destroyed() signal will be emitted even if the signals
for this object have been blocked.
- \sa signalsBlocked()
+ Signals emitted while being blocked are not buffered.
+
+ \sa signalsBlocked(), QSignalBlocker
*/
bool QObject::blockSignals(bool block) Q_DECL_NOTHROW
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h
index 72388f2bb7..52bd368301 100644
--- a/src/corelib/kernel/qpointer.h
+++ b/src/corelib/kernel/qpointer.h
@@ -66,6 +66,11 @@ public:
// compiler-generated copy/move ctor/assignment operators are fine!
// compiler-generated dtor is fine!
+#ifdef Q_QDOC
+ // Stop qdoc from complaining about missing function
+ ~QPointer();
+#endif
+
inline void swap(QPointer &other) { wp.swap(other.wp); }
inline QPointer<T> &operator=(T* p)
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 27b19982de..4c7e498280 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -750,7 +750,7 @@ namespace QtPrivate {
static QVariantList invoke(const QVariant &v)
{
const int typeId = v.userType();
- if (QtMetaTypePrivate::isBuiltinSequentialType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
+ if (typeId == qMetaTypeId<QStringList>() || typeId == qMetaTypeId<QByteArrayList>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>())) {
QSequentialIterable iter = QVariantValueHelperInterface<QSequentialIterable>::invoke(v);
QVariantList l;
l.reserve(iter.size());
@@ -767,7 +767,7 @@ namespace QtPrivate {
static QVariantHash invoke(const QVariant &v)
{
const int typeId = v.userType();
- if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
+ if (typeId == qMetaTypeId<QVariantMap>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantHash l;
l.reserve(iter.size());
@@ -784,7 +784,7 @@ namespace QtPrivate {
static QVariantMap invoke(const QVariant &v)
{
const int typeId = v.userType();
- if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
+ if (typeId == qMetaTypeId<QVariantHash>() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>())) {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 3b30b1286d..d84d702982 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -58,7 +58,7 @@ template<typename T>
struct QVariantIntegrator
{
static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data)
- && ((!QTypeInfo<T>::isStatic) || Q_IS_ENUM(T));
+ && ((QTypeInfoQuery<T>::isRelocatable) || Q_IS_ENUM(T));
};
Q_STATIC_ASSERT(QVariantIntegrator<double>::CanUseInternalSpace);
Q_STATIC_ASSERT(QVariantIntegrator<long int>::CanUseInternalSpace);
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index dd8f385c82..fa40b743d3 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -79,10 +79,9 @@ Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test
bool QMimeProviderBase::shouldCheck()
{
- const QDateTime now = QDateTime::currentDateTime();
- if (m_lastCheck.isValid() && m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks)
+ if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000)
return false;
- m_lastCheck = now;
+ m_lastCheck.start();
return true;
}
@@ -562,10 +561,13 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
// load comment and globPatterns
const QString file = data.name + QLatin1String(".xml");
- const QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file);
+ // shared-mime-info since 1.3 lowercases the xml files
+ QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower());
if (mimeFiles.isEmpty()) {
- // TODO: ask Thiago about this
- qWarning() << "No file found for" << file << ", even though the file appeared in a directory listing.";
+ mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3
+ }
+ if (mimeFiles.isEmpty()) {
+ qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.";
qWarning() << "Either it was just removed, or the directory doesn't have executable permission...";
qWarning() << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
return;
@@ -626,7 +628,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
// Let's assume that shared-mime-info is at least version 0.70
// Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
#if 1
- if (!mainPattern.isEmpty() && data.globPatterns.first() != mainPattern) {
+ if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.first() != mainPattern)) {
// ensure it's first in the list of patterns
data.globPatterns.removeAll(mainPattern);
data.globPatterns.prepend(mainPattern);
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index 5a89ac23c3..eaf95942f7 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -51,6 +51,7 @@
#include <QtCore/qdatetime.h>
#include <QtCore/qset.h>
+#include <QtCore/qelapsedtimer.h>
QT_BEGIN_NAMESPACE
@@ -77,7 +78,7 @@ public:
QMimeDatabasePrivate *m_db;
protected:
bool shouldCheck();
- QDateTime m_lastCheck;
+ QElapsedTimer m_lastCheck;
};
/*
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 812e2c9fb6..6698b140af 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -857,7 +857,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
different variant field, the return value is determined by
comparing the two \l{QUuid::Variant} {variants}.
- \sa variant()
+ \sa QUuid::variant()
*/
/*!
@@ -871,7 +871,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
different variant field, the return value is determined by
comparing the two \l{QUuid::Variant} {variants}.
- \sa variant()
+ \sa QUuid::variant()
*/
/*!
@@ -891,7 +891,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
\sa variant(), version()
*/
-#if defined(Q_OS_WIN32)
+#if defined(Q_OS_WIN)
QT_BEGIN_INCLUDE_NAMESPACE
#include <objbase.h> // For CoCreateGuid
@@ -905,7 +905,7 @@ QUuid QUuid::createUuid()
return result;
}
-#else // !Q_OS_WIN32
+#else // Q_OS_WIN
QT_BEGIN_INCLUDE_NAMESPACE
#include "qdatetime.h"
@@ -989,7 +989,7 @@ QUuid QUuid::createUuid()
return result;
}
-#endif // !Q_OS_WIN32
+#endif // !Q_OS_WIN
/*!
\fn bool QUuid::operator==(const GUID &guid) const
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 237b19bc0e..c5e251b37b 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -160,6 +160,8 @@ QT_BEGIN_NAMESPACE
\since 5.4
\brief the running state of this state machine
+
+ \sa start(), stop(), started(), stopped(), runningChanged()
*/
#ifndef QT_NO_ANIMATION
@@ -1832,6 +1834,7 @@ void QStateMachinePrivate::_q_start()
unregisterAllTransitions();
emitFinished();
emit q->runningChanged(false);
+ exitInterpreter();
} else {
_q_process();
}
@@ -1926,6 +1929,8 @@ void QStateMachinePrivate::_q_process()
break;
}
endMacrostep(didChange);
+ if (stopProcessingReason == Finished)
+ exitInterpreter();
}
void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay)
@@ -2055,6 +2060,8 @@ void QStateMachinePrivate::noMicrostep()
4) the state machine either enters an infinite loop, or stops (runningChanged(false),
and either finished or stopped are emitted), or processedPendingEvents() is called.
5) if the machine is not in an infinite loop endMacrostep is called
+ 6) when the machine is finished and all processing (like signal emission) is done,
+ exitInterpreter() is called. (This is the same name as the SCXML specification uses.)
didChange is set to true if at least one microstep was performed, it is possible
that the machine returned to exactly the same state as before, but some transitions
@@ -2075,6 +2082,9 @@ void QStateMachinePrivate::endMacrostep(bool didChange)
Q_UNUSED(didChange);
}
+void QStateMachinePrivate::exitInterpreter()
+{
+}
void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState)
{
@@ -2576,11 +2586,6 @@ void QStateMachine::removeState(QAbstractState *state)
state->setParent(0);
}
-/*!
- Returns whether this state machine is running.
-
- \sa start(), stop()
-*/
bool QStateMachine::isRunning() const
{
Q_D(const QStateMachine);
@@ -2643,11 +2648,6 @@ void QStateMachine::stop()
}
}
-/*!
- Convenience functions to start/stop this state machine.
-
- \sa start(), stop(), started(), finished(), stopped()
-*/
void QStateMachine::setRunning(bool running)
{
if (running)
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index 4419ebc7f3..fe7a06d16b 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -133,6 +133,7 @@ public:
virtual void processedPendingEvents(bool didChange);
virtual void beginMacrostep();
virtual void endMacrostep(bool didChange);
+ virtual void exitInterpreter();
void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted,
const QHash<QAbstractState*, QVector<QPropertyAssignment> > &assignmentsForEnteredStates);
QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions, CalculationCache *cache);
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 002a9cc7bc..3269ee3ae8 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -563,7 +563,28 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
};
typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
-Q_GLOBAL_STATIC(FreeList, freelist);
+// We cannot use Q_GLOBAL_STATIC because it uses QMutex
+#if defined(Q_COMPILER_THREADSAFE_STATICS)
+FreeList *freelist()
+{
+ static FreeList list;
+ return &list;
+}
+#else
+FreeList *freelist()
+{
+ static QAtomicPointer<FreeList> list;
+ FreeList *local = list.loadAcquire();
+ if (!local) {
+ local = new FreeList;
+ if (!list.testAndSetRelease(0, local)) {
+ delete local;
+ local = list.loadAcquire();
+ }
+ }
+ return local;
+}
+#endif
}
QMutexPrivate *QMutexPrivate::allocate()
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index f054a727cf..4b50936958 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -75,9 +75,6 @@
# define old_qDebug qDebug
# undef qDebug
# endif
-#ifdef Q_OS_MACX
-# include <CoreServices/CoreServices.h>
-#endif // Q_OS_MACX
# ifdef old_qDebug
# undef qDebug
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index c16a2e958c..72f04ff7af 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
//#define WINVER 0x0500
-#if !defined Q_OS_WINRT && (_WIN32_WINNT < 0x0400)
+#if !defined(WINAPI_FAMILY) && (_WIN32_WINNT < 0x0400)
#define _WIN32_WINNT 0x0400
#endif
@@ -118,7 +118,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
}
threadData->deref();
threadData->isAdopted = true;
- threadData->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+ threadData->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread;
@@ -340,7 +340,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
qt_create_tls();
TlsSetValue(qt_current_thread_data_tls_index, data);
- data->threadId = reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+ data->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
QThread::setTerminationEnabled(false);
@@ -413,7 +413,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway)
Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
{
- return reinterpret_cast<Qt::HANDLE>(GetCurrentThreadId());
+ return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
}
int QThread::idealThreadCount() Q_DECL_NOTHROW
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 3c1ddd984a..2cb00a6cf4 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -46,21 +46,21 @@ SOURCES += thread/qatomic.cpp \
unix:SOURCES += thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
-win32:SOURCES += thread/qmutex_win.cpp \
- thread/qthread_win.cpp \
+win32:SOURCES += thread/qthread_win.cpp \
thread/qwaitcondition_win.cpp
-integrity:SOURCES += thread/qmutex_unix.cpp \
- thread/qthread_unix.cpp \
+integrity:SOURCES += thread/qthread_unix.cpp \
thread/qwaitcondition_unix.cpp
-unix: {
- mac {
- SOURCES += thread/qmutex_mac.cpp
- } else:linux-*:!linux-lsb-* {
- SOURCES += thread/qmutex_linux.cpp
- } else {
- SOURCES += thread/qmutex_unix.cpp
- }
+false {
+ # files #included by others, but listed here so IDEs parsing this file know
+ # they are part of QtCore. Usually, qmake can find out that certain files
+ # are #included by others and thus remove from SOURCES, but it gets lost
+ # with qmutex.cpp.
+ SOURCES += \
+ thread/qmutex_linux.cpp \
+ thread/qmutex_mac.cpp \
+ thread/qmutex_unix.cpp \
+ thread/qmutex_win.cpp
}
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index 57fbdf0eba..ffa3082d5e 100755..100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -649,7 +649,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_D
return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
-Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW
{
#if defined(Q_CC_GNU)
return v ? __builtin_clz(v) : 32U;
@@ -664,7 +664,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW
#endif
}
-Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
{
#if defined(Q_CC_GNU)
return v ? __builtin_clz(v)-24U : 8U;
@@ -676,7 +676,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW
#endif
}
-Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
{
#if defined(Q_CC_GNU)
return v ? __builtin_clz(v)-16U : 16U;
@@ -689,7 +689,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW
#endif
}
-Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
{
#if defined(Q_CC_GNU)
return v ? __builtin_clzll(v) : 64U;
@@ -704,7 +704,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW
#endif
}
-Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW
+Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW
{
return qCountLeadingZeroBits(QIntegerForSizeof<long>::Unsigned(v));
}
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 241c255b5d..ac191ef265 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -489,8 +489,8 @@ quint16 qChecksum(const char *data, uint len)
\overload
- Compresses the first \a nbytes of \a data and returns the
- compressed data in a new byte array.
+ Compresses the first \a nbytes of \a data at compression level
+ \a compressionLevel and returns the compressed data in a new byte array.
*/
#ifndef QT_NO_COMPRESS
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index e6c246e8e6..5469eee14d 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -598,12 +598,22 @@ QT_BEGIN_NAMESPACE
\fn QChar::QChar(char ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+
+ \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII
+ is defined.
+
+ \sa QT_NO_CAST_FROM_ASCII
*/
/*!
\fn QChar::QChar(uchar ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
+
+ \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII
+ is defined.
+
+ \sa QT_NO_CAST_FROM_ASCII
*/
/*!
diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp
index eb50cee5bb..8c0ba8cb2b 100644
--- a/src/corelib/tools/qcommandlineoption.cpp
+++ b/src/corelib/tools/qcommandlineoption.cpp
@@ -284,7 +284,7 @@ QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList)
else
nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()),
nameList.end());
- return qMove(nameList);
+ return nameList;
}
/*!
@@ -391,7 +391,7 @@ QStringList QCommandLineOption::defaultValues() const
/*!
Sets whether to hide this option in the user-visible help output.
- All options are visible by default. Setting \a hidden to true for
+ All options are visible by default. Setting \a hide to true for
a particular option makes it internal, i.e. not listed in the help output.
\since 5.6
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index e445055e1d..0d7225eea0 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -1681,6 +1681,7 @@ bool QTime::setHMS(int h, int m, int s, int ms)
QTime QTime::addSecs(int s) const
{
+ s %= SECS_PER_DAY;
return addMSecs(s * 1000);
}
@@ -4791,23 +4792,21 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
// From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec
dateAndTime = dateTime.d->getDateTime();
out << dateAndTime;
- if (out.version() >= QDataStream::Qt_4_0) {
- switch (dateTime.timeSpec()) {
- case Qt::UTC:
- out << (qint8)QDateTimePrivate::UTC;
- break;
- case Qt::OffsetFromUTC:
- out << (qint8)QDateTimePrivate::OffsetFromUTC;
- break;
- case Qt::TimeZone:
+ switch (dateTime.timeSpec()) {
+ case Qt::UTC:
+ out << (qint8)QDateTimePrivate::UTC;
+ break;
+ case Qt::OffsetFromUTC:
+ out << (qint8)QDateTimePrivate::OffsetFromUTC;
+ break;
+ case Qt::TimeZone:
#ifndef QT_BOOTSTRAPPED
- out << (qint8)QDateTimePrivate::TimeZone;
- break;
+ out << (qint8)QDateTimePrivate::TimeZone;
+ break;
#endif // QT_BOOTSTRAPPED
- case Qt::LocalTime:
- out << (qint8)QDateTimePrivate::LocalUnknown;
- break;
- }
+ case Qt::LocalTime:
+ out << (qint8)QDateTimePrivate::LocalUnknown;
+ break;
}
} else { // version < QDataStream::Qt_4_0
diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp
index a355bf03e8..e946ac096f 100644
--- a/src/corelib/tools/qelapsedtimer_mac.cpp
+++ b/src/corelib/tools/qelapsedtimer_mac.cpp
@@ -59,8 +59,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime)
{
if (info.denom == 0)
mach_timebase_info(&info);
+#ifdef __LP64__
+ __uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom;
+ return static_cast<qint64>(nsecs);
+#else
qint64 nsecs = cpuTime * info.numer / info.denom;
return nsecs;
+#endif
}
static qint64 absoluteToMSecs(qint64 cpuTime)
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 1f3ea36121..b334a697a9 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -290,6 +290,53 @@ static void qt_initialize_qhash_seed()
}
}
+/*! \relates QHash
+ \since 5.6
+
+ Returns the current global QHash seed.
+
+ The seed is set in any newly created QHash. See \l{qHash} about how this seed
+ is being used by QHash.
+
+ \sa qSetGlobalQHashSeed
+ */
+int qGlobalQHashSeed()
+{
+ return qt_qhash_seed.load();
+}
+
+/*! \relates QHash
+ \since 5.6
+
+ Sets the global QHash seed.
+
+ Manually setting the global QHash seed value should be done only for testing
+ and debugging purposes, when deterministic and reproducible behavior on a QHash
+ is needed. We discourage to do it in production code as it can make your
+ application susceptible to \l{algorithmic complexity attacks}.
+
+ The seed is set in any newly created QHash. See \l{qHash} about how this seed
+ is being used by QHash.
+
+ If the environment variable \c QT_HASH_SEED is set, calling this function will
+ result in a no-op.
+
+ Passing the value -1 will reinitialize the global QHash seed to a random value.
+
+ \sa qGlobalQHashSeed
+ */
+void qSetGlobalQHashSeed(int newSeed)
+{
+ if (qEnvironmentVariableIsSet("QT_HASH_SEED"))
+ return;
+ if (newSeed == -1) {
+ int x(qt_create_qhash_seed() & INT_MAX);
+ qt_qhash_seed.store(x);
+ } else {
+ qt_qhash_seed.store(newSeed & INT_MAX);
+ }
+}
+
/*!
\internal
@@ -1132,7 +1179,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
where you temporarily need deterministic behavior, for example for debugging or
regression testing. To disable the randomization, define the environment
variable \c QT_HASH_SEED. The contents of that variable, interpreted as a
- decimal value, will be used as the seed for qHash().
+ decimal value, will be used as the seed for qHash(). Alternatively, you can
+ call the qSetGlobalQHashSeed() function.
\sa QHashIterator, QMutableHashIterator, QMap, QSet
*/
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index e367cc0068..8d65a018ae 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -1037,6 +1037,9 @@ Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value)
return n;
}
+Q_CORE_EXPORT int qGlobalQHashSeed();
+Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed);
+
Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash)
Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash)
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 703341cc36..181daa04e4 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2742,9 +2742,9 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
const QChar exponential, const QChar group, const QChar decimal,
double d, int precision, DoubleForm form, int width, unsigned flags)
{
- if (precision == -1)
+ if (precision < 0)
precision = 6;
- if (width == -1)
+ if (width < 0)
width = 0;
bool negative = false;
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index 1cad9b32e3..4781bab172 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -51,9 +51,7 @@
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
-#ifndef Q_OS_WINPHONE
#include <windows.globalization.h>
-#endif
#endif // Q_OS_WINRT
QT_BEGIN_NAMESPACE
@@ -639,7 +637,6 @@ QVariant QSystemLocalePrivate::uiLanguages()
return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage())));
#else // !Q_OS_WINRT
QStringList result;
-#ifndef Q_OS_WINPHONE
ComPtr<ABI::Windows::Globalization::IApplicationLanguagesStatics> appLanguagesStatics;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) {
qWarning("Could not obtain ApplicationLanguagesStatic");
@@ -661,9 +658,6 @@ QVariant QSystemLocalePrivate::uiLanguages()
PCWSTR rawString = language.GetRawBuffer(&length);
result << QString::fromWCharArray(rawString, length);
}
-#else // !Q_OS_WINPHONE
- result << QString::fromWCharArray(lcName);
-#endif // Q_OS_WINPHONE
return result;
#endif // Q_OS_WINRT
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index b2174745e4..847f650a70 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -2403,7 +2403,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW
/*!
\fn QRectF QRectF::marginsAdded(const QMarginsF &margins) const
- \relates QRectF
\since 5.3
Returns a rectangle grown by the \a margins.
@@ -2413,7 +2412,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW
/*!
\fn QRectF QRectF::marginsRemoved(const QMarginsF &margins) const
- \relates QRectF
\since 5.3
Removes the \a margins from the rectangle, shrinking it.
@@ -2423,7 +2421,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW
/*!
\fn QRectF QRectF::operator+=(const QMarginsF &margins)
- \relates QRectF
\since 5.3
Adds the \a margins to the rectangle, growing it.
@@ -2433,7 +2430,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW
/*!
\fn QRectF QRectF::operator-=(const QMarginsF &margins)
- \relates QRectF
\since 5.3
Returns a rectangle shrunk by the \a margins.
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index 8000dc8688..82de664a56 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -116,6 +116,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
A good text on regexps is \e {Mastering Regular Expressions}
(Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4.
+ \note In Qt 5, the new QRegularExpression class provides a Perl
+ compatible implementation of regular expressions and is recommended
+ in place of QRegExp.
+
\tableofcontents
\section1 Introduction
@@ -488,7 +492,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
when it is followed by 'char'.
\endtable
- \keyword QRegExp wildcard matching
+ \target QRegExp wildcard matching
\section1 Wildcard Matching
Most command shells such as \e bash or \e cmd.exe support "file
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 88a048d826..d8b0bf6e9f 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Copyright (C) 2015 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
@@ -1326,48 +1326,45 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
int * const captureOffsets = priv->capturedOffsets.data();
const int captureOffsetsCount = priv->capturedOffsets.size();
- int realOffset = offset + subjectStart;
- const int realSubjectLength = subjectLength + subjectStart;
-
- const unsigned short * const subjectUtf16 = subject.utf16();
+ const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart;
int result;
if (!previousMatchWasEmpty) {
result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, realSubjectLength,
- realOffset, pcreOptions,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
captureOffsets, captureOffsetsCount);
} else {
result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, realSubjectLength,
- realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
captureOffsets, captureOffsetsCount);
if (result == PCRE_ERROR_NOMATCH) {
- ++realOffset;
+ ++offset;
if (usingCrLfNewlines
- && realOffset < realSubjectLength
- && subjectUtf16[realOffset - 1] == QLatin1Char('\r')
- && subjectUtf16[realOffset] == QLatin1Char('\n')) {
- ++realOffset;
- } else if (realOffset < realSubjectLength
- && QChar::isLowSurrogate(subjectUtf16[realOffset])) {
- ++realOffset;
+ && offset < subjectLength
+ && subjectUtf16[offset - 1] == QLatin1Char('\r')
+ && subjectUtf16[offset] == QLatin1Char('\n')) {
+ ++offset;
+ } else if (offset < subjectLength
+ && QChar::isLowSurrogate(subjectUtf16[offset])) {
+ ++offset;
}
result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, realSubjectLength,
- realOffset, pcreOptions,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
captureOffsets, captureOffsetsCount);
}
}
#ifdef QREGULAREXPRESSION_DEBUG
qDebug() << "Matching" << pattern << "against" << subject
- << "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength
- << "offset" << offset << "real offset" << realOffset
+ << "starting at" << subjectStart << "len" << subjectLength
+ << "offset" << offset
<< matchType << matchOptions << previousMatchWasEmpty
<< "result" << result;
#endif
@@ -2057,7 +2054,7 @@ QString QRegularExpressionMatch::captured(int nth) const
if (start == -1) // didn't capture
return QString();
- return d->subject.mid(start, capturedLength(nth));
+ return d->subject.mid(start + d->subjectStart, capturedLength(nth));
}
/*!
@@ -2078,7 +2075,7 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const
if (start == -1) // didn't capture
return QStringRef();
- return d->subject.midRef(start, capturedLength(nth));
+ return d->subject.midRef(start + d->subjectStart, capturedLength(nth));
}
/*!
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index e7917ffdac..d0c65a04b1 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -78,28 +78,28 @@ static inline uint detectProcessorFeatures()
return 0;
}
#elif defined (Q_OS_WINCE)
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
- uint features = 0;
+ quint64 features = 0;
#if defined (ARM)
# ifdef PF_ARM_NEON
if (IsProcessorFeaturePresent(PF_ARM_NEON))
- features |= ARM_NEON;
+ features |= Q_UINT64_C(1) << CpuFeatureNEON;
# endif
#elif defined(_X86_)
if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
- features |= SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
- features |= SSE3;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE3;
#endif
return features;
}
#elif defined(Q_PROCESSOR_ARM)
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
- uint features = 0;
+ quint64 features = 0;
#if defined(Q_OS_LINUX)
int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY);
@@ -117,7 +117,7 @@ static inline uint detectProcessorFeatures()
for (int i = 0; i < max; i += 2)
if (vector[i] == AT_HWCAP) {
if (vector[i+1] & HWCAP_NEON)
- features |= NEON;
+ features |= Q_UINT64_C(1) << CpuFeatureNEON;
break;
}
}
@@ -129,7 +129,7 @@ static inline uint detectProcessorFeatures()
#endif
#if defined(__ARM_NEON__)
- features = NEON;
+ features = Q_UINT64_C(1) << CpuFeatureNEON;
#endif
return features;
@@ -205,21 +205,24 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));}
#endif
-static void cpuidFeatures07_00(uint &ebx)
+static void cpuidFeatures07_00(uint &ebx, uint &ecx)
{
#if defined(Q_CC_GNU)
qregisteruint rbx; // in case it's 64-bit
+ qregisteruint rcx = 0;
asm ("xchg " PICreg", %0\n"
"cpuid\n"
"xchg " PICreg", %0\n"
- : "=&r" (rbx)
- : "a" (7), "c" (0)
+ : "=&r" (rbx), "+&c" (rcx)
+ : "a" (7)
: "%edx");
ebx = rbx;
+ ecx = rcx;
#elif defined(Q_OS_WIN)
int info[4];
__cpuidex(info, 7, 0);
ebx = info[1];
+ ecx = info[2];
#endif
}
@@ -240,7 +243,7 @@ static void xgetbv(uint in, uint &eax, uint &edx)
#endif
}
-static inline uint detectProcessorFeatures()
+static quint64 detectProcessorFeatures()
{
// Flags from the CR0 / XCR0 state register
enum XCR0Flags {
@@ -257,8 +260,15 @@ static inline uint detectProcessorFeatures()
AVXState = XMM0_15 | YMM0_15Hi128,
AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
};
-
- uint features = 0;
+ static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512VL) |
+ (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
+ static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512;
+ static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2;
+
+ quint64 features = 0;
int cpuidLevel = maxBasicCpuidSupported();
#if Q_PROCESSOR_X86 < 5
if (cpuidLevel < 1)
@@ -269,28 +279,23 @@ static inline uint detectProcessorFeatures()
uint cpuid01ECX = 0, cpuid01EDX = 0;
cpuidFeatures01(cpuid01ECX, cpuid01EDX);
+
+ // the low 32-bits of features is cpuid01ECX
+ // note: we need to check OS support for saving the AVX register state
+ features = cpuid01ECX;
+
#if defined(Q_PROCESSOR_X86_32)
// x86 might not have SSE2 support
if (cpuid01EDX & (1u << 26))
- features |= SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
+ else
+ features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2);
// we should verify that the OS enabled saving of the SSE state...
#else
// x86-64 or x32
- features = SSE2;
+ features |= Q_UINT64_C(1) << CpuFeatureSSE2;
#endif
- // common part between 32- and 64-bit
- if (cpuid01ECX & (1u))
- features |= SSE3;
- if (cpuid01ECX & (1u << 9))
- features |= SSSE3;
- if (cpuid01ECX & (1u << 19))
- features |= SSE4_1;
- if (cpuid01ECX & (1u << 20))
- features |= SSE4_2;
- if (cpuid01ECX & (1u << 25))
- features |= 0; // AES, enable if needed
-
uint xgetbvA = 0, xgetbvD = 0;
if (cpuid01ECX & (1u << 27)) {
// XGETBV enabled
@@ -298,22 +303,27 @@ static inline uint detectProcessorFeatures()
}
uint cpuid0700EBX = 0;
- if (cpuidLevel >= 7)
- cpuidFeatures07_00(cpuid0700EBX);
+ uint cpuid0700ECX = 0;
+ if (cpuidLevel >= 7) {
+ cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX);
- if ((xgetbvA & AVXState) == AVXState) {
- // support for YMM and XMM registers is enabled
- if (cpuid01ECX & (1u << 28))
- features |= AVX;
-
- if (cpuid0700EBX & (1u << 5))
- features |= AVX2;
+ // the high 32-bits of features is cpuid0700EBX
+ features |= quint64(cpuid0700EBX) << 32;
}
- if (cpuid0700EBX & (1u << 4))
- features |= HLE; // Hardware Lock Ellision
- if (cpuid0700EBX & (1u << 11))
- features |= RTM; // Restricted Transactional Memory
+ if ((xgetbvA & AVXState) != AVXState) {
+ // support for YMM registers is disabled, disable all AVX
+ features &= ~AllAVX;
+ } else if ((xgetbvA & AVX512State) != AVX512State) {
+ // support for ZMM registers or mask registers is disabled, disable all AVX512
+ features &= ~AllAVX512;
+ } else {
+ // this feature is out of order
+ if (cpuid0700ECX & (1u << 1))
+ features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI;
+ else
+ features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
+ }
return features;
}
@@ -430,24 +440,24 @@ static bool procCpuinfoContains(const char *prefix, const char *string)
}
#endif
-static inline uint detectProcessorFeatures()
+static inline quint64 detectProcessorFeatures()
{
// NOTE: MIPS 74K cores are the only ones supporting DSPr2.
- uint flags = 0;
+ quint64 flags = 0;
#if defined __mips_dsp
- flags |= DSP;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSP;
# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
# elif defined(Q_OS_LINUX)
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
# endif
#elif defined(Q_OS_LINUX)
if (procCpuinfoContains("ASEs implemented", "dsp")) {
- flags |= DSP;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSP;
if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf"))
- flags |= DSPR2;
+ flags |= Q_UINT64_C(1) << CpuFeatureDSPR2;
}
#endif
@@ -462,70 +472,179 @@ static inline uint detectProcessorFeatures()
#endif
/*
- * Use kdesdk/scripts/generate_string_table.pl to update the table below.
- * Here's the data (don't forget the ONE leading space):
+ * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note
+ * that the x86 version has a lot of blanks that must be kept and that the
+ * offset table's type is changed to make the table smaller. We also remove the
+ * terminating -1 that the script adds.
+ */
+// begin generated
+#if defined(Q_PROCESSOR_ARM)
+/* Data:
neon
- sse2
+ */
+static const char features_string[] = " neon\0";
+static const int features_indices[] = { 0 };
+#elif defined(Q_PROCESSOR_MIPS)
+/* Data:
+ dsp
+ dspr2
+*/
+static const char features_string[] =
+ " dsp\0"
+ " dspr2\0"
+ "\0";
+
+static const int features_indices[] = {
+ 0, 5
+};
+#elif defined(Q_PROCESSOR_X86)
+/* Data:
sse3
+ sse2
+ avx512vbmi
+
+
+
+
+
+
ssse3
+
+
+ fma
+ cmpxchg16b
+
+
+
+
+
sse4.1
sse4.2
+
+ movbe
+ popcnt
+
+ aes
+
+
avx
- avx2
+ f16c
+ rdrand
+
+
+
+
+ bmi
hle
+ avx2
+
+
+ bmi2
+
+
rtm
- dsp
- dspr2
- */
-// begin generated
+
+
+
+ avx512f
+ avx512dq
+ rdseed
+
+
+ avx512ifma
+
+
+
+
+ avx512pf
+ avx512er
+ avx512cd
+ sha
+ avx512bw
+ avx512vl
+ */
static const char features_string[] =
- "\0"
- " neon\0"
- " sse2\0"
" sse3\0"
+ " sse2\0"
+ " avx512vbmi\0"
" ssse3\0"
+ " fma\0"
+ " cmpxchg16b\0"
" sse4.1\0"
" sse4.2\0"
+ " movbe\0"
+ " popcnt\0"
+ " aes\0"
" avx\0"
- " avx2\0"
+ " f16c\0"
+ " rdrand\0"
+ " bmi\0"
" hle\0"
+ " avx2\0"
+ " bmi2\0"
" rtm\0"
- " dsp\0"
- " dspr2\0"
+ " avx512f\0"
+ " avx512dq\0"
+ " rdseed\0"
+ " avx512ifma\0"
+ " avx512pf\0"
+ " avx512er\0"
+ " avx512cd\0"
+ " sha\0"
+ " avx512bw\0"
+ " avx512vl\0"
"\0";
-static const int features_indices[] = {
- 0, 1, 7, 13, 19, 26, 34, 42,
- 47, 53, 58, 63, 68, -1
+static const quint8 features_indices[] = {
+ 0, 6, 12, 5, 5, 5, 5, 5,
+ 5, 24, 5, 5, 31, 36, 5, 5,
+ 5, 5, 5, 48, 56, 5, 64, 71,
+ 5, 79, 5, 5, 84, 89, 95, 5,
+ 5, 5, 5, 103, 108, 113, 5, 5,
+ 119, 5, 5, 125, 5, 5, 5, 5,
+ 130, 139, 149, 5, 5, 157, 5, 5,
+ 5, 5, 169, 179, 189, 199, 204, 214
};
+#else
+static const char features_string[] = "";
+static const int features_indices[] = { };
+#endif
// end generated
-static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]);
+static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]);
// record what CPU features were enabled by default in this Qt build
-static const uint minFeature = qCompilerCpuFeatures;
+static const quint64 minFeature = qCompilerCpuFeatures;
#ifdef Q_OS_WIN
#if defined(Q_CC_GNU)
-# define ffs __builtin_ffs
+# define ffsll __builtin_ffsll
#else
-int ffs(int i)
+int ffsll(quint64 i)
{
-#ifndef Q_OS_WINCE
+#if defined(Q_OS_WIN64)
unsigned long result;
- return _BitScanForward(&result, i) ? result : 0;
+ return _BitScanForward64(&result, i) ? result : 0;
+#elif !defined(Q_OS_WINCE)
+ unsigned long result;
+ return _BitScanForward(&result, i) ? result :
+ _BitScanForward(&result, i >> 32) ? result + 32 : 0;
#else
return 0;
#endif
}
#endif
-#elif defined(Q_OS_ANDROID)
-# define ffs __builtin_ffs
+#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
+# define ffsll __builtin_ffsll
#endif
-QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0);
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };
+#else
+Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
+#endif
void qDetectCpuFeatures()
{
@@ -547,11 +666,11 @@ void qDetectCpuFeatures()
// contains all the features that the code required. Qt 4 ran for years
// like that, so it shouldn't be a problem.
- qt_cpu_features.store(minFeature | QSimdInitialized);
+ qt_cpu_features.store(minFeature | quint32(QSimdInitialized));
return;
# endif
#endif
- uint f = detectProcessorFeatures();
+ quint64 f = detectProcessorFeatures();
QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
if (!disable.isEmpty()) {
disable.prepend(' ');
@@ -567,29 +686,32 @@ void qDetectCpuFeatures()
bool runningOnValgrind = false;
#endif
if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) {
- uint missing = minFeature & ~f;
+ quint64 missing = minFeature & ~f;
fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n ");
for (int i = 0; i < features_count; ++i) {
- if (missing & (1 << i))
+ if (missing & (Q_UINT64_C(1) << i))
fprintf(stderr, "%s", features_string + features_indices[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
- qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing,
- features_string + features_indices[ffs(missing) - 1]);
+ qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing,
+ features_string + features_indices[ffsll(missing) - 1]);
}
- qt_cpu_features.store(f | QSimdInitialized);
+ qt_cpu_features[0].store(f | quint32(QSimdInitialized));
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ qt_cpu_features[1].store(f >> 32);
+#endif
}
void qDumpCPUFeatures()
{
- uint features = qCpuFeatures();
+ quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized);
printf("Processor features: ");
for (int i = 0; i < features_count; ++i) {
- if (features & (1 << i))
+ if (features & (Q_UINT64_C(1) << i))
printf("%s%s", features_string + features_indices[i],
- minFeature & (1 << i) ? "[required]" : "");
+ minFeature & (Q_UINT64_C(1) << i) ? "[required]" : "");
}
puts("");
}
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index dd93b4fd26..be003f6c6d 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -54,9 +54,9 @@
* for the x86 and ARM intrinsics:
* - GCC: the -mXXX or march=YYY flag is necessary before #include
* up to 4.8; GCC >= 4.9 can include unconditionally
+ * - Clang: same as GCC, with unconditional inclusion with version 3.7
* - Intel CC: #include can happen unconditionally
* - MSVC: #include can happen unconditionally
- * - RVCT: ???
*
* We will try to include all headers possible under this configuration.
*
@@ -138,7 +138,8 @@
#define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0)
#if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \
- || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \
+ || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409) \
+ || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 307)) \
&& !defined(QT_BOOTSTRAPPED)
# define QT_COMPILER_SUPPORTS_SIMD_ALWAYS
# define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x)
@@ -217,6 +218,23 @@
# endif
#endif
+#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f"
+#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd"
+#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er"
+#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf"
+#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw"
+#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq"
+#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl"
+#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma"
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi"
+
+#define QT_FUNCTION_TARGET_STRING_F16C "f16c"
+#define QT_FUNCTION_TARGET_STRING_RDRAND "rdrnd"
+#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
+#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
+#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
+#define QT_FUNCTION_TARGET_STRING_SHA "sha"
+
// other x86 intrinsics
#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \
|| (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \
@@ -244,74 +262,170 @@ QT_BEGIN_NAMESPACE
enum CPUFeatures {
- NEON = 0x2, ARM_NEON = NEON,
- SSE2 = 0x4,
- SSE3 = 0x8,
- SSSE3 = 0x10,
- SSE4_1 = 0x20,
- SSE4_2 = 0x40,
- AVX = 0x80,
- AVX2 = 0x100,
- HLE = 0x200,
- RTM = 0x400,
- DSP = 0x800,
- DSPR2 = 0x1000,
+#if defined(Q_PROCESSOR_ARM)
+ CpuFeatureNEON = 0,
+ CpuFeatureARM_NEON = CpuFeatureNEON,
+#elif defined(Q_PROCESSOR_MIPS)
+ CpuFeatureDSP = 0,
+ CpuFeatureDSPR2 = 1,
+#elif defined(Q_PROCESSOR_X86)
+ // The order of the flags is jumbled so it matches most closely the bits in CPUID
+ // Out of order:
+ CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ
+ // in level 1, ECX
+ CpuFeatureSSE3 = (0 + 0),
+ CpuFeatureSSSE3 = (0 + 9),
+ CpuFeatureSSE4_1 = (0 + 19),
+ CpuFeatureSSE4_2 = (0 + 20),
+ CpuFeatureMOVBE = (0 + 22),
+ CpuFeaturePOPCNT = (0 + 23),
+ CpuFeatureAES = (0 + 25),
+ CpuFeatureAVX = (0 + 28),
+ CpuFeatureF16C = (0 + 29),
+ CpuFeatureRDRAND = (0 + 30),
+ // 31 is always zero and we've used it for the QSimdInitialized
+
+ // in level 7, leaf 0, EBX
+ CpuFeatureBMI = (32 + 3),
+ CpuFeatureHLE = (32 + 4),
+ CpuFeatureAVX2 = (32 + 5),
+ CpuFeatureBMI2 = (32 + 8),
+ CpuFeatureRTM = (32 + 11),
+ CpuFeatureAVX512F = (32 + 16),
+ CpuFeatureAVX512DQ = (32 + 17),
+ CpuFeatureRDSEED = (32 + 18),
+ CpuFeatureAVX512IFMA = (32 + 21),
+ CpuFeatureAVX512PF = (32 + 26),
+ CpuFeatureAVX512ER = (32 + 27),
+ CpuFeatureAVX512CD = (32 + 28),
+ CpuFeatureSHA = (32 + 29),
+ CpuFeatureAVX512BW = (32 + 30),
+ CpuFeatureAVX512VL = (32 + 31),
+
+ // in level 7, leaf 0, ECX (out of order, for now)
+ CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64
+#endif
// used only to indicate that the CPU detection was initialised
QSimdInitialized = 0x80000000
};
-static const uint qCompilerCpuFeatures = 0
+static const quint64 qCompilerCpuFeatures = 0
+#if defined __SHA__
+ | (Q_UINT64_C(1) << CpuFeatureSHA)
+#endif
+#if defined __AES__
+ | (Q_UINT64_C(1) << CpuFeatureAES)
+#endif
#if defined __RTM__
- | RTM
+ | (Q_UINT64_C(1) << CpuFeatureRTM)
+#endif
+#ifdef __RDRND__
+ | (Q_UINT64_C(1) << CpuFeatureRDRAND)
+#endif
+#ifdef __RDSEED__
+ | (Q_UINT64_C(1) << CpuFeatureRDSEED)
+#endif
+#if defined __BMI__
+ | (Q_UINT64_C(1) << CpuFeatureBMI)
+#endif
+#if defined __BMI2__
+ | (Q_UINT64_C(1) << CpuFeatureBMI2)
+#endif
+#if defined __F16C__
+ | (Q_UINT64_C(1) << CpuFeatureF16C)
+#endif
+#if defined __POPCNT__
+ | (Q_UINT64_C(1) << CpuFeaturePOPCNT)
+#endif
+#if defined __MOVBE__ // GCC and Clang don't seem to define this
+ | (Q_UINT64_C(1) << CpuFeatureMOVBE)
+#endif
+#if defined __AVX512F__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512F)
+#endif
+#if defined __AVX512CD__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512CD)
+#endif
+#if defined __AVX512ER__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512ER)
+#endif
+#if defined __AVX512PF__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512PF)
+#endif
+#if defined __AVX512BW__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512BW)
+#endif
+#if defined __AVX512DQ__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512DQ)
+#endif
+#if defined __AVX512VL__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512VL)
+#endif
+#if defined __AVX512IFMA__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA)
+#endif
+#if defined __AVX512VBMI__
+ | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI)
#endif
#if defined __AVX2__
- | AVX2
+ | (Q_UINT64_C(1) << CpuFeatureAVX2)
#endif
#if defined __AVX__
- | AVX
+ | (Q_UINT64_C(1) << CpuFeatureAVX)
#endif
#if defined __SSE4_2__
- | SSE4_2
+ | (Q_UINT64_C(1) << CpuFeatureSSE4_2)
#endif
#if defined __SSE4_1__
- | SSE4_1
+ | (Q_UINT64_C(1) << CpuFeatureSSE4_1)
#endif
#if defined __SSSE3__
- | SSSE3
+ | (Q_UINT64_C(1) << CpuFeatureSSSE3)
#endif
#if defined __SSE3__
- | SSE3
+ | (Q_UINT64_C(1) << CpuFeatureSSE3)
#endif
#if defined __SSE2__
- | SSE2
+ | (Q_UINT64_C(1) << CpuFeatureSSE2)
#endif
#if defined __ARM_NEON__
- | NEON
+ | (Q_UINT64_C(1) << CpuFeatureNEON)
#endif
#if defined __mips_dsp
- | DSP
+ | (Q_UINT64_C(1) << CpuFeatureDSP)
#endif
#if defined __mips_dspr2
- | DSPR2
+ | (Q_UINT64_C(1) << CpuFeatureDSPR2)
#endif
;
-extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features;
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
+#else
+extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2];
+#endif
Q_CORE_EXPORT void qDetectCpuFeatures();
-static inline uint qCpuFeatures()
+static inline quint64 qCpuFeatures()
{
- int features = qt_cpu_features.load();
+ quint64 features = qt_cpu_features[0].load();
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ features |= quint64(qt_cpu_features[1].load()) << 32;
+#endif
if (Q_UNLIKELY(features == 0)) {
qDetectCpuFeatures();
- features = qt_cpu_features.load();
+ features = qt_cpu_features[0].load();
+#ifndef Q_ATOMIC_INT64_IS_SUPPORTED
+ features |= quint64(qt_cpu_features[1].load()) << 32;
+#endif
Q_ASSUME(features != 0);
}
- return uint(features);
+ return features;
}
-#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature)))
+#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \
+ || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature)))
#ifdef Q_PROCESSOR_X86
// Bit scan functions for x86
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 8bb8953dde..e3a3cc79c6 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -2680,6 +2680,8 @@ bool operator==(const QString &s1, const QString &s2)
/*!
\overload operator==()
+ Returns \c true if this string is equal to \a other; otherwise
+ returns \c false.
*/
bool QString::operator==(QLatin1String other) const
{
@@ -2738,7 +2740,7 @@ bool operator<(const QString &s1, const QString &s2)
}
/*!
\overload operator<()
- \relates QString
+
Returns \c true if this string is lexically less than the parameter
string called \a other; otherwise returns \c false.
*/
@@ -2843,7 +2845,7 @@ bool QString::operator<(QLatin1String other) const
/*!
\overload operator>()
- \relates QString
+
Returns \c true if this string is lexically greater than the parameter
string \a other; otherwise returns \c false.
*/
@@ -3614,9 +3616,14 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const
}
/*!
- \overload count()
+ \overload count()
- Returns the number of occurrences of character \a ch in the string.
+ Returns the number of occurrences of character \a ch in the string.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ \sa contains(), indexOf()
*/
int QString::count(QChar ch, Qt::CaseSensitivity cs) const
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 1dbc005bca..3d41aeee18 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -421,7 +421,7 @@ QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
a.reserve(len);
QChar *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
- a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
+ a.resize(int(it - a.constData())); //may be smaller than len if there was conversion from utf8
return a;
}
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index 45ae23cdf5..900c8ff14e 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -310,7 +310,6 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
/*!
\typedef QTimeZone::OffsetDataList
- \relates QTimeZone
Synonym for QVector<OffsetData>.
*/
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index 32b76ee5bd..1991a462e9 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -205,11 +206,6 @@ DEFINEFUNC(dbus_bool_t , dbus_connection_send_with_reply, (DBusConnection
DBusPendingCall **pending_return,
int timeout_milliseconds),
(connection, message, pending_return, timeout_milliseconds), return)
-DEFINEFUNC(DBusMessage * , dbus_connection_send_with_reply_and_block, (DBusConnection *connection,
- DBusMessage *message,
- int timeout_milliseconds,
- DBusError *error),
- (connection, message, timeout_milliseconds, error), return)
DEFINEFUNC(void , dbus_connection_set_exit_on_disconnect, (DBusConnection *connection,
dbus_bool_t exit_on_disconnect),
(connection, exit_on_disconnect), )
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index a7c70bce70..d63a317612 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -34,6 +35,7 @@
#include "qdbusabstractinterface.h"
#include "qdbusabstractinterface_p.h"
+#include <qcoreapplication.h>
#include <qthread.h>
#include "qdbusargument.h"
@@ -41,6 +43,7 @@
#include "qdbusmessage_p.h"
#include "qdbusmetaobject_p.h"
#include "qdbusmetatype_p.h"
+#include "qdbusservicewatcher.h"
#include "qdbusutil_p.h"
#include <qdebug.h>
@@ -49,6 +52,29 @@
QT_BEGIN_NAMESPACE
+namespace {
+// ### Qt6: change to a regular QEvent (customEvent)
+// We need to use a QMetaCallEvent here because we can't override customEvent() in
+// Qt 5. Since QDBusAbstractInterface is meant to be derived from, the vtables of
+// classes in generated code will have a pointer to QObject::customEvent instead
+// of to QDBusAbstractInterface::customEvent.
+// See solution in Patch Set 1 of this change in the Qt Gerrit servers.
+// (https://codereview.qt-project.org/#/c/126384/1)
+class DisconnectRelayEvent : public QMetaCallEvent
+{
+public:
+ DisconnectRelayEvent(QObject *sender, const QMetaMethod &m)
+ : QMetaCallEvent(0, 0, Q_NULLPTR, sender, m.methodIndex())
+ {}
+
+ void placeMetaCall(QObject *object) Q_DECL_OVERRIDE
+ {
+ QDBusAbstractInterface *iface = static_cast<QDBusAbstractInterface *>(object);
+ QDBusAbstractInterfacePrivate::finishDisconnectNotify(iface, signalId());
+ }
+};
+}
+
static QDBusError checkIfValid(const QString &service, const QString &path,
const QString &interface, bool isDynamic, bool isPeer)
{
@@ -97,6 +123,15 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv
}
}
+void QDBusAbstractInterfacePrivate::initOwnerTracking()
+{
+ if (!isValid || !connection.isConnected() || !connectionPrivate()->shouldWatchService(service))
+ return;
+ QObject::connect(new QDBusServiceWatcher(service, connection, QDBusServiceWatcher::WatchForOwnerChange, q_func()),
+ SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+ q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+}
+
bool QDBusAbstractInterfacePrivate::canMakeCalls() const
{
// recheck only if we have a wildcard (i.e. empty) service or path
@@ -218,9 +253,8 @@ void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name,
Q_UNUSED(oldOwner);
Q_UNUSED(name);
//qDebug() << "QDBusAbstractInterfacePrivate serviceOwnerChanged" << name << oldOwner << newOwner;
- if (name == service) {
- currentOwner = newOwner;
- }
+ Q_ASSERT(name == service);
+ currentOwner = newOwner;
}
QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent)
@@ -285,19 +319,7 @@ int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void
QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent)
: QDBusAbstractInterfaceBase(d, parent)
{
- // keep track of the service owner
- if (d.isValid &&
- d.connection.isConnected()
- && !d.service.isEmpty()
- && !d.service.startsWith(QLatin1Char(':'))
- && d.connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode)
- d_func()->connection.connect(QDBusUtil::dbusService(), // service
- QString(), // path
- QDBusUtil::dbusInterface(), // interface
- QDBusUtil::nameOwnerChanged(),
- QStringList() << d.service,
- QString(), // signature
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ d.initOwnerTracking();
}
/*!
@@ -312,18 +334,7 @@ QDBusAbstractInterface::QDBusAbstractInterface(const QString &service, const QSt
con, false), parent)
{
// keep track of the service owner
- if (d_func()->isValid &&
- d_func()->connection.isConnected()
- && !service.isEmpty()
- && !service.startsWith(QLatin1Char(':'))
- && d_func()->connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode)
- d_func()->connection.connect(QDBusUtil::dbusService(), // service
- QString(), // path
- QDBusUtil::dbusInterface(), // interface
- QDBusUtil::nameOwnerChanged(),
- QStringList() << service,
- QString(), //signature
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ d_func()->initOwnerTracking();
}
/*!
@@ -617,22 +628,38 @@ void QDBusAbstractInterface::disconnectNotify(const QMetaMethod &signal)
if (!d->isValid)
return;
+ // disconnection is just resource freeing, so it can be delayed;
+ // let's do that later, after all the QObject mutexes have been unlocked.
+ QCoreApplication::postEvent(this, new DisconnectRelayEvent(this, signal));
+}
+
+/*!
+ \internal
+ Continues the disconnect notification from above.
+*/
+void QDBusAbstractInterfacePrivate::finishDisconnectNotify(QDBusAbstractInterface *ptr, int signalId)
+{
+ QDBusAbstractInterfacePrivate *d = ptr->d_func();
QDBusConnectionPrivate *conn = d->connectionPrivate();
- if (conn && signal.isValid() && !isSignalConnected(signal))
- return conn->disconnectRelay(d->service, d->path, d->interface,
- this, signal);
if (!conn)
return;
- // wildcard disconnecting, we need to figure out which of our signals are
- // no longer connected to anything
- const QMetaObject *mo = metaObject();
- int midx = QObject::staticMetaObject.methodCount();
- const int end = mo->methodCount();
- for ( ; midx < end; ++midx) {
- QMetaMethod mm = mo->method(midx);
- if (mm.methodType() == QMetaMethod::Signal && !isSignalConnected(mm))
- conn->disconnectRelay(d->service, d->path, d->interface, this, mm);
+ const QMetaObject *mo = ptr->metaObject();
+ QMetaMethod signal = signalId >= 0 ? mo->method(signalId) : QMetaMethod();
+ if (signal.isValid()) {
+ if (!ptr->isSignalConnected(signal))
+ return conn->disconnectRelay(d->service, d->path, d->interface,
+ ptr, signal);
+ } else {
+ // wildcard disconnecting, we need to figure out which of our signals are
+ // no longer connected to anything
+ int midx = QObject::staticMetaObject.methodCount();
+ const int end = mo->methodCount();
+ for ( ; midx < end; ++midx) {
+ QMetaMethod mm = mo->method(midx);
+ if (mm.methodType() == QMetaMethod::Signal && !ptr->isSignalConnected(mm))
+ conn->disconnectRelay(d->service, d->path, d->interface, ptr, mm);
+ }
}
}
diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h
index ba2bcadfb0..1d9290b746 100644
--- a/src/dbus/qdbusabstractinterface_p.h
+++ b/src/dbus/qdbusabstractinterface_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -78,6 +79,7 @@ public:
QDBusAbstractInterfacePrivate(const QString &serv, const QString &p,
const QString &iface, const QDBusConnection& con, bool dynamic);
virtual ~QDBusAbstractInterfacePrivate() { }
+ void initOwnerTracking();
bool canMakeCalls() const;
// these functions do not check if the property is valid
@@ -89,6 +91,8 @@ public:
{ return QDBusConnectionPrivate::d(connection); }
void _q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
+
+ static void finishDisconnectNotify(QDBusAbstractInterface *iface, int signalId);
};
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 0adb3dd748..e9196173ad 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -58,6 +59,41 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
+struct QDBusConnectionManager::ConnectionRequestData
+{
+ enum RequestType {
+ ConnectToStandardBus,
+ ConnectToBusByAddress,
+ ConnectToPeerByAddress
+ } type;
+
+ union {
+ QDBusConnection::BusType busType;
+ const QString *busAddress;
+ };
+ const QString *name;
+
+ QDBusConnectionPrivate *result;
+};
+
+QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::BusType type)
+{
+ Q_STATIC_ASSERT(int(QDBusConnection::SessionBus) + int(QDBusConnection::SystemBus) == 1);
+ Q_ASSERT(type == QDBusConnection::SessionBus || type == QDBusConnection::SystemBus);
+
+ if (!qdbus_loadLibDBus())
+ return 0;
+
+ QMutexLocker lock(&defaultBusMutex);
+ if (defaultBuses[type])
+ return defaultBuses[type];
+
+ QString name = QStringLiteral("qt_default_session_bus");
+ if (type == QDBusConnection::SystemBus)
+ name = QStringLiteral("qt_default_system_bus");
+ return defaultBuses[type] = connectToBus(type, name);
+}
+
QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
{
return connectionHash.value(name, 0);
@@ -68,7 +104,7 @@ void QDBusConnectionManager::removeConnection(const QString &name)
QDBusConnectionPrivate *d = 0;
d = connectionHash.take(name);
if (d && !d->ref.deref())
- d->deleteYourself();
+ d->deleteLater();
// Static objects may be keeping the connection open.
// However, it is harmless to have outstanding references to a connection that is
@@ -77,17 +113,22 @@ void QDBusConnectionManager::removeConnection(const QString &name)
// ### Output a warning if connections are being used after they have been removed.
}
+QDBusConnectionManager::QDBusConnectionManager()
+{
+ connect(this, &QDBusConnectionManager::connectionRequested,
+ this, &QDBusConnectionManager::executeConnectionRequest, Qt::BlockingQueuedConnection);
+ connect(this, &QDBusConnectionManager::serverRequested,
+ this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection);
+ moveToThread(this); // ugly, don't do this in other projects
+
+ defaultBuses[0] = defaultBuses[1] = Q_NULLPTR;
+ start();
+}
+
QDBusConnectionManager::~QDBusConnectionManager()
{
- for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
- it != connectionHash.constEnd(); ++it) {
- QDBusConnectionPrivate *d = it.value();
- if (!d->ref.deref())
- d->deleteYourself();
- else
- d->closeConnection();
- }
- connectionHash.clear();
+ quit();
+ wait();
}
QDBusConnectionManager* QDBusConnectionManager::instance()
@@ -106,6 +147,122 @@ void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionP
c->name = name;
}
+void QDBusConnectionManager::run()
+{
+ exec();
+
+ // cleanup:
+ QMutexLocker locker(&mutex);
+ for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
+ it != connectionHash.constEnd(); ++it) {
+ QDBusConnectionPrivate *d = it.value();
+ if (!d->ref.deref()) {
+ delete d;
+ } else {
+ d->closeConnection();
+ d->moveToThread(Q_NULLPTR); // allow it to be deleted in another thread
+ }
+ }
+ connectionHash.clear();
+
+ // allow deletion from any thread without warning
+ moveToThread(Q_NULLPTR);
+}
+
+QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::BusType type, const QString &name)
+{
+ ConnectionRequestData data;
+ data.type = ConnectionRequestData::ConnectToStandardBus;
+ data.busType = type;
+ data.name = &name;
+
+ emit connectionRequested(&data);
+ return data.result;
+}
+
+QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(const QString &address, const QString &name)
+{
+ ConnectionRequestData data;
+ data.type = ConnectionRequestData::ConnectToBusByAddress;
+ data.busAddress = &address;
+ data.name = &name;
+
+ emit connectionRequested(&data);
+ return data.result;
+}
+
+QDBusConnectionPrivate *QDBusConnectionManager::connectToPeer(const QString &address, const QString &name)
+{
+ ConnectionRequestData data;
+ data.type = ConnectionRequestData::ConnectToPeerByAddress;
+ data.busAddress = &address;
+ data.name = &name;
+
+ emit connectionRequested(&data);
+ return data.result;
+}
+
+void QDBusConnectionManager::executeConnectionRequest(QDBusConnectionManager::ConnectionRequestData *data)
+{
+ QMutexLocker locker(&mutex);
+ const QString &name = *data->name;
+ QDBusConnectionPrivate *&d = data->result;
+
+ // check if the connection exists by name
+ d = connection(name);
+ if (d || name.isEmpty())
+ return;
+
+ d = new QDBusConnectionPrivate;
+ DBusConnection *c = 0;
+ QDBusErrorInternal error;
+ switch (data->type) {
+ case ConnectionRequestData::ConnectToStandardBus:
+ switch (data->busType) {
+ case QDBusConnection::SystemBus:
+ c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error);
+ break;
+ case QDBusConnection::SessionBus:
+ c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error);
+ break;
+ case QDBusConnection::ActivationBus:
+ c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error);
+ break;
+ }
+ break;
+
+ case ConnectionRequestData::ConnectToBusByAddress:
+ case ConnectionRequestData::ConnectToPeerByAddress:
+ c = q_dbus_connection_open_private(data->busAddress->toUtf8().constData(), error);
+ if (c && data->type == ConnectionRequestData::ConnectToBusByAddress) {
+ // register on the bus
+ if (!q_dbus_bus_register(c, error)) {
+ q_dbus_connection_unref(c);
+ c = 0;
+ }
+ }
+ break;
+ }
+
+ setConnection(name, d);
+ if (data->type == ConnectionRequestData::ConnectToPeerByAddress) {
+ d->setPeer(c, error);
+ } else {
+ // create the bus service
+ // will lock in QDBusConnectionPrivate::connectRelay()
+ d->setConnection(c, error);
+ d->createBusService();
+ }
+}
+
+void QDBusConnectionManager::createServer(const QString &address, void *server)
+{
+ QDBusErrorInternal error;
+ QDBusConnectionPrivate *d = new QDBusConnectionPrivate;
+ d->setServer(static_cast<QDBusServer *>(server),
+ q_dbus_server_listen(address.toUtf8().constData(), error), error);
+}
+
/*!
\class QDBusConnection
\inmodule QtDBus
@@ -268,7 +425,7 @@ QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd)
QDBusConnection::~QDBusConnection()
{
if (d && !d->ref.deref())
- d->deleteYourself();
+ d->deleteLater();
}
/*!
@@ -283,7 +440,7 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
if (other.d)
other.d->ref.ref();
if (d && !d->ref.deref())
- d->deleteYourself();
+ d->deleteLater();
d = other.d;
return *this;
}
@@ -295,44 +452,11 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
*/
QDBusConnection QDBusConnection::connectToBus(BusType type, 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;
- DBusConnection *c = 0;
- QDBusErrorInternal error;
- switch (type) {
- case SystemBus:
- c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error);
- break;
- case SessionBus:
- c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error);
- break;
- case ActivationBus:
- c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error);
- break;
- }
- d->setConnection(c, error); //setConnection does the error handling for us
-
- _q_manager()->setConnection(name, d);
-
- QDBusConnection retval(d);
-
- // create the bus service
- // will lock in QDBusConnectionPrivate::connectRelay()
- d->setBusService(retval);
-
- return retval;
+ return QDBusConnection(_q_manager()->connectToBus(type, name));
}
/*!
@@ -342,39 +466,11 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
QDBusConnection QDBusConnection::connectToBus(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;
- // setConnection does the error handling for us
- QDBusErrorInternal error;
- DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
- if (c) {
- if (!q_dbus_bus_register(c, error)) {
- q_dbus_connection_unref(c);
- c = 0;
- }
- }
- d->setConnection(c, error);
- _q_manager()->setConnection(name, d);
-
- QDBusConnection retval(d);
-
- // create the bus service
- // will lock in QDBusConnectionPrivate::connectRelay()
- d->setBusService(retval);
-
- return retval;
+ return QDBusConnection(_q_manager()->connectToBus(address, name));
}
/*!
\since 4.8
@@ -385,30 +481,11 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
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;
+ return QDBusConnection(_q_manager()->connectToPeer(address, name));
}
/*!
@@ -467,7 +544,7 @@ bool QDBusConnection::send(const QDBusMessage &message) const
d->lastError = err;
return false;
}
- return d->send(message) != 0;
+ return d->send(message);
}
/*!
@@ -688,7 +765,6 @@ bool QDBusConnection::connect(const QString &service, const QString &path, const
return false;
}
- QDBusWriteLocker locker(ConnectAction, d);
return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot);
}
@@ -744,7 +820,6 @@ bool QDBusConnection::disconnect(const QString &service, const QString &path, co
if (interface.isEmpty() && name.isEmpty())
return false;
- QDBusWriteLocker locker(DisconnectAction, d);
return d->disconnectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot);
}
@@ -929,7 +1004,7 @@ QObject *QDBusConnection::objectRegisteredAt(const QString &path) const
*/
QDBusConnectionInterface *QDBusConnection::interface() const
{
- if (!d)
+ if (!d || d->mode != QDBusConnectionPrivate::ClientMode)
return 0;
return d->busService;
}
@@ -1052,35 +1127,6 @@ bool QDBusConnection::unregisterService(const QString &serviceName)
return false;
}
-static const char _q_sessionBusName[] = "qt_default_session_bus";
-static const char _q_systemBusName[] = "qt_default_system_bus";
-
-class QDBusDefaultConnection: public QDBusConnection
-{
- const char *ownName;
-public:
- inline QDBusDefaultConnection(BusType type, const char *name)
- : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
- {
- // make sure this connection is running on the main thread
- QCoreApplication *instance = QCoreApplication::instance();
- if (!instance) {
- qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.",
- type == SessionBus ? "session" : type == SystemBus ? "system" : "generic");
- } else if (QDBusConnectionPrivate::d(*this)) {
- QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread());
- }
- }
-
- inline ~QDBusDefaultConnection()
- { disconnectFromBus(QString::fromLatin1(ownName)); }
-};
-
-Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus,
- (QDBusConnection::SessionBus, _q_sessionBusName))
-Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus,
- (QDBusConnection::SystemBus, _q_systemBusName))
-
/*!
\fn QDBusConnection QDBusConnection::sessionBus()
@@ -1090,7 +1136,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus,
*/
QDBusConnection QDBusConnection::sessionBus()
{
- return *_q_sessionBus();
+ return QDBusConnection(_q_manager()->busConnection(SessionBus));
}
/*!
@@ -1102,7 +1148,7 @@ QDBusConnection QDBusConnection::sessionBus()
*/
QDBusConnection QDBusConnection::systemBus()
{
- return *_q_systemBus();
+ return QDBusConnection(_q_manager()->busConnection(SystemBus));
}
#if QT_DEPRECATED_SINCE(5,5)
@@ -1123,8 +1169,10 @@ QDBusConnection QDBusConnection::sender()
/*!
\internal
*/
-void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection)
+void QDBusConnectionPrivate::createBusService()
{
+ Q_ASSERT(mode == ClientMode);
+ QDBusConnection connection(this);
busService = new QDBusConnectionInterface(connection, this);
ref.deref(); // busService has increased the refcounting to us
// avoid cyclic refcounting
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 752ca9c37a..49c7564566 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -62,6 +63,7 @@
#include "qdbus_symbols_p.h"
#include <qdbusmessage.h>
+#include <qdbusservicewatcher.h> // for the WatchMode enum
#ifndef QT_NO_DBUS
@@ -79,6 +81,7 @@ struct QDBusMetaObject;
class QDBusAbstractInterface;
class QDBusConnectionInterface;
class QDBusPendingCallPrivate;
+class QDBusServer;
#ifndef QT_BOOTSTRAPPED
@@ -187,17 +190,22 @@ public:
// public methods are entry points from other objects
explicit QDBusConnectionPrivate(QObject *parent = 0);
~QDBusConnectionPrivate();
- void deleteYourself();
- void setBusService(const QDBusConnection &connection);
+ void createBusService();
void setPeer(DBusConnection *connection, const QDBusErrorInternal &error);
void setConnection(DBusConnection *connection, const QDBusErrorInternal &error);
- void setServer(DBusServer *server, const QDBusErrorInternal &error);
+ void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error);
void closeConnection();
QString getNameOwner(const QString &service);
- int send(const QDBusMessage &message);
+ bool shouldWatchService(const QString &service);
+ void watchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
+ QObject *obj, const char *member);
+ void unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode,
+ QObject *obj, const char *member);
+
+ bool send(const QDBusMessage &message);
QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1);
QDBusMessage sendWithReplyLocal(const QDBusMessage &message);
QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
@@ -205,8 +213,6 @@ public:
bool connectSignal(const QString &service, const QString &path, const QString& interface,
const QString &name, const QStringList &argumentMatch, const QString &signature,
QObject *receiver, const char *slot);
- void connectSignal(const QString &key, const SignalHook &hook);
- SignalHookHash::Iterator disconnectSignal(SignalHookHash::Iterator &it);
bool disconnectSignal(const QString &service, const QString &path, const QString& interface,
const QString &name, const QStringList &argumentMatch, const QString &signature,
QObject *receiver, const char *slot);
@@ -222,16 +228,12 @@ public:
void unregisterService(const QString &serviceName);
bool handleMessage(const QDBusMessage &msg);
- void waitForFinished(QDBusPendingCallPrivate *pcall);
QDBusMetaObject *findMetaObject(const QString &service, const QString &path,
const QString &interface, QDBusError &error);
void postEventToThread(int action, QObject *target, QEvent *event);
- inline void serverConnection(const QDBusConnection &connection)
- { emit newServerConnection(connection); }
-
private:
void checkThread();
bool handleError(const QDBusErrorInternal &error);
@@ -245,16 +247,20 @@ private:
bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg);
bool activateCall(QObject *object, int flags, const QDBusMessage &msg);
+ void sendInternal(QDBusPendingCallPrivate *pcall, void *msg, int timeout);
void sendError(const QDBusMessage &msg, QDBusError::ErrorType code);
void deliverCall(QObject *object, int flags, const QDBusMessage &msg,
const QVector<int> &metaTypes, int slotIdx);
+ SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it);
+
bool isServiceRegisteredByThread(const QString &serviceName);
QString getNameOwnerNoCache(const QString &service);
+ void _q_newConnection(QDBusConnectionPrivate *newConnection);
+
protected:
- void customEvent(QEvent *e) Q_DECL_OVERRIDE;
void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
public slots:
@@ -264,6 +270,8 @@ public slots:
void socketWrite(int);
void objectDestroyed(QObject *o);
void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args);
+ void addSignalHook(const QString &key, const SignalHook &hook);
+ bool removeSignalHook(const QString &key, const SignalHook &hook);
private slots:
void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner);
@@ -271,9 +279,13 @@ private slots:
void unregisterServiceNoLock(const QString &serviceName);
signals:
+ void dispatchStatusChanged();
+ void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1);
+ void signalNeedsConnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook);
+ bool signalNeedsDisconnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook);
void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message);
- void newServerConnection(const QDBusConnection &connection);
+ void newServerConnection(QDBusConnectionPrivate *newConnection);
public:
QAtomicInt ref;
@@ -283,13 +295,18 @@ public:
QStringList serverConnectionNames;
ConnectionMode mode;
- QDBusConnectionInterface *busService;
+ union {
+ QDBusConnectionInterface *busService;
+ QDBusServer *serverObject;
+ };
// the dispatch lock protects everything related to the DBusConnection or DBusServer
// including the timeouts and watches
QMutex dispatchLock;
- DBusConnection *connection;
- DBusServer *server;
+ union {
+ DBusConnection *connection;
+ DBusServer *server;
+ };
WatcherHash watchers;
TimeoutHash timeouts;
PendingTimeoutList timeoutsPendingAdd;
@@ -334,6 +351,7 @@ public:
friend class QDBusActivateObjectEvent;
friend class QDBusCallDeliveryEvent;
+ friend class QDBusServer;
};
// in qdbusmisc.cpp
diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h
index fc0bb515e5..3f815fdcd7 100644
--- a/src/dbus/qdbusconnectionmanager_p.h
+++ b/src/dbus/qdbusconnectionmanager_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -47,26 +48,47 @@
#define QDBUSCONNECTIONMANAGER_P_H
#include "qdbusconnection_p.h"
+#include "private/qthread_p.h"
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
-class QDBusConnectionManager
+class QDBusConnectionManager : public QDaemonThread
{
+ Q_OBJECT
+ struct ConnectionRequestData;
public:
- QDBusConnectionManager() {}
+ QDBusConnectionManager();
~QDBusConnectionManager();
static QDBusConnectionManager* instance();
+ QDBusConnectionPrivate *busConnection(QDBusConnection::BusType type);
QDBusConnectionPrivate *connection(const QString &name) const;
void removeConnection(const QString &name);
void setConnection(const QString &name, QDBusConnectionPrivate *c);
+ QDBusConnectionPrivate *connectToBus(QDBusConnection::BusType type, const QString &name);
+ QDBusConnectionPrivate *connectToBus(const QString &address, const QString &name);
+ QDBusConnectionPrivate *connectToPeer(const QString &address, const QString &name);
mutable QMutex mutex;
+
+signals:
+ void connectionRequested(ConnectionRequestData *);
+ void serverRequested(const QString &address, void *server);
+
+protected:
+ void run() Q_DECL_OVERRIDE;
+
private:
+ void executeConnectionRequest(ConnectionRequestData *data);
+ void createServer(const QString &address, void *server);
+
QHash<QString, QDBusConnectionPrivate *> connectionHash;
+ QMutex defaultBusMutex;
+ QDBusConnectionPrivate *defaultBuses[2];
+
mutable QMutex senderMutex;
QString senderName; // internal; will probably change
};
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 22c1a3e363..c465706913 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -52,6 +53,7 @@
#include "qdbusmetatype_p.h"
#include "qdbusabstractadaptor.h"
#include "qdbusabstractadaptor_p.h"
+#include "qdbusserver.h"
#include "qdbusutil_p.h"
#include "qdbusvirtualobject.h"
#include "qdbusmessage_p.h"
@@ -92,12 +94,7 @@ static inline QDebug operator<<(QDebug dbg, const QDBusConnectionPrivate *conn)
<< "ptr=" << (const void*)conn
<< ", name=" << conn->name
<< ", baseService=" << conn->baseService
- << ", thread=";
- if (conn->thread() == QThread::currentThread())
- dbg.nospace() << "same thread";
- else
- dbg.nospace() << conn->thread();
- dbg.nospace() << ')';
+ << ')';
return dbg;
}
@@ -131,7 +128,6 @@ extern "C" {
// libdbus-1 callbacks
-static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms);
static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
{
Q_ASSERT(timeout);
@@ -140,29 +136,17 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
// qDebug("addTimeout %d", q_dbus_timeout_get_interval(timeout));
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+ Q_ASSERT(QThread::currentThread() == d->thread());
- if (!q_dbus_timeout_get_enabled(timeout))
- return true;
+ // we may get called from qDBusToggleTimeout
+ if (Q_UNLIKELY(!q_dbus_timeout_get_enabled(timeout)))
+ return false;
QDBusDispatchLocker locker(AddTimeoutAction, d);
- if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
- // correct thread
- return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout));
- } else {
- // wrong thread: sync back
- QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent;
- ev->subtype = QDBusConnectionCallbackEvent::AddTimeout;
- d->timeoutsPendingAdd.append(qMakePair(timeout, q_dbus_timeout_get_interval(timeout)));
- d->postEventToThread(AddTimeoutAction, d, ev);
- return true;
- }
-}
-
-static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms)
-{
Q_ASSERT(d->timeouts.key(timeout, 0) == 0);
- int timerId = d->startTimer(ms);
+ int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout));
+ Q_ASSERT_X(timerId, "QDBusConnection", "Failed to start a timer");
if (!timerId)
return false;
@@ -178,33 +162,14 @@ static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data)
// qDebug("removeTimeout");
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+ Q_ASSERT(QThread::currentThread() == d->thread());
QDBusDispatchLocker locker(RemoveTimeoutAction, d);
- // is it pending addition?
- QDBusConnectionPrivate::PendingTimeoutList::iterator pit = d->timeoutsPendingAdd.begin();
- while (pit != d->timeoutsPendingAdd.end()) {
- if (pit->first == timeout)
- pit = d->timeoutsPendingAdd.erase(pit);
- else
- ++pit;
- }
-
- // is it a running timer?
- bool correctThread = QCoreApplication::instance() && QThread::currentThread() == d->thread();
QDBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin();
while (it != d->timeouts.end()) {
if (it.value() == timeout) {
- if (correctThread) {
- // correct thread
- d->killTimer(it.key());
- } else {
- // incorrect thread or no application, post an event for later
- QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent;
- ev->subtype = QDBusConnectionCallbackEvent::KillTimer;
- ev->timerId = it.key();
- d->postEventToThread(KillTimerAction, d, ev);
- }
+ d->killTimer(it.key());
it = d->timeouts.erase(it);
break;
} else {
@@ -224,52 +189,33 @@ static void qDBusToggleTimeout(DBusTimeout *timeout, void *data)
qDBusAddTimeout(timeout, data);
}
-static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd);
static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
{
Q_ASSERT(watch);
Q_ASSERT(data);
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+ Q_ASSERT(QThread::currentThread() == d->thread());
int flags = q_dbus_watch_get_flags(watch);
int fd = q_dbus_watch_get_unix_fd(watch);
- if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
- return qDBusRealAddWatch(d, watch, flags, fd);
- } else {
- QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent;
- ev->subtype = QDBusConnectionCallbackEvent::AddWatch;
- ev->watch = watch;
- ev->fd = fd;
- ev->extra = flags;
- d->postEventToThread(AddWatchAction, d, ev);
- return true;
- }
-}
-
-static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd)
-{
QDBusConnectionPrivate::Watcher watcher;
QDBusDispatchLocker locker(AddWatchAction, d);
if (flags & DBUS_WATCH_READABLE) {
//qDebug("addReadWatch %d", fd);
watcher.watch = watch;
- if (QCoreApplication::instance()) {
- watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d);
- watcher.read->setEnabled(q_dbus_watch_get_enabled(watch));
- d->connect(watcher.read, SIGNAL(activated(int)), SLOT(socketRead(int)));
- }
+ watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d);
+ watcher.read->setEnabled(q_dbus_watch_get_enabled(watch));
+ d->connect(watcher.read, SIGNAL(activated(int)), SLOT(socketRead(int)));
}
if (flags & DBUS_WATCH_WRITABLE) {
//qDebug("addWriteWatch %d", fd);
watcher.watch = watch;
- if (QCoreApplication::instance()) {
- watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d);
- watcher.write->setEnabled(q_dbus_watch_get_enabled(watch));
- d->connect(watcher.write, SIGNAL(activated(int)), SLOT(socketWrite(int)));
- }
+ watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d);
+ watcher.write->setEnabled(q_dbus_watch_get_enabled(watch));
+ d->connect(watcher.write, SIGNAL(activated(int)), SLOT(socketWrite(int)));
}
d->watchers.insertMulti(fd, watcher);
@@ -284,23 +230,15 @@ static void qDBusRemoveWatch(DBusWatch *watch, void *data)
//qDebug("remove watch");
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+ Q_ASSERT(QThread::currentThread() == d->thread());
int fd = q_dbus_watch_get_unix_fd(watch);
QDBusDispatchLocker locker(RemoveWatchAction, d);
QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
while (i != d->watchers.end() && i.key() == fd) {
if (i.value().watch == watch) {
- if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
- // correct thread, delete the socket notifiers
- delete i.value().read;
- delete i.value().write;
- } else {
- // incorrect thread or no application, use delete later
- if (i->read)
- i->read->deleteLater();
- if (i->write)
- i->write->deleteLater();
- }
+ delete i.value().read;
+ delete i.value().write;
i = d->watchers.erase(i);
} else {
++i;
@@ -308,28 +246,15 @@ static void qDBusRemoveWatch(DBusWatch *watch, void *data)
}
}
-static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd);
static void qDBusToggleWatch(DBusWatch *watch, void *data)
{
Q_ASSERT(watch);
Q_ASSERT(data);
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+ Q_ASSERT(QThread::currentThread() == d->thread());
int fd = q_dbus_watch_get_unix_fd(watch);
- if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) {
- qDBusRealToggleWatch(d, watch, fd);
- } else {
- QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent;
- ev->subtype = QDBusConnectionCallbackEvent::ToggleWatch;
- ev->watch = watch;
- ev->fd = fd;
- d->postEventToThread(ToggleWatchAction, d, ev);
- }
-}
-
-static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd)
-{
QDBusDispatchLocker locker(ToggleWatchAction, d);
QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd);
@@ -355,18 +280,8 @@ static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchSt
Q_ASSERT(connection);
Q_UNUSED(connection);
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
-
- static int slotId; // 0 is QObject::deleteLater()
- if (!slotId) {
- // it's ok to do this: there's no race condition because the store is atomic
- // and we always set to the same value
- slotId = QDBusConnectionPrivate::staticMetaObject.indexOfSlot("doDispatch()");
- }
-
- //qDBusDebug() << "Updating dispatcher status" << slotId;
if (new_status == DBUS_DISPATCH_DATA_REMAINS)
- QDBusConnectionPrivate::staticMetaObject.method(slotId).
- invoke(d, Qt::QueuedConnection);
+ emit d->dispatchStatusChanged();
}
static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data)
@@ -393,10 +308,14 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
QDBusErrorInternal error;
newConnection->setPeer(connection, error);
- QDBusConnection retval = QDBusConnectionPrivate::q(newConnection);
+ // this is a queued connection and will resume in the QDBusServer's thread
+ emit serverConnection->newServerConnection(newConnection);
+}
- // make QDBusServer emit the newConnection signal
- serverConnection->serverConnection(retval);
+void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection)
+{
+ Q_ASSERT(mode == ServerMode);
+ emit serverObject->newConnection(QDBusConnectionPrivate::q(newConnection));
}
} // extern "C"
@@ -521,11 +440,27 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
return 0;
}
-static bool shouldWatchService(const QString &service)
+static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
{
- return !service.isEmpty() && !service.startsWith(QLatin1Char(':'));
+ QStringList matchArgs;
+ matchArgs << service;
+
+ switch (mode) {
+ case QDBusServiceWatcher::WatchForOwnerChange:
+ break;
+
+ case QDBusServiceWatcher::WatchForRegistration:
+ matchArgs << QString::fromLatin1("", 0);
+ break;
+
+ case QDBusServiceWatcher::WatchForUnregistration:
+ matchArgs << QString() << QString::fromLatin1("", 0);
+ break;
+ }
+ return matchArgs;
}
+
extern Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook);
void qDBusAddSpyHook(QDBusSpyHook hook)
{
@@ -1009,7 +944,7 @@ extern bool qDBusInitThreads();
QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
: QObject(p), ref(1), capabilities(0), mode(InvalidMode), busService(0),
- dispatchLock(QMutex::Recursive), connection(0), server(0),
+ dispatchLock(QMutex::Recursive), connection(0),
rootNode(QString(QLatin1Char('/'))),
anonymousAuthenticationAllowed(false)
{
@@ -1024,6 +959,14 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
#endif
QDBusMetaTypeId::init();
+ connect(this, &QDBusConnectionPrivate::dispatchStatusChanged,
+ this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
+ connect(this, &QDBusConnectionPrivate::messageNeedsSending,
+ this, &QDBusConnectionPrivate::sendInternal);
+ connect(this, &QDBusConnectionPrivate::signalNeedsConnecting,
+ this, &QDBusConnectionPrivate::addSignalHook, Qt::BlockingQueuedConnection);
+ connect(this, &QDBusConnectionPrivate::signalNeedsDisconnecting,
+ this, &QDBusConnectionPrivate::removeSignalHook, Qt::BlockingQueuedConnection);
rootNode.flags = 0;
@@ -1043,50 +986,38 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
"Timer and socket errors will follow and the program will probably crash",
qPrintable(name));
- if (mode == ClientMode) {
- // the bus service object holds a reference back to us;
- // we need to destroy it before we finish destroying ourselves
- Q_ASSERT(ref.load() == 0);
- QObject *obj = (QObject *)busService;
- disconnect(obj, Q_NULLPTR, this, Q_NULLPTR);
- delete obj;
- }
-
closeConnection();
rootNode.children.clear(); // free resources
qDeleteAll(cachedMetaObjects);
- if (server)
- q_dbus_server_unref(server);
- if (connection)
- q_dbus_connection_unref(connection);
-
- connection = 0;
- server = 0;
-}
-
-void QDBusConnectionPrivate::deleteYourself()
-{
- if (thread() && thread() != QThread::currentThread()) {
- // last reference dropped while not in the correct thread
- // ask the correct thread to delete
-
- // note: since we're posting an event to another thread, we
- // must consider deleteLater() to take effect immediately
- deleteLater();
- } else {
- delete this;
+ if (mode == ClientMode || mode == PeerMode) {
+ // the bus service object holds a reference back to us;
+ // we need to destroy it before we finish destroying ourselves
+ Q_ASSERT(ref.load() == 0);
+ QObject *obj = (QObject *)busService;
+ if (obj) {
+ disconnect(obj, Q_NULLPTR, this, Q_NULLPTR);
+ delete obj;
+ }
+ if (connection)
+ q_dbus_connection_unref(connection);
+ connection = 0;
+ } else if (mode == ServerMode) {
+ if (server)
+ q_dbus_server_unref(server);
+ server = 0;
}
}
void QDBusConnectionPrivate::closeConnection()
{
QDBusWriteLocker locker(CloseConnectionAction, this);
+ qDBusDebug() << this << "Disconnected";
ConnectionMode oldMode = mode;
mode = InvalidMode; // prevent reentrancy
baseService.clear();
- if (server) {
+ if (oldMode == ServerMode && server) {
q_dbus_server_disconnect(server);
q_dbus_server_free_data_slot(&server_slot);
}
@@ -1101,19 +1032,12 @@ void QDBusConnectionPrivate::closeConnection()
}
qDeleteAll(pendingCalls);
-
- qDBusDebug() << this << "Disconnected";
}
void QDBusConnectionPrivate::checkThread()
{
- if (!thread()) {
- if (QCoreApplication::instance())
- moveToThread(QCoreApplication::instance()->thread());
- else
- qWarning("The thread that had QDBusConnection('%s') has died and there is no main thread",
- qPrintable(name));
- }
+ Q_ASSERT(thread() == QDBusConnectionManager::instance());
+ Q_ASSERT(QThread::currentThread() == thread());
}
bool QDBusConnectionPrivate::handleError(const QDBusErrorInternal &error)
@@ -1139,40 +1063,6 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
doDispatch();
}
-void QDBusConnectionPrivate::customEvent(QEvent *e)
-{
- Q_ASSERT(e->type() == QEvent::User);
-
- QDBusConnectionCallbackEvent *ev = static_cast<QDBusConnectionCallbackEvent *>(e);
- QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype),
- QDBusLockerBase::BeforeDeliver, this);
- switch (ev->subtype)
- {
- case QDBusConnectionCallbackEvent::AddTimeout: {
- QDBusDispatchLocker locker(RealAddTimeoutAction, this);
- while (!timeoutsPendingAdd.isEmpty()) {
- QPair<DBusTimeout *, int> entry = timeoutsPendingAdd.takeFirst();
- qDBusRealAddTimeout(this, entry.first, entry.second);
- }
- break;
- }
-
- case QDBusConnectionCallbackEvent::KillTimer:
- killTimer(ev->timerId);
- break;
-
- case QDBusConnectionCallbackEvent::AddWatch:
- qDBusRealAddWatch(this, ev->watch, ev->extra, ev->fd);
- break;
-
- case QDBusConnectionCallbackEvent::ToggleWatch:
- qDBusRealToggleWatch(this, ev->watch, ev->fd);
- break;
- }
- QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype),
- QDBusLockerBase::AfterDeliver, this);
-}
-
void QDBusConnectionPrivate::doDispatch()
{
QDBusDispatchLocker locker(DoDispatchAction, this);
@@ -1217,7 +1107,7 @@ void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
SignalHookHash::iterator sit = signalHooks.begin();
while (sit != signalHooks.end()) {
if (static_cast<QObject *>(sit.value().obj) == obj)
- sit = disconnectSignal(sit);
+ sit = removeSignalHookNoLock(sit);
else
++sit;
}
@@ -1598,10 +1488,7 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
for ( ; it != end && it.key() == key; ++it) {
const SignalHook &hook = it.value();
if (!hook.service.isEmpty()) {
- const QString owner =
- shouldWatchService(hook.service) ?
- watchedServices.value(hook.service).owner :
- hook.service;
+ QString owner = watchedServices.value(hook.service, WatchedServiceData(hook.service)).owner;
if (owner != msg.service())
continue;
}
@@ -1659,9 +1546,11 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
handleSignal(key, msg); // third try
}
-void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &error)
+void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const QDBusErrorInternal &error)
{
mode = ServerMode;
+ serverObject = object;
+ object->d = this;
if (!s) {
handleError(error);
return;
@@ -1789,6 +1678,15 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
Q_ASSERT(hook.midx != -1);
signalHooks.insert(QLatin1String("NameLost:" DBUS_INTERFACE_DBUS), hook);
+ // And initialize the hook for the NameOwnerChanged signal;
+ // we don't use connectSignal here because the rules are added by connectSignal on a per-need basis
+ hook.params.clear();
+ hook.params.reserve(4);
+ hook.params << QMetaType::Void << QVariant::String << QVariant::String << QVariant::String;
+ hook.midx = staticMetaObject.indexOfSlot("serviceOwnerChangedNoLock(QString,QString,QString)");
+ Q_ASSERT(hook.midx != -1);
+ signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook);
+
qDBusDebug() << this << ": connected successfully";
// schedule a dispatch:
@@ -1805,34 +1703,6 @@ static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
}
}
-void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall)
-{
- Q_ASSERT(pcall->pending);
- //Q_ASSERT(pcall->mutex.isLocked()); // there's no such function
-
- if (pcall->waitingForFinished) {
- // another thread is already waiting
- pcall->waitForFinishedCondition.wait(&pcall->mutex);
- } else {
- pcall->waitingForFinished = true;
- pcall->mutex.unlock();
-
- {
- QDBusDispatchLocker locker(PendingCallBlockAction, this);
- q_dbus_pending_call_block(pcall->pending);
- // QDBusConnectionPrivate::processFinishedCall() is called automatically
- }
- pcall->mutex.lock();
-
- if (pcall->pending) {
- q_dbus_pending_call_unref(pcall->pending);
- pcall->pending = 0;
- }
-
- pcall->waitForFinishedCondition.wakeAll();
- }
-}
-
void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
{
QDBusConnectionPrivate *connection = const_cast<QDBusConnectionPrivate *>(call->connection);
@@ -1848,7 +1718,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities);
q_dbus_message_unref(reply);
}
- qDBusDebug() << connection << "got message reply (async):" << msg;
+ qDBusDebug() << connection << "got message reply:" << msg;
// Check if the reply has the expected signature
call->checkReceivedSignature();
@@ -1870,17 +1740,18 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
qDBusDebug() << "Deliver failed!";
}
- if (call->pending && !call->waitingForFinished) {
+ if (call->pending) {
q_dbus_pending_call_unref(call->pending);
call->pending = 0;
}
- locker.unlock();
-
// Are there any watchers?
if (call->watcherHelper)
call->watcherHelper->emitSignals(msg, call->sentMessage);
+ call->waitForFinishedCondition.wakeAll();
+ locker.unlock();
+
if (msg.type() == QDBusMessage::ErrorMessage)
emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage);
@@ -1888,10 +1759,10 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
delete call;
}
-int QDBusConnectionPrivate::send(const QDBusMessage& message)
+bool QDBusConnectionPrivate::send(const QDBusMessage& message)
{
if (QDBusMessagePrivate::isLocal(message))
- return -1; // don't send; the reply will be retrieved by the caller
+ return true; // don't send; the reply will be retrieved by the caller
// through the d_ptr->localReply link
QDBusError error;
@@ -1915,24 +1786,13 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message)
"invalid", qPrintable(message.service()),
qPrintable(error.message()));
lastError = error;
- return 0;
+ return false;
}
q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything
-
qDBusDebug() << this << "sending message (no reply):" << message;
- checkThread();
- bool isOk;
- {
- QDBusDispatchLocker locker(SendMessageAction, this);
- isOk = q_dbus_connection_send(connection, msg, 0);
- }
- int serial = 0;
- if (isOk)
- serial = q_dbus_message_get_serial(msg);
-
- q_dbus_message_unref(msg);
- return serial;
+ emit messageNeedsSending(Q_NULLPTR, msg);
+ return true;
}
// small helper to note long running blocking dbus calls.
@@ -2024,49 +1884,12 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
{
QDBusBlockingCallWatcher watcher(message);
- checkThread();
- if ((sendMode == QDBus::BlockWithGui || sendMode == QDBus::Block)
- && isServiceRegisteredByThread(message.service()))
- // special case for synchronous local calls
- return sendWithReplyLocal(message);
-
- if (!QCoreApplication::instance() || sendMode == QDBus::Block) {
- QDBusError err;
- DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &err);
- if (!msg) {
- qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
- qPrintable(message.service()), qPrintable(message.path()),
- qPrintable(message.interface()), qPrintable(message.member()),
- qPrintable(err.message()));
- lastError = err;
- return QDBusMessage::createError(err);
- }
-
- qDBusDebug() << this << "sending message (blocking):" << message;
- QDBusErrorInternal error;
- DBusMessage *reply;
- {
- QDBusDispatchLocker locker(SendWithReplyAndBlockAction, this);
- reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error);
- }
-
- q_dbus_message_unref(msg);
-
- if (!!error) {
- lastError = err = error;
- return QDBusMessage::createError(err);
- }
+ QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout);
+ Q_ASSERT(pcall);
- QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply, capabilities);
- q_dbus_message_unref(reply);
- qDBusDebug() << this << "got message reply (blocking):" << amsg;
-
- return amsg;
- } else { // use the event loop
- QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout);
- Q_ASSERT(pcall);
-
- if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
+ if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
+ // need to wait for the reply
+ if (sendMode == QDBus::BlockWithGui) {
pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
QEventLoop loop;
loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit()));
@@ -2074,18 +1897,17 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
// enter the event loop and wait for a reply
loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
+ } else {
+ pcall->waitForFinished();
}
+ }
- QDBusMessage reply = pcall->replyMessage;
- lastError = QDBusError(reply); // set or clear error
-
- bool r = pcall->ref.deref();
- Q_ASSERT(!r);
- Q_UNUSED(r);
+ QDBusMessage reply = pcall->replyMessage;
+ lastError = QDBusError(reply); // set or clear error
+ if (!pcall->ref.deref())
delete pcall;
- return reply;
- }
+ return reply;
}
QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message)
@@ -2125,34 +1947,13 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
QObject *receiver, const char *returnMethod,
const char *errorMethod, int timeout)
{
- if (isServiceRegisteredByThread(message.service())) {
+ QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this);
+ bool isLoopback;
+ if ((isLoopback = isServiceRegisteredByThread(message.service()))) {
// special case for local calls
- QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this);
pcall->replyMessage = sendWithReplyLocal(message);
- if (receiver && returnMethod)
- pcall->setReplyCallback(receiver, returnMethod);
-
- if (errorMethod) {
- pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
- connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod,
- Qt::QueuedConnection);
- pcall->watcherHelper->moveToThread(thread());
- }
-
- if ((receiver && returnMethod) || errorMethod) {
- // no one waiting, will delete pcall in processFinishedCall()
- pcall->ref.store(1);
- } else {
- // set double ref to prevent race between processFinishedCall() and ref counting
- // by QDBusPendingCall::QExplicitlySharedDataPointer<QDBusPendingCallPrivate>
- pcall->ref.store(2);
- }
- processFinishedCall(pcall);
- return pcall;
}
- checkThread();
- QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this);
if (receiver && returnMethod)
pcall->setReplyCallback(receiver, returnMethod);
@@ -2172,6 +1973,12 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
pcall->ref.store(2);
}
+ if (isLoopback) {
+ // a loopback call
+ processFinishedCall(pcall);
+ return pcall;
+ }
+
QDBusError error;
DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error);
if (!msg) {
@@ -2182,14 +1989,27 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
pcall->replyMessage = QDBusMessage::createError(error);
lastError = error;
processFinishedCall(pcall);
- return pcall;
+ } else {
+ qDBusDebug() << this << "sending message:" << message;
+ emit messageNeedsSending(pcall, msg, timeout);
}
+ return pcall;
+}
- qDBusDebug() << this << "sending message (async):" << message;
+void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *message, int timeout)
+{
+ QDBusError error;
DBusPendingCall *pending = 0;
+ DBusMessage *msg = static_cast<DBusMessage *>(message);
+ bool isNoReply = !pcall;
+ Q_ASSERT(isNoReply == !!q_dbus_message_get_no_reply(msg));
- QDBusDispatchLocker locker(SendWithReplyAsyncAction, this);
- if (q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
+ checkThread();
+ QDBusDispatchLocker locker(SendMessageAction, this);
+
+ if (isNoReply && q_dbus_connection_send(connection, msg, Q_NULLPTR)) {
+ // success
+ } else if (!isNoReply && q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) {
if (pending) {
q_dbus_message_unref(msg);
@@ -2200,7 +2020,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
if (mode == QDBusConnectionPrivate::PeerMode)
pendingCalls.append(pcall);
- return pcall;
+ return;
} else {
// we're probably disconnected at this point
lastError = error = QDBusError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
@@ -2210,9 +2030,10 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
}
q_dbus_message_unref(msg);
- pcall->replyMessage = QDBusMessage::createError(error);
- processFinishedCall(pcall);
- return pcall;
+ if (pcall) {
+ pcall->replyMessage = QDBusMessage::createError(error);
+ processFinishedCall(pcall);
+ }
}
bool QDBusConnectionPrivate::connectSignal(const QString &service,
@@ -2231,6 +2052,15 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service,
if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
return false; // don't connect
+ Q_ASSERT(thread() != QThread::currentThread());
+ emit signalNeedsConnecting(key, hook);
+ return true;
+}
+
+void QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook &hook)
+{
+ QDBusWriteLocker locker(ConnectAction, this);
+
// avoid duplicating:
QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.constFind(key);
QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd();
@@ -2243,24 +2073,18 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service,
entry.midx == hook.midx &&
entry.argumentMatch == hook.argumentMatch) {
// no need to compare the parameters if it's the same slot
- return true; // already there
+ return; // already there
}
}
- connectSignal(key, hook);
- return true;
-}
-
-void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook)
-{
signalHooks.insertMulti(key, hook);
connect(hook.obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)),
- Qt::ConnectionType(Qt::DirectConnection | Qt::UniqueConnection));
+ Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
- MatchRefCountHash::iterator it = matchRefCounts.find(hook.matchRule);
+ MatchRefCountHash::iterator mit = matchRefCounts.find(hook.matchRule);
- if (it != matchRefCounts.end()) { // Match already present
- it.value() = it.value() + 1;
+ if (mit != matchRefCounts.end()) { // Match already present
+ mit.value() = mit.value() + 1;
return;
}
@@ -2268,7 +2092,7 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook
if (connection) {
if (mode != QDBusConnectionPrivate::PeerMode) {
- qDBusDebug("Adding rule: %s", hook.matchRule.constData());
+ qDBusDebug() << this << "Adding rule:" << hook.matchRule;
q_dbus_bus_add_match(connection, hook.matchRule, NULL);
// Successfully connected the signal
@@ -2277,9 +2101,10 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook
WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
if (++data.refcount == 1) {
// we need to watch for this service changing
- connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
- QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
+ q_dbus_bus_add_match(connection,
+ buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
+ QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
+ NULL);
data.owner = getNameOwnerNoCache(hook.service);
qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
<< data.owner << ")";
@@ -2305,7 +2130,14 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
return false; // don't disconnect
- // avoid duplicating:
+ Q_ASSERT(thread() != QThread::currentThread());
+ return emit signalNeedsDisconnecting(key, hook);
+}
+
+bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHook &hook)
+{
+ // remove it from our list:
+ QDBusWriteLocker locker(ConnectAction, this);
QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key);
QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end();
for ( ; it != end && it.key() == key; ++it) {
@@ -2317,7 +2149,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
entry.midx == hook.midx &&
entry.argumentMatch == hook.argumentMatch) {
// no need to compare the parameters if it's the same slot
- disconnectSignal(it);
+ removeSignalHookNoLock(it);
return true; // it was there
}
}
@@ -2327,7 +2159,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
}
QDBusConnectionPrivate::SignalHookHash::Iterator
-QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
+QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
{
const SignalHook &hook = it.value();
@@ -2348,7 +2180,7 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
// we don't care about errors here
if (connection && erase) {
if (mode != QDBusConnectionPrivate::PeerMode) {
- qDBusDebug("Removing rule: %s", hook.matchRule.constData());
+ qDBusDebug() << this << "Removing rule:" << hook.matchRule;
q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
// Successfully disconnected the signal
@@ -2357,9 +2189,10 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
if (sit != watchedServices.end()) {
if (--sit.value().refcount == 0) {
watchedServices.erase(sit);
- disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
- QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
+ q_dbus_bus_remove_match(connection,
+ buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(),
+ QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()),
+ NULL);
}
}
}
@@ -2372,7 +2205,7 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node)
{
connect(node->obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)),
- Qt::DirectConnection);
+ Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection));
if (node->flags & (QDBusConnection::ExportAdaptors
| QDBusConnection::ExportScriptableSignals
@@ -2426,21 +2259,8 @@ void QDBusConnectionPrivate::connectRelay(const QString &service,
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
return; // don't connect
- // add it to our list:
- QDBusWriteLocker locker(ConnectRelayAction, this);
- SignalHookHash::ConstIterator it = signalHooks.constFind(key);
- SignalHookHash::ConstIterator end = signalHooks.constEnd();
- for ( ; it != end && it.key() == key; ++it) {
- const SignalHook &entry = it.value();
- if (entry.service == hook.service &&
- entry.path == hook.path &&
- entry.signature == hook.signature &&
- entry.obj == hook.obj &&
- entry.midx == hook.midx)
- return; // already there, no need to re-add
- }
-
- connectSignal(key, hook);
+ Q_ASSERT(thread() != QThread::currentThread());
+ emit signalNeedsConnecting(key, hook);
}
void QDBusConnectionPrivate::disconnectRelay(const QString &service,
@@ -2458,24 +2278,55 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
sig.append(signal.methodSignature());
if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig,
QDBusAbstractInterface::staticMetaObject.methodCount(), true))
- return; // don't connect
+ return; // don't disconnect
- // remove it from our list:
- QDBusWriteLocker locker(DisconnectRelayAction, this);
- SignalHookHash::Iterator it = signalHooks.find(key);
- SignalHookHash::Iterator end = signalHooks.end();
- for ( ; it != end && it.key() == key; ++it) {
- const SignalHook &entry = it.value();
- if (entry.service == hook.service &&
- entry.path == hook.path &&
- entry.signature == hook.signature &&
- entry.obj == hook.obj &&
- entry.midx == hook.midx) {
- // found it
- disconnectSignal(it);
- return;
- }
- }
+ Q_ASSERT(thread() != QThread::currentThread());
+ emit signalNeedsDisconnecting(key, hook);
+}
+
+bool QDBusConnectionPrivate::shouldWatchService(const QString &service)
+{
+ // we don't have to watch anything in peer mode
+ if (mode != ClientMode)
+ return false;
+ // we don't have to watch wildcard services (empty strings)
+ if (service.isEmpty())
+ return false;
+ // we don't have to watch the bus driver
+ if (service == QDBusUtil::dbusService())
+ return false;
+ return true;
+}
+
+/*!
+ Sets up a watch rule for service \a service for the change described by
+ mode \a mode. When the change happens, slot \a member in object \a obj will
+ be called.
+
+ The caller should call QDBusConnectionPrivate::shouldWatchService() before
+ calling this function to check whether the service needs to be watched at
+ all. Failing to do so may add rules that are never activated.
+*/
+void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
+{
+ QStringList matchArgs = matchArgsForService(service, mode);
+ connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
+ matchArgs, QString(), obj, member);
+}
+
+/*!
+ Removes a watch rule set up by QDBusConnectionPrivate::watchService(). The
+ arguments to this function must be the same as the ones for that function.
+
+ Sets up a watch rule for service \a service for the change described by
+ mode \a mode. When the change happens, slot \a member in object \a obj will
+ be called.
+*/
+void QDBusConnectionPrivate::unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member)
+{
+ QStringList matchArgs = matchArgsForService(service, mode);
+ disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
+ matchArgs, QString(), obj, member);
}
QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName)
@@ -2504,9 +2355,21 @@ QString QDBusConnectionPrivate::getNameOwnerNoCache(const QString &serviceName)
QStringLiteral("GetNameOwner"));
QDBusMessagePrivate::setParametersValidated(msg, true);
msg << serviceName;
- QDBusMessage reply = sendWithReply(msg, QDBus::Block);
- if (reply.type() == QDBusMessage::ReplyMessage)
- return reply.arguments().at(0).toString();
+
+ QDBusPendingCallPrivate *pcall = sendWithReplyAsync(msg, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR);
+ if (thread() == QThread::currentThread()) {
+ // this function may be called in our own thread and
+ // QDBusPendingCallPrivate::waitForFinished() would deadlock there
+ q_dbus_pending_call_block(pcall->pending);
+ }
+ pcall->waitForFinished();
+ msg = pcall->replyMessage;
+
+ if (!pcall->ref.deref())
+ delete pcall;
+
+ if (msg.type() == QDBusMessage::ReplyMessage)
+ return msg.arguments().at(0).toString();
return QString();
}
diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h
index 95eeed3fff..62106e4c0b 100644
--- a/src/dbus/qdbusintegrator_p.h
+++ b/src/dbus/qdbusintegrator_p.h
@@ -133,29 +133,6 @@ private:
bool handled;
};
-class QDBusConnectionCallbackEvent : public QEvent
-{
-public:
- QDBusConnectionCallbackEvent()
- : QEvent(User), subtype(Subtype(0))
- { }
-
- DBusWatch *watch;
- union {
- int timerId;
- int fd;
- };
- int extra;
-
- enum Subtype {
- AddTimeout = 0,
- KillTimer,
- AddWatch,
- //RemoveWatch,
- ToggleWatch
- } subtype;
-};
-
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QDBusSlotCache)
diff --git a/src/dbus/qdbusintrospection_p.h b/src/dbus/qdbusintrospection_p.h
index 572a39b140..f34e336eb3 100644
--- a/src/dbus/qdbusintrospection_p.h
+++ b/src/dbus/qdbusintrospection_p.h
@@ -158,7 +158,6 @@ public:
private:
QDBusIntrospection();
};
-Q_DECLARE_TYPEINFO(QDBusIntrospection::Argument, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp
index 09eff81107..ad5632be5a 100644
--- a/src/dbus/qdbuspendingcall.cpp
+++ b/src/dbus/qdbuspendingcall.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -231,7 +232,7 @@ void QDBusPendingCallPrivate::waitForFinished()
if (replyMessage.type() != QDBusMessage::InvalidMessage)
return; // already finished
- connection->waitForFinished(this);
+ waitForFinishedCondition.wait(&mutex);
}
/*!
diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h
index ac39487fee..dcf733679c 100644
--- a/src/dbus/qdbuspendingcall_p.h
+++ b/src/dbus/qdbuspendingcall_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -89,11 +90,10 @@ public:
DBusPendingCall *pending;
QString expectedReplySignature;
int expectedReplyCount;
- bool waitingForFinished;
// }
QDBusPendingCallPrivate(const QDBusMessage &sent, QDBusConnectionPrivate *connection)
- : sentMessage(sent), connection(connection), watcherHelper(0), pending(0), waitingForFinished(false)
+ : sentMessage(sent), connection(connection), watcherHelper(0), pending(0)
{ }
~QDBusPendingCallPrivate();
bool setReplyCallback(QObject *target, const char *member);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index cf1b6e9665..6c1b4c10ef 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -62,13 +63,10 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent)
d = 0;
return;
}
- d = new QDBusConnectionPrivate(this);
- QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)),
- this, SIGNAL(newConnection(QDBusConnection)));
-
- QDBusErrorInternal error;
- d->setServer(q_dbus_server_listen(address.toUtf8().constData(), error), error);
+ emit QDBusConnectionManager::instance()->serverRequested(address, this);
+ QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)),
+ this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
}
/*!
@@ -81,22 +79,19 @@ QDBusServer::QDBusServer(QObject *parent)
{
#ifdef Q_OS_UNIX
// Use Unix sockets on Unix systems only
- static const char address[] = "unix:tmpdir=/tmp";
+ const QString address = QStringLiteral("unix:tmpdir=/tmp");
#else
- static const char address[] = "tcp:";
+ const QString address = QStringLiteral("tcp:");
#endif
if (!qdbus_loadLibDBus()) {
d = 0;
return;
}
- d = new QDBusConnectionPrivate(this);
-
- QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)),
- this, SIGNAL(newConnection(QDBusConnection)));
- QDBusErrorInternal error;
- d->setServer(q_dbus_server_listen(address, error), error);
+ emit QDBusConnectionManager::instance()->serverRequested(address, this);
+ QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)),
+ this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
}
/*!
@@ -186,4 +181,6 @@ bool QDBusServer::isAnonymousAuthenticationAllowed() const
QT_END_NAMESPACE
+#include "moc_qdbusserver.cpp"
+
#endif // QT_NO_DBUS
diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h
index db21f268b0..3cb2ec8c50 100644
--- a/src/dbus/qdbusserver.h
+++ b/src/dbus/qdbusserver.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -66,7 +67,9 @@ Q_SIGNALS:
private:
Q_DISABLE_COPY(QDBusServer)
+ Q_PRIVATE_SLOT(d, void _q_newConnection(QDBusConnectionPrivate*))
QDBusConnectionPrivate *d;
+ friend class QDBusConnectionPrivate;
};
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp
index 4adf049d17..72c1a12f2c 100644
--- a/src/dbus/qdbusservicewatcher.cpp
+++ b/src/dbus/qdbusservicewatcher.cpp
@@ -38,6 +38,7 @@
#include <QStringList>
#include <private/qobject_p.h>
+#include <private/qdbusconnection_p.h>
#ifndef QT_NO_DBUS
@@ -59,7 +60,6 @@ public:
void _q_serviceOwnerChanged(const QString &, const QString &, const QString &);
void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode);
- QStringList matchArgsForService(const QString &service);
void addService(const QString &service);
void removeService(const QString &service);
};
@@ -93,40 +93,18 @@ void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBus
}
}
-QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service)
-{
- QStringList matchArgs;
- matchArgs << service;
-
- switch (watchMode) {
- case QDBusServiceWatcher::WatchForOwnerChange:
- break;
-
- case QDBusServiceWatcher::WatchForRegistration:
- matchArgs << QString::fromLatin1("", 0);
- break;
-
- case QDBusServiceWatcher::WatchForUnregistration:
- matchArgs << QString() << QString::fromLatin1("", 0);
- break;
- }
- return matchArgs;
-}
-
void QDBusServiceWatcherPrivate::addService(const QString &service)
{
- QStringList matchArgs = matchArgsForService(service);
- connection.connect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
- matchArgs, QString(), q_func(),
- SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection);
+ if (d && d->shouldWatchService(service))
+ d->watchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
}
void QDBusServiceWatcherPrivate::removeService(const QString &service)
{
- QStringList matchArgs = matchArgsForService(service);
- connection.disconnect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(),
- matchArgs, QString(), q_func(),
- SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection);
+ if (d && d->shouldWatchService(service))
+ d->unwatchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
}
/*!
diff --git a/src/dbus/qdbusservicewatcher.h b/src/dbus/qdbusservicewatcher.h
index 6f6ce917af..71c0f0af68 100644
--- a/src/dbus/qdbusservicewatcher.h
+++ b/src/dbus/qdbusservicewatcher.h
@@ -37,7 +37,7 @@
#include <QtCore/qobject.h>
#include <QtDBus/qdbusmacros.h>
-#ifndef QT_NO_DBUS
+#if !defined(QT_NO_DBUS) && !defined(QT_NO_QOBJECT)
QT_BEGIN_NAMESPACE
@@ -89,5 +89,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusServiceWatcher::WatchMode)
QT_END_NAMESPACE
-#endif // QT_NO_DBUS
+#endif // QT_NO_DBUS || QT_NO_QOBJECT
#endif // QDBUSSERVICEWATCHER_H
diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h
index a8e126cf73..eace25478d 100644
--- a/src/dbus/qdbusthreaddebug_p.h
+++ b/src/dbus/qdbusthreaddebug_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtDBus module of the Qt Toolkit.
@@ -82,13 +83,12 @@ enum ThreadAction {
HandleObjectCallPostEventAction = 22,
HandleObjectCallSemaphoreAction = 23,
DoDispatchAction = 24,
- SendWithReplyAsyncAction = 25,
+ // unused: 25,
MessageResultReceivedAction = 26,
ActivateSignalAction = 27,
PendingCallBlockAction = 28,
SendMessageAction = 29,
- SendWithReplyAndBlockAction = 30,
- HuntAndEmitAction = 31,
+ HuntAndEmitAction = 30,
AddTimeoutAction = 50,
RealAddTimeoutAction = 51,
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 50a4a09102..e9995045b1 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -451,7 +451,6 @@ QAccessibleInterface::~QAccessibleInterface()
/*!
\typedef QAccessible::Id
- \relates QAccessible
Synonym for unsigned, used by the QAccessibleInterface cache.
*/
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index f124cede36..ef12b23caa 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -212,6 +212,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
int blue_scale = 0;
int alpha_scale = 0;
+ if (!d->isSequential())
+ d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4 ? BMP_WIN : bi.biSize)); // goto start of colormap or masks
+
if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
@@ -299,9 +302,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
image.setDotsPerMeterX(bi.biXPelsPerMeter);
image.setDotsPerMeterY(bi.biYPelsPerMeter);
- if (!d->isSequential())
- d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
-
if (ncols > 0) { // read color table
uchar rgb[4];
int rgb_len = t == BMP_OLD ? 3 : 4;
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index 49a3bead53..7411dbb054 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -77,6 +77,13 @@ QSize QIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::St
return size;
}
+/*!
+ \since 5.6
+ Constructs the icon engine.
+ */
+QIconEngine::QIconEngine()
+{
+}
/*!
Destroys the icon engine.
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index f0ff143b36..6c45cd216f 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QIconEngine
{
public:
+ QIconEngine();
virtual ~QIconEngine();
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index aea6fc133f..7f2504ddd9 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -2209,12 +2209,12 @@ int QImage::pixelIndex(int x, int y) const
*/
QRgb QImage::pixel(int x, int y) const
{
- if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
+ if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y);
return 12345;
}
- const uchar * s = constScanLine(y);
+ const uchar *s = d->data + y * d->bytes_per_line;
switch(d->format) {
case Format_Mono:
return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1);
@@ -4237,9 +4237,6 @@ QImage QImage::alphaChannel() const
if (!d)
return QImage();
- if (d->format == QImage::Format_Alpha8)
- return *this;
-
int w = d->width;
int h = d->height;
@@ -4269,6 +4266,10 @@ QImage QImage::alphaChannel() const
src_data += d->bytes_per_line;
dest_data += image.d->bytes_per_line;
}
+ } else if (d->format == Format_Alpha8) {
+ const uchar *src_data = d->data;
+ uchar *dest_data = image.d->data;
+ memcpy(dest_data, src_data, d->bytes_per_line * h);
} else {
QImage alpha32 = *this;
bool canSkipConversion = (d->format == Format_ARGB32 || d->format == Format_ARGB32_Premultiplied);
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index c7df6107f7..26a0ab5c0f 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -171,6 +171,8 @@ QInputEvent::~QInputEvent()
\fn ulong QInputEvent::timestamp() const
Returns the window system's timestamp for this event.
+ It will normally be in milliseconds since some arbitrary point
+ in time, such as the time when the system was started.
*/
/*! \fn void QInputEvent::setTimestamp(ulong atimestamp)
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 898f14f8cb..c168a2bccc 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -99,6 +99,9 @@
#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
# include <QtCore/qt_windows.h>
# include <QtCore/QLibraryInfo>
+# if defined(Q_OS_WINPHONE)
+# include <Objbase.h>
+# endif
#endif // Q_OS_WIN && !Q_OS_WINCE
#include <ctype.h>
@@ -450,8 +453,7 @@ static QWindowGeometrySpecification windowGeometrySpecification;
\row
\li Miscellaneous
\li startingUp(),
- closingDown(),
- type().
+ closingDown().
\endtable
\sa QCoreApplication, QAbstractEventDispatcher, QEventLoop
@@ -907,16 +909,6 @@ QWindowList QGuiApplication::topLevelWindows()
return topLevelWindows;
}
-/*!
- Returns the primary (or default) screen of the application, or null if there is none
-
- This will be the screen where QWindows are initially shown, unless otherwise specified.
-
- On some platforms, it may be null when there are actually no screens connected.
- It is not possible to start a new QGuiApplication while there are no screens.
- Applications which were running at the time the primary screen was removed
- will stop rendering graphics until one or more screens are restored.
-*/
QScreen *QGuiApplication::primaryScreen()
{
if (QGuiApplicationPrivate::screen_list.isEmpty())
@@ -938,7 +930,7 @@ QList<QScreen *> QGuiApplication::screens()
This signal is emitted whenever a new screen \a screen has been added to the system.
- \sa screens(), primaryScreen(), screenRemoved()
+ \sa screens(), primaryScreen, screenRemoved()
*/
/*!
@@ -955,6 +947,23 @@ QList<QScreen *> QGuiApplication::screens()
/*!
+ \property QGuiApplication::primaryScreen
+
+ \brief the primary (or default) screen of the application, or null if there is none.
+
+ This will be the screen where QWindows are initially shown, unless otherwise specified.
+
+ On some platforms, it may be null when there are actually no screens connected.
+ It is not possible to start a new QGuiApplication while there are no screens.
+ Applications which were running at the time the primary screen was removed
+ will stop rendering graphics until one or more screens are restored.
+
+ The primaryScreenChanged signal was introduced in Qt 5.6.
+
+ \sa screens()
+*/
+
+/*!
Returns the highest screen device pixel ratio found on
the system. This is the ratio between physical pixels and
device-independent pixels.
@@ -1257,6 +1266,16 @@ void QGuiApplicationPrivate::init()
#ifndef QT_NO_SESSIONMANAGER
QString session_id;
QString session_key;
+# if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ wchar_t guidstr[40];
+ GUID guid;
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ session_id = QString::fromWCharArray(guidstr);
+ CoCreateGuid(&guid);
+ StringFromGUID2(guid, guidstr, 40);
+ session_key = QString::fromWCharArray(guidstr);
+# endif
#endif
int j = argc ? 1 : 0;
for (int i=1; i<argc; i++) {
@@ -1738,7 +1757,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
// should first send a move event followed by a button changed event. Since this is not the case
// with the current event, we split it in two.
QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent(
- e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers);
+ e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers, e->source);
if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic)
mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
e->buttons = buttons;
@@ -1834,6 +1853,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
}
QGuiApplication::sendSpontaneousEvent(window, &ev);
+ e->eventAccepted = ev.isAccepted();
if (!e->synthetic() && !ev.isAccepted()
&& !frameStrut
&& qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) {
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 6eb26e8b06..a773122d3e 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -71,6 +71,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
Q_PROPERTY(QString platformName READ platformName STORED false)
Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed)
+ Q_PROPERTY(QScreen *primaryScreen READ primaryScreen NOTIFY primaryScreenChanged STORED false)
public:
#ifdef Q_QDOC
@@ -162,6 +163,7 @@ Q_SIGNALS:
void fontDatabaseChanged();
void screenAdded(QScreen *screen);
void screenRemoved(QScreen *screen);
+ void primaryScreenChanged(QScreen *screen);
void lastWindowClosed();
void focusObjectChanged(QObject *focusObject);
void focusWindowChanged(QWindow *focusWindow);
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index de586ac46c..daba9f94a1 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -62,10 +62,10 @@ static inline qreal initialScaleFactor()
}
} else {
if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) {
- qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:";
- qWarning() << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors.";
- qWarning() << " " << screenFactorsEnvVar << "to set per-screen factors.";
- qWarning() << " " << scaleFactorEnvVar << "to set the application global scale factor.";
+ qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:" << endl
+ << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors." << endl
+ << " " << screenFactorsEnvVar << "to set per-screen factors." << endl
+ << " " << scaleFactorEnvVar << "to set the application global scale factor.";
int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar);
if (dpr > 0)
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 9e5767658f..85d05959de 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -462,8 +462,7 @@ QPlatformOpenGLContext *QOpenGLContext::shareHandle() const
QOpenGLContext::QOpenGLContext(QObject *parent)
: QObject(*new QOpenGLContextPrivate(), parent)
{
- Q_D(QOpenGLContext);
- d->screen = QGuiApplication::primaryScreen();
+ setScreen(QGuiApplication::primaryScreen());
}
/*!
@@ -499,9 +498,20 @@ void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)
void QOpenGLContext::setScreen(QScreen *screen)
{
Q_D(QOpenGLContext);
+ if (d->screen)
+ disconnect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*)));
d->screen = screen;
if (!d->screen)
d->screen = QGuiApplication::primaryScreen();
+ if (d->screen)
+ connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*)));
+}
+
+void QOpenGLContextPrivate::_q_screenDestroyed(QObject *object)
+{
+ Q_Q(QOpenGLContext);
+ if (object == static_cast<QObject *>(screen))
+ q->setScreen(0);
}
/*!
@@ -1626,4 +1636,6 @@ void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenG
m_groups.removeOne(group);
}
+#include "moc_qopenglcontext.cpp"
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 85e7abfa26..841967a545 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -241,6 +241,8 @@ private:
void setTextureFunctions(QOpenGLTextureHelper* textureFuncs);
void destroy();
+
+ Q_PRIVATE_SLOT(d_func(), void _q_screenDestroyed(QObject *object))
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index f9f3ce2c5f..4a746bf12b 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -270,6 +270,8 @@ public:
static QHash<QOpenGLContext *, bool> makeCurrentTracker;
static QMutex makeCurrentTrackerMutex;
#endif
+
+ void _q_screenDestroyed(QObject *object);
};
Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index 7239ac7ba4..cd43fc42fe 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtOpenVG module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h
index 4f4f9cc6ae..8c788fd27b 100644
--- a/src/gui/kernel/qplatformcursor.h
+++ b/src/gui/kernel/qplatformcursor.h
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the QtOpenVG module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 25894fd504..f69efe0935 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -119,6 +119,8 @@ static const int buttonRoleLayouts[2][5][14] =
QPlatformDialogHelper::QPlatformDialogHelper()
{
+ qRegisterMetaType<StandardButton>();
+ qRegisterMetaType<ButtonRole>();
}
QPlatformDialogHelper::~QPlatformDialogHelper()
@@ -651,12 +653,13 @@ void QPlatformFileDialogHelper::setOptions(const QSharedPointer<QFileDialogOptio
}
const char *QPlatformFileDialogHelper::filterRegExp =
-"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
+"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)"
QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter)
{
QRegExp regexp(QString::fromLatin1(filterRegExp));
+ Q_ASSERT(regexp.isValid());
QString f = filter;
int i = regexp.indexIn(f);
if (i >= 0)
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index ec88770862..936dbdfa89 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -160,6 +160,11 @@ Q_SIGNALS:
void reject();
};
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QPlatformDialogHelper::StandardButton)
+Q_DECLARE_METATYPE(QPlatformDialogHelper::ButtonRole)
+QT_BEGIN_NAMESPACE
+
class Q_GUI_EXPORT QColorDialogOptions
{
public:
diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp
index a7660e76ae..fedf940dda 100644
--- a/src/gui/kernel/qplatforminputcontextfactory.cpp
+++ b/src/gui/kernel/qplatforminputcontextfactory.cpp
@@ -56,48 +56,34 @@ QStringList QPlatformInputContextFactory::keys()
#endif
}
-QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key)
+QString QPlatformInputContextFactory::requested()
{
- QStringList paramList = key.split(QLatin1Char(':'));
- const QString platform = paramList.takeFirst().toLower();
-
-#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
- if (QPlatformInputContext *ret = qLoadPlugin1<QPlatformInputContext, QPlatformInputContextPlugin>(loader(), platform, paramList))
- return ret;
-#endif
- return 0;
+ QByteArray env = qgetenv("QT_IM_MODULE");
+ return env.isNull() ? QString() : QString::fromLocal8Bit(env);
}
-QPlatformInputContext *QPlatformInputContextFactory::create()
+QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key)
{
- QPlatformInputContext *ic = 0;
-
- QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE"));
-
- if (icString == QLatin1String("none"))
- return 0;
-
- ic = create(icString);
- if (ic && ic->isValid())
- return ic;
-
- delete ic;
- ic = 0;
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ if (!key.isEmpty()) {
+ QStringList paramList = key.split(QLatin1Char(':'));
+ const QString platform = paramList.takeFirst().toLower();
- QStringList k = keys();
- for (int i = 0; i < k.size(); ++i) {
- if (k.at(i) == icString)
- continue;
- ic = create(k.at(i));
+ QPlatformInputContext *ic = qLoadPlugin1<QPlatformInputContext, QPlatformInputContextPlugin>
+ (loader(), platform, paramList);
if (ic && ic->isValid())
return ic;
+
delete ic;
- ic = 0;
}
-
+#endif
return 0;
}
+QPlatformInputContext *QPlatformInputContextFactory::create()
+{
+ return create(requested());
+}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatforminputcontextfactory_p.h b/src/gui/kernel/qplatforminputcontextfactory_p.h
index a74c4f5f80..38f4358287 100644
--- a/src/gui/kernel/qplatforminputcontextfactory_p.h
+++ b/src/gui/kernel/qplatforminputcontextfactory_p.h
@@ -56,6 +56,7 @@ class Q_GUI_EXPORT QPlatformInputContextFactory
{
public:
static QStringList keys();
+ static QString requested();
static QPlatformInputContext *create(const QString &key);
static QPlatformInputContext *create();
};
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index e935907a62..457a420148 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -456,6 +456,24 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
QGuiApplicationPrivate::screen_list.append(screen);
}
emit qGuiApp->screenAdded(screen);
+
+ if (isPrimary)
+ emit qGuiApp->primaryScreenChanged(screen);
+}
+
+/*!
+ Just removes the screen, call destroyScreen instead.
+
+ \sa destroyScreen()
+*/
+
+void QPlatformIntegration::removeScreen(QScreen *screen)
+{
+ const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list[0] == screen);
+ QGuiApplicationPrivate::screen_list.removeOne(screen);
+
+ if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty())
+ emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list[0]);
}
/*!
@@ -469,11 +487,30 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
void QPlatformIntegration::destroyScreen(QPlatformScreen *screen)
{
QScreen *qScreen = screen->screen();
- QGuiApplicationPrivate::screen_list.removeOne(qScreen);
+ removeScreen(qScreen);
delete qScreen;
delete screen;
}
+/*!
+ Should be called whenever the primary screen changes.
+
+ When the screen specified as primary changes, this method will notify
+ QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
+ */
+
+void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary)
+{
+ QScreen* newPrimaryScreen = newPrimary->screen();
+ int idx = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
+ Q_ASSERT(idx >= 0);
+ if (idx == 0)
+ return;
+
+ QGuiApplicationPrivate::screen_list.swap(0, idx);
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+}
+
QStringList QPlatformIntegration::themeNames() const
{
return QStringList();
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 2aa502b3d2..00c50a9861 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -172,9 +172,13 @@ public:
virtual QOpenGLContext::OpenGLModuleType openGLModuleType();
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
+
+ void removeScreen(QScreen *screen);
+
protected:
void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
+ void setPrimaryScreen(QPlatformScreen *newPrimary);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 2fb53fe16b..d1d8eba697 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -56,7 +56,7 @@ QPlatformScreen::~QPlatformScreen()
Q_D(QPlatformScreen);
if (d->screen) {
qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead.");
- QGuiApplicationPrivate::screen_list.removeOne(d->screen);
+ QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen);
delete d->screen;
}
}
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 0430d5a4c6..ea3b75c81c 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -702,15 +702,20 @@ QRect QPlatformWindow::windowFrameGeometry() const
a resize/move event for platforms that support it, for example to
implement heightForWidth().
*/
-QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const
+
+QRectF QPlatformWindow::closestAcceptableGeometry(const QWindow *qWindow, const QRectF &nativeRect)
{
- QWindow *qWindow = window();
const QRectF rectF = QHighDpi::fromNativePixels(nativeRect, qWindow);
- const QRectF correctedGeometryF = qt_window_private(qWindow)->closestAcceptableGeometry(rectF);
+ const QRectF correctedGeometryF = qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(rectF);
return !correctedGeometryF.isEmpty() && rectF != correctedGeometryF
? QHighDpi::toNativePixels(correctedGeometryF, qWindow) : nativeRect;
}
+QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const
+{
+ return QPlatformWindow::closestAcceptableGeometry(window(), nativeRect);
+}
+
/*!
\class QPlatformWindow
\since 4.8
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 1b283dbb4f..9c2817906f 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -140,6 +140,7 @@ public:
QRect windowGeometry() const;
QRect windowFrameGeometry() const;
QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const;
+ static QRectF closestAcceptableGeometry(const QWindow *w, const QRectF &nativeRect);
protected:
static QString formatWindowTitle(const QString &title, const QString &separator);
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 407b4ee9b6..b6b50372ae 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -698,7 +698,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
{
const QDebugStateSaver saver(debug);
debug.nospace();
- debug << "QScreen(" << (void *)screen;
+ debug << "QScreen(" << (const void *)screen;
if (screen) {
debug << ", name=" << screen->name();
if (debug.verbosity() > 2) {
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index 0ff5c36119..3e267f2e0b 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -386,9 +386,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
result = find(e);
if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
// Try to find a match without keypad modifier
- QKeyEvent event = *e;
- event.setModifiers(e->modifiers() & ~Qt::KeypadModifier);
- result = find(&event);
+ result = find(e, Qt::KeypadModifier);
}
if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) {
// If Shift + Key_Backtab, also try Shift + Qt::Key_Tab
@@ -441,13 +439,13 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
which can be access through matches().
\sa matches
*/
-QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e)
+QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers)
{
Q_D(QShortcutMap);
if (!d->sequences.count())
return QKeySequence::NoMatch;
- createNewSequences(e, d->newEntries);
+ createNewSequences(e, d->newEntries, ignoredModifiers);
#if defined(DEBUG_QSHORTCUTMAP)
qDebug() << "Possible shortcut key sequences:" << d->newEntries;
#endif
@@ -549,7 +547,7 @@ void QShortcutMap::clearSequence(QVector<QKeySequence> &ksl)
Alters \a seq to the new sequence state, based on the
current sequence state, and the new key event \a e.
*/
-void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl)
+void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers)
{
Q_D(QShortcutMap);
QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
@@ -579,7 +577,7 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl)
curKsl.setKey(0, 2);
curKsl.setKey(0, 3);
}
- curKsl.setKey(possibleKeys.at(pkNum), index);
+ curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index);
}
}
}
diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h
index 242c021ca4..2376d27c78 100644
--- a/src/gui/kernel/qshortcutmap_p.h
+++ b/src/gui/kernel/qshortcutmap_p.h
@@ -88,10 +88,10 @@ private:
QKeySequence::SequenceMatch state();
void dispatchEvent(QKeyEvent *e);
- QKeySequence::SequenceMatch find(QKeyEvent *e);
+ QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0);
QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
QVector<const QShortcutEntry *> matches() const;
- void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl);
+ void createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl, int ignoredModifiers);
void clearSequence(QVector<QKeySequence> &ksl);
int translateModifiers(Qt::KeyboardModifiers modifiers);
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index 6e574d82e4..b02f1dd8bd 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -149,7 +149,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
{
QPoint nativePosition = getNativeMousePos(e, o);
move(nativePosition);
- return true; // Eat all mouse events
+ return true; // Eat all mouse move events
}
case QEvent::MouseButtonRelease:
disableEventFilter();
@@ -160,8 +160,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
cancel();
}
exitDndEventLoop();
- return true; // Eat all mouse events
- case QEvent::MouseButtonPress:
+ QCoreApplication::postEvent(o, new QMouseEvent(*static_cast<QMouseEvent *>(e)));
+ return true; // defer mouse release events until drag event loop has returned
case QEvent::MouseButtonDblClick:
case QEvent::Wheel:
return true;
diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp
index 9d19fa4b92..266b5308a2 100644
--- a/src/gui/kernel/qtouchdevice.cpp
+++ b/src/gui/kernel/qtouchdevice.cpp
@@ -237,6 +237,17 @@ void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev)
deviceList()->append(dev);
}
+/*!
+ \internal
+ */
+void QTouchDevicePrivate::unregisterDevice(const QTouchDevice *dev)
+{
+ QMutexLocker lock(&devicesMutex);
+ bool wasRemoved = deviceList()->removeOne(dev);
+ if (wasRemoved && deviceList()->isEmpty())
+ qRemovePostRoutine(cleanupDevicesList);
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QTouchDevice *device)
{
diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h
index 4aff8f2f33..63b83d33ec 100644
--- a/src/gui/kernel/qtouchdevice_p.h
+++ b/src/gui/kernel/qtouchdevice_p.h
@@ -65,6 +65,7 @@ public:
int maxTouchPoints;
static void registerDevice(const QTouchDevice *dev);
+ static void unregisterDevice(const QTouchDevice *dev);
static bool isRegistered(const QTouchDevice *dev);
};
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index e93e964c6b..89bd119564 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -2508,7 +2508,7 @@ QDebug operator<<(QDebug debug, const QWindow *window)
QDebugStateSaver saver(debug);
debug.nospace();
if (window) {
- debug << window->metaObject()->className() << '(' << (void *)window;
+ debug << window->metaObject()->className() << '(' << (const void *)window;
if (!window->objectName().isEmpty())
debug << ", name=" << window->objectName();
if (debug.verbosity() > 2) {
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 88cf2dac93..faa1ff8068 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -49,6 +49,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false;
QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
QMutex QWindowSystemInterfacePrivate::flushEventMutex;
+QAtomicInt QWindowSystemInterfacePrivate::eventAccepted;
QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler;
//------------------------------------------------------------
@@ -323,18 +324,18 @@ bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEven
return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text, bool autorep,
ushort count)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
+ return handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
text, autorep, count);
}
-void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key,
+bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key,
Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
@@ -345,7 +346,7 @@ void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam
QWindowSystemInterfacePrivate::KeyEvent * e =
new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers,
nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) {
@@ -441,27 +442,60 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e
windowSystemEventQueue.remove(event);
}
+void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev)
+{
+ windowSystemEventQueue.append(ev);
+ QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
+ if (dispatcher)
+ dispatcher->wakeUp();
+}
+
+/*!
+ Handles a window system event.
+
+ By default this function posts the event on the window system event queue and
+ wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously
+ at a later point. The return value is not used in asynchronous mode and will
+ always be true.
+
+ In synchronous mode Qt Gui will process the event immediately. The return value
+ indicates if Qt accepted the event.
+
+ \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
+*/
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
{
bool accepted = true;
if (synchronousWindowSystemEvents) {
- QGuiApplicationPrivate::processWindowSystemEvent(ev);
- accepted = ev->eventAccepted;
- delete ev;
+ if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
+ // Process the event immediately on the current thread and return the accepted state.
+ QGuiApplicationPrivate::processWindowSystemEvent(ev);
+ accepted = ev->eventAccepted;
+ delete ev;
+ } else {
+ // Post the event on the Qt main thread queue and flush the queue.
+ // This will wake up the Gui thread which will process the event.
+ // Return the accepted state for the last event on the queue,
+ // which is the event posted by this function.
+ postWindowSystemEvent(ev);
+ accepted = QWindowSystemInterface::flushWindowSystemEvents();
+ }
} else {
- windowSystemEventQueue.append(ev);
- QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
- if (dispatcher)
- dispatcher->wakeUp();
+ postWindowSystemEvent(ev);
}
return accepted;
}
-void QWindowSystemInterface::registerTouchDevice(QTouchDevice *device)
+void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device)
{
QTouchDevicePrivate::registerDevice(device);
}
+void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device)
+{
+ QTouchDevicePrivate::unregisterDevice(device);
+}
+
void QWindowSystemInterface::handleTouchEvent(QWindow *w, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
{
@@ -618,26 +652,33 @@ void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::Process
QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
}
-void QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
+/*!
+ Make Qt Gui process all events on the event queue immediately. Return the
+ accepted state for the last event on the queue.
+*/
+bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
if (!count)
- return;
+ return false;
if (!QGuiApplication::instance()) {
qWarning().nospace()
<< "QWindowSystemInterface::flushWindowSystemEvents() invoked after "
"QGuiApplication destruction, discarding " << count << " events.";
QWindowSystemInterfacePrivate::windowSystemEventQueue.clear();
- return;
+ return false;
}
if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
+ // Post a FlushEvents event which will trigger a call back to
+ // deferredFlushWindowSystemEvents from the Gui thread.
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::postWindowSystemEvent(e);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEvents(flags);
}
+ return QWindowSystemInterfacePrivate::eventAccepted.load() > 0;
}
bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
@@ -659,6 +700,13 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla
nevents++;
QGuiApplicationPrivate::processWindowSystemEvent(event);
}
+
+ // Record the accepted state for the processed event
+ // (excluding flush events). This state can then be
+ // returned by flushWindowSystemEvents().
+ if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
+ QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted);
+
delete event;
}
@@ -858,26 +906,23 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
}
#endif
+// The following functions are used by testlib, and need to be synchronous to avoid
+// race conditions with plugins delivering native events from secondary threads.
+
Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
{
- QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized);
- QGuiApplicationPrivate::processWindowSystemEvent(&e);
+ bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
+ QWindowSystemInterface::handleMouseEvent(w, timestamp, local, global, b, mods);
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
}
Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
{
- unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
-
- // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms
- // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for
- // shortcut overriding on other platforms.
-#if defined(Q_OS_OSX)
- if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text))
- return;
-#endif // Q_OS_OSX
-
- QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count);
- QGuiApplicationPrivate::processWindowSystemEvent(&e);
+ bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
+ QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count);
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
}
Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1)
@@ -885,37 +930,37 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int
return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count);
}
-Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
- const QList<QTouchEvent::TouchPoint> &points,
- Qt::KeyboardModifiers mods = Qt::NoModifier)
+static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt)
{
- unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
-
- if (!points.size()) // Touch events must have at least one point
- return;
-
- if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices.
- return;
-
- QEvent::Type type;
- Qt::TouchPointStates states;
+ QWindowSystemInterface::TouchPoint p;
+ p.id = pt.id();
+ p.flags = pt.flags();
+ p.normalPosition = pt.normalizedPos();
+ p.area = pt.screenRect();
+ p.pressure = pt.pressure();
+ p.state = pt.state();
+ p.velocity = pt.velocity();
+ p.rawPositions = pt.rawScreenPositions();
+ return p;
+}
+static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint>& pointList)
+{
+ QList<struct QWindowSystemInterface::TouchPoint> newList;
- QList<QTouchEvent::TouchPoint>::const_iterator point = points.constBegin();
- QList<QTouchEvent::TouchPoint>::const_iterator end = points.constEnd();
- while (point != end) {
- states |= point->state();
- ++point;
- }
+ Q_FOREACH (QTouchEvent::TouchPoint p, pointList)
+ newList.append(touchPoint(p));
- // Determine the event type based on the combined point states.
- type = QEvent::TouchUpdate;
- if (states == Qt::TouchPointPressed)
- type = QEvent::TouchBegin;
- else if (states == Qt::TouchPointReleased)
- type = QEvent::TouchEnd;
+ return newList;
+}
- QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods);
- QGuiApplicationPrivate::processWindowSystemEvent(&e);
+Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
+ const QList<QTouchEvent::TouchPoint> &points,
+ Qt::KeyboardModifiers mods = Qt::NoModifier)
+{
+ bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
+ QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods);
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
}
QWindowSystemEventHandler::~QWindowSystemEventHandler()
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index ace1a4fe24..97bd087b53 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -98,12 +98,12 @@ public:
static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
- static void handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ static bool handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
ushort count = 1);
- static void handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ static bool handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
@@ -127,7 +127,8 @@ public:
QVector<QPointF> rawPositions; // in screen coordinates
};
- static void registerTouchDevice(QTouchDevice *device);
+ static void registerTouchDevice(const QTouchDevice *device);
+ static void unregisterTouchDevice(const QTouchDevice *device);
static void handleTouchEvent(QWindow *w, QTouchDevice *device,
const QList<struct TouchPoint> &points, Qt::KeyboardModifiers mods = Qt::NoModifier);
static void handleTouchEvent(QWindow *w, ulong timestamp, QTouchDevice *device,
@@ -213,7 +214,7 @@ public:
// For event dispatcher implementations
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static void setSynchronousWindowSystemEvents(bool enable);
- static void flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
+ static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static int windowSystemEventsQueued();
};
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index cc0ca6bf81..e48d1e965b 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -51,6 +51,7 @@
#include <QMutex>
#include <QList>
#include <QWaitCondition>
+#include <QAtomicInt>
QT_BEGIN_NAMESPACE
@@ -481,6 +482,7 @@ public:
static WindowSystemEvent *getNonUserInputWindowSystemEvent();
static WindowSystemEvent *peekWindowSystemEvent(EventType t);
static void removeWindowSystemEvent(WindowSystemEvent *event);
+ static void postWindowSystemEvent(WindowSystemEvent *ev);
static bool handleWindowSystemEvent(WindowSystemEvent *ev);
static QElapsedTimer eventTime;
@@ -488,6 +490,7 @@ public:
static QWaitCondition eventsFlushed;
static QMutex flushEventMutex;
+ static QAtomicInt eventAccepted;
static QList<QTouchEvent::TouchPoint>
fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
index 7e53c01cba..40f4ce94c2 100644
--- a/src/gui/opengl/qopenglengineshadermanager.cpp
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -427,11 +427,10 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO
if (!inCache)
shaderCache.store(newProg->program, QOpenGLContext::currentContext());
} else {
- QLatin1String none("none");
- QLatin1String br("\n");
QString error;
error = QLatin1String("Shader program failed to link,");
#if defined(QT_DEBUG)
+ QLatin1String br("\n");
error += QLatin1String("\n Shaders Used:\n");
for (int i = 0; i < newProg->program->shaders().count(); ++i) {
QOpenGLShader *shader = newProg->program->shaders().at(i);
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index 3596591cf6..0e162713ce 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -951,8 +951,8 @@ QOpenGLFramebufferObject::~QOpenGLFramebufferObject()
}
/*!
- Creates and attaches an additional texture or renderbuffer of size \a width
- and \a height.
+ Creates and attaches an additional texture or renderbuffer of \a size width
+ and height.
There is always an attachment at GL_COLOR_ATTACHMENT0. Call this function
to set up additional attachments at GL_COLOR_ATTACHMENT1,
@@ -1142,7 +1142,7 @@ GLuint QOpenGLFramebufferObject::texture() const
\since 5.6
- \sa takeTextures(), texture()
+ \sa takeTexture(), texture()
*/
QVector<GLuint> QOpenGLFramebufferObject::textures() const
{
@@ -1172,7 +1172,7 @@ QVector<GLuint> QOpenGLFramebufferObject::textures() const
\since 5.3
- \sa texture(), bind(), release(), takeTextures()
+ \sa texture(), bind(), release()
*/
GLuint QOpenGLFramebufferObject::takeTexture()
{
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 668eaa9a89..d614ad8401 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -3701,7 +3701,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
- Convenience function that calls glCopyBufferSubData(\a readTarget, writeTarget, \a readOffset, \a writeOffset, \a size).
+ Convenience function that calls glCopyBufferSubData(\a readTarget, \a writeTarget, \a readOffset, \a writeOffset, \a size).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -3855,7 +3855,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
*/
/*!
- \fn void QOpenGLExtraFunctions::glEndTransformFeedback()
+ \fn void QOpenGLExtraFunctions::glEndTransformFeedback(void)
Convenience function that calls glEndTransformFeedback().
@@ -4362,7 +4362,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
*/
/*!
- \fn void QOpenGLExtraFunctions::glPauseTransformFeedback()
+ \fn void QOpenGLExtraFunctions::glPauseTransformFeedback(void)
Convenience function that calls glPauseTransformFeedback().
@@ -4427,7 +4427,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
*/
/*!
- \fn void QOpenGLExtraFunctions::glResumeTransformFeedback()
+ \fn void QOpenGLExtraFunctions::glResumeTransformFeedback(void)
Convenience function that calls glResumeTransformFeedback().
@@ -4455,7 +4455,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * param)
- Convenience function that calls glSamplerParameterfv(\a sampler, pname, \a param).
+ Convenience function that calls glSamplerParameterfv(\a sampler, \a pname, \a param).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4624,7 +4624,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glUniform3uiv(GLint location, GLsizei count, const GLuint * value)
- Convenience function that calls glUniform3uiv(\a location, count, \a value).
+ Convenience function that calls glUniform3uiv(\a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4858,7 +4858,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glActiveShaderProgram(GLuint pipeline, GLuint program)
- Convenience function that calls glActiveShaderProgram(pipeline, program).
+ Convenience function that calls glActiveShaderProgram(\a pipeline, \a program).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4869,9 +4869,9 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
*/
/*!
- \fn void QOpenGLFunctions::glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)
+ \fn void QOpenGLExtraFunctions::glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)
- Convenience function that calls glBindImageTexture(unit, texture, level, layered, layer, access, format).
+ Convenience function that calls glBindImageTexture(\a unit, \a texture, \a level, \a layered, \a layer, \a access, \a format).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4884,7 +4884,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glBindProgramPipeline(GLuint pipeline)
- Convenience function that calls glBindProgramPipeline(pipeline).
+ Convenience function that calls glBindProgramPipeline(\a pipeline).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4897,7 +4897,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
- Convenience function that calls glBindVertexBuffer(bindingindex, buffer, offset, stride).
+ Convenience function that calls glBindVertexBuffer(\a bindingindex, \a buffer, \a offset, \a stride).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4910,7 +4910,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn GLuint QOpenGLExtraFunctions::glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const* strings)
- Convenience function that calls glCreateShaderProgramv(type, count, strings).
+ Convenience function that calls glCreateShaderProgramv(\a type, \a count, \a strings).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4923,7 +4923,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glDeleteProgramPipelines(GLsizei n, const GLuint * pipelines)
- Convenience function that calls glDeleteProgramPipelines(n, pipelines).
+ Convenience function that calls glDeleteProgramPipelines(\a n, \a pipelines).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4936,7 +4936,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
- Convenience function that calls glDispatchCompute(num_groups_x, num_groups_y, num_groups_z).
+ Convenience function that calls glDispatchCompute(\a num_groups_x, \a num_groups_y, \a num_groups_z).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4949,7 +4949,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glDispatchComputeIndirect(GLintptr indirect)
- Convenience function that calls glDispatchComputeIndirect(indirect).
+ Convenience function that calls glDispatchComputeIndirect(\a indirect).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4962,7 +4962,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glDrawArraysIndirect(GLenum mode, const void * indirect)
- Convenience function that calls glDrawArraysIndirect(mode, indirect).
+ Convenience function that calls glDrawArraysIndirect(\a mode, \a indirect).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4975,7 +4975,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glDrawElementsIndirect(GLenum mode, GLenum type, const void * indirect)
- Convenience function that calls glDrawElementsIndirect(mode, type, indirect).
+ Convenience function that calls glDrawElementsIndirect(\a mode, \a type, \a indirect).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -4988,7 +4988,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glFramebufferParameteri(GLenum target, GLenum pname, GLint param)
- Convenience function that calls glFramebufferParameteri(target, pname, param).
+ Convenience function that calls glFramebufferParameteri(\a target, \a pname, \a param).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5001,7 +5001,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGenProgramPipelines(GLsizei n, GLuint* pipelines)
- Convenience function that calls glGenProgramPipelines(n, pipelines).
+ Convenience function that calls glGenProgramPipelines(\a n, \a pipelines).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5014,7 +5014,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetBooleani_v(GLenum target, GLuint index, GLboolean* data)
- Convenience function that calls glGetBooleani_v(target, index, data).
+ Convenience function that calls glGetBooleani_v(\a target, \a index, \a data).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5027,7 +5027,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params)
- Convenience function that calls glGetFramebufferParameteriv(target, pname, params).
+ Convenience function that calls glGetFramebufferParameteriv(\a target, \a pname, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5040,7 +5040,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetMultisamplefv(GLenum pname, GLuint index, GLfloat* val)
- Convenience function that calls glGetMultisamplefv(pname, index, val).
+ Convenience function that calls glGetMultisamplefv(\a pname, \a index, \a val).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5053,7 +5053,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params)
- Convenience function that calls glGetProgramInterfaceiv(program, programInterface, pname, params).
+ Convenience function that calls glGetProgramInterfaceiv(\a program, \a programInterface, \a pname, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5066,7 +5066,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog)
- Convenience function that calls glGetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog).
+ Convenience function that calls glGetProgramPipelineInfoLog(\a pipeline, \a bufSize, \a length, \a infoLog).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5079,7 +5079,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint* params)
- Convenience function that calls glGetProgramPipelineiv(pipeline, pname, params).
+ Convenience function that calls glGetProgramPipelineiv(\a pipeline, \a pname, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5092,7 +5092,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn GLuint QOpenGLExtraFunctions::glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar * name)
- Convenience function that calls glGetProgramResourceIndex(program, programInterface, name).
+ Convenience function that calls glGetProgramResourceIndex(\a program, \a programInterface, \a name).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5105,7 +5105,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn GLint QOpenGLExtraFunctions::glGetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar * name)
- Convenience function that calls glGetProgramResourceLocation(program, programInterface, name).
+ Convenience function that calls glGetProgramResourceLocation(\a program, \a programInterface, \a name).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5118,7 +5118,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name)
- Convenience function that calls glGetProgramResourceName(program, programInterface, index, bufSize, length, name).
+ Convenience function that calls glGetProgramResourceName(\a program, \a programInterface, \a index, \a bufSize, \a length, \a name).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5131,7 +5131,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei* length, GLint* params)
- Convenience function that calls glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length, params).
+ Convenience function that calls glGetProgramResourceiv(\a program, \a programInterface, \a index, \a propCount, \a props, \a bufSize, \a length, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5144,7 +5144,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params)
- Convenience function that calls glGetTexLevelParameterfv(target, level, pname, params).
+ Convenience function that calls glGetTexLevelParameterfv(\a target, \a level, \a pname, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5157,7 +5157,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params)
- Convenience function that calls glGetTexLevelParameteriv(target, level, pname, params).
+ Convenience function that calls glGetTexLevelParameteriv(\a target, \a level, \a pname, \a params).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5170,7 +5170,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn GLboolean QOpenGLExtraFunctions::glIsProgramPipeline(GLuint pipeline)
- Convenience function that calls glIsProgramPipeline(pipeline).
+ Convenience function that calls glIsProgramPipeline(\a pipeline).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5183,7 +5183,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glMemoryBarrier(GLbitfield barriers)
- Convenience function that calls glMemoryBarrier(barriers).
+ Convenience function that calls glMemoryBarrier(\a barriers).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5196,7 +5196,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glMemoryBarrierByRegion(GLbitfield barriers)
- Convenience function that calls glMemoryBarrierByRegion(barriers).
+ Convenience function that calls glMemoryBarrierByRegion(\a barriers).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5209,7 +5209,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1f(GLuint program, GLint location, GLfloat v0)
- Convenience function that calls glProgramUniform1f(program, location, v0).
+ Convenience function that calls glProgramUniform1f(\a program, \a location, \a v0).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5222,7 +5222,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat * value)
- Convenience function that calls glProgramUniform1fv(program, location, count, value).
+ Convenience function that calls glProgramUniform1fv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5235,7 +5235,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1i(GLuint program, GLint location, GLint v0)
- Convenience function that calls glProgramUniform1i(program, location, v0).
+ Convenience function that calls glProgramUniform1i(\a program, \a location, \a v0).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5248,7 +5248,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1iv(GLuint program, GLint location, GLsizei count, const GLint * value)
- Convenience function that calls glProgramUniform1iv(program, location, count, value).
+ Convenience function that calls glProgramUniform1iv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5261,7 +5261,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1ui(GLuint program, GLint location, GLuint v0)
- Convenience function that calls glProgramUniform1ui(program, location, v0).
+ Convenience function that calls glProgramUniform1ui(\a program, \a location, \a v0).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5274,7 +5274,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint * value)
- Convenience function that calls glProgramUniform1uiv(program, location, count, value).
+ Convenience function that calls glProgramUniform1uiv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5287,7 +5287,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
- Convenience function that calls glProgramUniform2f(program, location, v0, v1).
+ Convenience function that calls glProgramUniform2f(\a program, \a location, \a v0, \a v1).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5300,7 +5300,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat * value)
- Convenience function that calls glProgramUniform2fv(program, location, count, value).
+ Convenience function that calls glProgramUniform2fv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5313,7 +5313,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
- Convenience function that calls glProgramUniform2i(program, location, v0, v1).
+ Convenience function that calls glProgramUniform2i(\a program, \a location, \a v0, \a v1).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5326,7 +5326,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2iv(GLuint program, GLint location, GLsizei count, const GLint * value)
- Convenience function that calls glProgramUniform2iv(program, location, count, value).
+ Convenience function that calls glProgramUniform2iv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5339,7 +5339,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
- Convenience function that calls glProgramUniform2ui(program, location, v0, v1).
+ Convenience function that calls glProgramUniform2ui(\a program, \a location, \a v0, \a v1).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5352,7 +5352,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint * value)
- Convenience function that calls glProgramUniform2uiv(program, location, count, value).
+ Convenience function that calls glProgramUniform2uiv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5365,7 +5365,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
- Convenience function that calls glProgramUniform3f(program, location, v0, v1, v2).
+ Convenience function that calls glProgramUniform3f(\a program, \a location, \a v0, \a v1, \a v2).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5378,7 +5378,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat * value)
- Convenience function that calls glProgramUniform3fv(program, location, count, value).
+ Convenience function that calls glProgramUniform3fv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5391,7 +5391,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
- Convenience function that calls glProgramUniform3i(program, location, v0, v1, v2).
+ Convenience function that calls glProgramUniform3i(\a program, \a location, \a v0, \a v1, \a v2).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5404,7 +5404,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3iv(GLuint program, GLint location, GLsizei count, const GLint * value)
- Convenience function that calls glProgramUniform3iv(program, location, count, value).
+ Convenience function that calls glProgramUniform3iv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5417,7 +5417,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
- Convenience function that calls glProgramUniform3ui(program, location, v0, v1, v2).
+ Convenience function that calls glProgramUniform3ui(\a program, \a location, \a v0, \a v1, \a v2).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5430,7 +5430,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint * value)
- Convenience function that calls glProgramUniform3uiv(program, location, count, value).
+ Convenience function that calls glProgramUniform3uiv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5443,7 +5443,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
- Convenience function that calls glProgramUniform4f(program, location, v0, v1, v2, v3).
+ Convenience function that calls glProgramUniform4f(\a program, \a location, \a v0, \a v1, \a v2, \a v3).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5456,7 +5456,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat * value)
- Convenience function that calls glProgramUniform4fv(program, location, count, value).
+ Convenience function that calls glProgramUniform4fv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5469,7 +5469,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
- Convenience function that calls glProgramUniform4i(program, location, v0, v1, v2, v3).
+ Convenience function that calls glProgramUniform4i(\a program, \a location, \a v0, \a v1, \a v2, \a v3).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5482,7 +5482,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4iv(GLuint program, GLint location, GLsizei count, const GLint * value)
- Convenience function that calls glProgramUniform4iv(program, location, count, value).
+ Convenience function that calls glProgramUniform4iv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5495,7 +5495,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
- Convenience function that calls glProgramUniform4ui(program, location, v0, v1, v2, v3).
+ Convenience function that calls glProgramUniform4ui(\a program, \a location, \a v0, \a v1, \a v2, \a v3).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5508,7 +5508,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint * value)
- Convenience function that calls glProgramUniform4uiv(program, location, count, value).
+ Convenience function that calls glProgramUniform4uiv(\a program, \a location, \a count, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5521,7 +5521,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix2fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix2fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5534,7 +5534,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix2x3fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix2x3fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5547,7 +5547,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix2x4fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix2x4fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5560,7 +5560,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix3fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix3fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5573,7 +5573,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix3x2fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix3x2fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5586,7 +5586,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix3x4fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix3x4fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5599,7 +5599,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix4fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix4fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5612,7 +5612,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix4x2fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix4x2fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5625,7 +5625,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
- Convenience function that calls glProgramUniformMatrix4x3fv(program, location, count, transpose, value).
+ Convenience function that calls glProgramUniformMatrix4x3fv(\a program, \a location, \a count, \a transpose, \a value).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5638,7 +5638,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glSampleMaski(GLuint maskNumber, GLbitfield mask)
- Convenience function that calls glSampleMaski(maskNumber, mask).
+ Convenience function that calls glSampleMaski(\a maskNumber, \a mask).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5651,7 +5651,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)
- Convenience function that calls glTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations).
+ Convenience function that calls glTexStorage2DMultisample(\a target, \a samples, \a internalformat, \a width, \a height, \a fixedsamplelocations).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5664,7 +5664,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
- Convenience function that calls glUseProgramStages(pipeline, stages, program).
+ Convenience function that calls glUseProgramStages(\a pipeline, \a stages, \a program).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5677,7 +5677,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glValidateProgramPipeline(GLuint pipeline)
- Convenience function that calls glValidateProgramPipeline(pipeline).
+ Convenience function that calls glValidateProgramPipeline(\a pipeline).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5690,7 +5690,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glVertexAttribBinding(GLuint attribindex, GLuint bindingindex)
- Convenience function that calls glVertexAttribBinding(attribindex, bindingindex).
+ Convenience function that calls glVertexAttribBinding(\a attribindex, \a bindingindex).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5703,7 +5703,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
- Convenience function that calls glVertexAttribFormat(attribindex, size, type, normalized, relativeoffset).
+ Convenience function that calls glVertexAttribFormat(\a attribindex, \a size, \a type, \a normalized, \a relativeoffset).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5716,7 +5716,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
- Convenience function that calls glVertexAttribIFormat(attribindex, size, type, relativeoffset).
+ Convenience function that calls glVertexAttribIFormat(\a attribindex, \a size, \a type, \a relativeoffset).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -5729,7 +5729,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
/*!
\fn void QOpenGLExtraFunctions::glVertexBindingDivisor(GLuint bindingindex, GLuint divisor)
- Convenience function that calls glVertexBindingDivisor(bindingindex, divisor).
+ Convenience function that calls glVertexBindingDivisor(\a bindingindex, \a divisor).
This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
with plain OpenGL, the function is only usable when the given profile and version contains the
@@ -7398,10 +7398,25 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexBindingDivisor(GLuint binding
RESOLVE_FUNC_VOID(0, VertexBindingDivisor)(bindingindex, divisor);
}
+/*!
+ Constructs a default function resolver. The resolver cannot be used until
+ \l {QOpenGLFunctions::}{initializeOpenGLFunctions()} is called to specify
+ the context.
+*/
QOpenGLExtraFunctions::QOpenGLExtraFunctions()
{
}
+/*!
+ Constructs a function resolver for context. If \a context is null, then
+ the resolver will be created for the current QOpenGLContext.
+
+ The context or another context in the group must be current.
+
+ An object constructed in this way can only be used with context and other
+ contexts that share with it. Use \l {QOpenGLFunctions::}
+ {initializeOpenGLFunctions()} to change the object's context association.
+*/
QOpenGLExtraFunctions::QOpenGLExtraFunctions(QOpenGLContext *context)
: QOpenGLFunctions(context)
{
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index 41d53be31e..9714aa4bec 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -525,7 +525,8 @@ bool QOpenGLShader::compileSourceCode(const char *source)
// The precision qualifiers are useful on OpenGL/ES systems,
// but usually not present on desktop systems.
- const QSurfaceFormat currentSurfaceFormat = QOpenGLContext::currentContext()->format();
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ const QSurfaceFormat currentSurfaceFormat = ctx->format();
QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext());
if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL
|| ctx_d->workaround_missingPrecisionQualifiers
@@ -545,10 +546,16 @@ bool QOpenGLShader::compileSourceCode(const char *source)
}
#endif
- // Append #line directive in order to compensate for text insertion
- QByteArray lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8();
- sourceChunks.append(lineDirective.constData());
- sourceChunkLengths.append(GLint(lineDirective.length()));
+ QByteArray lineDirective;
+ // #line is rejected by some drivers:
+ // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel"
+ const char *version = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VERSION));
+ if (!version || !strstr(version, "2.1 Mesa 8")) {
+ // Append #line directive in order to compensate for text insertion
+ lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8();
+ sourceChunks.append(lineDirective.constData());
+ sourceChunkLengths.append(GLint(lineDirective.length()));
+ }
// Append rest of shader code
sourceChunks.append(source + versionDirectivePosition.position);
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 0cf7e20605..64a363868a 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6326,8 +6326,6 @@ template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4
void qInitDrawhelperAsm()
{
- const uint features = qCpuFeatures();
- Q_UNUSED(features);
#ifdef __SSE2__
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
@@ -6372,7 +6370,7 @@ void qInitDrawhelperAsm()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2;
#ifdef QT_COMPILER_SUPPORTS_SSSE3
- if (features & SSSE3) {
+ if (qCpuHasFeature(SSSE3)) {
extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
@@ -6466,7 +6464,7 @@ void qInitDrawhelperAsm()
#endif // Q_PROCESSOR_MIPS_32
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
- if (features & (DSP | DSPR2)) {
+ if (qCpuHasFeature(DSP) && qCpuHasFeature(DSPR2)) {
// Composition functions are all DSP r1
qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp;
qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp;
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 7b6a71737d..33dccc5374 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -305,7 +305,10 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
for (int x = 0; x < dw; x++) {
const unsigned int *pix = sptr + xpoints[x];
const int xap = xapoints[x];
- *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
+ if (xap > 0)
+ *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
+ else
+ *dptr = pix[0];
dptr++;
}
}
diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h
index c360573e78..72a6ca4cb3 100644
--- a/src/gui/painting/qpaintdevice.h
+++ b/src/gui/painting/qpaintdevice.h
@@ -81,7 +81,7 @@ public:
int colorCount() const { return metric(PdmNumColors); }
int depth() const { return metric(PdmDepth); }
- static inline qreal devicePixelRatioFScale() {return 10000000.0; }
+ static inline qreal devicePixelRatioFScale() { return 0x10000; }
protected:
QPaintDevice() Q_DECL_NOEXCEPT;
virtual int metric(PaintDeviceMetric metric) const;
diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc
index a83acdd21a..ef5deb154d 100644
--- a/src/gui/painting/qpaintdevice.qdoc
+++ b/src/gui/painting/qpaintdevice.qdoc
@@ -118,7 +118,13 @@
values are 1 for normal-dpi displays and 2 for high-dpi "retina"
displays.
- \sa metric()
+ \value PdmDevicePixelRatioScaled The scaled device pixel ratio for the device.
+ This is identical to PdmDevicePixelRatio, except that the value is scaled by a
+ constant factor in order to support paint devices with fractional scale factors.
+ The constant scaling factor used is devicePixelRatioFScale(). This enum value
+ has been introduced in Qt 5.6.
+
+ \sa metric(), devicePixelRatioF()
*/
/*!
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index e765a9e402..c86fdebea5 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -300,11 +300,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
}
funcs->glEnable(GL_BLEND);
- funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // Do not write out alpha. We need blending, but only for RGB. The toplevel may have
- // alpha enabled in which case blending (writing out < 1.0 alpha values) would lead to
- // semi-transparency even when it is not wanted.
- funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+ funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
// Backingstore texture with the normal widgets.
GLuint textureId = 0;
@@ -364,7 +360,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
}
- funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
funcs->glDisable(GL_BLEND);
d_ptr->blitter->release();
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index 75bf31cde1..34d72bf493 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -863,8 +863,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iLeft = int(left);
const Q16Dot16 iRight = int(right);
const Q16Dot16 leftWidth = IntToQ16Dot16(iLeft + 1)
- - FloatToQ16Dot16(left);
- const Q16Dot16 rightWidth = FloatToQ16Dot16(right)
+ - qSafeFloatToQ16Dot16(left);
+ const Q16Dot16 rightWidth = qSafeFloatToQ16Dot16(right)
- IntToQ16Dot16(iRight);
Q16Dot16 coverage[3];
@@ -898,8 +898,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iTopFP = IntToQ16Dot16(int(pa.y()));
const Q16Dot16 iBottomFP = IntToQ16Dot16(int(pb.y()));
- const Q16Dot16 yPa = FloatToQ16Dot16(pa.y());
- const Q16Dot16 yPb = FloatToQ16Dot16(pb.y());
+ const Q16Dot16 yPa = qSafeFloatToQ16Dot16(pa.y());
+ const Q16Dot16 yPb = qSafeFloatToQ16Dot16(pb.y());
for (Q16Dot16 yFP = iTopFP; yFP <= iBottomFP; yFP += Q16Dot16Factor) {
const Q16Dot16 rowHeight = qMin(yFP + Q16Dot16Factor, yPb)
- qMax(yFP, yPa);
@@ -983,16 +983,16 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const Q16Dot16 iRightFP = IntToQ16Dot16(int(right.y()));
const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound));
- Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
- Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
+ Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
+ Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
Q16Dot16 leftIntersectBf = 0;
Q16Dot16 rightIntersectBf = 0;
if (iLeftFP < iTopFP)
- leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
+ leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
if (iRightFP < iTopFP)
- rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
+ rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom;
Q16Dot16 topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf;
@@ -1000,10 +1000,10 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
int leftMin, leftMax, rightMin, rightMax;
- const Q16Dot16 yTopFP = FloatToQ16Dot16(top.y());
- const Q16Dot16 yLeftFP = FloatToQ16Dot16(left.y());
- const Q16Dot16 yRightFP = FloatToQ16Dot16(right.y());
- const Q16Dot16 yBottomFP = FloatToQ16Dot16(bottom.y());
+ const Q16Dot16 yTopFP = qSafeFloatToQ16Dot16(top.y());
+ const Q16Dot16 yLeftFP = qSafeFloatToQ16Dot16(left.y());
+ const Q16Dot16 yRightFP = qSafeFloatToQ16Dot16(right.y());
+ const Q16Dot16 yBottomFP = qSafeFloatToQ16Dot16(bottom.y());
rowTop = qMax(iTopFP, yTopFP);
topLeftIntersectAf = leftIntersectAf +
@@ -1021,7 +1021,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (yFP == iLeftFP) {
const int y = Q16Dot16ToInt(yFP);
- leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
+ leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP);
bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP);
} else {
@@ -1031,7 +1031,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (yFP == iRightFP) {
const int y = Q16Dot16ToInt(yFP);
- rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
+ rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP);
bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP);
} else {
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index b701b224be..264ec394cd 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -58,33 +58,34 @@ class QRgba64 {
#endif
};
+ // No constructors are allowed in C++98, since this needs to be usable in a union.
+ // We however require one for constexprs in C++11/C++14
+#ifdef Q_COMPILER_CONSTEXPR
+ explicit Q_ALWAYS_INLINE Q_DECL_CONSTEXPR QRgba64(quint64 c) : rgba(c) { }
+#endif
public:
- // No constructors are allowed, since this needs to be usable in a union in no-c++11 mode.
- // When c++11 is mandatory, we can add all but a copy constructor.
- Q_DECL_RELAXED_CONSTEXPR static
- QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
- {
- QRgba64 rgba64
-#ifdef Q_COMPILER_UNIFORM_INIT
- = {}
+#ifdef Q_COMPILER_CONSTEXPR
+ Q_ALWAYS_INLINE Q_DECL_CONSTEXPR QRgba64() : rgba(0) { }
#endif
- ;
- rgba64.rgba = quint64(red) << RedShift
- | quint64(green) << GreenShift
- | quint64(blue) << BlueShift
- | quint64(alpha) << AlphaShift;
- return rgba64;
- }
- Q_DECL_RELAXED_CONSTEXPR static
+
+ Q_DECL_CONSTEXPR static
QRgba64 fromRgba64(quint64 c)
{
- QRgba64 rgba64
-#ifdef Q_COMPILER_UNIFORM_INIT
- = {}
-#endif
- ;
+#ifdef Q_COMPILER_CONSTEXPR
+ return QRgba64(c);
+#else
+ QRgba64 rgba64;
rgba64.rgba = c;
return rgba64;
+#endif
+ }
+ Q_DECL_CONSTEXPR static
+ QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
+ {
+ return fromRgba64(quint64(red) << RedShift
+ | quint64(green) << GreenShift
+ | quint64(blue) << BlueShift
+ | quint64(alpha) << AlphaShift);
}
Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
{
@@ -112,10 +113,10 @@ public:
Q_DECL_CONSTEXPR quint16 green() const { return rgba >> GreenShift; }
Q_DECL_CONSTEXPR quint16 blue() const { return rgba >> BlueShift; }
Q_DECL_CONSTEXPR quint16 alpha() const { return rgba >> AlphaShift; }
- void setRed(quint16 _red) { *this = fromRgba64(_red, green(), blue(), alpha()); }
- void setGreen(quint16 _green) { *this = fromRgba64(red(), _green, blue(), alpha()); }
- void setBlue(quint16 _blue) { *this = fromRgba64(red(), green(), _blue, alpha()); }
- void setAlpha(quint16 _alpha) { *this = fromRgba64(red(), green(), blue(), _alpha); }
+ void setRed(quint16 _red) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << RedShift)) | (quint64(_red) << RedShift); }
+ void setGreen(quint16 _green) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << GreenShift)) | (quint64(_green) << GreenShift); }
+ void setBlue(quint16 _blue) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << BlueShift)) | (quint64(_blue) << BlueShift); }
+ void setAlpha(quint16 _alpha) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << AlphaShift)) | (quint64(_alpha) << AlphaShift); }
Q_DECL_CONSTEXPR quint8 red8() const { return div_257(red()); }
Q_DECL_CONSTEXPR quint8 green8() const { return div_257(green()); }
@@ -160,16 +161,16 @@ public:
}
private:
- static Q_DECL_CONSTEXPR quint64 alphaMask() { return quint64(0xffff) << AlphaShift; }
+ static Q_DECL_CONSTEXPR quint64 alphaMask() { return Q_UINT64_C(0xffff) << AlphaShift; }
static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; }
static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); }
static Q_DECL_CONSTEXPR uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_32bit() const
{
- const quint16 a = alpha();
- if (a == 0xffff || a == 0)
+ if (isOpaque() || isTransparent())
return *this;
+ const quint32 a = alpha();
const quint16 r = (quint32(red()) * 0xffff + a/2) / a;
const quint16 g = (quint32(green()) * 0xffff + a/2) / a;
const quint16 b = (quint32(blue()) * 0xffff + a/2) / a;
@@ -177,9 +178,9 @@ private:
}
Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_64bit() const
{
- const quint16 a = alpha();
- if (a == 0xffff || a == 0)
+ if (isOpaque() || isTransparent())
return *this;
+ const quint64 a = alpha();
const quint64 fa = (Q_UINT64_C(0xffff00008000) + a/2) / a;
const quint16 r = (red() * fa + 0x80000000) >> 32;
const quint16 g = (green() * fa + 0x80000000) >> 32;
@@ -190,12 +191,12 @@ private:
Q_DECLARE_TYPEINFO(QRgba64, Q_PRIMITIVE_TYPE);
-Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
+Q_DECL_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
{
return QRgba64::fromRgba64(r, g, b, a);
}
-Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint64 c)
+Q_DECL_CONSTEXPR inline QRgba64 qRgba64(quint64 c)
{
return QRgba64::fromRgba64(c);
}
diff --git a/src/gui/painting/qrgba64.qdoc b/src/gui/painting/qrgba64.qdoc
index 29da0aa390..b786e91b03 100644
--- a/src/gui/painting/qrgba64.qdoc
+++ b/src/gui/painting/qrgba64.qdoc
@@ -36,13 +36,19 @@
QRgba64 is a 64-bit data-structure containing four 16-bit color channels: Red, green, blue and alpha.
QRgba64 can be used a replacement for QRgb when higher precision is needed. In particular a
- premultiplied QRgba64 can operate on unpremultipled QRgb without loss of precision except
+ premultiplied QRgba64 can operate on unpremultiplied QRgb without loss of precision except
for alpha 0.
\sa QRgb, QColor
*/
/*!
+ \fn QRgba64 QRgba64::operator=(quint64 rgba)
+
+ Assigns the value \a rgba to this instance of QRgba64 and returns it.
+*/
+
+/*!
\fn static QRgba64 QRgba64::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
Returns the QRgba64 quadruplet (\a{r}, \a{g}, \a{b}, \a{a}).
@@ -75,27 +81,83 @@
*/
/*!
+ \fn bool QRgba64::isOpaque() const
+
+ Returns whether the color is fully opaque.
+
+ \sa isTransparent(), alpha()
+*/
+
+/*!
+ \fn bool QRgba64::isTransparent() const
+
+ Returns whether the color is transparent.
+
+ \sa isOpaque(), alpha()
+*/
+
+/*!
\fn quint16 QRgba64::red() const
Returns the 16-bit red color component.
+
+ \sa setRed()
+*/
+
+/*!
+ \fn QRgba64::setRed(quint16 red)
+
+ Sets the red color component of this color to \a red.
+
+ \sa red()
*/
/*!
\fn quint16 QRgba64::green() const
Returns the 16-bit green color component.
+
+ \sa setGreen()
+*/
+
+/*!
+ \fn QRgba64::setGreen(quint16 green)
+
+ Sets the green color component of this color to \a green.
+
+ \sa green()
*/
/*!
\fn quint16 QRgba64::blue() const
Returns the 16-bit blue color component.
+
+ \sa setBlue()
+*/
+
+/*!
+ \fn QRgba64::setBlue(quint16 blue)
+
+ Sets the blue color component of this color to \a blue.
+
+ \sa blue()
*/
/*!
\fn quint16 QRgba64::alpha() const
Returns the 16-bit alpha channel.
+
+ \sa setAlpha()
+*/
+
+/*!
+ \fn QRgba64::setAlpha(quint16 alpha)
+
+ Sets the alpha of this color to \a alpha.
+
+ \sa alpha()
*/
/*!
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 796f223797..7d9d00713c 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2218,6 +2218,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
}
if (s.version() >= QDataStream::Qt_5_4)
s << (quint8)font.d->request.hintingPreference;
+ if (s.version() >= QDataStream::Qt_5_6)
+ s << (quint8)font.d->capital;
return s;
}
@@ -2308,7 +2310,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
s >> value;
font.d->request.hintingPreference = QFont::HintingPreference(value);
}
-
+ if (s.version() >= QDataStream::Qt_5_6) {
+ quint8 value;
+ s >> value;
+ font.d->capital = QFont::Capitalization(value);
+ }
return s;
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index f9d924d10a..bef4dc5547 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -54,6 +54,7 @@
#include <private/qharfbuzz_p.h>
#include <algorithm>
+#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -74,6 +75,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
}
}
+template<typename T>
+static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output)
+{
+ if (source + sizeof(T) > end)
+ return false;
+
+ *output = qFromBigEndian<T>(source);
+ return true;
+}
+
// Harfbuzz helper functions
#ifdef QT_ENABLE_HARFBUZZ_NG
@@ -225,10 +236,14 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines()
// QFontEngine
+#define kBearingNotInitialized std::numeric_limits<qreal>::max()
+
QFontEngine::QFontEngine(Type type)
: m_type(type), ref(0),
font_(0), font_destroy_func(0),
- face_(0), face_destroy_func(0)
+ face_(0), face_destroy_func(0),
+ m_minLeftBearing(kBearingNotInitialized),
+ m_minRightBearing(kBearingNotInitialized)
{
faceData.user_data = this;
faceData.get_font_table = qt_get_font_table_default;
@@ -552,11 +567,91 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
{
glyph_metrics_t gi = boundingBox(glyph);
- bool isValid = gi.isValid();
if (leftBearing != 0)
- *leftBearing = isValid ? gi.x.toReal() : 0.0;
+ *leftBearing = gi.leftBearing().toReal();
if (rightBearing != 0)
- *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0;
+ *rightBearing = gi.rightBearing().toReal();
+}
+
+qreal QFontEngine::minLeftBearing() const
+{
+ if (m_minLeftBearing == kBearingNotInitialized)
+ minRightBearing(); // Initializes both (see below)
+
+ return m_minLeftBearing;
+}
+
+#define q16Dot16ToFloat(i) ((i) / 65536.0)
+
+#define kMinLeftSideBearingOffset 12
+#define kMinRightSideBearingOffset 14
+
+qreal QFontEngine::minRightBearing() const
+{
+ if (m_minRightBearing == kBearingNotInitialized) {
+
+ // Try the 'hhea' font table first, which covers the entire font
+ QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ if (hheaTable.size() >= int(kMinRightSideBearingOffset + sizeof(qint16))) {
+ const uchar *tableData = reinterpret_cast<const uchar *>(hheaTable.constData());
+ Q_ASSERT(q16Dot16ToFloat(qFromBigEndian<quint32>(tableData)) == 1.0);
+
+ qint16 minLeftSideBearing = qFromBigEndian<qint16>(tableData + kMinLeftSideBearingOffset);
+ qint16 minRightSideBearing = qFromBigEndian<qint16>(tableData + kMinRightSideBearingOffset);
+
+ // The table data is expressed as FUnits, meaning we have to take the number
+ // of units per em into account. Since pixelSize already has taken DPI into
+ // account we can use that directly instead of the point size.
+ int unitsPerEm = emSquareSize().toInt();
+ qreal funitToPixelFactor = fontDef.pixelSize / unitsPerEm;
+
+ // Some fonts on OS X (such as Gurmukhi Sangam MN, Khmer MN, Lao Sangam MN, etc.), have
+ // invalid values for their NBSPACE left bearing, causing the 'hhea' minimum bearings to
+ // be way off. We detect this by assuming that the minimum bearsings are within a certain
+ // range of the em square size.
+ static const int largestValidBearing = 4 * unitsPerEm;
+
+ if (qAbs(minLeftSideBearing) < largestValidBearing)
+ m_minLeftBearing = minLeftSideBearing * funitToPixelFactor;
+ if (qAbs(minRightSideBearing) < largestValidBearing)
+ m_minRightBearing = minRightSideBearing * funitToPixelFactor;
+ }
+
+ // Fallback in case of missing 'hhea' table (bitmap fonts e.g.) or broken 'hhea' values
+ if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) {
+
+ // To balance performance and correctness we only look at a subset of the
+ // possible glyphs in the font, based on which characters are more likely
+ // to have a left or right bearing.
+ static const ushort characterSubset[] = {
+ '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|',
+ 127, 205, 645, 884, 922, 1070, 12386
+ };
+
+ // The font may have minimum bearings larger than 0, so we have to start at the max
+ m_minLeftBearing = m_minRightBearing = std::numeric_limits<qreal>::max();
+
+ for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) {
+ const glyph_t glyph = glyphIndex(characterSubset[i]);
+ if (!glyph)
+ continue;
+
+ glyph_metrics_t glyphMetrics = const_cast<QFontEngine *>(this)->boundingBox(glyph);
+
+ // Glyphs with no contours shouldn't contribute to bearings
+ if (!glyphMetrics.width || !glyphMetrics.height)
+ continue;
+
+ m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal());
+ m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal());
+ }
+ }
+
+ if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized)
+ qWarning() << "Failed to compute left/right minimum bearings for" << fontDef.family;
+ }
+
+ return m_minRightBearing;
}
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
@@ -1039,26 +1134,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
return;
const uchar *table = reinterpret_cast<const uchar *>(tab.constData());
+ const uchar *end = table + tab.size();
+
+ quint16 version;
+ if (!qSafeFromBigEndian(table, end, &version))
+ return;
- unsigned short version = qFromBigEndian<quint16>(table);
if (version != 0) {
// qDebug("wrong version");
return;
}
- unsigned short numTables = qFromBigEndian<quint16>(table + 2);
+ quint16 numTables;
+ if (!qSafeFromBigEndian(table + 2, end, &numTables))
+ return;
+
{
int offset = 4;
for(int i = 0; i < numTables; ++i) {
- if (offset + 6 > tab.size()) {
-// qDebug("offset out of bounds");
- goto end;
- }
const uchar *header = table + offset;
- ushort version = qFromBigEndian<quint16>(header);
- ushort length = qFromBigEndian<quint16>(header+2);
- ushort coverage = qFromBigEndian<quint16>(header+4);
+ quint16 version;
+ if (!qSafeFromBigEndian(header, end, &version))
+ goto end;
+
+ quint16 length;
+ if (!qSafeFromBigEndian(header + 2, end, &length))
+ goto end;
+
+ quint16 coverage;
+ if (!qSafeFromBigEndian(header + 4, end, &coverage))
+ goto end;
+
// qDebug("subtable: version=%d, coverage=%x",version, coverage);
if(version == 0 && coverage == 0x0001) {
if (offset + length > tab.size()) {
@@ -1067,7 +1174,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
}
const uchar *data = table + offset + 6;
- ushort nPairs = qFromBigEndian<quint16>(data);
+ quint16 nPairs;
+ if (!qSafeFromBigEndian(data, end, &nPairs))
+ goto end;
+
if(nPairs * 6 + 8 > length - 6) {
// qDebug("corrupt table!");
// corrupt table
@@ -1077,8 +1187,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
int off = 8;
for(int i = 0; i < nPairs; ++i) {
QFontEngine::KernPair p;
- p.left_right = (((uint)qFromBigEndian<quint16>(data+off)) << 16) + qFromBigEndian<quint16>(data+off+2);
- p.adjust = QFixed(((int)(short)qFromBigEndian<quint16>(data+off+4))) / scalingFactor;
+
+ quint16 tmp;
+ if (!qSafeFromBigEndian(data + off, end, &tmp))
+ goto end;
+
+ p.left_right = uint(tmp) << 16;
+ if (!qSafeFromBigEndian(data + off + 2, end, &tmp))
+ goto end;
+
+ p.left_right |= tmp;
+
+ if (!qSafeFromBigEndian(data + off + 4, end, &tmp))
+ goto end;
+
+ p.adjust = QFixed(int(short(tmp))) / scalingFactor;
kerning_pairs.append(p);
off += 6;
}
@@ -1098,26 +1221,31 @@ int QFontEngine::glyphCount() const
QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
if (maxpTable.size() < 6)
return 0;
- return qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(maxpTable.constData() + 4));
+
+ const uchar *source = reinterpret_cast<const uchar *>(maxpTable.constData() + 4);
+ const uchar *end = source + maxpTable.size();
+
+ quint16 count = 0;
+ qSafeFromBigEndian(source, end, &count);
+ return count;
}
const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize)
{
const uchar *header = table;
- if (tableSize < 4)
- return 0;
-
const uchar *endPtr = table + tableSize;
// version check
- if (qFromBigEndian<quint16>(header) != 0)
+ quint16 version;
+ if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0)
return 0;
- unsigned short numTables = qFromBigEndian<quint16>(header + 2);
- const uchar *maps = table + 4;
- if (maps + 8 * numTables > endPtr)
+ quint16 numTables;
+ if (!qSafeFromBigEndian(header + 2, endPtr, &numTables))
return 0;
+ const uchar *maps = table + 4;
+
enum {
Invalid,
AppleRoman,
@@ -1132,8 +1260,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
int tableToUse = -1;
int score = Invalid;
for (int n = 0; n < numTables; ++n) {
- const quint16 platformId = qFromBigEndian<quint16>(maps + 8 * n);
- const quint16 platformSpecificId = qFromBigEndian<quint16>(maps + 8 * n + 2);
+ quint16 platformId;
+ if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
+ return 0;
+
+ quint16 platformSpecificId;
+ if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId))
+ return 0;
+
switch (platformId) {
case 0: // Unicode
if (score < Unicode &&
@@ -1187,20 +1321,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
resolveTable:
*isSymbolFont = (symbolTable > -1);
- unsigned int unicode_table = qFromBigEndian<quint32>(maps + 8*tableToUse + 4);
+ quint32 unicode_table;
+ if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
+ return 0;
- if (!unicode_table || unicode_table + 8 > tableSize)
+ if (!unicode_table)
return 0;
// get the header of the unicode table
header = table + unicode_table;
- unsigned short format = qFromBigEndian<quint16>(header);
- unsigned int length;
- if(format < 8)
- length = qFromBigEndian<quint16>(header + 2);
- else
- length = qFromBigEndian<quint32>(header + 4);
+ quint16 format;
+ if (!qSafeFromBigEndian(header, endPtr, &format))
+ return 0;
+
+ quint32 length;
+ if (format < 8) {
+ quint16 tmp;
+ if (!qSafeFromBigEndian(header + 2, endPtr, &tmp))
+ return 0;
+ length = tmp;
+ } else {
+ if (!qSafeFromBigEndian(header + 4, endPtr, &length))
+ return 0;
+ }
if (table + unicode_table + length > endPtr)
return 0;
@@ -1215,7 +1359,7 @@ resolveTable:
// Check that none of the latin1 range are in the unicode table
bool unicodeTableHasLatin1 = false;
for (int uc=0x00; uc<0x100; ++uc) {
- if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
+ if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
unicodeTableHasLatin1 = true;
break;
}
@@ -1225,7 +1369,7 @@ resolveTable:
bool unicodeTableHasSymbols = false;
if (!unicodeTableHasLatin1) {
for (int uc=0xf000; uc<0xf100; ++uc) {
- if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) {
+ if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) {
unicodeTableHasSymbols = true;
break;
}
@@ -1243,12 +1387,17 @@ resolveTable:
return table + unicode_table;
}
-quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
+quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
{
- unsigned short format = qFromBigEndian<quint16>(cmap);
+ const uchar *end = cmap + cmapSize;
+ quint16 format;
+ if (!qSafeFromBigEndian(cmap, end, &format))
+ return 0;
+
if (format == 0) {
- if (unicode < 256)
- return (int) *(cmap+6+unicode);
+ const uchar *ptr = cmap + 6 + unicode;
+ if (unicode < 256 && ptr < end)
+ return quint32(*ptr);
} else if (format == 4) {
/* some fonts come with invalid cmap tables, where the last segment
specified end = start = rangeoffset = 0xffff, delta = 0x0001
@@ -1257,25 +1406,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
*/
if(unicode >= 0xffff)
return 0;
- quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
+
+ quint16 segCountX2;
+ if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
+ return 0;
+
const unsigned char *ends = cmap + 14;
+
int i = 0;
- for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
+ for (; i < segCountX2/2; ++i) {
+ quint16 codePoint;
+ if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
+ return 0;
+ if (codePoint >= unicode)
+ break;
+ }
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
- quint16 startIndex = qFromBigEndian<quint16>(idx);
+ quint16 startIndex;
+ if (!qSafeFromBigEndian(idx, end, &startIndex))
+ return 0;
if (startIndex > unicode)
return 0;
idx += segCountX2;
- qint16 idDelta = (qint16)qFromBigEndian<quint16>(idx);
+
+ quint16 tmp;
+ if (!qSafeFromBigEndian(idx, end, &tmp))
+ return 0;
+ qint16 idDelta = qint16(tmp);
+
idx += segCountX2;
- quint16 idRangeoffset_t = (quint16)qFromBigEndian<quint16>(idx);
+
+ quint16 idRangeoffset_t;
+ if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
+ return 0;
quint16 glyphIndex;
if (idRangeoffset_t) {
- quint16 id = qFromBigEndian<quint16>(idRangeoffset_t + 2*(unicode - startIndex) + idx);
+ quint16 id;
+ if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
+ return 0;
+
if (id)
glyphIndex = (idDelta + id) % 0x10000;
else
@@ -1285,13 +1458,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
}
return glyphIndex;
} else if (format == 6) {
- quint16 tableSize = qFromBigEndian<quint16>(cmap + 2);
+ quint16 tableSize;
+ if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
+ return 0;
- quint16 firstCode6 = qFromBigEndian<quint16>(cmap + 6);
+ quint16 firstCode6;
+ if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
+ return 0;
if (unicode < firstCode6)
return 0;
- quint16 entryCount6 = qFromBigEndian<quint16>(cmap + 8);
+ quint16 entryCount6;
+ if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
+ return 0;
if (entryCount6 * 2 + 10 > tableSize)
return 0;
@@ -1300,9 +1479,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
quint16 entryIndex6 = unicode - firstCode6;
- return qFromBigEndian<quint16>(cmap + 10 + (entryIndex6 * 2));
+
+ quint16 index = 0;
+ qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);
+ return index;
} else if (format == 12) {
- quint32 nGroups = qFromBigEndian<quint32>(cmap + 12);
+ quint32 nGroups;
+ if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
+ return 0;
cmap += 16; // move to start of groups
@@ -1310,13 +1494,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
while (left <= right) {
int middle = left + ( ( right - left ) >> 1 );
- quint32 startCharCode = qFromBigEndian<quint32>(cmap + 12*middle);
+ quint32 startCharCode;
+ if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
+ return 0;
+
if(unicode < startCharCode)
right = middle - 1;
else {
- quint32 endCharCode = qFromBigEndian<quint32>(cmap + 12*middle + 4);
- if(unicode <= endCharCode)
- return qFromBigEndian<quint32>(cmap + 12*middle + 8) + unicode - startCharCode;
+ quint32 endCharCode;
+ if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
+ return 0;
+
+ if (unicode <= endCharCode) {
+ quint32 index;
+ if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
+ return 0;
+
+ return index + unicode - startCharCode;
+ }
left = middle + 1;
}
}
@@ -1359,8 +1554,7 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)
glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1];
glyph_metrics_t gi = boundingBox(glyph);
if (gi.isValid())
- return round ? QFixed(qRound(gi.xoff - gi.x - gi.width))
- : QFixed(gi.xoff - gi.x - gi.width);
+ return round ? qRound(gi.rightBearing()) : gi.rightBearing();
}
return 0;
}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 246df127ad..0d28785aa1 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -688,7 +688,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
}
- lbearing = rbearing = SHRT_MIN;
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
FT_Face face = lockFace();
@@ -1258,54 +1257,6 @@ qreal QFontEngineFT::maxCharWidth() const
return metrics.max_advance >> 6;
}
-static const ushort char_table[] = {
- 40,
- 67,
- 70,
- 75,
- 86,
- 88,
- 89,
- 91,
- 95,
- 102,
- 114,
- 124,
- 127,
- 205,
- 645,
- 884,
- 922,
- 1070,
- 12386
-};
-
-static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
-
-
-qreal QFontEngineFT::minLeftBearing() const
-{
- if (lbearing == SHRT_MIN)
- (void) minRightBearing(); // calculates both
- return lbearing.toReal();
-}
-
-qreal QFontEngineFT::minRightBearing() const
-{
- if (rbearing == SHRT_MIN) {
- lbearing = rbearing = 0;
- for (int i = 0; i < char_table_entries; ++i) {
- const glyph_t glyph = glyphIndex(char_table[i]);
- if (glyph != 0) {
- glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyph);
- lbearing = qMin(lbearing, gi.x);
- rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
- }
- }
- }
- return rbearing.toReal();
-}
-
QFixed QFontEngineFT::lineThickness() const
{
return line_thickness;
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index b81e51bf2e..83f9a4ef3d 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -208,8 +208,6 @@ private:
virtual QFixed averageCharWidth() const Q_DECL_OVERRIDE;
virtual qreal maxCharWidth() const Q_DECL_OVERRIDE;
- virtual qreal minLeftBearing() const Q_DECL_OVERRIDE;
- virtual qreal minRightBearing() const Q_DECL_OVERRIDE;
virtual QFixed lineThickness() const Q_DECL_OVERRIDE;
virtual QFixed underlinePosition() const Q_DECL_OVERRIDE;
@@ -324,8 +322,6 @@ private:
int xsize;
int ysize;
- mutable QFixed lbearing;
- mutable QFixed rbearing;
QFixed line_thickness;
QFixed underline_position;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 5329a5f11a..5282a4033e 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -214,8 +214,8 @@ public:
virtual QFixed underlinePosition() const;
virtual qreal maxCharWidth() const = 0;
- virtual qreal minLeftBearing() const { return qreal(); }
- virtual qreal minRightBearing() const { return qreal(); }
+ virtual qreal minLeftBearing() const;
+ virtual qreal minRightBearing() const;
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
@@ -240,7 +240,7 @@ public:
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const;
static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
- static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode);
+ static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
@@ -323,6 +323,10 @@ private:
private:
QVariant m_userData;
+
+ mutable qreal m_minLeftBearing;
+ mutable qreal m_minRightBearing;
+
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp
index a678b4c8ea..f2e05631a3 100644
--- a/src/gui/text/qfontengine_qpf2.cpp
+++ b/src/gui/text/qfontengine_qpf2.cpp
@@ -322,9 +322,9 @@ bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) co
glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const
{
- glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && symbol && ucs4 < 0x100)
- glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
if (!findGlyph(glyph))
glyph = 0;
@@ -348,16 +348,16 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else {
QStringIterator it(str, str + len);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index d2b39f274c..160daa0cfd 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -107,6 +107,22 @@ struct Q_GUI_EXPORT glyph_metrics_t
glyph_metrics_t transformed(const QTransform &xform) const;
inline bool isValid() const {return x != 100000 && y != 100000;}
+
+ inline QFixed leftBearing() const
+ {
+ if (!isValid())
+ return QFixed();
+
+ return x;
+ }
+
+ inline QFixed rightBearing() const
+ {
+ if (!isValid())
+ return QFixed();
+
+ return xoff - x - width;
+ }
};
Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index d56b9cf1b1..d68a59fae3 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1656,8 +1656,8 @@ namespace {
bool checkFullOtherwiseExtend(QScriptLine &line);
QFixed calculateNewWidth(const QScriptLine &line) const {
- return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth
- - qMin(rightBearing, QFixed());
+ return line.textWidth + tmpData.textWidth + spaceData.textWidth
+ + softHyphenWidth + negativeRightBearing();
}
inline glyph_t currentGlyph() const
@@ -1677,33 +1677,51 @@ namespace {
}
}
- inline void adjustRightBearing(glyph_t glyph)
+ inline void calculateRightBearing(glyph_t glyph)
{
qreal rb;
fontEngine->getGlyphBearings(glyph, 0, &rb);
- rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
+
+ // We only care about negative right bearings, so we limit the range
+ // of the bearing here so that we can assume it's negative in the rest
+ // of the code, as well ase use QFixed(1) as a sentinel to represent
+ // the state where we have yet to compute the right bearing.
+ rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));
}
- inline void adjustRightBearing()
+ inline void calculateRightBearing()
{
if (currentPosition <= 0)
return;
- adjustRightBearing(currentGlyph());
+ calculateRightBearing(currentGlyph());
}
- inline void adjustPreviousRightBearing()
+ inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
- adjustRightBearing(previousGlyph);
+ calculateRightBearing(previousGlyph);
}
+ static const QFixed RightBearingNotCalculated;
+
inline void resetRightBearing()
{
- rightBearing = QFixed(1); // Any positive number is defined as invalid since only
- // negative right bearings are interesting to us.
+ rightBearing = RightBearingNotCalculated;
+ }
+
+ // We express the negative right bearing as an absolute number
+ // so that it can be applied to the width using addition.
+ inline QFixed negativeRightBearing() const
+ {
+ if (rightBearing == RightBearingNotCalculated)
+ return QFixed(0);
+
+ return qAbs(rightBearing);
}
};
+const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
+
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
{
LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal());
@@ -1856,7 +1874,7 @@ void QTextLine::layout_helper(int maxGlyphs)
current, lbh.logClusters, lbh.glyphs);
} else {
lbh.tmpData.length++;
- lbh.adjustPreviousRightBearing();
+ lbh.calculateRightBearingForPreviousGlyph();
}
line += lbh.tmpData;
goto found;
@@ -1938,22 +1956,36 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
}
- // The actual width of the text needs to take the right bearing into account. The
- // right bearing is left-ward, which means that if the rightmost pixel is to the right
- // of the advance of the glyph, the bearing will be negative. We flip the sign
- // for the code to be more readable. Logic borrowed from qfontmetrics.cpp.
- // We ignore the right bearing if the minimum negative bearing is too little to
- // expand the text beyond the edge.
if (sb_or_ws|breakany) {
- QFixed rightBearing = lbh.rightBearing; // store previous right bearing
- if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width)
- lbh.adjustRightBearing();
+ // To compute the final width of the text we need to take negative right bearing
+ // into account (negative right bearing means the glyph has pixel data past the
+ // advance length). Note that the negative right bearing is an absolute number,
+ // so that we can apply it to the width using straight forward addition.
+
+ // Store previous right bearing (for the already accepted glyph) in case we
+ // end up breaking due to the current glyph being too wide.
+ QFixed previousRightBearing = lbh.rightBearing;
+
+ // We skip calculating the right bearing if the minimum negative bearing is too
+ // small to possibly expand the text beyond the edge. Note that this optimization
+ // will in some cases fail, as the minimum right bearing reported by the font
+ // engine may not cover all the glyphs in the font. The result is that we think
+ // we don't need to break at the current glyph (because the right bearing is 0),
+ // and when we then end up breaking on the next glyph we compute the right bearing
+ // and end up with a line width that is slightly larger width than what was requested.
+ // Unfortunately we can't remove this optimization as it will slow down text
+ // layouting significantly, so we accept the slight correctnes issue.
+ if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
+ lbh.calculateRightBearing();
+
if (lbh.checkFullOtherwiseExtend(line)) {
- // we are too wide, fix right bearing
- if (rightBearing <= 0)
- lbh.rightBearing = rightBearing; // take from cache
+ // We are too wide to accept the next glyph with its bearing, so we restore the
+ // right bearing to that of the previous glyph (the one that was already accepted),
+ // so that the bearing can be be applied to the final width of the text below.
+ if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated)
+ lbh.rightBearing = previousRightBearing;
else
- lbh.adjustPreviousRightBearing();
+ lbh.calculateRightBearingForPreviousGlyph();
if (!breakany) {
line.textWidth += lbh.softHyphenWidth;
@@ -1970,10 +2002,14 @@ void QTextLine::layout_helper(int maxGlyphs)
LB_DEBUG("reached end of line");
lbh.checkFullOtherwiseExtend(line);
found:
- if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted
- lbh.adjustRightBearing();
line.textAdvance = line.textWidth;
- line.textWidth -= qMin(QFixed(), lbh.rightBearing);
+
+ // If right bearing has not been calculated yet, do that now
+ if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject)
+ lbh.calculateRightBearing();
+
+ // Then apply any negative right bearing
+ line.textWidth += lbh.negativeRightBearing();
if (line.length == 0) {
LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f",
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 6053466148..be002167cb 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -795,12 +795,6 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
*/
/*!
- \variable FileInfo::d
- \internal
- private pointer.
-*/
-
-/*!
\class QZipReader
\internal
\since 4.5
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 16ed67fbc0..c2d986ef3d 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -971,7 +971,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
for (int i = 0; i < channelCount; ++i) {
if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) {
channels[i].resendCurrent = false;
- channels[i].state = QHttpNetworkConnectionChannel::IdleState;
// if this is not possible, error will be emitted and connection terminated
if (!channels[i].resetUploadData())
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 98247b7df0..8980ed7a41 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE
// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp
+// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP
+// connection times out)
+// We use 3 because we can get a _q_error 3 times depending on the timing:
+static const int reconnectAttemptsDefault = 3;
+
QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
: socket(0)
, ssl(false)
@@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
, resendCurrent(false)
, lastStatus(0)
, pendingEncrypt(false)
- , reconnectAttempts(2)
+ , reconnectAttempts(reconnectAttemptsDefault)
, authMethod(QAuthenticatorPrivate::None)
, proxyAuthMethod(QAuthenticatorPrivate::None)
, authenticationCredentialsSent(false)
@@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init()
socket->setProxy(QNetworkProxy::NoProxy);
#endif
- // We want all signals (except the interactive ones) be connected as QueuedConnection
- // because else we're falling into cases where we recurse back into the socket code
- // and mess up the state. Always going to the event loop (and expecting that when reading/writing)
- // is safer.
+ // After some back and forth in all the last years, this is now a DirectConnection because otherwise
+ // the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers
+ // which behave slightly differently on Windows vs Linux
QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
this, SLOT(_q_bytesWritten(qint64)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(connected()),
this, SLOT(_q_connected()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(readyRead()),
this, SLOT(_q_readyRead()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
// The disconnected() and error() signals may already come
// while calling connectToHost().
@@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init()
qRegisterMetaType<QAbstractSocket::SocketError>();
QObject::connect(socket, SIGNAL(disconnected()),
this, SLOT(_q_disconnected()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(_q_error(QAbstractSocket::SocketError)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
#ifndef QT_NO_NETWORKPROXY
@@ -147,7 +151,7 @@ void QHttpNetworkConnectionChannel::init()
// won't be a sslSocket if encrypt is false
QObject::connect(sslSocket, SIGNAL(encrypted()),
this, SLOT(_q_encrypted()),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(_q_sslErrors(QList<QSslError>)),
Qt::DirectConnection);
@@ -156,7 +160,7 @@ void QHttpNetworkConnectionChannel::init()
Qt::DirectConnection);
QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
this, SLOT(_q_encryptedBytesWritten(qint64)),
- Qt::QueuedConnection);
+ Qt::DirectConnection);
if (ignoreAllSslErrors)
sslSocket->ignoreSslErrors();
@@ -400,7 +404,7 @@ void QHttpNetworkConnectionChannel::allDone()
// reset the reconnection attempts after we receive a complete reply.
// in case of failures, each channel will attempt two reconnects before emitting error.
- reconnectAttempts = 2;
+ reconnectAttempts = reconnectAttemptsDefault;
// now the channel can be seen as free/idle again, all signal emissions for the reply have been done
if (state != QHttpNetworkConnectionChannel::ClosingState)
@@ -668,6 +672,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
+void QHttpNetworkConnectionChannel::resendCurrentRequest()
+{
+ requeueCurrentlyPipelinedRequests();
+ if (reply)
+ resendCurrent = true;
+ if (qobject_cast<QHttpNetworkConnection*>(connection))
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+}
+
bool QHttpNetworkConnectionChannel::isSocketBusy() const
{
return (state & QHttpNetworkConnectionChannel::BusyState);
@@ -711,8 +724,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
return;
}
- // read the available data before closing
- if (isSocketWaiting() || isSocketReading()) {
+ // read the available data before closing (also done in _q_error for other codepaths)
+ if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) {
if (reply) {
state = QHttpNetworkConnectionChannel::ReadingState;
_q_receiveReply();
@@ -724,7 +737,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
state = QHttpNetworkConnectionChannel::IdleState;
requeueCurrentlyPipelinedRequests();
- close();
+
+ pendingEncrypt = false;
}
@@ -806,11 +820,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
errorCode = QNetworkReply::ConnectionRefusedError;
break;
case QAbstractSocket::RemoteHostClosedError:
- // try to reconnect/resend before sending an error.
- // while "Reading" the _q_disconnected() will handle this.
- if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
+ // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer.
+ // Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket).
+ // The reconnectAttempts handling catches the cases where we can re-send the request.
+ if (!reply && state == QHttpNetworkConnectionChannel::IdleState) {
+ // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request
+ // is sent on them. No need to error the other replies below. Just bail out here.
+ // The _q_disconnected will handle the possibly pipelined replies
+ return;
+ } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
+ // Try to reconnect/resend before sending an error.
+ // While "Reading" the _q_disconnected() will handle this.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
} else {
errorCode = QNetworkReply::RemoteHostClosedError;
@@ -821,11 +843,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
if (!reply->d_func()->expectContent()) {
// No content expected, this is a valid way to have the connection closed by the server
+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) {
// There was no content-length header and it's not chunked encoding,
// so this is a valid way to have the connection closed by the server
+ // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState
+ QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection);
return;
}
// ok, we got a disconnect even though we did not expect it
@@ -835,24 +861,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// we can ignore the readbuffersize as the data is already
// in memory and we will not receive more data on the socket.
reply->setReadBufferSize(0);
+ reply->setDownstreamLimited(false);
_q_receiveReply();
-#ifndef QT_NO_SSL
- if (ssl) {
- // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket.
- // So we need to check this if the socket is a QSslSocket. When the socket is flushed
- // it will force a decrypt of the encrypted data in the plainsocket.
- QSslSocket *sslSocket = static_cast<QSslSocket*>(socket);
- qint64 beforeFlush = sslSocket->encryptedBytesAvailable();
- while (sslSocket->encryptedBytesAvailable()) {
- sslSocket->flush();
- _q_receiveReply();
- qint64 afterFlush = sslSocket->encryptedBytesAvailable();
- if (afterFlush == beforeFlush)
- break;
- beforeFlush = afterFlush;
- }
+ if (!reply) {
+ // No more reply assigned after the previous call? Then it had been finished successfully.
+ requeueCurrentlyPipelinedRequests();
+ state = QHttpNetworkConnectionChannel::IdleState;
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ return;
}
-#endif
}
errorCode = QNetworkReply::RemoteHostClosedError;
@@ -863,7 +880,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::SocketTimeoutError:
// try to reconnect/resend before sending an error.
if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::TimeoutError;
@@ -877,7 +894,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionClosedError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyConnectionClosedError;
@@ -885,7 +902,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
case QAbstractSocket::ProxyConnectionTimeoutError:
// try to reconnect/resend before sending an error.
if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
+ resendCurrentRequest();
return;
}
errorCode = QNetworkReply::ProxyTimeoutError;
@@ -933,8 +950,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
// send the next request
QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
- if (that) //signal emission triggered event loop
- close();
+ if (that) {
+ //signal emission triggered event loop
+ if (!socket)
+ state = QHttpNetworkConnectionChannel::IdleState;
+ else if (socket->state() == QAbstractSocket::UnconnectedState)
+ state = QHttpNetworkConnectionChannel::IdleState;
+ else
+ state = QHttpNetworkConnectionChannel::ClosingState;
+
+ // pendingEncrypt must only be true in between connected and encrypted states
+ pendingEncrypt = false;
+ }
}
#ifndef QT_NO_NETWORKPROXY
@@ -958,7 +985,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor
void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead()
{
- sendRequest();
+ if (reply)
+ sendRequest();
}
#ifndef QT_NO_SSL
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 16d6c3b40f..37ad6c9b0a 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -169,6 +169,7 @@ public:
void handleUnexpectedEOF();
void closeAndResendCurrentRequest();
+ void resendCurrentRequest();
bool isSocketBusy() const;
bool isSocketWriting() const;
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 172d4dab5b..dd108ad5c7 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -208,7 +208,7 @@ QByteArray QHttpNetworkReply::readAny()
return QByteArray();
// we'll take the last buffer, so schedule another read from http
- if (d->downstreamLimited && d->responseData.bufferCount() == 1)
+ if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished())
d->connection->d_func()->readMoreLater(this);
return d->responseData.read();
}
diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp
index 55187755bf..a2083158f1 100644
--- a/src/network/access/qhttpprotocolhandler.cpp
+++ b/src/network/access/qhttpprotocolhandler.cpp
@@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead()
}
if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) {
- m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
+ if (m_socket->bytesAvailable()) {
+ // We might get a spurious call from readMoreLater()
+ // call of the QHttpNetworkConnection even while the socket is disconnecting.
+ // Therefore check if there is actually bytes available before changing the channel state.
+ m_channel->state = QHttpNetworkConnectionChannel::ReadingState;
+ }
if (m_reply)
_q_receiveReply();
}
@@ -250,7 +255,6 @@ bool QHttpProtocolHandler::sendRequest()
if (!m_reply) {
// heh, how should that happen!
qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply";
- m_channel->state = QHttpNetworkConnectionChannel::IdleState;
return false;
}
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 78d4970ca1..71e435b771 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -43,6 +43,10 @@
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qthread_p.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qglobal.h>
+
+
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
@@ -375,6 +379,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
updating = false;
#ifndef QT_NO_LIBRARY
+ bool envOK = false;
+ const int skipGeneric = qgetenv("QT_EXCLUDE_GENERIC_BEARER").toInt(&envOK);
QBearerEngine *generic = 0;
QFactoryLoader *l = loader();
const PluginKeyMap keyMap = l->keyMap();
@@ -409,8 +415,10 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
}
}
- if (generic)
- sessionEngines.append(generic);
+ if (generic) {
+ if (!envOK || skipGeneric <= 0)
+ sessionEngines.append(generic);
+ }
#endif // QT_NO_LIBRARY
}
@@ -466,15 +474,18 @@ QList<QBearerEngine *> QNetworkConfigurationManagerPrivate::engines() const
void QNetworkConfigurationManagerPrivate::startPolling()
{
QMutexLocker locker(&mutex);
-
- if(!pollTimer) {
+ if (!pollTimer) {
pollTimer = new QTimer(this);
- pollTimer->setInterval(10000);
+ bool ok;
+ int interval = qgetenv("QT_BEARER_POLL_TIMEOUT").toInt(&ok);
+ if (!ok)
+ interval = 10000;//default 10 seconds
+ pollTimer->setInterval(interval);
pollTimer->setSingleShot(true);
connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines()));
}
- if(pollTimer->isActive())
+ if (pollTimer->isActive())
return;
foreach (QBearerEngine *engine, sessionEngines) {
@@ -483,6 +494,7 @@ void QNetworkConfigurationManagerPrivate::startPolling()
break;
}
}
+ performAsyncConfigurationUpdate();
}
void QNetworkConfigurationManagerPrivate::pollEngines()
diff --git a/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp b/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp
index a7ab8c0977..3bd57f1d44 100644
--- a/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp
+++ b/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp
@@ -51,7 +51,8 @@ void SslServer::incomingConnection(qintptr socketDescriptor)
{
QSslSocket *serverSocket = new QSslSocket;
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
- connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
+ addPendingConnection(serverSocket);
+ connect(serverSocket, &QSslSocket::encrypted, this, &SslServer::ready);
serverSocket->startServerEncryption();
} else {
delete serverSocket;
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index e539388b81..435bfd6c27 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -34,11 +34,12 @@ android {
win32: {
!winrt {
- HEADERS += kernel/qnetworkinterface_win_p.h
SOURCES += kernel/qdnslookup_win.cpp \
kernel/qhostinfo_win.cpp \
kernel/qnetworkinterface_win.cpp
- LIBS_PRIVATE += -ldnsapi
+ LIBS_PRIVATE += -ldnsapi -liphlpapi
+ DEFINES += WINVER=0x0600 _WIN32_WINNT=0x0600
+
} else {
SOURCES += kernel/qdnslookup_winrt.cpp \
kernel/qhostinfo_winrt.cpp \
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 58c0de1f3b..935af04e31 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -46,6 +46,9 @@
#ifndef QT_NO_DATASTREAM
#include <qdatastream.h>
#endif
+#ifdef __SSE2__
+# include <private/qsimd_p.h>
+#endif
#ifdef QT_LINUXBASE
# include <arpa/inet.h>
@@ -106,7 +109,11 @@ public:
QString scopeId;
quint32 a; // IPv4 address
- Q_IPV6ADDR a6; // IPv6 address
+ union {
+ Q_IPV6ADDR a6; // IPv6 address
+ struct { quint64 c[2]; } a6_64;
+ struct { quint32 c[4]; } a6_32;
+ };
QAbstractSocket::NetworkLayerProtocol protocol;
bool isParsed;
@@ -123,24 +130,17 @@ QHostAddressPrivate::QHostAddressPrivate()
void QHostAddressPrivate::setAddress(quint32 a_)
{
a = a_;
+ protocol = QAbstractSocket::IPv4Protocol;
+ isParsed = true;
+
//create mapped address, except for a_ == 0 (any)
- memset(&a6, 0, sizeof(a6));
+ a6_64.c[0] = 0;
if (a) {
- a6[11] = 0xFF;
- a6[10] = 0xFF;
+ a6_32.c[2] = qToBigEndian(0xffff);
+ a6_32.c[3] = qToBigEndian(a);
} else {
- a6[11] = 0;
- a6[10] = 0;
+ a6_64.c[1] = 0;
}
-
- int i;
- for (i=15; a_ != 0; i--) {
- a6[i] = a_ & 0xFF;
- a_ >>=8;
- }
- Q_ASSERT(i >= 11);
- protocol = QAbstractSocket::IPv4Protocol;
- isParsed = true;
}
/// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a;
@@ -163,21 +163,16 @@ static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6)
void QHostAddressPrivate::setAddress(const quint8 *a_)
{
- for (int i = 0; i < 16; i++)
- a6[i] = a_[i];
- a = 0;
- convertToIpv4(a, a6);
protocol = QAbstractSocket::IPv6Protocol;
isParsed = true;
+ memcpy(a6.c, a_, sizeof(a6));
+ a = 0;
+ convertToIpv4(a, a6);
}
void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
{
- a6 = a_;
- a = 0;
- convertToIpv4(a, a6);
- protocol = QAbstractSocket::IPv6Protocol;
- isParsed = true;
+ setAddress(a_.c);
}
static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId)
@@ -193,7 +188,7 @@ static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr,
return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()) == 0;
}
-bool QHostAddressPrivate::parse()
+Q_NEVER_INLINE bool QHostAddressPrivate::parse()
{
isParsed = true;
protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
@@ -486,31 +481,35 @@ QHostAddress::QHostAddress(SpecialAddress address)
{
Q_IPV6ADDR ip6;
memset(&ip6, 0, sizeof ip6);
+ quint32 ip4 = INADDR_ANY;
switch (address) {
case Null:
- break;
+ return;
+
case Broadcast:
- d->setAddress(quint32(-1));
+ ip4 = INADDR_BROADCAST;
break;
case LocalHost:
- d->setAddress(0x7f000001);
- break;
- case LocalHostIPv6:
- ip6[15] = 1;
- d->setAddress(ip6);
+ ip4 = INADDR_LOOPBACK;
break;
case AnyIPv4:
- setAddress(0u);
break;
+
+ case LocalHostIPv6:
+ ip6[15] = 1;
+ // fall through
case AnyIPv6:
d->setAddress(ip6);
- break;
+ return;
+
case Any:
- d->clear();
d->protocol = QAbstractSocket::AnyIPProtocol;
- break;
+ return;
}
+
+ // common IPv4 part
+ d->setAddress(ip4);
}
/*!
@@ -775,11 +774,6 @@ QString QHostAddress::toString() const
on your host. Link-local addresses ("fe80...") are generated from the MAC
address of the local network adaptor, and are not guaranteed to be unique.
- \li Site-local: Addresses that are local to the site / private network
- (e.g., the company intranet). Site-local addresses ("fec0...") are
- usually distributed by the site router, and are not guaranteed to be
- unique outside of the local site.
-
\li Global: For globally routable addresses, such as public servers on the
Internet.
@@ -790,7 +784,7 @@ QString QHostAddress::toString() const
usually the same as the interface name (e.g., "eth0", "en1") or number
(e.g., "1", "2").
- \sa setScopeId()
+ \sa setScopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
*/
QString QHostAddress::scopeId() const
{
@@ -801,8 +795,14 @@ QString QHostAddress::scopeId() const
/*!
\since 4.1
- Sets the IPv6 scope ID of the address to \a id. If the address
- protocol is not IPv6, this function does nothing.
+ Sets the IPv6 scope ID of the address to \a id. If the address protocol is
+ not IPv6, this function does nothing. The scope ID may be set as an
+ interface name (such as "eth0" or "en1") or as an integer representing the
+ interface index. If \a id is an interface name, QtNetwork will convert to
+ an interface index using QNetworkInterface::interfaceIndexFromName() before
+ calling the operating system networking functions.
+
+ \sa scopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName
*/
void QHostAddress::setScopeId(const QString &id)
{
@@ -836,34 +836,36 @@ bool QHostAddress::operator==(const QHostAddress &other) const
bool QHostAddress::operator ==(SpecialAddress other) const
{
QT_ENSURE_PARSED(this);
+ quint32 ip4 = INADDR_ANY;
switch (other) {
case Null:
return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol;
case Broadcast:
- return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_BROADCAST;
+ ip4 = INADDR_BROADCAST;
+ break;
case LocalHost:
- return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_LOOPBACK;
+ ip4 = INADDR_LOOPBACK;
+ break;
case Any:
return d->protocol == QAbstractSocket::AnyIPProtocol;
case AnyIPv4:
- return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_ANY;
+ break;
case LocalHostIPv6:
case AnyIPv6:
if (d->protocol == QAbstractSocket::IPv6Protocol) {
- Q_IPV6ADDR ip6 = { { 0 } };
- ip6[15] = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any
- return memcmp(&d->a6, &ip6, sizeof ip6) == 0;
+ quint64 second = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any
+ return d->a6_64.c[0] == 0 && d->a6_64.c[1] == qToBigEndian(second);
}
return false;
}
- Q_UNREACHABLE();
- return false;
+ // common IPv4 part
+ return d->protocol == QAbstractSocket::IPv4Protocol && d->a == ip4;
}
/*!
@@ -1085,16 +1087,36 @@ bool QHostAddress::isLoopback() const
if ((d->a & 0xFF000000) == 0x7F000000)
return true; // v4 range (including IPv6 wrapped IPv4 addresses)
if (d->protocol == QAbstractSocket::IPv6Protocol) {
- if (d->a6.c[15] != 1)
+#ifdef __SSE2__
+ const __m128i loopback = _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+ __m128i ipv6 = _mm_loadu_si128((const __m128i *)d->a6.c);
+ __m128i cmp = _mm_cmpeq_epi8(ipv6, loopback);
+ return _mm_movemask_epi8(cmp) == 0xffff;
+#else
+ if (d->a6_64.c[0] != 0 || qFromBigEndian(d->a6_64.c[1]) != 1)
return false;
- for (int i = 0; i < 15; i++)
- if (d->a6[i] != 0)
- return false;
+#endif
return true;
}
return false;
}
+/*!
+ \since 5.6
+
+ Returns \c true if the address is an IPv4 or IPv6 multicast address, \c
+ false otherwise.
+*/
+bool QHostAddress::isMulticast() const
+{
+ QT_ENSURE_PARSED(this);
+ if ((d->a & 0xF0000000) == 0xE0000000)
+ return true; // 224.0.0.0-239.255.255.255 (including v4-mapped IPv6 addresses)
+ if (d->protocol == QAbstractSocket::IPv6Protocol)
+ return d->a6.c[0] == 0xff;
+ return false;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QHostAddress &address)
{
@@ -1112,7 +1134,7 @@ uint qHash(const QHostAddress &key, uint seed)
{
// both lines might throw
QT_ENSURE_PARSED(&key);
- return qHash(QByteArray::fromRawData(reinterpret_cast<const char *>(key.d->a6.c), 16), seed);
+ return qHashBits(key.d->a6.c, 16, seed);
}
#ifndef QT_NO_DATASTREAM
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index 8478240d28..9e3ee43d04 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -124,6 +124,7 @@ public:
bool isInSubnet(const QPair<QHostAddress, int> &subnet) const;
bool isLoopback() const;
+ bool isMulticast() const;
static QPair<QHostAddress, int> parseSubnet(const QString &subnet);
@@ -131,6 +132,7 @@ public:
protected:
QScopedPointer<QHostAddressPrivate> d;
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QHostAddress)
inline bool operator ==(QHostAddress::SpecialAddress address1, const QHostAddress &address2)
{ return address2 == address1; }
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index a2ac9065fd..c6c09542e7 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -415,10 +415,22 @@ void QHostInfo::setErrorString(const QString &str)
/*!
\fn QString QHostInfo::localHostName()
- Returns the host name of this machine.
+ Returns this machine's host name, if one is configured. Note that hostnames
+ are not guaranteed to be globally unique, especially if they were
+ configured automatically.
- \sa hostName()
+ This function does not guarantee the returned host name is a Fully
+ Qualified Domain Name (FQDN). For that, use fromName() to resolve the
+ returned name to an FQDN.
+
+ This function returns the same as QSysInfo::machineHostName().
+
+ \sa hostName(), localDomainName()
*/
+QString QHostInfo::localHostName()
+{
+ return QSysInfo::machineHostName();
+}
/*!
\fn QString QHostInfo::localDomainName()
diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp
index 90a6f763f7..266a67771c 100644
--- a/src/network/kernel/qhostinfo_unix.cpp
+++ b/src/network/kernel/qhostinfo_unix.cpp
@@ -315,15 +315,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
-QString QHostInfo::localHostName()
-{
- char hostName[512];
- if (gethostname(hostName, sizeof(hostName)) == -1)
- return QString();
- hostName[sizeof(hostName) - 1] = '\0';
- return QString::fromLocal8Bit(hostName);
-}
-
QString QHostInfo::localDomainName()
{
#if !defined(Q_OS_VXWORKS) && !defined(Q_OS_ANDROID)
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index e044728198..da28cd48c1 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -111,7 +111,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
QMutexLocker locker(&qPrivCEMutex);
#endif
- QWindowsSockInit winSock;
+ QSysInfo::machineHostName(); // this initializes ws2_32.dll
// Load res_init on demand.
static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false);
@@ -136,7 +136,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
// Reverse lookup
if (local_getnameinfo) {
sockaddr_in sa4;
- qt_sockaddr_in6 sa6;
+ sockaddr_in6 sa6;
sockaddr *sa;
QT_SOCKLEN_T saSize;
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
@@ -150,7 +150,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
saSize = sizeof(sa6);
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
- memcpy(sa6.sin6_addr.qt_s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.qt_s6_addr));
+ memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr));
}
char hbuf[NI_MAXHOST];
@@ -197,7 +197,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
break;
case AF_INET6: {
QHostAddress addr;
- addr.setAddress(((qt_sockaddr_in6 *) p->ai_addr)->sin6_addr.qt_s6_addr);
+ addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr);
if (!addresses.contains(addr))
addresses.append(addr);
}
@@ -256,17 +256,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
-QString QHostInfo::localHostName()
-{
- QWindowsSockInit winSock;
-
- char hostName[512];
- if (gethostname(hostName, sizeof(hostName)) == -1)
- return QString();
- hostName[sizeof(hostName) - 1] = '\0';
- return QString::fromLocal8Bit(hostName);
-}
-
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp
index 1a97fe0e40..3d2344726b 100644
--- a/src/network/kernel/qhostinfo_winrt.cpp
+++ b/src/network/kernel/qhostinfo_winrt.cpp
@@ -130,45 +130,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
return results;
}
-QString QHostInfo::localHostName()
-{
- ComPtr<INetworkInformationStatics> statics;
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
-
- ComPtr<IVectorView<HostName *>> hostNames;
- statics->GetHostNames(&hostNames);
- if (!hostNames)
- return QString();
-
- unsigned int size;
- hostNames->get_Size(&size);
- if (size == 0)
- return QString();
-
- for (unsigned int i = 0; i < size; ++i) {
- ComPtr<IHostName> hostName;
- hostNames->GetAt(i, &hostName);
- HostNameType type;
- hostName->get_Type(&type);
- if (type != HostNameType_DomainName)
- continue;
-
- HString name;
- hostName->get_CanonicalName(name.GetAddressOf());
- UINT32 length;
- PCWSTR rawString = name.GetRawBuffer(&length);
- return QString::fromWCharArray(rawString, length);
- }
- ComPtr<IHostName> firstHost;
- hostNames->GetAt(0, &firstHost);
-
- HString name;
- firstHost->get_CanonicalName(name.GetAddressOf());
- UINT32 length;
- PCWSTR rawString = name.GetRawBuffer(&length);
- return QString::fromWCharArray(rawString, length);
-}
-
// QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp
QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 2fbbf56e0f..4a527052d1 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -86,9 +86,16 @@ QSharedDataPointer<QNetworkInterfacePrivate> QNetworkInterfaceManager::interface
{
QList<QSharedDataPointer<QNetworkInterfacePrivate> > interfaceList = allInterfaces();
QList<QSharedDataPointer<QNetworkInterfacePrivate> >::ConstIterator it = interfaceList.constBegin();
- for ( ; it != interfaceList.constEnd(); ++it)
- if ((*it)->name == name)
+
+ bool ok;
+ uint index = name.toUInt(&ok);
+
+ for ( ; it != interfaceList.constEnd(); ++it) {
+ if (ok && (*it)->index == int(index))
return *it;
+ else if ((*it)->name == name)
+ return *it;
+ }
return empty;
}
@@ -516,6 +523,9 @@ QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const
name. If no such interface exists, this function returns an
invalid QNetworkInterface object.
+ The string \a name may be either an actual interface name (such as "eth0"
+ or "en1") or an interface index in string form ("1", "2", etc.).
+
\sa name(), isValid()
*/
QNetworkInterface QNetworkInterface::interfaceFromName(const QString &name)
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index 31d3b7b128..b3daa3d4a0 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -133,6 +133,9 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkInterface &networ
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QNetworkAddressEntry)
+Q_DECLARE_METATYPE(QNetworkInterface)
+
#endif // QT_NO_NETWORKINTERFACE
#endif
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index 9c5ba4e799..cc53087024 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -127,14 +127,13 @@ static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags)
#ifdef QT_NO_GETIFADDRS
// getifaddrs not available
-static const int STORAGEBUFFER_GROWTH = 256;
-
static QSet<QByteArray> interfaceNames(int socket)
{
QSet<QByteArray> result;
#ifdef QT_NO_IPV6IFNAME
QByteArray storageBuffer;
struct ifconf interfaceList;
+ static const int STORAGEBUFFER_GROWTH = 256;
forever {
// grow the storage buffer
@@ -186,9 +185,14 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfa
QNetworkInterfacePrivate *iface = 0;
int ifindex = 0;
-#ifndef QT_NO_IPV6IFNAME
+#if !defined(QT_NO_IPV6IFNAME) || defined(SIOCGIFINDEX)
// Get the interface index
+# ifdef SIOCGIFINDEX
+ if (qt_safe_ioctl(socket, SIOCGIFINDEX, &req) >= 0)
+ ifindex = req.ifr_ifindex;
+# else
ifindex = if_nametoindex(req.ifr_name);
+# endif
// find the interface data
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
@@ -214,6 +218,27 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfa
iface = new QNetworkInterfacePrivate;
iface->index = ifindex;
interfaces << iface;
+ }
+
+ return iface;
+}
+
+static QList<QNetworkInterfacePrivate *> interfaceListing()
+{
+ QList<QNetworkInterfacePrivate *> interfaces;
+
+ int socket;
+ if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
+ return interfaces; // error
+
+ QSet<QByteArray> names = interfaceNames(socket);
+ QSet<QByteArray>::ConstIterator it = names.constBegin();
+ for ( ; it != names.constEnd(); ++it) {
+ ifreq req;
+ memset(&req, 0, sizeof(ifreq));
+ memcpy(req.ifr_name, *it, qMin<int>(it->length() + 1, sizeof(req.ifr_name) - 1));
+
+ QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req);
#ifdef SIOCGIFNAME
// Get the canonical name
@@ -242,27 +267,6 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfa
iface->hardwareAddress = iface->makeHwAddress(6, addr);
}
#endif
- }
-
- return iface;
-}
-
-static QList<QNetworkInterfacePrivate *> interfaceListing()
-{
- QList<QNetworkInterfacePrivate *> interfaces;
-
- int socket;
- if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
- return interfaces; // error
-
- QSet<QByteArray> names = interfaceNames(socket);
- QSet<QByteArray>::ConstIterator it = names.constBegin();
- for ( ; it != names.constEnd(); ++it) {
- ifreq req;
- memset(&req, 0, sizeof(ifreq));
- memcpy(req.ifr_name, *it, qMin<int>(it->length() + 1, sizeof(req.ifr_name) - 1));
-
- QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req);
// Get the interface broadcast address
QNetworkAddressEntry entry;
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index ddeb6c111f..907638f73e 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -31,7 +32,7 @@
**
****************************************************************************/
-#include "qnetworkinterface_win_p.h"
+#define WIN32_LEAN_AND_MEAN 1
#include "qnetworkinterface.h"
#include "qnetworkinterface_p.h"
@@ -41,16 +42,23 @@
#include <qhostinfo.h>
#include <qhash.h>
#include <qurl.h>
-#include <private/qsystemlibrary_p.h>
+
+// Since we need to include winsock2.h, we need to define WIN32_LEAN_AND_MEAN
+// (above) so windows.h won't include winsock.h.
+// In addition, we need to include winsock2.h before iphlpapi.h and we need
+// to include ws2ipdef.h to work around an MinGW-w64 bug
+// (http://sourceforge.net/p/mingw-w64/mailman/message/32935366/)
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <iphlpapi.h>
+#include <ws2tcpip.h>
+
+#include <qt_windows.h>
QT_BEGIN_NAMESPACE
-typedef DWORD (WINAPI *PtrGetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG);
-static PtrGetAdaptersInfo ptrGetAdaptersInfo = 0;
-typedef ULONG (WINAPI *PtrGetAdaptersAddresses)(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG);
-static PtrGetAdaptersAddresses ptrGetAdaptersAddresses = 0;
-typedef DWORD (WINAPI *PtrGetNetworkParams)(PFIXED_INFO, PULONG);
-static PtrGetNetworkParams ptrGetNetworkParams = 0;
+typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToName)(const NET_LUID *, PWSTR, SIZE_T);
+static PtrConvertInterfaceLuidToName ptrConvertInterfaceLuidToName = 0;
static void resolveLibs()
{
@@ -58,21 +66,17 @@ static void resolveLibs()
static bool done = false;
if (!done) {
- done = true;
-
- HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi");
- if (iphlpapiHnd == NULL)
- return;
+ HINSTANCE iphlpapiHnd = GetModuleHandle(L"iphlpapi");
+ Q_ASSERT(iphlpapiHnd);
#if defined(Q_OS_WINCE)
- ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo");
- ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses");
- ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams");
+ // since Windows Embedded Compact 7
+ ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToNameW");
#else
- ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo");
- ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses");
- ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, "GetNetworkParams");
+ // since Windows Vista
+ ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW");
#endif
+ done = true;
}
}
@@ -85,8 +89,8 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
if (sa->sa_family == AF_INET)
address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
else if (sa->sa_family == AF_INET6) {
- address.setAddress(((qt_sockaddr_in6 *)sa)->sin6_addr.qt_s6_addr);
- int scope = ((qt_sockaddr_in6 *)sa)->sin6_scope_id;
+ address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
+ int scope = ((sockaddr_in6 *)sa)->sin6_scope_id;
if (scope)
address.setScopeId(QString::number(scope));
} else
@@ -103,14 +107,14 @@ static QHash<QHostAddress, QHostAddress> ipv4Netmasks()
ULONG bufSize = sizeof staticBuf;
QHash<QHostAddress, QHostAddress> ipv4netmasks;
- DWORD retval = ptrGetAdaptersInfo(pAdapter, &bufSize);
+ DWORD retval = GetAdaptersInfo(pAdapter, &bufSize);
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_INFO *)malloc(bufSize);
if (!pAdapter)
return ipv4netmasks;
// try again
- if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
+ if (GetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
free(pAdapter);
return ipv4netmasks;
}
@@ -145,14 +149,14 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
ULONG flags = GAA_FLAG_INCLUDE_PREFIX |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_MULTICAST;
- ULONG retval = ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize);
+ ULONG retval = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize);
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_ADDRESSES *)malloc(bufSize);
if (!pAdapter)
return interfaces;
// try again
- if (ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) {
+ if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) {
free(pAdapter);
return interfaces;
}
@@ -180,7 +184,16 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
if (ptr->IfType == IF_TYPE_PPP)
iface->flags |= QNetworkInterface::IsPointToPoint;
- iface->name = QString::fromLocal8Bit(ptr->AdapterName);
+ if (ptrConvertInterfaceLuidToName && ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid)) {
+ // use ConvertInterfaceLuidToName because that returns a friendlier name, though not
+ // as friendly as FriendlyName below
+ WCHAR buf[IF_MAX_STRING_SIZE + 1];
+ if (ptrConvertInterfaceLuidToName(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
+ iface->name = QString::fromWCharArray(buf);
+ }
+ if (iface->name.isEmpty())
+ iface->name = QString::fromLocal8Bit(ptr->AdapterName);
+
iface->friendlyName = QString::fromWCharArray(ptr->FriendlyName);
if (ptr->PhysicalAddressLength)
iface->hardwareAddress = iface->makeHwAddress(ptr->PhysicalAddressLength,
@@ -221,92 +234,25 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
return interfaces;
}
-static QList<QNetworkInterfacePrivate *> interfaceListingWin2k()
-{
- QList<QNetworkInterfacePrivate *> interfaces;
- IP_ADAPTER_INFO staticBuf[2]; // 2 is arbitrary
- PIP_ADAPTER_INFO pAdapter = staticBuf;
- ULONG bufSize = sizeof staticBuf;
-
- DWORD retval = ptrGetAdaptersInfo(pAdapter, &bufSize);
- if (retval == ERROR_BUFFER_OVERFLOW) {
- // need more memory
- pAdapter = (IP_ADAPTER_INFO *)malloc(bufSize);
- if (!pAdapter)
- return interfaces;
- // try again
- if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
- free(pAdapter);
- return interfaces;
- }
- } else if (retval != ERROR_SUCCESS) {
- // error
- return interfaces;
- }
-
- // iterate over the list and add the entries to our listing
- for (PIP_ADAPTER_INFO ptr = pAdapter; ptr; ptr = ptr->Next) {
- QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
- interfaces << iface;
-
- iface->index = ptr->Index;
- iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning;
- if (ptr->Type == MIB_IF_TYPE_PPP)
- iface->flags |= QNetworkInterface::IsPointToPoint;
- else
- iface->flags |= QNetworkInterface::CanBroadcast;
- iface->name = QString::fromLocal8Bit(ptr->AdapterName);
- iface->hardwareAddress = QNetworkInterfacePrivate::makeHwAddress(ptr->AddressLength,
- ptr->Address);
-
- for (PIP_ADDR_STRING addr = &ptr->IpAddressList; addr; addr = addr->Next) {
- QNetworkAddressEntry entry;
- entry.setIp(QHostAddress(QLatin1String(addr->IpAddress.String)));
- entry.setNetmask(QHostAddress(QLatin1String(addr->IpMask.String)));
- // broadcast address is set on postProcess()
-
- iface->addressEntries << entry;
- }
- }
-
- if (pAdapter != staticBuf)
- free(pAdapter);
-
- return interfaces;
-}
-
-static QList<QNetworkInterfacePrivate *> interfaceListing()
-{
- resolveLibs();
- if (ptrGetAdaptersAddresses != NULL)
- return interfaceListingWinXP();
- else if (ptrGetAdaptersInfo != NULL)
- return interfaceListingWin2k();
-
- // failed
- return QList<QNetworkInterfacePrivate *>();
-}
-
QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
{
- return interfaceListing();
+ resolveLibs();
+ return interfaceListingWinXP();
}
QString QHostInfo::localDomainName()
{
resolveLibs();
- if (ptrGetNetworkParams == NULL)
- return QString(); // couldn't resolve
FIXED_INFO info, *pinfo;
ULONG bufSize = sizeof info;
pinfo = &info;
- if (ptrGetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
+ if (GetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
pinfo = (FIXED_INFO *)malloc(bufSize);
if (!pinfo)
return QString();
// try again
- if (ptrGetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) {
+ if (GetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) {
free(pinfo);
return QString(); // error
}
diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h
deleted file mode 100644
index 88c1945fe6..0000000000
--- a/src/network/kernel/qnetworkinterface_win_p.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QNETWORKINTERFACE_WIN_P_H
-#define QNETWORKINTERFACE_WIN_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <winsock2.h>
-#include <qt_windows.h>
-#include <time.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES
-# define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
-#endif
-#ifndef MAX_ADAPTER_ADDRESS_LENGTH
-// definitions from iptypes.h
-# define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
-# define MAX_ADAPTER_NAME_LENGTH 256 // arb.
-# define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
-# define DEFAULT_MINIMUM_ENTITIES 32 // arb.
-# define MAX_HOSTNAME_LEN 128 // arb.
-# define MAX_DOMAIN_NAME_LEN 128 // arb.
-# define MAX_SCOPE_ID_LEN 256 // arb.
-
-# define GAA_FLAG_SKIP_UNICAST 0x0001
-# define GAA_FLAG_SKIP_ANYCAST 0x0002
-# define GAA_FLAG_SKIP_MULTICAST 0x0004
-# define GAA_FLAG_SKIP_DNS_SERVER 0x0008
-# define GAA_FLAG_INCLUDE_PREFIX 0x0010
-# define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
-
-# define IP_ADAPTER_DDNS_ENABLED 0x01
-# define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02
-# define IP_ADAPTER_DHCP_ENABLED 0x04
-# define IP_ADAPTER_RECEIVE_ONLY 0x08
-# define IP_ADAPTER_NO_MULTICAST 0x10
-# define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
-
-# define MIB_IF_TYPE_OTHER 1
-# define MIB_IF_TYPE_ETHERNET 6
-# define MIB_IF_TYPE_TOKENRING 9
-# define MIB_IF_TYPE_FDDI 15
-# define MIB_IF_TYPE_PPP 23
-# define MIB_IF_TYPE_LOOPBACK 24
-# define MIB_IF_TYPE_SLIP 28
-
-// definitions from Ipifcons.h
-#define IF_TYPE_PPP 23
-
-#endif
-// copied from qnativesocketengine_win.cpp
-struct qt_in6_addr {
- u_char qt_s6_addr[16];
-};
-typedef struct {
- short sin6_family; /* AF_INET6 */
- u_short sin6_port; /* Transport level port number */
- u_long sin6_flowinfo; /* IPv6 flow information */
- struct qt_in6_addr sin6_addr; /* IPv6 address */
- u_long sin6_scope_id; /* set of interfaces for a scope */
-} qt_sockaddr_in6;
-
-// copied from MSDN online help
-typedef enum {
- IpPrefixOriginOther = 0,
- IpPrefixOriginManual,
- IpPrefixOriginWellKnown,
- IpPrefixOriginDhcp,
- IpPrefixOriginRouterAdvertisement
-} IP_PREFIX_ORIGIN;
-
-typedef enum {
- IpSuffixOriginOther = 0,
- IpSuffixOriginManual,
- IpSuffixOriginWellKnown,
- IpSuffixOriginDhcp,
- IpSuffixOriginLinkLayerAddress,
- IpSuffixOriginRandom
-} IP_SUFFIX_ORIGIN;
-
-typedef enum {
- IpDadStateInvalid = 0,
- IpDadStateTentative,
- IpDadStateDuplicate,
- IpDadStateDeprecated,
- IpDadStatePreferred,
-} IP_DAD_STATE;
-
-typedef enum {
- IfOperStatusUp = 1,
- IfOperStatusDown,
- IfOperStatusTesting,
- IfOperStatusUnknown,
- IfOperStatusDormant,
- IfOperStatusNotPresent,
- IfOperStatusLowerLayerDown
-} IF_OPER_STATUS;
-
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
- union {
- ULONGLONG Alignment;
- struct {
- ULONG Length;
- DWORD Flags;
- };
- };
- struct _IP_ADAPTER_UNICAST_ADDRESS* Next;
- SOCKET_ADDRESS Address;
- IP_PREFIX_ORIGIN PrefixOrigin;
- IP_SUFFIX_ORIGIN SuffixOrigin;
- IP_DAD_STATE DadState;
- ULONG ValidLifetime;
- ULONG PreferredLifetime;
- ULONG LeaseLifetime;
-} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
-
-typedef struct _IP_ADAPTER_ANYCAST_ADDRESS
- IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS;
-
-typedef struct _IP_ADAPTER_MULTICAST_ADDRESS
- IP_ADAPTER_MULTICAST_ADDRESS,
- *PIP_ADAPTER_MULTICAST_ADDRESS;
-
-typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS
- IP_ADAPTER_DNS_SERVER_ADDRESS,
- *PIP_ADAPTER_DNS_SERVER_ADDRESS;
-
-typedef struct _IP_ADAPTER_PREFIX {
- union {
- ULONGLONG Alignment;
- struct {
- ULONG Length;
- DWORD Flags;
- };
- };
- struct _IP_ADAPTER_PREFIX* Next;
- SOCKET_ADDRESS Address;
- ULONG PrefixLength;
-} IP_ADAPTER_PREFIX,
- *PIP_ADAPTER_PREFIX;
-
-typedef struct _IP_ADAPTER_ADDRESSES {
- union {
- ULONGLONG Alignment;
- struct {
- ULONG Length;
- DWORD IfIndex;
- };
- };
- struct _IP_ADAPTER_ADDRESSES* Next;
- PCHAR AdapterName;
- PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
- PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
- PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
- PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
- PWCHAR DnsSuffix;
- PWCHAR Description;
- PWCHAR FriendlyName;
- BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
- DWORD PhysicalAddressLength;
- DWORD Flags;
- DWORD Mtu;
- DWORD IfType;
- IF_OPER_STATUS OperStatus;
- DWORD Ipv6IfIndex;
- DWORD ZoneIndices[16];
- PIP_ADAPTER_PREFIX FirstPrefix;
-} IP_ADAPTER_ADDRESSES,
- *PIP_ADAPTER_ADDRESSES;
-
-typedef struct {
- char String[4 * 4];
-} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
-
-typedef struct _IP_ADDR_STRING {
- struct _IP_ADDR_STRING* Next;
- IP_ADDRESS_STRING IpAddress;
- IP_MASK_STRING IpMask;
- DWORD Context;
-} IP_ADDR_STRING,
- *PIP_ADDR_STRING;
-
-typedef struct _IP_ADAPTER_INFO {
- struct _IP_ADAPTER_INFO* Next;
- DWORD ComboIndex;
- char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
- char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
- UINT AddressLength;
- BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
- DWORD Index;
- UINT Type;
- UINT DhcpEnabled;
- PIP_ADDR_STRING CurrentIpAddress;
- IP_ADDR_STRING IpAddressList;
- IP_ADDR_STRING GatewayList;
- IP_ADDR_STRING DhcpServer;
- BOOL HaveWins;
- IP_ADDR_STRING PrimaryWinsServer;
- IP_ADDR_STRING SecondaryWinsServer;
- time_t LeaseObtained;
- time_t LeaseExpires;
-} IP_ADAPTER_INFO,
- *PIP_ADAPTER_INFO;
-
-typedef struct {
- char HostName[MAX_HOSTNAME_LEN + 4];
- char DomainName[MAX_DOMAIN_NAME_LEN + 4];
- PIP_ADDR_STRING CurrentDnsServer;
- IP_ADDR_STRING DnsServerList;
- UINT NodeType;
- char ScopeId[MAX_SCOPE_ID_LEN + 4];
- UINT EnableRouting;
- UINT EnableProxy;
- UINT EnableDns;
-} FIXED_INFO, *PFIXED_INFO;
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index 51400f55bb..05d4c6955a 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -35,6 +35,7 @@
#ifndef QT_NO_NETWORKPROXY
+#include <CFNetwork/CFNetwork.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 785ea17389..b2426f5c00 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -630,8 +630,8 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
resetSocketLayer();
socketEngine = QAbstractSocketEngine::createSocketEngine(q->socketType(), proxyInUse, q);
if (!socketEngine) {
- socketError = QAbstractSocket::UnsupportedSocketOperationError;
- q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported"));
+ setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QAbstractSocket::tr("Operation on socket is not supported"));
return false;
}
#ifndef QT_NO_BEARERMANAGEMENT
@@ -644,8 +644,7 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(),
socketEngine->errorString().toLatin1().constData());
#endif
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
+ setError(socketEngine->error(), socketEngine->errorString());
return false;
}
@@ -771,6 +770,7 @@ bool QAbstractSocketPrivate::canReadNotification()
void QAbstractSocketPrivate::canCloseNotification()
{
Q_Q(QAbstractSocket);
+ // Note that this method is only called on Windows. Other platforms close in the canReadNotification()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::canCloseNotification()");
@@ -780,7 +780,11 @@ void QAbstractSocketPrivate::canCloseNotification()
if (isBuffered) {
// Try to read to the buffer, if the read fail we can close the socket.
newBytes = buffer.size();
- if (!readFromSocket()) {
+ qint64 oldReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer
+ bool hadReadFromSocket = readFromSocket();
+ readBufferMaxSize = oldReadBufferMaxSize;
+ if (!hadReadFromSocket) {
q->disconnectFromHost();
return;
}
@@ -880,13 +884,11 @@ bool QAbstractSocketPrivate::writeToSocket()
// Attempt to write it all in one chunk.
qint64 written = socketEngine->write(ptr, nextSize);
if (written < 0) {
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug() << "QAbstractSocketPrivate::writeToSocket() write error, aborting."
<< socketEngine->errorString();
#endif
- emit q->error(socketError);
+ setErrorAndEmit(socketEngine->error(), socketEngine->errorString());
// an unexpected error so close the socket.
q->abort();
return false;
@@ -1004,8 +1006,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host)
}
// failed to connect
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
+ setError(socketEngine->error(), socketEngine->errorString());
}
state = QAbstractSocket::UnconnectedState;
@@ -1064,8 +1065,7 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo)
qDebug("QAbstractSocketPrivate::_q_startConnecting(), host not found");
#endif
state = QAbstractSocket::UnconnectedState;
- socketError = QAbstractSocket::HostNotFoundError;
- q->setErrorString(QAbstractSocket::tr("Host not found"));
+ setError(QAbstractSocket::HostNotFoundError, QAbstractSocket::tr("Host not found"));
emit q->stateChanged(state);
emit q->error(QAbstractSocket::HostNotFoundError);
return;
@@ -1114,11 +1114,10 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
|| socketEngine->error() == QAbstractSocket::UnsupportedSocketOperationError
#endif
) && socketEngine->state() == QAbstractSocket::ConnectingState) {
- socketError = QAbstractSocket::ConnectionRefusedError;
- q->setErrorString(QAbstractSocket::tr("Connection refused"));
+ setError(QAbstractSocket::ConnectionRefusedError,
+ QAbstractSocket::tr("Connection refused"));
} else {
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
+ setError(socketEngine->error(), socketEngine->errorString());
}
} else {
// socketError = QAbstractSocket::ConnectionRefusedError;
@@ -1242,8 +1241,8 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt()
if (addresses.isEmpty()) {
state = QAbstractSocket::UnconnectedState;
- socketError = QAbstractSocket::SocketTimeoutError;
- q->setErrorString(QAbstractSocket::tr("Connection timed out"));
+ setError(QAbstractSocket::SocketTimeoutError,
+ QAbstractSocket::tr("Connection timed out"));
emit q->stateChanged(state);
emit q->error(socketError);
} else {
@@ -1303,9 +1302,7 @@ bool QAbstractSocketPrivate::readFromSocket()
#endif
if (!socketEngine->isValid()) {
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
- emit q->error(socketError);
+ setErrorAndEmit(socketEngine->error(), socketEngine->errorString());
#if defined(QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s",
q->errorString().toLatin1().constData());
@@ -1390,6 +1387,31 @@ QAbstractSocketEngine* QAbstractSocketPrivate::getSocketEngine(QAbstractSocket *
return socket->d_func()->socketEngine;
}
+/*!
+ \internal
+
+ Sets the socket error state to \c errorCode and \a errorString.
+*/
+void QAbstractSocketPrivate::setError(QAbstractSocket::SocketError errorCode,
+ const QString &errStr)
+{
+ socketError = errorCode;
+ errorString = errStr;
+}
+
+/*!
+ \internal
+
+ Sets the socket error state to \c errorCode and \a errorString,
+ and emits the QAbstractSocket::error() signal.
+*/
+void QAbstractSocketPrivate::setErrorAndEmit(QAbstractSocket::SocketError errorCode,
+ const QString &errorString)
+{
+ Q_Q(QAbstractSocket);
+ setError(errorCode, errorString);
+ emit q->error(errorCode);
+}
/*! \internal
@@ -1554,9 +1576,7 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb
cachedSocketDescriptor = socketEngine->socketDescriptor();
if (!result) {
- socketError = socketEngine->error();
- q->setErrorString(socketEngine->errorString());
- emit q->error(socketError);
+ setErrorAndEmit(socketEngine->error(), socketEngine->errorString());
return false;
}
@@ -1633,9 +1653,7 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
if (d->state == ConnectedState || d->state == ConnectingState
|| d->state == ClosingState || d->state == HostLookupState) {
qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName));
- d->socketError = QAbstractSocket::OperationError;
- setErrorString(QAbstractSocket::tr("Trying to connect while connection is in progress"));
- emit error(d->socketError);
+ d->setErrorAndEmit(OperationError, tr("Trying to connect while connection is in progress"));
return;
}
@@ -1664,9 +1682,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
d->resolveProxy(hostName, port);
if (d->proxyInUse.type() == QNetworkProxy::DefaultProxy) {
// failed to setup the proxy
- d->socketError = QAbstractSocket::UnsupportedSocketOperationError;
- setErrorString(QAbstractSocket::tr("Operation on socket is not supported"));
- emit error(d->socketError);
+ d->setErrorAndEmit(UnsupportedSocketOperationError,
+ tr("Operation on socket is not supported"));
return;
}
#endif
@@ -1886,8 +1903,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
d->buffer.clear();
d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this);
if (!d->socketEngine) {
- d->socketError = UnsupportedSocketOperationError;
- setErrorString(tr("Operation on socket is not supported"));
+ d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported"));
return false;
}
#ifndef QT_NO_BEARERMANAGEMENT
@@ -1896,8 +1912,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
#endif
bool result = d->socketEngine->initialize(socketDescriptor, socketState);
if (!result) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
+ d->setError(d->socketEngine->error(), d->socketEngine->errorString());
return false;
}
@@ -2107,11 +2122,10 @@ bool QAbstractSocket::waitForConnected(int msecs)
}
if ((timedOut && state() != ConnectedState) || state() == ConnectingState) {
- d->socketError = SocketTimeoutError;
+ d->setError(SocketTimeoutError, tr("Socket operation timed out"));
d->state = UnconnectedState;
emit stateChanged(d->state);
d->resetSocketLayer();
- setErrorString(tr("Socket operation timed out"));
}
#if defined (QABSTRACTSOCKET_DEBUG)
@@ -2170,13 +2184,11 @@ bool QAbstractSocket::waitForReadyRead(int msecs)
bool readyToWrite = false;
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
- msecs, d->socketError, errorString().toLatin1().constData());
+ msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
#endif
- emit error(d->socketError);
+ d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
if (d->socketError != SocketTimeoutError)
close();
return false;
@@ -2242,13 +2254,11 @@ bool QAbstractSocket::waitForBytesWritten(int msecs)
bool readyToWrite = false;
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)",
- msecs, d->socketError, errorString().toLatin1().constData());
+ msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
#endif
- emit error(d->socketError);
+ d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
if (d->socketError != SocketTimeoutError)
close();
return false;
@@ -2324,13 +2334,11 @@ bool QAbstractSocket::waitForDisconnected(int msecs)
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, state() == ConnectedState,
!d->writeBuffer.isEmpty(),
qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)",
- msecs, d->socketError, errorString().toLatin1().constData());
+ msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
#endif
- emit error(d->socketError);
+ d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
if (d->socketError != SocketTimeoutError)
close();
return false;
@@ -2461,8 +2469,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize)
// -2 from the engine means no bytes available (EAGAIN) so read more later
return 0;
} else if (readBytes < 0) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
+ d->setError(d->socketEngine->error(), d->socketEngine->errorString());
d->resetSocketLayer();
d->state = QAbstractSocket::UnconnectedState;
} else if (!d->socketEngine->isReadNotificationEnabled()) {
@@ -2492,8 +2499,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size)
{
Q_D(QAbstractSocket);
if (d->state == QAbstractSocket::UnconnectedState) {
- d->socketError = QAbstractSocket::UnknownSocketError;
- setErrorString(tr("Socket is not connected"));
+ d->setError(UnknownSocketError, tr("Socket is not connected"));
return -1;
}
@@ -2501,8 +2507,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size)
// This code is for the new Unbuffered QTcpSocket use case
qint64 written = d->socketEngine->write(data, size);
if (written < 0) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
+ d->setError(d->socketEngine->error(), d->socketEngine->errorString());
return written;
} else if (written < size) {
// Buffer what was not written yet
@@ -2516,8 +2521,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size)
// This is for a QUdpSocket that was connect()ed
qint64 written = d->socketEngine->write(data, size);
if (written < 0) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
+ d->setError(d->socketEngine->error(), d->socketEngine->errorString());
} else if (!d->writeBuffer.isEmpty()) {
d->socketEngine->setWriteNotificationEnabled(true);
}
diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index c0662f01b4..ba129b48df 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -138,6 +138,9 @@ public:
bool writeToSocket();
void emitReadyRead();
+ void setError(QAbstractSocket::SocketError errorCode, const QString &errorString);
+ void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString);
+
qint64 readBufferMaxSize;
QRingBuffer writeBuffer;
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index f2a3149678..d2b5882d18 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -58,6 +59,30 @@ class QNetworkInterface;
#endif
class QNetworkProxy;
+class QIpPacketHeader
+{
+public:
+ QIpPacketHeader(const QHostAddress &dstAddr = QHostAddress(), quint16 port = 0)
+ : destinationAddress(dstAddr), ifindex(0), hopLimit(-1), destinationPort(port)
+ {}
+
+ void clear()
+ {
+ senderAddress.clear();
+ destinationAddress.clear();
+ ifindex = 0;
+ hopLimit = -1;
+ }
+
+ QHostAddress senderAddress;
+ QHostAddress destinationAddress;
+
+ uint ifindex;
+ qint16 hopLimit;
+ quint16 senderPort;
+ quint16 destinationPort;
+};
+
class QAbstractSocketEngineReceiver {
public:
virtual ~QAbstractSocketEngineReceiver(){}
@@ -93,9 +118,21 @@ public:
KeepAliveOption,
MulticastTtlOption,
MulticastLoopbackOption,
- TypeOfServiceOption
+ TypeOfServiceOption,
+ ReceivePacketInformation,
+ ReceiveHopLimit
};
+ enum PacketHeaderOption {
+ WantNone = 0,
+ WantDatagramSender,
+ WantDatagramDestination,
+ WantDatagramHopLimit,
+
+ WantAll = 0xff
+ };
+ Q_DECLARE_FLAGS(PacketHeaderOptions, PacketHeaderOption)
+
virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0;
virtual bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) = 0;
@@ -126,10 +163,9 @@ public:
virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0;
#endif // QT_NO_NETWORKINTERFACE
- virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
- quint16 *port = 0) = 0;
- virtual qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
- quint16 port) = 0;
+ virtual qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header = 0,
+ PacketHeaderOptions = WantNone) = 0;
+ virtual qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) = 0;
virtual bool hasPendingDatagrams() const = 0;
virtual qint64 pendingDatagramSize() const = 0;
#endif // QT_NO_UDPSOCKET
@@ -225,6 +261,8 @@ private:
friend class QAbstractSocketEngine;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractSocketEngine::PacketHeaderOptions)
+
QT_END_NAMESPACE
#endif // QABSTRACTSOCKETENGINE_P_H
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 23347ce08b..1a90abd22c 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -271,14 +271,12 @@ bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &)
}
#endif // QT_NO_NETWORKINTERFACE
-qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *,
- quint16 *)
+qint64 QHttpSocketEngine::readDatagram(char *, qint64, QIpPacketHeader *, PacketHeaderOptions)
{
return 0;
}
-qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QHostAddress &,
- quint16)
+qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QIpPacketHeader &)
{
return 0;
}
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index 4d90487679..41c63fe11e 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -105,10 +105,9 @@ public:
bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE;
#endif // QT_NO_NETWORKINTERFACE
- qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
- quint16 *port = 0) Q_DECL_OVERRIDE;
- qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
- quint16 port) Q_DECL_OVERRIDE;
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *,
+ PacketHeaderOptions) Q_DECL_OVERRIDE;
+ qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE;
bool hasPendingDatagrams() const Q_DECL_OVERRIDE;
qint64 pendingDatagramSize() const Q_DECL_OVERRIDE;
#endif // QT_NO_UDPSOCKET
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 33bf3af0b5..c11b889220 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -88,6 +88,25 @@
errorString() can be called to determine the cause of the error.
*/
+/*!
+ \enum QAbstractSocketEngine::PacketHeaderOption
+
+ Specifies which fields in the IP packet header are desired in the call to
+ readDatagram().
+
+ \value WantNone caller isn't interested in the packet metadata
+ \value WantDatagramSender caller wants the sender address and port number
+ \value WantDatagramDestination caller wants the packet's destination address and port number
+ (this option is useful to distinguish multicast packets from unicast)
+ \value WantDatagramHopLimit caller wants the packet's remaining hop limit or time to live
+ (this option is useful in IPv4 multicasting, where the TTL is used
+ to indicate the realm)
+ \value WantAll this is a catch-all value to indicate the caller is
+ interested in all the available information
+
+ \sa readDatagram(), QUdpDatagram
+*/
+
#include "qnativesocketengine_p.h"
#include <qabstracteventdispatcher.h>
@@ -152,10 +171,6 @@ QT_BEGIN_NAMESPACE
/*! \internal
Constructs the private class and initializes all data members.
-
- On Windows, WSAStartup is called "recursively" for every
- concurrent QNativeSocketEngine. This is safe, because WSAStartup and
- WSACleanup are reference counted.
*/
QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
socketDescriptor(-1),
@@ -163,6 +178,9 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() :
writeNotifier(0),
exceptNotifier(0)
{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ QSysInfo::machineHostName(); // this initializes ws2_32.dll
+#endif
}
/*! \internal
@@ -395,13 +413,18 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb
return false;
}
- // Set the broadcasting flag if it's a UDP socket.
- if (socketType == QAbstractSocket::UdpSocket
- && !setOption(BroadcastSocketOption, 1)) {
- d->setError(QAbstractSocket::UnsupportedSocketOperationError,
- QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
- close();
- return false;
+ if (socketType == QAbstractSocket::UdpSocket) {
+ // Set the broadcasting flag if it's a UDP socket.
+ if (!setOption(BroadcastSocketOption, 1)) {
+ d->setError(QAbstractSocket::UnsupportedSocketOperationError,
+ QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
+ close();
+ return false;
+ }
+
+ // Set some extra flags that are interesting to us, but accept failure
+ setOption(ReceivePacketInformation, 1);
+ setOption(ReceiveHopLimit, 1);
}
@@ -760,9 +783,8 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const
/*!
Reads up to \a maxSize bytes of a datagram from the socket,
stores it in \a data and returns the number of bytes read. The
- address and port of the sender are stored in \a address and \a
- port. If either of these pointers is 0, the corresponding value is
- discarded.
+ address, port, and other IP header fields are stored in \a header
+ according to the request in \a options.
To avoid unnecessarily loss of data, call pendingDatagramSize() to
determine the size of the pending message before reading it. If \a
@@ -772,20 +794,23 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const
\sa hasPendingDatagrams()
*/
-qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
- quint16 *port)
+qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
+ PacketHeaderOptions options)
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
Q_CHECK_TYPE(QNativeSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, -1);
- return d->nativeReceiveDatagram(data, maxSize, address, port);
+ return d->nativeReceiveDatagram(data, maxSize, header, options);
}
/*!
Writes a UDP datagram of size \a size bytes to the socket from
- \a data to the address \a host on port \a port, and returns the
- number of bytes written, or -1 if an error occurred.
+ \a data to the destination contained in \a header, and returns the
+ number of bytes written, or -1 if an error occurred. If \a header
+ contains other settings like hop limit or source address, this function
+ will try to pass them to the operating system too, but will not
+ indicate an error if it could not pass them.
Only one datagram is sent, and if there is too much data to fit
into a single datagram, the operation will fail and error()
@@ -795,18 +820,19 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddres
disadvised, as even if they are sent successfully, they are likely
to be fragmented before arriving at their destination.
- Experience has shown that it is in general safe to send datagrams
- no larger than 512 bytes.
+ Experience has shown that it is in general safe to send IPv4 datagrams
+ no larger than 512 bytes or IPv6 datagrams no larger than 1280 (the
+ minimum MTU).
\sa readDatagram()
*/
-qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size,
- const QHostAddress &host, quint16 port)
+qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const QIpPacketHeader &header)
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1);
- return d->nativeSendDatagram(data, size, d->adjustAddressProtocol(host), port);
+
+ return d->nativeSendDatagram(data, size, header);
}
/*!
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 24909bf310..0fa1d8f96e 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -51,46 +51,51 @@
# include <netinet/in.h>
#else
# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <mswsock.h>
#endif
QT_BEGIN_NAMESPACE
-// Use our own defines and structs which we know are correct
-# define QT_SS_MAXSIZE 128
-# define QT_SS_ALIGNSIZE (sizeof(qint64))
-# define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short))
-# define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE))
-struct qt_sockaddr_storage {
- short ss_family;
- char __ss_pad1[QT_SS_PAD1SIZE];
- qint64 __ss_align;
- char __ss_pad2[QT_SS_PAD2SIZE];
-};
-
#ifdef Q_OS_WIN
#define QT_SOCKLEN_T int
#define QT_SOCKOPTLEN_T int
-#endif
-// sockaddr_in6 size changed between old and new SDK
-// Only the new version is the correct one, so always
-// use this structure.
-struct qt_in6_addr {
- quint8 qt_s6_addr[16];
-};
-struct qt_sockaddr_in6 {
- short sin6_family; /* AF_INET6 */
- quint16 sin6_port; /* Transport level port number */
- quint32 sin6_flowinfo; /* IPv6 flow information */
- struct qt_in6_addr sin6_addr; /* IPv6 address */
- quint32 sin6_scope_id; /* set of interfaces for a scope */
-};
+// The following definitions are copied from the MinGW header mswsock.h which
+// was placed in the public domain. The WSASendMsg and WSARecvMsg functions
+// were introduced with Windows Vista, so some Win32 headers are lacking them.
+// There are no known versions of Windows CE or Embedded that contain them.
+#ifndef Q_OS_WINCE
+# ifndef WSAID_WSARECVMSG
+typedef INT (WINAPI *LPFN_WSARECVMSG)(SOCKET s, LPWSAMSG lpMsg,
+ LPDWORD lpdwNumberOfBytesRecvd,
+ LPWSAOVERLAPPED lpOverlapped,
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+# define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
+# endif
+# ifndef WSAID_WSASENDMSG
+typedef struct {
+ LPWSAMSG lpMsg;
+ DWORD dwFlags;
+ LPDWORD lpNumberOfBytesSent;
+ LPWSAOVERLAPPED lpOverlapped;
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine;
+} WSASENDMSG, *LPWSASENDMSG;
+
+typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags,
+ LPDWORD lpNumberOfBytesSent,
+ LPWSAOVERLAPPED lpOverlapped,
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+
+# define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
+# endif
+#endif
+#endif
union qt_sockaddr {
sockaddr a;
sockaddr_in a4;
- qt_sockaddr_in6 a6;
- qt_sockaddr_storage storage;
+ sockaddr_in6 a6;
};
class QNativeSocketEnginePrivate;
@@ -133,10 +138,9 @@ public:
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
- qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
- quint16 *port = 0) Q_DECL_OVERRIDE;
- qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
- quint16 port) Q_DECL_OVERRIDE;
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0,
+ PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE;
+ qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE;
bool hasPendingDatagrams() const Q_DECL_OVERRIDE;
qint64 pendingDatagramSize() const Q_DECL_OVERRIDE;
@@ -173,16 +177,6 @@ private:
Q_DISABLE_COPY(QNativeSocketEngine)
};
-#ifdef Q_OS_WIN
-class QWindowsSockInit
-{
-public:
- QWindowsSockInit();
- ~QWindowsSockInit();
- int version;
-};
-#endif
-
class QSocketNotifier;
class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate
@@ -196,10 +190,10 @@ public:
QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier;
-#ifdef Q_OS_WIN
- QWindowsSockInit winSock;
-#endif
-
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ LPFN_WSASENDMSG sendmsg;
+ LPFN_WSARECVMSG recvmsg;
+# endif
enum ErrorString {
NonBlockingInitFailedErrorString,
BroadcastingInitFailedErrorString,
@@ -256,24 +250,48 @@ public:
bool nativeHasPendingDatagrams() const;
qint64 nativePendingDatagramSize() const;
- qint64 nativeReceiveDatagram(char *data, qint64 maxLength,
- QHostAddress *address, quint16 *port);
- qint64 nativeSendDatagram(const char *data, qint64 length,
- const QHostAddress &host, quint16 port);
+ qint64 nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
+ QAbstractSocketEngine::PacketHeaderOptions options);
+ qint64 nativeSendDatagram(const char *data, qint64 length, const QIpPacketHeader &header);
qint64 nativeRead(char *data, qint64 maxLength);
qint64 nativeWrite(const char *data, qint64 length);
int nativeSelect(int timeout, bool selectForRead) const;
int nativeSelect(int timeout, bool checkRead, bool checkWrite,
bool *selectForRead, bool *selectForWrite) const;
-#ifdef Q_OS_WIN
- void setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
- quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize);
-#endif
void nativeClose();
bool checkProxy(const QHostAddress &address);
bool fetchConnectionParameters();
+
+ static uint scopeIdFromString(const QString &scopeid);
+
+ /*! \internal
+ Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize.
+ The address \a is converted to IPv6 if the current socket protocol is also IPv6.
+ */
+ void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize)
+ {
+ if (address.protocol() == QAbstractSocket::IPv6Protocol
+ || address.protocol() == QAbstractSocket::AnyIPProtocol
+ || socketProtocol == QAbstractSocket::IPv6Protocol
+ || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ memset(&aa->a6, 0, sizeof(sockaddr_in6));
+ aa->a6.sin6_family = AF_INET6;
+ aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId());
+ aa->a6.sin6_port = htons(port);
+ Q_IPV6ADDR tmp = address.toIPv6Address();
+ memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp));
+ *sockAddrSize = sizeof(sockaddr_in6);
+ } else {
+ memset(&aa->a, 0, sizeof(sockaddr_in));
+ aa->a4.sin_family = AF_INET;
+ aa->a4.sin_port = htons(port);
+ aa->a4.sin_addr.s_addr = htonl(address.toIPv4Address());
+ *sockAddrSize = sizeof(sockaddr_in);
+ }
+ }
+
};
QT_END_NAMESPACE
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 5c4e4e885b..0e14c175c5 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -49,6 +49,9 @@
#ifdef QT_LINUXBASE
#include <arpa/inet.h>
#endif
+#ifdef Q_OS_BSD4
+#include <net/if_dl.h>
+#endif
#if defined QNATIVESOCKETENGINE_DEBUG
#include <qstring.h>
@@ -128,9 +131,9 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
}
}
-static inline uint makeScopeId(const QHostAddress &addr)
+// inline on purpose
+inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
{
- QString scopeid = addr.scopeId();
if (scopeid.isEmpty())
return 0;
@@ -202,6 +205,32 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
n = IP_TOS;
}
break;
+ case QNativeSocketEngine::ReceivePacketInformation:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_RECVPKTINFO;
+ } else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+ level = IPPROTO_IP;
+#ifdef IP_PKTINFO
+ n = IP_PKTINFO;
+#elif defined(IP_RECVDSTADDR)
+ // variant found in QNX and FreeBSD; it will get us only the
+ // destination address, not the interface; we need IP_RECVIF for that.
+ n = IP_RECVDSTADDR;
+#endif
+ }
+ break;
+ case QNativeSocketEngine::ReceiveHopLimit:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_RECVHOPLIMIT;
+ } else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+#ifdef IP_RECVTTL // IP_RECVTTL is a non-standard extension supported on some OS
+ level = IPPROTO_IP;
+ n = IP_RECVTTL;
+#endif
+ }
+ break;
}
}
@@ -285,7 +314,7 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co
QT_SOCKOPTLEN_T len = sizeof(v);
convertToLevelAndOption(opt, socketProtocol, level, n);
- if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
+ if (n != -1 && ::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
return v;
return -1;
@@ -360,37 +389,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
#endif
- struct sockaddr_in sockAddrIPv4;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
-
- struct sockaddr_in6 sockAddrIPv6;
-
- if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
- sockAddrIPv6.sin6_scope_id = makeScopeId(addr);
-
- Q_IPV6ADDR ip6 = addr.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
-
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
- } else
- if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address());
-
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
- } else {
- // unreachable
- }
+ qt_sockaddr aa;
+ QT_SOCKLEN_T sockAddrSize;
+ setPortAndAddress(port, addr, &aa, &sockAddrSize);
- int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+ int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
#if defined (QNATIVESOCKETENGINE_DEBUG)
int ecopy = errno;
#endif
@@ -462,51 +465,28 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
{
- struct sockaddr_in sockAddrIPv4;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
-
-
- struct sockaddr_in6 sockAddrIPv6;
+ qt_sockaddr aa;
+ QT_SOCKLEN_T sockAddrSize;
+ setPortAndAddress(port, address, &aa, &sockAddrSize);
- if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) {
#ifdef IPV6_V6ONLY
+ if (aa.a.sa_family == AF_INET6) {
int ipv6only = 0;
if (address.protocol() == QAbstractSocket::IPv6Protocol)
ipv6only = 1;
//default value of this socket option varies depending on unix variant (or system configuration on BSD), so always set it explicitly
::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+ }
#endif
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
- sockAddrIPv6.sin6_scope_id = makeScopeId(address);
-
- Q_IPV6ADDR tmp = address.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
- } else
- if (address.protocol() == QAbstractSocket::IPv4Protocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
- } else {
- // unreachable
- }
- int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
+ int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
- bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
+ // retry with v4
+ aa.a4.sin_family = AF_INET;
+ aa.a4.sin_port = htons(port);
+ aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
+ sockAddrSize = sizeof(aa.a4);
+ bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
}
if (bindResult < 0) {
@@ -844,68 +824,183 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return qint64(recvResult);
}
-qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
- QHostAddress *address, quint16 *port)
+qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
+ QAbstractSocketEngine::PacketHeaderOptions options)
{
+ // we use quintptr to force the alignment
+ quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)];
+
+ struct msghdr msg;
+ struct iovec vec;
qt_sockaddr aa;
+ char c;
+ memset(&msg, 0, sizeof(msg));
memset(&aa, 0, sizeof(aa));
- QT_SOCKLEN_T sz;
- sz = sizeof(aa);
- ssize_t recvFromResult = 0;
+ // we need to receive at least one byte, even if our user isn't interested in it
+ vec.iov_base = maxSize ? data : &c;
+ vec.iov_len = maxSize ? maxSize : 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ if (options & QAbstractSocketEngine::WantDatagramSender) {
+ msg.msg_name = &aa;
+ msg.msg_namelen = sizeof(aa);
+ }
+ if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) {
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof(cbuf);
+ }
+
+ ssize_t recvResult = 0;
do {
- char c;
- recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
- 0, &aa.a, &sz);
- } while (recvFromResult == -1 && errno == EINTR);
+ recvResult = ::recvmsg(socketDescriptor, &msg, 0);
+ } while (recvResult == -1 && errno == EINTR);
- if (recvFromResult == -1) {
+ if (recvResult == -1) {
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
- } else if (port || address) {
- qt_socket_getPortAndAddress(&aa, port, address);
+ if (header)
+ header->clear();
+ } else if (options != QAbstractSocketEngine::WantNone) {
+ Q_ASSERT(header);
+ qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
+ header->destinationPort = localPort;
+
+ // parse the ancillary data
+ struct cmsghdr *cmsgptr;
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+ if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
+ && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in6_pktinfo))) {
+ in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
+
+ header->destinationAddress.setAddress(reinterpret_cast<quint8 *>(&info->ipi6_addr));
+ header->ifindex = info->ipi6_ifindex;
+ if (header->ifindex)
+ header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
+ }
+
+#ifdef IP_PKTINFO
+ if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
+ && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_pktinfo))) {
+ in_pktinfo *info = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
+
+ header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
+ header->ifindex = info->ipi_ifindex;
+ }
+#else
+# ifdef IP_RECVDSTADDR
+ if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
+ && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_addr))) {
+ in_addr *addr = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
+
+ header->destinationAddress.setAddress(ntohl(addr->s_addr));
+ }
+# endif
+# if defined(IP_RECVIF) && defined(Q_OS_BSD4)
+ if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
+ && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) {
+ sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
+
+ header->ifindex = LLINDEX(sdl);
+ }
+# endif
+#endif
+
+ if (cmsgptr->cmsg_len == CMSG_LEN(sizeof(int))
+ && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
+ || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
+ header->hopLimit = *reinterpret_cast<int *>(CMSG_DATA(cmsgptr));
+ }
+ }
}
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
- data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize,
+ data, qt_prettyDebug(data, qMin(recvResult, ssize_t(16)), recvResult).data(), maxSize,
address ? address->toString().toLatin1().constData() : "(nil)",
- port ? *port : 0, (qint64) recvFromResult);
+ port ? *port : 0, (qint64) recvResult);
#endif
- return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0);
+ return qint64(maxSize ? recvResult : recvResult == -1 ? -1 : 0);
}
-qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
- const QHostAddress &host, quint16 port)
+qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
- struct sockaddr_in sockAddrIPv4;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
-
- struct sockaddr_in6 sockAddrIPv6;
- if (host.protocol() == QAbstractSocket::IPv6Protocol
- || socketProtocol == QAbstractSocket::IPv6Protocol
- || socketProtocol == QAbstractSocket::AnyIPProtocol) {
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
- sockAddrIPv6.sin6_scope_id = makeScopeId(host);
-
- Q_IPV6ADDR tmp = host.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
- } else if (host.protocol() == QAbstractSocket::IPv4Protocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
+ // we use quintptr to force the alignment
+ quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)];
+
+ struct cmsghdr *cmsgptr = reinterpret_cast<struct cmsghdr *>(cbuf);
+ struct msghdr msg;
+ struct iovec vec;
+ qt_sockaddr aa;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&aa, 0, sizeof(aa));
+ vec.iov_base = const_cast<char *>(data);
+ vec.iov_len = len;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_name = &aa.a;
+ msg.msg_control = &cbuf;
+
+ setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen);
+
+ if (msg.msg_namelen == sizeof(aa.a6)) {
+ if (header.hopLimit != -1) {
+ msg.msg_controllen += CMSG_SPACE(sizeof(int));
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_HOPLIMIT;
+ memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
+ cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int)));
+ }
+ if (header.ifindex != 0 || !header.senderAddress.isNull()) {
+ struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
+ memset(data, 0, sizeof(*data));
+ msg.msg_controllen += CMSG_SPACE(sizeof(*data));
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data));
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_PKTINFO;
+ data->ipi6_ifindex = header.ifindex;
+
+ QIPv6Address tmp = header.senderAddress.toIPv6Address();
+ memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
+ cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
+ }
+ } else {
+ if (header.hopLimit != -1) {
+ msg.msg_controllen += CMSG_SPACE(sizeof(int));
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ cmsgptr->cmsg_type = IP_TTL;
+ memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
+ cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int)));
+ }
+
+#if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
+ if (header.ifindex != 0 || !header.senderAddress.isNull()) {
+# ifdef IP_PKTINFO
+ struct in_pktinfo *data = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
+ memset(data, 0, sizeof(*data));
+ cmsgptr->cmsg_type = IP_PKTINFO;
+ data->ipi_ifindex = header.ifindex;
+ data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
+# elif defined(IP_SENDSRCADDR)
+ struct in_addr *data = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
+ cmsgptr->cmsg_type = IP_SENDSRCADDR;
+ addr->s_addr = htonl(header.senderAddress.toIPv4Address());
+# endif
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ msg.msg_controllen += CMSG_SPACE(sizeof(*data));
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data));
+ cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data)));
+ }
+#endif
}
- ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
- 0, sockAddrPtr, sockAddrSize);
+ if (msg.msg_controllen == 0)
+ msg.msg_control = 0;
+ ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
if (sentBytes < 0) {
switch (errno) {
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 7856db0487..2e905ad610 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
+#ifndef IP_HOPLIMIT
+#define IP_HOPLIMIT 21 // Receive packet hop limit.
+#endif
#if defined(QNATIVESOCKETENGINE_DEBUG)
@@ -168,10 +171,10 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
{
if (sa->a.sa_family == AF_INET6) {
- const qt_sockaddr_in6 *sa6 = &sa->a6;
+ const sockaddr_in6 *sa6 = &sa->a6;
Q_IPV6ADDR tmp;
for (int i = 0; i < 16; ++i)
- tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
+ tmp.c[i] = sa6->sin6_addr.s6_addr[i];
if (address) {
QHostAddress a;
a.setAddress(tmp);
@@ -252,40 +255,24 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
n = IP_MULTICAST_LOOP;
}
break;
- }
-}
-
-/*! \internal
-
- Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
-*/
-void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
- quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
-{
- if (address.protocol() == QAbstractSocket::IPv6Protocol
- || address.protocol() == QAbstractSocket::AnyIPProtocol
- || socketProtocol == QAbstractSocket::IPv6Protocol
- || socketProtocol == QAbstractSocket::AnyIPProtocol) {
- memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
- sockAddrIPv6->sin6_family = AF_INET6;
- sockAddrIPv6->sin6_scope_id = address.scopeId().toUInt();
- WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
- Q_IPV6ADDR tmp = address.toIPv6Address();
- memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp));
- *sockAddrSize = sizeof(qt_sockaddr_in6);
- *sockAddrPtr = (struct sockaddr *) sockAddrIPv6;
- } else
-
- if (address.protocol() == QAbstractSocket::IPv4Protocol
- || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
- memset(sockAddrIPv4, 0, sizeof(sockaddr_in));
- sockAddrIPv4->sin_family = AF_INET;
- WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port));
- WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr));
- *sockAddrSize = sizeof(sockaddr_in);
- *sockAddrPtr = (struct sockaddr *) sockAddrIPv4;
- } else {
- // unreachable
+ case QNativeSocketEngine::ReceivePacketInformation:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_PKTINFO;
+ } else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+ level = IPPROTO_IP;
+ n = IP_PKTINFO;
+ }
+ break;
+ case QNativeSocketEngine::ReceiveHopLimit:
+ if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
+ level = IPPROTO_IPV6;
+ n = IPV6_HOPLIMIT;
+ } else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
+ level = IPPROTO_IP;
+ n = IP_HOPLIMIT;
+ }
+ break;
}
}
@@ -320,25 +307,6 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
return value;
}
-QWindowsSockInit::QWindowsSockInit()
-: version(0)
-{
- //### should we try for 2.2 on all platforms ??
- WSAData wsadata;
-
- // IPv6 requires Winsock v2.0 or better.
- if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
- qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
- } else {
- version = 0x20;
- }
-}
-
-QWindowsSockInit::~QWindowsSockInit()
-{
- WSACleanup();
-}
-
// MS Transport Provider IOCTL to control
// reporting PORT_UNREACHABLE messages
// on UDP sockets via recv/WSARecv/etc.
@@ -354,6 +322,12 @@ QWindowsSockInit::~QWindowsSockInit()
# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
#endif
+// inline on purpose
+inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid)
+{
+ return scopeid.toUInt();
+}
+
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{
@@ -439,6 +413,20 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
WS_ERROR_DEBUG(err);
}
}
+
+ // get the pointer to sendmsg and recvmsg
+ DWORD bytesReturned;
+ GUID recvmsgguid = WSAID_WSARECVMSG;
+ if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &recvmsgguid, sizeof(recvmsgguid),
+ &recvmsg, sizeof(recvmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
+ recvmsg = 0;
+
+ GUID sendmsgguid = WSAID_WSASENDMSG;
+ if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &sendmsgguid, sizeof(sendmsgguid),
+ &sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
+ sendmsg = 0;
#endif
socketDescriptor = socket;
@@ -630,12 +618,10 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
#endif
- struct sockaddr_in sockAddrIPv4;
- qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr = 0;
+ qt_sockaddr aa;
QT_SOCKLEN_T sockAddrSize = 0;
- setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
+ setPortAndAddress(port, address, &aa, &sockAddrSize);
if ((socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) && address.toIPv4Address()) {
//IPV6_V6ONLY option must be cleared to connect to a V4 mapped address
@@ -646,7 +632,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
}
forever {
- int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
+ int connectResult = ::WSAConnect(socketDescriptor, &aa.a, sockAddrSize, 0,0,0,0);
if (connectResult == SOCKET_ERROR) {
int err = WSAGetLastError();
WS_ERROR_DEBUG(err);
@@ -769,46 +755,36 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
{
QHostAddress address = a;
- DWORD ipv6only = 0;
- switch (address.protocol()) {
- case QAbstractSocket::IPv6Protocol:
- if (address.toIPv6Address()[0] == 0xff) {
- // binding to a multicast address
- address = QHostAddress(QHostAddress::AnyIPv6);
- }
- //This is default in current windows versions, it may change in future so set it explicitly
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) {
- ipv6only = 1;
- ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
- }
- break;
- case QAbstractSocket::IPv4Protocol:
+ if (address.protocol() == QAbstractSocket::IPv4Protocol) {
if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
// binding to a multicast address
address = QHostAddress(QHostAddress::AnyIPv4);
}
- break;
- case QAbstractSocket::AnyIPProtocol:
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) {
- ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
- } else {
- address = QHostAddress(QHostAddress::AnyIPv4); //xp/WS2003 and earlier don't support dual stack, so bind to IPv4
- socketProtocol = QAbstractSocket::IPv4Protocol;
- }
- break;
- default:
- break;
}
- struct sockaddr_in sockAddrIPv4;
- qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr = 0;
+ qt_sockaddr aa;
QT_SOCKLEN_T sockAddrSize = 0;
+ setPortAndAddress(port, address, &aa, &sockAddrSize);
- setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
+ if (aa.a.sa_family == AF_INET6) {
+ // The default may change in future, so set it explicitly
+ int ipv6only = 0;
+ if (address.protocol() == QAbstractSocket::IPv6Protocol)
+ ipv6only = 1;
+ ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
+ }
- int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
+ int bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize);
+ if (bindResult == SOCKET_ERROR && WSAGetLastError() == WSAEAFNOSUPPORT
+ && address.protocol() == QAbstractSocket::AnyIPProtocol) {
+ // retry with v4
+ aa.a4.sin_family = AF_INET;
+ aa.a4.sin_port = htons(port);
+ aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
+ sockAddrSize = sizeof(aa.a4);
+ bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize);
+ }
if (bindResult == SOCKET_ERROR) {
int err = WSAGetLastError();
WS_ERROR_DEBUG(err);
@@ -1215,33 +1191,47 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return ret;
}
+#ifdef Q_OS_WINCE
+// Windows CE has no support for sendmsg or recvmsg. We set it to null here to simplify the code below.
+static int (*const recvmsg)(...) = 0;
+static int (*const sendmsg)(...) = 0;
+#endif
-qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength,
- QHostAddress *address, quint16 *port)
+qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
+ QAbstractSocketEngine::PacketHeaderOptions options)
{
- qint64 ret = 0;
-
+ union {
+ char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))];
+ WSACMSGHDR align; // only to ensure alignment
+ };
+ WSAMSG msg;
+ WSABUF buf;
qt_sockaddr aa;
+ char c;
+ memset(&msg, 0, sizeof(msg));
memset(&aa, 0, sizeof(aa));
- QT_SOCKLEN_T sz;
- sz = sizeof(aa);
- WSABUF buf;
- buf.buf = data;
- buf.len = maxLength;
-#if !defined(Q_OS_WINCE)
- buf.buf = data;
- buf.len = maxLength;
-#else
- char tmpChar;
- buf.buf = data ? data : &tmpChar;
- buf.len = maxLength;
-#endif
+ // we need to receive at least one byte, even if our user isn't interested in it
+ buf.buf = maxLength ? data : &c;
+ buf.len = maxLength ? maxLength : 1;
+ msg.lpBuffers = &buf;
+ msg.dwBufferCount = 1;
+ msg.name = reinterpret_cast<LPSOCKADDR>(&aa);
+ msg.namelen = sizeof(aa);
+ if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) {
+ msg.Control.buf = cbuf;
+ msg.Control.len = sizeof(cbuf);
+ }
DWORD flags = 0;
DWORD bytesRead = 0;
- int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
- if (wsaRet == SOCKET_ERROR) {
+ qint64 ret;
+
+ if (recvmsg)
+ ret = recvmsg(socketDescriptor, &msg, &bytesRead, 0,0);
+ else
+ ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, msg.name, &msg.namelen,0,0);
+ if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEMSGSIZE) {
// it is ok the buffer was to small if bytesRead is larger than
@@ -1251,12 +1241,44 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
WS_ERROR_DEBUG(err);
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
ret = -1;
+ if (header)
+ header->clear();
}
} else {
ret = qint64(bytesRead);
+ if (options & QNativeSocketEngine::WantDatagramSender)
+ qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress);
}
- qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
+ if (ret != -1 && recvmsg) {
+ // get the ancillary data
+ WSACMSGHDR *cmsgptr;
+ for (cmsgptr = WSA_CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = WSA_CMSG_NXTHDR(&msg, cmsgptr)) {
+ if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
+ && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in6_pktinfo))) {
+ in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
+ QHostAddress target(reinterpret_cast<quint8 *>(&info->ipi6_addr));
+ if (info->ipi6_ifindex)
+ target.setScopeId(QString::number(info->ipi6_ifindex));
+ }
+ if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
+ && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in_pktinfo))) {
+ in_pktinfo *info = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
+ u_long addr;
+ WSANtohl(socketDescriptor, info->ipi_addr.s_addr, &addr);
+ QHostAddress target(addr);
+ if (info->ipi_ifindex)
+ target.setScopeId(QString::number(info->ipi_ifindex));
+ }
+
+ if (cmsgptr->cmsg_len == WSA_CMSG_LEN(sizeof(int))
+ && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
+ || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
+ header->hopLimit = *reinterpret_cast<int *>(WSA_CMSG_DATA(cmsgptr));
+ }
+ }
+ }
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li",
@@ -1270,27 +1292,94 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
- const QHostAddress &address, quint16 port)
+ const QIpPacketHeader &header)
{
- qint64 ret = -1;
- struct sockaddr_in sockAddrIPv4;
- qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
-
- setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
-
+ union {
+ char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))];
+ WSACMSGHDR align; // ensures alignment
+ };
+ WSACMSGHDR *cmsgptr = &align;
+ WSAMSG msg;
WSABUF buf;
+ qt_sockaddr aa;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&aa, 0, sizeof(aa));
#if !defined(Q_OS_WINCE)
buf.buf = len ? (char*)data : 0;
#else
char tmp;
buf.buf = len ? (char*)data : &tmp;
#endif
+ msg.lpBuffers = &buf;
+ msg.dwBufferCount = 1;
+ msg.name = &aa.a;
buf.len = len;
+
+ setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.namelen);
+
+ if (msg.namelen == sizeof(aa.a6)) {
+ // sending IPv6
+ if (header.hopLimit != -1) {
+ msg.Control.len += WSA_CMSG_SPACE(sizeof(int));
+ cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int));
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_HOPLIMIT;
+ memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
+ cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
+ + WSA_CMSG_SPACE(sizeof(int)));
+ }
+ if (header.ifindex != 0 || !header.senderAddress.isNull()) {
+ struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
+ memset(data, 0, sizeof(*data));
+ msg.Control.len += WSA_CMSG_SPACE(sizeof(*data));
+ cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data));
+ cmsgptr->cmsg_level = IPPROTO_IPV6;
+ cmsgptr->cmsg_type = IPV6_PKTINFO;
+ data->ipi6_ifindex = header.ifindex;
+
+ Q_IPV6ADDR tmp = header.senderAddress.toIPv6Address();
+ memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
+ cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
+ + WSA_CMSG_SPACE(sizeof(*data)));
+ }
+ } else {
+ // sending IPv4
+ if (header.hopLimit != -1) {
+ msg.Control.len += WSA_CMSG_SPACE(sizeof(int));
+ cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int));
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ cmsgptr->cmsg_type = IP_TTL;
+ memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
+ cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
+ + WSA_CMSG_SPACE(sizeof(int)));
+ }
+ if (header.ifindex != 0 || !header.senderAddress.isNull()) {
+ struct in_pktinfo *data = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
+ memset(data, 0, sizeof(*data));
+ msg.Control.len += WSA_CMSG_SPACE(sizeof(*data));
+ cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data));
+ cmsgptr->cmsg_level = IPPROTO_IP;
+ cmsgptr->cmsg_type = IP_PKTINFO;
+ data->ipi_ifindex = header.ifindex;
+ WSAHtonl(socketDescriptor, header.senderAddress.toIPv4Address(), &data->ipi_addr.s_addr);
+ cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
+ + WSA_CMSG_SPACE(sizeof(*data)));
+ }
+ }
+
+ if (msg.Control.len != 0)
+ msg.Control.buf = cbuf;
+
DWORD flags = 0;
DWORD bytesSent = 0;
- if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) {
+ qint64 ret = -1;
+ if (sendmsg) {
+ ret = sendmsg(socketDescriptor, &msg, flags, &bytesSent, 0,0);
+ } else {
+ ret = ::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, msg.name, msg.namelen, 0,0);
+ }
+ if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
WS_ERROR_DEBUG(err);
switch (err) {
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 2d04946601..025e3e5017 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -538,18 +538,19 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len)
return bytesWritten;
}
-qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port)
+qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header,
+ PacketHeaderOptions)
{
Q_D(QNativeSocketEngine);
- if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty())
+ if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) {
+ if (header)
+ header->clear();
return -1;
+ }
WinRtDatagram datagram = d->pendingDatagrams.takeFirst();
- if (addr)
- *addr = datagram.address;
-
- if (port)
- *port = datagram.port;
+ if (header)
+ *header = datagram.header;
QByteArray readOrigin;
// Do not read the whole datagram. Put the rest of it back into the "queue"
@@ -564,7 +565,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress
return readOrigin.length();
}
-qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &addr, quint16 port)
+qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
Q_D(QNativeSocketEngine);
if (d->socketType != QAbstractSocket::UdpSocket)
@@ -576,13 +577,13 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QH
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
&hostNameFactory);
RETURN_IF_FAILED("Could not obtain hostname factory", return -1);
- const QString addressString = addr.toString();
+ const QString addressString = header.destinationAddress.toString();
HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(addressString.utf16()));
hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
ComPtr<IAsyncOperation<IOutputStream *>> streamOperation;
ComPtr<IOutputStream> stream;
- const QString portString = QString::number(port);
+ const QString portString = QString::number(header.destinationPort);
HStringReference portRef(reinterpret_cast<LPCWSTR>(portString.utf16()));
hr = d->udpSocket()->GetOutputStreamAsync(remoteHost.Get(), portRef.Get(), &streamOperation);
RETURN_IF_FAILED("Failed to get output stream to socket", return -1);
@@ -1230,11 +1231,11 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I
remoteHost->get_CanonicalName(remoteHostString.GetAddressOf());
RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name");
returnAddress.setAddress(qt_QStringFromHString(remoteHostString));
- datagram.address = returnAddress;
+ datagram.header.senderAddress = returnAddress;
HString remotePort;
hr = args->get_RemotePort(remotePort.GetAddressOf());
RETURN_OK_IF_FAILED("Could not obtain remote port");
- datagram.port = qt_QStringFromHString(remotePort).toInt();
+ datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt();
ComPtr<IDataReader> reader;
hr = args->GetDataReader(&reader);
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index eb032bc977..4286ff6373 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -58,8 +58,7 @@ class QNativeSocketEnginePrivate;
struct WinRtDatagram {
QByteArray data;
- int port;
- QHostAddress address;
+ QIpPacketHeader header;
};
class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine
@@ -97,10 +96,8 @@ public:
qint64 read(char *data, qint64 maxlen);
qint64 write(const char *data, qint64 len);
- qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
- quint16 *port = 0);
- qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
- quint16 port);
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions);
+ qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h
index a5a87fc7c1..9626c53711 100644
--- a/src/network/socket/qnet_unix_p.h
+++ b/src/network/socket/qnet_unix_p.h
@@ -173,8 +173,7 @@ static inline in_addr_t qt_safe_inet_addr(const char *cp)
#endif
}
-// VxWorks' headers do not specify any const modifiers
-static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *to, QT_SOCKLEN_T tolen)
+static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
#ifdef MSG_NOSIGNAL
flags |= MSG_NOSIGNAL;
@@ -183,11 +182,7 @@ static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int fl
#endif
int ret;
-#ifdef Q_OS_VXWORKS
- EINTR_LOOP(ret, ::sendto(sockfd, (char *) buf, len, flags, (struct sockaddr *) to, tolen));
-#else
- EINTR_LOOP(ret, ::sendto(sockfd, buf, len, flags, to, tolen));
-#endif
+ EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags));
return ret;
}
@@ -199,24 +194,6 @@ static inline int qt_safe_recvmsg(int sockfd, struct msghdr *msg, int flags)
return ret;
}
-// VxWorks' headers do not specify any const modifiers
-static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags)
-{
-#ifdef MSG_NOSIGNAL
- flags |= MSG_NOSIGNAL;
-#else
- qt_ignore_sigpipe();
-#endif
-
- int ret;
-#ifdef Q_OS_VXWORKS
- EINTR_LOOP(ret, ::sendmsg(sockfd, (struct msghdr *) msg, flags);
-#else
- EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags));
-#endif
- return ret;
-}
-
QT_END_NAMESPACE
#endif // QNET_UNIX_P_H
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index a6eafd2601..26543883cc 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1383,7 +1383,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port)
#endif
dummy.setProxy(QNetworkProxy::NoProxy);
if (!dummy.bind()
- || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0
+ || writeDatagram(0,0, QIpPacketHeader(d->data->controlSocket->localAddress(), dummy.localPort())) != 0
|| !dummy.waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))
|| dummy.readDatagram(0,0, &d->localAddress, &d->localPort) != 0) {
QSOCKS5_DEBUG << "udp actual address and port lookup failed";
@@ -1555,7 +1555,7 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len)
#ifndef QT_NO_UDPSOCKET
} else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
// send to connected address
- return writeDatagram(data, len, d->peerAddress, d->peerPort);
+ return writeDatagram(data, len, QIpPacketHeader(d->peerAddress, d->peerPort));
#endif
}
//### set an error ???
@@ -1594,8 +1594,7 @@ bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &)
}
#endif // QT_NO_NETWORKINTERFACE
-qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr,
- quint16 *port)
+qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, PacketHeaderOptions)
{
Q_D(QSocks5SocketEngine);
@@ -1607,15 +1606,12 @@ qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress
QSocks5RevivedDatagram datagram = d->udpData->pendingDatagrams.dequeue();
int copyLen = qMin<int>(maxlen, datagram.data.size());
memcpy(data, datagram.data.constData(), copyLen);
- if (addr)
- *addr = datagram.address;
- if (port)
- *port = datagram.port;
+ header->senderAddress = datagram.address;
+ header->senderPort = datagram.port;
return copyLen;
}
-qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &address,
- quint16 port)
+qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
Q_D(QSocks5SocketEngine);
@@ -1634,7 +1630,7 @@ qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QH
outBuf[0] = 0x00;
outBuf[1] = 0x00;
outBuf[2] = 0x00;
- if (!qt_socks5_set_host_address_and_port(address, port, &outBuf)) {
+ if (!qt_socks5_set_host_address_and_port(header.destinationAddress, header.destinationPort, &outBuf)) {
}
outBuf += QByteArray(data, len);
QSOCKS5_DEBUG << "sending" << dump(outBuf);
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index c97b0e89ce..de20e0ef0e 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -93,10 +93,9 @@ public:
bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE;
#endif // QT_NO_NETWORKINTERFACE
- qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0,
- quint16 *port = 0) Q_DECL_OVERRIDE;
- qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr,
- quint16 port) Q_DECL_OVERRIDE;
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0,
+ PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE;
+ qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE;
bool hasPendingDatagrams() const Q_DECL_OVERRIDE;
qint64 pendingDatagramSize() const Q_DECL_OVERRIDE;
#endif // QT_NO_UDPSOCKET
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index 914c14877e..bf75666548 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -559,6 +559,10 @@ QTcpSocket *QTcpServer::nextPendingConnection()
may not be usable with native socket functions, and should only be
used with QTcpSocket::setSocketDescriptor().
+ \note If another socket is created in the reimplementation
+ of this method, it needs to be added to the Pending Connections mechanism
+ by calling addPendingConnection().
+
\note If you want to handle an incoming connection as a new QTcpSocket
object in another thread you have to pass the socketDescriptor
to the other thread and create the QTcpSocket object there and
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index 87686f94e1..a46e6ade04 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -333,15 +333,13 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre
if (state() == UnconnectedState)
bind();
- qint64 sent = d->socketEngine->writeDatagram(data, size, address, port);
+ qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
if (sent >= 0) {
emit bytesWritten(sent);
} else {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
- emit error(d->socketError);
+ d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
}
return sent;
}
@@ -379,13 +377,23 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres
qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port);
#endif
QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1);
- qint64 readBytes = d->socketEngine->readDatagram(data, maxSize, address, port);
- d_func()->socketEngine->setReadNotificationEnabled(true);
- if (readBytes < 0) {
- d->socketError = d->socketEngine->error();
- setErrorString(d->socketEngine->errorString());
- emit error(d->socketError);
+
+ qint64 readBytes;
+ if (address || port) {
+ QIpPacketHeader header;
+ readBytes = d->socketEngine->readDatagram(data, maxSize, &header,
+ QAbstractSocketEngine::WantDatagramSender);
+ if (address)
+ *address = header.senderAddress;
+ if (port)
+ *port = header.senderPort;
+ } else {
+ readBytes = d->socketEngine->readDatagram(data, maxSize);
}
+
+ d_func()->socketEngine->setReadNotificationEnabled(true);
+ if (readBytes < 0)
+ d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
return readBytes;
}
#endif // QT_NO_UDPSOCKET
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index c15045b180..b62cfd2fde 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -499,8 +499,7 @@ bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state
d->createPlainSocket(openMode);
bool retVal = d->plainSocket->setSocketDescriptor(socketDescriptor, state, openMode);
d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
- setSocketError(d->plainSocket->error());
- setErrorString(d->plainSocket->errorString());
+ d->setError(d->plainSocket->error(), d->plainSocket->errorString());
setSocketState(state);
setOpenMode(openMode);
setLocalPort(d->plainSocket->localPort());
@@ -1532,8 +1531,7 @@ bool QSslSocket::waitForConnected(int msecs)
bool retVal = d->plainSocket->waitForConnected(msecs);
if (!retVal) {
setSocketState(d->plainSocket->state());
- setSocketError(d->plainSocket->error());
- setErrorString(d->plainSocket->errorString());
+ d->setError(d->plainSocket->error(), d->plainSocket->errorString());
}
return retVal;
}
@@ -1688,8 +1686,7 @@ bool QSslSocket::waitForDisconnected(int msecs)
bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed()));
if (!retVal) {
setSocketState(d->plainSocket->state());
- setSocketError(d->plainSocket->error());
- setErrorString(d->plainSocket->errorString());
+ d->setError(d->plainSocket->error(), d->plainSocket->errorString());
}
return retVal;
}
@@ -2402,15 +2399,22 @@ void QSslSocketPrivate::_q_stateChangedSlot(QAbstractSocket::SocketState state)
*/
void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error)
{
- Q_Q(QSslSocket);
+ Q_UNUSED(error)
#ifdef QSSLSOCKET_DEBUG
+ Q_Q(QSslSocket);
qCDebug(lcSsl) << "QSslSocket::_q_errorSlot(" << error << ')';
qCDebug(lcSsl) << "\tstate =" << q->state();
qCDebug(lcSsl) << "\terrorString =" << q->errorString();
#endif
- q->setSocketError(plainSocket->error());
- q->setErrorString(plainSocket->errorString());
- emit q->error(error);
+ // this moves encrypted bytes from plain socket into our buffer
+ if (plainSocket->bytesAvailable()) {
+ qint64 tmpReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained
+ transmit();
+ readBufferMaxSize = tmpReadBufferMaxSize;
+ }
+
+ setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
}
/*!
@@ -2475,7 +2479,6 @@ void QSslSocketPrivate::_q_flushReadBuffer()
*/
void QSslSocketPrivate::_q_resumeImplementation()
{
- Q_Q(QSslSocket);
if (plainSocket)
plainSocket->resume();
paused = false;
@@ -2483,9 +2486,7 @@ void QSslSocketPrivate::_q_resumeImplementation()
if (verifyErrorsHaveBeenIgnored()) {
continueHandshake();
} else {
- q->setErrorString(sslErrors.first().errorString());
- q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
- emit q->error(QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString());
plainSocket->disconnectFromHost();
return;
}
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp
index b83e56c29e..06c707f271 100644
--- a/src/network/ssl/qsslsocket_mac.cpp
+++ b/src/network/ssl/qsslsocket_mac.cpp
@@ -51,6 +51,10 @@
#include <algorithm>
#include <cstddef>
+#ifdef Q_OS_OSX
+#include <CoreServices/CoreServices.h>
+#endif
+
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive))
@@ -318,7 +322,7 @@ void QSslSocketBackendPrivate::startClientEncryption()
// Error description/code were set, 'error' emitted
// by initSslContext, but OpenSSL socket also sets error
// emits a signal twice, so ...
- setError("Unable to init SSL Context", QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context");
return;
}
@@ -331,7 +335,7 @@ void QSslSocketBackendPrivate::startServerEncryption()
// Error description/code were set, 'error' emitted
// by initSslContext, but OpenSSL socket also sets error
// emits a signal twice, so ...
- setError("Unable to init SSL Context", QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context");
return;
}
@@ -360,8 +364,8 @@ void QSslSocketBackendPrivate::transmit()
qCDebug(lcSsl) << plainSocket << "SSLWrite returned" << err;
#endif
if (err != noErr && err != errSSLWouldBlock) {
- setError(QStringLiteral("SSLWrite failed: %1").arg(err),
- QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QStringLiteral("SSLWrite failed: %1").arg(err));
break;
}
@@ -395,12 +399,12 @@ void QSslSocketBackendPrivate::transmit()
#endif
if (err == errSSLClosedGraceful) {
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
- setError(QSslSocket::tr("The TLS/SSL connection has been closed"),
- QAbstractSocket::RemoteHostClosedError);
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ QSslSocket::tr("The TLS/SSL connection has been closed"));
break;
} else if (err != noErr && err != errSSLWouldBlock) {
- setError(QStringLiteral("SSLRead failed: %1").arg(err),
- QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QStringLiteral("SSLRead failed: %1").arg(err));
break;
}
@@ -658,7 +662,7 @@ bool QSslSocketBackendPrivate::initSslContext()
context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType);
if (!context) {
- setError("SSLCreateContext failed", QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError, "SSLCreateContext failed");
return false;
}
@@ -666,8 +670,8 @@ bool QSslSocketBackendPrivate::initSslContext()
reinterpret_cast<SSLWriteFunc>(&_q_SSLWrite));
if (err != noErr) {
destroySslContext();
- setError(QStringLiteral("SSLSetIOFuncs failed: %1").arg(err),
- QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QStringLiteral("SSLSetIOFuncs failed: %1").arg(err));
return false;
}
@@ -679,14 +683,14 @@ bool QSslSocketBackendPrivate::initSslContext()
QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
if (!setSessionCertificate(errorDescription, errorCode)) {
destroySslContext();
- setError(errorDescription, errorCode);
+ setErrorAndEmit(errorCode, errorDescription);
return false;
}
}
if (!setSessionProtocol()) {
destroySslContext();
- setError("Failed to set protocol version", QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError, "Failed to set protocol version");
return false;
}
@@ -698,8 +702,8 @@ bool QSslSocketBackendPrivate::initSslContext()
const OSStatus err = SSLSetEnableCertVerify(context, false);
if (err != noErr) {
destroySslContext();
- setError(QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err),
- QSslSocket::SslInternalError);
+ setErrorAndEmit(QSslSocket::SslInternalError,
+ QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err));
return false;
}
}
@@ -720,8 +724,8 @@ bool QSslSocketBackendPrivate::initSslContext()
if (err != noErr) {
destroySslContext();
- setError(QStringLiteral("SSLSetSessionOption failed: %1").arg(err),
- QSslSocket::SslInternalError);
+ setErrorAndEmit(QSslSocket::SslInternalError,
+ QStringLiteral("SSLSetSessionOption failed: %1").arg(err));
return false;
}
//
@@ -737,8 +741,8 @@ bool QSslSocketBackendPrivate::initSslContext()
if (err != noErr) {
destroySslContext();
- setError(QStringLiteral("failed to set SSL context option in server mode: %1").arg(err),
- QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QStringLiteral("failed to set SSL context option in server mode: %1").arg(err));
return false;
}
}
@@ -981,8 +985,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
// !trust - SSLCopyPeerTrust can return noErr but null trust.
if (err != noErr || !trust) {
if (!canIgnoreVerify) {
- setError(QStringLiteral("Failed to obtain peer trust: %1").arg(err),
- QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QStringLiteral("Failed to obtain peer trust: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
} else {
@@ -1005,8 +1009,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
if (err != noErr) {
// We can not ignore this, it's not even about trust verification
// probably ...
- setError(QStringLiteral("SecTrustEvaluate failed: %1").arg(err),
- QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
}
@@ -1124,8 +1128,8 @@ bool QSslSocketBackendPrivate::checkSslErrors()
pauseSocketNotifiers(q);
paused = true;
} else {
- setError(sslErrors.first().errorString(),
- QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ sslErrors.first().errorString());
plainSocket->disconnectFromHost();
}
return false;
@@ -1162,7 +1166,7 @@ bool QSslSocketBackendPrivate::startHandshake()
// setSessionCertificate does not fail if we have no certificate.
// Failure means a real error (invalid certificate, no private key, etc).
if (!setSessionCertificate(errorDescription, errorCode)) {
- setError(errorDescription, errorCode);
+ setErrorAndEmit(errorCode, errorDescription);
return false;
} else {
// We try to resume a handshake, even if have no
@@ -1177,8 +1181,8 @@ bool QSslSocketBackendPrivate::startHandshake()
return startHandshake();
}
- setError(QStringLiteral("SSLHandshake failed: %1").arg(err),
- QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QStringLiteral("SSLHandshake failed: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
}
@@ -1192,8 +1196,8 @@ bool QSslSocketBackendPrivate::startHandshake()
// check protocol version ourselves, as Secure Transport does not enforce
// the requested min / max versions.
if (!verifySessionProtocol()) {
- setError("Protocol version mismatch",
- QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ "Protocol version mismatch");
plainSocket->disconnectFromHost();
return false;
}
@@ -1206,16 +1210,6 @@ bool QSslSocketBackendPrivate::startHandshake()
}
}
-void QSslSocketBackendPrivate::setError(const QString &errorString,
- QAbstractSocket::SocketError errorCode)
-{
- Q_Q(QSslSocket);
-
- q->setErrorString(errorString);
- q->setSocketError(errorCode);
- emit q->error(errorCode);
-}
-
/*
PKCS12 helpers.
*/
diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h
index 868b816957..414c155882 100644
--- a/src/network/ssl/qsslsocket_mac_p.h
+++ b/src/network/ssl/qsslsocket_mac_p.h
@@ -101,13 +101,6 @@ private:
bool checkSslErrors();
bool startHandshake();
- // Aux. function, sets:
- //1) socket error code,
- //2) error string (description)
- //3) emits a signal.
- void setError(const QString &errorString,
- QAbstractSocket::SocketError errorCode);
-
mutable QCFType<SSLContextRef> context;
Q_DISABLE_COPY(QSslSocketBackendPrivate);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 1634d65eb6..0a4c68d7c0 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -364,9 +364,7 @@ bool QSslSocketBackendPrivate::initSslContext()
}
if (sslContextPointer->error() != QSslError::NoError) {
- q->setErrorString(sslContextPointer->errorString());
- q->setSocketError(QAbstractSocket::SslInvalidUserDataError);
- emit q->error(QAbstractSocket::SslInvalidUserDataError);
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString());
sslContextPointer.clear(); // deletes the QSslContext
return false;
}
@@ -374,9 +372,8 @@ bool QSslSocketBackendPrivate::initSslContext()
// Create and initialize SSL session
if (!(ssl = sslContextPointer->createSsl())) {
// ### Bad error code
- q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl()));
return false;
}
@@ -405,9 +402,8 @@ bool QSslSocketBackendPrivate::initSslContext()
readBio = q_BIO_new(q_BIO_s_mem());
writeBio = q_BIO_new(q_BIO_s_mem());
if (!readBio || !writeBio) {
- q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl()));
return false;
}
@@ -808,11 +804,9 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
void QSslSocketBackendPrivate::startClientEncryption()
{
- Q_Q(QSslSocket);
if (!initSslContext()) {
- q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl()));
return;
}
@@ -824,11 +818,9 @@ void QSslSocketBackendPrivate::startClientEncryption()
void QSslSocketBackendPrivate::startServerEncryption()
{
- Q_Q(QSslSocket);
if (!initSslContext()) {
- q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl()));
return;
}
@@ -874,9 +866,9 @@ void QSslSocketBackendPrivate::transmit()
break;
} else {
// ### Better error handling.
- q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Unable to write data: %1").arg(
+ getErrorsFromOpenSsl()));
return;
}
}
@@ -918,9 +910,7 @@ void QSslSocketBackendPrivate::transmit()
#endif
if (actualWritten < 0) {
//plain socket write fails if it was in the pending close state.
- q->setErrorString(plainSocket->errorString());
- q->setSocketError(plainSocket->error());
- emit q->error(plainSocket->error());
+ setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
return;
}
transmitting = true;
@@ -946,9 +936,9 @@ void QSslSocketBackendPrivate::transmit()
plainSocket->read(data.data(), writtenToBio);
} else {
// ### Better error handling.
- q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Unable to decrypt data: %1").arg(
+ getErrorsFromOpenSsl()));
return;
}
@@ -1022,17 +1012,15 @@ void QSslSocketBackendPrivate::transmit()
qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: remote disconnect";
#endif
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
- q->setErrorString(QSslSocket::tr("The TLS/SSL connection has been closed"));
- q->setSocketError(QAbstractSocket::RemoteHostClosedError);
- emit q->error(QAbstractSocket::RemoteHostClosedError);
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ QSslSocket::tr("The TLS/SSL connection has been closed"));
return;
case SSL_ERROR_SYSCALL: // some IO error
case SSL_ERROR_SSL: // error in the SSL library
// we do not know exactly what the error is, nor whether we can recover from it,
// so just return to prevent an endless loop in the outer "while" statement
- q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
return;
default:
// SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
@@ -1040,9 +1028,8 @@ void QSslSocketBackendPrivate::transmit()
// SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
// SSL_CTX_set_client_cert_cb(), which we do not call.
// So this default case should never be triggered.
- q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
break;
}
} while (ssl && readBytes > 0);
@@ -1134,12 +1121,12 @@ bool QSslSocketBackendPrivate::startHandshake()
// The handshake is not yet complete.
break;
default:
- q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()));
- q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
+ QString errorString
+ = QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl());
#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString();
+ qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << errorString;
#endif
- emit q->error(QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString);
q->abort();
}
return false;
@@ -1290,9 +1277,7 @@ bool QSslSocketBackendPrivate::checkSslErrors()
pauseSocketNotifiers(q);
paused = true;
} else {
- q->setErrorString(sslErrors.first().errorString());
- q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
- emit q->error(QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString());
plainSocket->disconnectFromHost();
}
return false;
@@ -1513,6 +1498,13 @@ void QSslSocketBackendPrivate::disconnected()
{
if (plainSocket->bytesAvailable() <= 0)
destroySslContext();
+ else {
+ // Move all bytes into the plain buffer
+ qint64 tmpReadBufferMaxSize = readBufferMaxSize;
+ readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained
+ transmit();
+ readBufferMaxSize = tmpReadBufferMaxSize;
+ }
//if there is still buffered data in the plain socket, don't destroy the ssl context yet.
//it will be destroyed when the socket is deleted.
}
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index aba3ea8170..b03f234d49 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -251,9 +251,8 @@ void QSslSocketBackendPrivate::startClientEncryption()
case QSsl::TlsV1_2OrLater:
// TlsV1_0OrLater, TlsV1_1OrLater and TlsV1_2OrLater are disabled on WinRT
// because there is no good way to map them to the native API.
- q->setErrorString(QStringLiteral("unsupported protocol"));
- q->setSocketError(QAbstractSocket::SslInvalidUserDataError);
- emit q->error(QAbstractSocket::SslInvalidUserDataError);
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
+ QStringLiteral("unsupported protocol"));
return;
default:
protectionLevel = SocketProtectionLevel_Tls12; // default to highest
@@ -347,13 +346,10 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
void QSslSocketBackendPrivate::continueHandshake()
{
- Q_Q(QSslSocket);
-
IStreamSocket *socket = reinterpret_cast<IStreamSocket *>(plainSocket->socketDescriptor());
if (qintptr(socket) == -1) {
- q->setErrorString(QStringLiteral("At attempt was made to continue the handshake on an invalid socket."));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QStringLiteral("At attempt was made to continue the handshake on an invalid socket."));
return;
}
@@ -372,9 +368,7 @@ void QSslSocketBackendPrivate::continueHandshake()
Q_ASSERT_SUCCEEDED(hr);
}
if (FAILED(hr)) {
- q->setErrorString(qt_error_string(hr));
- q->setSocketError(QAbstractSocket::SslInvalidUserDataError);
- emit q->error(QAbstractSocket::SslInvalidUserDataError);
+ setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, qt_error_string(hr));
return;
}
@@ -440,10 +434,8 @@ void QSslSocketBackendPrivate::continueHandshake()
ComPtr<IAsyncAction> op;
hr = socket->UpgradeToSslAsync(protectionLevel, hostName.Get(), &op);
if (FAILED(hr)) {
- q->setErrorString(QSslSocket::tr("Error creating SSL session: %1")
- .arg(qt_error_string(hr)));
- q->setSocketError(QAbstractSocket::SslInternalError);
- emit q->error(QAbstractSocket::SslInternalError);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error creating SSL session: %1").arg(qt_error_string(hr)));
return;
}
@@ -467,9 +459,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus
QSet<QSslError> errors;
switch (hr) {
case SEC_E_INVALID_TOKEN: // Occurs when the server doesn't support the requested protocol
- q->setErrorString(qt_error_string(hr));
- q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
- emit q->error(QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, qt_error_string(hr));
q->disconnectFromHost();
return S_OK;
default:
@@ -628,9 +618,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus
if (!sslErrors.isEmpty()) {
emit q->sslErrors(sslErrors);
- q->setErrorString(sslErrors.first().errorString());
- q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
- emit q->error(QAbstractSocket::SslHandshakeFailedError);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString());
// Disconnect if there are any non-ignorable errors
foreach (const QSslError &error, sslErrors) {
diff --git a/src/opengl/doc/src/qtopengl-index.qdoc b/src/opengl/doc/src/qtopengl-index.qdoc
index d8e63547b7..a01ccc67f6 100644
--- a/src/opengl/doc/src/qtopengl-index.qdoc
+++ b/src/opengl/doc/src/qtopengl-index.qdoc
@@ -32,7 +32,7 @@
use OpenGL in Qt applications.
\warning This module should not be used anymore for new code. Please
- use the corresponding OpenGL classes in \l{Qt Gui}.
+ use the corresponding OpenGL classes in \l{Qt GUI}.
OpenGL is a standard API for rendering 3D graphics. OpenGL only
deals with 3D rendering and provides little or no support for GUI
diff --git a/src/opengl/doc/src/qtopengl-module.qdoc b/src/opengl/doc/src/qtopengl-module.qdoc
index 824db48754..80742dd588 100644
--- a/src/opengl/doc/src/qtopengl-module.qdoc
+++ b/src/opengl/doc/src/qtopengl-module.qdoc
@@ -35,7 +35,7 @@
use OpenGL in Qt applications.
\warning This module should not be used anymore for new code. Please
- use the corresponding OpenGL classes in \l{Qt Gui}.
+ use the corresponding OpenGL classes in \l{Qt GUI}.
OpenGL is a standard API for rendering 3D graphics. OpenGL only
deals with 3D rendering and provides little or no support for GUI
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 8929a038e0..905f7695bb 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -241,7 +241,8 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
void QEGLPlatformContext::initialize()
{
- updateFormatFromGL();
+ if (m_eglContext != EGL_NO_CONTEXT)
+ updateFormatFromGL();
}
// Base implementation for pbuffers. Subclasses will handle the specialized cases for
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 222161734d..a87443cc85 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -45,7 +45,6 @@
#include "qcoretextfontdatabase_p.h"
#include "qfontengine_coretext_p.h"
#include <QtCore/QSettings>
-#include <QtGui/QGuiApplication>
#include <QtCore/QtEndian>
#ifndef QT_NO_FREETYPE
#include <QtGui/private/qfontengine_ft_p.h>
@@ -399,17 +398,14 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr)
}
#endif
+ // Since we do not pass in the destination DPI to CoreText when making
+ // the font, we need to pass in a point size which is scaled to include
+ // the DPI. The default DPI for the screen is 72, thus the scale factor
+ // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi,
+ // the pixelSize is actually the scaled point size for the destination
+ // DPI, and we can use that directly.
qreal scaledPointSize = f.pixelSize;
- // When 96 DPI is forced, the Mac plugin will use DPI 72 for some
- // fonts (hardcoded in qcocoaintegration.mm) and 96 for others. This
- // discrepancy makes it impossible to find the correct point size
- // here without having the DPI used for the font. Until a proper
- // solution (requiring API change) can be made, we simply fall back
- // to passing in the point size to retain old behavior.
- if (QGuiApplication::testAttribute(Qt::AA_Use96Dpi))
- scaledPointSize = f.pointSize;
-
CGAffineTransform matrix = qt_transform_from_fontdef(f);
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix);
if (font) {
@@ -725,8 +721,8 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
kATSOptionFlagsDefault, &fontContainer);
} else {
FSRef ref;
- OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref);
- if (qt_mac_create_fsref(fileName, &ref) != noErr)
+ if (FSPathMakeRef(reinterpret_cast<const UInt8 *>(fileName.toUtf8().constData()),
+ &ref, 0) != noErr)
return QStringList();
e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0,
kATSOptionFlagsDefault, &fontContainer);
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 7e1dfd9275..732aead62a 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -361,16 +361,6 @@ qreal QCoreTextFontEngine::maxCharWidth() const
return bb.xoff.toReal();
}
-qreal QCoreTextFontEngine::minLeftBearing() const
-{
- return 0;
-}
-
-qreal QCoreTextFontEngine::minRightBearing() const
-{
- return 0;
-}
-
void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
{
QVarLengthArray<QFixedPoint> positions;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
index f8ec1d326f..1c33ae7d84 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h
@@ -96,8 +96,6 @@ public:
QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE;
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
- qreal minRightBearing() const Q_DECL_OVERRIDE;
- qreal minLeftBearing() const Q_DECL_OVERRIDE;
QFixed emSquareSize() const Q_DECL_OVERRIDE;
bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index 1ca95074b9..ad348cc083 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -38,6 +38,7 @@
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <linux/input.h>
@@ -106,9 +107,8 @@ public:
int m_currentSlot;
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
- void reportPoints();
- void registerDevice();
void addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates);
+ void reportPoints();
int hw_range_x_min;
int hw_range_x_max;
@@ -118,7 +118,6 @@ public:
int hw_pressure_max;
QString hw_name;
bool m_forceToActiveWindow;
- QTouchDevice *m_device;
bool m_typeB;
QTransform m_rotate;
bool m_singleTouch;
@@ -131,23 +130,11 @@ QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, co
hw_range_x_min(0), hw_range_x_max(0),
hw_range_y_min(0), hw_range_y_max(0),
hw_pressure_min(0), hw_pressure_max(0),
- m_device(0), m_typeB(false), m_singleTouch(false)
+ m_typeB(false), m_singleTouch(false)
{
m_forceToActiveWindow = args.contains(QLatin1String("force_window"));
}
-void QEvdevTouchScreenData::registerDevice()
-{
- m_device = new QTouchDevice;
- m_device->setName(hw_name);
- m_device->setType(QTouchDevice::TouchScreen);
- m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area);
- if (hw_pressure_max > hw_pressure_min)
- m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure);
-
- QWindowSystemInterface::registerTouchDevice(m_device);
-}
-
#define LONG_BITS (sizeof(long) << 3)
#define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS)
@@ -159,9 +146,9 @@ static inline bool testBit(long bit, const long *array)
#endif
QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const QString &spec, QObject *parent)
- : QObject(parent), m_notify(0), m_fd(-1), d(0)
+ : QObject(parent), m_notify(Q_NULLPTR), m_fd(-1), d(Q_NULLPTR), m_device(Q_NULLPTR)
#if !defined(QT_NO_MTDEV)
- , m_mtdev(0)
+ , m_mtdev(Q_NULLPTR)
#endif
{
setObjectName(QLatin1String("Evdev Touch Handler"));
@@ -298,7 +285,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
if (inverty)
d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5);
- d->registerDevice();
+ registerTouchDevice();
}
QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler()
@@ -314,6 +301,13 @@ QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler()
QT_CLOSE(m_fd);
delete d;
+
+ unregisterTouchDevice();
+}
+
+QTouchDevice *QEvdevTouchScreenHandler::touchDevice() const
+{
+ return m_device;
}
void QEvdevTouchScreenHandler::readData()
@@ -367,15 +361,44 @@ err:
qErrnoWarning(errno, "evdevtouch: Could not read from input device");
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notify;
- m_notify = 0;
+ m_notify = Q_NULLPTR;
+
QT_CLOSE(m_fd);
m_fd = -1;
+
+ unregisterTouchDevice();
}
return;
}
}
}
+void QEvdevTouchScreenHandler::registerTouchDevice()
+{
+ if (m_device)
+ return;
+
+ m_device = new QTouchDevice;
+ m_device->setName(d->hw_name);
+ m_device->setType(QTouchDevice::TouchScreen);
+ m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area);
+ if (d->hw_pressure_max > d->hw_pressure_min)
+ m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure);
+
+ QWindowSystemInterface::registerTouchDevice(m_device);
+}
+
+void QEvdevTouchScreenHandler::unregisterTouchDevice()
+{
+ if (!m_device)
+ return;
+
+ QWindowSystemInterface::unregisterTouchDevice(m_device);
+
+ delete m_device;
+ m_device = Q_NULLPTR;
+}
+
void QEvdevTouchScreenData::addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates)
{
QWindowSystemInterface::TouchPoint tp;
@@ -604,9 +627,10 @@ void QEvdevTouchScreenData::reportPoints()
QWindow *win = QGuiApplication::focusWindow();
if (!win)
return;
- winRect = win->geometry();
+ winRect = QHighDpi::toNativePixels(win->geometry(), win);
} else {
- winRect = QGuiApplication::primaryScreen()->geometry();
+ QScreen *primary = QGuiApplication::primaryScreen();
+ winRect = QHighDpi::toNativePixels(primary->geometry(), primary);
}
const int hw_w = hw_range_x_max - hw_range_x_min;
@@ -637,12 +661,12 @@ void QEvdevTouchScreenData::reportPoints()
tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min);
}
- QWindowSystemInterface::handleTouchEvent(0, m_device, m_touchPoints);
+ QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, q->touchDevice(), m_touchPoints);
}
QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent)
- : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(0)
+ : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(Q_NULLPTR), m_touchDeviceRegistered(false)
{
start();
}
@@ -656,9 +680,24 @@ QEvdevTouchScreenHandlerThread::~QEvdevTouchScreenHandlerThread()
void QEvdevTouchScreenHandlerThread::run()
{
m_handler = new QEvdevTouchScreenHandler(m_device, m_spec);
+ // Report the registration to the parent thread by invoking the method asynchronously
+ QMetaObject::invokeMethod(this, "notifyTouchDeviceRegistered", Qt::QueuedConnection);
+
exec();
+
delete m_handler;
- m_handler = 0;
+ m_handler = Q_NULLPTR;
+}
+
+bool QEvdevTouchScreenHandlerThread::isTouchDeviceRegistered() const
+{
+ return m_touchDeviceRegistered;
+}
+
+void QEvdevTouchScreenHandlerThread::notifyTouchDeviceRegistered()
+{
+ m_touchDeviceRegistered = true;
+ emit touchDeviceRegistered();
}
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
index 8e7dfe59bb..ca9756d5de 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
@@ -66,16 +66,22 @@ class QEvdevTouchScreenHandler : public QObject
Q_OBJECT
public:
- explicit QEvdevTouchScreenHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0);
+ explicit QEvdevTouchScreenHandler(const QString &device, const QString &spec = QString(), QObject *parent = Q_NULLPTR);
~QEvdevTouchScreenHandler();
+ QTouchDevice *touchDevice() const;
+
private slots:
void readData();
private:
+ void registerTouchDevice();
+ void unregisterTouchDevice();
+
QSocketNotifier *m_notify;
int m_fd;
QEvdevTouchScreenData *d;
+ QTouchDevice *m_device;
#if !defined(QT_NO_MTDEV)
mtdev *m_mtdev;
#endif
@@ -83,16 +89,24 @@ private:
class QEvdevTouchScreenHandlerThread : public QDaemonThread
{
+ Q_OBJECT
public:
- explicit QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent = 0);
+ explicit QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent = Q_NULLPTR);
~QEvdevTouchScreenHandlerThread();
void run() Q_DECL_OVERRIDE;
- QEvdevTouchScreenHandler *handler() { return m_handler; }
+
+ bool isTouchDeviceRegistered() const;
+
+signals:
+ void touchDeviceRegistered();
private:
+ Q_INVOKABLE void notifyTouchDeviceRegistered();
+
QString m_device;
QString m_spec;
QEvdevTouchScreenHandler *m_handler;
+ bool m_touchDeviceRegistered;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
index 98fc83700c..35a685ff21 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
@@ -91,17 +91,17 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif
QEvdevTouchManager::~QEvdevTouchManager()
{
qDeleteAll(m_activeDevices);
+ updateInputDeviceCount();
}
void QEvdevTouchManager::addDevice(const QString &deviceNode)
{
- qCDebug(qLcEvdevTouch) << "Adding device at" << deviceNode;
+ qCDebug(qLcEvdevTouch) << "evdevtouch: Adding device at" << deviceNode;
QEvdevTouchScreenHandlerThread *handler;
handler = new QEvdevTouchScreenHandlerThread(deviceNode, m_spec);
if (handler) {
m_activeDevices.insert(deviceNode, handler);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count());
+ connect(handler, &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount);
} else {
qWarning("evdevtouch: Failed to open touch device %s", qPrintable(deviceNode));
}
@@ -110,13 +110,28 @@ void QEvdevTouchManager::addDevice(const QString &deviceNode)
void QEvdevTouchManager::removeDevice(const QString &deviceNode)
{
if (m_activeDevices.contains(deviceNode)) {
- qCDebug(qLcEvdevTouch) << "Removing device at" << deviceNode;
+ qCDebug(qLcEvdevTouch) << "evdevtouch: Removing device at" << deviceNode;
QEvdevTouchScreenHandlerThread *handler = m_activeDevices.value(deviceNode);
m_activeDevices.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count());
delete handler;
+
+ updateInputDeviceCount();
}
}
+void QEvdevTouchManager::updateInputDeviceCount()
+{
+ int registeredTouchDevices = 0;
+ Q_FOREACH (QEvdevTouchScreenHandlerThread *handler, m_activeDevices) {
+ if (handler->isTouchDeviceRegistered())
+ ++registeredTouchDevices;
+ }
+
+ qCDebug(qLcEvdevTouch) << "evdevtouch: Updating QInputDeviceManager device count:" << registeredTouchDevices << " touch devices,"
+ << m_activeDevices.count() - registeredTouchDevices << "pending handler(s)" ;
+
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeTouch, registeredTouchDevices);
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
index bf484fd88b..289c345ac4 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
@@ -65,6 +65,8 @@ private slots:
void addDevice(const QString &deviceNode);
void removeDevice(const QString &deviceNode);
+ void updateInputDeviceCount();
+
private:
QString m_spec;
QDeviceDiscovery *m_deviceDiscovery;
diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp
index 1a64ad5a30..5aa66a4eaf 100644
--- a/src/platformsupport/input/libinput/qlibinputhandler.cpp
+++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(qLcInput, "qt.qpa.input")
+Q_LOGGING_CATEGORY(qLcLibInput, "qt.qpa.input")
static int liOpen(const char *path, int flags, void *user_data)
{
@@ -75,7 +75,7 @@ static void liLogHandler(libinput *libinput, libinput_log_priority priority, con
if (n > 0) {
if (buf[n - 1] == '\n')
buf[n - 1] = '\0';
- qCDebug(qLcInput, "libinput: %s", buf);
+ qCDebug(qLcLibInput, "libinput: %s", buf);
}
}
@@ -93,7 +93,7 @@ QLibInputHandler::QLibInputHandler(const QString &key, const QString &spec)
qFatal("Failed to get libinput context");
libinput_log_set_handler(m_li, liLogHandler);
- if (qLcInput().isDebugEnabled())
+ if (qLcLibInput().isDebugEnabled())
libinput_log_set_priority(m_li, LIBINPUT_LOG_PRIORITY_DEBUG);
if (libinput_udev_assign_seat(m_li, "seat0"))
diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
index 5f1bc550b4..ec7ea7ef0d 100644
--- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
+++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
@@ -33,6 +33,7 @@
#include "qlibinputkeyboard_p.h"
#include <QtCore/QTextCodec>
+#include <QtCore/QLoggingCategory>
#include <qpa/qwindowsysteminterface.h>
#include <libinput.h>
#ifndef QT_NO_XKBCOMMON_EVDEV
@@ -42,6 +43,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(qLcLibInput)
+
const int REPEAT_DELAY = 500;
const int REPEAT_RATE = 100;
@@ -128,6 +131,7 @@ QLibInputKeyboard::QLibInputKeyboard()
#endif
{
#ifndef QT_NO_XKBCOMMON_EVDEV
+ qCDebug(qLcLibInput) << "Using xkbcommon for key mapping";
m_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!m_ctx) {
qWarning("Failed to create xkb context");
@@ -150,6 +154,8 @@ QLibInputKeyboard::QLibInputKeyboard()
m_repeatTimer.setSingleShot(true);
connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat);
+#else
+ qCWarning(qLcLibInput) << "X-less xkbcommon not available, not performing key mapping";
#endif
}
@@ -174,10 +180,13 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e)
const uint32_t k = libinput_event_keyboard_get_key(e) + 8;
const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED;
- QByteArray chars;
- chars.resize(1 + xkb_state_key_get_utf8(m_state, k, Q_NULLPTR, 0));
- xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
- const QString text = QString::fromUtf8(chars);
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
+ if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
+ chars.resize(size + 1);
+ xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
+ }
+ const QString text = QString::fromUtf8(chars.constData(), size);
const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k);
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index 637b06549a..ae1ba1819a 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -47,8 +47,11 @@
QT_BEGIN_NAMESPACE
-QString A11Y_SERVICE = QStringLiteral("org.a11y.Bus");
-QString A11Y_PATH = QStringLiteral("/org/a11y/bus");
+/* note: do not change these to QStringLiteral;
+ we are unloaded before QtDBus is done using the strings.
+ */
+#define A11Y_SERVICE QLatin1String("org.a11y.Bus")
+#define A11Y_PATH QLatin1String("/org/a11y/bus")
/*!
\class DBusConnection
@@ -137,7 +140,7 @@ void DBusConnection::connectA11yBus(const QString &address)
qWarning("Could not find Accessibility DBus address.");
return;
}
- m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, QStringLiteral("a11y")));
+ m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, QLatin1String("a11y")));
if (m_enabled)
emit enabledChanged(true);
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 93a8d83524..fe03c7ac06 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
+#include <QtCore/QStandardPaths>
#include <QtCore/QStringList>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
@@ -209,14 +210,16 @@ public:
, wheelScrollLines(3)
{ }
- static QString kdeGlobals(const QString &kdeDir)
+ static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
{
+ if (kdeVersion > 4)
+ return kdeDir + QStringLiteral("/kdeglobals");
return kdeDir + QStringLiteral("/share/config/kdeglobals");
}
void refresh();
- static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings);
- static void readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
+ static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings);
+ static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
static QFont *kdeFont(const QVariant &fontValue);
static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs);
@@ -246,30 +249,30 @@ void QKdeThemePrivate::refresh()
QHash<QString, QSettings*> kdeSettings;
QPalette systemPalette = QPalette();
- readKdeSystemPalette(kdeDirs, kdeSettings, &systemPalette);
+ readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, &systemPalette);
resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
- const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeSettings);
+ const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeVersion, kdeSettings);
if (styleValue.isValid()) {
const QString style = styleValue.toString();
if (style != styleNames.front())
styleNames.push_front(style);
}
- const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeSettings);
+ const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
if (singleClickValue.isValid())
singleClick = singleClickValue.toBool();
- const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeSettings);
+ const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeVersion, kdeSettings);
if (themeValue.isValid())
iconThemeName = themeValue.toString();
- const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeSettings);
+ const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeVersion, kdeSettings);
if (toolBarIconSizeValue.isValid())
toolBarIconSize = toolBarIconSizeValue.toInt();
- const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeSettings);
+ const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings);
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
if (toolBarStyle == QLatin1String("TextBesideIcon"))
@@ -280,17 +283,17 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
- const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeSettings);
+ const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeVersion, kdeSettings);
if (wheelScrollLinesValue.isValid())
wheelScrollLines = wheelScrollLinesValue.toInt();
// Read system font, ignore 'smallestReadableFont'
- if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeSettings)))
+ if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings)))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
else
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
- if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeSettings))) {
+ if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) {
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
} else {
fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
@@ -301,12 +304,12 @@ void QKdeThemePrivate::refresh()
qDeleteAll(kdeSettings);
}
-QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings)
+QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
{
foreach (const QString &kdeDir, kdeDirs) {
QSettings *settings = kdeSettings.value(kdeDir);
if (!settings) {
- const QString kdeGlobalsPath = kdeGlobals(kdeDir);
+ const QString kdeGlobalsPath = kdeGlobals(kdeDir, kdeVersion);
if (QFileInfo(kdeGlobalsPath).isReadable()) {
settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat);
kdeSettings.insert(kdeDir, settings);
@@ -334,9 +337,9 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVari
return true;
}
-void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
+void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
{
- if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeSettings))) {
+ if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings))) {
// kcolorscheme.cpp: SetDefaultColors
const QColor defaultWindowBackground(214, 210, 208);
const QColor defaultButtonBackground(223, 220, 217);
@@ -344,18 +347,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash<QS
return;
}
- kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeSettings));
- kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeSettings));
+ kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
// The above code sets _all_ color roles to "normal" colors. In KDE, the disabled
// color roles are calculated by applying various effects described in kdeglobals.
@@ -497,6 +500,11 @@ QPlatformTheme *QKdeTheme::createKdeTheme()
if (kdeVersion < 4)
return 0;
+ if (kdeVersion > 4)
+ // Plasma 5 follows XDG spec
+ // but uses the same config file format:
+ return new QKdeTheme(QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation), kdeVersion);
+
// Determine KDE prefixes in the following priority order:
// - KDEHOME and KDEDIRS environment variables
// - ~/.kde(<version>)
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 2ddbc4519b..19525397fa 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -100,9 +100,10 @@ public:
static bool write(QIODevice *device, const QVector<QImage> &images);
+ bool readIconEntry(int index, ICONDIRENTRY * iconEntry);
+
private:
bool readHeader();
- bool readIconEntry(int index, ICONDIRENTRY * iconEntry);
bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header);
void findColorInfo(QImage & image);
@@ -341,7 +342,7 @@ bool ICOReader::readHeader()
bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry)
{
- if (iod) {
+ if (readHeader()) {
if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) {
return readIconDirEntry(iod, iconEntry);
}
@@ -558,10 +559,10 @@ QImage ICOReader::iconAt(int index)
if (icoAttrib.ncolors > 256) //color table can't be more than 256
return img;
icoAttrib.w = iconEntry.bWidth;
- if (icoAttrib.w == 0)
+ if (icoAttrib.w == 0) // means 256 pixels
icoAttrib.w = header.biWidth;
icoAttrib.h = iconEntry.bHeight;
- if (icoAttrib.h == 0)
+ if (icoAttrib.h == 0) // means 256 pixels
icoAttrib.h = header.biHeight/2;
QImage::Format format = QImage::Format_ARGB32;
@@ -658,10 +659,11 @@ bool ICOReader::write(QIODevice *device, const QVector<QImage> &images)
for (int i=0; i<id.idCount; i++) {
QImage image = images[i];
- // Scale down the image if it is larger than 128 pixels in either width or height
- if (image.width() > 128 || image.height() > 128)
+ // Scale down the image if it is larger than 256 pixels in either width or height
+ // because this is a maximum size of image in the ICO file.
+ if (image.width() > 256 || image.height() > 256)
{
- image = image.scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ image = image.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QImage maskImage(image.width(), image.height(), QImage::Format_Mono);
image = image.convertToFormat(QImage::Format_ARGB32);
@@ -778,25 +780,37 @@ QtIcoHandler::~QtIcoHandler()
QVariant QtIcoHandler::option(ImageOption option) const
{
- if (option == Size) {
- QIODevice *device = QImageIOHandler::device();
- qint64 oldPos = device->pos();
+ if (option == Size || option == ImageFormat) {
ICONDIRENTRY iconEntry;
- if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) {
- if (readIconDirEntry(device, &iconEntry)) {
- device->seek(oldPos);
- return QSize(iconEntry.bWidth, iconEntry.bHeight);
+ if (m_pICOReader->readIconEntry(m_currentIconIndex, &iconEntry)) {
+ switch (option) {
+ case Size:
+ return QSize(iconEntry.bWidth ? iconEntry.bWidth : 256,
+ iconEntry.bHeight ? iconEntry.bHeight : 256);
+
+ case ImageFormat:
+ switch (iconEntry.wBitCount) {
+ case 2:
+ return QImage::Format_Mono;
+ case 24:
+ return QImage::Format_RGB32;
+ case 32:
+ return QImage::Format_ARGB32;
+ default:
+ return QImage::Format_Indexed8;
+ }
+ break;
+ default:
+ break;
}
}
- if (!device->isSequential())
- device->seek(oldPos);
}
return QVariant();
}
bool QtIcoHandler::supportsOption(ImageOption option) const
{
- return option == Size;
+ return (option == Size || option == ImageFormat);
}
/*!
@@ -881,9 +895,10 @@ bool QtIcoHandler::jumpToImage(int imageNumber)
{
if (imageNumber < imageCount()) {
m_currentIconIndex = imageNumber;
+ return true;
}
- return imageNumber < imageCount();
+ return false;
}
/*! \reimp
diff --git a/src/plugins/platforminputcontexts/compose/compose.json b/src/plugins/platforminputcontexts/compose/compose.json
index 2daf89ed30..fb95f1bfb0 100644
--- a/src/plugins/platforminputcontexts/compose/compose.json
+++ b/src/plugins/platforminputcontexts/compose/compose.json
@@ -1,3 +1,3 @@
{
- "Keys": [ "compose" ]
+ "Keys": [ "compose", "xim" ]
}
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
index 96f6424ba2..15c98ed006 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
@@ -52,7 +52,8 @@ QComposeInputContext *QComposePlatformInputContextPlugin::create(const QString &
{
Q_UNUSED(paramList);
- if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0)
+ if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0
+ || system.compare(system, QLatin1String("xim"), Qt::CaseInsensitive) == 0)
return new QComposeInputContext;
return 0;
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 2027e010d0..9a41244c63 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -301,12 +301,12 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
quint32 sym = keyEvent->nativeVirtualKey();
quint32 code = keyEvent->nativeScanCode();
quint32 state = keyEvent->nativeModifiers();
+ quint32 ibusState = state;
if (keyEvent->type() != QEvent::KeyPress)
- state |= IBUS_RELEASE_MASK;
+ ibusState |= IBUS_RELEASE_MASK;
- code -= 8; // ###
- QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code, state);
+ QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code - 8, ibusState);
if (m_eventFilterUseSynchronousMode || reply.isFinished()) {
bool retval = reply.value();
@@ -315,17 +315,36 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
}
Qt::KeyboardModifiers modifiers = keyEvent->modifiers();
+ const int qtcode = keyEvent->key();
+
+ // From QKeyEvent::modifiers()
+ switch (qtcode) {
+ case Qt::Key_Shift:
+ modifiers ^= Qt::ShiftModifier;
+ break;
+ case Qt::Key_Control:
+ modifiers ^= Qt::ControlModifier;
+ break;
+ case Qt::Key_Alt:
+ modifiers ^= Qt::AltModifier;
+ break;
+ case Qt::Key_Meta:
+ modifiers ^= Qt::MetaModifier;
+ break;
+ case Qt::Key_AltGr:
+ modifiers ^= Qt::GroupSwitchModifier;
+ break;
+ }
QVariantList args;
args << QVariant::fromValue(keyEvent->timestamp());
args << QVariant::fromValue(static_cast<uint>(keyEvent->type()));
- args << QVariant::fromValue(keyEvent->key());
+ args << QVariant::fromValue(qtcode);
args << QVariant::fromValue(code) << QVariant::fromValue(sym) << QVariant::fromValue(state);
args << QVariant::fromValue(keyEvent->text());
args << QVariant::fromValue(keyEvent->isAutoRepeat());
- args << QVariant::fromValue(keyEvent->count());
- QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, qApp->focusObject(), modifiers, args);
+ QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, QGuiApplication::focusWindow(), modifiers, args);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &QIBusPlatformInputContext::filterEventFinished);
return true;
@@ -343,9 +362,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
// Use watcher's window instead of the current focused window
// since there is a time lag until filterEventFinished() returns.
- QObject *input = watcher->input();
+ QWindow *window = watcher->window();
- if (!input) {
+ if (!window) {
call->deleteLater();
return;
}
@@ -360,14 +379,12 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
const quint32 state = args.at(5).toUInt();
const QString string = args.at(6).toString();
const bool isAutoRepeat = args.at(7).toBool();
- const int count = args.at(8).toInt();
// copied from QXcbKeyboard::handleKeyEvent()
bool retval = reply.value();
qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << retval;
if (!retval) {
#ifndef QT_NO_CONTEXTMENU
- QWindow *window = dynamic_cast<QWindow *>(input);
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu
&& window != NULL) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos();
@@ -376,10 +393,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
globalPos, modifiers);
}
#endif // QT_NO_CONTEXTMENU
- QKeyEvent event(type, qtcode, modifiers, code, sym,
- state, string, isAutoRepeat, count);
- event.setTimestamp(time);
- QCoreApplication::sendEvent(input, &event);
+ QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
+ code, sym, state, string, isAutoRepeat);
+
}
call->deleteLater();
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 91f15ea159..127db7df8b 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -38,6 +38,7 @@
#include <QtCore/qpointer.h>
#include <QtDBus/qdbuspendingreply.h>
#include <QLoggingCategory>
+#include <QWindow>
QT_BEGIN_NAMESPACE
@@ -51,23 +52,23 @@ class QIBusFilterEventWatcher: public QDBusPendingCallWatcher
public:
explicit QIBusFilterEventWatcher(const QDBusPendingCall &call,
QObject *parent = 0,
- QObject *input = 0,
+ QWindow *window = 0,
const Qt::KeyboardModifiers modifiers = 0,
const QVariantList arguments = QVariantList())
: QDBusPendingCallWatcher(call, parent)
- , m_input(input)
+ , m_window(window)
, m_modifiers(modifiers)
, m_arguments(arguments)
{}
~QIBusFilterEventWatcher()
{}
- inline QObject *input() const { return m_input; }
+ inline QWindow *window() const { return m_window; }
inline const Qt::KeyboardModifiers modifiers() const { return m_modifiers; }
inline const QVariantList arguments() const { return m_arguments; }
private:
- QPointer<QObject> m_input;
+ QPointer<QWindow> m_window;
const Qt::KeyboardModifiers m_modifiers;
const QVariantList m_arguments;
};
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index 18ea884091..2d1aa41a9a 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -38,6 +38,8 @@
#include <QtGui>
#include <qpa/qplatformaccessibility.h>
+#ifndef QT_NO_ACCESSIBILITY
+
QT_BEGIN_NAMESPACE
class QCocoaAccessibility : public QPlatformAccessibility
@@ -85,4 +87,6 @@ id getValueAttribute(QAccessibleInterface *interface);
QT_END_NAMESPACE
-#endif
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QCOCOAACCESIBILITY_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 56042e72ea..f83d15f48e 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -37,6 +37,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
+
QCocoaAccessibility::QCocoaAccessibility()
{
@@ -378,5 +380,7 @@ id getValueAttribute(QAccessibleInterface *interface)
} // namespace QCocoaAccessible
+#endif // QT_NO_ACCESSIBILITY
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 33a7ef4add..73aeae129b 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -37,7 +37,10 @@
#include "qt_mac_p.h"
-#import <AppKit/AppKit.h>
+#ifndef QT_NO_ACCESSIBILITY
+
+#import <Cocoa/Cocoa.h>
+#import <AppKit/NSAccessibility.h>
#import <qaccessible.h>
@@ -55,4 +58,6 @@
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
-#endif
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QCOCOAACCESIBILITYELEMENT_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index fd5962cc34..050fb7ba0a 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -42,6 +42,8 @@
QT_USE_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
+
static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0)
{
Q_ASSERT(line == -1 || offset == -1);
@@ -582,3 +584,5 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
}
@end
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index cac50825af..caa8884661 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -221,12 +221,8 @@ QT_END_NAMESPACE
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
QWindow *topLevelWindow = topLevels.at(i);
- // Widgets have alreay received a CloseEvent from the QApplication
- // QCloseEvent handler. (see canQuit above). Prevent running the
- // CloseEvent logic twice, call close() directly.
- if (topLevelWindow->inherits("QWidgetWindow"))
- topLevelWindow->close();
- else
+ // Already closed windows will not have a platform window, skip those
+ if (topLevelWindow->handle())
QWindowSystemInterface::handleCloseEvent(topLevelWindow);
}
QWindowSystemInterface::flushWindowSystemEvents();
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 6a4f7ed8ee..ca92103826 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -44,6 +44,8 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QCocoaBackingStore::~QCocoaBackingStore()
{
+ if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()))
+ [cocoaWindow->m_qtView clearBackingStore:this];
}
QPaintDevice *QCocoaBackingStore::paintDevice()
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 93ee4e8624..9dc013ba4d 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -588,9 +588,6 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_filterSelected(int menuInd
emit filterSelected(menuIndex >= 0 && menuIndex < filters.size() ? filters.at(menuIndex) : QString());
}
-extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
-extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
-
void QCocoaFileDialogHelper::setDirectory(const QUrl &directory)
{
if (mDelegate)
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index cdeef1c6db..d43c8e5ee9 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -146,19 +146,25 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
QMacAutoReleasePool pool; // For the SG Canvas render thread
+ // create native context for the requested pixel format and share
NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(m_format));
m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
+ m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext];
- m_context = [NSOpenGLContext alloc];
- [m_context initWithFormat:pixelFormat shareContext:m_shareContext];
-
+ // retry without sharing on context creation failure.
if (!m_context && m_shareContext) {
- // try without shared context
m_shareContext = nil;
- [m_context initWithFormat:pixelFormat shareContext:nil];
+ m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+ if (m_context)
+ qWarning("QCocoaGLContext: Falling back to unshared context.");
}
+ // give up if we still did not get a native context
[pixelFormat release];
+ if (!m_context) {
+ qWarning("QCocoaGLContext: Failed to create context.");
+ return;
+ }
const GLint interval = format.swapInterval() >= 0 ? format.swapInterval() : 1;
[m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 5977d88e87..c7875af83e 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -121,7 +121,9 @@ public:
QCoreTextFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QCocoaNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
+#ifndef QT_NO_ACCESSIBILITY
QCocoaAccessibility *accessibility() const Q_DECL_OVERRIDE;
+#endif
QCocoaClipboard *clipboard() const Q_DECL_OVERRIDE;
QCocoaDrag *drag() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index c988bdc6a7..e469ec5c74 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -47,6 +47,7 @@
#include "qcocoamimetypes.h"
#include "qcocoaaccessibility.h"
+#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <QtCore/qcoreapplication.h>
@@ -286,9 +287,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
qWarning("Creating multiple Cocoa platform integrations is not supported");
mInstance = this;
- mInputContext.reset(QPlatformInputContextFactory::create());
- if (mInputContext.isNull())
- mInputContext.reset(new QCocoaInputContext());
+ QString icStr = QPlatformInputContextFactory::requested();
+ icStr.isNull() ? mInputContext.reset(new QCocoaInputContext)
+ : mInputContext.reset(QPlatformInputContextFactory::create(icStr));
initResources();
QMacAutoReleasePool pool;
@@ -501,14 +502,12 @@ QPlatformInputContext *QCocoaIntegration::inputContext() const
return mInputContext.data();
}
+#ifndef QT_NO_ACCESSIBILITY
QCocoaAccessibility *QCocoaIntegration::accessibility() const
{
-#ifndef QT_NO_ACCESSIBILITY
return mAccessibility.data();
-#else
- return 0;
-#endif
}
+#endif
QCocoaClipboard *QCocoaIntegration::clipboard() const
{
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 7e09116a37..a49a42378d 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -51,8 +51,7 @@ QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
- QImage m_backingStore;
- qreal m_pixelRatio;
+ QCocoaBackingStore* m_backingStore;
QPoint m_backingStoreOffset;
CGImageRef m_maskImage;
uchar *m_maskData;
@@ -86,6 +85,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
+- (void)clearBackingStore:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index edcbd16dca..4db55c1b73 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -134,7 +134,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
{
self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
if (self) {
- m_pixelRatio = 1.;
+ m_backingStore = 0;
m_maskImage = 0;
m_shouldInvalidateWindowShadow = false;
m_window = 0;
@@ -376,7 +376,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
if (!m_platformWindow->m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
else
- m_backingStore = QImage();
+ m_backingStore = 0;
}
}
@@ -481,12 +481,16 @@ QT_WARNING_POP
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
- m_backingStore = backingStore->toImage();
- m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio();
- m_backingStoreOffset = offset * m_pixelRatio;
- foreach (QRect rect, region.rects()) {
+ m_backingStore = backingStore;
+ m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
+ foreach (QRect rect, region.rects())
[self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
- }
+}
+
+- (void)clearBackingStore:(QCocoaBackingStore *)backingStore
+{
+ if (backingStore == m_backingStore)
+ m_backingStore = 0;
}
- (BOOL) hasMask
@@ -549,7 +553,7 @@ QT_WARNING_POP
if (m_platformWindow->m_drawContentBorderGradient)
NSDrawWindowBackground(dirtyRect);
- if (m_backingStore.isNull())
+ if (!m_backingStore)
return;
// Calculate source and target rects. The target rect is the dirtyRect:
@@ -557,10 +561,11 @@ QT_WARNING_POP
// The backing store source rect will be larger on retina displays.
// Scale dirtyRect by the device pixel ratio:
- CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio,
- dirtyRect.origin.y * m_pixelRatio,
- dirtyRect.size.width * m_pixelRatio,
- dirtyRect.size.height * m_pixelRatio);
+ const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio();
+ CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
+ dirtyRect.origin.y * devicePixelRatio,
+ dirtyRect.size.width * devicePixelRatio,
+ dirtyRect.size.height * devicePixelRatio);
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
@@ -586,7 +591,7 @@ QT_WARNING_POP
dirtyBackingRect.size.width,
dirtyBackingRect.size.height
);
- CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore);
+ CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage());
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
// Optimization: Copy frame buffer content instead of blending for
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index 93f0817aad..1f15da5b3b 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -44,6 +44,8 @@
#import <AppKit/NSAccessibility.h>
+#ifndef QT_NO_ACCESSIBILITY
+
@implementation QNSView (QNSViewAccessibility)
- (id)childAccessibleElement {
@@ -80,3 +82,5 @@
}
@end
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index aec5a5e179..f0946b9b64 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -40,6 +40,7 @@
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QWindow>
+#include <QtCore/QLoggingCategory>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontextfactory_p.h>
@@ -62,6 +63,10 @@
#include <QtPlatformHeaders/QEGLNativeContext>
+#ifndef QT_NO_LIBINPUT
+#include <QtPlatformSupport/private/qlibinputhandler_p.h>
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
@@ -124,13 +129,14 @@ void QEglFSIntegration::initialize()
m_vtHandler.reset(new QFbVtHandler);
- if (!m_disableInputHandlers)
- createInputHandlers();
-
if (qt_egl_device_integration()->usesDefaultScreen())
addScreen(new QEglFSScreen(display()));
else
qt_egl_device_integration()->screenInit();
+
+ // Input code may rely on the screens, so do it only after the screen init.
+ if (!m_disableInputHandlers)
+ createInputHandlers();
}
void QEglFSIntegration::destroy()
@@ -389,6 +395,13 @@ void QEglFSIntegration::loadKeymapStatic(const QString &filename)
void QEglFSIntegration::createInputHandlers()
{
+#ifndef QT_NO_LIBINPUT
+ if (!qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) {
+ new QLibInputHandler(QLatin1String("libinput"), QString());
+ return;
+ }
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index e2c61e1161..e4917593db 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -344,6 +344,46 @@
// -------------------------------------------------------------------------
+- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers
+{
+ QKeyEvent press(QEvent::KeyPress, key, modifiers);
+ QKeyEvent release(QEvent::KeyRelease, key, modifiers);
+ [self sendEventToFocusObject:press];
+ [self sendEventToFocusObject:release];
+}
+
+- (void)cut:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier];
+}
+
+- (void)copy:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier];
+}
+
+- (void)paste:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier];
+}
+
+- (void)selectAll:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier];
+}
+
+- (void)delete:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier];
+}
+
+// -------------------------------------------------------------------------
+
- (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties
{
// As documented, we should not report textWillChange/textDidChange unless the text
@@ -560,7 +600,7 @@
if (cursorPos != int(r.location + r.length) || cursorPos != anchorPos) {
attrs = QList<QInputMethodEvent::Attribute>();
- attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, cursorPos, (cursorPos - anchorPos), 0);
+ attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, qMin(cursorPos, anchorPos), qAbs(cursorPos - anchorPos), 0);
e = QInputMethodEvent(m_markedText, attrs);
[self sendEventToFocusObject:e];
}
@@ -678,10 +718,7 @@
return;
if ([text isEqualToString:@"\n"]) {
- QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
- QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier);
- [self sendEventToFocusObject:press];
- [self sendEventToFocusObject:release];
+ [self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
@@ -700,10 +737,7 @@
// Since we're posting im events directly to the focus object, we should do the
// same for key events. Otherwise they might end up in a different place or out
// of sync with im events.
- QKeyEvent press(QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier);
- QKeyEvent release(QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier);
- [self sendEventToFocusObject:press];
- [self sendEventToFocusObject:release];
+ [self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier];
}
@end
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 4ea5fc7de1..67b33ce235 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -143,7 +143,7 @@
if (uiWindow.screen != [UIScreen mainScreen] && self.subviews.count == 1) {
// Removing the last view of an external screen, go back to mirror mode
- uiWindow.screen = nil;
+ uiWindow.screen = [UIScreen mainScreen];
uiWindow.hidden = YES;
}
}
@@ -190,8 +190,9 @@
- (void)setBounds:(CGRect)newBounds
{
+ Q_UNUSED(newBounds);
CGRect transformedWindowBounds = [self convertRect:self.window.bounds fromView:self.window];
- [super setBounds:CGRectMake(0, 0, CGRectGetWidth(newBounds), CGRectGetHeight(transformedWindowBounds))];
+ [super setBounds:CGRectMake(0, 0, CGRectGetWidth(transformedWindowBounds), CGRectGetHeight(transformedWindowBounds))];
}
- (void)setCenter:(CGPoint)newCenter
diff --git a/src/plugins/platforms/kms/kms.json b/src/plugins/platforms/kms/kms.json
deleted file mode 100644
index be662226ae..0000000000
--- a/src/plugins/platforms/kms/kms.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "kms" ]
-}
diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
deleted file mode 100644
index baa8778153..0000000000
--- a/src/plugins/platforms/kms/kms.pro
+++ /dev/null
@@ -1,37 +0,0 @@
-TARGET = qkms
-
-PLUGIN_TYPE = platforms
-PLUGIN_CLASS_NAME = QKmsIntegrationPlugin
-!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
-load(qt_plugin)
-
-QT += core-private gui-private platformsupport-private
-qtHaveModule(opengl):QT += opengl-private
-
-DEFINES += MESA_EGL_NO_X11_HEADERS __GBM__
-
-CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase
-
-PKGCONFIG += libdrm libudev egl gbm glesv2
-
-SOURCES = main.cpp \
- qkmsintegration.cpp \
- qkmsscreen.cpp \
- qkmscontext.cpp \
- qkmswindow.cpp \
- qkmscursor.cpp \
- qkmsdevice.cpp \
- qkmsbackingstore.cpp \
- qkmsnativeinterface.cpp
-
-HEADERS = qkmsintegration.h \
- qkmsscreen.h \
- qkmscontext.h \
- qkmswindow.h \
- qkmscursor.h \
- qkmsdevice.h \
- qkmsbackingstore.h \
- qkmsnativeinterface.h
-
-OTHER_FILES += \
- kms.json
diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp
deleted file mode 100644
index 565ac7a7d4..0000000000
--- a/src/plugins/platforms/kms/main.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qpa/qplatformintegrationplugin.h>
-#include "qkmsintegration.h"
-
-QT_BEGIN_NAMESPACE
-
-class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "kms.json")
-public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
-};
-
-QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const QStringList& paramList)
-{
- Q_UNUSED(paramList);
- if (!system.compare(QLatin1String("kms"), Qt::CaseInsensitive))
- return new QKmsIntegration;
-
- return 0;
-}
-
-QT_END_NAMESPACE
-
-#include "main.moc"
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.cpp b/src/plugins/platforms/kms/qkmsbackingstore.cpp
deleted file mode 100644
index 6e5a3f9192..0000000000
--- a/src/plugins/platforms/kms/qkmsbackingstore.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsbackingstore.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOpenGLShaderProgram>
-#include <QtGui/QScreen>
-
-QT_BEGIN_NAMESPACE
-
-QKmsBackingStore::QKmsBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
- , m_context(new QOpenGLContext)
- , m_texture(0)
- , m_program(0)
- , m_initialized(false)
-{
- m_context->setFormat(window->requestedFormat());
- m_context->setScreen(window->screen());
- m_context->create();
-}
-
-QKmsBackingStore::~QKmsBackingStore()
-{
- delete m_program;
- if (m_texture)
- glDeleteTextures(1, &m_texture);
-
- delete m_context;
-}
-
-QPaintDevice *QKmsBackingStore::paintDevice()
-{
- return &m_image;
-}
-
-void QKmsBackingStore::beginPaint(const QRegion &rgn)
-{
- m_dirty |= rgn;
-}
-
-void QKmsBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
-{
- Q_UNUSED(region)
- Q_UNUSED(offset)
-
- m_context->makeCurrent(window);
-
- if (!m_initialized) {
- initializeOpenGLFunctions();
- m_initialized = true;
- }
-
- if (!m_program) {
- static const char *textureVertexProgram =
- "attribute highp vec2 vertexCoordEntry;\n"
- "attribute highp vec2 textureCoordEntry;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " textureCoord = textureCoordEntry;\n"
- " gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n"
- "}\n";
-
- static const char *textureFragmentProgram =
- "uniform sampler2D texture;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
- "}\n";
-
- m_program = new QOpenGLShaderProgram;
-
- m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
- m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
- m_program->bindAttributeLocation("vertexCoordEntry", 0);
- m_program->bindAttributeLocation("textureCoordEntry", 1);
- m_program->link();
- }
-
- m_program->bind();
-
- QRectF r = window->geometry();
- QRectF sr = window->screen()->geometry();
-
- GLfloat x1 = (r.left() / sr.width()) * 2 - 1;
- GLfloat x2 = (r.right() / sr.width()) * 2 - 1;
- GLfloat y1 = -1 * ((r.top() / sr.height()) * 2 - 1);
- GLfloat y2 = -1 * ((r.bottom() / sr.height()) * 2 - 1);
-
- const GLfloat vertexCoordinates[] = {
- x1, y1,
- x2, y1,
- x2, y2,
- x1, y2
- };
-
- const GLfloat textureCoordinates[] = {
- 0, 0,
- 1, 0,
- 1, 1,
- 0, 1
- };
-
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
-
- glBindTexture(GL_TEXTURE_2D, m_texture);
-
- if (!m_dirty.isNull()) {
- QRect imageRect = m_image.rect();
- QRegion fixed;
- Q_FOREACH (const QRect &rect, m_dirty.rects()) {
- // intersect with image rect to be sure
- QRect r = imageRect & rect;
- // if the rect is wide enough it's cheaper to just
- // extend it instead of doing an image copy
- if (r.width() >= imageRect.width() / 2) {
- r.setX(0);
- r.setWidth(imageRect.width());
- }
- fixed |= r;
- }
-
- Q_FOREACH (const QRect &rect, fixed.rects()) {
- // if the sub-rect is full-width we can pass the image data directly to
- // OpenGL instead of copying, since there's no gap between scanlines
- if (rect.width() == imageRect.width()) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(),
- rect.width(), rect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- m_image.constScanLine(rect.y()));
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(),
- rect.width(), rect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- m_image.copy(rect).constBits());
- }
- }
-
- m_dirty = QRegion();
- }
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- m_program->release();
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- m_context->swapBuffers(window);
-
- m_context->doneCurrent();
-}
-
-void QKmsBackingStore::resize(const QSize &size, const QRegion &staticContents)
-{
- Q_UNUSED(staticContents)
-
- m_image = QImage(size, QImage::Format_RGB32);
-
- m_context->makeCurrent(window());
-
- if (!m_initialized) {
- initializeOpenGLFunctions();
- m_initialized = true;
- }
-
- if (m_texture)
- glDeleteTextures(1, &m_texture);
-
- glGenTextures(1, &m_texture);
- glBindTexture(GL_TEXTURE_2D, m_texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(),
- 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h
deleted file mode 100644
index a34b10d3d9..0000000000
--- a/src/plugins/platforms/kms/qkmsbackingstore.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBACKINGSTORE_KMS_H
-#define QBACKINGSTORE_KMS_H
-
-#include <qpa/qplatformbackingstore.h>
-#include <QtGui/QOpenGLFunctions>
-#include <QImage>
-
-QT_BEGIN_NAMESPACE
-
-class QOpenGLContext;
-class QOpenGLShaderProgram;
-
-class QKmsBackingStore : public QPlatformBackingStore, public QOpenGLFunctions
-{
-public:
- QKmsBackingStore(QWindow *window);
- ~QKmsBackingStore();
-
- QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
-
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
-
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
- void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
-
- QImage toImage() const Q_DECL_OVERRIDE { return m_image; }
-
-private:
- QOpenGLContext *m_context;
- QImage m_image;
- uint m_texture;
- QOpenGLShaderProgram *m_program;
- QRegion m_dirty;
- bool m_initialized;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp
deleted file mode 100644
index e00835fbac..0000000000
--- a/src/plugins/platforms/kms/qkmscontext.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-#include "qkmscontext.h"
-#include "qkmswindow.h"
-#include "qkmsintegration.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device)
- : m_device(device)
-{
- EGLDisplay display = m_device->eglDisplay();
- EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format()));
- m_format = q_glFormatFromConfig(display, config);
-
- //Initialize EGLContext
- static EGLint contextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, context->format().majorVersion(),
- EGL_NONE
- };
-
- eglBindAPI(EGL_OPENGL_ES_API);
-
- EGLContext share = EGL_NO_CONTEXT;
- if (context->shareContext())
- share = static_cast<QKmsContext *>(context->shareContext()->handle())->eglContext();
-
- m_eglContext = eglCreateContext(display, config, share, contextAttribs);
- if (m_eglContext == EGL_NO_CONTEXT) {
- qWarning("QKmsContext::QKmsContext(): eglError: %x, this: %p",
- eglGetError(), this);
- m_eglContext = 0;
- }
-}
-
-bool QKmsContext::isValid() const
-{
- return m_eglContext != EGL_NO_CONTEXT;
-}
-
-bool QKmsContext::makeCurrent(QPlatformSurface *surface)
-{
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- EGLDisplay display = m_device->eglDisplay();
- EGLSurface eglSurface;
-
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
- QKmsScreen *screen = static_cast<QKmsScreen *>(QPlatformScreen::platformScreenForWindow(window->window()));
- eglSurface = screen->eglSurface();
- screen->waitForPageFlipComplete();
- } else {
- eglSurface = static_cast<QKmsOffscreenWindow *>(surface)->surface();
- }
-
- bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext);
- if (!ok)
- qWarning("QKmsContext::makeCurrent(): eglError: %x, this: %p",
- eglGetError(), this);
-
- return true;
-}
-
-void QKmsContext::doneCurrent()
-{
- bool ok = eglMakeCurrent(m_device->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- if (!ok)
- qWarning("QKmsContext::doneCurrent(): eglError: %x, this: %p",
- eglGetError(), this);
-
-}
-
-void QKmsContext::swapBuffers(QPlatformSurface *surface)
-{
- //Cast context to a window surface and get the screen the context
- //is on and call swapBuffers on that screen.
- QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
- QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
- screen->swapBuffers();
-}
-
-void (*QKmsContext::getProcAddress(const QByteArray &procName)) ()
-{
- return eglGetProcAddress(procName.data());
-}
-
-
-EGLContext QKmsContext::eglContext() const
-{
- return m_eglContext;
-}
-
-QSurfaceFormat QKmsContext::format() const
-{
- return m_format;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h
deleted file mode 100644
index 59cf9b1e34..0000000000
--- a/src/plugins/platforms/kms/qkmscontext.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSCONTEXT_H
-#define QKMSCONTEXT_H
-
-#include <qpa/qplatformopenglcontext.h>
-
-#define EGL_EGLEXT_PROTOTYPES 1
-#include <EGL/egl.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsDevice;
-
-class QKmsContext : public QPlatformOpenGLContext
-{
-public:
- QKmsContext(QOpenGLContext *context, QKmsDevice *device);
-
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE;
-
- bool isValid() const Q_DECL_OVERRIDE;
-
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
-
- EGLContext eglContext() const;
-
-private:
- EGLContext m_eglContext;
- QSurfaceFormat m_format;
-
- QKmsDevice *m_device;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSCONTEXT_H
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
deleted file mode 100644
index 44212cd3c8..0000000000
--- a/src/plugins/platforms/kms/qkmscursor.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-//#include <QDebug>
-#include "qkmscursor.h"
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef DRM_CAP_CURSOR_WIDTH
-#define DRM_CAP_CURSOR_WIDTH 0x8
-#endif
-
-#ifndef DRM_CAP_CURSOR_HEIGHT
-#define DRM_CAP_CURSOR_HEIGHT 0x9
-#endif
-
-QKmsCursor::QKmsCursor(QKmsScreen *screen)
- : m_screen(screen),
- m_graphicsBufferManager(screen->device()->gbmDevice()),
- m_cursorImage(new QPlatformCursorImage(0, 0, 0, 0, 0, 0)),
- m_moved(false),
- m_cursorSize(64, 64)
-{
- uint64_t value = 0;
- if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &value))
- m_cursorSize.setWidth(value);
- if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &value))
- m_cursorSize.setHeight(value);
-
- m_cursorBufferObject = gbm_bo_create(m_graphicsBufferManager, m_cursorSize.width(), m_cursorSize.height(),
- GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
-}
-
-QKmsCursor::~QKmsCursor()
-{
- drmModeSetCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0, 0);
- gbm_bo_destroy(m_cursorBufferObject);
-}
-
-void QKmsCursor::pointerEvent(const QMouseEvent &event)
-{
- m_moved = true;
- int status = drmModeMoveCursor(m_screen->device()->fd(),
- m_screen->crtcId(),
- event.globalX(),
- event.globalY());
- if (status) {
- qWarning("failed to move cursor: %d", status);
- }
-}
-
-void QKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
-{
- Q_UNUSED(window)
-
- if (!m_moved)
- drmModeMoveCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0);
-
- const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
- if (newShape != Qt::BitmapCursor) {
- m_cursorImage->set(newShape);
- } else {
- m_cursorImage->set(windowCursor->pixmap().toImage(),
- windowCursor->hotSpot().x(),
- windowCursor->hotSpot().y());
- }
-
- if (m_cursorImage->image()->width() > m_cursorSize.width() || m_cursorImage->image()->width() > m_cursorSize.height())
- qWarning("cursor larger than %dx%d, cursor truncated", m_cursorSize.width(), m_cursorSize.height());
-
- QImage cursorImage = m_cursorImage->image()->convertToFormat(QImage::Format_ARGB32)
- .copy(0, 0, m_cursorSize.width(), m_cursorSize.height());
- gbm_bo_write(m_cursorBufferObject, cursorImage.constBits(), cursorImage.byteCount());
-
- quint32 handle = gbm_bo_get_handle(m_cursorBufferObject).u32;
- int status = drmModeSetCursor(m_screen->device()->fd(),
- m_screen->crtcId(), handle,
- m_cursorSize.width(), m_cursorSize.height());
-
- if (status) {
- qWarning("failed to set cursor: %d", status);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h
deleted file mode 100644
index 9aadf407c0..0000000000
--- a/src/plugins/platforms/kms/qkmscursor.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSCURSOR_H
-#define QKMSCURSOR_H
-
-#include <qpa/qplatformcursor.h>
-
-struct gbm_device;
-struct gbm_bo;
-
-QT_BEGIN_NAMESPACE
-
-class QKmsScreen;
-
-class QKmsCursor : public QPlatformCursor
-{
-public:
- QKmsCursor(QKmsScreen *screen);
- ~QKmsCursor();
-
- void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
- void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE;
-
-private:
- QKmsScreen *m_screen;
- gbm_device *m_graphicsBufferManager;
- gbm_bo *m_cursorBufferObject;
- QPlatformCursorImage *m_cursorImage;
- bool m_moved;
- QSize m_cursorSize;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSCURSOR_H
diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp
deleted file mode 100644
index 74fa59c16a..0000000000
--- a/src/plugins/platforms/kms/qkmsdevice.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-//#include <QDebug>
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-
-#include "qkmsintegration.h"
-
-#include <QtCore/QSocketNotifier>
-#include <QtCore/private/qcore_unix_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsDevice::QKmsDevice(const QString &path, QKmsIntegration *parent) :
- QObject(0), m_integration(parent)
-{
- m_fd = QT_OPEN(path.toLatin1().constData(), O_RDWR);
- if (m_fd < 0) {
- qWarning("Could not open %s.", path.toLatin1().constData());
- qFatal("No DRM display device");
- }
-
- m_graphicsBufferManager = gbm_create_device(m_fd);
- m_eglDisplay = eglGetDisplay(m_graphicsBufferManager);
-
- if (m_eglDisplay == EGL_NO_DISPLAY) {
- qWarning("Could not open EGL display");
- qFatal("EGL error");
- }
-
- EGLint major;
- EGLint minor;
- if (!eglInitialize(m_eglDisplay, &major, &minor)) {
- qWarning("Could not initialize EGL display");
- qFatal("EGL error");
- }
-
- createScreens();
-
-// QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
-// connect(notifier, SIGNAL(activated(int)), this, SLOT(handlePageFlipCompleted()));
-}
-
-QKmsDevice::~QKmsDevice()
-{
-}
-
-void QKmsDevice::createScreens()
-{
- drmModeRes *resources = drmModeGetResources(m_fd);
- if (!resources)
- qFatal("drmModeGetResources failed");
-
- //Iterate connectors and create screens on each one active
- for (int i = 0; i < resources->count_connectors; i++) {
- drmModeConnector *connector = 0;
- connector = drmModeGetConnector(m_fd, resources->connectors[i]);
- if (connector && connector->connection == DRM_MODE_CONNECTED) {
- m_integration->addScreen(new QKmsScreen(this, resources, connector));
- }
- drmModeFreeConnector(connector);
- }
- drmModeFreeResources(resources);
-}
-
-void QKmsDevice::handlePageFlipCompleted()
-{
- drmEventContext eventContext;
-
- memset(&eventContext, 0, sizeof eventContext);
- eventContext.version = DRM_EVENT_CONTEXT_VERSION;
- eventContext.page_flip_handler = QKmsDevice::pageFlipHandler;
- drmHandleEvent(m_fd, &eventContext);
-
-}
-
-void QKmsDevice::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
-{
- Q_UNUSED(fd)
- Q_UNUSED(frame)
- Q_UNUSED(sec)
- Q_UNUSED(usec)
-
- QKmsScreen *screen = static_cast<QKmsScreen *>(data);
- screen->handlePageFlipped();
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsdevice.h b/src/plugins/platforms/kms/qkmsdevice.h
deleted file mode 100644
index d5e33cb8c7..0000000000
--- a/src/plugins/platforms/kms/qkmsdevice.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSDEVICE_H
-#define QKMSDEVICE_H
-
-#include <stddef.h>
-
-extern "C" {
-#include <gbm.h>
-}
-#include <EGL/egl.h>
-
-#include <QObject>
-
-struct gbm_device;
-
-QT_BEGIN_NAMESPACE
-
-class QKmsIntegration;
-
-class QKmsDevice : public QObject
-{
- Q_OBJECT
-public:
- explicit QKmsDevice(const QString &path, QKmsIntegration *parent);
- ~QKmsDevice();
-
- EGLDisplay eglDisplay() { return m_eglDisplay; }
- gbm_device *gbmDevice() { return m_graphicsBufferManager; }
- int fd() const { return m_fd; }
-
- static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *data);
-
-public slots:
- void handlePageFlipCompleted();
-private:
- void createScreens();
-
- QKmsIntegration *m_integration;
-
- EGLDisplay m_eglDisplay;
- EGLContext m_eglContext;
- gbm_device *m_graphicsBufferManager;
- int m_fd;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSDEVICE_H
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
deleted file mode 100644
index f48c868ae5..0000000000
--- a/src/plugins/platforms/kms/qkmsintegration.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsintegration.h"
-#include "qkmsdevice.h"
-#include "qkmsscreen.h"
-#include "qkmswindow.h"
-#include "qkmsbackingstore.h"
-#include "qkmscontext.h"
-#include "qkmsnativeinterface.h"
-
-#if !defined(QT_NO_EVDEV)
-#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
-#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
-#include <QtPlatformSupport/private/qevdevtouch_p.h>
-#endif
-
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
-#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtPlatformSupport/private/qfbvthandler_p.h>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QScreen>
-#include <QtGui/QOffscreenSurface>
-#include <qpa/qplatformoffscreensurface.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsIntegration::QKmsIntegration()
- : QPlatformIntegration(),
- m_fontDatabase(new QGenericUnixFontDatabase()),
- m_nativeInterface(new QKmsNativeInterface),
- m_vtHandler(0),
- m_deviceDiscovery(0)
-{
-}
-
-QKmsIntegration::~QKmsIntegration()
-{
- delete m_deviceDiscovery;
- foreach (QKmsDevice *device, m_devices) {
- delete device;
- }
- foreach (QPlatformScreen *screen, m_screens) {
- destroyScreen(screen);
- }
- delete m_fontDatabase;
- delete m_vtHandler;
-}
-
-void QKmsIntegration::initialize()
-{
- qputenv("EGL_PLATFORM", "drm");
- m_vtHandler = new QFbVtHandler;
-
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_DRM | QDeviceDiscovery::Device_DRM_PrimaryGPU, 0);
- if (m_deviceDiscovery) {
- QStringList devices = m_deviceDiscovery->scanConnectedDevices();
- foreach (const QString &device, devices)
- addDevice(device);
-
- connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString)));
- connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString)));
- }
-
-#if !defined(QT_NO_EVDEV)
- new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
- new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
- new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
-#endif
-}
-
-void QKmsIntegration::addDevice(const QString &deviceNode)
-{
- m_devices.append(new QKmsDevice(deviceNode, this));
-}
-
-void QKmsIntegration::removeDevice(const QString &deviceNode)
-{
- // TODO: support hot-plugging some day?
- Q_UNUSED(deviceNode);
-}
-
-bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
-{
- switch (cap) {
- case ThreadedPixmaps: return true;
- case OpenGL: return true;
- case ThreadedOpenGL: return false;
- case RasterGLSurface: return true;
- default: return QPlatformIntegration::hasCapability(cap);
- }
-}
-
-QPlatformOpenGLContext *QKmsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(context->screen()->handle());
- return new QKmsContext(context, screen->device());
-}
-
-QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const
-{
- QKmsWindow *w = new QKmsWindow(window);
- w->requestActivateWindow();
- return w;
-}
-
-QPlatformBackingStore *QKmsIntegration::createPlatformBackingStore(QWindow *window) const
-{
- return new QKmsBackingStore(window);
-}
-
-// Neither a pbuffer nor a hidden QWindow is suitable. Just use an additional, small gbm surface.
-QKmsOffscreenWindow::QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
- : QPlatformOffscreenSurface(offscreenSurface)
- , m_format(format)
- , m_display(display)
- , m_surface(EGL_NO_SURFACE)
- , m_window(0)
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(offscreenSurface->screen()->handle());
- m_window = gbm_surface_create(screen->device()->gbmDevice(),
- 10, 10,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_RENDERING);
- if (!m_window) {
- qWarning("QKmsOffscreenWindow: Failed to create native window");
- return;
- }
-
- EGLConfig config = q_configFromGLFormat(m_display, m_format);
- m_surface = eglCreateWindowSurface(m_display, config, m_window, 0);
- if (m_surface != EGL_NO_SURFACE)
- m_format = q_glFormatFromConfig(m_display, config);
-}
-
-QKmsOffscreenWindow::~QKmsOffscreenWindow()
-{
- if (m_surface != EGL_NO_SURFACE)
- eglDestroySurface(m_display, m_surface);
- if (m_window)
- gbm_surface_destroy((gbm_surface *) m_window);
-}
-
-QPlatformOffscreenSurface *QKmsIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(surface->screen()->handle());
- return new QKmsOffscreenWindow(screen->device()->eglDisplay(), QKmsScreen::tweakFormat(surface->format()), surface);
-}
-
-QPlatformFontDatabase *QKmsIntegration::fontDatabase() const
-{
- return m_fontDatabase;
-}
-
-void QKmsIntegration::addScreen(QKmsScreen *screen)
-{
- m_screens.append(screen);
- screenAdded(screen);
-}
-
-QAbstractEventDispatcher *QKmsIntegration::createEventDispatcher() const
-{
- return createUnixEventDispatcher();
-}
-
-QPlatformNativeInterface *QKmsIntegration::nativeInterface() const
-{
- return m_nativeInterface;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h
deleted file mode 100644
index bcf9ac7296..0000000000
--- a/src/plugins/platforms/kms/qkmsintegration.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPLATFORMINTEGRATION_KMS_H
-#define QPLATFORMINTEGRATION_KMS_H
-
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qplatformoffscreensurface.h>
-#include <QtPlatformSupport/private/qdevicediscovery_p.h>
-#include <EGL/egl.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsScreen;
-class QKmsDevice;
-class QFbVtHandler;
-
-class QKmsOffscreenWindow : public QPlatformOffscreenSurface
-{
-public:
- QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface);
- ~QKmsOffscreenWindow();
-
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; }
-
- EGLSurface surface() const { return m_surface; }
-
-private:
- QSurfaceFormat m_format;
- EGLDisplay m_display;
- EGLSurface m_surface;
- EGLNativeWindowType m_window;
-};
-
-class QKmsIntegration : public QObject, public QPlatformIntegration
-{
- Q_OBJECT
-
-public:
- QKmsIntegration();
- ~QKmsIntegration();
-
- void initialize() Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
-
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
-
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
-
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
-
- void addScreen(QKmsScreen *screen);
- QObject *createDevice(const char *);
-
-private slots:
- void addDevice(const QString &deviceNode);
- void removeDevice(const QString &deviceNode);
-
-private:
- QStringList findDrmDevices();
-
- QList<QPlatformScreen *> m_screens;
- QList<QKmsDevice *> m_devices;
- QPlatformFontDatabase *m_fontDatabase;
- QPlatformNativeInterface *m_nativeInterface;
- QFbVtHandler *m_vtHandler;
- QDeviceDiscovery *m_deviceDiscovery;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp
deleted file mode 100644
index 1538a7f8c3..0000000000
--- a/src/plugins/platforms/kms/qkmsnativeinterface.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qguiapplication_p.h>
-#include "qkmsnativeinterface.h"
-#include "qkmsdevice.h"
-
-#include "qscreen.h"
-#include "qkmscontext.h"
-#include <QOpenGLContext>
-
-class QKmsResourceMap : public QMap<QByteArray, QKmsNativeInterface::ResourceType>
-{
-public:
- QKmsResourceMap()
- :QMap<QByteArray, QKmsNativeInterface::ResourceType>()
- {
- insert("egldisplay", QKmsNativeInterface::EglDisplay);
- insert("eglcontext", QKmsNativeInterface::EglContext);
- }
-};
-
-Q_GLOBAL_STATIC(QKmsResourceMap, qKmsResourceMap)
-
-void *QKmsNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
-{
- QByteArray lowerCaseResource = resourceString.toLower();
- ResourceType resource = qKmsResourceMap()->value(lowerCaseResource);
- void *result = 0;
- switch (resource) {
- case EglDisplay:
- result = eglDisplay();
- break;
- default:
- result = 0;
- }
- return result;
-
-}
-void *QKmsNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
-{
- QByteArray lowerCaseResource = resourceString.toLower();
- ResourceType resource = qKmsResourceMap()->value(lowerCaseResource);
- void *result = 0;
- switch (resource) {
- case EglDisplay:
- result = eglDisplayForWindow(window);
- break;
- case EglContext:
- result = eglContextForWindow(window);
- break;
- default:
- result = 0;
- }
- return result;
-}
-
-QPlatformNativeInterface::NativeResourceForContextFunction QKmsNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
-{
- QByteArray lowerCaseResource = resource.toLower();
- if (lowerCaseResource == "get_egl_context") {
- return eglContextForContext;
- }
- return 0;
-}
-
-void *QKmsNativeInterface::eglDisplay()
-{
- //QKmsIntegration *integration = static_cast<QKmsIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QKmsScreen *screen = static_cast<QKmsScreen *>(QGuiApplication::primaryScreen()->handle());
- if (!screen || !screen->device())
- return 0;
- return screen->device()->eglDisplay();
-}
-
-void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window)
-{
- QKmsScreen *screen = qPlatformScreenForWindow(window);
- if (!screen)
- return 0;
- QKmsDevice *device = screen->device();
- if (!device)
- return 0;
- return device->eglDisplay();
-}
-
-void *QKmsNativeInterface::eglContextForWindow(QWindow *)
-{
- return 0;
-}
-
-QKmsScreen *QKmsNativeInterface::qPlatformScreenForWindow(QWindow *window)
-{
- QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
- return static_cast<QKmsScreen *>(screen->handle());
-}
-
-void *QKmsNativeInterface::eglContextForContext(QOpenGLContext *context)
-{
- Q_ASSERT(context);
-
- QKmsContext *eglPlatformContext = static_cast<QKmsContext *>(context->handle());
-
- return eglPlatformContext->eglContext();
-}
diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.h b/src/plugins/platforms/kms/qkmsnativeinterface.h
deleted file mode 100644
index 56879d0a3a..0000000000
--- a/src/plugins/platforms/kms/qkmsnativeinterface.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSNATIVEINTERFACE_H
-#define QKMSNATIVEINTERFACE_H
-
-#include "qkmsscreen.h"
-
-#include <qpa/qplatformnativeinterface.h>
-
-class QKmsNativeInterface : public QPlatformNativeInterface
-{
-public:
- enum ResourceType {
- EglDisplay,
- EglContext
- };
-
- void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
-
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
-
- void *eglDisplay();
- void *eglDisplayForWindow(QWindow *window);
- void *eglContextForWindow(QWindow *window);
- static void *eglContextForContext(QOpenGLContext *context);
-
-private:
- static QKmsScreen *qPlatformScreenForWindow(QWindow *window);
-};
-
-
-#endif // QKMSNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
deleted file mode 100644
index 6392b99cd5..0000000000
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsscreen.h"
-#include "qkmscursor.h"
-#include "qkmsdevice.h"
-#include "qkmscontext.h"
-
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-#include <QCoreApplication>
-#include <QtDebug>
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.kms.screen")
-
-//Fallback mode (taken from Wayland DRM demo compositor)
-static drmModeModeInfo builtin_1024x768 = {
- 63500, //clock
- 1024, 1072, 1176, 1328, 0,
- 768, 771, 775, 798, 0,
- 59920,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
- 0,
- "1024x768"
-};
-
-QKmsScreen::QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector)
- : m_device(device),
- m_current_bo(0),
- m_next_bo(0),
- m_connectorId(connector->connector_id),
- m_depth(32),
- m_format(QImage::Format_Invalid),
- m_eglWindowSurface(EGL_NO_SURFACE),
- m_modeSet(false)
-{
- m_cursor = new QKmsCursor(this);
- initializeScreenMode(resources, connector);
-}
-
-QKmsScreen::~QKmsScreen()
-{
- delete m_cursor;
- drmModeSetCrtc(m_device->fd(), m_oldCrtc->crtc_id, m_oldCrtc->buffer_id,
- m_oldCrtc->x, m_oldCrtc->y,
- &m_connectorId, 1, &m_oldCrtc->mode);
- drmModeFreeCrtc(m_oldCrtc);
- if (m_eglWindowSurface != EGL_NO_SURFACE)
- eglDestroySurface(m_device->eglDisplay(), m_eglWindowSurface);
- gbm_surface_destroy(m_gbmSurface);
-}
-
-QRect QKmsScreen::geometry() const
-{
- return m_geometry;
-}
-
-int QKmsScreen::depth() const
-{
- return m_depth;
-}
-
-QImage::Format QKmsScreen::format() const
-{
- return m_format;
-}
-
-QSizeF QKmsScreen::physicalSize() const
-{
- return m_physicalSize;
-}
-
-QPlatformCursor *QKmsScreen::cursor() const
-{
- return m_cursor;
-}
-
-void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector)
-{
- //Determine optimal mode for screen
- drmModeModeInfo *mode = 0;
- for (int i = 0; i < connector->count_modes; ++i) {
- if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
- mode = &connector->modes[i];
- break;
- }
- }
- if (!mode) {
- if (connector->count_modes > 0)
- mode = &connector->modes[0];
- else
- mode = &builtin_1024x768;
- }
-
- drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
- if (encoder == 0)
- qFatal("No encoder for connector.");
-
- int i;
- for (i = 0; i < resources->count_crtcs; i++) {
- if (encoder->possible_crtcs & (1 << i))
- break;
- }
- if (i == resources->count_crtcs)
- qFatal("No usable crtc for encoder.");
-
- m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id);
-
- m_crtcId = resources->crtcs[i];
- m_mode = *mode;
- m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
- qCDebug(lcQpaScreen) << "kms initialized with geometry" << m_geometry;
- m_depth = 32;
- m_format = QImage::Format_RGB32;
- m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);
-
- m_gbmSurface = gbm_surface_create(m_device->gbmDevice(),
- m_mode.hdisplay, m_mode.vdisplay,
- GBM_BO_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-
- qCDebug(lcQpaScreen) << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
- //Cleanup
- drmModeFreeEncoder(encoder);
-}
-
-QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format)
-{
- QSurfaceFormat fmt = format;
- fmt.setRedBufferSize(8);
- fmt.setGreenBufferSize(8);
- fmt.setBlueBufferSize(8);
- if (fmt.alphaBufferSize() != -1)
- fmt.setAlphaBufferSize(8);
- return fmt;
-}
-
-void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format)
-{
- EGLDisplay display = m_device->eglDisplay();
- EGLConfig config = q_configFromGLFormat(display, tweakFormat(format));
-
- m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL);
- qCDebug(lcQpaScreen) << "created window surface";
- m_surfaceFormat = q_glFormatFromConfig(display, config);
-}
-
-void QKmsScreen::swapBuffers()
-{
- eglSwapBuffers(m_device->eglDisplay(), m_eglWindowSurface);
-
- m_next_bo = gbm_surface_lock_front_buffer(m_gbmSurface);
- if (!m_next_bo)
- qFatal("kms: Failed to lock front buffer");
-
- performPageFlip();
-}
-
-void QKmsScreen::performPageFlip()
-{
- if (!m_next_bo)
- return;
-
- uint32_t width = gbm_bo_get_width(m_next_bo);
- uint32_t height = gbm_bo_get_height(m_next_bo);
- uint32_t stride = gbm_bo_get_stride(m_next_bo);
- uint32_t handle = gbm_bo_get_handle(m_next_bo).u32;
-
- uint32_t fb_id;
- int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32,
- stride, handle, &fb_id);
- if (ret) {
- qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d",
- m_device->fd(), width, height, stride, handle, ret);
- }
-
- if (!m_modeSet) {
- //Set the Mode of the screen.
- int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id,
- 0, 0, &m_connectorId, 1, &m_mode);
- if (ret)
- qFatal("failed to set mode");
- m_modeSet = true;
-
- // Initialize cursor
-
- static int hideCursor = qEnvironmentVariableIntValue("QT_QPA_KMS_HIDECURSOR");
- if (!hideCursor) {
- QCursor cursor(Qt::ArrowCursor);
- m_cursor->changeCursor(&cursor, 0);
- }
- }
-
- int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
- fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, this);
- if (pageFlipStatus)
- {
- qWarning("Pageflip status: %d", pageFlipStatus);
- gbm_surface_release_buffer(m_gbmSurface, m_next_bo);
- m_next_bo = 0;
- }
-}
-
-void QKmsScreen::handlePageFlipped()
-{
- if (m_current_bo)
- gbm_surface_release_buffer(m_gbmSurface, m_current_bo);
-
- m_current_bo = m_next_bo;
- m_next_bo = 0;
-}
-
-QKmsDevice * QKmsScreen::device() const
-{
- return m_device;
-}
-
-void QKmsScreen::waitForPageFlipComplete()
-{
- while (m_next_bo) {
-#if 0
- //Check manually if there is something to be read on the device
- //as there are senarios where the signal is not received (starvation)
- fd_set fdSet;
- timeval timeValue;
- int returnValue;
-
- FD_ZERO(&fdSet);
- FD_SET(m_device->fd(), &fdSet);
- timeValue.tv_sec = 0;
- timeValue.tv_usec = 1000;
-
- returnValue = select(1, &fdSet, 0, 0, &timeValue);
- printf("select returns %d\n", returnValue);
-#endif
-
- m_device->handlePageFlipCompleted();
- }
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
deleted file mode 100644
index c52d0211b3..0000000000
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSSCREEN_H
-#define QKMSSCREEN_H
-
-#include <stddef.h>
-
-#define EGL_EGLEXT_PROTOTYPES 1
-#define GL_GLEXT_PROTOTYPES 1
-
-extern "C" {
-#include <gbm.h>
-#include <xf86drmMode.h>
-#include <xf86drm.h>
-}
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <QtGui/qopengl.h>
-#include <QtGui/qsurfaceformat.h>
-#include <QtCore/qloggingcategory.h>
-
-#include <qpa/qplatformscreen.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
-
-class QKmsCursor;
-class QKmsDevice;
-class QKmsContext;
-
-class QKmsScreen : public QPlatformScreen
-{
-public:
- QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector);
- ~QKmsScreen();
-
- QRect geometry() const Q_DECL_OVERRIDE;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
- QSizeF physicalSize() const Q_DECL_OVERRIDE;
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
-
- quint32 crtcId() const { return m_crtcId; }
- QKmsDevice *device() const;
-
- void initializeWithFormat(const QSurfaceFormat &format);
-
- //Called by context for each screen
- void swapBuffers();
- void handlePageFlipped();
-
- EGLSurface eglSurface() const { return m_eglWindowSurface; }
-
- void waitForPageFlipComplete();
-
- static QSurfaceFormat tweakFormat(const QSurfaceFormat &format);
-
- QSurfaceFormat surfaceFormat() const { return m_surfaceFormat; }
-
-private:
- void performPageFlip();
- void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector);
-
- QKmsDevice *m_device;
- gbm_bo *m_current_bo;
- gbm_bo *m_next_bo;
- quint32 m_connectorId;
-
- quint32 m_crtcId;
- drmModeModeInfo m_mode;
- QRect m_geometry;
- QSizeF m_physicalSize;
- int m_depth;
- QImage::Format m_format;
-
- drmModeCrtcPtr m_oldCrtc;
-
- QKmsCursor *m_cursor;
-
- gbm_surface *m_gbmSurface;
- EGLSurface m_eglWindowSurface;
-
- bool m_modeSet;
- QSurfaceFormat m_surfaceFormat;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSSCREEN_H
diff --git a/src/plugins/platforms/kms/qkmswindow.cpp b/src/plugins/platforms/kms/qkmswindow.cpp
deleted file mode 100644
index 3b01dfedca..0000000000
--- a/src/plugins/platforms/kms/qkmswindow.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmswindow.h"
-#include "qkmsscreen.h"
-
-#include <qpa/qwindowsysteminterface.h>
-#include <qpa/qplatformwindow_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsWindow::QKmsWindow(QWindow *window)
- : QPlatformWindow(window)
-{
- Q_D(QPlatformWindow);
- m_screen = QPlatformScreen::platformScreenForWindow(window);
- static_cast<QKmsScreen *>(m_screen)->initializeWithFormat(window->requestedFormat());
- setGeometry(d->rect); // rect is set to window->geometry() in base ctor
-}
-
-void QKmsWindow::setGeometry(const QRect &rect)
-{
- // All windows must be fullscreen
- QRect fullscreenRect = m_screen->availableGeometry();
- if (rect != fullscreenRect)
- QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
-
- QPlatformWindow::setGeometry(fullscreenRect);
-}
-
-QSurfaceFormat QKmsWindow::format() const
-{
- return static_cast<QKmsScreen *>(m_screen)->surfaceFormat();
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmswindow.h b/src/plugins/platforms/kms/qkmswindow.h
deleted file mode 100644
index aec6d55b5d..0000000000
--- a/src/plugins/platforms/kms/qkmswindow.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** 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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSWINDOW_H
-#define QKMSWINDOW_H
-
-#include <qpa/qplatformwindow.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsWindow : public QPlatformWindow
-{
- Q_DECLARE_PRIVATE(QPlatformWindow)
-
-public:
- QKmsWindow(QWindow *window);
-
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
-
-private:
- QPlatformScreen *m_screen;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSWINDOW_H
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index ccf86dafb2..8c8c8a15ea 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -46,6 +46,10 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
+#ifndef QT_NO_LIBINPUT
+#include <QtPlatformSupport/private/qlibinputhandler_p.h>
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
@@ -130,6 +134,13 @@ QPlatformServices *QLinuxFbIntegration::services() const
void QLinuxFbIntegration::createInputHandlers()
{
+#ifndef QT_NO_LIBINPUT
+ if (!qEnvironmentVariableIntValue("QT_QPA_FB_NO_LIBINPUT")) {
+ new QLibInputHandler(QLatin1String("libinput"), QString());
+ return;
+ }
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this);
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index 925427ac30..97459a4d97 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -109,8 +109,11 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const
{
IDataObject * pDataObj = 0;
- if (OleGetClipboard(&pDataObj) == S_OK)
+ if (OleGetClipboard(&pDataObj) == S_OK) {
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj;
return pDataObj;
+ }
return 0;
}
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 717adcc47f..4ec34c05bd 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -33,6 +33,7 @@
****************************************************************************/
#include "qwindowscontext.h"
+#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
#include "qwindowsguieventdispatcher.h"
@@ -907,16 +908,30 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
}
+ if (et & QtWindows::InputMethodEventFlag) {
+ QWindowsInputContext *windowsInputContext =
+ qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+ // Disable IME assuming this is a special implementation hooking into keyboard input.
+ // "Real" IME implementations should use a native event filter intercepting IME events.
+ if (!windowsInputContext) {
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, false);
+ return false;
+ }
+ switch (et) {
+ case QtWindows::InputMethodStartCompositionEvent:
+ return windowsInputContext->startComposition(hwnd);
+ case QtWindows::InputMethodCompositionEvent:
+ return windowsInputContext->composition(hwnd, lParam);
+ case QtWindows::InputMethodEndCompositionEvent:
+ return windowsInputContext->endComposition(hwnd);
+ case QtWindows::InputMethodRequest:
+ return windowsInputContext->handleIME_Request(wParam, lParam, result);
+ default:
+ break;
+ }
+ } // InputMethodEventFlag
switch (et) {
- case QtWindows::InputMethodStartCompositionEvent:
- return QWindowsInputContext::instance()->startComposition(hwnd);
- case QtWindows::InputMethodCompositionEvent:
- return QWindowsInputContext::instance()->composition(hwnd, lParam);
- case QtWindows::InputMethodEndCompositionEvent:
- return QWindowsInputContext::instance()->endComposition(hwnd);
- case QtWindows::InputMethodRequest:
- return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result);
case QtWindows::GestureEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 06c9985cac..e4ec3f3cf8 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
{
const HDC dc = QWindowsContext::instance()->displayContext();
if (!dc){
- qWarning("%s: No Display", Q_FUNC_INFO);
+ qWarning("%s: No Display", __FUNCTION__);
return 0;
}
if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
return 0;
}
if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
return 0;
}
@@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
if (display == EGL_NO_DISPLAY)
display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
- qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
+ qWarning("%s: Could not obtain EGL display", __FUNCTION__);
return 0;
}
if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
int err = libEGL.eglGetError();
- qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
if (err == 0x3001)
- qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
return 0;
}
@@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na
(EGLNativeWindowType) nativeWindow, 0);
if (surface == EGL_NO_SURFACE) {
*err = libEGL.eglGetError();
- qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
+ qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
}
return surface;
@@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
}
if (m_eglContext == EGL_NO_CONTEXT) {
- qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ int err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
+ // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
+ // A common cause for this is disabling the graphics adapter used by the app.
+ if (err == EGL_BAD_ALLOC)
+ qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
return;
}
@@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
+ } else if (err == EGL_BAD_ACCESS) {
+ // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
+ qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
+ // Simulate context loss as the context is useless.
+ QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
+ m_eglContext = EGL_NO_CONTEXT;
}
return false;
}
@@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
// Drop the surface. Will recreate on the next makeCurrent.
window->invalidateSurface();
} else {
- qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this);
+ qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
}
}
@@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent()
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
- qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
+ QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
@@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
}
bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok)
- qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ if (!ok) {
+ err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ if (err == EGL_CONTEXT_LOST) {
+ m_eglContext = EGL_NO_CONTEXT;
+ qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
+ } else {
+ qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
+ }
+ }
}
QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 16b9118e81..3685197430 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap()
bool symb = false;
if (ttf) {
cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
- int size = 0;
cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
- cmapTable.size(), &symb, &size);
+ cmapTable.size(), &symb, &cmapSize);
}
if (!cmap) {
ttf = false;
@@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else if (ttf) {
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
++glyph_pos;
}
} else {
@@ -275,6 +274,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
hasOutline(0),
lw(0),
cmap(0),
+ cmapSize(0),
lbearing(SHRT_MIN),
rbearing(SHRT_MIN),
x_height(-1),
@@ -346,11 +346,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
#if !defined(Q_OS_WINCE)
if (symbol) {
- glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && ucs4 < 0x100)
- glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
} else if (ttf) {
- glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
#else
if (tm.tmFirstChar > 60000) {
glyph = ucs4;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 6df69c34db..409b44264e 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -146,6 +146,7 @@ private:
TEXTMETRIC tm;
int lw;
const unsigned char *cmap;
+ int cmapSize;
QByteArray cmapTable;
mutable qreal lbearing;
mutable qreal rbearing;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 485b876fc7..e016b84bba 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -199,32 +199,44 @@ void QWindowsInputContext::reset()
doneContext();
}
-void QWindowsInputContext::setFocusObject(QObject *object)
+void QWindowsInputContext::setFocusObject(QObject *)
{
// ### fixme: On Windows 8.1, it has been observed that the Input context
// remains active when this happens resulting in a lock-up. Consecutive
// key events still have VK_PROCESSKEY set and are thus ignored.
if (m_compositionContext.isComposing)
- imeNotifyCancelComposition(m_compositionContext.hwnd);
+ reset();
+ updateEnabled();
+}
+void QWindowsInputContext::updateEnabled()
+{
+ if (!QGuiApplication::focusObject())
+ return;
const QWindow *window = QGuiApplication::focusWindow();
- if (object && window && window->handle()) {
+ if (window && window->handle()) {
QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window);
- if (inputMethodAccepted()) {
- // Re-enable IME by associating default context saved on first disabling.
- if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
- platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
- }
- } else {
- // Disable IME by associating 0 context. Store context first time.
- if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
- platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
- if (!QWindowsInputContext::m_defaultContext && oldImC)
- QWindowsInputContext::m_defaultContext = oldImC;
- }
- }
+ const bool accepted = inputMethodAccepted();
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted;
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted);
+ }
+}
+
+void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
+{
+ if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled)
+ return;
+ if (enabled) {
+ // Re-enable Windows IME by associating default context saved on first disabling.
+ ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
+ platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
+ } else {
+ // Disable Windows IME by associating 0 context. Store context first time.
+ const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
+ platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
+ if (!QWindowsInputContext::m_defaultContext && oldImC)
+ QWindowsInputContext::m_defaultContext = oldImC;
}
}
@@ -234,6 +246,8 @@ void QWindowsInputContext::setFocusObject(QObject *object)
void QWindowsInputContext::update(Qt::InputMethodQueries queries)
{
+ if (queries & Qt::ImEnabled)
+ updateEnabled();
QPlatformInputContext::update(queries);
}
@@ -295,11 +309,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP
ImmReleaseContext(m_compositionContext.hwnd, himc);
}
-QWindowsInputContext *QWindowsInputContext::instance()
-{
- return static_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
-}
-
static inline QString getCompositionString(HIMC himc, DWORD dwIndex)
{
enum { bufferSize = 256 };
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 83a39989f6..eb4e3a3faa 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
class QInputMethodEvent;
+class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
@@ -62,14 +63,14 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
+ static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
+
bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
void reset() Q_DECL_OVERRIDE;
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
- static QWindowsInputContext *instance();
-
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
bool endComposition(HWND hwnd);
@@ -87,6 +88,7 @@ private:
void doneContext();
void startContextComposition();
void endContextComposition();
+ void updateEnabled();
const DWORD m_WM_MSIME_MOUSE;
static HIMC m_defaultContext;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 081a800913..402ab9ad71 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -266,10 +266,9 @@ QWindowsIntegration::~QWindowsIntegration()
void QWindowsIntegration::initialize()
{
- if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create())
- d->m_inputContext.reset(pluginContext);
- else
- d->m_inputContext.reset(new QWindowsInputContext);
+ QString icStr = QPlatformInputContextFactory::requested();
+ icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext)
+ : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
}
bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 3636bb7893..f8e2ded228 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -33,6 +33,7 @@
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
+#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowsguieventdispatcher.h"
#include "qwindowsinputcontext.h"
@@ -1074,7 +1075,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
- if (!QWindowsInputContext::instance()->isComposing())
+ const QWindowsInputContext *windowsInputContext =
+ qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+ if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey((HWND)window->winId());
BYTE keyState[256];
wchar_t newKey[3] = {0};
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index f86ab9fee3..375a7f11db 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -299,8 +299,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
return true;
}
-//#define QMIME_DEBUG
-
// helpers for using global memory
static int getCf(const FORMATETC &formatetc)
@@ -380,6 +378,73 @@ static bool canGetData(int cf, IDataObject * pDataObj)
return true;
}
+#ifndef QT_NO_DEBUG_OUTPUT
+QDebug operator<<(QDebug d, const FORMATETC &tc)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "FORMATETC(cfFormat=" << tc.cfFormat << ' ';
+ switch (tc.cfFormat) {
+ case CF_TEXT:
+ d << "CF_TEXT";
+ break;
+ case CF_BITMAP:
+ d << "CF_BITMAP";
+ break;
+ case CF_TIFF:
+ d << "CF_TIFF";
+ break;
+ case CF_OEMTEXT:
+ d << "CF_OEMTEXT";
+ break;
+ case CF_DIB:
+ d << "CF_DIB";
+ break;
+ case CF_DIBV5:
+ d << "CF_DIBV5";
+ break;
+ case CF_UNICODETEXT:
+ d << "CF_UNICODETEXT";
+ break;
+#ifndef Q_OS_WINCE
+ case CF_ENHMETAFILE:
+ d << "CF_ENHMETAFILE";
+ break;
+#endif // !Q_OS_WINCE
+ default:
+ d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat);
+ break;
+ }
+ d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex
+ << ", tymed=" << tc.tymed << ", ptd=" << tc.ptd << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, IDataObject *dataObj)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "IDataObject(";
+ if (dataObj) { // Output formats contained in IDataObject.
+ IEnumFORMATETC *enumFormatEtc;
+ if (SUCCEEDED(dataObj->EnumFormatEtc(DATADIR_GET, &enumFormatEtc)) && enumFormatEtc) {
+ FORMATETC formatEtc[1];
+ ULONG fetched;
+ if (SUCCEEDED(enumFormatEtc->Reset())) {
+ while (SUCCEEDED(enumFormatEtc->Next(1, formatEtc, &fetched)) && fetched)
+ d << formatEtc[0] << ',';
+ enumFormatEtc->Release();
+ }
+ }
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_OUTPUT
+
/*!
\class QWindowsMime
\brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
@@ -894,11 +959,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
QVariant result;
if (canConvertToMime(mime, pDataObj)) {
QByteArray html = getData(CF_HTML, pDataObj);
-#ifdef QMIME_DEBUG
- qDebug("QWindowsMimeHtml::convertToMime");
- qDebug("raw :");
- qDebug(html);
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html;
int start = html.indexOf("StartHTML:");
int end = html.indexOf("EndHTML:");
@@ -990,13 +1051,14 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
{
QVector<FORMATETC> formatetcs;
if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
- //add DIBV5 if image has alpha channel
+ //add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
- formatetcs += setCf(CF_PNG); // QTBUG-86848, Paste into GIMP queries for PNG.
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
@@ -1024,11 +1086,7 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
- // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of
- // transparency in conversion.
- return cf == CF_DIBV5
- || (cf == CF_DIB && !image.hasAlphaChannel())
- || cf == int(CF_PNG);
+ return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
@@ -1221,9 +1279,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat
if (canConvertToMime(mimeType, pDataObj)) {
QByteArray data = getData(inFormats.key(mimeType), pDataObj);
if (!data.isEmpty()) {
-#ifdef QMIME_DEBUG
- qDebug("QBuiltInMimes::convertToMime()");
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__;
if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
// text/html is in wide chars on windows (compatible with Mozilla)
val = QString::fromWCharArray((const wchar_t *)data.data());
@@ -1331,6 +1387,8 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con
that->formats.insert(cf, mimeType);
formatetcs += setCf(cf);
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\"";
@@ -1405,11 +1463,8 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
if (!format.isEmpty())
return format;
- wchar_t buffer[256];
- int len = GetClipboardFormatName(getCf(formatetc), buffer, 256);
-
- if (len) {
- QString clipFormat = QString::fromWCharArray(buffer, len);
+ const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc));
+ if (!clipFormat.isEmpty()) {
#ifndef QT_NO_DRAGANDDROP
if (QInternalMimeData::canReadData(clipFormat))
format = clipFormat;
@@ -1475,15 +1530,12 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
if (hr == NOERROR) {
FORMATETC fmtetc;
while (S_OK == fmtenum->Next(1, &fmtetc, 0)) {
-#if defined(QMIME_DEBUG)
- wchar_t buf[256] = {0};
- GetClipboardFormatName(fmtetc.cfFormat, buf, 255);
- qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf)));
-#endif
for (int i= m_mimes.size() - 1; i >= 0; --i) {
QString format = m_mimes.at(i)->mimeForFormat(fmtetc);
if (!format.isEmpty() && !formats.contains(format)) {
formats += format;
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetc << format;
}
}
// as documented in MSDN to avoid possible memleak
@@ -1499,6 +1551,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
ensureInitialized();
+ qCDebug(lcQpaMime) << __FUNCTION__ << formatetc;
for (int i = m_mimes.size()-1; i >= 0; --i) {
if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData))
return m_mimes.at(i);
@@ -1533,6 +1586,13 @@ void QWindowsMimeConverter::ensureInitialized() const
}
}
+QString QWindowsMimeConverter::clipboardFormatName(int cf)
+{
+ wchar_t buf[256] = {0};
+ return GetClipboardFormatName(cf, buf, 255)
+ ? QString::fromWCharArray(buf) : QString();
+}
+
QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
IDataObject *pDataObj,
QVariant::Type preferredType,
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 952410e14b..17fddef1bc 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
+class QDebug;
class QMimeData;
class QWindowsMime
@@ -83,6 +84,8 @@ public:
void registerMime(QWindowsMime *mime);
void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
+ static QString clipboardFormatName(int cf);
+
private:
void ensureInitialized() const;
@@ -90,6 +93,11 @@ private:
mutable int m_internalMimeCount;
};
+#ifndef QT_NO_DEBUG_OUTPUT
+QDebug operator<<(QDebug, const FORMATETC &);
+QDebug operator<<(QDebug d, IDataObject *);
+#endif
+
QT_END_NAMESPACE
#endif // QWINDOWSMIME_H
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 200eb11855..90cb6fe195 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -368,7 +368,10 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
m_previousCaptureWindow = hasCapture ? window : 0;
- return true;
+ // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
+ // is sent for unhandled WM_XBUTTONDOWN.
+ return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
+ || QWindowSystemInterface::flushWindowSystemEvents();
}
static bool isValidWheelReceiver(QWindow *candidate)
@@ -474,7 +477,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
typedef QList<QWindowSystemInterface::TouchPoint> QTouchPointList;
Q_ASSERT(m_touchDevice);
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
const int winTouchPointCount = msg.wParam;
QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]);
@@ -566,7 +574,12 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd,
if (gi.dwID != GID_DIRECTMANIPULATION)
return true;
static QPoint lastTouchPos;
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
QWindowSystemInterface::TouchPoint touchPoint;
static QWindowSystemInterface::TouchPoint touchPoint2;
touchPoint.id = 0;//gi.dwInstanceID;
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 6f5a521af8..e480c1ebcf 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -132,12 +132,6 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
{
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
- if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << QString::fromWCharArray(buf);
- }
-
if (data) {
const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data))
@@ -145,11 +139,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
hr = ResultFromScode(S_OK);
}
- if (QWindowsContext::verbose > 1) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << " returns 0x" << int(hr) << dec;
- }
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr);
return hr;
}
@@ -211,7 +202,7 @@ STDMETHODIMP
QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection;
if (!data)
return ResultFromScode(DATA_E_FORMATETC);
@@ -274,7 +265,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
m_dwRefs(1), m_nIndex(0), m_isNull(false)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
m_lpfmtetcs.reserve(fmtetcs.count());
for (int idx = 0; idx < fmtetcs.count(); ++idx) {
LPFORMATETC destetc = new FORMATETC();
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 391735a035..e6abfb2403 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -276,18 +276,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
return result;
}
-QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w)
-{
- if (w)
- if (const QScreen *s = w->screen())
- if (QPlatformScreen *pscr = s->handle())
- return static_cast<QWindowsScreen *>(pscr);
- if (const QScreen *ps = QGuiApplication::primaryScreen())
- if (QPlatformScreen *ppscr = ps->handle())
- return static_cast<QWindowsScreen *>(ppscr);
- return 0;
-}
-
qreal QWindowsScreen::pixelDensity() const
{
const qreal physicalDpi = m_data.geometry.width() / m_data.physicalSizeMM.width() * qreal(25.4);
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 67e7ff644b..bc8fbf553b 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -79,8 +79,6 @@ public:
explicit QWindowsScreen(const QWindowsScreenData &data);
- static QWindowsScreen *screenOf(const QWindow *w = 0);
-
QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 05bddec530..3951401273 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -54,7 +54,7 @@
#include <QtCore/private/qsystemlibrary_p.h>
// Note: The definition of the PACKET structure in pktdef.h depends on this define.
-#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z | PK_TIME)
#include <pktdef.h>
QT_BEGIN_NAMESPACE
@@ -342,17 +342,18 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueI
bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam)
{
+ PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
+ const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
+ if (!totalPacks)
+ return false;
if (!LOWORD(lParam)) {
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
- QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
}
- PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
- const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
- if (!totalPacks)
- return false;
const UINT currentCursor = proximityBuffer[0].pkCursor;
UINT physicalCursorId;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
@@ -370,7 +371,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
qCDebug(lcQpaTablet) << "enter proximity for device #"
<< m_currentDevice << m_devices.at(m_currentDevice);
- QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
@@ -473,7 +475,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF,
+ QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 1b5d7b87bc..abfddcfed6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1045,8 +1045,8 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
RegisterDragDrop(m_data.hwnd, m_dropTarget);
CoLockObjectExternal(m_dropTarget, true, true);
} else {
- m_dropTarget->Release();
CoLockObjectExternal(m_dropTarget, false, true);
+ m_dropTarget->Release();
RevokeDragDrop(m_data.hwnd);
m_dropTarget = 0;
}
@@ -1637,8 +1637,12 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
bool QWindowsWindow::isFullScreen_sys() const
{
const QWindow *w = window();
- return w->isTopLevel()
- && geometry_sys() == QHighDpi::toNativePixels(w->screen()->geometry(), w);
+ if (!w->isTopLevel())
+ return false;
+ const QScreen *screen = w->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ return screen && geometry_sys() == QHighDpi::toNativePixels(screen->geometry(), w);
}
/*!
@@ -1708,7 +1712,9 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
const QScreen *screen = window()->screen();
- const QRect r = QHighDpi::toNativePixels(screen->geometry(), window());
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
@@ -1825,7 +1831,7 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
windowPos->cx, windowPos->cy);
const QRect suggestedGeometry = suggestedFrameGeometry - margins;
- const QRectF correctedGeometryF = qWindow->handle()->windowClosestAcceptableGeometry(suggestedGeometry);
+ const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
if (!correctedGeometryF.isValid())
return false;
const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
index 44aab266ca..9cb45336d6 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
@@ -56,7 +56,6 @@ public:
EGLDisplay eglDisplay;
EGLConfig eglConfig;
EGLContext eglContext;
- QHash<QPlatformSurface *, EGLSurface> surfaceForWindow;
};
QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
@@ -70,8 +69,6 @@ QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
QWinRTEGLContext::~QWinRTEGLContext()
{
Q_D(QWinRTEGLContext);
- foreach (const EGLSurface &surface, d->surfaceForWindow)
- eglDestroySurface(d->eglDisplay, surface);
if (d->eglContext != EGL_NO_CONTEXT)
eglDestroyContext(d->eglDisplay, d->eglContext);
if (d->eglDisplay != EGL_NO_DISPLAY)
@@ -112,23 +109,13 @@ bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface)
Q_D(QWinRTEGLContext);
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
- EGLSurface surface = d->surfaceForWindow.value(windowSurface);
- if (surface == EGL_NO_SURFACE) {
- QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() {
- surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig,
- reinterpret_cast<EGLNativeWindowType>(window->winId()),
- nullptr);
- if (surface == EGL_NO_SURFACE) {
- qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
- return E_FAIL;
- }
- return S_OK;
- });
- if (FAILED(hr))
- return false;
- d->surfaceForWindow.insert(windowSurface, surface);
- }
+ QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
+ if (window->eglSurface() == EGL_NO_SURFACE)
+ window->createEglSurface(d->eglDisplay, d->eglConfig);
+
+ EGLSurface surface = window->eglSurface();
+ if (surface == EGL_NO_SURFACE)
+ return false;
const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext);
if (!ok) {
@@ -153,7 +140,8 @@ void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface)
Q_D(QWinRTEGLContext);
Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
- eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface));
+ const QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
+ eglSwapBuffers(d->eglDisplay, window->eglSurface());
}
QSurfaceFormat QWinRTEGLContext::format() const
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index e1b2a07d5f..05b1fd76b1 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -37,25 +37,32 @@
#include "qwinrtfiledialoghelper.h"
#include "qwinrtfileengine.h"
+#include <QtCore/qcoreapplication.h>
#include <QtCore/QEventLoop>
#include <QtCore/QMap>
#include <QtCore/QVector>
#include <QtCore/qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.storage.pickers.h>
+#include <Windows.ApplicationModel.activation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::ApplicationModel::Activation;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::Storage;
using namespace ABI::Windows::Storage::Pickers;
+#ifndef Q_OS_WINPHONE
typedef IAsyncOperationCompletedHandler<StorageFile *> SingleFileHandler;
typedef IAsyncOperationCompletedHandler<IVectorView<StorageFile *> *> MultipleFileHandler;
typedef IAsyncOperationCompletedHandler<StorageFolder *> SingleFolderHandler;
+#endif
QT_BEGIN_NAMESPACE
@@ -142,6 +149,16 @@ private:
QVector<HSTRING> impl;
};
+#ifdef Q_OS_WINPHONE
+class QActivationEvent : public QEvent
+{
+public:
+ IInspectable *args() const {
+ return reinterpret_cast<IInspectable *>(d);
+ }
+};
+#endif
+
template<typename T>
static bool initializePicker(HSTRING runtimeId, T **picker, const QSharedPointer<QFileDialogOptions> &options)
{
@@ -200,6 +217,99 @@ static bool initializeOpenPickerOptions(T *picker, const QSharedPointer<QFileDia
return true;
}
+static bool pickFiles(IFileOpenPicker *picker, QWinRTFileDialogHelper *helper, bool singleFile)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker, singleFile]() {
+ HRESULT hr;
+ ComPtr<IFileOpenPicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast file picker");
+ if (singleFile)
+ return picker2->PickSingleFileAndContinue();
+ else
+ return picker2->PickMultipleFilesAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open file picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+ return true;
+#else
+ if (singleFile) {
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = picker->PickSingleFileAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to open single file picker");
+ hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
+ RETURN_FALSE_IF_FAILED("Failed to attach file picker callback");
+ } else {
+ ComPtr<IAsyncOperation<IVectorView<StorageFile *> *>> op;
+ hr = picker->PickMultipleFilesAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to open multi file picker");
+ hr = op->put_Completed(Callback<MultipleFileHandler>(helper, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get());
+ RETURN_FALSE_IF_FAILED("Failed to attach multi file callback");
+ }
+ return true;
+#endif
+}
+
+static bool pickFolder(IFolderPicker *picker, QWinRTFileDialogHelper *helper)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker]() {
+ HRESULT hr;
+ ComPtr<IFolderPicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast folder picker");
+ return picker2->PickFolderAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open folder picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+#else
+ ComPtr<IAsyncOperation<StorageFolder *>> op;
+ hr = picker->PickSingleFolderAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to open folder picker");
+ hr = op->put_Completed(Callback<SingleFolderHandler>(helper, &QWinRTFileDialogHelper::onSingleFolderPicked).Get());
+ RETURN_FALSE_IF_FAILED("Failed to attach folder picker callback");
+#endif
+ return true;
+}
+
+static bool pickSaveFile(IFileSavePicker *picker, QWinRTFileDialogHelper *helper)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker]() {
+ HRESULT hr;
+ ComPtr<IFileSavePicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast save file picker");
+ return picker2->PickSaveFileAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open single file picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+#else
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = picker->PickSaveFileAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to open save file picker");
+ hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
+ RETURN_FALSE_IF_FAILED("Failed to attach save file picker callback");
+#endif
+ return true;
+}
+
class QWinRTFileDialogHelperPrivate
{
public:
@@ -260,18 +370,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
return false;
- if (dialogOptions->fileMode() == QFileDialogOptions::ExistingFiles) {
- ComPtr<IAsyncOperation<IVectorView<StorageFile *> *>> op;
- hr = picker->PickMultipleFilesAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open multi file picker");
- hr = op->put_Completed(Callback<MultipleFileHandler>(this, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get());
- } else {
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSingleFileAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open single file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- }
- RETURN_FALSE_IF_FAILED("Failed to attach file picker callback");
+ if (!pickFiles(picker.Get(), this, dialogOptions->fileMode() == QFileDialogOptions::ExistingFile))
+ return false;
+
break;
}
case QFileDialogOptions::Directory:
@@ -284,11 +385,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
return false;
- ComPtr<IAsyncOperation<StorageFolder *>> op;
- hr = picker->PickSingleFolderAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open folder picker");
- hr = op->put_Completed(Callback<SingleFolderHandler>(this, &QWinRTFileDialogHelper::onSingleFolderPicked).Get());
- RETURN_FALSE_IF_FAILED("Failed to attach folder picker callback");
+ if (!pickFolder(picker.Get(), this))
+ return false;
+
break;
}
}
@@ -344,11 +443,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
}
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSaveFileAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open save file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- RETURN_FALSE_IF_FAILED("Failed to attach file picker callback");
+ if (!pickSaveFile(picker.Get(), this))
+ return false;
+
break;
}
}
@@ -367,6 +464,68 @@ void QWinRTFileDialogHelper::hide()
d->shown = false;
}
+#ifdef Q_OS_WINPHONE
+bool QWinRTFileDialogHelper::eventFilter(QObject *, QEvent *e)
+{
+ if (e->type() != QEvent::WinEventAct)
+ return false;
+
+ HRESULT hr;
+ QActivationEvent *event = static_cast<QActivationEvent *>(e);
+ ComPtr<IInspectable> inspectable = event->args();
+ ComPtr<IActivatedEventArgs> arguments;
+ hr = inspectable.As(&arguments);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ActivationKind activationKind;
+ hr = arguments->get_Kind(&activationKind);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // Handle only File, Folder and Save file pick continuation here.
+ if (activationKind != ActivationKind_PickFileContinuation
+ && activationKind != ActivationKind_PickFolderContinuation
+ && activationKind != ActivationKind_PickSaveFileContinuation) {
+ return false;
+ }
+
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->removeEventFilter(this);
+ e->accept();
+
+ if (activationKind == ActivationKind_PickFileContinuation) {
+ ComPtr<IFileOpenPickerContinuationEventArgs> fileContinuationArgs;
+ hr = arguments.As(&fileContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<StorageFile *>> files;
+ hr = fileContinuationArgs->get_Files(&files);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFilesPicked(files.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ } else if (activationKind == ActivationKind_PickFolderContinuation) {
+ ComPtr<IFolderPickerContinuationEventArgs> folderContinuationArgs;
+ hr = arguments.As(&folderContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IStorageFolder> folder;
+ hr = folderContinuationArgs->get_Folder(&folder);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFolderPicked(folder.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ } else {
+ ComPtr<IFileSavePickerContinuationEventArgs> saveFileContinuationArgs;
+ hr = arguments.As(&saveFileContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IStorageFile> file;
+ hr = saveFileContinuationArgs->get_File(&file);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFilePicked(file.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ return true;
+}
+#endif
+
void QWinRTFileDialogHelper::setDirectory(const QUrl &directory)
{
Q_D(QWinRTFileDialogHelper);
@@ -403,6 +562,7 @@ QString QWinRTFileDialogHelper::selectedNameFilter() const
return d->selectedNameFilter;
}
+#ifndef Q_OS_WINPHONE
HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation<StorageFile *> *args, AsyncStatus status)
{
Q_D(QWinRTFileDialogHelper);
@@ -419,14 +579,7 @@ HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation<StorageFile *
ComPtr<IStorageFile> file;
hr = args->GetResults(&file);
Q_ASSERT_SUCCEEDED(hr);
- if (!file) {
- emit reject();
- return S_OK;
- }
-
- appendFile(file.Get());
- emit accept();
- return S_OK;
+ return onFilePicked(file.Get());
}
HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorView<StorageFile *> *> *args, AsyncStatus status)
@@ -445,17 +598,50 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorVie
ComPtr<IVectorView<StorageFile *>> fileList;
hr = args->GetResults(&fileList);
RETURN_HR_IF_FAILED("Failed to get file list");
+ return onFilesPicked(fileList.Get());
+}
+
+HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation<StorageFolder *> *args, AsyncStatus status)
+{
+ Q_D(QWinRTFileDialogHelper);
+
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+ if (status == Canceled || status == Error) {
+ emit reject();
+ return S_OK;
+ }
+
+ HRESULT hr;
+ ComPtr<IStorageFolder> folder;
+ hr = args->GetResults(&folder);
+ Q_ASSERT_SUCCEEDED(hr);
+ return onFolderPicked(folder.Get());
+}
+#endif //Q_OS_WINPHONE
+
+HRESULT QWinRTFileDialogHelper::onFilesPicked(IVectorView<StorageFile *> *files)
+{
+#ifdef Q_OS_WINPHONE
+ Q_D(QWinRTFileDialogHelper);
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+#endif
+ HRESULT hr;
quint32 size;
- hr = fileList->get_Size(&size);
+ hr = files->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
if (!size) {
emit reject();
return S_OK;
}
+
for (quint32 i = 0; i < size; ++i) {
ComPtr<IStorageFile> file;
- hr = fileList->GetAt(i, &file);
+ hr = files->GetAt(i, &file);
Q_ASSERT_SUCCEEDED(hr);
appendFile(file.Get());
}
@@ -464,28 +650,40 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorVie
return S_OK;
}
-HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation<StorageFolder *> *args, AsyncStatus status)
+HRESULT QWinRTFileDialogHelper::onFolderPicked(IStorageFolder *folder)
{
+#ifdef Q_OS_WINPHONE
Q_D(QWinRTFileDialogHelper);
-
QEventLoopLocker locker(&d->loop);
d->shown = false;
d->selectedFiles.clear();
- if (status == Canceled || status == Error) {
+#endif
+
+ if (!folder) {
emit reject();
return S_OK;
}
- HRESULT hr;
- ComPtr<IStorageFolder> folder;
- hr = args->GetResults(&folder);
- Q_ASSERT_SUCCEEDED(hr);
- if (!folder) {
+ appendFile(folder);
+ emit accept();
+ return S_OK;
+}
+
+HRESULT QWinRTFileDialogHelper::onFilePicked(IStorageFile *file)
+{
+#ifdef Q_OS_WINPHONE
+ Q_D(QWinRTFileDialogHelper);
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+#endif
+
+ if (!file) {
emit reject();
return S_OK;
}
- appendFile(folder.Get());
+ appendFile(file);
emit accept();
return S_OK;
}
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
index 51b79c84ef..d6bacd2db9 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
@@ -47,6 +47,7 @@ namespace ABI {
class StorageFile;
class StorageFolder;
struct IStorageFile;
+ struct IStorageFolder;
}
namespace Foundation {
enum class AsyncStatus;
@@ -71,6 +72,9 @@ public:
void exec() Q_DECL_OVERRIDE;
bool show(Qt::WindowFlags, Qt::WindowModality, QWindow *) Q_DECL_OVERRIDE;
void hide() Q_DECL_OVERRIDE;
+#ifdef Q_OS_WINPHONE
+ bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE;
+#endif
bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return false; }
void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
@@ -81,13 +85,19 @@ public:
void selectNameFilter(const QString &selectedNameFilter) Q_DECL_OVERRIDE;
QString selectedNameFilter() const;
-private:
+#ifndef Q_OS_WINPHONE
HRESULT onSingleFilePicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFile *> *,
ABI::Windows::Foundation::AsyncStatus);
HRESULT onMultipleFilesPicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::Collections::IVectorView<ABI::Windows::Storage::StorageFile *> *> *,
ABI::Windows::Foundation::AsyncStatus);
HRESULT onSingleFolderPicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFolder *> *,
ABI::Windows::Foundation::AsyncStatus);
+#endif
+
+private:
+ HRESULT onFilesPicked(ABI::Windows::Foundation::Collections::IVectorView<ABI::Windows::Storage::StorageFile *> *files);
+ HRESULT onFolderPicked(ABI::Windows::Storage::IStorageFolder *folder);
+ HRESULT onFilePicked(ABI::Windows::Storage::IStorageFile *file);
void appendFile(IInspectable *);
QScopedPointer<QWinRTFileDialogHelperPrivate> d_ptr;
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
index 7bd9e87ca6..f3b390b4d6 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -37,7 +37,9 @@
#include "qwinrtinputcontext.h"
#include "qwinrtscreen.h"
#include <QtGui/QWindow>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <wrl.h>
#include <roapi.h>
#include <windows.ui.viewmanagement.h>
@@ -163,10 +165,14 @@ void QWinRTInputContext::showInputPanel()
if (FAILED(hr))
return;
- boolean success;
- hr = inputPane->TryShow(&success);
- if (FAILED(hr))
- qErrnoWarning(hr, "Failed to show input panel.");
+ QEventDispatcherWinRT::runOnXamlThread([&inputPane]() {
+ HRESULT hr;
+ boolean success;
+ hr = inputPane->TryShow(&success);
+ if (FAILED(hr) || !success)
+ qErrnoWarning(hr, "Failed to show input panel.");
+ return hr;
+ });
}
void QWinRTInputContext::hideInputPanel()
@@ -176,10 +182,14 @@ void QWinRTInputContext::hideInputPanel()
if (FAILED(hr))
return;
- boolean success;
- hr = inputPane->TryHide(&success);
- if (FAILED(hr))
- qErrnoWarning(hr, "Failed to hide input panel.");
+ QEventDispatcherWinRT::runOnXamlThread([&inputPane]() {
+ HRESULT hr;
+ boolean success;
+ hr = inputPane->TryHide(&success);
+ if (FAILED(hr) || !success)
+ qErrnoWarning(hr, "Failed to hide input panel.");
+ return hr;
+ });
}
#endif // Q_OS_WINPHONE
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 7079d46523..fce77c56d1 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -188,9 +188,9 @@ bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case ThreadedPixmaps:
case OpenGL:
case ApplicationState:
- return true;
case NonFullScreenWindows:
- return false;
+ case MultipleWindows:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
index 4fc1fea626..68bf1fdcac 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -38,7 +38,9 @@
#include "qwinrttheme.h"
#include <QtCore/qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <windows.ui.popups.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
@@ -168,16 +170,20 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa
}
}
- ComPtr<IAsyncOperation<IUICommand *>> op;
- hr = dialog->ShowAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to show dialog");
- hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
- RETURN_FALSE_IF_FAILED("Failed to set dialog callback");
-
- d->shown = true;
- hr = op.As(&d->info);
- RETURN_FALSE_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
-
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, d, dialog]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<IUICommand *>> op;
+ hr = dialog->ShowAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to show dialog");
+ hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
+ RETURN_HR_IF_FAILED("Failed to set dialog callback");
+ d->shown = true;
+ hr = op.As(&d->info);
+ RETURN_HR_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
+ return hr;
+ });
+
+ RETURN_FALSE_IF_FAILED("Failed to show dialog")
return true;
}
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 89ad33657b..563753cfcb 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -83,6 +83,9 @@ typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
+#ifdef Q_OS_WINPHONE
+typedef ITypedEventHandler<StatusBar*, IInspectable*> StatusBarHandler;
+#endif
QT_BEGIN_NAMESPACE
@@ -405,6 +408,10 @@ typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistr
uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IStatusBar::*StatusBarCallbackRemover)(EventRegistrationToken);
+uint qHash(StatusBarCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
class QWinRTScreenPrivate
{
@@ -414,11 +421,12 @@ public:
ComPtr<Xaml::IDependencyObject> canvas;
ComPtr<IApplicationView> view;
ComPtr<IDisplayInformation> displayInformation;
+#ifdef Q_OS_WINPHONE
+ ComPtr<IStatusBar> statusBar;
+#endif
QScopedPointer<QWinRTCursor> cursor;
-
QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
-
QSizeF logicalSize;
QSurfaceFormat surfaceFormat;
qreal logicalDpi;
@@ -433,6 +441,9 @@ public:
QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
+#ifdef Q_OS_WINPHONE
+ QHash<StatusBarCallbackRemover, EventRegistrationToken> statusBarTokens;
+#endif
};
// To be called from the XAML thread
@@ -472,8 +483,10 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
Q_ASSERT_SUCCEEDED(hr);
+#ifndef Q_OS_WINPHONE
hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
Q_ASSERT_SUCCEEDED(hr);
+#endif
hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
@@ -535,6 +548,19 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
Q_ASSERT_SUCCEEDED(hr);
d->cursor.reset(new QWinRTCursor);
+
+#ifdef Q_OS_WINPHONE
+ ComPtr<IStatusBarStatics> statusBarStatics;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_StatusBar).Get(),
+ IID_PPV_ARGS(&statusBarStatics));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = statusBarStatics->GetForCurrentView(&d->statusBar);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]);
+ Q_ASSERT_SUCCEEDED(hr);
+#endif // Q_OS_WINPHONE
}
QWinRTScreen::~QWinRTScreen()
@@ -553,6 +579,12 @@ QWinRTScreen::~QWinRTScreen()
hr = (d->displayInformation.Get()->*i.key())(i.value());
Q_ASSERT_SUCCEEDED(hr);
}
+#ifdef Q_OS_WINPHONE
+ for (QHash<StatusBarCallbackRemover, EventRegistrationToken>::const_iterator i = d->statusBarTokens.begin(); i != d->statusBarTokens.end(); ++i) {
+ hr = (d->statusBar.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif //Q_OS_WINPHONE
return hr;
});
RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks");
@@ -564,6 +596,31 @@ QRect QWinRTScreen::geometry() const
return QRect(QPoint(), (d->logicalSize * d->scaleFactor).toSize());
}
+#ifdef Q_OS_WINPHONE
+QRect QWinRTScreen::availableGeometry() const
+{
+ Q_D(const QWinRTScreen);
+ QRect statusBar;
+ QEventDispatcherWinRT::runOnXamlThread([d, &statusBar]() {
+ HRESULT hr;
+ Rect rect;
+ hr = d->statusBar->get_OccludedRect(&rect);
+ Q_ASSERT_SUCCEEDED(hr);
+ statusBar.setRect(qRound(rect.X * d->scaleFactor),
+ qRound(rect.Y * d->scaleFactor),
+ qRound(rect.Width * d->scaleFactor),
+ qRound(rect.Height * d->scaleFactor));
+ return S_OK;
+ });
+
+ return geometry().adjusted(
+ d->orientation == Qt::LandscapeOrientation ? statusBar.width() : 0,
+ d->orientation == Qt::PortraitOrientation ? statusBar.height() : 0,
+ d->orientation == Qt::InvertedLandscapeOrientation ? -statusBar.width() : 0,
+ 0);
+}
+#endif //Q_OS_WINPHONE
+
int QWinRTScreen::depth() const
{
return 32;
@@ -649,6 +706,26 @@ Xaml::IDependencyObject *QWinRTScreen::canvas() const
return d->canvas.Get();
}
+#ifdef Q_OS_WINPHONE
+void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window)
+{
+ Q_D(QWinRTScreen);
+ if (!window || (window->flags() & Qt::WindowType_Mask) != Qt::Window)
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, visible]() {
+ HRESULT hr;
+ ComPtr<IAsyncAction> op;
+ if (visible)
+ hr = d->statusBar->ShowAsync(&op);
+ else
+ hr = d->statusBar->HideAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+#endif //Q_OS_WINPHONE
+
QWindow *QWinRTScreen::topWindow() const
{
Q_D(const QWinRTScreen);
@@ -660,6 +737,12 @@ void QWinRTScreen::addWindow(QWindow *window)
Q_D(QWinRTScreen);
if (window == topWindow())
return;
+
+#ifdef Q_OS_WINPHONE
+ if (window->visibility() != QWindow::Maximized && window->visibility() != QWindow::Windowed)
+ setStatusBarVisibility(false, window);
+#endif
+
d->visibleWindows.prepend(window);
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
@@ -668,6 +751,12 @@ void QWinRTScreen::addWindow(QWindow *window)
void QWinRTScreen::removeWindow(QWindow *window)
{
Q_D(QWinRTScreen);
+
+#ifdef Q_OS_WINPHONE
+ if (window->visibility() == QWindow::Minimized)
+ setStatusBarVisibility(false, window);
+#endif
+
const bool wasTopWindow = window == topWindow();
if (!d->visibleWindows.removeAll(window))
return;
@@ -964,13 +1053,8 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
HRESULT hr;
hr = d->coreWindow->get_Bounds(&size);
RETURN_OK_IF_FAILED("Failed to get window bounds");
- QSizeF logicalSize = QSizeF(size.Width, size.Height);
- if (d->logicalSize == logicalSize)
- return S_OK;
-
- d->logicalSize = logicalSize;
- const QRect newGeometry = geometry();
- QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
+ d->logicalSize = QSizeF(size.Width, size.Height);
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
return S_OK;
@@ -1024,7 +1108,11 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *
Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
if (d->orientation != newOrientation) {
d->orientation = newOrientation;
+#ifdef Q_OS_WINPHONE
+ onSizeChanged(nullptr, nullptr);
+#endif
QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
+ handleExpose(); // Clean broken frames caused by race between Qt and ANGLE
}
return S_OK;
}
@@ -1062,4 +1150,18 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
return S_OK;
}
+#ifdef Q_OS_WINPHONE
+HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *)
+{
+ onSizeChanged(nullptr, nullptr);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *)
+{
+ onSizeChanged(nullptr, nullptr);
+ return S_OK;
+}
+#endif //Q_OS_WINPHONE
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index 796e6abb80..3297617740 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -61,6 +61,9 @@ namespace ABI {
struct IDependencyObject;
struct IWindow;
}
+ namespace ViewManagement {
+ struct IStatusBar;
+ }
}
namespace Graphics {
namespace Display {
@@ -82,17 +85,20 @@ class QWinRTScreen : public QPlatformScreen
public:
explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow);
~QWinRTScreen();
- QRect geometry() const;
- int depth() const;
- QImage::Format format() const;
+ QRect geometry() const Q_DECL_OVERRIDE;
+#ifdef Q_OS_WINPHONE
+ QRect availableGeometry() const Q_DECL_OVERRIDE;
+#endif
+ int depth() const Q_DECL_OVERRIDE;
+ QImage::Format format() const Q_DECL_OVERRIDE;
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
qreal scaleFactor() const;
- QPlatformCursor *cursor() const;
+ QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
Qt::KeyboardModifiers keyboardModifiers() const;
- Qt::ScreenOrientation nativeOrientation() const;
- Qt::ScreenOrientation orientation() const;
+ Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
+ Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
QWindow *topWindow() const;
void addWindow(QWindow *window);
@@ -105,6 +111,10 @@ public:
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
ABI::Windows::UI::Xaml::IDependencyObject *canvas() const;
+#ifdef Q_OS_WINPHONE
+ void setStatusBarVisibility(bool visible, QWindow *window);
+#endif
+
private:
void handleExpose();
@@ -124,6 +134,11 @@ private:
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
+#ifdef Q_OS_WINPHONE
+ HRESULT onStatusBarShowing(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *);
+ HRESULT onStatusBarHiding(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *);
+#endif
+
QScopedPointer<QWinRTScreenPrivate> d_ptr;
Q_DECLARE_PRIVATE(QWinRTScreen)
};
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index 634d62ef24..c5b06a5d8a 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -64,9 +64,22 @@ using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Controls;
QT_BEGIN_NAMESPACE
+static void setUIElementVisibility(IUIElement *uiElement, bool visibility)
+{
+ Q_ASSERT(uiElement);
+ QEventDispatcherWinRT::runOnXamlThread([uiElement, visibility]() {
+ HRESULT hr;
+ hr = uiElement->put_Visibility(visibility ? Visibility_Visible : Visibility_Collapsed);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+
class QWinRTWindowPrivate
{
public:
@@ -74,8 +87,13 @@ public:
QSurfaceFormat surfaceFormat;
QString windowTitle;
+ Qt::WindowState state;
+ EGLDisplay display;
+ EGLSurface surface;
- ComPtr<Xaml::Controls::ISwapChainPanel> swapChainPanel;
+ ComPtr<ISwapChainPanel> swapChainPanel;
+ ComPtr<ICanvasStatics> canvas;
+ ComPtr<IUIElement> uiElement;
};
QWinRTWindow::QWinRTWindow(QWindow *window)
@@ -84,6 +102,8 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
{
Q_D(QWinRTWindow);
+ d->surface = EGL_NO_SURFACE;
+ d->display = EGL_NO_DISPLAY;
d->screen = static_cast<QWinRTScreen *>(screen());
setWindowFlags(window->flags());
setWindowState(window->windowState());
@@ -101,24 +121,26 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(),
+ IID_PPV_ARGS(&d->canvas));
+ Q_ASSERT_SUCCEEDED(hr);
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
// Create a new swapchain and place it inside the canvas
HRESULT hr;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
&d->swapChainPanel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Xaml::IUIElement> uiElement;
- hr = d->swapChainPanel.As(&uiElement);
+ hr = d->swapChainPanel.As(&d->uiElement);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
- ComPtr<Xaml::Controls::IPanel> panel;
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVector<Xaml::UIElement *>> children;
+ ComPtr<IVector<UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
- hr = children->Append(uiElement.Get());
+ hr = children->Append(d->uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
});
@@ -134,20 +156,16 @@ QWinRTWindow::~QWinRTWindow()
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
HRESULT hr;
- ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
- ComPtr<Xaml::Controls::IPanel> panel;
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
hr = canvas.As(&panel);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IVector<Xaml::UIElement *>> children;
+ ComPtr<IVector<UIElement *>> children;
hr = panel->get_Children(&children);
Q_ASSERT_SUCCEEDED(hr);
-
- ComPtr<Xaml::IUIElement> uiElement;
- hr = d->swapChainPanel.As(&uiElement);
- Q_ASSERT_SUCCEEDED(hr);
quint32 index;
boolean found;
- hr = children->IndexOf(uiElement.Get(), &index, &found);
+ hr = children->IndexOf(d->uiElement.Get(), &index, &found);
Q_ASSERT_SUCCEEDED(hr);
if (found) {
hr = children->RemoveAt(index);
@@ -156,6 +174,11 @@ QWinRTWindow::~QWinRTWindow()
return S_OK;
});
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
+
+ EGLBoolean value = eglDestroySurface(d->display, d->surface);
+ d->surface = EGL_NO_SURFACE;
+ if (value == EGL_FALSE)
+ qCritical("Failed to destroy EGL window surface: 0x%x", eglGetError());
}
QSurfaceFormat QWinRTWindow::format() const
@@ -180,8 +203,10 @@ void QWinRTWindow::setGeometry(const QRect &rect)
{
Q_D(QWinRTWindow);
- if (window()->isTopLevel()) {
- QPlatformWindow::setGeometry(d->screen->geometry());
+ const Qt::WindowFlags windowFlags = window()->flags();
+ if (window()->isTopLevel() && (windowFlags & Qt::WindowType_Mask) == Qt::Window) {
+ QPlatformWindow::setGeometry(windowFlags & Qt::MaximizeUsingFullscreenGeometryHint
+ ? d->screen->geometry() : d->screen->availableGeometry());
QWindowSystemInterface::handleGeometryChange(window(), geometry());
} else {
QPlatformWindow::setGeometry(rect);
@@ -191,10 +216,16 @@ void QWinRTWindow::setGeometry(const QRect &rect)
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
+ const QRect windowGeometry = geometry();
+ const QPointF topLeft= QPointF(windowGeometry.topLeft()) / d->screen->scaleFactor();
+ hr = d->canvas->SetTop(d->uiElement.Get(), topLeft.y());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->canvas->SetLeft(d->uiElement.Get(), topLeft.x());
+ Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IFrameworkElement> frameworkElement;
hr = d->swapChainPanel.As(&frameworkElement);
Q_ASSERT_SUCCEEDED(hr);
- const QSizeF size = QSizeF(geometry().size()) / d->screen->scaleFactor();
+ const QSizeF size = QSizeF(windowGeometry.size()) / d->screen->scaleFactor();
hr = frameworkElement->put_Width(size.width());
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Height(size.height());
@@ -209,10 +240,13 @@ void QWinRTWindow::setVisible(bool visible)
Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
- if (visible)
+ if (visible) {
d->screen->addWindow(window());
- else
+ setUIElementVisibility(d->uiElement.Get(), d->state != Qt::WindowMinimized);
+ } else {
d->screen->removeWindow(window());
+ setUIElementVisibility(d->uiElement.Get(), false);
+ }
}
void QWinRTWindow::setWindowTitle(const QString &title)
@@ -249,4 +283,45 @@ qreal QWinRTWindow::devicePixelRatio() const
return screen()->devicePixelRatio();
}
+void QWinRTWindow::setWindowState(Qt::WindowState state)
+{
+ Q_D(QWinRTWindow);
+ if (d->state == state)
+ return;
+
+#ifdef Q_OS_WINPHONE
+ d->screen->setStatusBarVisibility(state == Qt::WindowMaximized || state == Qt::WindowNoState, window());
+#endif
+
+ if (state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), false);
+
+ if (d->state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), true);
+
+ d->state = state;
+}
+
+EGLSurface QWinRTWindow::eglSurface() const
+{
+ Q_D(const QWinRTWindow);
+ return d->surface;
+}
+
+void QWinRTWindow::createEglSurface(EGLDisplay display, EGLConfig config)
+{
+ Q_D(QWinRTWindow);
+ if (d->surface == EGL_NO_SURFACE) {
+ d->display = display;
+ QEventDispatcherWinRT::runOnXamlThread([this, d, display, config]() {
+ d->surface = eglCreateWindowSurface(display, config,
+ reinterpret_cast<EGLNativeWindowType>(winId()),
+ nullptr);
+ if (d->surface == EGL_NO_SURFACE)
+ qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
+ return S_OK;
+ });
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index 88c149b080..9ac7adbf4d 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -39,6 +39,7 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
+#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +62,10 @@ public:
WId winId() const Q_DECL_OVERRIDE;
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+
+ EGLSurface eglSurface() const;
+ void createEglSurface(EGLDisplay display, EGLConfig config);
private:
QScopedPointer<QWinRTWindowPrivate> d_ptr;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 15d3575e60..c35b019f7e 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -107,6 +107,24 @@ Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
#define XCB_GE_GENERIC 35
#endif
+// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
+// - "pad0" became "extension"
+// - "pad1" and "pad" became "pad0"
+// New and old version of this struct share the following fields:
+typedef struct qt_xcb_ge_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+} qt_xcb_ge_event_t;
+
+static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
+{
+ qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event;
+ return e->extension == opCode;
+}
+
#ifdef XCB_USE_XLIB
static const char * const xcbConnectionErrors[] = {
"No error", /* Error 0 */
@@ -305,13 +323,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
screen->updateRefreshRate(output.mode);
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
- // TODO: add a proper mechanism for updating primary screen
if (!wasPrimary && screen->isPrimary()) {
- QScreen *realScreen = static_cast<QPlatformScreen*>(screen)->screen();
- QGuiApplicationPrivate::screen_list.removeOne(realScreen);
- QGuiApplicationPrivate::screen_list.prepend(realScreen);
- m_screens.removeOne(screen);
- m_screens.prepend(screen);
+ const int idx = m_screens.indexOf(screen);
+ m_screens.swap(0, idx);
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
}
qCDebug(lcQpaScreen) << "output has changed" << screen;
}
@@ -590,9 +605,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration";
sync();
-
- if (qEnvironmentVariableIsEmpty("QT_IM_MODULE"))
- qputenv("QT_IM_MODULE", QByteArray("compose"));
}
QXcbConnection::~QXcbConnection()
@@ -1115,7 +1127,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
#if defined(XCB_USE_XINPUT2)
case XCB_GE_GENERIC:
// Here the windowEventListener is invoked from xi2HandleEvent()
- if (m_xi2Enabled)
+ if (m_xi2Enabled && isXIEvent(event, m_xiOpCode))
xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
break;
#endif
@@ -1288,10 +1300,12 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
memset(&event, 0, sizeof(event));
const xcb_window_t eventListener = xcb_generate_id(m_connection);
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
+ xcb_screen_t *screen = it.data;
Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
- eventListener, m_screens.at(0)->root(),
+ eventListener, screen->root,
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
- m_screens.at(0)->screen()->root_visual, 0, 0));
+ screen->root_visual, 0, 0));
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
@@ -1437,6 +1451,105 @@ void *QXcbConnection::createVisualInfoForDefaultVisualId() const
#endif
+#if defined(XCB_USE_XINPUT2)
+// it is safe to cast XI_* events here as long as we are only touching the first 32 bytes,
+// after that position event needs memmove, see xi2PrepareXIGenericDeviceEvent
+static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type)
+{
+ if (!isXIEvent(event, opCode))
+ return false;
+
+ xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ return xiEvent->evtype == type;
+}
+#endif
+static inline bool isValid(xcb_generic_event_t *event)
+{
+ return event && (event->response_type & ~0x80);
+}
+
+/*! \internal
+
+ Compresses events of the same type to avoid swamping the event queue.
+ If event compression is not desired there are several options what developers can do:
+
+ 1) Write responsive applications. We drop events that have been buffered in the event
+ queue while waiting on unresponsive GUI thread.
+ 2) Use QAbstractNativeEventFilter to get all events from X connection. This is not optimal
+ because it requires working with native event types.
+ 3) Or add public API to Qt for disabling event compression QTBUG-44964
+
+*/
+bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const
+{
+ uint responseType = event->response_type & ~0x80;
+ int nextIndex = currentIndex + 1;
+
+ if (responseType == XCB_MOTION_NOTIFY) {
+ // compress XCB_MOTION_NOTIFY notify events
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (next->response_type == XCB_MOTION_NOTIFY)
+ return true;
+ }
+ return false;
+ }
+#if defined(XCB_USE_XINPUT2)
+ // compress XI_* events
+ if (responseType == XCB_GE_GENERIC) {
+ if (!m_xi2Enabled)
+ return false;
+
+ // compress XI_Motion
+ if (isXIType(event, m_xiOpCode, XI_Motion)) {
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (isXIType(next, m_xiOpCode, XI_Motion))
+ return true;
+ }
+ return false;
+ }
+#ifdef XCB_USE_XINPUT22
+ // compress XI_TouchUpdate for the same touch point id
+ if (isXIType(event, m_xiOpCode, XI_TouchUpdate)) {
+ xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ uint32_t id = xiDeviceEvent->detail % INT_MAX;
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (isXIType(next, m_xiOpCode, XI_TouchUpdate)) {
+ xXIDeviceEvent *xiDeviceNextEvent = reinterpret_cast<xXIDeviceEvent *>(next);
+ if (id == xiDeviceNextEvent->detail % INT_MAX)
+ return true;
+ }
+ }
+ return false;
+ }
+#endif
+ return false;
+ }
+#endif
+ if (responseType == XCB_CONFIGURE_NOTIFY) {
+ // compress multiple configure notify events for the same window
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY
+ && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+}
+
void QXcbConnection::processXcbEvents()
{
int connection_error = xcb_connection_has_error(xcb_connection());
@@ -1447,61 +1560,39 @@ void QXcbConnection::processXcbEvents()
QXcbEventArray *eventqueue = m_reader->lock();
- for(int i = 0; i < eventqueue->size(); ++i) {
+ for (int i = 0; i < eventqueue->size(); ++i) {
xcb_generic_event_t *event = eventqueue->at(i);
if (!event)
continue;
QScopedPointer<xcb_generic_event_t, QScopedPointerPodDeleter> eventGuard(event);
(*eventqueue)[i] = 0;
- uint response_type = event->response_type & ~0x80;
-
- if (!response_type) {
+ if (!(event->response_type & ~0x80)) {
handleXcbError((xcb_generic_error_t *)event);
- } else {
- if (response_type == XCB_MOTION_NOTIFY) {
- // compress multiple motion notify events in a row
- // to avoid swamping the event queue
- xcb_generic_event_t *next = eventqueue->value(i+1, 0);
- if (next && (next->response_type & ~0x80) == XCB_MOTION_NOTIFY)
- continue;
- }
+ continue;
+ }
- if (response_type == XCB_CONFIGURE_NOTIFY) {
- // compress multiple configure notify events for the same window
- bool found = false;
- for (int j = i; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *other = eventqueue->at(j);
- if (other && (other->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY
- && ((xcb_configure_notify_event_t *)other)->event == ((xcb_configure_notify_event_t *)event)->event)
- {
- found = true;
- break;
- }
- }
- if (found)
- continue;
- }
+ if (compressEvent(event, i, eventqueue))
+ continue;
- bool accepted = false;
- if (clipboard()->processIncr())
- clipboard()->incrTransactionPeeker(event, accepted);
- if (accepted)
- continue;
+ bool accepted = false;
+ if (clipboard()->processIncr())
+ clipboard()->incrTransactionPeeker(event, accepted);
+ if (accepted)
+ continue;
- QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
- while (it != m_peekFuncs.end()) {
- // These callbacks return true if the event is what they were
- // waiting for, remove them from the list in that case.
- if ((*it)(this, event))
- it = m_peekFuncs.erase(it);
- else
- ++it;
- }
- m_reader->unlock();
- handleXcbEvent(event);
- m_reader->lock();
+ QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
+ while (it != m_peekFuncs.end()) {
+ // These callbacks return true if the event is what they were
+ // waiting for, remove them from the list in that case.
+ if ((*it)(this, event))
+ it = m_peekFuncs.erase(it);
+ else
+ ++it;
}
+ m_reader->unlock();
+ handleXcbEvent(event);
+ m_reader->lock();
}
eventqueue->clear();
@@ -1746,7 +1837,8 @@ static const char * xcb_atomnames = {
"_XSETTINGS_SETTINGS\0"
"_COMPIZ_DECOR_PENDING\0"
"_COMPIZ_DECOR_REQUEST\0"
- "_COMPIZ_DECOR_DELETE_PIXMAP\0" // \0\0 terminates loop.
+ "_COMPIZ_DECOR_DELETE_PIXMAP\0"
+ "_COMPIZ_TOOLKIT_ACTION\0" // \0\0 terminates loop.
};
QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
@@ -2043,34 +2135,13 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub
return true;
}
-// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
-// - "pad0" became "extension"
-// - "pad1" and "pad" became "pad0"
-// New and old version of this struct share the following fields:
-// NOTE: API might change again in the next release of xcb in which case this comment will
-// need to be updated to reflect the reality.
-typedef struct qt_xcb_ge_event_t {
- uint8_t response_type;
- uint8_t extension;
- uint16_t sequence;
- uint32_t length;
- uint16_t event_type;
-} qt_xcb_ge_event_t;
-
-bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode)
-{
- qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev;
- // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from
- // the xcb version 1.9.3, prior to that it was called "pad0".
- if (event->extension == opCode) {
- // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
- // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
- // Move this data back to have the same layout in memory as it was on the wire
- // and allow casting, overwriting the full_sequence field.
- memmove((char*) event + 32, (char*) event + 36, event->length * 4);
- return true;
- }
- return false;
+void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
+{
+ // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
+ // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
+ // Move this data back to have the same layout in memory as it was on the wire
+ // and allow casting, overwriting the full_sequence field.
+ memmove((char*) event + 32, (char*) event + 36, event->length * 4);
}
#endif // defined(XCB_USE_XINPUT2)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 4a0348aa0c..6ee32bf600 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -286,6 +286,7 @@ namespace QXcbAtom {
_COMPIZ_DECOR_PENDING,
_COMPIZ_DECOR_REQUEST,
_COMPIZ_DECOR_DELETE_PIXMAP,
+ _COMPIZ_TOOLKIT_ACTION,
NPredefinedAtoms,
@@ -522,6 +523,7 @@ private:
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void initializeScreens();
void updateScreens(const xcb_randr_notify_event_t *event);
+ bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled;
int m_xi2Minor;
@@ -574,7 +576,7 @@ private:
QHash<int, ScrollingDevice> m_scrollingDevices;
static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value);
- static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode);
+ static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event);
#endif
xcb_connection_t *m_connection;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 5a2ea74258..8097cce709 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -216,6 +216,12 @@ void QXcbConnection::xi2SetupDevices()
isTablet = true;
tabletData.pointerType = QTabletEvent::Pen;
dbgType = QLatin1String("pen");
+ } else if (name.contains("waltop") && name.contains("tablet")) {
+ // other "Genius" tablets
+ // WALTOP International Corp. Slim Tablet
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
} else {
isTablet = false;
}
@@ -413,8 +419,10 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
hasRelativeCoords = true;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
} else if (vci->label == atom(QXcbAtom::AbsX)) {
+ caps |= QTouchDevice::Position;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
} else if (vci->label == atom(QXcbAtom::AbsY)) {
+ caps |= QTouchDevice::Position;
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
}
break;
@@ -459,82 +467,81 @@ static inline qreal fixed1616ToReal(FP1616 val)
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
- if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
- xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
- int sourceDeviceId = xiEvent->deviceid; // may be the master id
- xXIDeviceEvent *xiDeviceEvent = 0;
- QXcbWindowEventListener *eventListener = 0;
+ xi2PrepareXIGenericDeviceEvent(event);
+ xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ int sourceDeviceId = xiEvent->deviceid; // may be the master id
+ xXIDeviceEvent *xiDeviceEvent = 0;
+ QXcbWindowEventListener *eventListener = 0;
- switch (xiEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
+ switch (xiEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
#ifdef XCB_USE_XINPUT22
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
#endif
- {
- xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
- eventListener = windowEventListenerFromId(xiDeviceEvent->event);
- if (eventListener) {
- long result = 0;
- if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
- return;
- }
- sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
- break;
- }
- case XI_HierarchyChanged:
- xi2HandleHierachyEvent(xiEvent);
- return;
- case XI_DeviceChanged:
- xi2HandleDeviceChangedEvent(xiEvent);
- return;
- default:
- break;
+ {
+ xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ eventListener = windowEventListenerFromId(xiDeviceEvent->event);
+ if (eventListener) {
+ long result = 0;
+ if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
+ return;
}
+ sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
+ break;
+ }
+ case XI_HierarchyChanged:
+ xi2HandleHierachyEvent(xiEvent);
+ return;
+ case XI_DeviceChanged:
+ xi2HandleDeviceChangedEvent(xiEvent);
+ return;
+ default:
+ break;
+ }
#ifndef QT_NO_TABLETEVENT
- for (int i = 0; i < m_tabletData.count(); ++i) {
- if (m_tabletData.at(i).deviceId == sourceDeviceId) {
- if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
- return;
- }
+ for (int i = 0; i < m_tabletData.count(); ++i) {
+ if (m_tabletData.at(i).deviceId == sourceDeviceId) {
+ if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
+ return;
}
+ }
#endif // QT_NO_TABLETEVENT
#ifdef XCB_USE_XINPUT21
- QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
- if (device != m_scrollingDevices.end())
- xi2HandleScrollEvent(xiEvent, device.value());
+ QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
+ if (device != m_scrollingDevices.end())
+ xi2HandleScrollEvent(xiEvent, device.value());
#endif // XCB_USE_XINPUT21
#ifdef XCB_USE_XINPUT22
- if (xiDeviceEvent) {
- switch (xiDeviceEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
- if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
- eventListener->handleXIMouseEvent(event);
- break;
+ if (xiDeviceEvent) {
+ switch (xiDeviceEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
+ eventListener->handleXIMouseEvent(event);
+ break;
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
- if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
- event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
- fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
- fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
- if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
- xi2ProcessTouch(xiDeviceEvent, platformWindow);
- break;
- }
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
+ if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+ qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
+ event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
+ fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
+ fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
+ if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
+ xi2ProcessTouch(xiDeviceEvent, platformWindow);
+ break;
}
-#endif // XCB_USE_XINPUT22
}
+#endif // XCB_USE_XINPUT22
}
#ifdef XCB_USE_XINPUT22
@@ -967,15 +974,6 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xiEvent);
-#ifdef XCB_USE_XINPUT22
- // Synthesize mouse events since otherwise there are no mouse events from
- // the pen on the XI 2.2+ path.
- if (xi2MouseEvents() && eventListener)
- eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event));
-#else
- Q_UNUSED(eventListener);
-#endif
-
switch (xiEvent->evtype) {
case XI_ButtonPress: {
Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
@@ -1029,9 +1027,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
tabletData->inProximity = true;
tabletData->tool = toolIdToTabletDevice(tool);
tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_TOOL_SERIAL]);
- QWindowSystemInterface::handleTabletEnterProximityEvent(tabletData->tool,
- tabletData->pointerType,
- tabletData->serialId);
+ QWindowSystemInterface::handleTabletEnterProximityEvent(ev->time,
+ tabletData->tool, tabletData->pointerType, tabletData->serialId);
} else {
tabletData->inProximity = false;
tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_ID]);
@@ -1040,9 +1037,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
if (!tabletData->tool)
tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]);
tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_LAST_TOOL_SERIAL]);
- QWindowSystemInterface::handleTabletLeaveProximityEvent(tabletData->tool,
- tabletData->pointerType,
- tabletData->serialId);
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(ev->time,
+ tabletData->tool, tabletData->pointerType, tabletData->serialId);
}
// TODO maybe have a hash of tabletData->deviceId to device data so we can
// look up the tablet name here, and distinguish multiple tablets
@@ -1060,6 +1056,16 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
handled = false;
break;
}
+
+#ifdef XCB_USE_XINPUT22
+ // Synthesize mouse events since otherwise there are no mouse events from
+ // the pen on the XI 2.2+ path.
+ if (xi2MouseEvents() && eventListener)
+ eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event));
+#else
+ Q_UNUSED(eventListener);
+#endif
+
return handled;
}
@@ -1110,13 +1116,14 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
}
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
- tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
+ qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d "
+ "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time,
fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
(int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
- QWindowSystemInterface::handleTabletEvent(window, local, global,
+ QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global,
tabletData.tool, tabletData.pointerType,
tabletData.buttons, pressure,
xTilt, yTilt, tangentialPressure,
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index a3e646ed7a..de23c59a63 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -444,7 +444,7 @@ void QXcbDrag::move(const QPoint &globalPos)
DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
if (w)
- handleEnter(w, &enter);
+ handleEnter(w, &enter, current_proxy_target);
else if (target)
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
waiting_for_status = false;
@@ -665,7 +665,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe)
#endif
-void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event)
+void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy)
{
Q_UNUSED(window);
DEBUG() << "handleEnter" << window;
@@ -677,6 +677,9 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve
return;
xdnd_dragsource = event->data.data32[0];
+ if (!proxy)
+ proxy = xdndProxy(connection(), xdnd_dragsource);
+ current_proxy_target = proxy ? proxy : xdnd_dragsource;
if (event->data.data32[1] & 1) {
// get the types from XdndTypeList
@@ -775,7 +778,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
if (xdnd_dragsource == connection()->clipboard()->owner())
handle_xdnd_status(&response);
else
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
}
@@ -967,7 +970,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
finished.data.data32[1] = response.isAccepted(); // flags
finished.data.data32[2] = toXdndAction(response.acceptedAction());
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
xdnd_dragsource = 0;
@@ -1132,7 +1135,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
}
}
- xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
+ xcb_window_t proxy_target = xdndProxy(connection(), event->requestor);
+ if (!proxy_target)
+ proxy_target = event->requestor;
+
+ xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
}
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 699d402ea6..9584c04238 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -76,7 +76,7 @@ public:
void drop(const QPoint &globalPos) Q_DECL_OVERRIDE;
void endDrag() Q_DECL_OVERRIDE;
- void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event);
+ void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0);
void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index fc06f1a7b0..9cedfa77ad 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -268,7 +268,10 @@ void QXcbIntegration::initialize()
{
// Perform everything that may potentially need the event dispatcher (timers, socket
// notifiers) here instead of the constructor.
- m_inputContext.reset(QPlatformInputContextFactory::create());
+ QString icStr = QPlatformInputContextFactory::requested();
+ if (icStr.isNull())
+ icStr = QLatin1String("compose");
+ m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
}
void QXcbIntegration::moveToScreen(QWindow *window, int screen)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index f9a85cdf44..d751c6d48a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1971,7 +1971,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
// and other messages.
} else if (event->type == atom(QXcbAtom::_COMPIZ_DECOR_PENDING)
|| event->type == atom(QXcbAtom::_COMPIZ_DECOR_REQUEST)
- || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)) {
+ || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)
+ || event->type == atom(QXcbAtom::_COMPIZ_TOOLKIT_ACTION)) {
//silence the _COMPIZ messages for now
} else {
qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type);
@@ -2208,17 +2209,17 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
switch (ev->evtype) {
case XI_ButtonPress:
- qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button);
+ qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d", button, ev->time);
conn->setButton(button, true);
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
break;
case XI_ButtonRelease:
- qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button);
+ qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d", button, ev->time);
conn->setButton(button, false);
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
break;
case XI_Motion:
- qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y);
+ qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d", event_x, event_y, ev->time);
handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time);
break;
default:
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 7d31ac7118..82c1c1de77 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -94,14 +94,14 @@ void QXcbWMSupport::updateVirtualRoots()
int offset = 0;
int remaining = 0;
do {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_ATOM, offset, 1024);
+ xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL);
if (!reply)
break;
remaining = 0;
- if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
+ if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) {
int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t);
xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply);
int s = net_virtual_roots.size();
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index f3be45262b..a15fd51c98 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -231,6 +231,7 @@ public:
QPrintPropertiesDialog::QPrintPropertiesDialog(QAbstractPrintDialog *parent)
: QDialog(parent)
{
+ setWindowTitle(tr("Printer Properties"));
QVBoxLayout *lay = new QVBoxLayout(this);
this->setLayout(lay);
QWidget *content = new QWidget(this);
@@ -803,7 +804,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties()
QString cur = QDir::currentPath();
if (home.at(home.length()-1) != QLatin1Char('/'))
home += QLatin1Char('/');
- if (cur.at(cur.length()-1) != QLatin1Char('/'))
+ if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/'))
cur += QLatin1Char('/');
if (cur.left(home.length()) != home)
cur = home;
diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp
index 710691453a..0ae9464b69 100644
--- a/src/printsupport/kernel/qpaintengine_alpha.cpp
+++ b/src/printsupport/kernel/qpaintengine_alpha.cpp
@@ -376,6 +376,7 @@ QAlphaPaintEnginePrivate::QAlphaPaintEnginePrivate()
m_pic(0),
m_picengine(0),
m_picpainter(0),
+ m_numberOfCachedRects(0),
m_hasalpha(false),
m_alphaPen(false),
m_alphaBrush(false),
@@ -426,7 +427,14 @@ void QAlphaPaintEnginePrivate::addAlphaRect(const QRectF &rect)
bool QAlphaPaintEnginePrivate::canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const
{
- return somethingInRectHasAlpha && m_dirtyrgn.intersects(rect.toAlignedRect());
+ if (somethingInRectHasAlpha) {
+ if (m_dirtyRects.count() != m_numberOfCachedRects) {
+ m_cachedDirtyRgn.setRects(m_dirtyRects.constData(), m_dirtyRects.count());
+ m_numberOfCachedRects = m_dirtyRects.count();
+ }
+ return m_cachedDirtyRgn.intersects(rect.toAlignedRect());
+ }
+ return false;
}
void QAlphaPaintEnginePrivate::drawAlphaImage(const QRectF &rect)
diff --git a/src/printsupport/kernel/qpaintengine_alpha_p.h b/src/printsupport/kernel/qpaintengine_alpha_p.h
index 2becad7379..49a9938e56 100644
--- a/src/printsupport/kernel/qpaintengine_alpha_p.h
+++ b/src/printsupport/kernel/qpaintengine_alpha_p.h
@@ -99,7 +99,9 @@ public:
QRegion m_alphargn;
QRegion m_cliprgn;
- QRegion m_dirtyrgn;
+ mutable QRegion m_cachedDirtyRgn;
+ mutable int m_numberOfCachedRects;
+ QVector<QRect> m_dirtyRects;
bool m_hasalpha;
bool m_alphaPen;
@@ -115,7 +117,7 @@ public:
QPen m_pen;
void addAlphaRect(const QRectF &rect);
- void addDirtyRect(const QRectF &rect) { m_dirtyrgn |= rect.toAlignedRect(); }
+ void addDirtyRect(const QRectF &rect) { m_dirtyRects.append(rect.toAlignedRect()); }
bool canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const;
QRectF addPenWidth(const QPainterPath &path);
diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp
index 5c67652cdb..f4e40b6582 100644
--- a/src/sql/drivers/psql/qsql_psql.cpp
+++ b/src/sql/drivers/psql/qsql_psql.cpp
@@ -1332,6 +1332,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
if (r.isEmpty())
r = QSqlDriver::formatValue(field, trimStrings);
break;
+ case QVariant::Uuid:
+ r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\'');
+ break;
default:
r = QSqlDriver::formatValue(field, trimStrings);
break;
diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp
index ee212a49d0..f6d2c20a4a 100644
--- a/src/testlib/qbenchmarkmetric.cpp
+++ b/src/testlib/qbenchmarkmetric.cpp
@@ -79,7 +79,6 @@
*/
/*!
- \relates QTest
\since 4.7
Returns the enum value \a metric as a character string.
*/
@@ -152,7 +151,6 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric)
};
/*!
- \relates QTest
\since 4.7
Retuns the units of measure for the specified \a metric.
*/
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 1d8b195907..8da16af91e 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -51,6 +51,9 @@
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
+#ifdef QT_NETWORK_LIB
+# include <QtNetwork/qhostaddress.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -162,6 +165,23 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+#ifdef QT_NETWORK_LIB
+template<> inline char *toString(const QHostAddress &addr)
+{
+ switch (addr.protocol()) {
+ case QAbstractSocket::UnknownNetworkLayerProtocol:
+ return qstrdup("<unknown address (parse error)>");
+ case QAbstractSocket::AnyIPProtocol:
+ return qstrdup("QHostAddress::Any");
+ case QAbstractSocket::IPv4Protocol:
+ case QAbstractSocket::IPv6Protocol:
+ break;
+ }
+
+ return qstrdup(addr.toString().toLatin1().constData());
+}
+#endif
+
template<>
inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index ae83432eb8..000470e9e5 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -76,6 +76,7 @@
#if defined(Q_OS_LINUX)
#include <sys/types.h>
#include <unistd.h>
+#include <fcntl.h>
#endif
#ifdef Q_OS_WIN
@@ -271,7 +272,7 @@ static void stackTrace()
The QTRY_VERIFY2_WITH_TIMEOUT macro is similar to QTRY_VERIFY_WITH_TIMEOUT()
except that it outputs a verbose \a message when \a condition is still false
- after the specified timeout. The \a message is a plain C string.
+ after the specified \a timeout. The \a message is a plain C string.
Example:
\code
@@ -2213,9 +2214,11 @@ static bool qInvokeTestMethod(const char *slotName, const char *data, WatchDog *
QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0)
: table.testData(curDataIndex));
- watchDog->beginTest();
+ if (watchDog)
+ watchDog->beginTest();
qInvokeTestMethodDataEntry(slot);
- watchDog->testFinished();
+ if (watchDog)
+ watchDog->testFinished();
if (data)
break;
@@ -2487,6 +2490,37 @@ char *toPrettyUnicode(const ushort *p, int length)
return buffer.take();
}
+static bool debuggerPresent()
+{
+#if defined(Q_OS_LINUX)
+ int fd = open("/proc/self/status", O_RDONLY);
+ if (fd == -1)
+ return false;
+ char buffer[2048];
+ ssize_t size = read(fd, buffer, sizeof(buffer));
+ if (size == -1) {
+ close(fd);
+ return false;
+ }
+ buffer[size] = 0;
+ const char tracerPidToken[] = "\nTracerPid:";
+ char *tracerPid = strstr(buffer, tracerPidToken);
+ if (!tracerPid) {
+ close(fd);
+ return false;
+ }
+ tracerPid += sizeof(tracerPidToken);
+ long int pid = strtol(tracerPid, &tracerPid, 10);
+ close(fd);
+ return pid != 0;
+#elif defined(Q_OS_WIN)
+ return IsDebuggerPresent();
+#else
+ // TODO
+ return false;
+#endif
+}
+
static void qInvokeTestMethods(QObject *testObject)
{
const QMetaObject *metaObject = testObject->metaObject();
@@ -2496,7 +2530,9 @@ static void qInvokeTestMethods(QObject *testObject)
QTestTable::globalTestTable();
invokeMethod(testObject, "initTestCase_data()");
- WatchDog watchDog;
+ QScopedPointer<WatchDog> watchDog;
+ if (!debuggerPresent())
+ watchDog.reset(new WatchDog);
if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) {
invokeMethod(testObject, "initTestCase()");
@@ -2512,7 +2548,7 @@ static void qInvokeTestMethods(QObject *testObject)
if (QTest::testFuncs) {
for (int i = 0; i != QTest::testFuncCount; i++) {
if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).methodSignature().constData(),
- QTest::testFuncs[i].data(), &watchDog)) {
+ QTest::testFuncs[i].data(), watchDog.data())) {
break;
}
}
@@ -2525,7 +2561,7 @@ static void qInvokeTestMethods(QObject *testObject)
for (int i = 0; i != methodCount; i++) {
if (!isValidSlot(testMethods[i]))
continue;
- if (!qInvokeTestMethod(testMethods[i].methodSignature().constData(), 0, &watchDog))
+ if (!qInvokeTestMethod(testMethods[i].methodSignature().constData(), 0, watchDog.data()))
break;
}
delete[] testMethods;
@@ -2760,33 +2796,34 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
appName[0] = 0;
const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress;
- fprintf(stderr, "A crash occurred in %s.\n\n"
- "Exception address: 0x%p\n"
- "Exception code : 0x%lx\n",
- appName, exceptionAddress, exInfo->ExceptionRecord->ExceptionCode);
+ printf("A crash occurred in %s.\n\n"
+ "Exception address: 0x%p\n"
+ "Exception code : 0x%lx\n",
+ appName, exceptionAddress, exInfo->ExceptionRecord->ExceptionCode);
DebugSymbolResolver resolver(GetCurrentProcess());
if (resolver.isValid()) {
DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress));
if (exceptionSymbol.name) {
- fprintf(stderr, "Nearby symbol : %s\n", exceptionSymbol.name);
+ printf("Nearby symbol : %s\n", exceptionSymbol.name);
delete [] exceptionSymbol.name;
}
void *stack[maxStackFrames];
- fputs("\nStack:\n", stderr);
+ fputs("\nStack:\n", stdout);
const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL);
for (unsigned f = 0; f < frameCount; ++f) {
DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[f]));
if (symbol.name) {
- fprintf(stderr, "#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address);
+ printf("#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address);
delete [] symbol.name;
} else {
- fprintf(stderr, "#%3u: Unable to obtain symbol\n", f + 1);
+ printf("#%3u: Unable to obtain symbol\n", f + 1);
}
}
}
- fputc('\n', stderr);
+ fputc('\n', stdout);
+ fflush(stdout);
return EXCEPTION_EXECUTE_HANDLER;
}
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index 82dd6fa098..d73658d8fc 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -61,7 +61,7 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int
namespace QTest
{
- enum KeyAction { Press, Release, Click };
+ enum KeyAction { Press, Release, Click, Shortcut };
static void simulateEvent(QWindow *window, bool press, int code,
Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1)
@@ -95,6 +95,12 @@ namespace QTest
bool repeat = false;
+ if (action == Shortcut) {
+ int timestamp = 0;
+ qt_sendShortcutOverrideEvent(window, timestamp, code, modifier, text, repeat);
+ return;
+ }
+
if (action == Press) {
if (modifier & Qt::ShiftModifier)
simulateEvent(window, true, Qt::Key_Shift, Qt::KeyboardModifiers(), QString(), false, delay);
diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp
index beb0bae291..ae6bbaf5da 100644
--- a/src/tools/qdoc/config.cpp
+++ b/src/tools/qdoc/config.cpp
@@ -53,6 +53,8 @@ QString ConfigStrings::BASE = QStringLiteral("base");
QString ConfigStrings::BASEDIR = QStringLiteral("basedir");
QString ConfigStrings::BUILDVERSION = QStringLiteral("buildversion");
QString ConfigStrings::CODEINDENT = QStringLiteral("codeindent");
+QString ConfigStrings::CODEPREFIX = QStringLiteral("codeprefix");
+QString ConfigStrings::CODESUFFIX = QStringLiteral("codesuffix");
QString ConfigStrings::CPPCLASSESPAGE = QStringLiteral("cppclassespage");
QString ConfigStrings::DEFINES = QStringLiteral("defines");
QString ConfigStrings::DEPENDS = QStringLiteral("depends");
diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h
index 8d6a124bd1..740568ca0c 100644
--- a/src/tools/qdoc/config.h
+++ b/src/tools/qdoc/config.h
@@ -165,6 +165,8 @@ struct ConfigStrings
static QString BASEDIR;
static QString BUILDVERSION;
static QString CODEINDENT;
+ static QString CODEPREFIX;
+ static QString CODESUFFIX;
static QString CPPCLASSESPAGE;
static QString DEFINES;
static QString DEPENDS;
@@ -241,6 +243,8 @@ struct ConfigStrings
#define CONFIG_BASEDIR ConfigStrings::BASEDIR
#define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION
#define CONFIG_CODEINDENT ConfigStrings::CODEINDENT
+#define CONFIG_CODEPREFIX ConfigStrings::CODEPREFIX
+#define CONFIG_CODESUFFIX ConfigStrings::CODESUFFIX
#define CONFIG_CPPCLASSESPAGE ConfigStrings::CPPCLASSESPAGE
#define CONFIG_DEFINES ConfigStrings::DEFINES
#define CONFIG_DEPENDS ConfigStrings::DEPENDS
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index 0f70777256..5d2a2c90d0 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -924,10 +924,19 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc,
else if (command == COMMAND_RELATES) {
QStringList path = arg.split("::");
Node* n = qdb_->findRelatesNode(path);
- if (!n)
- doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
- else
+ if (!n) {
+ // Store just a string to write to the index file
+ if (Generator::preparing())
+ node->setRelates(arg);
+ else
+ doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES));
+
+ }
+ else if (node->parent() != n)
node->setRelates(static_cast<Aggregate*>(n));
+ else
+ doc.location().warning(tr("Invalid use of '\\%1' (already a member of '%2')")
+ .arg(COMMAND_RELATES, arg));
}
else if (command == COMMAND_CONTENTSPAGE) {
setLink(node, Node::ContentsLink, arg);
diff --git a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
index 2472b0f4fb..d490f8549a 100644
--- a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc
@@ -185,6 +185,13 @@
to adjust the appearance of certain types of HTML elements, this
level of indentation is not always required.
+ \target codeprefix-variable
+ \target codesuffix-variable
+ \section1 codeprefix, codesuffix
+
+ The \c codeprefix and \c codesuffix variables specify a pair of
+ strings that each code snippet is enclosed in.
+
\target defines-variable
\section1 defines
@@ -727,6 +734,18 @@
command to render a superscript asterisk, but only when generating
HTML.
+ A macro can also take up to seven parameters:
+
+ \badcode
+ macro.hello = "Hello \1!"
+ \endcode
+
+ Parameters are passed to macros the same way as to other commands:
+
+ \badcode
+ \hello World
+ \endcode
+
See also \l {alias-variable} {alias}.
\target manifestmeta-variable
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 7dfbbb1cb8..5037d95640 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -807,6 +807,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
QVector<Parameter>::ConstIterator p = func->parameters().constBegin();
while (p != func->parameters().constEnd()) {
if ((*p).name().isEmpty() && (*p).dataType() != QLatin1String("...")
+ && (*p).dataType() != QLatin1String("void")
&& func->name() != QLatin1String("operator++")
&& func->name() != QLatin1String("operator--")) {
node->doc().location().warning(tr("Missing parameter name"));
@@ -2114,11 +2115,14 @@ void Generator::terminateGenerator()
Trims trailing whitespace off the \a string and returns
the trimmed string.
*/
-QString Generator::trimmedTrailing(const QString& string)
+QString Generator::trimmedTrailing(const QString& string, const QString &prefix, const QString &suffix)
{
QString trimmed = string;
while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
trimmed.truncate(trimmed.length() - 1);
+
+ trimmed.append(suffix);
+ trimmed.prepend(prefix);
return trimmed;
}
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index 6c44cd189c..025f516986 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -139,7 +139,9 @@ protected:
static QString outputSuffix(const Node* node);
static void singularPlural(Text& text, const NodeList& nodes);
static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
- static QString trimmedTrailing(const QString &string);
+ static QString trimmedTrailing(const QString &string,
+ const QString &prefix,
+ const QString &suffix);
static QString sinceTitles[];
void initializeTextOutput();
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 18d2af5810..eaa6de42ef 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -220,8 +220,9 @@ void HtmlGenerator::initializeGenerator(const Config &config)
++edition;
}
- // The following line was changed to fix QTBUG-27798
- //codeIndent = config.getInt(CONFIG_CODEINDENT);
+ codeIndent = config.getInt(CONFIG_CODEINDENT); // QTBUG-27798
+ codePrefix = config.getString(CONFIG_CODEPREFIX);
+ codeSuffix = config.getString(CONFIG_CODESUFFIX);
/*
The help file write should be allocated once and only once
@@ -584,23 +585,23 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break;
case Atom::Code:
out() << "<pre class=\"cpp\">"
- << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+ << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
<< "</pre>\n";
break;
case Atom::Qml:
out() << "<pre class=\"qml\">"
- << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+ << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
<< "</pre>\n";
break;
case Atom::JavaScript:
out() << "<pre class=\"js\">"
- << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+ << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
<< "</pre>\n";
break;
case Atom::CodeNew:
out() << "<p>you can rewrite it as</p>\n"
<< "<pre class=\"cpp\">"
- << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+ << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
<< "</pre>\n";
break;
case Atom::CodeOld:
@@ -608,7 +609,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
// fallthrough
case Atom::CodeBad:
out() << "<pre class=\"cpp\">"
- << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))))
+ << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))), codePrefix, codeSuffix)
<< "</pre>\n";
break;
case Atom::DivLeft:
@@ -2370,7 +2371,7 @@ void HtmlGenerator::generateIncludes(const Aggregate *inner, CodeMarker *marker)
out() << "<pre class=\"cpp\">"
<< trimmedTrailing(highlightedCode(indent(codeIndent,
marker->markedUpIncludes(inner->includes())),
- inner))
+ inner), codePrefix, codeSuffix)
<< "</pre>";
}
}
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index d46fc9ebee..bbb8f12e3e 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -233,6 +233,8 @@ private:
QHash<QString, QString> refMap;
int codeIndent;
+ QString codePrefix;
+ QString codeSuffix;
HelpProjectWriter *helpProjectWriter;
bool inObsoleteLink;
QRegExp funcLeftParen;
diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp
index 3833cbb5dd..d6e00b4833 100644
--- a/src/tools/qdoc/main.cpp
+++ b/src/tools/qdoc/main.cpp
@@ -729,7 +729,7 @@ int main(int argc, char **argv)
Location::startLoggingProgress();
/*
- The default indent for code is 4.
+ The default indent for code is 0.
The default value for false is 0.
The default supported file extensions are cpp, h, qdoc and qml.
The default language is c++.
@@ -738,7 +738,7 @@ int main(int argc, char **argv)
And those are all the default values for configuration variables.
*/
if (defaults.isEmpty()) {
- defaults.insert(CONFIG_CODEINDENT, QLatin1String("4"));
+ defaults.insert(CONFIG_CODEINDENT, QLatin1String("0"));
defaults.insert(CONFIG_FALSEHOODS, QLatin1String("0"));
defaults.insert(CONFIG_FILEEXTENSIONS, QLatin1String("*.cpp *.h *.qdoc *.qml"));
defaults.insert(CONFIG_LANGUAGE, QLatin1String("Cpp"));
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index 2e9e7e76be..9740f984f5 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -106,8 +106,27 @@ Node::~Node()
{
if (parent_)
parent_->removeChild(this);
+
if (relatesTo_)
+ removeRelates();
+}
+
+/*!
+ Removes this node from the aggregate's list of related
+ nodes, or if this node has created a dummy "relates"
+ aggregate, deletes it.
+*/
+void Node::removeRelates()
+{
+ if (!relatesTo_)
+ return;
+
+ if (relatesTo_->isDocumentNode() && !relatesTo_->parent()) {
+ delete relatesTo_;
+ relatesTo_ = 0;
+ } else {
relatesTo_->removeRelated(this);
+ }
}
/*!
@@ -463,11 +482,22 @@ bool Node::fromFlagValue(FlagValue fv, bool defaultValue)
*/
void Node::setRelates(Aggregate *pseudoParent)
{
- if (relatesTo_) {
- relatesTo_->removeRelated(this);
- }
+ if (pseudoParent == parent())
+ return;
+
+ removeRelates();
relatesTo_ = pseudoParent;
- pseudoParent->related_.append(this);
+ pseudoParent->addRelated(this);
+}
+
+/*!
+ Sets the (unresolved) entity \a name that this node relates to.
+ */
+void Node::setRelates(const QString& name)
+{
+ removeRelates();
+ // Create a dummy aggregate for writing the name into the index
+ relatesTo_ = new DocumentNode(0, name, Node::NoSubtype, Node::NoPageType);
}
/*!
@@ -711,8 +741,8 @@ void Node::setLocation(const Location& t)
*/
Aggregate::~Aggregate()
{
- deleteChildren();
removeFromRelated();
+ deleteChildren();
}
/*!
@@ -945,8 +975,9 @@ void Aggregate::makeUndocumentedChildrenInternal()
}
/*!
- This is where we should set the overload numbers, including
- the related non-members.
+ This is where we set the overload numbers for function nodes.
+ \note Overload numbers for related non-members are handled
+ separately.
*/
void Aggregate::normalizeOverloads()
{
@@ -1018,23 +1049,6 @@ void Aggregate::normalizeOverloads()
++p;
}
/*
- Add the related non-members here.
- */
- if (!related_.isEmpty()) {
- foreach (Node* n, related_) {
- if (n->isFunction()) {
- FunctionNode* fn = static_cast<FunctionNode*>(n);
- QMap<QString, Node *>::Iterator p = primaryFunctionMap_.find(fn->name());
- if (p != primaryFunctionMap_.end()) {
- secondaryFunctionMap_[fn->name()].append(fn);
- fn->setOverloadNumber(secondaryFunctionMap_[fn->name()].size());
- }
- else
- fn->setOverloadNumber(0);
- }
- }
- }
- /*
Recursive part.
*/
NodeList::ConstIterator c = childNodes().constBegin();
@@ -1061,7 +1075,13 @@ void Aggregate::removeFromRelated()
*/
void Aggregate::deleteChildren()
{
- NodeList childrenCopy = children_; // `children_` will be changed in ~Node()
+ NodeList childrenCopy = children_;
+ // Clear internal collections before deleting child nodes
+ children_.clear();
+ childMap_.clear();
+ enumChildren_.clear();
+ primaryFunctionMap_.clear();
+ secondaryFunctionMap_.clear();
qDeleteAll(childrenCopy);
}
@@ -1188,7 +1208,9 @@ bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
void Aggregate::addChild(Node *child)
{
children_.append(child);
- if ((child->type() == Function) || (child->type() == QmlMethod)) {
+ if (child->type() == Function
+ || child->type() == QmlMethod
+ || child->type() == QmlSignal) {
FunctionNode *func = static_cast<FunctionNode*>(child);
QString name = func->name();
if (!primaryFunctionMap_.contains(name)) {
@@ -1233,7 +1255,9 @@ void Aggregate::removeChild(Node *child)
{
children_.removeAll(child);
enumChildren_.removeAll(child);
- if (child->type() == Function) {
+ if (child->type() == Function
+ || child->type() == QmlMethod
+ || child->type() == QmlSignal) {
QMap<QString, Node *>::Iterator primary = primaryFunctionMap_.find(child->name());
NodeList& overloads = secondaryFunctionMap_[child->name()];
if (primary != primaryFunctionMap_.end() && *primary == child) {
@@ -1333,10 +1357,49 @@ QString Node::physicalModuleName() const
}
/*!
+ Removes a node from the list of nodes related to this one.
+ If it is a function node, also remove from the primary/
+ secondary function maps.
*/
void Aggregate::removeRelated(Node *pseudoChild)
{
related_.removeAll(pseudoChild);
+
+ if (pseudoChild->isFunction()) {
+ QMap<QString, Node *>::Iterator p = primaryFunctionMap_.find(pseudoChild->name());
+ while (p != primaryFunctionMap_.end()) {
+ if (p.value() == pseudoChild) {
+ primaryFunctionMap_.erase(p);
+ break;
+ }
+ ++p;
+ }
+ NodeList& overloads = secondaryFunctionMap_[pseudoChild->name()];
+ overloads.removeAll(pseudoChild);
+ }
+}
+
+/*!
+ Adds \a pseudoChild to the list of nodes related to this one. Resolve a correct
+ overload number for a related non-member function.
+ */
+void Aggregate::addRelated(Node *pseudoChild)
+{
+ related_.append(pseudoChild);
+
+ if (pseudoChild->isFunction()) {
+ FunctionNode* fn = static_cast<FunctionNode*>(pseudoChild);
+ if (primaryFunctionMap_.contains(pseudoChild->name())) {
+ secondaryFunctionMap_[pseudoChild->name()].append(pseudoChild);
+ fn->setOverloadNumber(secondaryFunctionMap_[pseudoChild->name()].size());
+ fn->setOverloadFlag(true);
+ }
+ else {
+ primaryFunctionMap_.insert(pseudoChild->name(), pseudoChild);
+ fn->setOverloadNumber(0);
+ fn->setOverloadFlag(false);
+ }
+ }
}
/*!
@@ -2096,7 +2159,7 @@ QString FunctionNode::signature(bool values) const
PropertyNode::FunctionRole PropertyNode::role(const FunctionNode* fn) const
{
for (int i=0; i<4; i++) {
- if (functions_[i].contains((Node*)fn))
+ if (functions_[i].contains(const_cast<FunctionNode*>(fn)))
return (FunctionRole) i;
}
return Notifier;
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 596a71b6d5..6262cee0ab 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -178,6 +178,7 @@ public:
void setThreadSafeness(ThreadSafeness t) { safeness_ = (unsigned char) t; }
void setSince(const QString &since);
void setRelates(Aggregate* pseudoParent);
+ void setRelates(const QString &name);
void setPhysicalModuleName(const QString &name) { physicalModuleName_ = name; }
void setUrl(const QString& url) { url_ = url; }
void setTemplateStuff(const QString &t) { templateStuff_ = t; }
@@ -336,6 +337,7 @@ public:
protected:
Node(NodeType type, Aggregate* parent, const QString& name);
+ void removeRelates();
private:
@@ -421,6 +423,7 @@ private:
static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2);
void removeRelated(Node* pseudoChild);
+ void addRelated(Node* pseudoChild);
QString outputFileName_;
QStringList pageKeywds;
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index aef785f30e..ca1648ec2f 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -276,7 +276,7 @@ const QVector<Tree*>& QDocForest::indexSearchOrder()
NamespaceNode* QDocForest::newIndexTree(const QString& module)
{
primaryTree_ = new Tree(module, qdb_);
- forest_.insert(module, primaryTree_);
+ forest_.insert(module.toLower(), primaryTree_);
return primaryTree_->root();
}
@@ -306,15 +306,12 @@ const Node* QDocForest::findNodeForTarget(QStringList& targetPath,
{
int flags = SearchBaseClasses | SearchEnumValues;
- QString entity = targetPath.at(0);
- targetPath.removeFirst();
+ QString entity = targetPath.takeFirst();
QStringList entityPath = entity.split("::");
QString target;
- if (!targetPath.isEmpty()) {
- target = targetPath.at(0);
- targetPath.removeFirst();
- }
+ if (!targetPath.isEmpty())
+ target = targetPath.takeFirst();
foreach (Tree* t, searchOrder()) {
const Node* n = t->findNodeForTarget(entityPath, target, relative, flags, genus, ref);
@@ -1295,6 +1292,10 @@ void QDocDatabase::resolveIssues() {
resolveQmlInheritance(primaryTreeRoot());
primaryTree()->resolveTargets(primaryTreeRoot());
primaryTree()->resolveCppToQmlLinks();
+ if (!Generator::singleExec()) {
+ QDocIndexFiles::qdocIndexFiles()->resolveRelates();
+ QDocIndexFiles::destroyQDocIndexFiles();
+ }
}
void QDocDatabase::resolveStuff()
@@ -1305,7 +1306,6 @@ void QDocDatabase::resolveStuff()
primaryTree()->resolveCppToQmlLinks();
primaryTree()->resolveUsingClauses();
resolveNamespaces();
- primaryTreeRoot()->normalizeOverloads();
}
/*!
@@ -1495,7 +1495,6 @@ void QDocDatabase::readIndexes(const QStringList& t)
qDebug() << "This index file is already in memory:" << f;
}
QDocIndexFiles::qdocIndexFiles()->readIndexes(indexFiles);
- QDocIndexFiles::destroyQDocIndexFiles();
}
/*!
@@ -1699,35 +1698,26 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q
function = first.left(position);
node = domain->findFunctionNode(function, params, 0, genus);
}
- else {
+ if (!node) {
int flags = SearchBaseClasses | SearchEnumValues;
QStringList nodePath = first.split("::");
QString target;
targetPath.removeFirst();
- if (!targetPath.isEmpty()) {
- target = targetPath.at(0);
- targetPath.removeFirst();
- }
+ if (!targetPath.isEmpty())
+ target = targetPath.takeFirst();
if (relative && relative->tree()->physicalModuleName() != domain->physicalModuleName())
relative = 0;
- node = domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
- return node;
+ return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref);
}
}
else {
- if (first.endsWith(".html")) {
+ if (first.endsWith(".html"))
node = findNodeByNameAndType(QStringList(first), Node::Document);
- // the path may also refer to an example file with .html extension
- if (!node && first.contains("/"))
- return findNodeForTarget(targetPath, relative, genus, ref);
- }
else if (first.endsWith(QChar(')'))) {
node = findFunctionNode(first, relative, genus);
}
- else {
- node = findNodeForTarget(targetPath, relative, genus, ref);
- return node;
- }
+ if (!node)
+ return findNodeForTarget(targetPath, relative, genus, ref);
}
if (node && ref.isEmpty()) {
diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp
index 8db901bbc7..fc262d9834 100644
--- a/src/tools/qdoc/qdocindexfiles.cpp
+++ b/src/tools/qdoc/qdocindexfiles.cpp
@@ -100,6 +100,7 @@ void QDocIndexFiles::destroyQDocIndexFiles()
*/
void QDocIndexFiles::readIndexes(const QStringList& indexFiles)
{
+ relatedList_.clear();
foreach (const QString& indexFile, indexFiles) {
QString msg = "Loading index file: " + indexFile;
Location::logToStdErr(msg);
@@ -146,9 +147,7 @@ void QDocIndexFiles::readIndexFile(const QString& path)
indexUrl = installDir.relativeFilePath(path).section('/', 0, -2);
}
project_ = attrs.value(QLatin1String("project")).toString();
-
basesList_.clear();
- relatedList_.clear();
NamespaceNode* root = qdb_->newIndexTree(project_);
@@ -730,17 +729,37 @@ void QDocIndexFiles::resolveIndex()
pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString());
}
}
+ // No longer needed.
+ basesList_.clear();
+}
+
+/*
+ Goes though the list of nodes that are related to other aggregates
+ that were read from all index files, and tries to find the aggregate
+ nodes from the database. Calls the node's setRelates() for each
+ aggregate that is found in the local module (primary tree).
+
+ This function is meant to be called before starting the doc generation,
+ after all the index files are read.
+ */
+void QDocIndexFiles::resolveRelates()
+{
+ if (relatedList_.isEmpty())
+ return;
+
+ // Restrict searching only to the local (primary) tree
+ QVector<Tree*> searchOrder = qdb_->searchOrder();
+ qdb_->setLocalSearch();
QPair<FunctionNode*,QString> relatedPair;
foreach (relatedPair, relatedList_) {
QStringList path = relatedPair.second.split("::");
Node* n = qdb_->findRelatesNode(path);
if (n)
- relatedPair.first->setRelates(static_cast<ClassNode*>(n));
+ relatedPair.first->setRelates(static_cast<Aggregate*>(n));
}
-
- // No longer needed.
- basesList_.clear();
+ // Restore original search order
+ qdb_->setSearchOrder(searchOrder);
relatedList_.clear();
}
diff --git a/src/tools/qdoc/qdocindexfiles.h b/src/tools/qdoc/qdocindexfiles.h
index 1b9b6afc40..67a7e7226e 100644
--- a/src/tools/qdoc/qdocindexfiles.h
+++ b/src/tools/qdoc/qdocindexfiles.h
@@ -65,6 +65,7 @@ class QDocIndexFiles
void readIndexFile(const QString& path);
void readIndexSection(QXmlStreamReader &reader, Node* current, const QString& indexUrl);
void resolveIndex();
+ void resolveRelates();
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index d64903e61e..f8f88e6b91 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -721,12 +721,8 @@ const Node* Tree::findNodeForTarget(const QStringList& path,
QString& ref) const
{
const Node* node = 0;
- QString p;
- if (path.size() > 1)
- p = path.join(QString("::"));
- else if ((genus == Node::DontCare) || (genus == Node::DOC)) {
- p = path.at(0);
- node = findDocumentNodeByTitle(p);
+ if ((genus == Node::DontCare) || (genus == Node::DOC)) {
+ node = findDocumentNodeByTitle(path.at(0));
if (node) {
if (!target.isEmpty()) {
ref = getRef(target, node);
@@ -737,7 +733,8 @@ const Node* Tree::findNodeForTarget(const QStringList& path,
return node;
}
}
- node = findUnambiguousTarget(p, ref);
+
+ node = findUnambiguousTarget(path.join(QStringLiteral("::")), ref);
if (node) {
if (!target.isEmpty()) {
ref = getRef(target, node);
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 054c220b84..d04241fee0 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -243,7 +243,7 @@ void QDialogPrivate::deletePlatformHelper()
\section1 Escape Key
If the user presses the Esc key in a dialog, QDialog::reject()
- will be called. This will cause the window to close: The \l{QCloseEvent}{close event} cannot be \l{QCloseEvent::ignore()}{ignored}.
+ will be called. This will cause the window to close: The \l{QCloseEvent}{close event} cannot be \l{QEvent::ignore()}{ignored}.
\section1 Extensibility
@@ -565,7 +565,7 @@ int QDialog::exec()
last window closed, the QApplication::lastWindowClosed() signal is
emitted.
- \sa accept(), reject(), QApplication::activeWindow(), QApplication::quit()
+ \sa accept(), reject(), QApplication::activeWindow(), QCoreApplication::quit()
*/
void QDialog::done(int r)
diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp
index be3c060ba1..f883705cc3 100644
--- a/src/widgets/dialogs/qsidebar.cpp
+++ b/src/widgets/dialogs/qsidebar.cpp
@@ -60,6 +60,8 @@ void QSideBarDelegate::initStyleOption(QStyleOptionViewItem *option,
}
/*!
+ \internal
+ \class QUrlModel
QUrlModel lets you have indexes from a QFileSystemModel to a list. When QFileSystemModel
changes them QUrlModel will automatically update.
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index 6a1c0eb592..8b9ea95cf3 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -1347,7 +1347,6 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
}
if (info.watermark && !info.sideWidget) {
minimumSize.setHeight(mainLayout->totalSizeHint().height());
- maximumSize.setHeight(mainLayout->totalSizeHint().height());
}
if (q->minimumWidth() == minimumWidth) {
minimumWidth = minimumSize.width();
diff --git a/src/widgets/doc/src/model-view-programming.qdoc b/src/widgets/doc/src/model-view-programming.qdoc
index 098bb39fe2..0032e77c6a 100644
--- a/src/widgets/doc/src/model-view-programming.qdoc
+++ b/src/widgets/doc/src/model-view-programming.qdoc
@@ -2301,7 +2301,7 @@
{fetchMore()} must be reimplemented as their default implementation returns
false and does nothing.
- \keyword Model/View Classes
+ \target Model/View Classes
\section1 The Model/View Classes
These classes use the model/view design pattern in which the
diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
index 3f093ab2d6..60281ce109 100644
--- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc
@@ -197,7 +197,7 @@
\section2 Stretch Factors
- \keyword stretch factor
+ \target stretch factor
Widgets are normally created without any stretch factor set. When they are
laid out in a layout the widgets are given a share of space in accordance
diff --git a/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc b/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc
index 0e52944bb0..6e58fe4499 100644
--- a/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc
+++ b/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc
@@ -78,7 +78,7 @@
design ideas. Creating designs visually and reading the code generated by
\l{uic} is a great way to learn Qt!
- \keyword window geometry
+ \target window geometry
\section1 Window Geometry
QWidget provides several functions that deal with a widget's
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 0259ce216b..5f5c402a4a 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -1425,10 +1425,13 @@ QGraphicsItem::~QGraphicsItem()
QObjectPrivate *p = QObjectPrivate::get(o);
p->wasDeleted = true;
if (p->declarativeData) {
- if (QAbstractDeclarativeData::destroyed)
- QAbstractDeclarativeData::destroyed(p->declarativeData, o);
- if (QAbstractDeclarativeData::destroyed_qml1)
- QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
+ if (static_cast<QAbstractDeclarativeDataImpl*>(p->declarativeData)->ownedByQml1) {
+ if (QAbstractDeclarativeData::destroyed_qml1)
+ QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
+ } else {
+ if (QAbstractDeclarativeData::destroyed)
+ QAbstractDeclarativeData::destroyed(p->declarativeData, o);
+ }
p->declarativeData = 0;
}
}
diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
index 08ea1ea0e3..edb0f4e0ff 100644
--- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp
@@ -879,6 +879,19 @@ bool QGraphicsProxyWidget::event(QEvent *event)
break;
}
#endif
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->widget, event);
+ else
+ QApplication::sendEvent(d->widget, event);
+
+ if (event->isAccepted())
+ return true;
+
+ break;
+ }
default:
break;
}
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 9b3e270fdd..57092a7cdc 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -433,6 +433,9 @@ void QTreeView::setRootIsDecorated(bool show)
The height is obtained from the first item in the view. It is updated
when the data changes on that item.
+ \note If the editor size hint is bigger than the cell size hint, then the
+ size hint of the editor will be used.
+
By default, this property is \c false.
*/
bool QTreeView::uniformRowHeights() const
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 95c4877eb9..1563d020b6 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -1270,7 +1270,7 @@ QAction::MenuRole QAction::menuRole() const
For example:
\snippet code/src_gui_kernel_qaction.cpp 0
- \sa QAction::icon, QApplication::setAttribute()
+ \sa QAction::icon, QCoreApplication::setAttribute()
*/
void QAction::setIconVisibleInMenu(bool visible)
{
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index f82fac836a..148ed61424 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -339,8 +339,7 @@ void QApplicationPrivate::createEventDispatcher()
\li Miscellaneous
\li closeAllWindows(),
startingUp(),
- closingDown(),
- type().
+ closingDown().
\endtable
\sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings
@@ -558,7 +557,7 @@ void QApplicationPrivate::process_cmdline()
and will make the application wait until a debugger connects to it.
\endlist
- \sa arguments()
+ \sa QCoreApplication::arguments()
*/
#ifdef Q_QDOC
@@ -1906,7 +1905,7 @@ bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows
if (!w->isVisible() || w->data->is_closing)
break;
QWindow *window = w->windowHandle();
- if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion.
+ if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
return false;
if (window)
processedWindows->append(window);
@@ -1918,7 +1917,7 @@ bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows
if (w->isVisible() && w->windowType() != Qt::Desktop &&
!w->testAttribute(Qt::WA_DontShowOnScreen) && !w->data->is_closing) {
QWindow *window = w->windowHandle();
- if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion.
+ if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
return false;
if (window)
processedWindows->append(window);
@@ -1951,7 +1950,7 @@ bool QApplicationPrivate::tryCloseAllWindows()
\l quitOnLastWindowClosed to false.
\sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(),
- QWidget::closeEvent(), lastWindowClosed(), quit(), topLevelWidgets(),
+ QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(), topLevelWidgets(),
QWidget::isWindow()
*/
void QApplication::closeAllWindows()
@@ -2969,8 +2968,8 @@ int QApplication::startDragDistance()
application will have time to exit its event loop and execute code at the
end of the \c{main()} function, after the QApplication::exec() call.
- \sa quitOnLastWindowClosed, quit(), exit(), processEvents(),
- QCoreApplication::exec()
+ \sa quitOnLastWindowClosed, QCoreApplication::quit(), QCoreApplication::exit(),
+ QCoreApplication::processEvents(), QCoreApplication::exec()
*/
int QApplication::exec()
{
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 94716025b9..b88b3cc61d 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -134,6 +134,7 @@ QDesktopWidget::QDesktopWidget()
setObjectName(QLatin1String("desktop"));
d->_q_updateScreens();
connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens()));
+ connect(qApp, SIGNAL(primaryScreenChanged(QScreen*)), this, SIGNAL(primaryScreenChanged()));
}
QDesktopWidget::~QDesktopWidget()
diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h
index c0cc4f1b81..f5f7d69887 100644
--- a/src/widgets/kernel/qdesktopwidget.h
+++ b/src/widgets/kernel/qdesktopwidget.h
@@ -77,6 +77,7 @@ Q_SIGNALS:
void resized(int);
void workAreaResized(int);
void screenCountChanged(int);
+ void primaryScreenChanged();
protected:
void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE;
diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc
index 31a99f1acb..d1a6ecabd6 100644
--- a/src/widgets/kernel/qdesktopwidget.qdoc
+++ b/src/widgets/kernel/qdesktopwidget.qdoc
@@ -271,3 +271,17 @@
\sa screenCount
*/
+
+
+/*!
+ \fn void QDesktopWidget::primaryScreenChanged()
+
+ \since 5.6
+
+ \brief This signal is emitted whenever the primary screen changes.
+
+ \note This doesn't mean the QDesktopWidget::primaryScreen index will
+ necessarily be different, but now it will refer to the new primary screen.
+
+ \sa primaryScreen, screenGeometry()
+*/
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index 3d444136e3..03988aab99 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -92,7 +92,7 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
be expressed using hasHeightForWidth(), heightForWidth(), and
minimumHeightForWidth(). For more explanation see the \e{Qt
Quarterly} article
- \l{http://doc.qt.digia.com/qq/qq04-height-for-width.html}{Trading
+ \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}{Trading
Height for Width}.
\sa QLayout
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index b98e8a6a66..92f6066936 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -425,7 +425,12 @@ QT_BEGIN_NAMESPACE
Note that this does not apply when there are no other widgets underneath and
the intention is to have a semi-transparent window. In that case the
- traditional approach of setting Qt::WA_TranslucentBackground is sufficient.
+ traditional approach of setting Qt::WA_TranslucentBackground
+ on the top-level window is sufficient. Note that if the transparent areas are
+ only desired in the QOpenGLWidget, then Qt::WA_NoSystemBackground will need
+ to be turned back to \c false after enabling Qt::WA_TranslucentBackground.
+ Additionally, requesting an alpha channel for the QOpenGLWidget's context via
+ setFormat() may be necessary too, depending on the system.
QOpenGLWidget supports multiple update behaviors, just like QOpenGLWindow. In
preserved mode the rendered content from the previous paintGL() call is
@@ -607,7 +612,7 @@ void QOpenGLWidgetPaintDevicePrivate::beginPaint()
// with the palette's background color.
if (w->autoFillBackground()) {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
- if (w->testAttribute(Qt::WA_TranslucentBackground)) {
+ if (w->format().hasAlpha()) {
f->glClearColor(0, 0, 0, 0);
} else {
QColor c = w->palette().brush(w->backgroundRole()).color();
@@ -955,13 +960,12 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
OpenGL widgets, individual calls to this function can be replaced by one single call to
QSurfaceFormat::setDefaultFormat() before creating the first widget.
- \note Requesting an alpha buffer via this function, or by setting
- Qt::WA_TranslucentBackground, will not lead to the desired results when the intention is
- to make other widgets beneath visible. Instead, use Qt::WA_AlwaysStackOnTop to enable
- semi-transparent QOpenGLWidget instances with other widgets visible underneath. Keep in
- mind however that this breaks the stacking order, so it will no longer be possible to
- have other widgets on top of the QOpenGLWidget. When the intention is to have a
- semi-transparent top-level window, Qt::WA_TranslucentBackground is sufficient.
+ \note Requesting an alpha buffer via this function will not lead to the
+ desired results when the intention is to make other widgets beneath visible.
+ Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent QOpenGLWidget
+ instances with other widgets visible underneath. Keep in mind however that
+ this breaks the stacking order, so it will no longer be possible to have
+ other widgets on top of the QOpenGLWidget.
\sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat()
*/
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index f9a9fe2d0c..ae674534e3 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1634,10 +1634,13 @@ QWidget::~QWidget()
}
if (d->declarativeData) {
- if (QAbstractDeclarativeData::destroyed)
- QAbstractDeclarativeData::destroyed(d->declarativeData, this);
- if (QAbstractDeclarativeData::destroyed_qml1)
- QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
+ if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
+ if (QAbstractDeclarativeData::destroyed_qml1)
+ QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
+ } else {
+ if (QAbstractDeclarativeData::destroyed)
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
+ }
d->declarativeData = 0; // don't activate again in ~QObject
}
@@ -5213,7 +5216,7 @@ QPixmap QWidget::grab(const QRect &rectangle)
QPixmap res(r.size());
if (!d->isOpaque)
res.fill(Qt::transparent);
- render(&res, QPoint(), QRegion(r), renderFlags);
+ d->render(&res, QPoint(), QRegion(r), renderFlags);
d->dirtyOpaqueChildren = oldDirtyOpaqueChildren;
return res;
@@ -8338,8 +8341,8 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
otherwise returns \c false.
First it sends the widget a QCloseEvent. The widget is
- \l{hide()}{hidden} if it \l{QCloseEvent::accept()}{accepts}
- the close event. If it \l{QCloseEvent::ignore()}{ignores}
+ \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts}
+ the close event. If it \l{QEvent::ignore()}{ignores}
the event, nothing happens. The default
implementation of QWidget::closeEvent() accepts the close event.
@@ -9312,12 +9315,12 @@ void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
subclass to receive wheel events for the widget.
If you reimplement this handler, it is very important that you
- \l{QWheelEvent}{ignore()} the event if you do not handle
+ \l{QEvent}{ignore()} the event if you do not handle
it, so that the widget's parent can interpret it.
The default implementation ignores the event.
- \sa QWheelEvent::ignore(), QWheelEvent::accept(), event(),
+ \sa QEvent::ignore(), QEvent::accept(), event(),
QWheelEvent
*/
@@ -9333,12 +9336,12 @@ void QWidget::wheelEvent(QWheelEvent *event)
subclass to receive tablet events for the widget.
If you reimplement this handler, it is very important that you
- \l{QTabletEvent}{ignore()} the event if you do not handle
+ \l{QEvent}{ignore()} the event if you do not handle
it, so that the widget's parent can interpret it.
The default implementation ignores the event.
- \sa QTabletEvent::ignore(), QTabletEvent::accept(), event(),
+ \sa QEvent::ignore(), QEvent::accept(), event(),
QTabletEvent
*/
@@ -9398,7 +9401,7 @@ void QWidget::keyPressEvent(QKeyEvent *event)
need to call QKeyEvent::accept() - just do not call the base class
implementation if you act upon the key.
- \sa keyPressEvent(), QKeyEvent::ignore(), setFocusPolicy(),
+ \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(),
focusInEvent(), focusOutEvent(), event(), QKeyEvent
*/
@@ -12878,7 +12881,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget)
const QDebugStateSaver saver(debug);
debug.nospace();
if (widget) {
- debug << widget->metaObject()->className() << '(' << (void *)widget;
+ debug << widget->metaObject()->className() << '(' << (const void *)widget;
if (!widget->objectName().isEmpty())
debug << ", name=" << widget->objectName();
if (debug.verbosity() > 2) {
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index f1e25d116d..e3c40ef95e 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -445,11 +445,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
receiver = popupChild;
if (receiver != popup)
widgetPos = receiver->mapFromGlobal(event->globalPos());
- QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos()));
+ QWidget *alien = receiver->childAt(receiver->mapFromGlobal(event->globalPos()));
QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers(), event->source());
e.setTimestamp(event->timestamp());
- QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver);
+ QApplicationPrivate::sendMouseEvent(receiver, &e, alien, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
qt_last_mouse_receiver = receiver;
} else {
// close disabled popups when a mouse button is pressed or released
@@ -556,6 +556,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
translated.setTimestamp(event->timestamp());
QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget,
&qt_button_down, qt_last_mouse_receiver);
+ event->setAccepted(translated.isAccepted());
}
#ifndef QT_NO_CONTEXTMENU
if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton
@@ -711,6 +712,7 @@ void QWidgetWindow::handleCloseEvent(QCloseEvent *event)
{
bool is_closing = m_widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
event->setAccepted(is_closing);
+ QWindow::event(event); // Call QWindow QCloseEvent handler.
}
#ifndef QT_NO_WHEELEVENT
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index f87542ffa8..2fc52e9a32 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -554,11 +554,19 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
QColor arrowColor = header->palette.foreground().color();
QPoint offset = QPoint(0, -1);
+#if defined(Q_OS_LINUX)
if (header->sortIndicator & QStyleOptionHeader::SortUp) {
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
} else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
}
+#else
+ if (header->sortIndicator & QStyleOptionHeader::SortUp) {
+ arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
+ } else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
+ arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
+ }
+#endif
if (!arrow.isNull()) {
r.setSize(QSize(arrow.width()/2, arrow.height()/2));
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 44917b3f16..95fb2f5b91 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1960,7 +1960,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
const bool button = opt->type == QStyleOption::SO_Button;
const bool viewItem = opt->type == QStyleOption::SO_ViewItem;
const bool pressed = bdi->state == kThemeStatePressed;
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
+ const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
if (button && pressed) {
if (bdi->kind == kThemePushButton) {
@@ -3601,6 +3601,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QWindow *window = w && w->window() ? w->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
+ const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
switch (ce) {
case CE_HeaderSection:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
@@ -3812,13 +3813,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// No default button pulsating animation on Yosemite,
// so we have to do few things differently.
- const bool yosemiteOrLater = QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
// a focused auto-default button within an active window
// takes precedence over a normal default button
if (btn->features & QStyleOptionButton::AutoDefaultButton
&& opt->state & State_Active && opt->state & State_HasFocus) {
- if (yosemiteOrLater)
+ if (usingYosemiteOrLater)
d->autoDefaultButton = opt->styleObject;
else
d->setAutoDefaultButton(opt->styleObject);
@@ -3829,7 +3829,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (!d->autoDefaultButton) {
if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) {
d->defaultButton = opt->styleObject;
- if (!yosemiteOrLater && !d->animation(opt->styleObject))
+ if (!usingYosemiteOrLater && !d->animation(opt->styleObject))
d->startAnimation(new QStyleAnimation(opt->styleObject));
} else if (d->defaultButton == opt->styleObject) {
if (QStyleAnimation *animation = d->animation(opt->styleObject)) {
@@ -3851,7 +3851,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
HIThemeButtonDrawInfo bdi;
d->initHIThemePushButton(btn, w, tds, &bdi);
- if (yosemiteOrLater) {
+ if (usingYosemiteOrLater) {
if (!hasMenu) {
// HITheme is not drawing a nice focus frame around buttons.
// We'll do it ourselves further down.
@@ -3904,7 +3904,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4;
}
- if (hasMenu && yosemiteOrLater && bdi.kind != kThemeBevelButton) {
+ if (hasMenu && usingYosemiteOrLater && bdi.kind != kThemeBevelButton) {
QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind);
cw.first = QCocoaPullDownButton;
NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw);
@@ -3918,7 +3918,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
else
HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
- if (yosemiteOrLater && btn->state & State_HasFocus) {
+ if (usingYosemiteOrLater && btn->state & State_HasFocus) {
CGRect focusRect = newRect;
if (bdi.kind == kThemePushButton)
focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about.
@@ -3949,7 +3949,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath);
}
- if (hasMenu && (!yosemiteOrLater || bdi.kind == kThemeBevelButton)) {
+ if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) {
int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
QRect ir = btn->rect;
int arrowXOffset = bdi.kind == kThemePushButton ? 6 :
@@ -4121,8 +4121,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
}
- bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
-
HIThemeTabDrawInfo tdi;
tdi.version = 1;
tdi.style = kThemeTabNonFront;
@@ -4234,7 +4232,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
ThemeTabDirection ttd = getTabDirection(myTab.shape);
bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
bool selected = (myTab.state & QStyle::State_Selected);
- bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
if (selected && !myTab.documentMode
&& (!usingYosemiteOrLater || myTab.state & State_Active))
@@ -4266,7 +4263,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QPalette np = tab->palette;
np.setColor(QPalette::WindowText, shadowColor);
- QRect nr = subElementRect(SE_TabBarTabText, opt, w);
+ QRect nr = proxy()->subElementRect(SE_TabBarTabText, opt, w);
nr.moveTop(-1);
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic;
proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled,
@@ -4682,7 +4679,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
tdi.value = pb->progress;
tdi.attributes = vertical ? 0 : kThemeTrackHorizontal;
- if (isIndeterminate || tdi.value < tdi.max) {
+ if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) {
if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject)))
tdi.trackInfo.progress.phase = animation->animationStep();
else if (opt->styleObject)
@@ -4764,8 +4761,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
HIThemeSplitterDrawInfo sdi;
sdi.version = qt_mac_hitheme_version;
sdi.state = tds;
- sdi.adornment = qt_mac_is_metal(w) ? kHIThemeSplitterAdornmentMetal
- : kHIThemeSplitterAdornmentNone;
+ sdi.adornment = qt_mac_is_metal(w) || usingYosemiteOrLater ?
+ kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone;
HIRect hirect = qt_hirectForQRect(opt->rect);
HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal);
} else {
@@ -5300,6 +5297,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
+ const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
switch (cc) {
case CC_Slider:
case CC_ScrollBar:
@@ -5377,7 +5375,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
tdi.attributes |= kThemeTrackHideTrack;
}
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
const bool isHorizontal = slider->orientation == Qt::Horizontal;
if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) {
@@ -5753,7 +5750,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
break;
case CC_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
HIThemeButtonDrawInfo bdi;
d->initComboboxBdi(combo, &bdi, widget, tds);
HIRect rect = qt_hirectForQRect(combo->rect);
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 5e51866d8f..b368477a39 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -541,17 +541,21 @@ QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pi
QRect result;
int x, y, w, h;
rect.getRect(&x, &y, &w, &h);
+
+ const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio();
+ const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio();
+
if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
- y += h/2 - pixmap.height()/2;
+ y += h/2 - pixmapHeight/2;
else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
- y += h - pixmap.height();
+ y += h - pixmapHeight;
if ((alignment & Qt::AlignRight) == Qt::AlignRight)
- x += w - pixmap.width();
+ x += w - pixmapWidth;
else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
- x += w/2 - pixmap.width()/2;
+ x += w/2 - pixmapWidth/2;
else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft())
- x += w - pixmap.width();
- result = QRect(x, y, pixmap.width(), pixmap.height());
+ x += w - pixmapWidth;
+ result = QRect(x, y, pixmapWidth, pixmapHeight);
return result;
}
@@ -2263,8 +2267,9 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up
standard palette is not used. In particular, the Windows XP,
Vista, and Mac styles do not use the standard palette, but make
use of native theme engines. With these styles, you should not set
- the palette with QApplication::setStandardPalette().
+ the palette with QApplication::setPalette().
+ \sa QApplication::setPalette()
*/
QPalette QStyle::standardPalette() const
{
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index b8ed82fee3..ab4b4245c6 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -657,8 +657,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
newStyle = !qobject_cast<const QTableView*>(view);
selectionBehavior = view->selectionBehavior();
selectionMode = view->selectionMode();
+#ifndef QT_NO_ACCESSIBILITY
} else if (!widget) {
newStyle = !QStyleHelper::hasAncestor(option->styleObject, QAccessible::MenuItem) ;
+#endif
}
if (newStyle && (vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option))) {
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index c96c779d6a..ba4bbe40a8 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -720,7 +720,16 @@ void QAbstractSpinBox::interpretText()
QVariant QAbstractSpinBox::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QAbstractSpinBox);
- return d->edit->inputMethodQuery(query);
+ const QVariant lineEditValue = d->edit->inputMethodQuery(query);
+ switch (query) {
+ case Qt::ImHints:
+ if (const int hints = inputMethodHints())
+ return QVariant(hints | lineEditValue.toInt());
+ break;
+ default:
+ break;
+ }
+ return lineEditValue;
}
/*!
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index af085747ec..89fd3d3d57 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -1772,6 +1772,8 @@ void QComboBox::setLineEdit(QLineEdit *edit)
connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished()));
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString)));
connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString)));
+ connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus()));
+ connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus()));
d->lineEdit->setFrame(false);
d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu);
d->updateFocusPolicy();
@@ -3028,9 +3030,6 @@ void QComboBox::mousePressEvent(QMouseEvent *e)
d->showPopupFromMouseEvent(e);
}
-/*!
- \reimp
-*/
void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
{
Q_Q(QComboBox);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 6ea92e4c4d..8b0263fc0c 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -614,6 +614,7 @@ void QDockWidgetPrivate::init()
#ifndef QT_NO_ACTION
toggleViewAction = new QAction(q);
toggleViewAction->setCheckable(true);
+ toggleViewAction->setMenuRole(QAction::NoRole);
fixedWindowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q);
toggleViewAction->setText(fixedWindowTitle);
QObject::connect(toggleViewAction, SIGNAL(triggered(bool)),
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 0500907b3d..32502fca09 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1897,18 +1897,14 @@ void QLineEdit::paintEvent(QPaintEvent *)
}
QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height());
- int minLB = qMax(0, -fm.minLeftBearing());
- int minRB = qMax(0, -fm.minRightBearing());
-
if (d->shouldShowPlaceholderText()) {
if (!d->placeholderText.isEmpty()) {
QColor col = pal.text().color();
col.setAlpha(128);
QPen oldpen = p.pen();
p.setPen(col);
- QRect ph = lineRect.adjusted(minLB, 0, 0, 0);
- QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, ph.width());
- p.drawText(ph, va, elidedText);
+ QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width());
+ p.drawText(lineRect, va, elidedText);
p.setPen(oldpen);
}
}
@@ -1918,11 +1914,10 @@ void QLineEdit::paintEvent(QPaintEvent *)
// horizontal scrolling. d->hscroll is the left indent from the beginning
// of the text line to the left edge of lineRect. we update this value
// depending on the delta from the last paint event; in effect this means
- // the below code handles all scrolling based on the textline (widthUsed,
- // minLB, minRB), the line edit rect (lineRect) and the cursor position
- // (cix).
- int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB;
- if ((minLB + widthUsed) <= lineRect.width()) {
+ // the below code handles all scrolling based on the textline (widthUsed),
+ // the line edit rect (lineRect) and the cursor position (cix).
+ int widthUsed = qRound(d->control->naturalTextWidth()) + 1;
+ if (widthUsed <= lineRect.width()) {
// text fits in lineRect; use hscroll for alignment
switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
case Qt::AlignRight:
@@ -1936,7 +1931,6 @@ void QLineEdit::paintEvent(QPaintEvent *)
d->hscroll = 0;
break;
}
- d->hscroll -= minLB;
} else if (cix - d->hscroll >= lineRect.width()) {
// text doesn't fit, cursor is to the right of lineRect (scroll right)
d->hscroll = cix - lineRect.width() + 1;
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index b798bca4d1..a68f5a41ed 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -188,6 +188,9 @@ void QLineEditPrivate::init(const QString& txt)
QObject::connect(control, SIGNAL(selectionChanged()),
q, SLOT(update()));
+ QObject::connect(control, SIGNAL(selectionChanged()),
+ q, SLOT(updateMicroFocus()));
+
QObject::connect(control, SIGNAL(displayTextChanged(QString)),
q, SLOT(update()));
@@ -321,6 +324,24 @@ void QLineEditIconButton::paintEvent(QPaintEvent *)
painter.drawPixmap(pixmapRect, iconPixmap);
}
+void QLineEditIconButton::actionEvent(QActionEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::ActionChanged: {
+ const QAction *action = e->action();
+ if (isVisible() != action->isVisible()) {
+ setVisible(action->isVisible());
+ if (QLineEdit *le = qobject_cast<QLineEdit *>(parentWidget()))
+ static_cast<QLineEditPrivate *>(qt_widget_private(le))->positionSideWidgets();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ QToolButton::actionEvent(e);
+}
+
void QLineEditIconButton::setOpacity(qreal value)
{
if (!qFuzzyCompare(m_opacity, value)) {
@@ -412,12 +433,14 @@ void QLineEditPrivate::positionSideWidgets()
QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize);
foreach (const SideWidgetEntry &e, leftSideWidgetList()) {
e.widget->setGeometry(widgetGeometry);
- widgetGeometry.moveLeft(widgetGeometry.left() + delta);
+ if (e.widget->isVisible())
+ widgetGeometry.moveLeft(widgetGeometry.left() + delta);
}
widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin);
foreach (const SideWidgetEntry &e, rightSideWidgetList()) {
e.widget->setGeometry(widgetGeometry);
- widgetGeometry.moveLeft(widgetGeometry.left() - delta);
+ if (e.widget->isVisible())
+ widgetGeometry.moveLeft(widgetGeometry.left() - delta);
}
}
}
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index 57055757eb..b47866b827 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -61,6 +61,8 @@
#include "private/qwidgetlinecontrol_p.h"
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
// QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text
@@ -81,6 +83,7 @@ public:
#endif
protected:
+ void actionEvent(QActionEvent *e) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private slots:
@@ -227,14 +230,23 @@ private:
};
Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetEntry, Q_PRIMITIVE_TYPE);
+static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e)
+{
+ return e.widget->isVisible();
+}
+
inline int QLineEditPrivate::effectiveLeftTextMargin() const
{
- return leftTextMargin + leftSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width());
+ return leftTextMargin + (QLineEditIconButton::IconMargin + iconSize().width())
+ * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(),
+ isSideWidgetVisible));
}
inline int QLineEditPrivate::effectiveRightTextMargin() const
{
- return rightTextMargin + rightSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width());
+ return rightTextMargin + (QLineEditIconButton::IconMargin + iconSize().width())
+ * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(),
+ isSideWidgetVisible));
}
#endif // QT_NO_LINEEDIT
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index a7c58ab332..0556c02b64 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1443,7 +1443,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
addSeparator(), and addMenu().
\sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up},
- {Application Example}, {Menus Example}, {Recent Files Example}
+ {Application Example}, {Menus Example}
*/
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 9e76ff082c..d382131075 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -638,7 +638,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti
\row \li quit or exit
\li Application Menu | Quit <application name>
\li If this entry is not found a default Quit item will be
- created to call QApplication::quit()
+ created to call QCoreApplication::quit()
\endtable
You can override this behavior by using the QAction::menuRole()
@@ -1044,8 +1044,8 @@ void QMenuBar::mousePressEvent(QMouseEvent *e)
if(d->currentAction == action && d->popupState) {
if(QMenu *menu = d->activeMenu) {
d->activeMenu = 0;
+ menu->setAttribute(Qt::WA_NoMouseReplay);
menu->hide();
- d->closePopupMode = 1;
}
} else {
d->setCurrentAction(action, true);
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index d9f8c8f991..b7125eec59 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -70,6 +70,7 @@ extern "C" {
#include <qdir.h>
#include <qstandardpaths.h>
#include <qfunctions_winrt.h>
+#include <qcoreapplication.h>
#include <wrl.h>
#include <Windows.ApplicationModel.core.h>
@@ -109,6 +110,24 @@ static void devMessageHandler(QtMsgType type, const QMessageLogContext &context,
defaultMessageHandler(type, context, message);
}
+class QActivationEvent : public QEvent
+{
+public:
+ explicit QActivationEvent(IInspectable *args)
+ : QEvent(QEvent::WinEventAct)
+ {
+ setAccepted(false);
+ args->AddRef();
+ d = reinterpret_cast<QEventPrivate *>(args);
+ }
+
+ ~QActivationEvent() {
+ IUnknown *args = reinterpret_cast<IUnknown *>(d);
+ args->Release();
+ d = nullptr;
+ }
+};
+
class AppContainer : public RuntimeClass<Xaml::IApplicationOverrides>
{
public:
@@ -158,7 +177,10 @@ public:
private:
HRESULT __stdcall OnActivated(IActivatedEventArgs *args) Q_DECL_OVERRIDE
{
- return base->OnActivated(args);
+ QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
+ if (dispatcher)
+ QCoreApplication::postEvent(dispatcher, new QActivationEvent(args));
+ return S_OK;
}
HRESULT __stdcall OnLaunched(ILaunchActivatedEventArgs *launchArgs) Q_DECL_OVERRIDE