summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/bearer/android/jar/bundledjar.pro3
-rw-r--r--src/plugins/bearer/android/jar/distributedjar.pro2
-rw-r--r--src/plugins/bearer/android/jar/jar.pri11
-rw-r--r--src/plugins/bearer/android/jar/jar.pro15
-rw-r--r--src/plugins/bearer/android/src/main.cpp2
-rw-r--r--src/plugins/bearer/android/src/qandroidbearerengine.h28
-rw-r--r--src/plugins/bearer/generic/main.cpp2
-rw-r--r--src/plugins/bearer/generic/qgenericengine.h18
-rw-r--r--src/plugins/bearer/qnetworksession_impl.h44
-rw-r--r--src/plugins/generic/evdevkeyboard/main.cpp2
-rw-r--r--src/plugins/generic/evdevmouse/main.cpp2
-rw-r--r--src/plugins/generic/evdevtablet/main.cpp2
-rw-r--r--src/plugins/generic/evdevtouch/main.cpp2
-rw-r--r--src/plugins/generic/generic.pro4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp3
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp32
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h10
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp2
-rw-r--r--src/plugins/platforminputcontexts/ibus/main.cpp2
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp71
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h21
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxy.cpp45
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxy.h50
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp5
-rw-r--r--src/plugins/platforms/bsdfb/qbsdfbscreen.cpp3
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm20
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm41
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.h22
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h14
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h22
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm68
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h40
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h39
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm234
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h26
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.h86
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.mm296
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.h34
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.h40
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm97
-rw-r--r--src/plugins/platforms/cocoa/qcocoaservices.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.h18
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h24
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h58
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm23
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm41
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm98
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac_p.h6
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm2
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac_p.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h10
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp144
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h10
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h6
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h50
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h20
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp6
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp23
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp8
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow_p.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp50
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp56
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp240
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h34
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp80
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h (renamed from src/plugins/platforms/windows/accessible/comutils.h)35
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp10
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp10
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmshelpers.h60
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp22
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp47
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h8
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.json3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro31
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.cpp136
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.h78
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp242
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h80
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2main.cpp56
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp359
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h115
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp607
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h113
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp326
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h92
-rw-r--r--src/plugins/platforms/haiku/main.cpp2
-rw-r--r--src/plugins/platforms/haiku/main.h2
-rw-r--r--src/plugins/platforms/haiku/qhaikuapplication.h4
-rw-r--r--src/plugins/platforms/haiku/qhaikubuffer.cpp6
-rw-r--r--src/plugins/platforms/haiku/qhaikuclipboard.cpp10
-rw-r--r--src/plugins/platforms/haiku/qhaikuclipboard.h10
-rw-r--r--src/plugins/platforms/haiku/qhaikucursor.h2
-rw-r--r--src/plugins/platforms/haiku/qhaikuintegration.cpp6
-rw-r--r--src/plugins/platforms/haiku/qhaikuintegration.h14
-rw-r--r--src/plugins/platforms/haiku/qhaikurasterbackingstore.cpp6
-rw-r--r--src/plugins/platforms/haiku/qhaikurasterbackingstore.h6
-rw-r--r--src/plugins/platforms/haiku/qhaikurasterwindow.cpp4
-rw-r--r--src/plugins/platforms/haiku/qhaikurasterwindow.h16
-rw-r--r--src/plugins/platforms/haiku/qhaikuscreen.cpp8
-rw-r--r--src/plugins/platforms/haiku/qhaikuscreen.h10
-rw-r--r--src/plugins/platforms/haiku/qhaikuservices.h6
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.cpp8
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.h36
-rw-r--r--src/plugins/platforms/integrity/main.cpp2
-rw-r--r--src/plugins/platforms/integrity/qintegrityfbintegration.h18
-rw-r--r--src/plugins/platforms/integrity/qintegrityfbscreen.cpp13
-rw-r--r--src/plugins/platforms/integrity/qintegrityfbscreen.h4
-rw-r--r--src/plugins/platforms/integrity/qintegrityhidmanager.cpp8
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm8
-rw-r--r--src/plugins/platforms/ios/qiosbackingstore.h2
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.h8
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm4
-rw-r--r--src/plugins/platforms/ios/qioscontext.h16
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h4
-rw-r--r--src/plugins/platforms/ios/qiosfiledialog.h22
-rw-r--r--src/plugins/platforms/ios/qiosfiledialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h22
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h34
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm7
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h52
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.h6
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosoptionalplugininterface.h2
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h20
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm18
-rw-r--r--src/plugins/platforms/ios/qiostheme.h14
-rw-r--r--src/plugins/platforms/ios/qioswindow.h34
-rw-r--r--src/plugins/platforms/ios/quiview.h1
-rw-r--r--src/plugins/platforms/ios/quiview.mm94
-rw-r--r--src/plugins/platforms/linuxfb/main.cpp2
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp76
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.h18
-rw-r--r--src/plugins/platforms/minimal/main.cpp2
-rw-r--r--src/plugins/platforms/minimal/minimal.pro2
-rw-r--r--src/plugins/platforms/minimal/qminimalbackingstore.h6
-rw-r--r--src/plugins/platforms/minimal/qminimalintegration.cpp34
-rw-r--r--src/plugins/platforms/minimal/qminimalintegration.h19
-rw-r--r--src/plugins/platforms/minimalegl/main.cpp2
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglbackingstore.h10
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.cpp4
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.h14
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglscreen.cpp2
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglscreen.h6
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglwindow.h4
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.cpp30
-rw-r--r--src/plugins/platforms/offscreen/main.cpp2
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.cpp6
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h20
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h18
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.h18
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h12
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp5
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.cpp7
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp19
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h2
-rw-r--r--src/plugins/platforms/vnc/qvnc.cpp9
-rw-r--r--src/plugins/platforms/windows/accessible/accessible.pri19
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.cpp280
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp1640
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h358
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp245
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp1223
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h176
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h14
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp29
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp22
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp25
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp140
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h (renamed from src/plugins/platforms/windows/accessible/qwindowsaccessibility.h)28
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp81
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h78
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp176
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h71
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp136
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h69
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp84
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h67
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp638
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h105
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp106
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h77
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp190
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h73
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp201
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h71
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp147
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h69
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp129
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h68
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp154
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h69
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp261
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h80
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp554
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h88
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp105
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h68
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp221
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h89
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp132
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h70
-rw-r--r--src/plugins/platforms/windows/uiautomation/uiautomation.pri43
-rw-r--r--src/plugins/platforms/windows/windows.pri4
-rw-r--r--src/plugins/platforms/winrt/qwinrtclipboard.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp8
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp12
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h8
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp10
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp4
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp6
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h38
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h34
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp215
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp29
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h28
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp110
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp72
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp170
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp539
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp54
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp189
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h14
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro2
-rw-r--r--src/plugins/platformthemes/flatpak/flatpak.json3
-rw-r--r--src/plugins/platformthemes/flatpak/flatpak.pro17
-rw-r--r--src/plugins/platformthemes/flatpak/main.cpp65
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp347
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h105
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpaktheme.cpp254
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpaktheme.h90
-rw-r--r--src/plugins/platformthemes/gtk3/main.cpp2
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h42
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.h12
-rw-r--r--src/plugins/platformthemes/platformthemes.pro2
-rw-r--r--src/plugins/printsupport/cups/main.cpp2
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine.cpp12
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h8
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport_p.h10
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.cpp46
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.h38
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp4
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.h30
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.h10
-rw-r--r--src/plugins/sqldrivers/db2/qsql_db2.cpp89
-rw-r--r--src/plugins/sqldrivers/db2/qsql_db2_p.h26
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase.cpp19
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase_p.h32
-rw-r--r--src/plugins/sqldrivers/mysql/main.cpp2
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp36
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql_p.h28
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci.cpp232
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci_p.h24
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp42
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc_p.h28
-rw-r--r--src/plugins/sqldrivers/psql/main.cpp2
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp584
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql_p.h34
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp22
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h30
-rw-r--r--src/plugins/sqldrivers/sqlite/smain.cpp2
-rw-r--r--src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp19
-rw-r--r--src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h24
-rw-r--r--src/plugins/sqldrivers/tds/qsql_tds.cpp15
-rw-r--r--src/plugins/sqldrivers/tds/qsql_tds_p.h26
-rw-r--r--src/plugins/styles/mac/qmacstyle.qdoc28
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm257
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h1
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp85
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h11
336 files changed, 12406 insertions, 6925 deletions
diff --git a/src/plugins/bearer/android/jar/bundledjar.pro b/src/plugins/bearer/android/jar/bundledjar.pro
deleted file mode 100644
index 6037f813f2..0000000000
--- a/src/plugins/bearer/android/jar/bundledjar.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TARGET = QtAndroidBearer-bundled
-CONFIG += bundled_jar_file
-include(jar.pri)
diff --git a/src/plugins/bearer/android/jar/distributedjar.pro b/src/plugins/bearer/android/jar/distributedjar.pro
deleted file mode 100644
index c769a113d5..0000000000
--- a/src/plugins/bearer/android/jar/distributedjar.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET = QtAndroidBearer
-include(jar.pri)
diff --git a/src/plugins/bearer/android/jar/jar.pri b/src/plugins/bearer/android/jar/jar.pri
deleted file mode 100644
index e43dbf0711..0000000000
--- a/src/plugins/bearer/android/jar/jar.pri
+++ /dev/null
@@ -1,11 +0,0 @@
-load(qt_build_paths)
-CONFIG += java
-DESTDIR = $$MODULE_BASE_OUTDIR/jar
-
-JAVACLASSPATH += $$PWD/src
-
-JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
-
-# install
-target.path = $$[QT_INSTALL_PREFIX]/jar
-INSTALLS += target
diff --git a/src/plugins/bearer/android/jar/jar.pro b/src/plugins/bearer/android/jar/jar.pro
index 923e757d9b..f988019dac 100644
--- a/src/plugins/bearer/android/jar/jar.pro
+++ b/src/plugins/bearer/android/jar/jar.pro
@@ -1,2 +1,13 @@
-TEMPLATE=subdirs
-SUBDIRS += distributedjar.pro bundledjar.pro
+TARGET = QtAndroidBearer
+
+load(qt_build_paths)
+CONFIG += java
+DESTDIR = $$MODULE_BASE_OUTDIR/jar
+
+JAVACLASSPATH += $$PWD/src
+
+JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java
+
+# install
+target.path = $$[QT_INSTALL_PREFIX]/jar
+INSTALLS += target
diff --git a/src/plugins/bearer/android/src/main.cpp b/src/plugins/bearer/android/src/main.cpp
index 3892766b89..f3a5074e5d 100644
--- a/src/plugins/bearer/android/src/main.cpp
+++ b/src/plugins/bearer/android/src/main.cpp
@@ -50,7 +50,7 @@ class QAndroidBearerEnginePlugin : public QBearerEnginePlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QBearerEngineFactoryInterface" FILE "android.json")
public:
- QBearerEngine *create(const QString &key) const Q_DECL_OVERRIDE
+ QBearerEngine *create(const QString &key) const override
{
return (key == QLatin1String("android")) ? new QAndroidBearerEngine() : 0;
}
diff --git a/src/plugins/bearer/android/src/qandroidbearerengine.h b/src/plugins/bearer/android/src/qandroidbearerengine.h
index f404ca65eb..837b02232d 100644
--- a/src/plugins/bearer/android/src/qandroidbearerengine.h
+++ b/src/plugins/bearer/android/src/qandroidbearerengine.h
@@ -60,20 +60,20 @@ class QAndroidBearerEngine : public QBearerEngineImpl
public:
explicit QAndroidBearerEngine(QObject *parent = 0);
- ~QAndroidBearerEngine() Q_DECL_OVERRIDE;
-
- QString getInterfaceFromId(const QString &id) Q_DECL_OVERRIDE;
- bool hasIdentifier(const QString &id) Q_DECL_OVERRIDE;
- void connectToId(const QString &id) Q_DECL_OVERRIDE;
- void disconnectFromId(const QString &id) Q_DECL_OVERRIDE;
- QNetworkSession::State sessionStateForId(const QString &id) Q_DECL_OVERRIDE;
- QNetworkConfigurationManager::Capabilities capabilities() const Q_DECL_OVERRIDE;
- QNetworkSessionPrivate *createSessionBackend() Q_DECL_OVERRIDE;
- QNetworkConfigurationPrivatePointer defaultConfiguration() Q_DECL_OVERRIDE;
- bool requiresPolling() const Q_DECL_OVERRIDE;
- quint64 bytesWritten(const QString &id) Q_DECL_OVERRIDE;
- quint64 bytesReceived(const QString &id) Q_DECL_OVERRIDE;
- quint64 startTime(const QString &id) Q_DECL_OVERRIDE;
+ ~QAndroidBearerEngine() override;
+
+ QString getInterfaceFromId(const QString &id) override;
+ bool hasIdentifier(const QString &id) override;
+ void connectToId(const QString &id) override;
+ void disconnectFromId(const QString &id) override;
+ QNetworkSession::State sessionStateForId(const QString &id) override;
+ QNetworkConfigurationManager::Capabilities capabilities() const override;
+ QNetworkSessionPrivate *createSessionBackend() override;
+ QNetworkConfigurationPrivatePointer defaultConfiguration() override;
+ bool requiresPolling() const override;
+ quint64 bytesWritten(const QString &id) override;
+ quint64 bytesReceived(const QString &id) override;
+ quint64 startTime(const QString &id) override;
Q_INVOKABLE void initialize();
Q_INVOKABLE void requestUpdate();
diff --git a/src/plugins/bearer/generic/main.cpp b/src/plugins/bearer/generic/main.cpp
index 80e7b7d9aa..82a9ce97f4 100644
--- a/src/plugins/bearer/generic/main.cpp
+++ b/src/plugins/bearer/generic/main.cpp
@@ -54,7 +54,7 @@ public:
QGenericEnginePlugin();
~QGenericEnginePlugin();
- QBearerEngine *create(const QString &key) const Q_DECL_OVERRIDE;
+ QBearerEngine *create(const QString &key) const override;
};
QGenericEnginePlugin::QGenericEnginePlugin()
diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h
index e680eb9cc0..08960d66f6 100644
--- a/src/plugins/bearer/generic/qgenericengine.h
+++ b/src/plugins/bearer/generic/qgenericengine.h
@@ -58,24 +58,24 @@ public:
QGenericEngine(QObject *parent = 0);
~QGenericEngine();
- QString getInterfaceFromId(const QString &id) Q_DECL_OVERRIDE;
- bool hasIdentifier(const QString &id) Q_DECL_OVERRIDE;
+ QString getInterfaceFromId(const QString &id) override;
+ bool hasIdentifier(const QString &id) override;
- void connectToId(const QString &id) Q_DECL_OVERRIDE;
- void disconnectFromId(const QString &id) Q_DECL_OVERRIDE;
+ void connectToId(const QString &id) override;
+ void disconnectFromId(const QString &id) override;
Q_INVOKABLE void initialize();
Q_INVOKABLE void requestUpdate();
- QNetworkSession::State sessionStateForId(const QString &id) Q_DECL_OVERRIDE;
+ QNetworkSession::State sessionStateForId(const QString &id) override;
- QNetworkConfigurationManager::Capabilities capabilities() const Q_DECL_OVERRIDE;
+ QNetworkConfigurationManager::Capabilities capabilities() const override;
- QNetworkSessionPrivate *createSessionBackend() Q_DECL_OVERRIDE;
+ QNetworkSessionPrivate *createSessionBackend() override;
- QNetworkConfigurationPrivatePointer defaultConfiguration() Q_DECL_OVERRIDE;
+ QNetworkConfigurationPrivatePointer defaultConfiguration() override;
- bool requiresPolling() const Q_DECL_OVERRIDE;
+ bool requiresPolling() const override;
private Q_SLOTS:
void doRequestUpdate();
diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h
index e9c0e383fc..d9aa6ca8fb 100644
--- a/src/plugins/bearer/qnetworksession_impl.h
+++ b/src/plugins/bearer/qnetworksession_impl.h
@@ -75,31 +75,31 @@ public:
//that the state is immediately updated (w/o actually opening
//a session). Also this function should take care of
//notification hooks to discover future state changes.
- void syncStateWithInterface() Q_DECL_OVERRIDE;
+ void syncStateWithInterface() override;
#ifndef QT_NO_NETWORKINTERFACE
- QNetworkInterface currentInterface() const Q_DECL_OVERRIDE;
+ QNetworkInterface currentInterface() const override;
#endif
- QVariant sessionProperty(const QString& key) const Q_DECL_OVERRIDE;
- void setSessionProperty(const QString& key, const QVariant& value) Q_DECL_OVERRIDE;
-
- void open() Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- void stop() Q_DECL_OVERRIDE;
- void migrate() Q_DECL_OVERRIDE;
- void accept() Q_DECL_OVERRIDE;
- void ignore() Q_DECL_OVERRIDE;
- void reject() Q_DECL_OVERRIDE;
-
- QString errorString() const Q_DECL_OVERRIDE; //must return translated string
- QNetworkSession::SessionError error() const Q_DECL_OVERRIDE;
-
- quint64 bytesWritten() const Q_DECL_OVERRIDE;
- quint64 bytesReceived() const Q_DECL_OVERRIDE;
- quint64 activeTime() const Q_DECL_OVERRIDE;
-
- QNetworkSession::UsagePolicies usagePolicies() const Q_DECL_OVERRIDE;
- void setUsagePolicies(QNetworkSession::UsagePolicies) Q_DECL_OVERRIDE;
+ QVariant sessionProperty(const QString& key) const override;
+ void setSessionProperty(const QString& key, const QVariant& value) override;
+
+ void open() override;
+ void close() override;
+ void stop() override;
+ void migrate() override;
+ void accept() override;
+ void ignore() override;
+ void reject() override;
+
+ QString errorString() const override; //must return translated string
+ QNetworkSession::SessionError error() const override;
+
+ quint64 bytesWritten() const override;
+ quint64 bytesReceived() const override;
+ quint64 activeTime() const override;
+
+ QNetworkSession::UsagePolicies usagePolicies() const override;
+ void setUsagePolicies(QNetworkSession::UsagePolicies) override;
private Q_SLOTS:
void networkConfigurationsChanged();
diff --git a/src/plugins/generic/evdevkeyboard/main.cpp b/src/plugins/generic/evdevkeyboard/main.cpp
index ef08cd56ab..5c170e1a06 100644
--- a/src/plugins/generic/evdevkeyboard/main.cpp
+++ b/src/plugins/generic/evdevkeyboard/main.cpp
@@ -50,7 +50,7 @@ class QEvdevKeyboardPlugin : public QGenericPlugin
public:
QEvdevKeyboardPlugin();
- QObject* create(const QString &key, const QString &specification) Q_DECL_OVERRIDE;
+ QObject* create(const QString &key, const QString &specification) override;
};
QEvdevKeyboardPlugin::QEvdevKeyboardPlugin()
diff --git a/src/plugins/generic/evdevmouse/main.cpp b/src/plugins/generic/evdevmouse/main.cpp
index 86ec7cb575..1b8517f4c4 100644
--- a/src/plugins/generic/evdevmouse/main.cpp
+++ b/src/plugins/generic/evdevmouse/main.cpp
@@ -50,7 +50,7 @@ class QEvdevMousePlugin : public QGenericPlugin
public:
QEvdevMousePlugin();
- QObject* create(const QString &key, const QString &specification) Q_DECL_OVERRIDE;
+ QObject* create(const QString &key, const QString &specification) override;
};
QEvdevMousePlugin::QEvdevMousePlugin()
diff --git a/src/plugins/generic/evdevtablet/main.cpp b/src/plugins/generic/evdevtablet/main.cpp
index 0646d71146..f43a32910d 100644
--- a/src/plugins/generic/evdevtablet/main.cpp
+++ b/src/plugins/generic/evdevtablet/main.cpp
@@ -50,7 +50,7 @@ class QEvdevTabletPlugin : public QGenericPlugin
public:
QEvdevTabletPlugin();
- QObject* create(const QString &key, const QString &specification) Q_DECL_OVERRIDE;
+ QObject* create(const QString &key, const QString &specification) override;
};
QEvdevTabletPlugin::QEvdevTabletPlugin()
diff --git a/src/plugins/generic/evdevtouch/main.cpp b/src/plugins/generic/evdevtouch/main.cpp
index aa60614936..f1a0ad53ab 100644
--- a/src/plugins/generic/evdevtouch/main.cpp
+++ b/src/plugins/generic/evdevtouch/main.cpp
@@ -50,7 +50,7 @@ class QEvdevTouchScreenPlugin : public QGenericPlugin
public:
QEvdevTouchScreenPlugin();
- QObject* create(const QString &key, const QString &specification) Q_DECL_OVERRIDE;
+ QObject* create(const QString &key, const QString &specification) override;
};
QEvdevTouchScreenPlugin::QEvdevTouchScreenPlugin()
diff --git a/src/plugins/generic/generic.pro b/src/plugins/generic/generic.pro
index e323f32d2c..980aa1a506 100644
--- a/src/plugins/generic/generic.pro
+++ b/src/plugins/generic/generic.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
-QT_FOR_CONFIG += gui-private network-private
+QT_FOR_CONFIG += gui-private
qtConfig(evdev) {
SUBDIRS += evdevmouse evdevtouch evdevkeyboard
@@ -11,7 +11,7 @@ qtConfig(tslib) {
SUBDIRS += tslib
}
-qtConfig(udpsocket) {
+qtConfig(tuiotouch) {
SUBDIRS += tuiotouch
}
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 68619928d3..1cdc28c077 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -65,9 +65,6 @@ extern "C" {
#endif
#define XMD_H // shut JPEGlib up
-#if defined(Q_OS_UNIXWARE)
-# define HAVE_BOOLEAN // libjpeg under Unixware seems to need this
-#endif
#include <jpeglib.h>
#ifdef const
# undef const // remove crazy C hackery in jconfig.h
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
index 48693ccdb0..81a730232c 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
@@ -82,7 +82,37 @@ static const int composingKeys[] = {
Qt::Key_Dead_Semivoiced_Sound,
Qt::Key_Dead_Belowdot,
Qt::Key_Dead_Hook,
- Qt::Key_Dead_Horn
+ Qt::Key_Dead_Horn,
+ Qt::Key_Dead_Stroke,
+ Qt::Key_Dead_Abovecomma,
+ Qt::Key_Dead_Abovereversedcomma,
+ Qt::Key_Dead_Doublegrave,
+ Qt::Key_Dead_Belowring,
+ Qt::Key_Dead_Belowmacron,
+ Qt::Key_Dead_Belowcircumflex,
+ Qt::Key_Dead_Belowtilde,
+ Qt::Key_Dead_Belowbreve,
+ Qt::Key_Dead_Belowdiaeresis,
+ Qt::Key_Dead_Invertedbreve,
+ Qt::Key_Dead_Belowcomma,
+ Qt::Key_Dead_Currency,
+ Qt::Key_Dead_a,
+ Qt::Key_Dead_A,
+ Qt::Key_Dead_e,
+ Qt::Key_Dead_E,
+ Qt::Key_Dead_i,
+ Qt::Key_Dead_I,
+ Qt::Key_Dead_o,
+ Qt::Key_Dead_O,
+ Qt::Key_Dead_u,
+ Qt::Key_Dead_U,
+ Qt::Key_Dead_Small_Schwa,
+ Qt::Key_Dead_Capital_Schwa,
+ Qt::Key_Dead_Greek,
+ Qt::Key_Dead_Lowline,
+ Qt::Key_Dead_Aboveverticalline,
+ Qt::Key_Dead_Belowverticalline,
+ Qt::Key_Dead_Longsolidusoverlay
};
QComposeInputContext::QComposeInputContext()
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
index f82280903d..4830959665 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
@@ -58,11 +58,11 @@ public:
QComposeInputContext();
~QComposeInputContext();
- bool isValid() const Q_DECL_OVERRIDE;
- void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
- void reset() Q_DECL_OVERRIDE;
- void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
- bool filterEvent(const QEvent *event) Q_DECL_OVERRIDE;
+ bool isValid() const override;
+ void setFocusObject(QObject *object) override;
+ void reset() override;
+ void update(Qt::InputMethodQueries) override;
+ bool filterEvent(const QEvent *event) override;
protected:
void clearComposeBuffer();
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
index 97a7242ca6..6b33df65b9 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
@@ -51,7 +51,7 @@ class QComposePlatformInputContextPlugin : public QPlatformInputContextPlugin
Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "compose.json")
public:
- QComposeInputContext *create(const QString &, const QStringList &) Q_DECL_OVERRIDE;
+ QComposeInputContext *create(const QString &, const QStringList &) override;
};
QComposeInputContext *QComposePlatformInputContextPlugin::create(const QString &system, const QStringList &paramList)
diff --git a/src/plugins/platforminputcontexts/ibus/main.cpp b/src/plugins/platforminputcontexts/ibus/main.cpp
index 2846f52c8c..0a7da3b14c 100644
--- a/src/plugins/platforminputcontexts/ibus/main.cpp
+++ b/src/plugins/platforminputcontexts/ibus/main.cpp
@@ -51,7 +51,7 @@ class QIbusPlatformInputContextPlugin : public QPlatformInputContextPlugin
Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "ibus.json")
public:
- QIBusPlatformInputContext *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QIBusPlatformInputContext *create(const QString&, const QStringList&) override;
};
QIBusPlatformInputContext *QIbusPlatformInputContextPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 9675d828e7..76f42d764d 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -60,6 +60,10 @@
#ifndef IBUS_RELEASE_MASK
#define IBUS_RELEASE_MASK (1 << 30)
+#define IBUS_SHIFT_MASK (1 << 0)
+#define IBUS_CONTROL_MASK (1 << 2)
+#define IBUS_MOD1_MASK (1 << 3)
+#define IBUS_META_MASK (1 << 28)
#endif
QT_BEGIN_NAMESPACE
@@ -90,6 +94,7 @@ public:
bool valid;
bool busConnected;
QString predit;
+ QList<QInputMethodEvent::Attribute> attributes;
bool needsSurroundingText;
QLocale locale;
};
@@ -165,6 +170,7 @@ void QIBusPlatformInputContext::reset()
d->context->Reset();
d->predit = QString();
+ d->attributes.clear();
}
void QIBusPlatformInputContext::commit()
@@ -177,6 +183,7 @@ void QIBusPlatformInputContext::commit()
QObject *input = qApp->focusObject();
if (!input) {
d->predit = QString();
+ d->attributes.clear();
return;
}
@@ -188,6 +195,7 @@ void QIBusPlatformInputContext::commit()
d->context->Reset();
d->predit = QString();
+ d->attributes.clear();
}
@@ -274,6 +282,7 @@ void QIBusPlatformInputContext::commitText(const QDBusVariant &text)
QCoreApplication::sendEvent(input, &event);
d->predit = QString();
+ d->attributes.clear();
}
void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint cursorPos, bool visible)
@@ -292,16 +301,48 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint
if (debug)
qDebug() << "preedit text:" << t.text;
- QList<QInputMethodEvent::Attribute> attributes = t.attributes.imAttributes();
+ d->attributes = t.attributes.imAttributes();
if (!t.text.isEmpty())
- attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, visible ? 1 : 0);
+ d->attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, visible ? 1 : 0, QVariant());
- QInputMethodEvent event(t.text, attributes);
+ QInputMethodEvent event(t.text, d->attributes);
QCoreApplication::sendEvent(input, &event);
d->predit = t.text;
}
+void QIBusPlatformInputContext::forwardKeyEvent(uint keyval, uint keycode, uint state)
+{
+ if (!qApp)
+ return;
+
+ QObject *input = qApp->focusObject();
+ if (!input)
+ return;
+
+ if (debug)
+ qDebug() << "forwardKeyEvent" << keyval << keycode << state;
+
+ QEvent::Type type = QEvent::KeyPress;
+ if (state & IBUS_RELEASE_MASK)
+ type = QEvent::KeyRelease;
+
+ state &= ~IBUS_RELEASE_MASK;
+
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+ if (state & IBUS_SHIFT_MASK)
+ modifiers |= Qt::ShiftModifier;
+ if (state & IBUS_CONTROL_MASK)
+ modifiers |= Qt::ControlModifier;
+ if (state & IBUS_MOD1_MASK)
+ modifiers |= Qt::AltModifier;
+ if (state & IBUS_META_MASK)
+ modifiers |= Qt::MetaModifier;
+
+ QKeyEvent event(type, keyval, modifiers, QString(keyval));
+ QCoreApplication::sendEvent(input, &event);
+}
+
void QIBusPlatformInputContext::surroundingTextRequired()
{
if (debug)
@@ -324,6 +365,27 @@ void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars)
QCoreApplication::sendEvent(input, &event);
}
+void QIBusPlatformInputContext::hidePreeditText()
+{
+ QObject *input = QGuiApplication::focusObject();
+ if (!input)
+ return;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event(QString(), attributes);
+ QCoreApplication::sendEvent(input, &event);
+}
+
+void QIBusPlatformInputContext::showPreeditText()
+{
+ QObject *input = QGuiApplication::focusObject();
+ if (!input)
+ return;
+
+ QInputMethodEvent event(d->predit, d->attributes);
+ QCoreApplication::sendEvent(input, &event);
+}
+
bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
{
if (!d->busConnected)
@@ -496,8 +558,11 @@ void QIBusPlatformInputContext::connectToContextSignals()
if (d->context) {
connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant)));
connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool)));
+ connect(d->context, SIGNAL(ForwardKeyEvent(uint, uint, uint)), this, SLOT(forwardKeyEvent(uint, uint, uint)));
connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired()));
+ connect(d->context, SIGNAL(HidePreeditText()), this, SLOT(hidePreeditText()));
+ connect(d->context, SIGNAL(ShowPreeditText()), this, SLOT(showPreeditText()));
}
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 7baa9ad1da..9b92b2e1f9 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -86,23 +86,26 @@ public:
QIBusPlatformInputContext();
~QIBusPlatformInputContext();
- bool isValid() const Q_DECL_OVERRIDE;
- void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
+ bool isValid() const override;
+ void setFocusObject(QObject *object) override;
- void invokeAction(QInputMethod::Action a, int x) Q_DECL_OVERRIDE;
- void reset() Q_DECL_OVERRIDE;
- void commit() Q_DECL_OVERRIDE;
- void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
- bool filterEvent(const QEvent *event) Q_DECL_OVERRIDE;
- QLocale locale() const Q_DECL_OVERRIDE;
- bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
+ void invokeAction(QInputMethod::Action a, int x) override;
+ void reset() override;
+ void commit() override;
+ void update(Qt::InputMethodQueries) override;
+ bool filterEvent(const QEvent *event) override;
+ QLocale locale() const override;
+ bool hasCapability(Capability capability) const override;
public Q_SLOTS:
void commitText(const QDBusVariant &text);
void updatePreeditText(const QDBusVariant &text, uint cursor_pos, bool visible);
+ void forwardKeyEvent(uint keyval, uint keycode, uint state);
void cursorRectChanged();
void deleteSurroundingText(int offset, uint n_chars);
void surroundingTextRequired();
+ void hidePreeditText();
+ void showPreeditText();
void filterEventFinished(QDBusPendingCallWatcher *call);
void socketChanged(const QString &str);
void connectToBus();
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
index 9efa6f7eb0..156e9b7c90 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
@@ -33,10 +33,53 @@ QIBusProxy::~QIBusProxy()
{
}
+#ifdef QIBUS_GET_ADDRESS
+QString QIBusProxy::getAddress()
+{
+ QDBusReply<QDBusVariant> reply = Address();
+ QVariant variant = reply.value().variant();
+ if (!variant.isValid())
+ return QString();
+ return variant.toString();
+}
+#endif
+
+#ifdef QIBUS_GET_ENGINES
+QList<QIBusEngineDesc> QIBusProxy::getEngines()
+{
+ QList<QIBusEngineDesc> engines;
+ QDBusReply<QDBusVariant> reply = Engines();
+ QVariant variant = reply.value().variant();
+ if (!variant.isValid())
+ return engines;
+ const QDBusArgument argument = variant.value<QDBusArgument>();
+ qCDebug(qtQpaInputMethodsSerialize) << "QIBusProxy::getEngines()" << argument.currentSignature();
+
+ int i = 1;
+ argument.beginMap();
+ while (!argument.atEnd()) {
+ QDBusVariant value;
+ argument >> value;
+ if (!value.variant().isValid()) {
+ qWarning() << "Warning in QIBusProxy::getEngines():" << QString::asprintf("%dth variant is wrong", i);
+ break;
+ }
+ const QDBusArgument desc_arg = value.variant().value<QDBusArgument>();
+
+ QIBusEngineDesc desc;
+ desc_arg >> desc;
+ engines.append(desc);
+ ++i;
+ }
+ argument.endMap();
+ return engines;
+}
+#endif
+
QIBusEngineDesc QIBusProxy::getGlobalEngine()
{
QIBusEngineDesc desc;
- QDBusReply<QDBusVariant> reply = GetGlobalEngine();
+ QDBusReply<QDBusVariant> reply = GlobalEngine();
QVariant variant = reply.value().variant();
if (!variant.isValid())
return desc;
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.h b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
index bbaebe1b96..839e972c34 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
@@ -54,24 +54,6 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("Exit"), argumentList);
}
- inline QDBusPendingReply<QString> GetAddress()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("GetAddress"), argumentList);
- }
-
- inline QDBusPendingReply<QVariantList> ListActiveEngines()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ListActiveEngines"), argumentList);
- }
-
- inline QDBusPendingReply<QVariantList> ListEngines()
- {
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QLatin1String("ListEngines"), argumentList);
- }
-
inline QDBusPendingReply<QDBusVariant> Ping(const QDBusVariant &data)
{
QList<QVariant> argumentList;
@@ -86,19 +68,45 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("RegisterComponent"), argumentList);
}
- inline QDBusPendingReply<QDBusVariant> GetGlobalEngine()
+// Property
+ inline QDBusPendingCall GetProperty(const QString method)
{
if (!this->isValid() || this->service().isEmpty() || this->path().isEmpty())
- return QDBusMessage::createError(this->lastError());
+ return QDBusPendingCall::fromError(this->lastError());
QDBusMessage msg = QDBusMessage::createMethodCall(this->service(),
this->path(),
dbusInterfaceProperties(),
QStringLiteral("Get"));
- msg << this->interface() << QStringLiteral("GlobalEngine");
+ msg << this->interface() << method;
return this->connection().asyncCall(msg, this->timeout());
}
+#ifdef QIBUS_GET_ADDRESS
+ inline QDBusPendingCall Address()
+ {
+ return GetProperty(QStringLiteral("Address"));
+ }
+#endif
+
+#ifdef QIBUS_GET_ENGINES
+ inline QDBusPendingCall Engines()
+ {
+ return GetProperty(QStringLiteral("Engines"));
+ }
+#endif
+
+ inline QDBusPendingCall GlobalEngine()
+ {
+ return GetProperty(QStringLiteral("GlobalEngine"));
+ }
+
+#ifdef QIBUS_GET_ADDRESS
+ QString getAddress();
+#endif
+#ifdef QIBUS_GET_ENGINES
+ QList<QIBusEngineDesc> getEngines();
+#endif
QIBusEngineDesc getGlobalEngine();
private:
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 3a79e32abe..7dc8bb8080 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -59,6 +59,8 @@
#include <QtGui/QWindow>
#include <QtGui/private/qwindow_p.h>
+#include <vector>
+
QT_BEGIN_NAMESPACE
#ifdef QANDROIDPLATFORMSCREEN_DEBUG
@@ -376,8 +378,7 @@ void QAndroidPlatformScreen::doRedraw()
|| !window->isRaster())
continue;
- const QVector<QRect> visibleRects = visibleRegion.rects();
- for (const QRect &rect : visibleRects) {
+ for (const QRect &rect : std::vector<QRect>(visibleRegion.begin(), visibleRegion.end())) {
QRect targetRect = window->geometry();
targetRect &= rect;
diff --git a/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp b/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
index 067a26a7b1..d752b539a0 100644
--- a/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
+++ b/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
@@ -247,8 +247,7 @@ QRegion QBsdFbScreen::doRedraw()
if (!m_blitter)
m_blitter.reset(new QPainter(&m_onscreenImage));
- const auto rects = touched.rects();
- for (const QRect &rect : rects)
+ for (const QRect &rect : touched)
m_blitter->drawImage(rect, mScreenImage, rect);
return touched;
}
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 5354bdafbc..2694cb3607 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -14,6 +14,7 @@ SOURCES += main.mm \
qcocoaeventdispatcher.mm \
qcocoaapplicationdelegate.mm \
qcocoaapplication.mm \
+ qcocoansmenu.mm \
qcocoamenu.mm \
qcocoamenuitem.mm \
qcocoamenubar.mm \
@@ -47,6 +48,7 @@ HEADERS += qcocoaintegration.h \
qcocoaeventdispatcher.h \
qcocoaapplicationdelegate.h \
qcocoaapplication.h \
+ qcocoansmenu.h \
qcocoamenu.h \
qcocoamenuitem.h \
qcocoamenubar.h \
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index e7957276c2..e456364555 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -53,10 +53,10 @@ class QCocoaAccessibility : public QPlatformAccessibility
public:
QCocoaAccessibility();
~QCocoaAccessibility();
- void notifyAccessibilityUpdate(QAccessibleEvent *event) Q_DECL_OVERRIDE;
- void setRootObject(QObject *o) Q_DECL_OVERRIDE;
- void initialize() Q_DECL_OVERRIDE;
- void cleanup() Q_DECL_OVERRIDE;
+ void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+ void setRootObject(QObject *o) override;
+ void initialize() override;
+ void cleanup() override;
};
namespace QCocoaAccessible {
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 7e6bae127c..df2336d08b 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -40,6 +40,7 @@
#include "qcocoaaccessibility.h"
#include "qcocoahelpers.h"
#include "qcocoawindow.h"
+#include "qcocoascreen.h"
#include "private/qaccessiblecache_p.h"
#include <QtAccessibilitySupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
@@ -298,9 +299,9 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
// We're in the same top level element as our parent.
return [[self parentElement] accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
} else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) {
- QPoint qtPosition = iface->rect().topLeft();
- QSize qtSize = iface->rect().size();
- return [NSValue valueWithPoint: NSMakePoint(qtPosition.x(), qt_mac_flipYCoordinate(qtPosition.y() + qtSize.height()))];
+ // The position in points of the element's lower-left corner in screen-relative coordinates
+ QPointF qtPosition = QRectF(iface->rect()).bottomLeft();
+ return [NSValue valueWithPoint:QCocoaScreen::mapToNative(qtPosition)];
} else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) {
QSize qtSize = iface->rect().size();
return [NSValue valueWithSize: NSMakeSize(qtSize.width(), qtSize.height())];
@@ -430,7 +431,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) {
NSRange range = [parameter rangeValue];
QRect firstRect = iface->textInterface()->characterRect(range.location);
- QRect rect;
+ QRectF rect;
if (range.length > 0) {
NSUInteger position = range.location + range.length - 1;
if (position > range.location && iface->textInterface()->text(position, position + 1) == QStringLiteral("\n"))
@@ -441,15 +442,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
rect = firstRect;
rect.setWidth(1);
}
- return [NSValue valueWithRect: NSMakeRect((CGFloat) rect.x(),(CGFloat) qt_mac_flipYCoordinate(rect.y() + rect.height()), rect.width(), rect.height())];
+ return [NSValue valueWithRect:QCocoaScreen::mapToNative(rect)];
}
if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
NSRange range = [parameter rangeValue];
QString text = iface->textInterface()->text(range.location, range.location + range.length);
return [[NSAttributedString alloc] initWithString:text.toNSString()];
} else if ([attribute isEqualToString: NSAccessibilityRangeForPositionParameterizedAttribute]) {
- NSPoint nsPoint = [parameter pointValue];
- QPoint point(static_cast<int>(nsPoint.x), static_cast<int>(qt_mac_flipYCoordinate(nsPoint.y)));
+ QPoint point = QCocoaScreen::mapFromNative([parameter pointValue]).toPoint();
int offset = iface->textInterface()->offsetAtPoint(point);
return [NSValue valueWithRange:NSMakeRange(static_cast<NSUInteger>(offset), 1)];
} else if ([attribute isEqualToString: NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
@@ -566,8 +566,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return NSAccessibilityUnignoredAncestor(self);
}
- int y = qt_mac_flipYCoordinate(point.y);
- QAccessibleInterface *childInterface = iface->childAt(point.x, y);
+ QPointF screenPoint = QCocoaScreen::mapFromNative(point);
+ QAccessibleInterface *childInterface = iface->childAt(screenPoint.x(), screenPoint.y());
// No child found, meaning we hit this element.
if (!childInterface || !childInterface->isValid())
return NSAccessibilityUnignoredAncestor(self);
@@ -575,7 +575,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
// find the deepest child at the point
QAccessibleInterface *childOfChildInterface = 0;
do {
- childOfChildInterface = childInterface->childAt(point.x, y);
+ childOfChildInterface = childInterface->childAt(screenPoint.x(), screenPoint.y());
if (childOfChildInterface && childOfChildInterface->isValid())
childInterface = childOfChildInterface;
} while (childOfChildInterface && childOfChildInterface->isValid());
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 5392804d62..32be9ad4ee 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -86,16 +86,21 @@
QT_USE_NAMESPACE
-QT_BEGIN_NAMESPACE
-static QCocoaApplicationDelegate *sharedCocoaApplicationDelegate = nil;
+@implementation QCocoaApplicationDelegate
-static void cleanupCocoaApplicationDelegate()
++ (instancetype)sharedDelegate
{
- [sharedCocoaApplicationDelegate release];
+ static QCocoaApplicationDelegate *shared = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ shared = [[self alloc] init];
+ atexit_b(^{
+ [shared release];
+ shared = nil;
+ });
+ });
+ return shared;
}
-QT_END_NAMESPACE
-
-@implementation QCocoaApplicationDelegate
- (id)init
{
@@ -120,7 +125,6 @@ QT_END_NAMESPACE
- (void)dealloc
{
- sharedCocoaApplicationDelegate = nil;
[dockMenu release];
if (reflectionDelegate) {
[[NSApplication sharedApplication] setDelegate:reflectionDelegate];
@@ -131,27 +135,6 @@ QT_END_NAMESPACE
[super dealloc];
}
-+ (id)allocWithZone:(NSZone *)zone
-{
- @synchronized(self) {
- if (sharedCocoaApplicationDelegate == nil) {
- sharedCocoaApplicationDelegate = [super allocWithZone:zone];
- qAddPostRoutine(cleanupCocoaApplicationDelegate);
- return sharedCocoaApplicationDelegate;
- }
- }
- return nil;
-}
-
-+ (QCocoaApplicationDelegate *)sharedDelegate
-{
- @synchronized(self) {
- if (sharedCocoaApplicationDelegate == nil)
- [[self alloc] init];
- }
- return [[sharedCocoaApplicationDelegate retain] autorelease];
-}
-
- (void)setDockMenu:(NSMenu*)newMenu
{
[newMenu retain];
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index a0bc204013..b4cd506513 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -52,11 +52,11 @@ public:
QCocoaBackingStore(QWindow *window);
~QCocoaBackingStore();
- void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE;
+ void flush(QWindow *, const QRegion &, const QPoint &) override;
private:
bool windowHasUnifiedToolbar() const;
- QImage::Format format() const Q_DECL_OVERRIDE;
+ QImage::Format format() const override;
void redrawRoundedBottomCorners(CGRect) const;
};
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h
index cab2cfaa91..a78d8f4187 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.h
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h
@@ -56,10 +56,10 @@ class QCocoaClipboard : public QObject, public QPlatformClipboard
public:
QCocoaClipboard();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
- bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
private Q_SLOTS:
void handleApplicationStateChanged(Qt::ApplicationState state);
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
index 133efd6db8..01ac7e181d 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
@@ -55,12 +55,12 @@ public:
QCocoaColorDialogHelper();
~QCocoaColorDialogHelper();
- void exec() Q_DECL_OVERRIDE;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ void exec() override;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
- void setCurrentColor(const QColor&) Q_DECL_OVERRIDE;
- QColor currentColor() const Q_DECL_OVERRIDE;
+ void setCurrentColor(const QColor&) override;
+ QColor currentColor() const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index d1586660a4..58b9ef2151 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -53,9 +53,9 @@ public:
QCocoaCursor();
~QCocoaCursor();
- void changeCursor(QCursor *cursor, QWindow *window) Q_DECL_OVERRIDE;
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &position) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor *cursor, QWindow *window) override;
+ QPoint pos() const override;
+ void setPos(const QPoint &position) override;
private:
QHash<Qt::CursorShape, NSCursor *> m_cursors;
NSCursor *convertCursor(QCursor *cursor);
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 99a136d384..c021128e4c 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -39,6 +39,7 @@
#include "qcocoacursor.h"
#include "qcocoawindow.h"
+#include "qcocoascreen.h"
#include "qcocoahelpers.h"
#include <QtGui/private/qcoregraphics_p.h>
@@ -70,7 +71,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
QPoint QCocoaCursor::pos() const
{
- return qt_mac_flipPoint([NSEvent mouseLocation]).toPoint();
+ return QCocoaScreen::mapFromNative([NSEvent mouseLocation]).toPoint();
}
void QCocoaCursor::setPos(const QPoint &position)
@@ -86,7 +87,7 @@ void QCocoaCursor::setPos(const QPoint &position)
NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
{
- if (cursor == Q_NULLPTR)
+ if (cursor == nullptr)
return 0;
const Qt::CursorShape newShape = cursor->shape();
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
index c7277a47bf..dc0cc17dfb 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.h
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -56,10 +56,10 @@ public:
~QCocoaDrag();
QMimeData *dragMimeData();
- Qt::DropAction drag(QDrag *m_drag) Q_DECL_OVERRIDE;
+ Qt::DropAction drag(QDrag *m_drag) override;
Qt::DropAction defaultAction(Qt::DropActions possibleActions,
- Qt::KeyboardModifiers modifiers) const Q_DECL_OVERRIDE;
+ Qt::KeyboardModifiers modifiers) const override;
/**
* to meet NSView dragImage:at guarantees, we need to record the original
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index 3bd0b05725..e1f36b47a1 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -188,7 +188,7 @@ QPixmap QCocoaDrag::dragPixmap(QDrag *drag, QPoint &hotSpot) const
if (s.length() > dragImageMaxChars)
s = s.left(dragImageMaxChars -3) + QChar(0x2026);
if (!s.isEmpty()) {
- const int width = fm.width(s);
+ const int width = fm.horizontalAdvance(s);
const int height = fm.height();
if (width > 0 && height > 0) {
qreal dpr = 1.0;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
index f5ba1dc22e..2ddda14289 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h
@@ -59,19 +59,19 @@ public:
QCocoaFileDialogHelper();
virtual ~QCocoaFileDialogHelper();
- void exec() Q_DECL_OVERRIDE;
+ void exec() override;
- bool defaultNameFilterDisables() const Q_DECL_OVERRIDE;
+ bool defaultNameFilterDisables() const override;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
- void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
- QUrl directory() const Q_DECL_OVERRIDE;
- void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- void setFilter() Q_DECL_OVERRIDE;
- void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE;
- QString selectedNameFilter() const Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
+ void setDirectory(const QUrl &directory) override;
+ QUrl directory() const override;
+ void selectFile(const QUrl &filename) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override;
+ void selectNameFilter(const QString &filter) override;
+ QString selectedNameFilter() const override;
public:
bool showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent);
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index fa123550ef..7ea3d130f7 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -63,7 +63,8 @@
#include <qsysinfo.h>
#include <qoperatingsystemversion.h>
#include <qglobal.h>
-#include <QDir>
+#include <qdir.h>
+#include <qregularexpression.h>
#include <qpa/qplatformnativeinterface.h>
@@ -509,9 +510,10 @@ static QString strippedText(QString s)
- (QString)removeExtensions:(const QString &)filter
{
- QRegExp regExp(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
- if (regExp.indexIn(filter) != -1)
- return regExp.cap(1).trimmed();
+ QRegularExpression regExp(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp));
+ QRegularExpressionMatch match = regExp.match(filter);
+ if (match.hasMatch())
+ return match.captured(1).trimmed();
return filter;
}
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
index c3fad7cfd6..14f12f2d76 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
@@ -54,13 +54,13 @@ public:
QCocoaFontDialogHelper();
~QCocoaFontDialogHelper();
- void exec() Q_DECL_OVERRIDE;
+ void exec() override;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
- void setCurrentFont(const QFont &) Q_DECL_OVERRIDE;
- QFont currentFont() const Q_DECL_OVERRIDE;
+ void setCurrentFont(const QFont &) override;
+ QFont currentFont() const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 732b50d29e..0530aa8201 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -55,22 +55,22 @@ public:
QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
~QCocoaGLContext();
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *surface) override;
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
- QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE;
+ QFunctionPointer getProcAddress(const char *procName) override;
void update();
static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format);
NSOpenGLContext *nsOpenGLContext() const;
- bool isSharing() const Q_DECL_OVERRIDE;
- bool isValid() const Q_DECL_OVERRIDE;
+ bool isSharing() const override;
+ bool isValid() const override;
void windowWasHidden();
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 7ce247f861..2c4783b1e3 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -85,13 +85,8 @@ QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
void qt_mac_transformProccessToForegroundApplication();
QString qt_mac_applicationName();
-int qt_mac_flipYCoordinate(int y);
-qreal qt_mac_flipYCoordinate(qreal y);
-QPointF qt_mac_flipPoint(const NSPoint &p);
-NSPoint qt_mac_flipPoint(const QPoint &p);
-NSPoint qt_mac_flipPoint(const QPointF &p);
-
-NSRect qt_mac_flipRect(const QRect &rect);
+QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference);
+QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference);
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
@@ -196,6 +191,19 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper);
// -------------------------------------------------------------------------
+// QAppleRefCounted expects the retain function to return the object
+io_object_t q_IOObjectRetain(io_object_t obj);
+// QAppleRefCounted expects the release function to return void
+void q_IOObjectRelease(io_object_t obj);
+
+template <typename T>
+class QIOType : public QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>
+{
+ using QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>::QAppleRefCounted;
+};
+
+// -------------------------------------------------------------------------
+
// Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret:
// - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
// - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 0380e0e79d..fdf4733f0e 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -232,50 +232,37 @@ QString qt_mac_applicationName()
return appName;
}
-int qt_mac_primaryScreenHeight()
-{
- QMacAutoReleasePool pool;
- NSArray *screens = [NSScreen screens];
- if ([screens count] > 0) {
- // The first screen in the screens array is documented to
- // have the (0,0) origin and is designated the primary screen.
- NSRect screenFrame = [[screens objectAtIndex: 0] frame];
- return screenFrame.size.height;
- }
- return 0;
-}
+// -------------------------------------------------------------------------
-int qt_mac_flipYCoordinate(int y)
-{
- return qt_mac_primaryScreenHeight() - y;
-}
+/*!
+ \fn QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference)
+ \fn QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference)
-qreal qt_mac_flipYCoordinate(qreal y)
-{
- return qt_mac_primaryScreenHeight() - y;
-}
+ Flips the Y coordinate of the point/rect between quadrant I and IV.
-QPointF qt_mac_flipPoint(const NSPoint &p)
-{
- return QPointF(p.x, qt_mac_flipYCoordinate(p.y));
-}
+ The native coordinate system on macOS uses quadrant I, with origin
+ in bottom left, and Qt uses quadrant IV, with origin in top left.
-NSPoint qt_mac_flipPoint(const QPoint &p)
-{
- return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y()));
-}
+ By flipping the Y coordinate, we can map the point/rect between
+ the two coordinate systems.
-NSPoint qt_mac_flipPoint(const QPointF &p)
+ The flip is always in relation to a reference rectangle, e.g.
+ the frame of the parent view, or the screen geometry. In the
+ latter case the specialized QCocoaScreen::mapFrom/To functions
+ should be used instead.
+*/
+QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference)
{
- return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y()));
+ return QPointF(pos.x(), reference.height() - pos.y());
}
-NSRect qt_mac_flipRect(const QRect &rect)
+QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference)
{
- int flippedY = qt_mac_flipYCoordinate(rect.y() + rect.height());
- return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height());
+ return QRectF(qt_mac_flip(rect.bottomLeft(), reference), rect.size());
}
+// -------------------------------------------------------------------------
+
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
{
if (buttonNum >= 0 && buttonNum <= 31)
@@ -408,4 +395,19 @@ QT_END_NAMESPACE
[super layout];
}
+// -------------------------------------------------------------------------
+
+io_object_t q_IOObjectRetain(io_object_t obj)
+{
+ kern_return_t ret = IOObjectRetain(obj);
+ Q_ASSERT(!ret);
+ return obj;
+}
+
+void q_IOObjectRelease(io_object_t obj)
+{
+ kern_return_t ret = IOObjectRelease(obj);
+ Q_ASSERT(!ret);
+}
+
@end
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h
index a248ca0d8d..7190ba0de8 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h
@@ -53,11 +53,11 @@ public:
explicit QCocoaInputContext();
~QCocoaInputContext();
- bool isValid() const Q_DECL_OVERRIDE { return true; }
+ bool isValid() const override { return true; }
- void reset() Q_DECL_OVERRIDE;
+ void reset() override;
- QLocale locale() const Q_DECL_OVERRIDE { return m_locale; }
+ QLocale locale() const override { return m_locale; }
void updateLocale();
private Q_SLOTS:
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
index 9221099a57..d0baea5b36 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
@@ -129,6 +129,8 @@ void QCocoaInputContext::focusObjectChanged(QObject *focusObject)
return;
QCocoaWindow *window = static_cast<QCocoaWindow *>(mWindow->handle());
+ if (!window)
+ return;
QNSView *view = qnsview_cast(window->view());
if (!view)
return;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 2fc5156d24..301771fd53 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -75,35 +75,35 @@ public:
static QCocoaIntegration *instance();
Options options() const;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
#ifndef QT_NO_OPENGL
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif
- QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const override;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
- QCoreTextFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QCocoaNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
+ QCoreTextFontDatabase *fontDatabase() const override;
+ QCocoaNativeInterface *nativeInterface() const override;
+ QPlatformInputContext *inputContext() const override;
#ifndef QT_NO_ACCESSIBILITY
- QCocoaAccessibility *accessibility() const Q_DECL_OVERRIDE;
+ QCocoaAccessibility *accessibility() const override;
#endif
#ifndef QT_NO_CLIPBOARD
- QCocoaClipboard *clipboard() const Q_DECL_OVERRIDE;
+ QCocoaClipboard *clipboard() const override;
#endif
- QCocoaDrag *drag() const Q_DECL_OVERRIDE;
+ QCocoaDrag *drag() const override;
- QStringList themeNames() const Q_DECL_OVERRIDE;
- QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
- QCocoaServices *services() const Q_DECL_OVERRIDE;
- QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
+ QStringList themeNames() const override;
+ QPlatformTheme *createPlatformTheme(const QString &name) const override;
+ QCocoaServices *services() const override;
+ QVariant styleHint(StyleHint hint) const override;
- Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
- QList<int> possibleKeys(const QKeyEvent *event) const Q_DECL_OVERRIDE;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+ QList<int> possibleKeys(const QKeyEvent *event) const override;
void updateScreens();
QCocoaScreen *screenForNSScreen(NSScreen *nsScreen);
@@ -117,9 +117,9 @@ public:
QCocoaWindow *activePopupWindow() const;
QList<QCocoaWindow *> *popupWindowStack();
- void setApplicationIcon(const QIcon &icon) const Q_DECL_OVERRIDE;
+ void setApplicationIcon(const QIcon &icon) const override;
- void beep() const Q_DECL_OVERRIDE;
+ void beep() const override;
private Q_SLOTS:
void focusWindowChanged(QWindow *);
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index 5081fc78c6..2b4cf0ef98 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -45,6 +45,8 @@
#include <qpa/qplatformmenu.h>
#include "qcocoamenuitem.h"
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenu));
+
QT_BEGIN_NAMESPACE
class QCocoaMenuBar;
@@ -55,32 +57,31 @@ public:
QCocoaMenu();
~QCocoaMenu();
- void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
- void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
- void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
- void setEnabled(bool enabled) Q_DECL_OVERRIDE;
- bool isEnabled() const Q_DECL_OVERRIDE;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE;
- void dismiss() Q_DECL_OVERRIDE;
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
+ void removeMenuItem(QPlatformMenuItem *menuItem) override;
+ void syncMenuItem(QPlatformMenuItem *menuItem) override;
+ void setEnabled(bool enabled) override;
+ bool isEnabled() const override;
+ void setVisible(bool visible) override;
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override;
+ void dismiss() override;
- void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE;
+ void syncSeparatorsCollapsible(bool enable) override;
void propagateEnabledState(bool enabled);
- void setIcon(const QIcon &icon) Q_DECL_OVERRIDE { Q_UNUSED(icon) }
+ void setIcon(const QIcon &icon) override { Q_UNUSED(icon) }
- void setText(const QString &text) Q_DECL_OVERRIDE;
- void setMinimumWidth(int width) Q_DECL_OVERRIDE;
- void setFont(const QFont &font) Q_DECL_OVERRIDE;
+ void setText(const QString &text) override;
+ void setMinimumWidth(int width) override;
+ void setFont(const QFont &font) override;
- inline NSMenu *nsMenu() const
- { return m_nativeMenu; }
+ NSMenu *nsMenu() const;
inline bool isVisible() const { return m_visible; }
- QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
- QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemAt(int position) const override;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
QList<QCocoaMenuItem *> items() const;
QList<QCocoaMenuItem *> merged() const;
@@ -91,7 +92,7 @@ public:
bool isOpen() const;
void setIsOpen(bool isOpen);
- void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent *e) override;
void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate);
@@ -101,7 +102,7 @@ private:
void scheduleUpdate();
QList<QCocoaMenuItem *> m_menuItems;
- NSMenu *m_nativeMenu;
+ QT_MANGLE_NAMESPACE(QCocoaNSMenu) *m_nativeMenu;
NSMenuItem *m_attachedItem;
int m_updateTimer;
bool m_enabled:1;
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 1345295ef5..7a550b163b 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -38,234 +38,15 @@
****************************************************************************/
#include "qcocoamenu.h"
+#include "qcocoansmenu.h"
#include "qcocoahelpers.h"
#include <QtCore/QtDebug>
-#include <QtCore/qmetaobject.h>
-#include <QtCore/private/qthread_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#include "qcocoaapplication.h"
#include "qcocoamenuloader.h"
#include "qcocoamenubar.h"
#include "qcocoawindow.h"
-#import "qnsview.h"
-
-QT_BEGIN_NAMESPACE
-
-NSString *qt_mac_removePrivateUnicode(NSString* string)
-{
- int len = [string length];
- if (len) {
- QVarLengthArray <unichar, 10> characters(len);
- bool changed = false;
- for (int i = 0; i<len; i++) {
- characters[i] = [string characterAtIndex:i];
- // check if they belong to key codes in private unicode range
- // currently we need to handle only the NSDeleteFunctionKey
- if (characters[i] == NSDeleteFunctionKey) {
- characters[i] = NSDeleteCharacter;
- changed = true;
- }
- }
- if (changed)
- return [NSString stringWithCharacters:characters.data() length:len];
- }
- return string;
-}
-
-QT_END_NAMESPACE
-
-@interface QT_MANGLE_NAMESPACE(QCocoaMenuDelegate) : NSObject <NSMenuDelegate> {
- QCocoaMenu *m_menu;
-}
-
-- (id) initWithMenu:(QCocoaMenu*) m;
-- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier;
-
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
-
-@implementation QCocoaMenuDelegate
-
-- (id) initWithMenu:(QCocoaMenu*) m
-{
- if ((self = [super init]))
- m_menu = m;
-
- return self;
-}
-
-- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
-{
- Q_ASSERT(m_menu->nsMenu() == menu);
- return menu.numberOfItems;
-}
-
-- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
-{
- Q_UNUSED(index);
- Q_ASSERT(m_menu->nsMenu() == menu);
- if (shouldCancel) {
- // TODO detach all submenus
- return NO;
- }
-
- QCocoaMenuItem *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
- if (m_menu->items().contains(menuItem)) {
- if (QCocoaMenu *itemSubmenu = menuItem->menu())
- itemSubmenu->setAttachedItem(item);
- }
- return YES;
-}
-
-- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item
-{
- Q_UNUSED(menu);
- if (item && [item tag]) {
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
- cocoaItem->hovered();
- }
-}
-
-- (void) menuWillOpen:(NSMenu*)m
-{
- Q_UNUSED(m);
- m_menu->setIsOpen(true);
- emit m_menu->aboutToShow();
-}
-
-- (void) menuDidClose:(NSMenu*)m
-{
- Q_UNUSED(m);
- m_menu->setIsOpen(false);
- // wrong, but it's the best we can do
- emit m_menu->aboutToHide();
-}
-
-- (void) itemFired:(NSMenuItem*) item
-{
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
- // Menu-holding items also get a target to play nicely
- // with NSMenuValidation but should not trigger.
- if (cocoaItem->menu())
- return;
- QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
- QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
- static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
- activatedSignal.invoke(cocoaItem, Qt::QueuedConnection);
-}
-
-- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
-{
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>(menuItem.tag);
- // Menu-holding items are always enabled, as it's conventional in Cocoa
- if (!cocoaItem || cocoaItem->menu())
- return YES;
-
- return cocoaItem->isEnabled();
-}
-
-- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
-{
- /*
- Check if the menu actually has a keysequence defined for this key event.
- If it does, then we will first send the key sequence to the QWidget that has focus
- since (in Qt's eyes) it needs to a chance at the key event first (QEvent::ShortcutOverride).
- If the widget accepts the key event, we then return YES, but set the target and action to be nil,
- which means that the action should not be triggered, and instead dispatch the event ourselves.
- In every other case we return NO, which means that Cocoa can do as it pleases
- (i.e., fire the menu action).
- */
-
- // Change the private unicode keys to the ones used in setting the "Key Equivalents"
- NSString *characters = qt_mac_removePrivateUnicode([event characters]);
- // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
- const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
- if (NSMenuItem *menuItem = [self findItem:menu forKey:characters forModifiers:([event modifierFlags] & mask)]) {
- if (!menuItem.target) {
- // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder
- // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel.
- // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal
- // (modal sheet, window modal, application modal).
- // Whatever the current first responder is, let's give it a chance
- // and do not touch the Qt's focusObject (which is different from some native view
- // having a focus inside NSSave/OpenPanel.
- *target = nil;
- *action = menuItem.action;
- return YES;
- }
-
- QObject *object = qApp->focusObject();
- if (object) {
- QChar ch;
- int keyCode;
- ulong nativeModifiers = [event modifierFlags];
- Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers];
- NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers];
- NSString *characters = [event characters];
-
- if ([charactersIgnoringModifiers length] > 0) { // convert the first character into a key code
- if ((modifiers & Qt::ControlModifier) && ([characters length] != 0)) {
- ch = QChar([characters characterAtIndex:0]);
- } else {
- ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
- }
- keyCode = qt_mac_cocoaKey2QtKey(ch);
- } else {
- // might be a dead key
- ch = QChar::ReplacementCharacter;
- keyCode = Qt::Key_unknown;
- }
-
- QKeyEvent accel_ev(QEvent::ShortcutOverride, (keyCode & (~Qt::KeyboardModifierMask)),
- Qt::KeyboardModifiers(modifiers & Qt::KeyboardModifierMask));
- accel_ev.ignore();
- QCoreApplication::sendEvent(object, &accel_ev);
- if (accel_ev.isAccepted()) {
- [[NSApp keyWindow] sendEvent: event];
- *target = nil;
- *action = nil;
- return YES;
- }
- }
- }
- return NO;
-}
-
-- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
-{
- for (NSMenuItem *item in [menu itemArray]) {
- if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
- continue;
- if ([item hasSubmenu]) {
- if (NSMenuItem *nested = [self findItem:[item submenu] forKey:key forModifiers:modifier])
- return nested;
- }
-
- NSString *menuKey = [item keyEquivalent];
- if (menuKey
- && NSOrderedSame == [menuKey compare:key]
- && modifier == [item keyEquivalentModifierMask])
- return item;
- }
- return nil;
-}
-
-// Cocoa will query the menu item's target for the worksWhenModal selector.
-// So we need to implement this to allow the items to be handled correctly
-// when a modal dialog is visible.
-- (BOOL)worksWhenModal
-{
- if (!QGuiApplication::modalWindow())
- return YES;
- if (auto *mb = qobject_cast<QCocoaMenuBar *>(m_menu->menuParent()))
- return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO;
- return YES;
-}
-
-@end
QT_BEGIN_NAMESPACE
@@ -279,9 +60,7 @@ QCocoaMenu::QCocoaMenu() :
{
QMacAutoReleasePool pool;
- m_nativeMenu = [[NSMenu alloc] initWithTitle:@"Untitled"];
- [m_nativeMenu setAutoenablesItems:YES];
- m_nativeMenu.delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this];
+ m_nativeMenu = [[QCocoaNSMenu alloc] initWithQPAMenu:this];
}
QCocoaMenu::~QCocoaMenu()
@@ -291,10 +70,6 @@ QCocoaMenu::~QCocoaMenu()
item->setMenuParent(0);
}
- QMacAutoReleasePool pool;
- NSObject *delegate = m_nativeMenu.delegate;
- m_nativeMenu.delegate = nil;
- [delegate release];
[m_nativeMenu release];
}
@@ -319,6 +94,11 @@ void QCocoaMenu::setFont(const QFont &font)
}
}
+NSMenu *QCocoaMenu::nsMenu() const
+{
+ return static_cast<NSMenu *>(m_nativeMenu);
+}
+
void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
{
QMacAutoReleasePool pool;
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h
index a259147247..6f3aca3a51 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.h
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.h
@@ -56,11 +56,11 @@ public:
QCocoaMenuBar();
~QCocoaMenuBar();
- void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) Q_DECL_OVERRIDE;
- void removeMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
- void syncMenu(QPlatformMenu *menuItem) Q_DECL_OVERRIDE;
- void handleReparent(QWindow *newParentWindow) Q_DECL_OVERRIDE;
- QPlatformMenu *menuForTag(quintptr tag) const Q_DECL_OVERRIDE;
+ void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) override;
+ void removeMenu(QPlatformMenu *menu) override;
+ void syncMenu(QPlatformMenu *menuItem) override;
+ void handleReparent(QWindow *newParentWindow) override;
+ QPlatformMenu *menuForTag(quintptr tag) const override;
inline NSMenu *nsMenu() const
{ return m_nativeMenu; }
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index cf9553bcf7..8091d00bda 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -449,7 +449,7 @@ NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r)
foreach (QCocoaMenuItem *i, m->items())
if (i->effectiveRole() == r)
return i->nsItem();
- return Q_NULLPTR;
+ return nullptr;
}
QCocoaWindow *QCocoaMenuBar::cocoaWindow() const
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index 53862d0484..2b598ee3a0 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -78,22 +78,22 @@ public:
QCocoaMenuItem();
~QCocoaMenuItem();
- void setText(const QString &text) Q_DECL_OVERRIDE;
- void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
- void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
- void setVisible(bool isVisible) Q_DECL_OVERRIDE;
- void setIsSeparator(bool isSeparator) Q_DECL_OVERRIDE;
- void setFont(const QFont &font) Q_DECL_OVERRIDE;
- void setRole(MenuRole role) Q_DECL_OVERRIDE;
+ void setText(const QString &text) override;
+ void setIcon(const QIcon &icon) override;
+ void setMenu(QPlatformMenu *menu) override;
+ void setVisible(bool isVisible) override;
+ void setIsSeparator(bool isSeparator) override;
+ void setFont(const QFont &font) override;
+ void setRole(MenuRole role) override;
#ifndef QT_NO_SHORTCUT
- void setShortcut(const QKeySequence& shortcut) Q_DECL_OVERRIDE;
+ void setShortcut(const QKeySequence& shortcut) override;
#endif
- void setCheckable(bool checkable) Q_DECL_OVERRIDE { Q_UNUSED(checkable) }
- void setChecked(bool isChecked) Q_DECL_OVERRIDE;
- void setEnabled(bool isEnabled) Q_DECL_OVERRIDE;
- void setIconSize(int size) Q_DECL_OVERRIDE;
+ void setCheckable(bool checkable) override { Q_UNUSED(checkable) }
+ void setChecked(bool isChecked) override;
+ void setEnabled(bool isEnabled) override;
+ void setIconSize(int size) override;
- void setNativeContents(WId item) Q_DECL_OVERRIDE;
+ void setNativeContents(WId item) override;
inline QString text() const { return m_text; }
inline NSMenuItem * nsItem() { return m_native; }
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index eaf310ec51..f8f9648822 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -49,6 +49,7 @@
#include "qcocoaapplication.h" // for custom application category
#include "qcocoamenuloader.h"
#include <QtGui/private/qcoregraphics_p.h>
+#include <QtCore/qregularexpression.h>
#include <QtCore/QDebug>
@@ -261,7 +262,8 @@ NSMenuItem *QCocoaMenuItem::sync()
m_detectedRole = detectMenuRole(m_text);
switch (m_detectedRole) {
case QPlatformMenuItem::AboutRole:
- if (m_text.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1)
+ if (m_text.indexOf(QRegularExpression(QString::fromLatin1("qt$"),
+ QRegularExpression::CaseInsensitiveOption)) == -1)
mergeItem = [loader aboutMenuItem];
else
mergeItem = [loader aboutQtMenuItem];
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index b986833f6d..cd597da71c 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -57,8 +57,12 @@
static QCocoaMenuLoader *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
- shared = [[self alloc] init];
- });
+ shared = [[self alloc] init];
+ atexit_b(^{
+ [shared release];
+ shared = nil;
+ });
+ });
return shared;
}
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 26fbe3e4bc..c78f1d5a7f 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -60,18 +60,18 @@ public:
QCocoaNativeInterface();
#ifndef QT_NO_OPENGL
- void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) override;
#endif
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) override;
- NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) override;
#ifndef QT_NO_OPENGL
static void *cglContextForContext(QOpenGLContext *context);
static void *nsOpenGLContextForContext(QOpenGLContext* context);
#endif
- QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const override;
public Q_SLOTS:
void onAppFocusWindowChanged(QWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 58cfcd3c42..955b147bfd 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -233,7 +233,7 @@ QFunctionPointer QCocoaNativeInterface::platformFunction(const QByteArray &funct
if (function == QCocoaWindowFunctions::bottomLeftClippedByNSWindowOffsetIdentifier())
return QFunctionPointer(QCocoaWindowFunctions::BottomLeftClippedByNSWindowOffset(QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic));
- return Q_NULLPTR;
+ return nullptr;
}
void QCocoaNativeInterface::addToMimeList(void *macPasteboardMime)
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.h b/src/plugins/platforms/cocoa/qcocoansmenu.h
new file mode 100644
index 0000000000..8fb0a26f27
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOANSMENU_H
+#define QCOCOANSMENU_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#import <AppKit/AppKit.h>
+
+#include <QtCore/qpointer.h>
+#include <qcocoahelpers.h>
+
+QT_FORWARD_DECLARE_CLASS(QCocoaMenu);
+typedef QPointer<QCocoaMenu> QCocoaMenuPointer;
+
+
+@interface QT_MANGLE_NAMESPACE(QCocoaNSMenuDelegate) : NSObject <NSMenuDelegate>
+
++ (instancetype)sharedMenuDelegate;
+
+- (NSMenuItem *)findItemInMenu:(NSMenu *)menu
+ forKey:(NSString *)key
+ modifiers:(NSUInteger)modifiers;
+
+- (BOOL)validateMenuItem:(NSMenuItem *)item; // NSMenuValidation
+
+@end
+
+@interface QT_MANGLE_NAMESPACE(QCocoaNSMenu) : NSMenu
+
+@property (readonly, nonatomic) QCocoaMenuPointer qpaMenu;
+
+- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu;
+
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenu);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenuDelegate);
+
+#endif // QCOCOANSMENU_H
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm
new file mode 100644
index 0000000000..996a4ff194
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import "qcocoansmenu.h"
+#include "qcocoamenu.h"
+#include "qcocoamenuitem.h"
+#import "qnsview.h"
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/private/qthread_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+static NSString *qt_mac_removePrivateUnicode(NSString* string)
+{
+ int len = [string length];
+ if (len) {
+ QVarLengthArray <unichar, 10> characters(len);
+ bool changed = false;
+ for (int i = 0; i<len; i++) {
+ characters[i] = [string characterAtIndex:i];
+ // check if they belong to key codes in private unicode range
+ // currently we need to handle only the NSDeleteFunctionKey
+ if (characters[i] == NSDeleteFunctionKey) {
+ characters[i] = NSDeleteCharacter;
+ changed = true;
+ }
+ }
+ if (changed)
+ return [NSString stringWithCharacters:characters.data() length:len];
+ }
+ return string;
+}
+
+@implementation QCocoaNSMenu
+
+- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu
+{
+ if ((self = [super initWithTitle:@"Untitled"])) {
+ _qpaMenu = menu;
+ self.autoenablesItems = YES;
+ self.delegate = [QCocoaNSMenuDelegate sharedMenuDelegate];
+ }
+
+ return self;
+}
+
+@end
+
+#define CHECK_MENU_CLASS(menu) Q_ASSERT([menu isMemberOfClass:[QCocoaNSMenu class]])
+
+@implementation QCocoaNSMenuDelegate
+
++ (instancetype)sharedMenuDelegate
+{
+ static QCocoaNSMenuDelegate *shared = nil;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ shared = [[self alloc] init];
+ atexit_b(^{
+ [shared release];
+ shared = nil;
+ });
+ });
+ return shared;
+}
+
+- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
+{
+ CHECK_MENU_CLASS(menu);
+ return menu.numberOfItems;
+}
+
+- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
+{
+ Q_UNUSED(index);
+ CHECK_MENU_CLASS(menu);
+
+ if (shouldCancel)
+ return NO;
+
+ const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
+ if (qpaMenu.isNull())
+ return YES;
+
+ auto *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
+ if (qpaMenu->items().contains(menuItem)) {
+ if (QCocoaMenu *itemSubmenu = menuItem->menu())
+ itemSubmenu->setAttachedItem(item);
+ }
+
+ return YES;
+}
+
+- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
+{
+ CHECK_MENU_CLASS(menu);
+ auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
+ if (qpaItem)
+ qpaItem->hovered();
+}
+
+- (void)menuWillOpen:(NSMenu *)menu
+{
+ CHECK_MENU_CLASS(menu);
+ const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
+ if (qpaMenu.isNull())
+ return;
+
+ qpaMenu->setIsOpen(true);
+ emit qpaMenu->aboutToShow();
+}
+
+- (void)menuDidClose:(NSMenu *)menu
+{
+ CHECK_MENU_CLASS(menu);
+ const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
+ if (qpaMenu.isNull())
+ return;
+
+ qpaMenu->setIsOpen(false);
+ // wrong, but it's the best we can do
+ emit qpaMenu->aboutToHide();
+}
+
+- (void)itemFired:(NSMenuItem *)item
+{
+ auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
+ // Menu-holding items also get a target to play nicely
+ // with NSMenuValidation but should not trigger.
+ if (!qpaItem || qpaItem->menu())
+ return;
+
+ QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
+ QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
+
+ static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
+ activatedSignal.invoke(qpaItem, Qt::QueuedConnection);
+}
+
+- (BOOL)validateMenuItem:(NSMenuItem*)item
+{
+ auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
+ // Menu-holding items are always enabled, as it's conventional in Cocoa
+ if (!qpaItem || qpaItem->menu())
+ return YES;
+
+ return qpaItem->isEnabled();
+}
+
+- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
+{
+ /*
+ Check if the menu actually has a keysequence defined for this key event.
+ If it does, then we will first send the key sequence to the QWidget that has focus
+ since (in Qt's eyes) it needs to a chance at the key event first (QEvent::ShortcutOverride).
+ If the widget accepts the key event, we then return YES, but set the target and action to be nil,
+ which means that the action should not be triggered, and instead dispatch the event ourselves.
+ In every other case we return NO, which means that Cocoa can do as it pleases
+ (i.e., fire the menu action).
+ */
+
+ CHECK_MENU_CLASS(menu);
+
+ // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
+ static const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
+
+ // Change the private unicode keys to the ones used in setting the "Key Equivalents"
+ NSString *characters = qt_mac_removePrivateUnicode(event.charactersIgnoringModifiers);
+ const auto modifiers = event.modifierFlags & mask;
+ NSMenuItem *keyEquivalentItem = [self findItemInMenu:menu
+ forKey:characters
+ modifiers:modifiers];
+ if (!keyEquivalentItem) {
+ // Maybe the modified character is what we're looking for after all
+ characters = qt_mac_removePrivateUnicode(event.characters);
+ keyEquivalentItem = [self findItemInMenu:menu
+ forKey:characters
+ modifiers:modifiers];
+ }
+
+ if (keyEquivalentItem) {
+ if (!keyEquivalentItem.target) {
+ // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder
+ // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel.
+ // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal
+ // (modal sheet, window modal, application modal).
+ // Whatever the current first responder is, let's give it a chance
+ // and do not touch the Qt's focusObject (which is different from some native view
+ // having a focus inside NSSave/OpenPanel.
+ *target = nil;
+ *action = keyEquivalentItem.action;
+ return YES;
+ }
+
+ QObject *object = qApp->focusObject();
+ if (object) {
+ QChar ch;
+ int keyCode;
+ ulong nativeModifiers = [event modifierFlags];
+ Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers];
+ NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers];
+ NSString *characters = [event characters];
+
+ if ([charactersIgnoringModifiers length] > 0) { // convert the first character into a key code
+ if ((modifiers & Qt::ControlModifier) && ([characters length] != 0)) {
+ ch = QChar([characters characterAtIndex:0]);
+ } else {
+ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+ }
+ keyCode = qt_mac_cocoaKey2QtKey(ch);
+ } else {
+ // might be a dead key
+ ch = QChar::ReplacementCharacter;
+ keyCode = Qt::Key_unknown;
+ }
+
+ QKeyEvent accel_ev(QEvent::ShortcutOverride, (keyCode & (~Qt::KeyboardModifierMask)),
+ Qt::KeyboardModifiers(modifiers & Qt::KeyboardModifierMask));
+ accel_ev.ignore();
+ QCoreApplication::sendEvent(object, &accel_ev);
+ if (accel_ev.isAccepted()) {
+ [[NSApp keyWindow] sendEvent: event];
+ *target = nil;
+ *action = nil;
+ return YES;
+ }
+ }
+ }
+
+ return NO;
+}
+
+- (NSMenuItem *)findItemInMenu:(NSMenu *)menu
+ forKey:(NSString *)key
+ modifiers:(NSUInteger)modifiers
+{
+ // Find an item in 'menu' that has the same key equivalent as specified by
+ // 'key' and 'modifiers'. We ignore disabled, hidden and separator items.
+ // In a similar fashion, we don't need to recurse into submenus because their
+ // delegate will have [menuHasKeyEquivalent:...] invoked at some point.
+
+ for (NSMenuItem *item in menu.itemArray) {
+ if (!item.enabled || item.hidden || item.separatorItem)
+ continue;
+
+ if (item.hasSubmenu)
+ continue;
+
+ NSString *menuKey = item.keyEquivalent;
+ if (menuKey && NSOrderedSame == [menuKey compare:key]
+ && modifiers == item.keyEquivalentModifierMask)
+ return item;
+ }
+
+ return nil;
+}
+
+@end
+
+#undef CHECK_MENU_CLASS
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
index c726cca4e5..20b27f3286 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h
@@ -68,37 +68,37 @@ public:
explicit QCocoaPrintDevice(const QString &id);
virtual ~QCocoaPrintDevice();
- bool isValid() const Q_DECL_OVERRIDE;
- bool isDefault() const Q_DECL_OVERRIDE;
+ bool isValid() const override;
+ bool isDefault() const override;
- QPrint::DeviceState state() const Q_DECL_OVERRIDE;
+ QPrint::DeviceState state() const override;
- QPageSize defaultPageSize() const Q_DECL_OVERRIDE;
+ QPageSize defaultPageSize() const override;
QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
- int resolution) const Q_DECL_OVERRIDE;
+ int resolution) const override;
- int defaultResolution() const Q_DECL_OVERRIDE;
+ int defaultResolution() const override;
- QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE;
+ QPrint::InputSlot defaultInputSlot() const override;
- QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE;
+ QPrint::OutputBin defaultOutputBin() const override;
- QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE;
+ QPrint::DuplexMode defaultDuplexMode() const override;
- QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE;
+ QPrint::ColorMode defaultColorMode() const override;
PMPrinter macPrinter() const;
PMPaper macPaper(const QPageSize &pageSize) const;
protected:
- void loadPageSizes() const Q_DECL_OVERRIDE;
- void loadResolutions() const Q_DECL_OVERRIDE;
- void loadInputSlots() const Q_DECL_OVERRIDE;
- void loadOutputBins() const Q_DECL_OVERRIDE;
- void loadDuplexModes() const Q_DECL_OVERRIDE;
- void loadColorModes() const Q_DECL_OVERRIDE;
- void loadMimeTypes() const Q_DECL_OVERRIDE;
+ void loadPageSizes() const override;
+ void loadResolutions() const override;
+ void loadInputSlots() const override;
+ void loadOutputBins() const override;
+ void loadDuplexModes() const override;
+ void loadColorModes() const override;
+ void loadMimeTypes() const override;
private:
QPageSize createPageSize(const PMPaper &paper) const;
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index 39fcf285ed..bfe6cd09b6 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -46,6 +46,15 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PRINTER
+// The CUPS PPD APIs were deprecated in CUPS 1.6/macOS 10.8, but
+// as long as we're supporting RHEL 6, which still ships CUPS 1.4
+// we're not going to rewrite this, as we want to share the code
+// between macOS and Linux for the CUPS-bits. See discussion in
+// https://bugreports.qt.io/browse/QTBUG-56545
+#pragma message "Disabling CUPS PPD deprecation warnings. This should be fixed once we drop support for RHEL6 (QTBUG-56545)"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode)
{
if (mode == kPMDuplexTumble)
@@ -474,6 +483,8 @@ PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const
return paper;
}
+#pragma clang diagnostic pop
+
#endif // QT_NO_PRINTER
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
index a07bf0ec1b..40a638207a 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h
+++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h
@@ -53,12 +53,12 @@ public:
QCocoaPrinterSupport();
~QCocoaPrinterSupport();
- QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) Q_DECL_OVERRIDE;
- QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE;
+ QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
+ QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) override;
- QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE;
- QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE;
- QString defaultPrintDeviceId() const Q_DECL_OVERRIDE;
+ QPrintDevice createPrintDevice(const QString &id) override;
+ QStringList availablePrintDeviceIds() const override;
+ QString defaultPrintDeviceId() const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h
index 937002f493..3d59c3de79 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.h
+++ b/src/plugins/platforms/cocoa/qcocoascreen.h
@@ -56,20 +56,20 @@ public:
// ----------------------------------------------------
// Virtual methods overridden from QPlatformScreen
- QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; }
- QRect availableGeometry() const Q_DECL_OVERRIDE { return m_availableGeometry; }
- int depth() const Q_DECL_OVERRIDE { return m_depth; }
- QImage::Format format() const Q_DECL_OVERRIDE { return m_format; }
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_physicalSize; }
- QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_logicalDpi; }
- qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; }
- QString name() const Q_DECL_OVERRIDE { return m_name; }
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor; }
- QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
- QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
- QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
+ QRect geometry() const override { return m_geometry; }
+ QRect availableGeometry() const override { return m_availableGeometry; }
+ int depth() const override { return m_depth; }
+ QImage::Format format() const override { return m_format; }
+ qreal devicePixelRatio() const override;
+ QSizeF physicalSize() const override { return m_physicalSize; }
+ QDpi logicalDpi() const override { return m_logicalDpi; }
+ qreal refreshRate() const override { return m_refreshRate; }
+ QString name() const override { return m_name; }
+ QPlatformCursor *cursor() const override { return m_cursor; }
+ QWindow *topLevelAt(const QPoint &point) const override;
+ QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; }
+ QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
// ----------------------------------------------------
// Additional methods
@@ -77,16 +77,12 @@ public:
NSScreen *nativeScreen() const;
void updateGeometry();
- QPointF mapToNative(const QPointF &pos) const { return flipCoordinate(pos); }
- QRectF mapToNative(const QRectF &rect) const { return flipCoordinate(rect); }
- QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); }
- QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); }
-
static QCocoaScreen *primaryScreen();
-private:
- QPointF flipCoordinate(const QPointF &pos) const;
- QRectF flipCoordinate(const QRectF &rect) const;
+ static CGPoint mapToNative(const QPointF &pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
+ static CGRect mapToNative(const QRectF &rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
+ static QPointF mapFromNative(CGPoint pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
+ static QRectF mapFromNative(CGRect rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
public:
int m_screenIndex;
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index f523873bde..ed1b19cd53 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -75,32 +75,36 @@ NSScreen *QCocoaScreen::nativeScreen() const
return [screens objectAtIndex:m_screenIndex];
}
-/*!
- Flips the Y coordinate of the point between quadrant I and IV.
+static QString displayName(CGDirectDisplayID displayID)
+{
+ QIOType<io_iterator_t> iterator;
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+ IOServiceMatching("IODisplayConnect"), &iterator))
+ return QString();
+
+ QIOType<io_service_t> display;
+ while ((display = IOIteratorNext(iterator)) != 0)
+ {
+ NSDictionary *info = [(__bridge NSDictionary*)IODisplayCreateInfoDictionary(
+ display, kIODisplayOnlyPreferredName) autorelease];
+
+ if ([[info objectForKey:@kDisplayVendorID] longValue] != CGDisplayVendorNumber(displayID))
+ continue;
- The native coordinate system on macOS uses quadrant I, with origin
- in bottom left, and Qt uses quadrant IV, with origin in top left.
+ if ([[info objectForKey:@kDisplayProductID] longValue] != CGDisplayModelNumber(displayID))
+ continue;
- By flippig the Y coordinate, we can map the position between the
- two coordinate systems.
-*/
-QPointF QCocoaScreen::flipCoordinate(const QPointF &pos) const
-{
- return QPointF(pos.x(), m_geometry.height() - pos.y());
-}
+ if ([[info objectForKey:@kDisplaySerialNumber] longValue] != CGDisplaySerialNumber(displayID))
+ continue;
-/*!
- Flips the Y coordinate of the rectangle between quadrant I and IV.
+ NSDictionary *localizedNames = [info objectForKey:@kDisplayProductName];
+ if (![localizedNames count])
+ break; // Correct screen, but no name in dictionary
- The native coordinate system on macOS uses quadrant I, with origin
- in bottom left, and Qt uses quadrant IV, with origin in top left.
+ return QString::fromNSString([localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]]);
+ }
- By flippig the Y coordinate, we can map the rectangle between the
- two coordinate systems.
-*/
-QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const
-{
- return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size());
+ return QString();
}
void QCocoaScreen::updateGeometry()
@@ -109,20 +113,10 @@ void QCocoaScreen::updateGeometry()
if (!nsScreen)
return;
- // At this point the geometry is in native coordinates, but the size
- // is correct, which we take advantage of next when we map the native
- // coordinates to the Qt coordinate system.
- m_geometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.frame)).toRect();
- m_availableGeometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.visibleFrame)).toRect();
-
- // The reference screen for the geometry is always the primary screen, but since
- // we may be in the process of creating and registering the primary screen, we
- // must special-case that and assign it direcly.
- QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ?
- this : QCocoaScreen::primaryScreen();
-
- m_geometry = primaryScreen->mapFromNative(m_geometry).toRect();
- m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect();
+ // The reference screen for the geometry is always the primary screen
+ QRectF primaryScreenGeometry = QRectF::fromCGRect([[NSScreen screens] firstObject].frame);
+ m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
+ m_availableGeometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.visibleFrame), primaryScreenGeometry).toRect();
m_format = QImage::Format_RGB32;
m_depth = NSBitsPerPixelFromDepth([nsScreen depth]);
@@ -139,12 +133,7 @@ void QCocoaScreen::updateGeometry()
if (refresh > 0)
m_refreshRate = refresh;
- // Get m_name (brand/model of the monitor)
- NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName);
- NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
- if ([localizedNames count] > 0)
- m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
- [deviceInfo release];
+ m_name = displayName(dpy);
QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
@@ -170,7 +159,7 @@ QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingType
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
- NSPoint screenPoint = qt_mac_flipPoint(point);
+ NSPoint screenPoint = mapToNative(point);
// Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint:
// belowWindowWithWindowNumber] may return windows that are not interesting
@@ -275,6 +264,30 @@ QCocoaScreen *QCocoaScreen::primaryScreen()
return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
}
+CGPoint QCocoaScreen::mapToNative(const QPointF &pos, QCocoaScreen *screen)
+{
+ Q_ASSERT(screen);
+ return qt_mac_flip(pos, screen->geometry()).toCGPoint();
+}
+
+CGRect QCocoaScreen::mapToNative(const QRectF &rect, QCocoaScreen *screen)
+{
+ Q_ASSERT(screen);
+ return qt_mac_flip(rect, screen->geometry()).toCGRect();
+}
+
+QPointF QCocoaScreen::mapFromNative(CGPoint pos, QCocoaScreen *screen)
+{
+ Q_ASSERT(screen);
+ return qt_mac_flip(QPointF::fromCGPoint(pos), screen->geometry());
+}
+
+QRectF QCocoaScreen::mapFromNative(CGRect rect, QCocoaScreen *screen)
+{
+ Q_ASSERT(screen);
+ return qt_mac_flip(QRectF::fromCGRect(rect), screen->geometry());
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QCocoaScreen *screen)
{
diff --git a/src/plugins/platforms/cocoa/qcocoaservices.h b/src/plugins/platforms/cocoa/qcocoaservices.h
index c2ceede0f0..62a8891f96 100644
--- a/src/plugins/platforms/cocoa/qcocoaservices.h
+++ b/src/plugins/platforms/cocoa/qcocoaservices.h
@@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE
class QCocoaServices : public QPlatformServices
{
public:
- bool openUrl(const QUrl &url) Q_DECL_OVERRIDE;
- bool openDocument(const QUrl &url) Q_DECL_OVERRIDE;
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
index d542a3cb8f..2f1a1e42a9 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
@@ -57,17 +57,17 @@ class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon
public:
QCocoaSystemTrayIcon() : m_sys(0) {}
- void init() Q_DECL_OVERRIDE;
- void cleanup() Q_DECL_OVERRIDE;
- void updateIcon(const QIcon &icon) Q_DECL_OVERRIDE;
- void updateToolTip(const QString &toolTip) Q_DECL_OVERRIDE;
- void updateMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE;
+ void init() override;
+ void cleanup() override;
+ void updateIcon(const QIcon &icon) override;
+ void updateToolTip(const QString &toolTip) override;
+ void updateMenu(QPlatformMenu *menu) override;
+ QRect geometry() const override;
void showMessage(const QString &title, const QString &msg,
- const QIcon& icon, MessageIcon iconType, int secs) Q_DECL_OVERRIDE;
+ const QIcon& icon, MessageIcon iconType, int secs) override;
- bool isSystemTrayAvailable() const Q_DECL_OVERRIDE;
- bool supportsMessages() const Q_DECL_OVERRIDE;
+ bool isSystemTrayAvailable() const override;
+ bool supportsMessages() const override;
private:
QSystemTrayIconSys *m_sys;
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index 27c071a8cd..69eaf8db56 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -56,25 +56,25 @@ public:
void reset();
- QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE;
- QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE;
- QPlatformMenuBar* createPlatformMenuBar() const Q_DECL_OVERRIDE;
+ QPlatformMenuItem* createPlatformMenuItem() const override;
+ QPlatformMenu* createPlatformMenu() const override;
+ QPlatformMenuBar* createPlatformMenuBar() const override;
#ifndef QT_NO_SYSTEMTRAYICON
- QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const Q_DECL_OVERRIDE;
+ QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
#endif
- bool usePlatformNativeDialog(DialogType dialogType) const Q_DECL_OVERRIDE;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const Q_DECL_OVERRIDE;
+ bool usePlatformNativeDialog(DialogType dialogType) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const override;
- const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE;
- const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE;
- QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE;
+ const QPalette *palette(Palette type = SystemPalette) const override;
+ const QFont *font(Font type = SystemFont) const override;
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = 0) const override;
- QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE;
- QString standardButtonText(int button) const Q_DECL_OVERRIDE;
- QKeySequence standardButtonShortcut(int button) const Q_DECL_OVERRIDE;
+ QVariant themeHint(ThemeHint hint) const override;
+ QString standardButtonText(int button) const override;
+ QKeySequence standardButtonShortcut(int button) const override;
static const char *name;
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 5239864ad8..93f0400916 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -98,7 +98,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeNotificationReceiver);
{
Q_UNUSED(notification);
mPrivate->reset();
- QWindowSystemInterface::handleThemeChange(Q_NULLPTR);
+ QWindowSystemInterface::handleThemeChange(nullptr);
}
@end
@@ -127,7 +127,7 @@ QCocoaTheme::~QCocoaTheme()
void QCocoaTheme::reset()
{
delete m_systemPalette;
- m_systemPalette = Q_NULLPTR;
+ m_systemPalette = nullptr;
qDeleteAll(m_palettes);
m_palettes.clear();
}
@@ -275,7 +275,7 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
}
if (iconType != 0) {
QPixmap pixmap;
- IconRef icon = Q_NULLPTR;
+ IconRef icon = nullptr;
GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon);
if (icon) {
@@ -347,6 +347,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
return QVariant(int(HoverEffect));
case QPlatformTheme::SpellCheckUnderlineStyle:
return QVariant(int(QTextCharFormat::DotLine));
+ case QPlatformTheme::UseFullScreenForPopupMenu:
+ return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen));
default:
break;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 6fbe29f683..fb91c53a7a 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -97,37 +97,37 @@ public:
void initialize() override;
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &rect) override;
+ QRect geometry() const override;
void setCocoaGeometry(const QRect &rect);
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
- void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
- void setWindowFilePath(const QString &filePath) Q_DECL_OVERRIDE;
- void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
- void setAlertState(bool enabled) Q_DECL_OVERRIDE;
- bool isAlertState() const Q_DECL_OVERRIDE;
- void raise() Q_DECL_OVERRIDE;
- void lower() Q_DECL_OVERRIDE;
- bool isExposed() const Q_DECL_OVERRIDE;
+ void setVisible(bool visible) override;
+ void setWindowFlags(Qt::WindowFlags flags) override;
+ void setWindowState(Qt::WindowStates state) override;
+ void setWindowTitle(const QString &title) override;
+ void setWindowFilePath(const QString &filePath) override;
+ void setWindowIcon(const QIcon &icon) override;
+ void setAlertState(bool enabled) override;
+ bool isAlertState() const override;
+ void raise() override;
+ void lower() override;
+ bool isExposed() const override;
bool isOpaque() const;
- void propagateSizeHints() Q_DECL_OVERRIDE;
- void setOpacity(qreal level) Q_DECL_OVERRIDE;
- void setMask(const QRegion &region) Q_DECL_OVERRIDE;
- bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
- bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
- QMargins frameMargins() const Q_DECL_OVERRIDE;
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ void propagateSizeHints() override;
+ void setOpacity(qreal level) override;
+ void setMask(const QRegion &region) override;
+ bool setKeyboardGrabEnabled(bool grab) override;
+ bool setMouseGrabEnabled(bool grab) override;
+ QMargins frameMargins() const override;
+ QSurfaceFormat format() const override;
- bool isForeignWindow() const Q_DECL_OVERRIDE;
+ bool isForeignWindow() const override;
void requestUpdate() override;
- void requestActivateWindow() Q_DECL_OVERRIDE;
+ void requestActivateWindow() override;
- WId winId() const Q_DECL_OVERRIDE;
- void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
+ WId winId() const override;
+ void setParent(const QPlatformWindow *window) override;
NSView *view() const;
NSWindow *nativeWindow() const;
@@ -167,10 +167,10 @@ public:
QCocoaGLContext *currentContext() const;
#endif
- bool setWindowModified(bool modified) Q_DECL_OVERRIDE;
+ bool setWindowModified(bool modified) override;
- void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE;
- bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE
+ void setFrameStrutEventsEnabled(bool enabled) override;
+ bool frameStrutEventsEnabled() const override
{ return m_frameStrutEventsEnabled; }
void setMenubar(QCocoaMenuBar *mb);
@@ -187,7 +187,7 @@ public:
void applyContentBorderThickness(NSWindow *window = nullptr);
void updateNSToolbar();
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ qreal devicePixelRatio() const override;
QWindow *childWindowAt(QPoint windowPoint);
bool shouldRefuseKeyWindowAndFirstResponder();
@@ -209,8 +209,6 @@ protected:
void recreateWindowIfNeeded();
QCocoaNSWindow *createNSWindow(bool shouldBePanel);
- QRect nativeWindowGeometry() const;
-
Qt::WindowState windowState() const;
void applyWindowState(Qt::WindowStates newState);
void toggleMaximized();
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index e86cc2d955..c000c90a85 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -287,7 +287,7 @@ QRect QCocoaWindow::geometry() const
NSPoint windowPoint = [m_view convertPoint:NSMakePoint(0, 0) toView:nil];
NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
NSPoint screenPoint = screenRect.origin;
- QPoint position = qt_mac_flipPoint(screenPoint).toPoint();
+ QPoint position = QCocoaScreen::mapFromNative(screenPoint).toPoint();
QSize size = QRectF::fromCGRect(NSRectToCGRect([m_view bounds])).toRect().size();
return QRect(position, size);
}
@@ -310,7 +310,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
}
if (isContentView()) {
- NSRect bounds = qt_mac_flipRect(rect);
+ NSRect bounds = QCocoaScreen::mapToNative(rect);
[m_view.window setFrame:[m_view.window frameRectForContentRect:bounds] display:YES animate:NO];
} else {
[m_view setFrame:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
@@ -403,7 +403,7 @@ void QCocoaWindow::setVisible(bool visible)
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
removeMonitor();
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
- QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]);
+ QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]);
QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
cocoaButton2QtButton([e buttonNumber]));
}];
@@ -1116,7 +1116,7 @@ void QCocoaWindow::handleGeometryChange()
CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame];
// The result above is in native screen coordinates, so remap to the Qt coordinate system
- newGeometry = QCocoaScreen::primaryScreen()->mapFromNative(QRectF::fromCGRect(contentRect)).toRect();
+ newGeometry = QCocoaScreen::mapFromNative(contentRect).toRect();
} else {
// QNSView has isFlipped set, so no need to remap the geometry
newGeometry = QRectF::fromCGRect(m_view.frame).toRect();
@@ -1378,7 +1378,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
rect.translate(-targetScreen->geometry().topLeft());
QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
- NSRect frame = NSRectFromCGRect(cocoaScreen->mapToNative(rect).toCGRect());
+ NSRect frame = QCocoaScreen::mapToNative(rect, cocoaScreen);
// Note: The macOS window manager has a bug, where if a screen is rotated, it will not allow
// a window to be created within the area of the screen that has a Y coordinate (I quadrant)
@@ -1474,19 +1474,6 @@ void QCocoaWindow::removeMonitor()
monitor = nil;
}
-// Returns the current global screen geometry for the nswindow associated with this window.
-QRect QCocoaWindow::nativeWindowGeometry() const
-{
- if (!isContentView())
- return geometry();
-
- NSRect rect = m_view.window.frame;
- QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window());
- int flippedY = onScreen->geometry().height() - rect.origin.y - rect.size.height; // account for nswindow inverted y.
- QRect qRect = QRect(rect.origin.x, flippedY, rect.size.width, rect.size.height);
- return qRect;
-}
-
/*!
Applies the given state to the NSWindow, going in/out of minimize/zoomed/fullscreen
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 79f8af7783..9eca4d2d43 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -39,6 +39,7 @@
#include "qmultitouch_mac_p.h"
#include "qcocoahelpers.h"
+#include "qcocoascreen.h"
#include <private/qtouchdevice_p.h>
QT_BEGIN_NAMESPACE
@@ -83,7 +84,7 @@ void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase)
if (_touchPoint.id == 0 && phase == NSTouchPhaseBegan) {
_trackpadReferencePos = qnpos;
- _screenReferencePos = qt_mac_flipPoint([NSEvent mouseLocation]);
+ _screenReferencePos = QCocoaScreen::mapFromNative([NSEvent mouseLocation]);
}
QPointF screenPos = _screenReferencePos;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 61f0012a2d..32f73759c2 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -42,6 +42,7 @@
#include "qnsview.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include "qcocoascreen.h"
#include "qmultitouch_mac_p.h"
#include "qcocoadrag.h"
#include "qcocoainputcontext.h"
@@ -442,8 +443,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
nsWindowPoint = windowRect.origin; // NSWindow coordinates
NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates
*qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y); // NSView/QWindow coordinates
-
- *qtScreenPoint = QPointF(mouseLocation.x, qt_mac_flipYCoordinate(mouseLocation.y)); // Qt screen coordinates
+ *qtScreenPoint = QCocoaScreen::mapFromNative(mouseLocation);
}
- (void)resetMouseButtons
@@ -554,7 +554,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil];
QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y);
NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin;
- QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y));
+ QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
ulong timestamp = [theEvent timestamp] * 1000;
QWindowSystemInterface::handleFrameStrutMouseEvent(m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons);
@@ -646,7 +646,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if (!popups->isEmpty()) {
// Check if the click is outside all popups.
bool inside = false;
- QPointF qtScreenPoint = qt_mac_flipPoint([self screenMousePoint:theEvent]);
+ QPointF qtScreenPoint = QCocoaScreen::mapFromNative([self screenMousePoint:theEvent]);
for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) {
if ((*it)->geometry().contains(qtScreenPoint.toPoint())) {
inside = true;
@@ -689,7 +689,8 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if ([self hasMarkedText]) {
[[NSTextInputContext currentInputContext] handleEvent:theEvent];
} else {
- if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) {
+ auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
+ if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & ctrlOrMetaModifier) {
m_buttons |= Qt::RightButton;
m_sendUpAsRightButton = true;
} else {
@@ -1314,15 +1315,16 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags
{
+ const bool dontSwapCtrlAndMeta = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
Qt::KeyboardModifiers qtMods =Qt::NoModifier;
if (modifierFlags & NSShiftKeyMask)
qtMods |= Qt::ShiftModifier;
if (modifierFlags & NSControlKeyMask)
- qtMods |= Qt::MetaModifier;
+ qtMods |= dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier;
if (modifierFlags & NSAlternateKeyMask)
qtMods |= Qt::AltModifier;
if (modifierFlags & NSCommandKeyMask)
- qtMods |= Qt::ControlModifier;
+ qtMods |= dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier;
if (modifierFlags & NSNumericPadKeyMask)
qtMods |= Qt::KeypadModifier;
return qtMods;
@@ -1355,7 +1357,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
// ALT+E to be used as a shortcut with an English keyboard even though
// pressing ALT+E will give a dead key while doing normal text input.
if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
- if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
+ auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
+ if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
else if ([characters length] != 0)
ch = QChar([characters characterAtIndex:0]);
@@ -1504,10 +1507,17 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
if ((delta & mac_mask) == 0u)
continue;
+ Qt::Key qtCode = modifier_key_symbols[i].qt_code;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ if (qtCode == Qt::Key_Meta)
+ qtCode = Qt::Key_Control;
+ else if (qtCode == Qt::Key_Control)
+ qtCode = Qt::Key_Meta;
+ }
QWindowSystemInterface::handleKeyEvent(m_platformWindow->window(),
timestamp,
(lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress,
- modifier_key_symbols[i].qt_code,
+ qtCode,
qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]);
}
}
@@ -1739,14 +1749,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
// The returned rect is always based on the internal cursor.
QRect mr = qApp->inputMethod()->cursorRectangle().toRect();
- QPoint mp = m_platformWindow->window()->mapToGlobal(mr.bottomLeft());
-
- NSRect rect;
- rect.origin.x = mp.x();
- rect.origin.y = qt_mac_flipYCoordinate(mp.y());
- rect.size.width = mr.width();
- rect.size.height = mr.height();
- return rect;
+ mr.moveBottomLeft(m_platformWindow->window()->mapToGlobal(mr.bottomLeft()));
+ return QCocoaScreen::mapToNative(mr);
}
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
@@ -2032,8 +2036,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
NSPoint windowPoint = [self.window convertRectFromScreen:NSMakeRect(screenPoint.x, screenPoint.y, 1, 1)].origin;
NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; // NSView/QWindow coordinates
QPoint qtWindowPoint(nsViewPoint.x, nsViewPoint.y);
-
- QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y));
+ QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_platformWindow->window(), target, qtWindowPoint), qtScreenPoint, m_buttons);
}
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 7e241e3ae6..3f363b62d5 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -108,7 +108,7 @@ CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) {
return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy());
}
-inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevice *pdev)
+inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col)
{
CGFloat components[] = {
qt_mac_convert_color_to_cg(col.red()),
@@ -116,7 +116,8 @@ inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevi
qt_mac_convert_color_to_cg(col.blue()),
qt_mac_convert_color_to_cg(col.alpha())
};
- return CGColorCreate(qt_mac_colorSpaceForDeviceType(pdev), components);
+ QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ return CGColorCreate(colorSpace, components);
}
// There's architectural problems with using native gradients
@@ -239,81 +240,6 @@ static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0)
return ret;
}
-CGColorSpaceRef QCoreGraphicsPaintEngine::m_genericColorSpace = 0;
-QHash<CGDirectDisplayID, CGColorSpaceRef> QCoreGraphicsPaintEngine::m_displayColorSpaceHash;
-bool QCoreGraphicsPaintEngine::m_postRoutineRegistered = false;
-
-CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace()
-{
-#if 0
- if (!m_genericColorSpace) {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
- m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
- } else
- {
- m_genericColorSpace = CGColorSpaceCreateDeviceRGB();
- }
- if (!m_postRoutineRegistered) {
- m_postRoutineRegistered = true;
- qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces);
- }
- }
- return m_genericColorSpace;
-#else
- // Just return the main display colorspace for the moment.
- return macDisplayColorSpace();
-#endif
-}
-
-/*
- Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc.
- to support multiple displays correctly.
-*/
-CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *widget)
-{
- CGColorSpaceRef colorSpace;
-
- CGDirectDisplayID displayID;
- if (widget == 0) {
- displayID = CGMainDisplayID();
- } else {
- const QRect &qrect = widget->window()->geometry();
- CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height());
- CGDisplayCount throwAway;
- CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway);
- if (dErr != kCGErrorSuccess)
- return macDisplayColorSpace(0); // fall back on main display
- }
- if ((colorSpace = m_displayColorSpaceHash.value(displayID)))
- return colorSpace;
-
- colorSpace = CGDisplayCopyColorSpace(displayID);
- if (colorSpace == 0)
- colorSpace = CGColorSpaceCreateDeviceRGB();
-
- m_displayColorSpaceHash.insert(displayID, colorSpace);
- if (!m_postRoutineRegistered) {
- m_postRoutineRegistered = true;
- qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces);
- }
- return colorSpace;
-}
-
-void QCoreGraphicsPaintEngine::cleanUpMacColorSpaces()
-{
- if (m_genericColorSpace) {
- CFRelease(m_genericColorSpace);
- m_genericColorSpace = 0;
- }
- QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin();
- while (it != m_displayColorSpaceHash.constEnd()) {
- if (it.value())
- CFRelease(it.value());
- ++it;
- }
- m_displayColorSpaceHash.clear();
-}
-
//pattern handling (tiling)
#if 1
# define QMACPATTERN_MASK_MULTIPLIER 32
@@ -377,7 +303,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c)
QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER);
pm.fill(c0);
QMacCGContext pm_ctx(&pm);
- CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev));
+ CGContextSetFillColorWithColor(c, cgColorForQColor(c1));
CGRect rect = CGRectMake(0, 0, w, h);
for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) {
rect.origin.x = x * w;
@@ -409,7 +335,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c)
bool needRestore = false;
if (CGImageIsMask(pat->image)) {
CGContextSaveGState(c);
- CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground, pat->pdev));
+ CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground));
}
CGRect rect = CGRectMake(0, 0, w, h);
qt_mac_drawCGImage(c, &rect, pat->image);
@@ -871,7 +797,7 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co
d->saveGraphicsState();
const QColor &col = d->current.pen.color();
- CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev));
+ CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col));
image = qt_mac_create_imagemask(pm, sr);
} else if (differentSize) {
QCFType<CGImageRef> img = qt_mac_toCGImage(pm.toImage());
@@ -1233,7 +1159,7 @@ QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen)
CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size());
// color
- CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color(), pdev));
+ CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color()));
}
// Add our own patterns here to deal with the fact that the coordinate system
@@ -1276,7 +1202,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(&current.brush),
1, domain, 4, 0, &callbacks);
- CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev);
+ CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
if (bs == Qt::LinearGradientPattern) {
const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad);
const QPointF start(linearGrad->start());
@@ -1315,7 +1241,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
components[0] = qt_mac_convert_color_to_cg(col.red());
components[1] = qt_mac_convert_color_to_cg(col.green());
components[2] = qt_mac_convert_color_to_cg(col.blue());
- base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
+ base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
}
} else {
qpattern->as_mask = true;
@@ -1325,7 +1251,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
components[0] = qt_mac_convert_color_to_cg(col.red());
components[1] = qt_mac_convert_color_to_cg(col.green());
components[2] = qt_mac_convert_color_to_cg(col.blue());
- base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
+ base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
}
int width = qpattern->width(), height = qpattern->height();
qpattern->foreground = current.brush.color();
@@ -1346,10 +1272,12 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
!base_colorspace, &callbks);
CGContextSetFillPattern(hd, fill_pattern, components);
+
CGPatternRelease(fill_pattern);
+ CGColorSpaceRelease(base_colorspace);
CGColorSpaceRelease(fill_colorspace);
} else if (bs != Qt::NoBrush) {
- CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color(), pdev));
+ CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color()));
}
}
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
index 57d985c399..c9519ac827 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
@@ -73,8 +73,6 @@ public:
bool begin(QPaintDevice *pdev);
bool end();
- static CGColorSpaceRef macGenericColorSpace();
- static CGColorSpaceRef macDisplayColorSpace(const QWidget *widget = 0);
void updateState(const QPaintEngineState &state);
@@ -126,10 +124,6 @@ protected:
QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr);
private:
- static bool m_postRoutineRegistered;
- static CGColorSpaceRef m_genericColorSpace;
- static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash;
- static void cleanUpMacColorSpaces();
Q_DISABLE_COPY(QCoreGraphicsPaintEngine)
};
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index c39af870d4..b3d48c1ec3 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -247,7 +247,7 @@ void QMacPrintEnginePrivate::initialize()
QList<int> resolutions = m_printDevice->supportedResolutions();
if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) {
- qSort(resolutions);
+ std::sort(resolutions.begin(), resolutions.end());
if (resolutions.count() > 1 && mode == QPrinter::HighResolution)
resolution.hRes = resolution.vRes = resolutions.last();
else
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
index 2d46a250d5..9514f3e691 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
@@ -150,8 +150,8 @@ public:
PMPrintSession session() const { return static_cast<PMPrintSession>([printInfo PMPrintSession]); }
PMPrintSettings settings() const { return static_cast<PMPrintSettings>([printInfo PMPrintSettings]); }
- QPaintEngine *aggregateEngine() Q_DECL_OVERRIDE { return paintEngine; }
- Qt::HANDLE nativeHandle() Q_DECL_OVERRIDE { return q_func()->handle(); }
+ QPaintEngine *aggregateEngine() override { return paintEngine; }
+ Qt::HANDLE nativeHandle() override { return q_func()->handle(); }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
index 670c4e9840..f72ea2b038 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
@@ -54,12 +54,12 @@ public:
QWindowsDirect2DBackingStore(QWindow *window);
~QWindowsDirect2DBackingStore();
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
- void endPaint() Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &) override;
+ void endPaint() override;
- QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
- void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
QImage toImage() const override;
};
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
index 643ae877d0..d578a58982 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
@@ -161,7 +161,7 @@ void QWindowsDirect2DDeviceContextSuspender::resume()
{
if (m_dc) {
m_dc->resume();
- m_dc = Q_NULLPTR;
+ m_dc = nullptr;
}
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index ea51135583..6d98da5be5 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -48,6 +48,7 @@
#include <qplatformdefs.h>
#include <QtCore/QCoreApplication>
+#include <QtCore/QVersionNumber>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
@@ -73,127 +74,60 @@ public:
QWindowsDirect2DContext m_d2dContext;
};
-class Direct2DVersion
+static QVersionNumber systemD2DVersion()
{
-private:
- Direct2DVersion() = default;
-
- Direct2DVersion(int one, int two, int three, int four)
- : partOne(one)
- , partTwo(two)
- , partThree(three)
- , partFour(four)
- {}
+ static const int bufSize = 512;
+ TCHAR filename[bufSize];
+
+ UINT i = GetSystemDirectory(filename, bufSize);
+ if (i > 0 && i < bufSize) {
+ if (_tcscat_s(filename, bufSize, __TEXT("\\d2d1.dll")) == 0) {
+ DWORD versionInfoSize = GetFileVersionInfoSize(filename, NULL);
+ if (versionInfoSize) {
+ QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize));
+ if (GetFileVersionInfo(filename, 0, versionInfoSize, info.data())) {
+ UINT size;
+ DWORD *fi;
+
+ if (VerQueryValue(info.constData(), __TEXT("\\"),
+ reinterpret_cast<void **>(&fi), &size) && size) {
+ const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
+ return QVersionNumber{HIWORD(verInfo->dwFileVersionMS), LOWORD(verInfo->dwFileVersionMS),
+ HIWORD(verInfo->dwFileVersionLS), LOWORD(verInfo->dwFileVersionLS)};
+ }
+ }
+ }
+ }
+ }
+ return QVersionNumber();
+}
-public:
+static QVersionNumber minimumD2DVersion()
+{
// 6.2.9200.16492 corresponds to Direct2D 1.1 on Windows 7 SP1 with Platform Update
- enum {
+ enum : int {
D2DMinVersionPart1 = 6,
D2DMinVersionPart2 = 2,
D2DMinVersionPart3 = 9200,
D2DMinVersionPart4 = 16492
};
- static Direct2DVersion systemVersion() {
- static const int bufSize = 512;
- TCHAR filename[bufSize];
-
- UINT i = GetSystemDirectory(filename, bufSize);
- if (i > 0 && i < bufSize) {
- if (_tcscat_s(filename, bufSize, __TEXT("\\d2d1.dll")) == 0) {
- DWORD versionInfoSize = GetFileVersionInfoSize(filename, NULL);
- if (versionInfoSize) {
- QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize));
- if (GetFileVersionInfo(filename, 0, versionInfoSize, info.data())) {
- UINT size;
- DWORD *fi;
-
- if (VerQueryValue(info.constData(), __TEXT("\\"),
- reinterpret_cast<void **>(&fi), &size) && size) {
- const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
- return Direct2DVersion(HIWORD(verInfo->dwFileVersionMS),
- LOWORD(verInfo->dwFileVersionMS),
- HIWORD(verInfo->dwFileVersionLS),
- LOWORD(verInfo->dwFileVersionLS));
- }
- }
- }
- }
- }
-
- return Direct2DVersion();
- }
-
- static Direct2DVersion minimumVersion() {
- return Direct2DVersion(D2DMinVersionPart1,
- D2DMinVersionPart2,
- D2DMinVersionPart3,
- D2DMinVersionPart4);
- }
-
- bool isValid() const {
- return partOne || partTwo || partThree || partFour;
- }
-
- bool operator<(const Direct2DVersion &other) {
- int c = cmp(partOne, other.partOne);
- if (c > 0)
- return false;
- if (c < 0)
- return true;
-
- c = cmp(partTwo, other.partTwo);
- if (c > 0)
- return false;
- if (c < 0)
- return true;
-
- c = cmp(partThree, other.partThree);
- if (c > 0)
- return false;
- if (c < 0)
- return true;
-
- c = cmp(partFour, other.partFour);
- if (c > 0)
- return false;
- if (c < 0)
- return true;
-
- return false;
- }
-
- static Q_DECL_CONSTEXPR int cmp(int a, int b) {
- return a - b;
- }
-
- int partOne = 0;
- int partTwo = 0;
- int partThree = 0;
- int partFour = 0;
-};
+ return QVersionNumber{D2DMinVersionPart1, D2DMinVersionPart2, D2DMinVersionPart3, D2DMinVersionPart4};
+}
QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList &paramList)
{
- Direct2DVersion systemVersion = Direct2DVersion::systemVersion();
-
- if (systemVersion.isValid() && systemVersion < Direct2DVersion::minimumVersion()) {
+ const QVersionNumber systemVersion = systemD2DVersion();
+ const QVersionNumber minimumVersion = minimumD2DVersion();
+ if (!systemVersion.isNull() && systemVersion < minimumVersion) {
QString msg = QCoreApplication::translate("QWindowsDirect2DIntegration",
"Qt cannot load the direct2d platform plugin because " \
"the Direct2D version on this system is too old. The " \
"minimum system requirement for this platform plugin " \
"is Windows 7 SP1 with Platform Update.\n\n" \
- "The minimum Direct2D version required is %1.%2.%3.%4. " \
- "The Direct2D version on this system is %5.%6.%7.%8.");
-
- msg = msg.arg(Direct2DVersion::D2DMinVersionPart1)
- .arg(Direct2DVersion::D2DMinVersionPart2)
- .arg(Direct2DVersion::D2DMinVersionPart3)
- .arg(Direct2DVersion::D2DMinVersionPart4)
- .arg(systemVersion.partOne)
- .arg(systemVersion.partTwo)
- .arg(systemVersion.partThree)
- .arg(systemVersion.partFour);
+ "The minimum Direct2D version required is %1. " \
+ "The Direct2D version on this system is %2.")
+ .arg(minimumVersion.toString(), systemVersion.toString());
QString caption = QCoreApplication::translate("QWindowsDirect2DIntegration",
"Cannot load direct2d platform plugin");
@@ -203,7 +137,7 @@ QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringLi
caption.toStdWString().c_str(),
MB_OK | MB_ICONERROR);
- return Q_NULLPTR;
+ return nullptr;
}
QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
index 43f2a08745..39ca1d0dbf 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
@@ -58,15 +58,15 @@ public:
static QWindowsDirect2DIntegration *instance();
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
- QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformNativeInterface *nativeInterface() const override;
+ QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
QWindowsDirect2DContext *direct2DContext() const;
protected:
- QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const Q_DECL_OVERRIDE;
+ QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const override;
private:
explicit QWindowsDirect2DIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h
index d57136129b..fce6ff9969 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.h
@@ -48,7 +48,7 @@ class QWindowsDirect2DNativeInterface : public QWindowsNativeInterface
{
Q_OBJECT
public:
- void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs) Q_DECL_OVERRIDE;
+ void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
index f434ef993c..1f23d604f5 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
@@ -58,11 +58,11 @@ public:
QWindowsDirect2DPaintEngine::Flags paintFlags = QWindowsDirect2DPaintEngine::NoFlag);
~QWindowsDirect2DPaintDevice();
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
- int devType() const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const override;
+ int devType() const override;
protected:
- int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ int metric(PaintDeviceMetric metric) const override;
private:
QScopedPointer<QWindowsDirect2DPaintDevicePrivate> d_ptr;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 164429ba30..95fbd37247 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -804,7 +804,7 @@ public:
const bool alias = !q->antiAliasingEnabled();
QVectorPath::CacheEntry *cacheEntry = path.isCacheable() ? path.lookupCacheData(q)
- : Q_NULLPTR;
+ : nullptr;
if (cacheEntry) {
D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index a8f63af5d5..b9616acd6a 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -65,45 +65,45 @@ public:
QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap *bitmap, Flags flags);
- bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
- bool end() Q_DECL_OVERRIDE;
+ bool begin(QPaintDevice *pdev) override;
+ bool end() override;
- Type type() const Q_DECL_OVERRIDE;
+ Type type() const override;
- void setState(QPainterState *s) Q_DECL_OVERRIDE;
+ void setState(QPainterState *s) override;
- void draw(const QVectorPath &path) Q_DECL_OVERRIDE;
+ void draw(const QVectorPath &path) override;
- void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE;
+ void fill(const QVectorPath &path, const QBrush &brush) override;
void fill(ID2D1Geometry *geometry, const QBrush &brush);
- void stroke(const QVectorPath &path, const QPen &pen) Q_DECL_OVERRIDE;
+ void stroke(const QVectorPath &path, const QPen &pen) override;
void stroke(ID2D1Geometry *geometry, const QPen &pen);
- void clip(const QVectorPath &path, Qt::ClipOperation op) Q_DECL_OVERRIDE;
+ void clip(const QVectorPath &path, Qt::ClipOperation op) override;
- void clipEnabledChanged() Q_DECL_OVERRIDE;
- void penChanged() Q_DECL_OVERRIDE;
- void brushChanged() Q_DECL_OVERRIDE;
- void brushOriginChanged() Q_DECL_OVERRIDE;
- void opacityChanged() Q_DECL_OVERRIDE;
- void compositionModeChanged() Q_DECL_OVERRIDE;
- void renderHintsChanged() Q_DECL_OVERRIDE;
- void transformChanged() Q_DECL_OVERRIDE;
+ void clipEnabledChanged() override;
+ void penChanged() override;
+ void brushChanged() override;
+ void brushOriginChanged() override;
+ void opacityChanged() override;
+ void compositionModeChanged() override;
+ void renderHintsChanged() override;
+ void transformChanged() override;
- void fillRect(const QRectF &rect, const QBrush &brush) Q_DECL_OVERRIDE;
+ void fillRect(const QRectF &rect, const QBrush &brush) override;
- void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE;
- void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE;
+ void drawRects(const QRect *rects, int rectCount) override;
+ void drawRects(const QRectF *rects, int rectCount) override;
- void drawEllipse(const QRectF &r) Q_DECL_OVERRIDE;
- void drawEllipse(const QRect &r) Q_DECL_OVERRIDE;
+ void drawEllipse(const QRectF &r) override;
+ void drawEllipse(const QRect &r) override;
- void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
+ void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor) override;
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
- void drawStaticTextItem(QStaticTextItem *staticTextItem) Q_DECL_OVERRIDE;
- void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE;
+ void drawStaticTextItem(QStaticTextItem *staticTextItem) override;
+ void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
private:
void ensureBrush();
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index 5f65a2313a..0448613a95 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -59,21 +59,21 @@ public:
QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DPaintEngine::Flags flags, QWindowsDirect2DBitmap *bitmap);
~QWindowsDirect2DPlatformPixmap();
- void resize(int width, int height) Q_DECL_OVERRIDE;
- void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
+ void resize(int width, int height) override;
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags) override;
- int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
- void fill(const QColor &color) Q_DECL_OVERRIDE;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+ void fill(const QColor &color) override;
- bool hasAlphaChannel() const Q_DECL_OVERRIDE;
+ bool hasAlphaChannel() const override;
- QImage toImage() const Q_DECL_OVERRIDE;
- QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
+ QImage toImage() const override;
+ QImage toImage(const QRect &rect) const override;
- QPaintEngine* paintEngine() const Q_DECL_OVERRIDE;
+ QPaintEngine* paintEngine() const override;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
+ qreal devicePixelRatio() const override;
+ void setDevicePixelRatio(qreal scaleFactor) override;
QWindowsDirect2DBitmap *bitmap() const;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index 21294cfb15..f81182e0b1 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -209,7 +209,7 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
{
m_pixmap.reset();
m_bitmap.reset();
- m_deviceContext->SetTarget(Q_NULLPTR);
+ m_deviceContext->SetTarget(nullptr);
m_needsFullFlush = true;
if (!m_swapChain)
@@ -241,7 +241,7 @@ QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer()
dpiX, // FLOAT dpiX;
dpiY, // FLOAT dpiY;
D2D1_BITMAP_OPTIONS_TARGET, // D2D1_BITMAP_OPTIONS bitmapOptions;
- Q_NULLPTR // _Field_size_opt_(1) ID2D1ColorContext *colorContext;
+ nullptr // _Field_size_opt_(1) ID2D1ColorContext *colorContext;
};
ComPtr<ID2D1Bitmap1> copy;
HRESULT hr = m_deviceContext.Get()->CreateBitmap(size, NULL, 0, properties, &copy);
@@ -257,7 +257,7 @@ QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer()
return null_result;
}
- return QSharedPointer<QWindowsDirect2DBitmap>(new QWindowsDirect2DBitmap(copy.Get(), Q_NULLPTR));
+ return QSharedPointer<QWindowsDirect2DBitmap>(new QWindowsDirect2DBitmap(copy.Get(), nullptr));
}
void QWindowsDirect2DWindow::setupBitmap()
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
index 156d4660d1..3ac532d938 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
@@ -56,7 +56,7 @@ public:
QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsDirect2DWindow();
- void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
+ void setWindowFlags(Qt::WindowFlags flags) override;
QPixmap *pixmap();
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, const QPoint &offset);
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
index e411ea55e9..1b8f50a1c6 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
@@ -103,7 +103,7 @@ QStringList QEglFSDeviceIntegrationFactory::keys(const QString &pluginPath)
QEglFSDeviceIntegration *QEglFSDeviceIntegrationFactory::create(const QString &key, const QString &pluginPath)
{
- QEglFSDeviceIntegration *integration = Q_NULLPTR;
+ QEglFSDeviceIntegration *integration = nullptr;
#if QT_CONFIG(library)
if (!pluginPath.isEmpty()) {
QCoreApplication::addLibraryPath(pluginPath);
@@ -351,9 +351,28 @@ bool QEglFSDeviceIntegration::supportsSurfacelessContexts() const
return true;
}
+QFunctionPointer QEglFSDeviceIntegration::platformFunction(const QByteArray &function) const
+{
+ Q_UNUSED(function);
+ return nullptr;
+}
+
+void *QEglFSDeviceIntegration::nativeResourceForIntegration(const QByteArray &name)
+{
+ Q_UNUSED(name);
+ return nullptr;
+}
+
+void *QEglFSDeviceIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
+{
+ Q_UNUSED(resource);
+ Q_UNUSED(screen);
+ return nullptr;
+}
+
void *QEglFSDeviceIntegration::wlDisplay() const
{
- return Q_NULLPTR;
+ return nullptr;
}
EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
index 4335554912..71ffb4c69a 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
@@ -103,7 +103,9 @@ public:
virtual int framebufferIndex() const;
virtual bool supportsPBuffers() const;
virtual bool supportsSurfacelessContexts() const;
-
+ virtual QFunctionPointer platformFunction(const QByteArray &function) const;
+ virtual void *nativeResourceForIntegration(const QByteArray &name);
+ virtual void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
virtual void *wlDisplay() const;
static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 9a0be489a8..33878a5f50 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -324,13 +324,14 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource
result = qt_egl_device_integration()->wlDisplay();
break;
default:
+ result = qt_egl_device_integration()->nativeResourceForIntegration(resource);
break;
}
return result;
}
-void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *)
+void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
{
void *result = 0;
@@ -341,6 +342,7 @@ void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QSc
result = reinterpret_cast<void*>(nativeDisplay());
break;
default:
+ result = qt_egl_device_integration()->nativeResourceForScreen(resource, screen);
break;
}
@@ -427,11 +429,9 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function)
#if QT_CONFIG(evdev)
if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
return QFunctionPointer(loadKeymapStatic);
-#else
- Q_UNUSED(function)
#endif
- return 0;
+ return qt_egl_device_integration()->platformFunction(function);
}
void QEglFSIntegration::loadKeymapStatic(const QString &filename)
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
index 6bda262523..c61f04f569 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
@@ -95,7 +95,7 @@ public:
EGLNativeWindowType eglWindow() const;
EGLSurface surface() const;
- QEglFSScreen *screen() const;
+ QEglFSScreen *screen() const override;
bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
index 92ee83fd8f..919ecd01f6 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
@@ -4,6 +4,7 @@ QT_FOR_CONFIG += gui-private
qtConfig(egl_x11): SUBDIRS += eglfs_x11
qtConfig(eglfs_gbm): SUBDIRS *= eglfs_kms_support eglfs_kms
qtConfig(eglfs_egldevice): SUBDIRS *= eglfs_kms_support eglfs_kms_egldevice
+qtConfig(eglfs_vsp2): SUBDIRS += eglfs_kms_vsp2
qtConfig(eglfs_brcm): SUBDIRS += eglfs_brcm
qtConfig(eglfs_mali): SUBDIRS += eglfs_mali
qtConfig(eglfs_viv): SUBDIRS += eglfs_viv
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index 27c0af1f08..43170a3875 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -19,11 +19,13 @@ SOURCES += $$PWD/qeglfskmsgbmmain.cpp \
$$PWD/qeglfskmsgbmintegration.cpp \
$$PWD/qeglfskmsgbmdevice.cpp \
$$PWD/qeglfskmsgbmscreen.cpp \
- $$PWD/qeglfskmsgbmcursor.cpp
+ $$PWD/qeglfskmsgbmcursor.cpp \
+ $$PWD/qeglfskmsgbmwindow.cpp
HEADERS += $$PWD/qeglfskmsgbmintegration.h \
$$PWD/qeglfskmsgbmdevice.h \
$$PWD/qeglfskmsgbmscreen.h \
- $$PWD/qeglfskmsgbmcursor.h
+ $$PWD/qeglfskmsgbmcursor.h \
+ $$PWD/qeglfskmsgbmwindow.h
OTHER_FILES += $$PWD/eglfs_kms.json
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
index 800118362d..9bd7fee1fb 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
@@ -68,7 +68,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen)
: m_screen(screen)
, m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below
- , m_bo(Q_NULLPTR)
+ , m_bo(nullptr)
, m_cursorImage(0, 0, 0, 0, 0, 0)
, m_state(CursorPendingVisible)
{
@@ -118,7 +118,7 @@ QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor()
if (m_bo) {
gbm_bo_destroy(m_bo);
- m_bo = Q_NULLPTR;
+ m_bo = nullptr;
}
}
@@ -132,7 +132,7 @@ void QEglFSKmsGbmCursor::updateMouseStatus()
m_state = visible ? CursorPendingVisible : CursorPendingHidden;
#ifndef QT_NO_CURSOR
- changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos()));
+ changeCursor(nullptr, m_screen->topLevelAt(pos()));
#endif
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index e218d580a2..20127ae7f7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -53,28 +53,17 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
-void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
-{
- Q_UNUSED(fd);
- Q_UNUSED(sequence);
- Q_UNUSED(tv_sec);
- Q_UNUSED(tv_usec);
-
- QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data);
- screen->flipFinished();
-}
-
QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path)
: QEglFSKmsDevice(screenConfig, path)
- , m_gbm_device(Q_NULLPTR)
- , m_globalCursor(Q_NULLPTR)
+ , m_gbm_device(nullptr)
+ , m_globalCursor(nullptr)
{
}
bool QEglFSKmsGbmDevice::open()
{
Q_ASSERT(fd() == -1);
- Q_ASSERT(m_gbm_device == Q_NULLPTR);
+ Q_ASSERT(m_gbm_device == nullptr);
int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
if (fd == -1) {
@@ -103,7 +92,7 @@ void QEglFSKmsGbmDevice::close()
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
- m_gbm_device = Q_NULLPTR;
+ m_gbm_device = nullptr;
}
if (fd() != -1) {
@@ -134,24 +123,13 @@ void QEglFSKmsGbmDevice::destroyGlobalCursor()
if (m_globalCursor) {
qCDebug(qLcEglfsKmsDebug, "Destroying global GBM mouse cursor");
delete m_globalCursor;
- m_globalCursor = Q_NULLPTR;
+ m_globalCursor = nullptr;
}
}
-void QEglFSKmsGbmDevice::handleDrmEvent()
-{
- drmEventContext drmEvent;
- memset(&drmEvent, 0, sizeof(drmEvent));
- drmEvent.version = 2;
- drmEvent.vblank_handler = nullptr;
- drmEvent.page_flip_handler = pageFlipHandler;
-
- drmHandleEvent(fd(), &drmEvent);
-}
-
QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
{
- QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output);
+ QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output, false);
if (!m_globalCursor && screenConfig()->hwCursor()) {
qCDebug(qLcEglfsKmsDebug, "Creating new global GBM mouse cursor");
@@ -161,4 +139,20 @@ QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
return screen;
}
+QPlatformScreen *QEglFSKmsGbmDevice::createHeadlessScreen()
+{
+ return new QEglFSKmsGbmScreen(this, QKmsOutput(), true);
+}
+
+void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen)
+{
+ if (!screenThisScreenClones && screensCloningThisScreen.isEmpty())
+ return;
+
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen);
+ gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
index 08ca28d48e..518e2ce58b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
@@ -65,9 +65,11 @@ public:
QPlatformCursor *globalCursor() const;
void destroyGlobalCursor();
- void handleDrmEvent();
-
QPlatformScreen *createScreen(const QKmsOutput &output) override;
+ QPlatformScreen *createHeadlessScreen() override;
+ void registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen) override;
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
@@ -75,12 +77,6 @@ private:
gbm_device *m_gbm_device;
QEglFSKmsGbmCursor *m_globalCursor;
-
- static void pageFlipHandler(int fd,
- unsigned int sequence,
- unsigned int tv_sec,
- unsigned int tv_usec,
- void *user_data);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index 058791e473..402338197d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -43,21 +43,13 @@
#include "qeglfskmsgbmdevice.h"
#include "qeglfskmsgbmscreen.h"
#include "qeglfskmsgbmcursor.h"
-#include "private/qeglfswindow_p.h"
+#include "qeglfskmsgbmwindow.h"
#include "private/qeglfscursor_p.h"
-#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
-#include <QtEglSupport/private/qeglconvenience_p.h>
#include <QtCore/QLoggingCategory>
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonArray>
-#include <QtGui/qpa/qplatformwindow.h>
-#include <QtGui/qpa/qplatformcursor.h>
#include <QtGui/QScreen>
+#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
#include <gbm.h>
QT_BEGIN_NAMESPACE
@@ -105,7 +97,6 @@ EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const Q
Q_UNUSED(format);
Q_ASSERT(device());
- qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window";
gbm_surface *surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
1, 1,
GBM_FORMAT_XRGB8888,
@@ -134,8 +125,7 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen)
void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
{
QWindow *window = static_cast<QWindow *>(surface->surface());
- QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle());
-
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(window->screen()->handle());
screen->flip();
}
@@ -160,46 +150,6 @@ QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
return new QEglFSKmsGbmDevice(screenConfig(), path);
}
-class QEglFSKmsGbmWindow : public QEglFSWindow
-{
-public:
- QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration)
- : QEglFSWindow(w)
- , m_integration(integration)
- {}
- void resetSurface() override;
- const QEglFSKmsGbmIntegration *m_integration;
-};
-
-void QEglFSKmsGbmWindow::resetSurface()
-{
- QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
- if (gbmScreen->surface()) {
- qWarning("Only single window per screen supported!");
- return;
- }
-
- EGLDisplay display = gbmScreen->display();
- QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
- m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
- m_format = q_glFormatFromConfig(display, m_config, platformFormat);
- m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface());
-
- PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
- const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
- createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
- eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
- }
-
- if (createPlatformWindowSurface) {
- m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
- } else {
- qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
- m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
- }
-}
-
QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const
{
return new QEglFSKmsGbmWindow(window, this);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 87fb3146c7..4742143121 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
@@ -55,6 +55,18 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return drmFormat;
+}
+
+static inline uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat)
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return gbmFormat;
+}
+
void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
{
FrameBuffer *fb = static_cast<FrameBuffer *>(data);
@@ -77,29 +89,34 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(
uint32_t width = gbm_bo_get_width(bo);
uint32_t height = gbm_bo_get_height(bo);
- uint32_t stride = gbm_bo_get_stride(bo);
- uint32_t handle = gbm_bo_get_handle(bo).u32;
+ uint32_t handles[4] = { gbm_bo_get_handle(bo).u32 };
+ uint32_t strides[4] = { gbm_bo_get_stride(bo) };
+ uint32_t offsets[4] = { 0 };
+ uint32_t pixelFormat = gbmFormatToDrmFormat(gbm_bo_get_format(bo));
QScopedPointer<FrameBuffer> fb(new FrameBuffer);
+ qCDebug(qLcEglfsKmsDebug, "Adding FB, size %ux%u, DRM format 0x%x", width, height, pixelFormat);
- int ret = drmModeAddFB(device()->fd(), width, height, 24, 32,
- stride, handle, &fb->fb);
+ int ret = drmModeAddFB2(device()->fd(), width, height, pixelFormat,
+ handles, strides, offsets, &fb->fb, 0);
if (ret) {
qWarning("Failed to create KMS FB!");
- return Q_NULLPTR;
+ return nullptr;
}
gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
return fb.take();
}
-QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output)
- : QEglFSKmsScreen(device, output)
- , m_gbm_surface(Q_NULLPTR)
- , m_gbm_bo_current(Q_NULLPTR)
- , m_gbm_bo_next(Q_NULLPTR)
- , m_cursor(Q_NULLPTR)
+QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless)
+ : QEglFSKmsScreen(device, output, headless)
+ , m_gbm_surface(nullptr)
+ , m_gbm_bo_current(nullptr)
+ , m_gbm_bo_next(nullptr)
+ , m_flipPending(false)
+ , m_cursor(nullptr)
+ , m_cloneSource(nullptr)
{
}
@@ -114,6 +131,8 @@ QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen()
QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
{
QKmsScreenConfig *config = device()->screenConfig();
+ if (config->headless())
+ return nullptr;
if (config->hwCursor()) {
if (!config->separateScreens())
return static_cast<QEglFSKmsGbmDevice *>(device())->globalCursor();
@@ -132,47 +151,112 @@ QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
gbm_surface *QEglFSKmsGbmScreen::createSurface()
{
if (!m_gbm_surface) {
- qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name();
+ uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format);
+ qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s with format 0x%x", qPrintable(name()), gbmFormat);
m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
rawGeometry().width(),
rawGeometry().height(),
- GBM_FORMAT_XRGB8888,
+ gbmFormat,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
}
- return m_gbm_surface;
+ return m_gbm_surface; // not owned, gets destroyed in QEglFSKmsGbmIntegration::destroyNativeWindow() via QEglFSKmsGbmWindow::invalidateSurface()
}
-void QEglFSKmsGbmScreen::destroySurface()
+void QEglFSKmsGbmScreen::resetSurface()
{
- if (m_gbm_bo_current) {
- gbm_bo_destroy(m_gbm_bo_current);
- m_gbm_bo_current = Q_NULLPTR;
- }
+ m_gbm_surface = nullptr;
+}
- if (m_gbm_bo_next) {
- gbm_bo_destroy(m_gbm_bo_next);
- m_gbm_bo_next = Q_NULLPTR;
+void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen)
+{
+ // clone destinations need to know the clone source
+ const bool clonesAnother = screenThisScreenClones != nullptr;
+ if (clonesAnother && !screensCloningThisScreen.isEmpty()) {
+ qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name()));
+ return;
}
+ if (clonesAnother)
+ m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones);
+
+ // clone sources need to know their additional destinations
+ for (QPlatformScreen *s : screensCloningThisScreen) {
+ CloneDestination d;
+ d.screen = static_cast<QEglFSKmsGbmScreen *>(s);
+ m_cloneDests.append(d);
+ }
+}
+
+void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb)
+{
+ QKmsOutput &op(output());
+ const int fd = device()->fd();
+
+ if (!op.mode_set) {
+ op.mode_set = true;
+
+ bool doModeSet = true;
+ drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
+ const bool alreadySet = currentMode && !memcmp(&currentMode->mode, &op.modes[op.mode], sizeof(drmModeModeInfo));
+ if (currentMode)
+ drmModeFreeCrtc(currentMode);
+ if (alreadySet) {
+ static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
+ if (!alwaysDoSet) {
+ qCDebug(qLcEglfsKmsDebug, "Mode already set, skipping modesetting for screen %s", qPrintable(name()));
+ doModeSet = false;
+ }
+ }
- if (m_gbm_surface) {
- gbm_surface_destroy(m_gbm_surface);
- m_gbm_surface = Q_NULLPTR;
+ if (doModeSet) {
+ qCDebug(qLcEglfsKmsDebug, "Setting mode for screen %s", qPrintable(name()));
+ int ret = drmModeSetCrtc(fd,
+ op.crtc_id,
+ fb,
+ 0, 0,
+ &op.connector_id, 1,
+ &op.modes[op.mode]);
+
+ if (ret == 0)
+ setPowerState(PowerStateOn);
+ else
+ qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name()));
+ }
}
}
void QEglFSKmsGbmScreen::waitForFlip()
{
+ if (m_headless || m_cloneSource)
+ return;
+
// Don't lock the mutex unless we actually need to
if (!m_gbm_bo_next)
return;
QMutexLocker lock(&m_waitForFlipMutex);
- while (m_gbm_bo_next)
- static_cast<QEglFSKmsGbmDevice *>(device())->handleDrmEvent();
+ while (m_gbm_bo_next) {
+ drmEventContext drmEvent;
+ memset(&drmEvent, 0, sizeof(drmEvent));
+ drmEvent.version = 2;
+ drmEvent.vblank_handler = nullptr;
+ drmEvent.page_flip_handler = pageFlipHandler;
+ drmHandleEvent(device()->fd(), &drmEvent);
+ }
}
void QEglFSKmsGbmScreen::flip()
{
+ // For headless screen just return silently. It is not necessarily an error
+ // to end up here, so show no warnings.
+ if (m_headless)
+ return;
+
+ if (m_cloneSource) {
+ qWarning("Screen %s clones another screen. swapBuffers() not allowed.", qPrintable(name()));
+ return;
+ }
+
if (!m_gbm_surface) {
qWarning("Cannot sync before platform init!");
return;
@@ -185,60 +269,92 @@ void QEglFSKmsGbmScreen::flip()
}
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
+ ensureModeSet(fb->fb);
QKmsOutput &op(output());
const int fd = device()->fd();
- const uint32_t w = op.modes[op.mode].hdisplay;
- const uint32_t h = op.modes[op.mode].vdisplay;
-
- if (!op.mode_set) {
- int ret = drmModeSetCrtc(fd,
- op.crtc_id,
- fb->fb,
- 0, 0,
- &op.connector_id, 1,
- &op.modes[op.mode]);
-
- if (ret == -1) {
- qErrnoWarning(errno, "Could not set DRM mode!");
- } else {
- op.mode_set = true;
- setPowerState(PowerStateOn);
-
- if (!op.plane_set) {
- op.plane_set = true;
- if (op.wants_plane) {
- int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id,
- uint32_t(-1), 0,
- 0, 0, w, h,
- 0 << 16, 0 << 16, w << 16, h << 16);
- if (ret == -1)
- qErrnoWarning(errno, "drmModeSetPlane failed");
- }
- }
- }
- }
-
+ m_flipPending = true;
int ret = drmModePageFlip(fd,
op.crtc_id,
fb->fb,
DRM_MODE_PAGE_FLIP_EVENT,
this);
if (ret) {
- qErrnoWarning("Could not queue DRM page flip!");
+ qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
+ m_flipPending = false;
gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
- m_gbm_bo_next = Q_NULLPTR;
+ m_gbm_bo_next = nullptr;
+ return;
+ }
+
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen != this) {
+ d.screen->ensureModeSet(fb->fb);
+ d.cloneFlipPending = true;
+ int ret = drmModePageFlip(fd,
+ d.screen->output().crtc_id,
+ fb->fb,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ d.screen);
+ if (ret) {
+ qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
+ d.cloneFlipPending = false;
+ }
+ }
}
}
+void QEglFSKmsGbmScreen::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+ Q_UNUSED(fd);
+ Q_UNUSED(sequence);
+ Q_UNUSED(tv_sec);
+ Q_UNUSED(tv_usec);
+
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data);
+ screen->flipFinished();
+}
+
void QEglFSKmsGbmScreen::flipFinished()
{
+ if (m_cloneSource) {
+ m_cloneSource->cloneDestFlipFinished(this);
+ return;
+ }
+
+ m_flipPending = false;
+ updateFlipStatus();
+}
+
+void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen)
+{
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen == cloneDestScreen) {
+ d.cloneFlipPending = false;
+ break;
+ }
+ }
+ updateFlipStatus();
+}
+
+void QEglFSKmsGbmScreen::updateFlipStatus()
+{
+ Q_ASSERT(!m_cloneSource);
+
+ if (m_flipPending)
+ return;
+
+ for (const CloneDestination &d : m_cloneDests) {
+ if (d.cloneFlipPending)
+ return;
+ }
+
if (m_gbm_bo_current)
gbm_surface_release_buffer(m_gbm_surface,
m_gbm_bo_current);
m_gbm_bo_current = m_gbm_bo_next;
- m_gbm_bo_next = Q_NULLPTR;
+ m_gbm_bo_next = nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
index 341cc95bbe..f5a2122723 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
@@ -54,34 +54,54 @@ class QEglFSKmsGbmCursor;
class QEglFSKmsGbmScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output);
+ QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless);
~QEglFSKmsGbmScreen();
QPlatformCursor *cursor() const override;
- gbm_surface *surface() const { return m_gbm_surface; }
gbm_surface *createSurface();
- void destroySurface();
+ void resetSurface();
+
+ void initCloning(QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen);
void waitForFlip() override;
- void flip() override;
- void flipFinished() override;
+
+ void flip();
private:
+ void flipFinished();
+ void ensureModeSet(uint32_t fb);
+ void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen);
+ void updateFlipStatus();
+
+ static void pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
+
gbm_surface *m_gbm_surface;
gbm_bo *m_gbm_bo_current;
gbm_bo *m_gbm_bo_next;
+ bool m_flipPending;
QScopedPointer<QEglFSKmsGbmCursor> m_cursor;
struct FrameBuffer {
- FrameBuffer() : fb(0) {}
- uint32_t fb;
+ uint32_t fb = 0;
};
static void bufferDestroyedHandler(gbm_bo *bo, void *data);
FrameBuffer *framebufferForBufferObject(gbm_bo *bo);
+ QEglFSKmsGbmScreen *m_cloneSource;
+ struct CloneDestination {
+ QEglFSKmsGbmScreen *screen = nullptr;
+ bool cloneFlipPending = false;
+ };
+ QVector<CloneDestination> m_cloneDests;
+
static QMutex m_waitForFlipMutex;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp
new file mode 100644
index 0000000000..110a592dec
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfskmsgbmwindow.h"
+#include "qeglfskmsgbmintegration.h"
+#include "qeglfskmsgbmscreen.h"
+
+#include <QtEglSupport/private/qeglconvenience_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QEglFSKmsGbmWindow::resetSurface()
+{
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
+ EGLDisplay display = gbmScreen->display();
+ QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
+ m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
+ // One fullscreen window per screen -> the native window is simply the gbm_surface the screen created.
+ m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface());
+
+ PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
+ eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+ }
+
+ if (createPlatformWindowSurface) {
+ m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
+ m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
+ }
+}
+
+void QEglFSKmsGbmWindow::invalidateSurface()
+{
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
+ QEglFSWindow::invalidateSurface();
+ gbmScreen->resetSurface();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
index b1e6183a0f..a19cf7e8bc 100644
--- a/src/plugins/platforms/windows/accessible/comutils.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
@@ -1,6 +1,8 @@
/****************************************************************************
**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -36,29 +38,30 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef COMUTILS_H
-#define COMUTILS_H
-#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__)
-#error Must include windows.h first!
-#endif
+#ifndef QEGLFSKMSGBMWINDOW_H
+#define QEGLFSKMSGBMWINDOW_H
-#include <ocidl.h>
-#include <QtCore/qstring.h>
+#include "private/qeglfswindow_p.h"
QT_BEGIN_NAMESPACE
-class QVariant;
+class QEglFSKmsGbmIntegration;
-// Originally QVariantToVARIANT copied from ActiveQt - renamed to avoid conflicts in static builds.
-bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out);
-
-inline BSTR QStringToBSTR(const QString &str)
+class QEglFSKmsGbmWindow : public QEglFSWindow
{
- return SysAllocStringLen(reinterpret_cast<const OLECHAR *>(str.unicode()), UINT(str.length()));
-}
+public:
+ QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration)
+ : QEglFSWindow(w),
+ m_integration(integration)
+ { }
+ void resetSurface() override;
+ void invalidateSurface() override;
-QT_END_NAMESPACE
+private:
+ const QEglFSKmsGbmIntegration *m_integration;
+};
-#endif // COMUTILS_H
+QT_END_NAMESPACE
+#endif // QEGLFSKMSGBMWINDOW_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
index cca413ff2d..8c8e6260f1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
@@ -58,7 +58,7 @@ bool QEglFSKmsEglDevice::open()
{
Q_ASSERT(fd() == -1);
- int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR);
+ int fd = drmOpen(devicePath().toLocal8Bit().constData(), nullptr);
if (Q_UNLIKELY(fd < 0))
qFatal("Could not open DRM (NV) device");
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index 3af21d768e..a67457a6a5 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
: m_egl_device(EGL_NO_DEVICE_EXT)
- , m_funcs(Q_NULLPTR)
+ , m_funcs(nullptr)
{
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
}
@@ -75,7 +75,7 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat
EGLDisplay display;
if (m_funcs->has_egl_platform_device) {
- display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, Q_NULLPTR);
+ display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, nullptr);
} else {
qWarning("EGL_EXT_platform_device not available, falling back to legacy path!");
display = eglGetDisplay(nativeDisplay);
@@ -162,7 +162,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
qCDebug(qLcEglfsKmsDebug, "Could not query number of EGLStream FIFO frames");
}
- if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) {
+ if (!m_integration->m_funcs->get_output_layers(display, nullptr, nullptr, 0, &count) || count == 0) {
qWarning("No output layers found");
return;
}
@@ -172,7 +172,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
QVector<EGLOutputLayerEXT> layers;
layers.resize(count);
EGLint actualCount;
- if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, layers.data(), count, &actualCount)) {
+ if (!m_integration->m_funcs->get_output_layers(display, nullptr, layers.data(), count, &actualCount)) {
qWarning("Failed to get layers");
return;
}
@@ -180,7 +180,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
QEglFSKmsEglDeviceScreen *cur_screen = static_cast<QEglFSKmsEglDeviceScreen *>(screen());
Q_ASSERT(cur_screen);
QKmsOutput &output(cur_screen->output());
- const uint32_t wantedId = !output.wants_plane ? output.crtc_id : output.plane_id;
+ const uint32_t wantedId = !output.wants_forced_plane ? output.crtc_id : output.forced_plane_id;
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", wantedId);
EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
index a27c89faab..531b73d1dc 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
@@ -105,12 +105,12 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
qErrnoWarning(errno, "drmModeSetCrtc failed");
}
- if (!op.plane_set) {
- op.plane_set = true;
+ if (!op.forced_plane_set) {
+ op.forced_plane_set = true;
- if (op.wants_plane) {
- qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.plane_id);
- int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id, uint32_t(-1), 0,
+ if (op.wants_forced_plane) {
+ qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
+ int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, uint32_t(-1), 0,
0, 0, w, h,
0 << 16, 0 << 16, w << 16, h << 16);
if (ret == -1)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
index 88cf6db33b..4d1321079c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
@@ -19,4 +19,5 @@ SOURCES += $$PWD/qeglfskmsintegration.cpp \
HEADERS += $$PWD/qeglfskmsintegration.h \
$$PWD/qeglfskmsdevice.h \
- $$PWD/qeglfskmsscreen.h
+ $$PWD/qeglfskmsscreen.h \
+ $$PWD/qeglfskmshelpers.h
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmshelpers.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmshelpers.h
new file mode 100644
index 0000000000..c9e5f04a7b
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmshelpers.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSKMSHELPERS_H
+#define QEGLFSKMSHELPERS_H
+
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+inline QString q_fourccToString(uint code)
+{
+ QString s;
+ s.reserve(4);
+ s.append(code & 0xff);
+ s.append((code >> 8) & 0xff);
+ s.append((code >> 16) & 0xff);
+ s.append((code >> 24) & 0xff);
+ return s;
+}
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSKMSHELPERS_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index c77151181e..06bc272050 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
QEglFSKmsIntegration::QEglFSKmsIntegration()
- : m_device(Q_NULLPTR),
+ : m_device(nullptr),
m_screenConfig(new QKmsScreenConfig)
{
}
@@ -78,7 +78,7 @@ void QEglFSKmsIntegration::platformDestroy()
qCDebug(qLcEglfsKmsDebug, "platformDestroy: Closing DRM device");
m_device->close();
delete m_device;
- m_device = Q_NULLPTR;
+ m_device = nullptr;
}
EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const
@@ -133,6 +133,24 @@ bool QEglFSKmsIntegration::supportsPBuffers() const
return m_screenConfig->supportsPBuffers();
}
+void *QEglFSKmsIntegration::nativeResourceForIntegration(const QByteArray &name)
+{
+ if (name == QByteArrayLiteral("dri_fd") && m_device)
+ return (void *) (qintptr) m_device->fd();
+
+ return nullptr;
+}
+
+void *QEglFSKmsIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
+{
+ QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen->handle());
+ if (s) {
+ if (resource == QByteArrayLiteral("dri_crtcid"))
+ return (void *) (qintptr) s->output().crtc_id;
+ }
+ return nullptr;
+}
+
QKmsDevice *QEglFSKmsIntegration::device() const
{
return m_device;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
index 9955616919..e2c37f60fc 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
@@ -69,6 +69,8 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override;
void waitForVSync(QPlatformSurface *surface) const override;
bool supportsPBuffers() const override;
+ void *nativeResourceForIntegration(const QByteArray &name) override;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override;
QKmsDevice *device() const;
QKmsScreenConfig *screenConfig() const;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 734f5cd611..5e45b42abe 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
@@ -68,12 +68,13 @@ private:
QEglFSKmsScreen *m_screen;
};
-QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
+QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless)
: QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
+ , m_headless(headless)
{
m_siblings << this; // gets overridden later
@@ -109,6 +110,9 @@ void QEglFSKmsScreen::setVirtualPosition(const QPoint &pos)
// geometry() calls rawGeometry() and may apply additional transforms.
QRect QEglFSKmsScreen::rawGeometry() const
{
+ if (m_headless)
+ return QRect(QPoint(0, 0), m_device->screenConfig()->headlessSize());
+
const int mode = m_output.mode;
return QRect(m_pos.x(), m_pos.y(),
m_output.modes[mode].hdisplay,
@@ -117,12 +121,30 @@ QRect QEglFSKmsScreen::rawGeometry() const
int QEglFSKmsScreen::depth() const
{
- return 32;
+ return format() == QImage::Format_RGB16 ? 16 : 32;
}
QImage::Format QEglFSKmsScreen::format() const
{
- return QImage::Format_RGB32;
+ // the result can be slightly incorrect, it won't matter in practice
+ switch (m_output.drm_format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ return QImage::Format_ARGB32;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ return QImage::Format_RGB16;
+ case DRM_FORMAT_XRGB2101010:
+ return QImage::Format_RGB30;
+ case DRM_FORMAT_XBGR2101010:
+ return QImage::Format_BGR30;
+ case DRM_FORMAT_ARGB2101010:
+ return QImage::Format_A2RGB30_Premultiplied;
+ case DRM_FORMAT_ABGR2101010:
+ return QImage::Format_A2BGR30_Premultiplied;
+ default:
+ return QImage::Format_RGB32;
+ }
}
QSizeF QEglFSKmsScreen::physicalSize() const
@@ -159,7 +181,7 @@ Qt::ScreenOrientation QEglFSKmsScreen::orientation() const
QString QEglFSKmsScreen::name() const
{
- return m_output.name;
+ return !m_headless ? m_output.name : QStringLiteral("qt_Headless");
}
QString QEglFSKmsScreen::manufacturer() const
@@ -177,22 +199,10 @@ QString QEglFSKmsScreen::serialNumber() const
return m_edid.serialNumber;
}
-void QEglFSKmsScreen::destroySurface()
-{
-}
-
void QEglFSKmsScreen::waitForFlip()
{
}
-void QEglFSKmsScreen::flip()
-{
-}
-
-void QEglFSKmsScreen::flipFinished()
-{
-}
-
void QEglFSKmsScreen::restoreMode()
{
m_output.restoreMode(m_device);
@@ -200,6 +210,9 @@ void QEglFSKmsScreen::restoreMode()
qreal QEglFSKmsScreen::refreshRate() const
{
+ if (m_headless)
+ return 60;
+
quint32 refresh = m_output.modes[m_output.mode].vrefresh;
return refresh > 0 ? refresh : 60;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index 4e09929189..7f395aacb7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -56,7 +56,7 @@ class QEglFSKmsInterruptHandler;
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
{
public:
- QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output);
+ QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless = false);
~QEglFSKmsScreen();
void setVirtualPosition(const QPoint &pos);
@@ -89,11 +89,7 @@ public:
QKmsDevice *device() const { return m_device; }
- void destroySurface();
-
virtual void waitForFlip();
- virtual void flip();
- virtual void flipFinished();
QKmsOutput &output() { return m_output; }
void restoreMode();
@@ -115,6 +111,8 @@ protected:
PowerState m_powerState;
QEglFSKmsInterruptHandler *m_interruptHandler;
+
+ bool m_headless;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.json
new file mode 100644
index 0000000000..b898dc27cb
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "eglfs_kms_vsp2" ]
+}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro
new file mode 100644
index 0000000000..826c2f989f
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro
@@ -0,0 +1,31 @@
+TARGET = qeglfs-kms-vsp2-integration
+
+PLUGIN_TYPE = egldeviceintegrations
+PLUGIN_CLASS_NAME = QEglFSKmsVsp2IntegrationPlugin
+load(qt_plugin)
+
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private edid_support-private
+
+INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
+
+# Avoid X11 header collision, use generic EGL native types
+DEFINES += QT_EGL_NO_X11
+
+QMAKE_USE += gbm drm v4l2
+CONFIG += egl
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
+
+SOURCES += $$PWD/qeglfskmsvsp2main.cpp \
+ $$PWD/qeglfskmsvsp2integration.cpp \
+ $$PWD/qeglfskmsvsp2device.cpp \
+ $$PWD/qeglfskmsvsp2screen.cpp \
+ $$PWD/qlinuxmediadevice.cpp \
+ $$PWD/qvsp2blendingdevice.cpp
+
+HEADERS += $$PWD/qeglfskmsvsp2integration.h \
+ $$PWD/qeglfskmsvsp2device.h \
+ $$PWD/qeglfskmsvsp2screen.h \
+ $$PWD/qlinuxmediadevice.h \
+ $$PWD/qvsp2blendingdevice.h
+
+OTHER_FILES += $$PWD/eglfs_kms.json
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.cpp
new file mode 100644
index 0000000000..44f855910c
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfskmsvsp2device.h"
+#include "qeglfskmsvsp2screen.h"
+
+#include "qeglfsintegration_p.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/private/qcore_unix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+QEglFSKmsVsp2Device::QEglFSKmsVsp2Device(QKmsScreenConfig *screenConfig, const QString &path)
+ : QEglFSKmsDevice(screenConfig, path)
+{
+}
+
+bool QEglFSKmsVsp2Device::open()
+{
+ Q_ASSERT(fd() == -1);
+ Q_ASSERT(m_gbm_device == nullptr);
+
+ int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
+ if (fd == -1) {
+ qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath()));
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << fd
+ << "obtained from" << devicePath();
+ m_gbm_device = gbm_create_device(fd);
+ if (!m_gbm_device) {
+ qErrnoWarning("Could not create GBM device");
+ qt_safe_close(fd);
+ fd = -1;
+ return false;
+ }
+
+ setFd(fd);
+
+ return true;
+}
+
+void QEglFSKmsVsp2Device::close()
+{
+ // Note: screens are gone at this stage.
+
+ if (m_gbm_device) {
+ gbm_device_destroy(m_gbm_device);
+ m_gbm_device = nullptr;
+ }
+
+ if (fd() != -1) {
+ qt_safe_close(fd());
+ setFd(-1);
+ }
+}
+
+void *QEglFSKmsVsp2Device::nativeDisplay() const
+{
+ return m_gbm_device;
+}
+
+gbm_device * QEglFSKmsVsp2Device::gbmDevice() const
+{
+ return m_gbm_device;
+}
+
+QPlatformScreen *QEglFSKmsVsp2Device::createScreen(const QKmsOutput &output)
+{
+ auto *screen = new QEglFSKmsVsp2Screen(this, output);
+
+ return screen;
+}
+
+QPlatformScreen *QEglFSKmsVsp2Device::createHeadlessScreen()
+{
+ qWarning() << Q_FUNC_INFO << "Not implemented yet";
+ return nullptr;
+}
+
+void QEglFSKmsVsp2Device::registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen)
+{
+ Q_UNUSED(screen);
+ qWarning() << Q_FUNC_INFO << "Not implemented yet";
+ if (!screenThisScreenClones && screensCloningThisScreen.isEmpty())
+ return;
+
+// auto *vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen);
+// vsp2Screen->initCloning(screenThisScreenClones, screensCloningThisScreen);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.h
new file mode 100644
index 0000000000..c795fa4005
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2device.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSKMSVSP2DEVICE_H
+#define QEGLFSKMSVSP2DEVICE_H
+
+#include <qeglfskmsdevice.h>
+
+#include <gbm.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsScreen;
+
+class QEglFSKmsVsp2Device: public QEglFSKmsDevice
+{
+public:
+ QEglFSKmsVsp2Device(QKmsScreenConfig *screenConfig, const QString &path);
+
+ bool open() override;
+ void close() override;
+
+ void *nativeDisplay() const override;
+ gbm_device *gbmDevice() const;
+
+ QPlatformScreen *createScreen(const QKmsOutput &output) override;
+ QPlatformScreen *createHeadlessScreen() override;
+ void registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen) override;
+
+private:
+ Q_DISABLE_COPY(QEglFSKmsVsp2Device)
+
+ gbm_device *m_gbm_device = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSKMSVSP2DEVICE_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
new file mode 100644
index 0000000000..f85d6183f6
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfskmsvsp2integration.h"
+#include "qeglfskmsvsp2device.h"
+#include "qeglfskmsvsp2screen.h"
+#include "private/qeglfswindow_p.h"
+
+#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
+#include <QtEglSupport/private/qeglconvenience_p.h>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/QScreen>
+#include <QtPlatformHeaders/qeglfsfunctions.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+
+QT_BEGIN_NAMESPACE
+
+QEglFSKmsVsp2Integration::QEglFSKmsVsp2Integration()
+{
+ qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via Vsp2 integration created");
+}
+
+#ifndef EGL_EXT_platform_base
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+#endif
+
+#ifndef EGL_PLATFORM_GBM_KHR
+#define EGL_PLATFORM_GBM_KHR 0x31D7
+#endif
+
+EGLDisplay QEglFSKmsVsp2Integration::createDisplay(EGLNativeDisplayType nativeDisplay)
+{
+ qCDebug(qLcEglfsKmsDebug, "Querying EGLDisplay");
+ EGLDisplay display;
+
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+ eglGetProcAddress("eglGetPlatformDisplayEXT"));
+ }
+
+ if (getPlatformDisplay) {
+ display = getPlatformDisplay(EGL_PLATFORM_GBM_KHR, nativeDisplay, nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglGetPlatformDisplay for GBM, falling back to eglGetDisplay");
+ display = eglGetDisplay(nativeDisplay);
+ }
+
+ return display;
+}
+
+EGLNativeWindowType QEglFSKmsVsp2Integration::createNativeOffscreenWindow(const QSurfaceFormat &format)
+{
+ Q_UNUSED(format);
+ Q_ASSERT(device());
+
+ gbm_surface *surface = gbm_surface_create(static_cast<QEglFSKmsVsp2Device *>(device())->gbmDevice(),
+ 1, 1,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_RENDERING);
+
+ return reinterpret_cast<EGLNativeWindowType>(surface);
+}
+
+void QEglFSKmsVsp2Integration::destroyNativeWindow(EGLNativeWindowType window)
+{
+ gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
+ //TODO call screen destroysurface instead
+ gbm_surface_destroy(surface);
+}
+
+void QEglFSKmsVsp2Integration::presentBuffer(QPlatformSurface *surface)
+{
+ QWindow *window = static_cast<QWindow *>(surface->surface());
+ auto *screen = static_cast<QEglFSKmsVsp2Screen *>(window->screen()->handle());
+ screen->flip();
+}
+
+QFunctionPointer QEglFSKmsVsp2Integration::platformFunction(const QByteArray &function) const
+{
+ if (function == QEglFSFunctions::vsp2AddLayerTypeIdentifier())
+ return QFunctionPointer(addLayerStatic);
+ if (function == QEglFSFunctions::vsp2RemoveLayerTypeIdentifier())
+ return QFunctionPointer(removeLayerStatic);
+ if (function == QEglFSFunctions::vsp2SetLayerBufferTypeIdentifier())
+ return QFunctionPointer(setLayerBufferStatic);
+ if (function == QEglFSFunctions::vsp2SetLayerPositionTypeIdentifier())
+ return QFunctionPointer(setLayerPositionStatic);
+ if (function == QEglFSFunctions::vsp2AddBlendListenerTypeIdentifier())
+ return QFunctionPointer(addBlendListenerStatic);
+
+ return nullptr;
+}
+
+QKmsDevice *QEglFSKmsVsp2Integration::createDevice()
+{
+ QString path = screenConfig()->devicePath();
+ if (!path.isEmpty()) {
+ qCDebug(qLcEglfsKmsDebug) << "VSP2: Using DRM device" << path << "specified in config file";
+ } else {
+ QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask);
+ const QStringList devices = d->scanConnectedDevices();
+ qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
+ d->deleteLater();
+
+ if (Q_UNLIKELY(devices.isEmpty()))
+ qFatal("Could not find DRM device!");
+
+ path = devices.first();
+ qCDebug(qLcEglfsKmsDebug) << "Using" << path;
+ }
+
+ return new QEglFSKmsVsp2Device(screenConfig(), path);
+}
+
+int QEglFSKmsVsp2Integration::addLayerStatic(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint pixelFormat, uint bytesPerLine)
+{
+ auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());
+ return vsp2Screen->addLayer(dmabufFd, size, position, pixelFormat, bytesPerLine);
+}
+
+bool QEglFSKmsVsp2Integration::removeLayerStatic(const QScreen *screen, int id)
+{
+ auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());
+ return vsp2Screen->removeLayer(id);
+}
+
+void QEglFSKmsVsp2Integration::setLayerBufferStatic(const QScreen *screen, int id, int dmabufFd)
+{
+ auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());
+ vsp2Screen->setLayerBuffer(id, dmabufFd);
+}
+
+void QEglFSKmsVsp2Integration::setLayerPositionStatic(const QScreen *screen, int id, const QPoint &position)
+{
+ auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());
+ vsp2Screen->setLayerPosition(id, position);
+}
+
+void QEglFSKmsVsp2Integration::addBlendListenerStatic(const QScreen *screen, void(*callback)())
+{
+ auto vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen->handle());
+ vsp2Screen->addBlendListener(callback);
+}
+
+class QEglFSKmsVsp2Window : public QEglFSWindow
+{
+public:
+ QEglFSKmsVsp2Window(QWindow *w, const QEglFSKmsVsp2Integration *integration)
+ : QEglFSWindow(w)
+ , m_integration(integration)
+ {}
+ void resetSurface() override;
+ void invalidateSurface() override;
+ const QEglFSKmsVsp2Integration *m_integration;
+};
+
+void QEglFSKmsVsp2Window::resetSurface()
+{
+ auto *vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen());
+ EGLDisplay display = vsp2Screen->display();
+ QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
+ m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
+ // One fullscreen window per screen -> the native window is simply the gbm_surface the screen created.
+ m_window = reinterpret_cast<EGLNativeWindowType>(vsp2Screen->createSurface());
+
+ PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
+ eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+ }
+
+ if (createPlatformWindowSurface) {
+ m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
+ m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
+ }
+}
+
+void QEglFSKmsVsp2Window::invalidateSurface()
+{
+ auto *vsp2Screen = static_cast<QEglFSKmsVsp2Screen *>(screen());
+ QEglFSWindow::invalidateSurface();
+ vsp2Screen->resetSurface();
+}
+
+QEglFSWindow *QEglFSKmsVsp2Integration::createWindow(QWindow *window) const
+{
+ return new QEglFSKmsVsp2Window(window, this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h
new file mode 100644
index 0000000000..c09ee205c8
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSKMSVSP2INTEGRATION_H
+#define QEGLFSKMSVSP2INTEGRATION_H
+
+#include "qeglfskmsintegration.h"
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsDevice;
+
+class QEglFSKmsVsp2Integration : public QEglFSKmsIntegration
+{
+public:
+ QEglFSKmsVsp2Integration();
+
+ EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) override;
+ EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
+
+ void presentBuffer(QPlatformSurface *surface) override;
+ QEglFSWindow *createWindow(QWindow *window) const override;
+
+ QFunctionPointer platformFunction(const QByteArray &function) const override;
+
+protected:
+ QKmsDevice *createDevice() override;
+
+private:
+ static int addLayerStatic(const QScreen *screen, int dmabufFd, const QSize &size, const QPoint &position, uint pixelFormat, uint bytesPerLine);
+ static bool removeLayerStatic(const QScreen *screen, int id);
+ static void setLayerBufferStatic(const QScreen *screen, int id, int dmabufFd);
+ static void setLayerPositionStatic(const QScreen *screen, int id, const QPoint &position);
+ static void addBlendListenerStatic(const QScreen *screen, void(*callback)());
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSKMSVSP2INTEGRATION_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2main.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2main.cpp
new file mode 100644
index 0000000000..1345d38359
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qeglfsdeviceintegration_p.h"
+#include "qeglfskmsvsp2integration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsVsp2IntegrationPlugin : public QEglFSDeviceIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms_vsp2.json")
+
+public:
+ QEglFSDeviceIntegration *create() override { return new QEglFSKmsVsp2Integration; }
+};
+
+QT_END_NAMESPACE
+
+#include "qeglfskmsvsp2main.moc"
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp
new file mode 100644
index 0000000000..42af93287d
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfskmsvsp2screen.h"
+#include "qeglfskmsvsp2device.h"
+#include <qeglfskmshelpers.h>
+
+#include <QtCore/QLoggingCategory>
+#include <QtGui/private/qguiapplication_p.h>
+
+#include <drm_fourcc.h>
+#include <xf86drm.h>
+#include <fcntl.h>
+
+//TODO move to qlinuxmediadevice?
+#include <cstdlib> //this needs to go before mediactl/mediactl.h because it uses size_t without including it
+extern "C" {
+#include <mediactl/mediactl.h>
+#include <mediactl/v4l2subdev.h> //needed in header for default arguments
+}
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return drmFormat;
+}
+
+static inline uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat) //TODO: is this needed?
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return gbmFormat;
+}
+
+void QEglFSKmsVsp2Screen::dmaBufferDestroyedHandler(gbm_bo *gbmBo, void *data)
+{
+ Q_UNUSED(gbmBo); //TODO: do we need to do something with it after all?
+ auto dmabuf = static_cast<DmaBuffer *>(data);
+ //TODO: need some extra cleanup here?
+ delete dmabuf;
+}
+
+QEglFSKmsVsp2Screen::DmaBuffer *QEglFSKmsVsp2Screen::dmaBufferForGbmBuffer(gbm_bo *gbmBo)
+{
+ auto existingBuffer = static_cast<DmaBuffer *>(gbm_bo_get_user_data(gbmBo));
+ if (existingBuffer)
+ return existingBuffer;
+
+ uint32_t handle = gbm_bo_get_handle(gbmBo).u32;
+ QScopedPointer<DmaBuffer> fb(new DmaBuffer);
+ int ret = drmPrimeHandleToFD(device()->fd(), handle, DRM_CLOEXEC, &fb->dmabufFd);
+ if (ret) {
+ qWarning("Failed to create dmabuf file descriptor for buffer with drmPrimeHandleToFd");
+ return nullptr;
+ }
+
+ gbm_bo_set_user_data(gbmBo, fb.data(), dmaBufferDestroyedHandler);
+ return fb.take();
+}
+
+QEglFSKmsVsp2Screen::QEglFSKmsVsp2Screen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSKmsScreen(device, output)
+ , m_blender(new Blender(this))
+{
+}
+
+gbm_surface *QEglFSKmsVsp2Screen::createSurface()
+{
+ if (!m_gbmSurface) {
+ uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format);
+ qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s with format 0x%x", qPrintable(name()), gbmFormat);
+ Q_ASSERT(rawGeometry().isValid());
+ m_gbmSurface = gbm_surface_create(static_cast<QEglFSKmsVsp2Device *>(device())->gbmDevice(),
+ uint(rawGeometry().width()),
+ uint(rawGeometry().height()),
+ gbmFormat,
+ GBM_BO_USE_RENDERING);
+ }
+
+ if (!m_blendDevice)
+ initVsp2();
+
+ if (m_frameBuffers[m_backFb].dmabufFd == -1)
+ initDumbFrameBuffers();
+
+ return m_gbmSurface; // not owned, gets destroyed in QEglFSKmsGbmIntegration::destroyNativeWindow()
+}
+
+void QEglFSKmsVsp2Screen::resetSurface()
+{
+ m_gbmSurface = nullptr;
+}
+
+void QEglFSKmsVsp2Screen::initDumbFrameBuffers()
+{
+ for (auto &fb : m_frameBuffers)
+ initDumbFrameBuffer(fb);
+}
+
+void QEglFSKmsVsp2Screen::initVsp2()
+{
+ qCDebug(qLcEglfsKmsDebug, "Initializing Vsp2 hardware");
+ const QSize screenSize = rawGeometry().size();
+ m_blendDevice.reset(new QVsp2BlendingDevice(screenSize));
+
+ // Enable input for main buffer drawn by the compositor (always on)
+ const uint bytesPerLine = uint(screenSize.width()) * 4; //TODO: is this ok?
+ bool formatSet = m_blendDevice->enableInput(m_qtLayer, QRect(QPoint(), screenSize), m_output.drm_format, bytesPerLine);
+ if (!formatSet) {
+ const uint32_t fallbackFormat = DRM_FORMAT_ARGB8888;
+ qWarning() << "Failed to set format" << q_fourccToString(m_output.drm_format)
+ << "falling back to" << q_fourccToString(fallbackFormat);
+ formatSet = m_blendDevice->enableInput(m_qtLayer, QRect(QPoint(), screenSize), fallbackFormat, bytesPerLine);
+ if (!formatSet)
+ qFatal("Failed to set vsp2 blending format");
+ }
+}
+
+int QEglFSKmsVsp2Screen::addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine)
+{
+ int index = m_blendDevice->enableInput(QRect(position, size), drmPixelFormat, bytesPerLine);
+ if (index != -1) {
+ m_blendDevice->setInputBuffer(index, dmabufFd);
+ int id = index; //TODO: maybe make id something independent of layer index?
+ qCDebug(qLcEglfsKmsDebug) << "Enabled extra layer for vsp input" << index;
+ return id;
+ }
+ qWarning() << "Failed to add layer";
+ return -1;
+}
+
+void QEglFSKmsVsp2Screen::setLayerBuffer(int id, int dmabufFd)
+{
+ int layerIndex = id;
+ m_blendDevice->setInputBuffer(layerIndex, dmabufFd);
+ if (!m_blendScheduled) {
+ m_blendScheduled = true;
+ QCoreApplication::postEvent(m_blender.data(), new QEvent(QEvent::User));
+ }
+}
+
+void QEglFSKmsVsp2Screen::setLayerPosition(int id, const QPoint &position)
+{
+ int layerIndex = id;
+ m_blendDevice->setInputPosition(layerIndex, position);
+}
+
+bool QEglFSKmsVsp2Screen::removeLayer(int id)
+{
+ int layerIndex = id;
+ m_blendDevice->disableInput(layerIndex);
+ return true;
+}
+
+void QEglFSKmsVsp2Screen::addBlendListener(void (*callback)())
+{
+ m_blendFinishedCallbacks.append(callback);
+}
+
+void QEglFSKmsVsp2Screen::flip()
+{
+ if (!m_gbmSurface) {
+ qWarning("Cannot sync before platform init!");
+ return;
+ }
+
+ if (!m_blendScheduled && !m_nextGbmBo) {
+ m_nextGbmBo = gbm_surface_lock_front_buffer(m_gbmSurface);
+
+ if (!m_nextGbmBo) {
+ qWarning("Could not lock GBM surface front buffer!");
+ return;
+ }
+
+ m_blendScheduled = true;
+ QCoreApplication::postEvent(m_blender.data(), new QEvent(QEvent::User));
+ }
+}
+
+void QEglFSKmsVsp2Screen::ensureModeSet()
+{
+ const int driFd = device()->fd();
+ QKmsOutput &op(output());
+ if (!op.mode_set) {
+ int ret = drmModeSetCrtc(driFd,
+ op.crtc_id,
+ m_frameBuffers[m_backFb].drmBufferId,
+ 0, 0,
+ &op.connector_id, 1,
+ &op.modes[op.mode]);
+
+ if (ret == -1) {
+ qErrnoWarning(errno, "Could not set DRM mode!");
+ } else {
+ op.mode_set = true;
+ setPowerState(PowerStateOn);
+ }
+ }
+}
+
+void QEglFSKmsVsp2Screen::doDrmFlip()
+{
+ QKmsOutput &op(output());
+ const int driFd = device()->fd();
+
+ int ret = drmModePageFlip(driFd,
+ op.crtc_id,
+ m_frameBuffers[m_backFb].drmBufferId,
+ 0,
+ this);
+
+ if (ret)
+ qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
+
+ m_backFb = (m_backFb + 1) % 2;
+}
+
+void QEglFSKmsVsp2Screen::blendAndFlipDrm()
+{
+ m_blendScheduled = false;
+ if (!m_nextGbmBo && !m_blendDevice->isDirty())
+ return;
+
+ FrameBuffer &backBuffer = m_frameBuffers[m_backFb];
+ if (backBuffer.dmabufFd == -1)
+ initDumbFrameBuffers();
+
+ if (m_nextGbmBo) {
+ Q_ASSERT(m_nextGbmBo != m_currentGbmBo);
+ int compositorBackBufferDmaFd = dmaBufferForGbmBuffer(m_nextGbmBo)->dmabufFd;
+ m_blendDevice->setInputBuffer(m_qtLayer, compositorBackBufferDmaFd);
+
+ if (m_currentGbmBo)
+ gbm_surface_release_buffer(m_gbmSurface, m_currentGbmBo);
+ m_currentGbmBo = m_nextGbmBo;
+ m_nextGbmBo = nullptr;
+ }
+
+ ensureModeSet();
+
+ if (!m_blendDevice)
+ initVsp2();
+
+ if (!m_blendDevice->isDirty())
+ return;
+
+ const int driFd = device()->fd();
+ drmVBlank vBlank;
+ vBlank.request.type = static_cast<drmVBlankSeqType>(DRM_VBLANK_RELATIVE | DRM_VBLANK_SECONDARY); //TODO: make secondary configurable (or automatic)
+ vBlank.request.sequence = 1;
+ vBlank.request.signal = 0;
+ drmWaitVBlank(driFd, &vBlank);
+
+ if (!m_blendDevice->blend(backBuffer.dmabufFd))
+ qWarning() << "Vsp2: blending failed";
+
+ for (auto cb : m_blendFinishedCallbacks)
+ cb();
+
+ doDrmFlip();
+}
+
+void QEglFSKmsVsp2Screen::initDumbFrameBuffer(FrameBuffer &fb)
+{
+ QKmsOutput &op(output());
+ const uint32_t width = op.modes[op.mode].hdisplay;
+ const uint32_t height = op.modes[op.mode].vdisplay;
+
+ Q_ASSERT(fb.dmabufFd == -1);
+ const uint32_t dumbBufferFlags = 0; //TODO: do we want some flags? What's possible?
+ const uint32_t bpp = 32;
+
+ drm_mode_create_dumb creq = {
+ height,
+ width,
+ bpp,
+ dumbBufferFlags,
+ 0, 0, 0 //return values
+ };
+
+ const int driFd = device()->fd();
+ if (drmIoctl(driFd, DRM_IOCTL_MODE_CREATE_DUMB, &creq) == -1)
+ qFatal("Failed to create dumb buffer: %s", strerror(errno));
+
+// uint32_t handles[4] = { gbm_bo_get_handle(bo).u32 };
+// uint32_t strides[4] = { gbm_bo_get_stride(bo) };
+// uint32_t offsets[4] = { 0 };
+// uint32_t pixelFormat = gbmFormatToDrmFormat(gbm_bo_get_format(bo));
+
+ //TODO: support additional planes
+ uint32_t gbmBoHandles[4] = { creq.handle, 0, 0, 0 };
+ uint32_t strides[4] = { creq.pitch, 0, 0, 0 };
+ uint32_t offsets[4] = { 0 };
+ uint32_t pixelFormat = DRM_FORMAT_ARGB8888; //TODO: support other formats?
+ uint32_t drmFlags = 0;
+
+ qCDebug(qLcEglfsKmsDebug) << "Adding FB" << QSize(width, height)
+ << ", DRM format" << q_fourccToString(pixelFormat);
+ int ret = drmModeAddFB2(driFd, width, height, pixelFormat,
+ gbmBoHandles, strides, offsets, &fb.drmBufferId, drmFlags);
+ if (ret)
+ qFatal("drmModeAddFB2 failed: %s", strerror(errno));
+
+ drmPrimeHandleToFD(driFd, gbmBoHandles[0], DRM_CLOEXEC, &fb.dmabufFd);
+}
+
+bool QEglFSKmsVsp2Screen::Blender::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::User:
+ m_screen->blendAndFlipDrm();
+ return true;
+ default:
+ return QObject::event(event);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h
new file mode 100644
index 0000000000..19f65e7e7d
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2screen.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSKMSVSP2SCREEN_H
+#define QEGLFSKMSVSP2SCREEN_H
+
+#include "qeglfskmsscreen.h"
+#include "qvsp2blendingdevice.h"
+#include <QtCore/QMutex>
+
+#include <gbm.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsVsp2Screen : public QEglFSKmsScreen
+{
+public:
+ QEglFSKmsVsp2Screen(QKmsDevice *device, const QKmsOutput &output);
+
+ gbm_surface *createSurface();
+ void resetSurface();
+
+ void initDumbFrameBuffers();
+ void initVsp2();
+
+ //TODO: use a fixed index API instead of auto increment?
+ int addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine);
+ void setLayerBuffer(int id, int dmabufFd);
+ void setLayerPosition(int id, const QPoint &position);
+ bool removeLayer(int id);
+ void addBlendListener(void (*callback)());
+
+ void flip();
+ void blendAndFlipDrm();
+
+private:
+ class Blender : public QObject // This is a workaround we really would want the screen to be a QObject
+ {
+ public:
+ Blender(QEglFSKmsVsp2Screen *screen) : m_screen(screen) {}
+ ~Blender() override {}
+ bool event(QEvent *event) override;
+ QEglFSKmsVsp2Screen *m_screen = nullptr;
+ };
+ QScopedArrayPointer<Blender> m_blender;
+
+ gbm_surface *m_gbmSurface = nullptr;
+ gbm_bo *m_currentGbmBo = nullptr;
+ gbm_bo *m_nextGbmBo = nullptr;
+
+ QScopedPointer<QVsp2BlendingDevice> m_blendDevice;
+
+ struct FrameBuffer { //these are for buffers that have been blended by the bru
+ uint32_t drmBufferId = 0;
+ int dmabufFd = -1;
+ };
+ std::array<FrameBuffer, 2> m_frameBuffers;
+ uint m_backFb = 0;
+ void initDumbFrameBuffer(FrameBuffer &fb);
+ QVector<void (*)()> m_blendFinishedCallbacks;
+
+ struct DmaBuffer { //these are for qt buffers before blending with additional layers (gbm buffer data)
+ int dmabufFd = -1;
+ };
+ static void dmaBufferDestroyedHandler(gbm_bo *gbmBo, void *data);
+ DmaBuffer *dmaBufferForGbmBuffer(gbm_bo *gbmBo);
+
+ void ensureModeSet();
+ void doDrmFlip();
+
+ bool m_blendScheduled = false;
+ int m_qtLayer = 0; //TODO: add API for changing this
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSKMSVSP2SCREEN_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp
new file mode 100644
index 0000000000..21de052b87
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp
@@ -0,0 +1,607 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfsintegration_p.h"
+#include "qlinuxmediadevice.h"
+#include <qeglfskmshelpers.h>
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QSize>
+#include <QtCore/QRect>
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <cstdlib> //this needs to go before mediactl/mediactl.h because it uses size_t without including it
+extern "C" {
+#include <mediactl/mediactl.h>
+#include <mediactl/v4l2subdev.h>
+}
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+static QString mediaBusFmtToString(uint code)
+{
+ switch (code) {
+ case MEDIA_BUS_FMT_FIXED: return "FIXED";
+ case MEDIA_BUS_FMT_RGB444_1X12: return "RGB444_1X12";
+// case MEDIA_BUS_FMT_RGB444_2X8_PADHI_B: return "RGB444_2X8_PADHI_B";
+// case MEDIA_BUS_FMT_RGB444_2X8_PADHI_L: return "RGB444_2X8_PADHI_L";
+// case MEDIA_BUS_FMT_RGB555_2X8_PADHI_B: return "RGB555_2X8_PADHI_B";
+// case MEDIA_BUS_FMT_RGB555_2X8_PADHI_L: return "RGB555_2X8_PADHI_L";
+ case MEDIA_BUS_FMT_RGB565_1X16: return "RGB565_1X16";
+ case MEDIA_BUS_FMT_BGR565_2X8_BE: return "BGR565_2X8_BE";
+ case MEDIA_BUS_FMT_BGR565_2X8_LE: return "BGR565_2X8_LE";
+ case MEDIA_BUS_FMT_RGB565_2X8_BE: return "RGB565_2X8_BE";
+ case MEDIA_BUS_FMT_RGB565_2X8_LE: return "RGB565_2X8_LE";
+ case MEDIA_BUS_FMT_RGB666_1X18: return "RGB666_1X18";
+ case MEDIA_BUS_FMT_RBG888_1X24: return "RBG888_1X24";
+// case MEDIA_BUS_FMT_RGB666_1X24_CPADH: return "RGB666_1X24_CPADH";
+ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: return "RGB666_1X7X3_SPWG";
+ case MEDIA_BUS_FMT_BGR888_1X24: return "BGR888_1X24";
+ case MEDIA_BUS_FMT_GBR888_1X24: return "GBR888_1X24";
+ case MEDIA_BUS_FMT_RGB888_1X24: return "RGB888_1X24";
+ case MEDIA_BUS_FMT_RGB888_2X12_BE: return "RGB888_2X12_BE";
+ case MEDIA_BUS_FMT_RGB888_2X12_LE: return "RGB888_2X12_LE";
+ case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: return "RGB888_1X7X4_SPWG";
+// case MEDIA_BUS_FMT_RGB888_1X7X4_JEID: return "RGB888_1X7X4_JEID";
+ case MEDIA_BUS_FMT_ARGB8888_1X32: return "ARGB8888_1X32";
+ case MEDIA_BUS_FMT_RGB888_1X32_PADHI: return "RGB888_1X32_PADHI";
+// case MEDIA_BUS_FMT_RGB101010_1X30: return "RGB101010_1X30";
+// case MEDIA_BUS_FMT_RGB121212_1X36: return "RGB121212_1X36";
+// case MEDIA_BUS_FMT_RGB161616_1X48: return "RGB161616_1X48";
+ case MEDIA_BUS_FMT_Y8_1X8: return "Y8_1X8";
+ case MEDIA_BUS_FMT_UV8_1X8: return "UV8_1X8";
+ case MEDIA_BUS_FMT_UYVY8_1_5X8: return "UYVY8_1_5X8";
+ case MEDIA_BUS_FMT_VYUY8_1_5X8: return "VYUY8_1_5X8";
+ case MEDIA_BUS_FMT_YUYV8_1_5X8: return "YUYV8_1_5X8";
+ case MEDIA_BUS_FMT_YVYU8_1_5X8: return "YVYU8_1_5X8";
+ case MEDIA_BUS_FMT_UYVY8_2X8: return "UYVY8_2X8";
+ case MEDIA_BUS_FMT_VYUY8_2X8: return "VYUY8_2X8";
+ case MEDIA_BUS_FMT_YUYV8_2X8: return "YUYV8_2X8";
+ case MEDIA_BUS_FMT_YVYU8_2X8: return "YVYU8_2X8";
+ case MEDIA_BUS_FMT_Y10_1X10: return "Y10_1X10";
+ case MEDIA_BUS_FMT_UYVY10_2X10: return "UYVY10_2X10";
+ case MEDIA_BUS_FMT_VYUY10_2X10: return "VYUY10_2X10";
+ case MEDIA_BUS_FMT_YUYV10_2X10: return "YUYV10_2X10";
+ case MEDIA_BUS_FMT_YVYU10_2X10: return "YVYU10_2X10";
+ case MEDIA_BUS_FMT_Y12_1X12: return "Y12_1X12";
+ case MEDIA_BUS_FMT_UYVY12_2X12: return "UYVY12_2X12";
+ case MEDIA_BUS_FMT_VYUY12_2X12: return "VYUY12_2X12";
+ case MEDIA_BUS_FMT_YUYV12_2X12: return "YUYV12_2X12";
+ case MEDIA_BUS_FMT_YVYU12_2X12: return "YVYU12_2X12";
+ case MEDIA_BUS_FMT_UYVY8_1X16: return "UYVY8_1X16";
+ case MEDIA_BUS_FMT_VYUY8_1X16: return "VYUY8_1X16";
+ case MEDIA_BUS_FMT_YUYV8_1X16: return "YUYV8_1X16";
+ case MEDIA_BUS_FMT_YVYU8_1X16: return "YVYU8_1X16";
+ case MEDIA_BUS_FMT_YDYUYDYV8_1X16: return "YDYUYDYV8_1X16";
+ case MEDIA_BUS_FMT_UYVY10_1X20: return "UYVY10_1X20";
+ case MEDIA_BUS_FMT_VYUY10_1X20: return "VYUY10_1X20";
+ case MEDIA_BUS_FMT_YUYV10_1X20: return "YUYV10_1X20";
+ case MEDIA_BUS_FMT_YVYU10_1X20: return "YVYU10_1X20";
+ case MEDIA_BUS_FMT_VUY8_1X24: return "VUY8_1X24";
+ case MEDIA_BUS_FMT_YUV8_1X24: return "YUV8_1X24";
+// case MEDIA_BUS_FMT_UYYVYY8_0_5X24: return "UYYVYY8_0_5X24";
+ case MEDIA_BUS_FMT_UYVY12_1X24: return "UYVY12_1X24";
+ case MEDIA_BUS_FMT_VYUY12_1X24: return "VYUY12_1X24";
+ case MEDIA_BUS_FMT_YUYV12_1X24: return "YUYV12_1X24";
+ case MEDIA_BUS_FMT_YVYU12_1X24: return "YVYU12_1X24";
+ case MEDIA_BUS_FMT_YUV10_1X30: return "YUV10_1X30";
+// case MEDIA_BUS_FMT_UYYVYY10_0_5X30: return "UYYVYY10_0_5X30";
+ case MEDIA_BUS_FMT_AYUV8_1X32: return "AYUV8_1X32";
+// case MEDIA_BUS_FMT_UYYVYY12_0_5X36: return "UYYVYY12_0_5X36";
+// case MEDIA_BUS_FMT_YUV12_1X36: return "YUV12_1X36";
+// case MEDIA_BUS_FMT_YUV16_1X48: return "YUV16_1X48";
+// case MEDIA_BUS_FMT_UYYVYY16_0_5X48: return "UYYVYY16_0_5X48";
+ case MEDIA_BUS_FMT_SBGGR8_1X8: return "SBGGR8_1X8";
+ case MEDIA_BUS_FMT_SGBRG8_1X8: return "SGBRG8_1X8";
+ case MEDIA_BUS_FMT_SGRBG8_1X8: return "SGRBG8_1X8";
+ case MEDIA_BUS_FMT_SRGGB8_1X8: return "SRGGB8_1X8";
+ case MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8: return "SBGGR10_ALAW8_1X8";
+ case MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8: return "SGBRG10_ALAW8_1X8";
+ case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8: return "SGRBG10_ALAW8_1X8";
+ case MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8: return "SRGGB10_ALAW8_1X8";
+ case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8: return "SBGGR10_DPCM8_1X8";
+ case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8: return "SGBRG10_DPCM8_1X8";
+ case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8: return "SGRBG10_DPCM8_1X8";
+ case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8: return "SRGGB10_DPCM8_1X8";
+// case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_B: return "SBGGR10_2X8_PADHI_B";
+// case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_L: return "SBGGR10_2X8_PADHI_L";
+// case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_B: return "SBGGR10_2X8_PADLO_B";
+// case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_L: return "SBGGR10_2X8_PADLO_L";
+ case MEDIA_BUS_FMT_SBGGR10_1X10: return "SBGGR10_1X10";
+ case MEDIA_BUS_FMT_SGBRG10_1X10: return "SGBRG10_1X10";
+ case MEDIA_BUS_FMT_SGRBG10_1X10: return "SGRBG10_1X10";
+ case MEDIA_BUS_FMT_SRGGB10_1X10: return "SRGGB10_1X10";
+ case MEDIA_BUS_FMT_SBGGR12_1X12: return "SBGGR12_1X12";
+ case MEDIA_BUS_FMT_SGBRG12_1X12: return "SGBRG12_1X12";
+ case MEDIA_BUS_FMT_SGRBG12_1X12: return "SGRBG12_1X12";
+ case MEDIA_BUS_FMT_SRGGB12_1X12: return "SRGGB12_1X12";
+ case MEDIA_BUS_FMT_SBGGR14_1X14: return "SBGGR14_1X14";
+ case MEDIA_BUS_FMT_SGBRG14_1X14: return "SGBRG14_1X14";
+ case MEDIA_BUS_FMT_SGRBG14_1X14: return "SGRBG14_1X14";
+ case MEDIA_BUS_FMT_SRGGB14_1X14: return "SRGGB14_1X14";
+ case MEDIA_BUS_FMT_SBGGR16_1X16: return "SBGGR16_1X16";
+ case MEDIA_BUS_FMT_SGBRG16_1X16: return "SGBRG16_1X16";
+ case MEDIA_BUS_FMT_SGRBG16_1X16: return "SGRBG16_1X16";
+ case MEDIA_BUS_FMT_SRGGB16_1X16: return "SRGGB16_1X16";
+ case MEDIA_BUS_FMT_JPEG_1X8: return "JPEG_1X8";
+ case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8: return "S5C_UYVY_JPEG_1X8";
+ case MEDIA_BUS_FMT_AHSV8888_1X32: return "AHSV8888_1X32";
+ default: return QString(code);
+ }
+}
+
+static QDebug operator<<(QDebug debug, const struct v4l2_mbus_framefmt &format)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "v4l2_mbus_framefmt("
+ << "code: " << mediaBusFmtToString(format.code) << ", "
+ << "size: " << format.width << "x" << format.height << ")";
+ return debug;
+}
+
+static QDebug operator<<(QDebug debug, const struct v4l2_pix_format_mplane &format)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "v4l2_pix_format_mplane("
+ << "pixel format: " << q_fourccToString(format.pixelformat) << ", "
+ << "size: " << format.width << "x" << format.height << ", "
+ << "planes: " << format.num_planes << ")";
+ return debug;
+}
+
+QLinuxMediaDevice::QLinuxMediaDevice(const QString &devicePath)
+ : m_mediaDevice(media_device_new(devicePath.toStdString().c_str()))
+{
+ if (!m_mediaDevice)
+ qFatal("Couldn't get media device");
+
+ if (media_device_enumerate(m_mediaDevice))
+ qFatal("Couldn't enumerate media device");
+
+ m_info = media_get_info(m_mediaDevice);
+
+ qCDebug(qLcEglfsKmsDebug) << "Opened linux media device:"
+ << "\n\t Path:" << devicePath
+ << "\n\t Model:" << model()
+ << "\n\t Device name:" << deviceName();
+
+ resetLinks();
+}
+
+QLinuxMediaDevice::~QLinuxMediaDevice()
+{
+ if (m_mediaDevice)
+ media_device_unref(m_mediaDevice);
+}
+
+QString QLinuxMediaDevice::model()
+{
+ return QString(m_info->model);
+}
+
+QString QLinuxMediaDevice::deviceName()
+{
+ return QString(m_info->bus_info).split(":").last();
+}
+
+bool QLinuxMediaDevice::resetLinks()
+{
+ if (media_reset_links(m_mediaDevice)) {
+ qWarning() << "Could not reset media controller links.";
+ return false;
+ }
+ qCDebug(qLcEglfsKmsDebug) << "Reset media links";
+ return true;
+}
+
+struct media_link *QLinuxMediaDevice::parseLink(const QString &link)
+{
+ char *endp = nullptr;;
+ struct media_link *mediaLink = media_parse_link(m_mediaDevice, link.toStdString().c_str(), &endp);
+
+ if (!mediaLink)
+ qWarning() << "Failed to parse media link:" << link;
+
+ return mediaLink;
+}
+
+struct media_pad *QLinuxMediaDevice::parsePad(const QString &pad)
+{
+ struct media_pad *mediaPad = media_parse_pad(m_mediaDevice, pad.toStdString().c_str(), nullptr);
+
+ if (!mediaPad)
+ qWarning() << "Failed to parse media pad:" << pad;
+
+ return mediaPad;
+}
+
+bool QLinuxMediaDevice::enableLink(struct media_link *link)
+{
+ if (media_setup_link(m_mediaDevice, link->source, link->sink, 1)) {
+ qWarning() << "Failed to enable media link.";
+ return false;
+ }
+ return true;
+}
+
+bool QLinuxMediaDevice::disableLink(struct media_link *link)
+{
+ if (media_setup_link(m_mediaDevice, link->source, link->sink, 0)) {
+ qWarning() << "Failed to disable media link.";
+ return false;
+ }
+ return true;
+}
+
+media_entity *QLinuxMediaDevice::getEntity(const QString &name)
+{
+ struct media_entity *entity = media_get_entity_by_name(m_mediaDevice, name.toStdString().c_str(), name.length());
+
+ if (!entity)
+ qWarning() << "Failed to get media entity:" << name;
+
+ return entity;
+}
+
+int QLinuxMediaDevice::openVideoDevice(const QString &name)
+{
+ struct media_entity *entity = getEntity(name);
+ const char *deviceName = media_entity_get_devname(entity);
+ int fd = open(deviceName, O_RDWR);
+ qCDebug(qLcEglfsKmsDebug) << "Opened video device:" << deviceName << "with fd" << fd;
+ return fd;
+}
+
+QLinuxMediaDevice::CaptureSubDevice::CaptureSubDevice(QLinuxMediaDevice *mediaDevice, const QString &name)
+ : m_subdevFd(mediaDevice->openVideoDevice(name))
+{
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::setFormat(const QSize &size, uint32_t pixelFormat)
+{
+ Q_ASSERT(size.isValid());
+ struct v4l2_format format;
+ memset(&format, 0, sizeof(struct v4l2_format));
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ if (ioctl(m_subdevFd, VIDIOC_G_FMT, &format) == -1) {
+ qErrnoWarning("VIDIOC_G_FMT for capture device failed");
+ return false;
+ }
+
+ format.fmt.pix_mp.width = static_cast<uint>(size.width());
+ format.fmt.pix_mp.height = static_cast<uint>(size.height());
+ format.fmt.pix_mp.field = V4L2_FIELD_NONE;
+ format.fmt.pix_mp.pixelformat = pixelFormat;
+ format.fmt.pix_mp.num_planes = 1;
+ format.fmt.pix_mp.flags = 0;
+ format.fmt.pix_mp.plane_fmt[0].bytesperline = 0;
+ format.fmt.pix_mp.plane_fmt[0].sizeimage = 0;
+
+ if (ioctl(m_subdevFd, VIDIOC_S_FMT, &format) == -1) {
+ qWarning() << "Capture device" << m_subdevFd << "VIDIOC_S_FMT with format" << format.fmt.pix_mp
+ << "failed:" << strerror(errno);
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug) << "Capture device" << m_subdevFd << "format set:" << format.fmt.pix_mp;
+ return true;
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::clearBuffers()
+{
+ struct v4l2_requestbuffers requestBuffers;
+ memset(&requestBuffers, 0, sizeof(requestBuffers));
+ requestBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ requestBuffers.memory = V4L2_MEMORY_DMABUF;
+ requestBuffers.count = 0;
+ if (ioctl(m_subdevFd, VIDIOC_REQBUFS, &requestBuffers) == -1) {
+ qWarning("Capture device %d: VIDIOC_REQBUFS clear failed: %s", m_subdevFd, strerror(errno));
+ return false;
+ }
+ qCDebug(qLcEglfsKmsDebug, "Capture device %d: Deallocced buffers with REQBUF, now has %d buffers", m_subdevFd, requestBuffers.count);
+ Q_ASSERT(requestBuffers.count == 0);
+ return true;
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::requestBuffer()
+{
+ struct v4l2_requestbuffers requestBuffers;
+ memset(&requestBuffers, 0, sizeof(requestBuffers));
+ requestBuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ requestBuffers.memory = V4L2_MEMORY_DMABUF;
+ requestBuffers.count = 1;
+ if (ioctl(m_subdevFd, VIDIOC_REQBUFS, &requestBuffers) == -1) {
+ if (errno == EINVAL)
+ qWarning("Capture device %d: Multi-planar capture or dma buffers not supported", m_subdevFd);
+ qWarning("Capture device %d: VIDIOC_REQBUFS failed: %s", m_subdevFd, strerror(errno));
+ return false;
+ }
+ Q_ASSERT(requestBuffers.count == 1);
+ return true;
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::queueBuffer(int dmabufFd, const QSize &bufferSize)
+{
+ const uint numPlanes = 1;
+ struct v4l2_buffer buffer;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.index = 0;
+
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ buffer.m.planes = planes;
+ buffer.length = numPlanes;
+ memset(planes, 0, sizeof(planes));
+ for (uint i = 0; i < numPlanes; i++) {
+ buffer.m.planes[i].m.fd = dmabufFd;
+ buffer.m.planes[i].length = static_cast<uint>(bufferSize.width() * bufferSize.height() * 4); //TODO: don't harcode bpp
+ buffer.m.planes[i].bytesused = static_cast<uint>(bufferSize.width() * bufferSize.height() * 4); //TODO: don't harcode bpp
+ }
+
+ if (ioctl(m_subdevFd, VIDIOC_QBUF, &buffer) == -1) {
+ qWarning("Capture device %d: VIDIOC_QBUF failed for dma buffer with fd %d: %s",
+ m_subdevFd, dmabufFd, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::dequeueBuffer()
+{
+ const int numPlanes = 1;
+ struct v4l2_buffer buffer;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.index = 0;
+ buffer.m.planes = planes;
+ buffer.length = numPlanes;
+ memset(planes, 0, sizeof(planes));
+
+ if (ioctl(m_subdevFd, VIDIOC_DQBUF, &buffer) == -1) {
+ qWarning("Capture device %d: VIDIOC_DQBUF failed: %s", m_subdevFd, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::streamOn()
+{
+ return QLinuxMediaDevice::streamOn(m_subdevFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+}
+
+bool QLinuxMediaDevice::CaptureSubDevice::streamOff()
+{
+ return QLinuxMediaDevice::streamOff(m_subdevFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+}
+
+QLinuxMediaDevice::OutputSubDevice::OutputSubDevice(QLinuxMediaDevice *mediaDevice, const QString &name)
+ : m_subdevFd(mediaDevice->openVideoDevice(name))
+{
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::setFormat(const QSize &size, uint32_t pixelFormat, uint32_t bytesPerLine)
+{
+ Q_ASSERT(size.isValid());
+ struct v4l2_format format;
+ memset(&format, 0, sizeof(struct v4l2_format));
+ format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ if (ioctl(m_subdevFd, VIDIOC_G_FMT, &format) == -1) {
+ qErrnoWarning("VIDIOC_G_FMT for output device failed");
+ return false;
+ }
+
+ format.fmt.pix_mp.width = static_cast<uint>(size.width());
+ format.fmt.pix_mp.height = static_cast<uint>(size.height());
+ format.fmt.pix_mp.field = V4L2_FIELD_NONE;
+ format.fmt.pix_mp.pixelformat = pixelFormat;
+ format.fmt.pix_mp.num_planes = 1;
+ format.fmt.pix_mp.flags = 0;
+ format.fmt.pix_mp.plane_fmt[0].bytesperline = bytesPerLine;
+ format.fmt.pix_mp.plane_fmt[0].sizeimage = 0;
+
+ if (ioctl(m_subdevFd, VIDIOC_S_FMT, &format) == -1) {
+ qWarning() << "Output device" << m_subdevFd << "VIDIOC_S_FMT with format" << format.fmt.pix_mp
+ << "failed:" << strerror(errno);
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug) << "Output device device" << m_subdevFd << "format set:" << format.fmt.pix_mp;
+ return true;
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::clearBuffers()
+{
+ struct v4l2_requestbuffers requestBuffers;
+ memset(&requestBuffers, 0, sizeof(requestBuffers));
+ requestBuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ requestBuffers.memory = V4L2_MEMORY_DMABUF;
+ requestBuffers.count = 0;
+ if (ioctl(m_subdevFd, VIDIOC_REQBUFS, &requestBuffers) == -1) {
+ qWarning("Output device %d: VIDIOC_REQBUFS clear failed: %s", m_subdevFd, strerror(errno));
+ return false;
+ }
+ qCDebug(qLcEglfsKmsDebug, "Output device %d: Deallocced buffers with REQBUF, now has %d buffers", m_subdevFd, requestBuffers.count);
+ Q_ASSERT(requestBuffers.count == 0);
+ return true;
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::requestBuffer()
+{
+ struct v4l2_requestbuffers requestBuffers;
+ memset(&requestBuffers, 0, sizeof(requestBuffers));
+ requestBuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ requestBuffers.memory = V4L2_MEMORY_DMABUF;
+ requestBuffers.count = 1;
+ if (ioctl(m_subdevFd, VIDIOC_REQBUFS, &requestBuffers) == -1) {
+ if (errno == EINVAL)
+ qWarning("Output device %d: Multi-planar output or dma buffers not supported", m_subdevFd);
+ qWarning("Output device %d: VIDIOC_REQBUFS failed: %s", m_subdevFd, strerror(errno));
+ return false;
+ }
+ qCDebug(qLcEglfsKmsDebug) << "REQBUF returned" << requestBuffers.count << "buffers for output device" << m_subdevFd;
+ return true;
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::queueBuffer(int dmabufFd, uint bytesUsed, uint length)
+{
+ const int numPlanes = 1;
+ struct v4l2_buffer buffer;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.index = 0;
+ buffer.length = numPlanes;
+ buffer.bytesused = bytesUsed;
+ buffer.field = V4L2_FIELD_NONE; //TODO: what is this?
+
+ struct v4l2_plane planes[numPlanes];
+ memset(planes, 0, sizeof(planes));
+ buffer.m.planes = planes;
+
+ for (int i = 0; i < numPlanes; i++) {
+ buffer.m.planes[i].m.fd = dmabufFd;
+ buffer.m.planes[i].length = length;
+ buffer.m.planes[i].bytesused = bytesUsed;
+ }
+
+ if (ioctl(m_subdevFd, VIDIOC_QBUF, &buffer) == -1) {
+ qWarning("Output device %d: VIDIOC_QBUF failed for dmabuf %d: %s", m_subdevFd, dmabufFd, strerror(errno));
+ return false;
+ }
+
+ if (!(buffer.flags & V4L2_BUF_FLAG_QUEUED)) {
+ qWarning() << "Queued flag not set on buffer for output device";
+ return false;
+ }
+
+ return true;
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::streamOn()
+{
+ return QLinuxMediaDevice::streamOn(m_subdevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+}
+
+bool QLinuxMediaDevice::OutputSubDevice::streamOff()
+{
+ return QLinuxMediaDevice::streamOff(m_subdevFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+}
+
+bool QLinuxMediaDevice::setSubdevFormat(struct media_pad *pad, const QSize &size, uint32_t mbusFormat)
+{
+ Q_ASSERT(size.isValid());
+ struct v4l2_mbus_framefmt format;
+ format.width = static_cast<uint>(size.width());
+ format.height = static_cast<uint>(size.height());
+ format.code = mbusFormat;
+
+ if (v4l2_subdev_set_format(pad->entity, &format, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE)) {
+ qWarning() << "Setting v4l2_subdev_set_format failed for format" << format;
+ return false;
+ }
+
+ if (format.code != mbusFormat) {
+ qWarning() << "Got" << mediaBusFmtToString(format.code) << "instead of"
+ << mediaBusFmtToString(mbusFormat) << "when setting subdevice format";
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug) << "Set format to" << format << "for entity" << pad->entity << "index" << pad->index;
+ return true;
+}
+
+bool QLinuxMediaDevice::setSubdevSelection(struct media_pad *pad, const QRect &geometry, uint target)
+{
+ Q_ASSERT(geometry.isValid());
+ struct v4l2_rect rect;
+ rect.left = geometry.left();
+ rect.top = geometry.top();
+ rect.width = static_cast<uint>(geometry.width());
+ rect.height = static_cast<uint>(geometry.height());
+
+ int ret = v4l2_subdev_set_selection(pad->entity, &rect, pad->index, target, V4L2_SUBDEV_FORMAT_ACTIVE);
+ if (ret) {
+ qWarning() << "Setting subdev selection failed.";
+ return false;
+ }
+
+ return true;
+}
+
+bool QLinuxMediaDevice::setSubdevCrop(struct media_pad *pad, const QRect &geometry)
+{
+ return setSubdevSelection(pad, geometry, V4L2_SEL_TGT_CROP);
+}
+
+bool QLinuxMediaDevice::setSubdevCompose(struct media_pad *pad, const QRect &geometry)
+{
+ return setSubdevSelection(pad, geometry, V4L2_SEL_TGT_COMPOSE);
+}
+
+bool QLinuxMediaDevice::streamOn(int subDeviceFd, v4l2_buf_type bufferType)
+{
+ if (ioctl(subDeviceFd, VIDIOC_STREAMON, &bufferType) == -1) {
+ qWarning("VIDIOC_STREAMON failed for subdevice %d: %s", subDeviceFd, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+bool QLinuxMediaDevice::streamOff(int subDeviceFd, v4l2_buf_type bufferType)
+{
+ if (ioctl(subDeviceFd, VIDIOC_STREAMOFF, &bufferType) == -1) {
+ qWarning("VIDIOC_STREAMOFF failed for subdevice %d: %s", subDeviceFd, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h
new file mode 100644
index 0000000000..848099eb46
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLINUXMEDIADEVICE_H
+#define QLINUXMEDIADEVICE_H
+
+#include <linux/v4l2-mediabus.h>
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QSize;
+class QRect;
+
+class QLinuxMediaDevice
+{
+public:
+ QLinuxMediaDevice(const QString &devicePath);
+ ~QLinuxMediaDevice();
+
+ QString model();
+ QString deviceName();
+ bool resetLinks();
+ struct media_link *parseLink(const QString &link);
+ struct media_pad *parsePad(const QString &pad);
+ bool enableLink(struct media_link *link);
+ bool disableLink(struct media_link *link);
+ struct media_entity *getEntity(const QString &name);
+ int openVideoDevice(const QString &name);
+
+ class CaptureSubDevice
+ {
+ public:
+ CaptureSubDevice(QLinuxMediaDevice *mediaDevice, const QString &name);
+ bool setFormat(const QSize &size, uint32_t pixelFormat = V4L2_PIX_FMT_ABGR32); //TODO: fix to match output device
+ bool clearBuffers();
+ bool requestBuffer();
+ bool queueBuffer(int dmabufFd, const QSize &bufferSize);
+ bool dequeueBuffer();
+ bool streamOn();
+ bool streamOff();
+ private:
+ int m_subdevFd = -1;
+ };
+
+ class OutputSubDevice
+ {
+ public:
+ OutputSubDevice(QLinuxMediaDevice *mediaDevice, const QString &name);
+ bool setFormat(const QSize &size, uint32_t pixelFormat, uint32_t bytesPerLine);
+ bool clearBuffers();
+ bool requestBuffer();
+ bool queueBuffer(int dmabufFd, uint bytesUsed, uint length);
+ bool streamOn();
+ bool streamOff();
+ private:
+ int m_subdevFd = -1;
+ };
+
+ static bool setSubdevFormat(struct media_pad *pad, const QSize &size, uint32_t mbusFormat = MEDIA_BUS_FMT_ARGB8888_1X32);
+
+ static bool setSubdevSelection(struct media_pad *pad, const QRect &geometry, uint target);
+ static bool setSubdevCrop(struct media_pad *pad, const QRect &geometry);
+ static bool setSubdevCompose(struct media_pad *pad, const QRect &geometry);
+
+private:
+ static bool streamOn(int subDeviceFd, v4l2_buf_type bufferType);
+ static bool streamOff(int subDeviceFd, v4l2_buf_type bufferType);
+ struct media_device *m_mediaDevice = nullptr;
+ const struct media_device_info *m_info = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QLINUXMEDIADEVICE_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp
new file mode 100644
index 0000000000..c9b9bb5b7f
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvsp2blendingdevice.h"
+#include <qeglfskmshelpers.h>
+
+#include <QDebug>
+#include <QtCore/QLoggingCategory>
+
+#include <drm_fourcc.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+//TODO: is this the right place for these conversion functions?
+static inline uint drmFormatToV4l2PixelFormat(uint drmFormat) {
+ //ARGB8888 == ABGR32 because linux media list stuff in the opposite order, but the fourcc is the same
+ Q_ASSERT(DRM_FORMAT_ARGB8888 == V4L2_PIX_FMT_ABGR32);
+ return drmFormat;
+}
+
+static uint drmFormatToMediaBusFormat(uint drmFormat)
+{
+ switch (drmFormat) {
+ case DRM_FORMAT_RGB888:
+ return MEDIA_BUS_FMT_RGB888_1X24;
+ case DRM_FORMAT_BGR888:
+ return MEDIA_BUS_FMT_BGR888_1X24;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+// return MEDIA_BUS_FMT_RGB888_1X32_PADHI; // doesn't work on renesas m3, just use fallthrough to argb for now
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_BGRA8888:
+ return MEDIA_BUS_FMT_ARGB8888_1X32;
+ default:
+ qWarning() << "Unknown drm format" << q_fourccToString(drmFormat) << "defaulting to argb8888";
+ return MEDIA_BUS_FMT_ARGB8888_1X32;
+ }
+}
+
+QVsp2BlendingDevice::QVsp2BlendingDevice(const QSize &screenSize)
+ : m_mediaDevice("/dev/media0")
+ , m_screenSize(screenSize)
+{
+ QLinuxMediaDevice &md = m_mediaDevice;
+ QString deviceName = md.deviceName();
+
+ if (md.model() != QString("VSP2"))
+ qWarning() << "Unsupported media device model:" << md.model();
+
+ if (deviceName != "fe960000.vsp")
+ qWarning() << "Unknown media device name:" << deviceName;
+
+ const int numInputs = 5;
+
+ for (int i = 0; i < numInputs; ++i) {
+ Input input;
+ input.linkToBru = md.parseLink(QString("'%1 rpf.%2':1 -> '%1 bru':%2").arg(deviceName).arg(i));
+ input.inputFormatPad = md.parsePad(QString("'%1 rpf.%2':0").arg(deviceName).arg(i));
+ input.outputFormatPad = md.parsePad(QString("'%1 rpf.%2':1").arg(deviceName).arg(i));
+ input.bruInputFormatPad = md.parsePad(QString("'%1 bru':%2").arg(deviceName).arg(i));
+ input.rpfInput = new QLinuxMediaDevice::OutputSubDevice(&md, QString("%1 rpf.%2 input").arg(deviceName).arg(i));
+ m_inputs.append(input);
+ }
+
+ m_wpfOutput = new QLinuxMediaDevice::CaptureSubDevice(&md, QString("%1 wpf.0 output").arg(deviceName));
+
+ // Setup links for output
+ md.enableLink(md.parseLink(QString("'%1 bru':5 -> '%1 wpf.0':0").arg(deviceName)));
+ md.enableLink(md.parseLink(QString("'%1 wpf.0':1 -> '%1 wpf.0 output':0").arg(deviceName)));
+
+ // Output pads
+ auto bruOutputFormatPad = md.parsePad(QString("'%1 bru':5").arg(deviceName));
+ auto wpfInputFormatPad = md.parsePad(QString("'%1 wpf.0':0").arg(deviceName));
+ auto wpfOutputFormatPad = md.parsePad(QString("'%1 wpf.0':1").arg(deviceName));
+
+ m_wpfOutput->setFormat(screenSize);
+ QLinuxMediaDevice::setSubdevFormat(bruOutputFormatPad, screenSize);
+ QLinuxMediaDevice::setSubdevFormat(wpfInputFormatPad, screenSize);
+ QLinuxMediaDevice::setSubdevFormat(wpfOutputFormatPad, screenSize);
+
+ m_wpfOutput->requestBuffer();
+}
+
+bool QVsp2BlendingDevice::enableInput(int i, const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine)
+{
+ qCDebug(qLcEglfsKmsDebug) << "Blend unit: Enabling input" << i;
+ if (m_inputs[i].enabled) {
+ qWarning("Vsp2: Input %d already enabled", i);
+ return false;
+ }
+
+ if (!bufferGeometry.isValid()) { //TODO: bounds checking as well?
+ qWarning() << "Vsp2: Invalid buffer geometry";
+ return false;
+ }
+
+ Input &input = m_inputs[i];
+ if (!m_mediaDevice.enableLink(input.linkToBru))
+ return false;
+
+ uint pixelFormat = drmFormatToV4l2PixelFormat(drmFormat);
+ if (!setInputFormat(i, bufferGeometry, pixelFormat, bytesPerLine)) {
+ disableInput(i);
+ return false;
+ }
+
+ input.rpfInput->requestBuffer();
+ return true;
+}
+
+int QVsp2BlendingDevice::enableInput(const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine)
+{
+ for (int i = 0; i < m_inputs.size(); ++i) {
+ if (!m_inputs[i].enabled)
+ return enableInput(i, bufferGeometry, drmFormat, bytesPerLine) ? i : -1;
+ }
+ qWarning() << "Vsp2: No more inputs available in blend unit";
+ return -1;
+}
+
+bool QVsp2BlendingDevice::disableInput(int i)
+{
+ qCDebug(qLcEglfsKmsDebug) << "Vsp2: disabling input" << i;
+ if (!m_inputs[i].enabled) {
+ qWarning("Vsp2: Input %d already disabled", i);
+ return false;
+ }
+ m_mediaDevice.disableLink(m_inputs[i].linkToBru);
+ m_inputs[i].rpfInput->clearBuffers();
+ m_inputs[i].enabled = false;
+ return true;
+}
+
+bool QVsp2BlendingDevice::setInputBuffer(int index, int dmabufFd)
+{
+ Input &input = m_inputs[index];
+
+ if (!input.enabled) {
+ qWarning() << "Vsp2: Can't queue on disabled input" << index;
+ return false;
+ }
+
+ // Don't queue the buffer yet, store it here and wait until blending
+ if (input.dmabuf.fd != dmabufFd) {
+ m_dirty = true;
+ input.dmabuf.fd = dmabufFd;
+ }
+ return true;
+}
+
+bool QVsp2BlendingDevice::setInputPosition(int index, const QPoint &position)
+{
+ Input &input = m_inputs[index];
+
+ if (input.geometry.topLeft() == position)
+ return true;
+
+ m_dirty = true;
+ input.geometry.moveTopLeft(position);
+ return QLinuxMediaDevice::setSubdevCompose(input.bruInputFormatPad, input.geometry);
+}
+
+bool QVsp2BlendingDevice::blend(int outputDmabufFd)
+{
+ if (!m_dirty)
+ qWarning("Blending without being dirty, should not be necessary");
+
+ if (!m_inputs[0].enabled) {
+ qWarning("Vsp2: Can't blend with layer 0 disabled");
+ return false;
+ }
+
+ // Queue dma input buffers
+ for (int i=0; i < m_inputs.size(); ++i) {
+ auto &input = m_inputs[i];
+ if (input.enabled) {
+ if (!input.rpfInput->queueBuffer(input.dmabuf.fd, input.dmabuf.bytesUsed, input.dmabuf.length)) {
+ qWarning() << "Vsp2: Failed to queue buffer for input" << i
+ << "with dmabuf" << input.dmabuf.fd
+ << "and size" << input.geometry.size();
+
+ if (!disableInput(i))
+ qWarning() << "Vsp2: Failed to disable input" << i;
+ }
+ }
+ }
+
+ if (!m_wpfOutput->queueBuffer(outputDmabufFd, m_screenSize)) {
+ qWarning() << "Vsp2: Failed to queue blending output buffer" << outputDmabufFd << m_screenSize;
+ return false;
+ }
+
+ if (!streamOn()) {
+ qWarning() << "Vsp2: Failed to start streaming";
+ return false;
+ }
+
+ if (!m_wpfOutput->dequeueBuffer()) {
+ qWarning() << "Vsp2: Failed to dequeue blending output buffer";
+ return false;
+ }
+
+ if (!streamOff()) {
+ qWarning() << "Vsp2: Failed to stop streaming";
+ return false;
+ }
+
+ m_dirty = false;
+ return true;
+}
+
+int QVsp2BlendingDevice::numInputs() const
+{
+ return m_inputs.size();
+}
+
+bool QVsp2BlendingDevice::streamOn()
+{
+ for (auto &input : m_inputs) {
+ if (input.enabled) {
+ if (!input.rpfInput->streamOn()) {
+ //TODO: perhaps it's better to try to continue with the other inputs?
+ return false;
+ }
+ }
+ }
+
+ return m_wpfOutput->streamOn();
+}
+
+bool QVsp2BlendingDevice::streamOff()
+{
+ if (!m_wpfOutput->streamOff()) {
+ //TODO: perhaps it's better to try to continue with the other inputs?
+ return false;
+ }
+
+ for (auto &input : m_inputs) {
+ if (input.enabled) {
+ if (!input.rpfInput->streamOff())
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool QVsp2BlendingDevice::setInputFormat(int i, const QRect &bufferGeometry, uint pixelFormat, uint bytesPerLine)
+{
+ Input &input = m_inputs[i];
+
+ Q_ASSERT(bufferGeometry.isValid());
+
+ const uint bpp = 4; //TODO: don't hardcode bpp, get it from pixelFormat?
+ input.enabled = true;
+ input.geometry = bufferGeometry;
+ input.dmabuf.bytesUsed = bpp * static_cast<uint>(bufferGeometry.width()) * static_cast<uint>(bufferGeometry.height());
+ input.dmabuf.length = static_cast<uint>(bufferGeometry.height()) * bytesPerLine;
+
+ const QSize size = bufferGeometry.size();
+
+ if (!input.rpfInput->setFormat(size, pixelFormat, bytesPerLine)) // rpf.x input
+ return false;
+
+ const uint mediaBusFormat = drmFormatToMediaBusFormat(pixelFormat);
+ if (!QLinuxMediaDevice::setSubdevFormat(input.inputFormatPad, size, mediaBusFormat)) // rpf.x:0
+ return false;
+
+ if (!QLinuxMediaDevice::setSubdevFormat(input.outputFormatPad, size, mediaBusFormat)) // rpf.x:1
+ return false;
+
+ if (!QLinuxMediaDevice::setSubdevFormat(input.bruInputFormatPad, size, mediaBusFormat)) // bru:x
+ return false;
+
+ if (!QLinuxMediaDevice::setSubdevCrop(input.inputFormatPad, QRect(QPoint(0, 0), size)))
+ return false;
+
+ if (!QLinuxMediaDevice::setSubdevCompose(input.bruInputFormatPad, bufferGeometry))
+ return false;
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h
new file mode 100644
index 0000000000..ff2d581d72
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVSP2BLENDINGDEVICE_H
+#define QVSP2BLENDINGDEVICE_H
+
+#include <QtCore/QRect>
+#include <QtCore/QVector>
+#include <QtCore/qglobal.h>
+
+#include "qlinuxmediadevice.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSize;
+
+class QVsp2BlendingDevice
+{
+public:
+ QVsp2BlendingDevice(const QSize& screenSize); //TODO: add support for output format as well?
+ bool enableInput(int i, const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine);
+ int enableInput(const QRect &bufferGeometry, uint drmFormat, uint bytesPerLine);
+ bool disableInput(int i);
+ bool setInputBuffer(int index, int dmabufFd);
+ bool setInputPosition(int index, const QPoint &position);
+ bool blend(int outputDmabufFd);
+ int numInputs() const;
+ bool isDirty() const { return m_dirty; }
+private:
+ bool streamOn();
+ bool streamOff();
+ bool setInputFormat(int i, const QRect &bufferGeometry, uint pixelFormat, uint bytesPerLine);
+ QLinuxMediaDevice m_mediaDevice;
+ QLinuxMediaDevice::CaptureSubDevice *m_wpfOutput = nullptr; // wpf output
+ struct Input {
+ bool enabled = false;
+ QRect geometry;
+ struct {
+ int fd = -1;
+ uint bytesUsed = 0;
+ uint length = 0;
+ } dmabuf;
+ struct media_link *linkToBru = nullptr; //rpf.x:1 -> bru:x
+ struct media_pad *inputFormatPad = nullptr; // rpf.x:0
+ struct media_pad *outputFormatPad = nullptr; // rpf.x:1
+ struct media_pad *bruInputFormatPad = nullptr; // bru:x
+ QLinuxMediaDevice::OutputSubDevice *rpfInput = nullptr; // rpf.x input
+ };
+ QVector<struct Input> m_inputs;
+ const QSize m_screenSize;
+ bool m_dirty = true;
+};
+
+QT_END_NAMESPACE
+
+#endif // QVSP2BLENDINGDEVICE
diff --git a/src/plugins/platforms/haiku/main.cpp b/src/plugins/platforms/haiku/main.cpp
index 02168d0165..841891970d 100644
--- a/src/plugins/platforms/haiku/main.cpp
+++ b/src/plugins/platforms/haiku/main.cpp
@@ -47,7 +47,7 @@ QPlatformIntegration *QHaikuIntegrationPlugin::create(const QString& system, con
if (!system.compare(QLatin1String("haiku"), Qt::CaseInsensitive))
return new QHaikuIntegration(paramList);
- return Q_NULLPTR;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/haiku/main.h b/src/plugins/platforms/haiku/main.h
index 82f3313652..e316b79d7c 100644
--- a/src/plugins/platforms/haiku/main.h
+++ b/src/plugins/platforms/haiku/main.h
@@ -47,7 +47,7 @@ class QHaikuIntegrationPlugin : public QPlatformIntegrationPlugin
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "haiku.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/haiku/qhaikuapplication.h b/src/plugins/platforms/haiku/qhaikuapplication.h
index 0696df8109..a9ea442691 100644
--- a/src/plugins/platforms/haiku/qhaikuapplication.h
+++ b/src/plugins/platforms/haiku/qhaikuapplication.h
@@ -49,8 +49,8 @@ class QHaikuApplication : public BApplication
public:
explicit QHaikuApplication(const char *signature);
- bool QuitRequested() Q_DECL_OVERRIDE;
- void RefsReceived(BMessage* message) Q_DECL_OVERRIDE;
+ bool QuitRequested() override;
+ void RefsReceived(BMessage* message) override;
};
#endif
diff --git a/src/plugins/platforms/haiku/qhaikubuffer.cpp b/src/plugins/platforms/haiku/qhaikubuffer.cpp
index c6f6ffe6bc..f25ddef86b 100644
--- a/src/plugins/platforms/haiku/qhaikubuffer.cpp
+++ b/src/plugins/platforms/haiku/qhaikubuffer.cpp
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
QHaikuBuffer::QHaikuBuffer()
- : m_buffer(Q_NULLPTR)
+ : m_buffer(nullptr)
{
}
@@ -63,12 +63,12 @@ BBitmap* QHaikuBuffer::nativeBuffer() const
const QImage *QHaikuBuffer::image() const
{
- return (m_buffer != Q_NULLPTR) ? &m_image : Q_NULLPTR;
+ return (m_buffer != nullptr) ? &m_image : nullptr;
}
QImage *QHaikuBuffer::image()
{
- return (m_buffer != Q_NULLPTR) ? &m_image : Q_NULLPTR;
+ return (m_buffer != nullptr) ? &m_image : nullptr;
}
QRect QHaikuBuffer::rect() const
diff --git a/src/plugins/platforms/haiku/qhaikuclipboard.cpp b/src/plugins/platforms/haiku/qhaikuclipboard.cpp
index 774da4432a..20519e21d0 100644
--- a/src/plugins/platforms/haiku/qhaikuclipboard.cpp
+++ b/src/plugins/platforms/haiku/qhaikuclipboard.cpp
@@ -47,8 +47,8 @@
#include <Clipboard.h>
QHaikuClipboard::QHaikuClipboard()
- : m_systemMimeData(Q_NULLPTR)
- , m_userMimeData(Q_NULLPTR)
+ : m_systemMimeData(nullptr)
+ , m_userMimeData(nullptr)
{
if (be_clipboard)
be_clipboard->StartWatching(BMessenger(this));
@@ -81,12 +81,12 @@ QMimeData *QHaikuClipboard::mimeData(QClipboard::Mode mode)
const BMessage *clipboard = be_clipboard->Data();
if (clipboard) {
- char *name = Q_NULLPTR;
+ char *name = nullptr;
uint32 type = 0;
int32 count = 0;
for (int i = 0; clipboard->GetInfo(B_MIME_TYPE, i, &name, &type, &count) == B_OK; i++) {
- const void *data = Q_NULLPTR;
+ const void *data = nullptr;
int32 dataLen = 0;
const status_t status = clipboard->FindData(name, B_MIME_TYPE, &data, &dataLen);
@@ -162,7 +162,7 @@ void QHaikuClipboard::MessageReceived(BMessage* message)
{
if (message->what == B_CLIPBOARD_CHANGED) {
delete m_userMimeData;
- m_userMimeData = Q_NULLPTR;
+ m_userMimeData = nullptr;
emitChanged(QClipboard::Clipboard);
}
diff --git a/src/plugins/platforms/haiku/qhaikuclipboard.h b/src/plugins/platforms/haiku/qhaikuclipboard.h
index 3dd4496e8d..b6eb3f591f 100644
--- a/src/plugins/platforms/haiku/qhaikuclipboard.h
+++ b/src/plugins/platforms/haiku/qhaikuclipboard.h
@@ -54,13 +54,13 @@ public:
QHaikuClipboard();
~QHaikuClipboard();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
- bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
// override from BHandler to catch change notifications from Haiku clipboard
- void MessageReceived(BMessage* message) Q_DECL_OVERRIDE;
+ void MessageReceived(BMessage* message) override;
private:
QMimeData *m_systemMimeData;
diff --git a/src/plugins/platforms/haiku/qhaikucursor.h b/src/plugins/platforms/haiku/qhaikucursor.h
index 5d70c97d9e..73a1d2c492 100644
--- a/src/plugins/platforms/haiku/qhaikucursor.h
+++ b/src/plugins/platforms/haiku/qhaikucursor.h
@@ -52,7 +52,7 @@ public:
QHaikuCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor *windowCursor, QWindow *window) override;
#endif
private:
diff --git a/src/plugins/platforms/haiku/qhaikuintegration.cpp b/src/plugins/platforms/haiku/qhaikuintegration.cpp
index d46d77ff18..8bd2171794 100644
--- a/src/plugins/platforms/haiku/qhaikuintegration.cpp
+++ b/src/plugins/platforms/haiku/qhaikuintegration.cpp
@@ -87,13 +87,13 @@ QHaikuIntegration::QHaikuIntegration(const QStringList &parameters)
QHaikuIntegration::~QHaikuIntegration()
{
destroyScreen(m_screen);
- m_screen = Q_NULLPTR;
+ m_screen = nullptr;
delete m_services;
- m_services = Q_NULLPTR;
+ m_services = nullptr;
delete m_clipboard;
- m_clipboard = Q_NULLPTR;
+ m_clipboard = nullptr;
be_app->LockLooper();
be_app->Quit();
diff --git a/src/plugins/platforms/haiku/qhaikuintegration.h b/src/plugins/platforms/haiku/qhaikuintegration.h
index 1b938acb82..5c7a173c91 100644
--- a/src/plugins/platforms/haiku/qhaikuintegration.h
+++ b/src/plugins/platforms/haiku/qhaikuintegration.h
@@ -54,17 +54,17 @@ public:
explicit QHaikuIntegration(const QStringList &paramList);
~QHaikuIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const override;
+ QPlatformServices *services() const override;
#ifndef QT_NO_CLIPBOARD
- QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
+ QPlatformClipboard *clipboard() const override;
#endif
private:
diff --git a/src/plugins/platforms/haiku/qhaikurasterbackingstore.cpp b/src/plugins/platforms/haiku/qhaikurasterbackingstore.cpp
index ee53f693cd..613ae471cb 100644
--- a/src/plugins/platforms/haiku/qhaikurasterbackingstore.cpp
+++ b/src/plugins/platforms/haiku/qhaikurasterbackingstore.cpp
@@ -47,14 +47,14 @@ QT_BEGIN_NAMESPACE
QHaikuRasterBackingStore::QHaikuRasterBackingStore(QWindow *window)
: QPlatformBackingStore(window)
- , m_bitmap(Q_NULLPTR)
+ , m_bitmap(nullptr)
{
}
QHaikuRasterBackingStore::~QHaikuRasterBackingStore()
{
delete m_bitmap;
- m_bitmap = Q_NULLPTR;
+ m_bitmap = nullptr;
}
QPaintDevice *QHaikuRasterBackingStore::paintDevice()
@@ -62,7 +62,7 @@ QPaintDevice *QHaikuRasterBackingStore::paintDevice()
if (!m_bufferSize.isEmpty() && m_bitmap)
return m_buffer.image();
- return Q_NULLPTR;
+ return nullptr;
}
void QHaikuRasterBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
diff --git a/src/plugins/platforms/haiku/qhaikurasterbackingstore.h b/src/plugins/platforms/haiku/qhaikurasterbackingstore.h
index 06a46e7eb3..060ab27126 100644
--- a/src/plugins/platforms/haiku/qhaikurasterbackingstore.h
+++ b/src/plugins/platforms/haiku/qhaikurasterbackingstore.h
@@ -55,9 +55,9 @@ public:
explicit QHaikuRasterBackingStore(QWindow *window);
~QHaikuRasterBackingStore();
- QPaintDevice *paintDevice() 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;
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
private:
BBitmap *m_bitmap;
diff --git a/src/plugins/platforms/haiku/qhaikurasterwindow.cpp b/src/plugins/platforms/haiku/qhaikurasterwindow.cpp
index 9834b7cbc7..7e57e67bab 100644
--- a/src/plugins/platforms/haiku/qhaikurasterwindow.cpp
+++ b/src/plugins/platforms/haiku/qhaikurasterwindow.cpp
@@ -211,7 +211,7 @@ void HaikuViewProxy::handleKeyEvent(QEvent::Type type, BMessage *message)
{
int32 key = 0;
uint32 code = 0;
- const char *bytes = Q_NULLPTR;
+ const char *bytes = nullptr;
QString text;
if (message) {
@@ -265,7 +265,7 @@ QHaikuRasterWindow::~QHaikuRasterWindow()
m_window->UnlockLooper();
delete m_view;
- m_view = Q_NULLPTR;
+ m_view = nullptr;
}
BView* QHaikuRasterWindow::nativeViewHandle() const
diff --git a/src/plugins/platforms/haiku/qhaikurasterwindow.h b/src/plugins/platforms/haiku/qhaikurasterwindow.h
index ae57e0f0e4..24b13aa122 100644
--- a/src/plugins/platforms/haiku/qhaikurasterwindow.h
+++ b/src/plugins/platforms/haiku/qhaikurasterwindow.h
@@ -51,15 +51,15 @@ class HaikuViewProxy : public QObject, public BView
Q_OBJECT
public:
- explicit HaikuViewProxy(BWindow *window, QObject *parent = Q_NULLPTR);
+ explicit HaikuViewProxy(BWindow *window, QObject *parent = nullptr);
- void MessageReceived(BMessage *message) Q_DECL_OVERRIDE;
- void Draw(BRect updateRect) Q_DECL_OVERRIDE;
- void MouseDown(BPoint pos) Q_DECL_OVERRIDE;
- void MouseUp(BPoint pos) Q_DECL_OVERRIDE;
- void MouseMoved(BPoint pos, uint32 code, const BMessage *dragMessage) Q_DECL_OVERRIDE;
- void KeyDown(const char *bytes, int32 numBytes) Q_DECL_OVERRIDE;
- void KeyUp(const char *bytes, int32 numBytes) Q_DECL_OVERRIDE;
+ void MessageReceived(BMessage *message) override;
+ void Draw(BRect updateRect) override;
+ void MouseDown(BPoint pos) override;
+ void MouseUp(BPoint pos) override;
+ void MouseMoved(BPoint pos, uint32 code, const BMessage *dragMessage) override;
+ void KeyDown(const char *bytes, int32 numBytes) override;
+ void KeyUp(const char *bytes, int32 numBytes) override;
Q_SIGNALS:
void mouseEvent(const QPoint &localPosition, const QPoint &globalPosition, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
diff --git a/src/plugins/platforms/haiku/qhaikuscreen.cpp b/src/plugins/platforms/haiku/qhaikuscreen.cpp
index 54951a0af5..2c8abba8aa 100644
--- a/src/plugins/platforms/haiku/qhaikuscreen.cpp
+++ b/src/plugins/platforms/haiku/qhaikuscreen.cpp
@@ -58,10 +58,10 @@ QHaikuScreen::QHaikuScreen()
QHaikuScreen::~QHaikuScreen()
{
delete m_cursor;
- m_cursor = Q_NULLPTR;
+ m_cursor = nullptr;
delete m_screen;
- m_screen = Q_NULLPTR;
+ m_screen = nullptr;
}
QPixmap QHaikuScreen::grabWindow(WId winId, int x, int y, int width, int height) const
@@ -69,8 +69,8 @@ QPixmap QHaikuScreen::grabWindow(WId winId, int x, int y, int width, int height)
if (width == 0 || height == 0)
return QPixmap();
- BScreen screen(Q_NULLPTR);
- BBitmap *bitmap = Q_NULLPTR;
+ BScreen screen(nullptr);
+ BBitmap *bitmap = nullptr;
screen.GetBitmap(&bitmap);
const BRect frame = (winId ? ((BWindow*)winId)->Frame() : screen.Frame());
diff --git a/src/plugins/platforms/haiku/qhaikuscreen.h b/src/plugins/platforms/haiku/qhaikuscreen.h
index 49fa3f0a60..98de6fdd03 100644
--- a/src/plugins/platforms/haiku/qhaikuscreen.h
+++ b/src/plugins/platforms/haiku/qhaikuscreen.h
@@ -53,13 +53,13 @@ public:
QHaikuScreen();
~QHaikuScreen();
- QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
- QRect geometry() const Q_DECL_OVERRIDE;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
+ QRect geometry() const override;
+ int depth() const override;
+ QImage::Format format() const override;
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ QPlatformCursor *cursor() const override;
private:
BScreen *m_screen;
diff --git a/src/plugins/platforms/haiku/qhaikuservices.h b/src/plugins/platforms/haiku/qhaikuservices.h
index a210eb8b61..59ff6395fb 100644
--- a/src/plugins/platforms/haiku/qhaikuservices.h
+++ b/src/plugins/platforms/haiku/qhaikuservices.h
@@ -47,10 +47,10 @@ QT_BEGIN_NAMESPACE
class QHaikuServices : public QPlatformServices
{
public:
- bool openUrl(const QUrl &url) Q_DECL_OVERRIDE;
- bool openDocument(const QUrl &url) Q_DECL_OVERRIDE;
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
- QByteArray desktopEnvironment() const Q_DECL_OVERRIDE;
+ QByteArray desktopEnvironment() const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.cpp b/src/plugins/platforms/haiku/qhaikuwindow.cpp
index 4bea7f7ff6..f8fdf3f92d 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.cpp
+++ b/src/plugins/platforms/haiku/qhaikuwindow.cpp
@@ -118,12 +118,12 @@ void HaikuWindowProxy::zoomByQt()
QHaikuWindow::QHaikuWindow(QWindow *window)
: QPlatformWindow(window)
- , m_window(Q_NULLPTR)
+ , m_window(nullptr)
, m_windowState(Qt::WindowNoState)
{
const QRect rect = initialGeometry(window, window->geometry(), DefaultWindowWidth, DefaultWindowHeight);
- HaikuWindowProxy *haikuWindow = new HaikuWindowProxy(window, rect, Q_NULLPTR);
+ HaikuWindowProxy *haikuWindow = new HaikuWindowProxy(window, rect, nullptr);
connect(haikuWindow, SIGNAL(moved(QPoint)), SLOT(haikuWindowMoved(QPoint)));
connect(haikuWindow, SIGNAL(resized(QSize,bool)), SLOT(haikuWindowResized(QSize,bool)));
connect(haikuWindow, SIGNAL(windowActivated(bool)), SLOT(haikuWindowActivated(bool)));
@@ -145,7 +145,7 @@ QHaikuWindow::~QHaikuWindow()
m_window->LockLooper();
m_window->Quit();
- m_window = Q_NULLPTR;
+ m_window = nullptr;
}
void QHaikuWindow::setGeometry(const QRect &rect)
@@ -330,7 +330,7 @@ void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
void QHaikuWindow::haikuWindowActivated(bool activated)
{
- QWindowSystemInterface::handleWindowActivated(activated ? window() : Q_NULLPTR);
+ QWindowSystemInterface::handleWindowActivated(activated ? window() : nullptr);
}
void QHaikuWindow::haikuWindowMinimized(bool minimize)
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.h b/src/plugins/platforms/haiku/qhaikuwindow.h
index 5bfb99e532..bb57742087 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.h
+++ b/src/plugins/platforms/haiku/qhaikuwindow.h
@@ -51,14 +51,14 @@ class HaikuWindowProxy : public QObject, public BWindow
Q_OBJECT
public:
- explicit HaikuWindowProxy(QWindow *window, const QRect &rect, QObject *parent = Q_NULLPTR);
+ explicit HaikuWindowProxy(QWindow *window, const QRect &rect, QObject *parent = nullptr);
- void FrameMoved(BPoint pos) Q_DECL_OVERRIDE;
- void FrameResized(float width, float height) Q_DECL_OVERRIDE;
- void WindowActivated(bool activated) Q_DECL_OVERRIDE;
- void Minimize(bool minimize) Q_DECL_OVERRIDE;
- void Zoom(BPoint pos, float width, float height) Q_DECL_OVERRIDE;
- bool QuitRequested() Q_DECL_OVERRIDE;
+ void FrameMoved(BPoint pos) override;
+ void FrameResized(float width, float height) override;
+ void WindowActivated(bool activated) override;
+ void Minimize(bool minimize) override;
+ void Zoom(BPoint pos, float width, float height) override;
+ bool QuitRequested() override;
void zoomByQt();
@@ -83,23 +83,23 @@ public:
explicit QHaikuWindow(QWindow *window);
virtual ~QHaikuWindow();
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QMargins frameMargins() const Q_DECL_OVERRIDE;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &rect) override;
+ QMargins frameMargins() const override;
+ void setVisible(bool visible) override;
- bool isExposed() const Q_DECL_OVERRIDE;
- bool isActive() const Q_DECL_OVERRIDE;
+ bool isExposed() const override;
+ bool isActive() const override;
- WId winId() const Q_DECL_OVERRIDE;
+ WId winId() const override;
BWindow* nativeHandle() const;
- void requestActivateWindow() Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
- void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
+ void requestActivateWindow() override;
+ void setWindowState(Qt::WindowStates state) override;
+ void setWindowFlags(Qt::WindowFlags flags) override;
- void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
+ void setWindowTitle(const QString &title) override;
- void propagateSizeHints() Q_DECL_OVERRIDE;
+ void propagateSizeHints() override;
protected:
HaikuWindowProxy *m_window;
diff --git a/src/plugins/platforms/integrity/main.cpp b/src/plugins/platforms/integrity/main.cpp
index f75e227335..6313aa47e5 100644
--- a/src/plugins/platforms/integrity/main.cpp
+++ b/src/plugins/platforms/integrity/main.cpp
@@ -47,7 +47,7 @@ class QIntegrityFbIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "integrity.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration* QIntegrityFbIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/integrity/qintegrityfbintegration.h b/src/plugins/platforms/integrity/qintegrityfbintegration.h
index a954dc2356..d0cd5417ab 100644
--- a/src/plugins/platforms/integrity/qintegrityfbintegration.h
+++ b/src/plugins/platforms/integrity/qintegrityfbintegration.h
@@ -54,19 +54,19 @@ public:
QIntegrityFbIntegration(const QStringList &paramList);
~QIntegrityFbIntegration();
- void initialize() Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ void initialize() override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; }
+ QPlatformFontDatabase *fontDatabase() const override;
+ QPlatformServices *services() const override;
+ QPlatformInputContext *inputContext() const override { return m_inputContext; }
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QPlatformNativeInterface *nativeInterface() const override;
QList<QPlatformScreen *> screens() const;
diff --git a/src/plugins/platforms/integrity/qintegrityfbscreen.cpp b/src/plugins/platforms/integrity/qintegrityfbscreen.cpp
index 3979937955..d64b96ca4c 100644
--- a/src/plugins/platforms/integrity/qintegrityfbscreen.cpp
+++ b/src/plugins/platforms/integrity/qintegrityfbscreen.cpp
@@ -204,15 +204,14 @@ QRegion QIntegrityFbScreen::doRedraw()
if (!mBlitter)
mBlitter = new QPainter(&mFbScreenImage);
- QVector<QRect> rects = touched.rects();
- for (int i = 0; i < rects.size(); i++) {
+ for (QRect rect : touched) {
FBRect fbrect = {
- (uint32_t)rects[i].left(),
- (uint32_t)rects[i].top(),
- (uint32_t)rects[i].width(),
- (uint32_t)rects[i].height()
+ (uint32_t)rect.left(),
+ (uint32_t)rect.top(),
+ (uint32_t)rect.width(),
+ (uint32_t)rect.height()
};
- mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
+ mBlitter->drawImage(rect, mScreenImage, rect);
gh_FB_expose(mFbh, &fbrect, NULL);
}
return touched;
diff --git a/src/plugins/platforms/integrity/qintegrityfbscreen.h b/src/plugins/platforms/integrity/qintegrityfbscreen.h
index 6bc78913c9..c38b4f073d 100644
--- a/src/plugins/platforms/integrity/qintegrityfbscreen.h
+++ b/src/plugins/platforms/integrity/qintegrityfbscreen.h
@@ -57,9 +57,9 @@ public:
bool initialize();
- QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
- QRegion doRedraw() Q_DECL_OVERRIDE;
+ QRegion doRedraw() override;
private:
QStringList mArgs;
diff --git a/src/plugins/platforms/integrity/qintegrityhidmanager.cpp b/src/plugins/platforms/integrity/qintegrityhidmanager.cpp
index 49583735f5..3570b90134 100644
--- a/src/plugins/platforms/integrity/qintegrityhidmanager.cpp
+++ b/src/plugins/platforms/integrity/qintegrityhidmanager.cpp
@@ -73,8 +73,8 @@ public:
{
CheckSuccess(gh_hid_close(handle));
};
- void process_event(void) Q_DECL_OVERRIDE;
- void async_wait(void) Q_DECL_OVERRIDE;
+ void process_event(void) override;
+ void async_wait(void) override;
HIDDriver *get_driver(void) { return driver; };
HIDHandle get_handle(void) { return handle; };
private:
@@ -92,8 +92,8 @@ public:
{
qDeleteAll(devices);
};
- void process_event(void) Q_DECL_OVERRIDE;
- void async_wait(void) Q_DECL_OVERRIDE;
+ void process_event(void) override;
+ void async_wait(void) override;
void find_devices(void);
private:
QHash<Value, HIDDeviceHandler *> devices;
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
index bea2897240..54152aebf7 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosfileengineassetslibrary.mm
@@ -302,7 +302,7 @@ public:
g_iteratorCurrentUrl.setLocalData(QString());
}
- QString next() Q_DECL_OVERRIDE
+ QString next() override
{
// Cache the URL that we are about to return, since QDir will immediately create a
// new file engine on the file and ask if it exists. Unless we do this, we end up
@@ -314,17 +314,17 @@ public:
return url;
}
- bool hasNext() const Q_DECL_OVERRIDE
+ bool hasNext() const override
{
return m_enumerator->hasNext();
}
- QString currentFileName() const Q_DECL_OVERRIDE
+ QString currentFileName() const override
{
return g_iteratorCurrentUrl.localData();
}
- QFileInfo currentFileInfo() const Q_DECL_OVERRIDE
+ QFileInfo currentFileInfo() const override
{
return QFileInfo(currentFileName());
}
diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h
index e6b890251a..38006ba90b 100644
--- a/src/plugins/platforms/ios/qiosbackingstore.h
+++ b/src/plugins/platforms/ios/qiosbackingstore.h
@@ -54,7 +54,7 @@ public:
QIOSBackingStore(QWindow *window);
~QIOSBackingStore();
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosclipboard.h b/src/plugins/platforms/ios/qiosclipboard.h
index f3ccfcace0..3fe9b29b71 100644
--- a/src/plugins/platforms/ios/qiosclipboard.h
+++ b/src/plugins/platforms/ios/qiosclipboard.h
@@ -58,10 +58,10 @@ public:
QIOSClipboard();
~QIOSClipboard();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- void setMimeData(QMimeData *mimeData, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
- bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData *mimeData, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
private:
QUIClipboard *m_clipboard;
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index 15deb3332e..9a975eadc9 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -138,8 +138,8 @@ public:
QIOSMimeData(QClipboard::Mode mode) : QMimeData(), m_mode(mode) { }
~QIOSMimeData() { }
- QStringList formats() const Q_DECL_OVERRIDE;
- QVariant retrieveData(const QString &mimeType, QVariant::Type type) const Q_DECL_OVERRIDE;
+ QStringList formats() const override;
+ QVariant retrieveData(const QString &mimeType, QVariant::Type type) const override;
private:
const QClipboard::Mode m_mode;
diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h
index ce50eff1d9..a2595877dc 100644
--- a/src/plugins/platforms/ios/qioscontext.h
+++ b/src/plugins/platforms/ios/qioscontext.h
@@ -57,18 +57,18 @@ public:
QIOSContext(QOpenGLContext *context);
~QIOSContext();
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *surface) override;
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
- GLuint defaultFramebufferObject(QPlatformSurface *) const Q_DECL_OVERRIDE;
- QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE;
+ GLuint defaultFramebufferObject(QPlatformSurface *) const override;
+ QFunctionPointer getProcAddress(const char *procName) override;
- bool isSharing() const Q_DECL_OVERRIDE;
- bool isValid() const Q_DECL_OVERRIDE;
+ bool isSharing() const override;
+ bool isValid() const override;
private Q_SLOTS:
void windowDestroyed(QObject *object);
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
index c1442ed1e8..62133b9510 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -51,8 +51,8 @@ class QIOSEventDispatcher : public QEventDispatcherCoreFoundation
public:
explicit QIOSEventDispatcher(QObject *parent = 0);
- bool processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
- bool processPostedEvents() Q_DECL_OVERRIDE;
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ bool processPostedEvents() override;
void handleRunLoopExit(CFRunLoopActivity activity);
diff --git a/src/plugins/platforms/ios/qiosfiledialog.h b/src/plugins/platforms/ios/qiosfiledialog.h
index 0b56bd20bf..5cb1b45e20 100644
--- a/src/plugins/platforms/ios/qiosfiledialog.h
+++ b/src/plugins/platforms/ios/qiosfiledialog.h
@@ -53,17 +53,17 @@ public:
QIOSFileDialog();
~QIOSFileDialog();
- void exec() Q_DECL_OVERRIDE;
- bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return false; }
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
- void setDirectory(const QUrl &) Q_DECL_OVERRIDE {}
- QUrl directory() const Q_DECL_OVERRIDE { return QUrl(); }
- void selectFile(const QUrl &) Q_DECL_OVERRIDE {}
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- void setFilter() Q_DECL_OVERRIDE {}
- void selectNameFilter(const QString &) Q_DECL_OVERRIDE {}
- QString selectedNameFilter() const Q_DECL_OVERRIDE { return QString(); }
+ void exec() override;
+ bool defaultNameFilterDisables() const override { return false; }
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
+ void setDirectory(const QUrl &) override {}
+ QUrl directory() const override { return QUrl(); }
+ void selectFile(const QUrl &) override {}
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override {}
+ void selectNameFilter(const QString &) override {}
+ QString selectedNameFilter() const override { return QString(); }
void selectedFilesChanged(QList<QUrl> selection);
diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm
index c5722d33f8..5987bc1540 100644
--- a/src/plugins/platforms/ios/qiosfiledialog.mm
+++ b/src/plugins/platforms/ios/qiosfiledialog.mm
@@ -48,7 +48,7 @@
#include "qiosoptionalplugininterface.h"
QIOSFileDialog::QIOSFileDialog()
- : m_viewController(Q_NULLPTR)
+ : m_viewController(nullptr)
{
}
@@ -112,7 +112,7 @@ void QIOSFileDialog::hide()
[m_viewController dismissViewControllerAnimated:YES completion:nil];
[m_viewController release];
- m_viewController = Q_NULLPTR;
+ m_viewController = nullptr;
m_eventLoop.exit();
}
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 966d1a7e80..255cf8bca9 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -88,24 +88,24 @@ public:
QIOSInputContext();
~QIOSInputContext();
- bool isValid() const Q_DECL_OVERRIDE { return true; }
+ bool isValid() const override { return true; }
- void showInputPanel() Q_DECL_OVERRIDE;
- void hideInputPanel() Q_DECL_OVERRIDE;
+ void showInputPanel() override;
+ void hideInputPanel() override;
- bool isInputPanelVisible() const Q_DECL_OVERRIDE;
- bool isAnimating() const Q_DECL_OVERRIDE;
- QRectF keyboardRect() const Q_DECL_OVERRIDE;
+ bool isInputPanelVisible() const override;
+ bool isAnimating() const override;
+ QRectF keyboardRect() const override;
- void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
- void reset() Q_DECL_OVERRIDE;
- void commit() Q_DECL_OVERRIDE;
+ void update(Qt::InputMethodQueries) override;
+ void reset() override;
+ void commit() override;
- QLocale locale() const Q_DECL_OVERRIDE;
+ QLocale locale() const override;
void clearCurrentFocusObject();
- void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
+ void setFocusObject(QObject *object) override;
void focusWindowChanged(QWindow *focusWindow);
void scrollToCursor();
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 522cc032ff..6be8855020 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -62,45 +62,45 @@ public:
QIOSIntegration();
~QIOSIntegration();
- bool hasCapability(Capability cap) const Q_DECL_OVERRIDE;
+ bool hasCapability(Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const override;
#ifndef QT_NO_CLIPBOARD
- QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
+ QPlatformClipboard *clipboard() const override;
#endif
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const override;
+ QPlatformServices *services() const override;
- QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
+ QVariant styleHint(StyleHint hint) const override;
- QStringList themeNames() const Q_DECL_OVERRIDE;
- QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
+ QStringList themeNames() const override;
+ QPlatformTheme *createPlatformTheme(const QString &name) const override;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ QPlatformNativeInterface *nativeInterface() const override;
QTouchDevice *touchDevice();
#ifndef QT_NO_ACCESSIBILITY
- QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
+ QPlatformAccessibility *accessibility() const override;
#endif
// Called from Objective-C class QIOSScreenTracker, which can't be friended
void addScreen(QPlatformScreen *screen) { screenAdded(screen); }
void destroyScreen(QPlatformScreen *screen) { QPlatformIntegration::destroyScreen(screen); }
- void beep() const Q_DECL_OVERRIDE;
+ void beep() const override;
static QIOSIntegration *instance();
// -- QPlatformNativeInterface --
- void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
QFactoryLoader *optionalPlugins() { return m_optionalPlugins; }
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 94a30eb931..92c1e39d72 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -118,6 +118,9 @@ QIOSIntegration::QIOSIntegration()
}
m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
+#if QT_CONFIG(tabletevent)
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
+#endif
QMacInternalPasteboardMime::initializeMimeTypes();
for (int i = 0; i < m_optionalPlugins->metaData().size(); ++i)
@@ -196,12 +199,12 @@ class QIOSOffscreenSurface : public QPlatformOffscreenSurface
public:
QIOSOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {}
- QSurfaceFormat format() const Q_DECL_OVERRIDE
+ QSurfaceFormat format() const override
{
Q_ASSERT(offscreenSurface());
return offscreenSurface()->requestedFormat();
}
- bool isValid() const Q_DECL_OVERRIDE { return true; }
+ bool isValid() const override { return true; }
};
QPlatformOffscreenSurface *QIOSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
index 61cadab56d..32022a3bb8 100644
--- a/src/plugins/platforms/ios/qiosmenu.h
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -56,20 +56,20 @@ class QIOSMenuItem : public QPlatformMenuItem
public:
QIOSMenuItem();
- void setText(const QString &text) Q_DECL_OVERRIDE;
- void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
- void setMenu(QPlatformMenu *) Q_DECL_OVERRIDE;
- void setVisible(bool isVisible) Q_DECL_OVERRIDE;
- void setIsSeparator(bool) Q_DECL_OVERRIDE;
- void setFont(const QFont &) Q_DECL_OVERRIDE {}
- void setRole(MenuRole role) Q_DECL_OVERRIDE;
- void setCheckable(bool) Q_DECL_OVERRIDE {}
- void setChecked(bool) Q_DECL_OVERRIDE {}
+ void setText(const QString &text) override;
+ void setIcon(const QIcon &) override {}
+ void setMenu(QPlatformMenu *) override;
+ void setVisible(bool isVisible) override;
+ void setIsSeparator(bool) override;
+ void setFont(const QFont &) override {}
+ void setRole(MenuRole role) override;
+ void setCheckable(bool) override {}
+ void setChecked(bool) override {}
#ifndef QT_NO_SHORTCUT
- void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE;
+ void setShortcut(const QKeySequence&) override;
#endif
- void setEnabled(bool enabled) Q_DECL_OVERRIDE;
- void setIconSize(int) Q_DECL_OVERRIDE {}
+ void setEnabled(bool enabled) override;
+ void setIconSize(int) override {}
bool m_visible;
QString m_text;
@@ -88,22 +88,22 @@ public:
QIOSMenu();
~QIOSMenu();
- void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
- void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
- void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE;
- void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
+ void removeMenuItem(QPlatformMenuItem *menuItem) override;
+ void syncMenuItem(QPlatformMenuItem *) override;
+ void syncSeparatorsCollapsible(bool) override {}
- void setText(const QString &) Q_DECL_OVERRIDE;
- void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
- void setEnabled(bool enabled) Q_DECL_OVERRIDE;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void setMenuType(MenuType type) Q_DECL_OVERRIDE;
+ void setText(const QString &) override;
+ void setIcon(const QIcon &) override {}
+ void setEnabled(bool enabled) override;
+ void setVisible(bool visible) override;
+ void setMenuType(MenuType type) override;
- void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE;
- void dismiss() Q_DECL_OVERRIDE;
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override;
+ void dismiss() override;
- QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
- QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemAt(int position) const override;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
void handleItemSelected(QIOSMenuItem *menuItem);
@@ -111,7 +111,7 @@ public:
static id menuActionTarget() { return m_currentMenu ? m_currentMenu->m_menuController : 0; }
protected:
- bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
+ bool eventFilter(QObject *obj, QEvent *event) override;
private:
bool m_enabled;
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.h b/src/plugins/platforms/ios/qiosmessagedialog.h
index e67e10a5e1..92a4db8319 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.h
+++ b/src/plugins/platforms/ios/qiosmessagedialog.h
@@ -54,9 +54,9 @@ public:
QIOSMessageDialog();
~QIOSMessageDialog();
- void exec() Q_DECL_OVERRIDE;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ void exec() override;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
private:
QEventLoop m_eventLoop;
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 5507f13de7..9d05b792c2 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -48,7 +48,7 @@
#include "qiosmessagedialog.h"
QIOSMessageDialog::QIOSMessageDialog()
- : m_alertController(Q_NULLPTR)
+ : m_alertController(nullptr)
{
}
@@ -136,5 +136,5 @@ void QIOSMessageDialog::hide()
m_eventLoop.exit();
[m_alertController dismissViewControllerAnimated:YES completion:nil];
[m_alertController release];
- m_alertController = Q_NULLPTR;
+ m_alertController = nullptr;
}
diff --git a/src/plugins/platforms/ios/qiosoptionalplugininterface.h b/src/plugins/platforms/ios/qiosoptionalplugininterface.h
index 3f74e41c83..660c74e856 100644
--- a/src/plugins/platforms/ios/qiosoptionalplugininterface.h
+++ b/src/plugins/platforms/ios/qiosoptionalplugininterface.h
@@ -55,7 +55,7 @@ class QIosOptionalPluginInterface
public:
virtual ~QIosOptionalPluginInterface() {}
virtual void initPlugin() const {};
- virtual UIViewController* createImagePickerController(QIOSFileDialog *) const { return Q_NULLPTR; };
+ virtual UIViewController* createImagePickerController(QIOSFileDialog *) const { return nullptr; };
};
Q_DECLARE_INTERFACE(QIosOptionalPluginInterface, QIosOptionalPluginInterface_iid)
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index be0f301710..d5a253461d 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -62,18 +62,18 @@ public:
QString name() const override;
- QRect geometry() const Q_DECL_OVERRIDE;
- QRect availableGeometry() const Q_DECL_OVERRIDE;
- 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 devicePixelRatio() const Q_DECL_OVERRIDE;
+ QRect geometry() const override;
+ QRect availableGeometry() const override;
+ int depth() const override;
+ QImage::Format format() const override;
+ QSizeF physicalSize() const override;
+ QDpi logicalDpi() const override;
+ qreal devicePixelRatio() const override;
qreal refreshRate() const override;
- Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
- Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
- void setOrientationUpdateMask(Qt::ScreenOrientations mask) Q_DECL_OVERRIDE;
+ Qt::ScreenOrientation nativeOrientation() const override;
+ Qt::ScreenOrientation orientation() const override;
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask) override;
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index bb9fe4d58f..fe3c29d037 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -608,7 +608,7 @@ static void executeBlockWithoutAnimation(Block block)
- (QIOSLoupeLayer *)createLoupeLayer
{
Q_UNREACHABLE();
- return Q_NULLPTR;
+ return nullptr;
}
- (void)updateFocalPoint:(QPointF)touchPoint
@@ -984,12 +984,12 @@ static void executeBlockWithoutAnimation(Block block)
QT_BEGIN_NAMESPACE
-QIOSEditMenu *QIOSTextInputOverlay::s_editMenu = Q_NULLPTR;
+QIOSEditMenu *QIOSTextInputOverlay::s_editMenu = nullptr;
QIOSTextInputOverlay::QIOSTextInputOverlay()
- : m_cursorRecognizer(Q_NULLPTR)
- , m_selectionRecognizer(Q_NULLPTR)
- , m_openMenuOnTapRecognizer(Q_NULLPTR)
+ : m_cursorRecognizer(nullptr)
+ , m_selectionRecognizer(nullptr)
+ , m_openMenuOnTapRecognizer(nullptr)
{
connect(qApp, &QGuiApplication::focusObjectChanged, this, &QIOSTextInputOverlay::updateFocusObject);
}
@@ -1012,10 +1012,10 @@ void QIOSTextInputOverlay::updateFocusObject()
[m_selectionRecognizer release];
[m_openMenuOnTapRecognizer release];
[s_editMenu release];
- m_cursorRecognizer = Q_NULLPTR;
- m_selectionRecognizer = Q_NULLPTR;
- m_openMenuOnTapRecognizer = Q_NULLPTR;
- s_editMenu = Q_NULLPTR;
+ m_cursorRecognizer = nullptr;
+ m_selectionRecognizer = nullptr;
+ m_openMenuOnTapRecognizer = nullptr;
+ s_editMenu = nullptr;
}
if (platformInputContext()->inputMethodAccepted()) {
diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h
index fc6b58178a..c917679a91 100644
--- a/src/plugins/platforms/ios/qiostheme.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -52,16 +52,16 @@ public:
QIOSTheme();
~QIOSTheme();
- const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE;
- QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE;
+ const QPalette *palette(Palette type = SystemPalette) const override;
+ QVariant themeHint(ThemeHint hint) const override;
- QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE;
- QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE;
+ QPlatformMenuItem* createPlatformMenuItem() const override;
+ QPlatformMenu* createPlatformMenu() const override;
- bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
+ bool usePlatformNativeDialog(DialogType type) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
- const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE;
+ const QFont *font(Font type = SystemFont) const override;
static const char *name;
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 14fa2084c9..d5af31044d 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -60,37 +60,37 @@ public:
explicit QIOSWindow(QWindow *window);
~QIOSWindow();
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &rect) override;
- void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
- void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
- void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void setOpacity(qreal level) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates state) override;
+ void setParent(const QPlatformWindow *window) override;
+ void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
+ void setVisible(bool visible) override;
+ void setOpacity(qreal level) override;
- bool isExposed() const Q_DECL_OVERRIDE;
- void propagateSizeHints() Q_DECL_OVERRIDE {}
+ bool isExposed() const override;
+ void propagateSizeHints() override {}
QMargins safeAreaMargins() const override;
- void raise() Q_DECL_OVERRIDE{ raiseOrLower(true); }
- void lower() Q_DECL_OVERRIDE { raiseOrLower(false); }
+ void raise() override{ raiseOrLower(true); }
+ void lower() override { raiseOrLower(false); }
bool shouldAutoActivateWindow() const;
- void requestActivateWindow() Q_DECL_OVERRIDE;
+ void requestActivateWindow() override;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ qreal devicePixelRatio() const override;
- bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE { return grab; }
- bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE { return grab; }
+ bool setMouseGrabEnabled(bool grab) override { return grab; }
+ bool setKeyboardGrabEnabled(bool grab) override { return grab; }
- WId winId() const Q_DECL_OVERRIDE { return WId(m_view); }
+ WId winId() const override { return WId(m_view); }
void clearAccessibleCache();
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override;
- void requestUpdate() Q_DECL_OVERRIDE;
+ void requestUpdate() override;
CAEAGLLayer *eaglLayer() const;
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 1ce9007a35..3e3c579075 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -58,6 +58,7 @@ QT_END_NAMESPACE
QT_PREPEND_NAMESPACE(QIOSWindow) *m_qioswindow;
@private
QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ UITouch *m_activePencilTouch;
int m_nextTouchId;
@private
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 4c2184a1f6..6960698bf1 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -53,6 +53,8 @@
#include <QtGui/private/qwindow_p.h>
#include <qpa/qwindowsysteminterface_p.h>
+Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+
@implementation QUIView
+ (void)load
@@ -353,11 +355,44 @@
return [super pointInside:point withEvent:event];
}
-- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
+- (void)handleTouches:(NSSet *)touches withEvent:(UIEvent *)event withState:(Qt::TouchPointState)state withTimestamp:(ulong)timeStamp
{
+ QIOSIntegration *iosIntegration = QIOSIntegration::instance();
bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure;
- foreach (UITouch *uiTouch, m_activeTouches.keys()) {
+#if QT_CONFIG(tabletevent)
+ if (m_activePencilTouch && [touches containsObject:m_activePencilTouch]) {
+ NSArray<UITouch *> *cTouches = [event coalescedTouchesForTouch:m_activePencilTouch];
+ int i = 0;
+ for (UITouch *cTouch in cTouches) {
+ QPointF localViewPosition = QPointF::fromCGPoint([cTouch preciseLocationInView:self]);
+ QPoint localViewPositionI = localViewPosition.toPoint();
+ QPointF globalScreenPosition = m_qioswindow->mapToGlobal(localViewPositionI) +
+ (localViewPosition - localViewPositionI);
+ qreal pressure = cTouch.force / cTouch.maximumPossibleForce;
+ // azimuth unit vector: +x to the right, +y going downwards
+ CGVector azimuth = [cTouch azimuthUnitVectorInView: self];
+ // azimuthAngle given in radians, zero when the stylus points towards +x axis; converted to degrees with 0 pointing straight up
+ qreal azimuthAngle = [cTouch azimuthAngleInView: self] * 180 / M_PI + 90;
+ // altitudeAngle given in radians, pi / 2 is with the stylus perpendicular to the iPad, smaller values mean more tilted, but never negative.
+ // Convert to degrees with zero being perpendicular.
+ qreal altitudeAngle = 90 - cTouch.altitudeAngle * 180 / M_PI;
+ qCDebug(lcQpaTablet) << i << ":" << timeStamp << localViewPosition << pressure << state << "azimuth" << azimuth.dx << azimuth.dy
+ << "angle" << azimuthAngle << "altitude" << cTouch.altitudeAngle
+ << "xTilt" << qBound(-60.0, altitudeAngle * azimuth.dx, 60.0) << "yTilt" << qBound(-60.0, altitudeAngle * azimuth.dy, 60.0);
+ QWindowSystemInterface::handleTabletEvent(m_qioswindow->window(), timeStamp, localViewPosition, globalScreenPosition,
+ // device, pointerType, buttons
+ QTabletEvent::RotationStylus, QTabletEvent::Pen, state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton,
+ // pressure, xTilt, yTilt
+ pressure, qBound(-60.0, altitudeAngle * azimuth.dx, 60.0), qBound(-60.0, altitudeAngle * azimuth.dy, 60.0),
+ // tangentialPressure, rotation, z, uid, modifiers
+ 0, azimuthAngle, 0, 0, Qt::NoModifier);
+ ++i;
+ }
+ }
+#endif
+
+ for (UITouch *uiTouch : m_activeTouches.keys()) {
QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
if (![touches containsObject:uiTouch]) {
touchPoint.state = Qt::TouchPointStationary;
@@ -386,16 +421,14 @@
touchPoint.pressure = uiTouch.force / uiTouch.maximumPossibleForce;
} else {
// We don't claim that our touch device supports QTouchDevice::Pressure,
- // but fill in a meaningfull value in case clients use it anyways.
+ // but fill in a meaningful value in case clients use it anyway.
touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
}
}
}
-}
-
-- (void)sendTouchEventWithTimestamp:(ulong)timeStamp
-{
- QIOSIntegration *iosIntegration = QIOSIntegration::instance();
+ if (m_activeTouches.isEmpty())
+ return;
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
if (!static_cast<QUIWindow *>(self.window).sendingEvent) {
// The event is likely delivered as part of delayed touch delivery, via
// _UIGestureEnvironmentSortAndSendDelayedTouches, due to one of the two
@@ -420,8 +453,21 @@
// points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
// an id for use by Qt.
for (UITouch *touch in touches) {
- Q_ASSERT(!m_activeTouches.contains(touch));
- m_activeTouches[touch].id = m_nextTouchId++;
+#if QT_CONFIG(tabletevent)
+ if (touch.type == UITouchTypeStylus) {
+ if (Q_UNLIKELY(m_activePencilTouch)) {
+ qWarning("ignoring additional Pencil while first is still active");
+ continue;
+ }
+ m_activePencilTouch = touch;
+ } else
+ {
+ Q_ASSERT(!m_activeTouches.contains(touch));
+#endif
+ m_activeTouches[touch].id = m_nextTouchId++;
+#if QT_CONFIG(tabletevent)
+ }
+#endif
}
if (m_qioswindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) {
@@ -432,31 +478,36 @@
topLevel->requestActivateWindow();
}
- [self updateTouchList:touches withState:Qt::TouchPointPressed];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:Qt::TouchPointPressed withTimestamp:ulong(event.timestamp * 1000)];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
- [self updateTouchList:touches withState:Qt::TouchPointMoved];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:Qt::TouchPointMoved withTimestamp:ulong(event.timestamp * 1000)];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
- [self updateTouchList:touches withState:Qt::TouchPointReleased];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+ [self handleTouches:touches withEvent:event withState:Qt::TouchPointReleased withTimestamp:ulong(event.timestamp * 1000)];
// Remove ended touch points from the active set:
- for (UITouch *touch in touches)
- m_activeTouches.remove(touch);
- if (m_activeTouches.isEmpty())
+ for (UITouch *touch in touches) {
+#if QT_CONFIG(tabletevent)
+ if (touch.type == UITouchTypeStylus) {
+ m_activePencilTouch = nil;
+ } else
+#endif
+ {
+ m_activeTouches.remove(touch);
+ }
+ }
+ if (m_activeTouches.isEmpty() && !m_activePencilTouch)
m_nextTouchId = 0;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
- if (m_activeTouches.isEmpty())
+ if (m_activeTouches.isEmpty() && !m_activePencilTouch)
return;
// When four-finger swiping, we get a touchesCancelled callback
@@ -480,11 +531,12 @@
// sub-set of the active touch events are intentionally cancelled.
NSInteger count = static_cast<NSInteger>([touches count]);
- if (count != 0 && count != m_activeTouches.count())
+ if (count != 0 && count != m_activeTouches.count() && !m_activePencilTouch)
qWarning("Subset of active touches cancelled by UIKit");
m_activeTouches.clear();
m_nextTouchId = 0;
+ m_activePencilTouch = nil;
NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp
index 82b916b9a9..24156b68e8 100644
--- a/src/plugins/platforms/linuxfb/main.cpp
+++ b/src/plugins/platforms/linuxfb/main.cpp
@@ -47,7 +47,7 @@ class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "linuxfb.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration* QLinuxFbIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
index e15d6fee24..dcc1ef2790 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
@@ -43,7 +43,6 @@
// Multiscreen: QWindow-QScreen(-output) association. Needs some reorg (device cannot be owned by screen)
// Find card via devicediscovery like in eglfs_kms.
// Mode restore like QEglFSKmsInterruptHandler.
-// Formats other then 32 bpp?
// grabWindow
#include "qlinuxfbdrmscreen.h"
@@ -187,15 +186,67 @@ void QLinuxFbDevice::registerScreen(QPlatformScreen *screen,
Q_UNREACHABLE();
}
+static uint32_t bppForDrmFormat(uint32_t drmFormat)
+{
+ switch (drmFormat) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ return 16;
+ default:
+ return 32;
+ }
+}
+
+static int depthForDrmFormat(uint32_t drmFormat)
+{
+ switch (drmFormat) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ return 16;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ return 24;
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XBGR2101010:
+ return 30;
+ default:
+ return 32;
+ }
+}
+
+static QImage::Format formatForDrmFormat(uint32_t drmFormat)
+{
+ switch (drmFormat) {
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ return QImage::Format_RGB32;
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ return QImage::Format_ARGB32;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ return QImage::Format_RGB16;
+ case DRM_FORMAT_XRGB2101010:
+ case DRM_FORMAT_XBGR2101010:
+ return QImage::Format_RGB30;
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_ABGR2101010:
+ return QImage::Format_A2RGB30_Premultiplied;
+ default:
+ return QImage::Format_ARGB32;
+ }
+}
+
bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int bufferIdx)
{
const QSize size = output->currentRes();
const uint32_t w = size.width();
const uint32_t h = size.height();
+ const uint32_t bpp = bppForDrmFormat(output->kmsOutput.drm_format);
drm_mode_create_dumb creq = {
h,
w,
- 32,
+ bpp,
0, 0, 0, 0
};
if (drmIoctl(fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq) == -1) {
@@ -207,10 +258,15 @@ bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int buffe
fb.handle = creq.handle;
fb.pitch = creq.pitch;
fb.size = creq.size;
- qCDebug(qLcFbDrm, "Got a dumb buffer for size %dx%d, handle %u, pitch %u, size %u",
- w, h, fb.handle, fb.pitch, (uint) fb.size);
+ qCDebug(qLcFbDrm, "Got a dumb buffer for size %dx%d and bpp %u: handle %u, pitch %u, size %u",
+ w, h, bpp, fb.handle, fb.pitch, (uint) fb.size);
+
+ uint32_t handles[4] = { fb.handle };
+ uint32_t strides[4] = { fb.pitch };
+ uint32_t offsets[4] = { 0 };
- if (drmModeAddFB(fd(), w, h, 24, 32, fb.pitch, fb.handle, &fb.fb) == -1) {
+ if (drmModeAddFB2(fd(), w, h, output->kmsOutput.drm_format,
+ handles, strides, offsets, &fb.fb, 0) == -1) {
qErrnoWarning(errno, "Failed to add FB");
return false;
}
@@ -229,10 +285,10 @@ bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int buffe
return false;
}
- qCDebug(qLcFbDrm, "FB is %u, mapped at %p", fb.fb, fb.p);
+ qCDebug(qLcFbDrm, "FB is %u (DRM format 0x%x), mapped at %p", fb.fb, output->kmsOutput.drm_format, fb.p);
memset(fb.p, 0, fb.size);
- fb.wrapper = QImage(static_cast<uchar *>(fb.p), w, h, fb.pitch, QImage::Format_ARGB32);
+ fb.wrapper = QImage(static_cast<uchar *>(fb.p), w, h, fb.pitch, formatForDrmFormat(output->kmsOutput.drm_format));
return true;
}
@@ -357,10 +413,10 @@ bool QLinuxFbDrmScreen::initialize()
QLinuxFbDevice::Output *output(m_device->output(0));
mGeometry = QRect(QPoint(0, 0), output->currentRes());
- mDepth = 32;
- mFormat = QImage::Format_ARGB32;
+ mDepth = depthForDrmFormat(output->kmsOutput.drm_format);
+ mFormat = formatForDrmFormat(output->kmsOutput.drm_format);
mPhysicalSize = output->kmsOutput.physical_size;
- qCDebug(qLcFbDrm) << mGeometry << mPhysicalSize;
+ qCDebug(qLcFbDrm) << mGeometry << mPhysicalSize << mDepth << mFormat;
QFbScreen::initializeCompositor();
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
index 9934a8cd54..22578bf980 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
@@ -55,19 +55,19 @@ public:
QLinuxFbIntegration(const QStringList &paramList);
~QLinuxFbIntegration();
- void initialize() Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ void initialize() override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; }
+ QPlatformFontDatabase *fontDatabase() const override;
+ QPlatformServices *services() const override;
+ QPlatformInputContext *inputContext() const override { return m_inputContext; }
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QPlatformNativeInterface *nativeInterface() const override;
QList<QPlatformScreen *> screens() const;
diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp
index 29809c1843..f9a0c17509 100644
--- a/src/plugins/platforms/minimal/main.cpp
+++ b/src/plugins/platforms/minimal/main.cpp
@@ -48,7 +48,7 @@ class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimal.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration *QMinimalIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro
index 8cfb68824e..a1a2da547b 100644
--- a/src/plugins/platforms/minimal/minimal.pro
+++ b/src/plugins/platforms/minimal/minimal.pro
@@ -14,6 +14,8 @@ HEADERS = qminimalintegration.h \
OTHER_FILES += minimal.json
+qtConfig(freetype): QMAKE_USE_PRIVATE += freetype
+
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
diff --git a/src/plugins/platforms/minimal/qminimalbackingstore.h b/src/plugins/platforms/minimal/qminimalbackingstore.h
index 3d7aaf2b99..2119894809 100644
--- a/src/plugins/platforms/minimal/qminimalbackingstore.h
+++ b/src/plugins/platforms/minimal/qminimalbackingstore.h
@@ -52,9 +52,9 @@ public:
QMinimalBackingStore(QWindow *window);
~QMinimalBackingStore();
- QPaintDevice *paintDevice() 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;
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
private:
QImage mImage;
diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp
index ca33689cd7..0c04608fca 100644
--- a/src/plugins/platforms/minimal/qminimalintegration.cpp
+++ b/src/plugins/platforms/minimal/qminimalintegration.cpp
@@ -54,11 +54,17 @@
# endif
#elif defined(Q_OS_DARWIN)
# include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
-#elif QT_CONFIG(fontconfig)
+#endif
+
+#if QT_CONFIG(fontconfig)
# include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
# include <qpa/qplatformfontdatabase.h>
#endif
+#if QT_CONFIG(freetype)
+#include <QtFontDatabaseSupport/private/qfontengine_ft_p.h>
+#endif
+
#if !defined(Q_OS_WIN)
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#elif defined(Q_OS_WINRT)
@@ -81,6 +87,8 @@ static inline unsigned parseOptions(const QStringList &paramList)
options |= QMinimalIntegration::EnableFonts;
else if (param == QLatin1String("freetype"))
options |= QMinimalIntegration::FreeTypeFontDatabase;
+ else if (param == QLatin1String("fontconfig"))
+ options |= QMinimalIntegration::FontconfigDatabase;
}
return options;
}
@@ -123,15 +131,13 @@ bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) co
class DummyFontDatabase : public QPlatformFontDatabase
{
public:
- virtual void populateFontDatabase() Q_DECL_OVERRIDE {}
+ virtual void populateFontDatabase() override {}
};
QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const
{
if (!m_fontDatabase && (m_options & EnableFonts)) {
-#if QT_CONFIG(fontconfig)
- m_fontDatabase = new QGenericUnixFontDatabase;
-#elif defined(Q_OS_WINRT)
+#if defined(Q_OS_WINRT)
m_fontDatabase = new QWinRTFontDatabase;
#elif defined(Q_OS_WIN)
if (m_options & FreeTypeFontDatabase) {
@@ -142,10 +148,24 @@ QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const
m_fontDatabase = new QWindowsFontDatabase;
}
#elif defined(Q_OS_DARWIN)
- m_fontDatabase = new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
+ if (!(m_options & FontconfigDatabase)) {
+ if (m_options & FreeTypeFontDatabase) {
+# if QT_CONFIG(freetype)
+ m_fontDatabase = new QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
+# endif // freetype
+ } else {
+ m_fontDatabase = new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
+ }
+ }
+#endif
+
+ if (!m_fontDatabase) {
+#if QT_CONFIG(fontconfig)
+ m_fontDatabase = new QGenericUnixFontDatabase;
#else
- m_fontDatabase = QPlatformIntegration::fontDatabase();
+ m_fontDatabase = QPlatformIntegration::fontDatabase();
#endif
+ }
}
if (!m_fontDatabase)
m_fontDatabase = new DummyFontDatabase;
diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h
index eaa2f228c5..ad1bec2112 100644
--- a/src/plugins/platforms/minimal/qminimalintegration.h
+++ b/src/plugins/platforms/minimal/qminimalintegration.h
@@ -51,9 +51,9 @@ public:
QMinimalScreen()
: mDepth(32), mFormat(QImage::Format_ARGB32_Premultiplied) {}
- QRect geometry() const Q_DECL_OVERRIDE { return mGeometry; }
- int depth() const Q_DECL_OVERRIDE { return mDepth; }
- QImage::Format format() const Q_DECL_OVERRIDE { return mFormat; }
+ QRect geometry() const override { return mGeometry; }
+ int depth() const override { return mDepth; }
+ QImage::Format format() const override { return mFormat; }
public:
QRect mGeometry;
@@ -68,18 +68,19 @@ public:
enum Options { // Options to be passed on command line or determined from environment
DebugBackingStore = 0x1,
EnableFonts = 0x2,
- FreeTypeFontDatabase = 0x4
+ FreeTypeFontDatabase = 0x4,
+ FontconfigDatabase = 0x8
};
explicit QMinimalIntegration(const QStringList &parameters);
~QMinimalIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QPlatformFontDatabase *fontDatabase() const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
unsigned options() const { return m_options; }
diff --git a/src/plugins/platforms/minimalegl/main.cpp b/src/plugins/platforms/minimalegl/main.cpp
index a010ed76e2..5aac71e140 100644
--- a/src/plugins/platforms/minimalegl/main.cpp
+++ b/src/plugins/platforms/minimalegl/main.cpp
@@ -47,7 +47,7 @@ class QMinimalEglIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimalegl.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration* QMinimalEglIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h
index 0e22298891..382f2d1404 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h
@@ -53,13 +53,13 @@ public:
QMinimalEglBackingStore(QWindow *window);
~QMinimalEglBackingStore();
- QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ QPaintDevice *paintDevice() override;
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
- void endPaint() Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &) override;
+ void endPaint() 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;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
private:
QOpenGLContext *m_context;
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
index a716a6092a..5d31af53d5 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
@@ -71,7 +71,7 @@ public:
QWinRTEventDispatcher() {}
protected:
- bool hasPendingEvents() Q_DECL_OVERRIDE
+ bool hasPendingEvents() override
{
return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued();
}
@@ -156,7 +156,7 @@ QAbstractEventDispatcher *QMinimalEglIntegration::createEventDispatcher() const
#elif defined(Q_OS_WIN)
return new QWindowsGuiEventDispatcher;
#else
- return Q_NULLPTR;
+ return nullptr;
#endif
}
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.h b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
index d0ab75bd3c..70a51004a6 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
@@ -51,18 +51,18 @@ public:
QMinimalEglIntegration();
~QMinimalEglIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
#ifndef QT_NO_OPENGL
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const override;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
- QVariant styleHint(QPlatformIntegration::StyleHint hint) const Q_DECL_OVERRIDE;
+ QVariant styleHint(QPlatformIntegration::StyleHint hint) const override;
private:
QPlatformFontDatabase *mFontDb;
diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
index 0175d2dbdd..6e122e28ce 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
@@ -64,7 +64,7 @@ public:
{
}
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE
+ EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override
{
QMinimalEglWindow *window = static_cast<QMinimalEglWindow *>(surface);
QMinimalEglScreen *screen = static_cast<QMinimalEglScreen *>(window->screen());
diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.h b/src/plugins/platforms/minimalegl/qminimaleglscreen.h
index 24098b8127..926936ae32 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglscreen.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.h
@@ -56,9 +56,9 @@ public:
QMinimalEglScreen(EGLNativeDisplayType display);
~QMinimalEglScreen();
- QRect geometry() const Q_DECL_OVERRIDE;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
+ QRect geometry() const override;
+ int depth() const override;
+ QImage::Format format() const override;
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *platformContext() const;
#endif
diff --git a/src/plugins/platforms/minimalegl/qminimaleglwindow.h b/src/plugins/platforms/minimalegl/qminimaleglwindow.h
index b8bfd6c8d2..098ec05e6b 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglwindow.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglwindow.h
@@ -51,8 +51,8 @@ class QMinimalEglWindow : public QPlatformWindow
public:
QMinimalEglWindow(QWindow *w);
- void setGeometry(const QRect &) Q_DECL_OVERRIDE;
- WId winId() const Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &) override;
+ WId winId() const override;
private:
WId m_winid;
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp
index ea13f3cc17..e5319b0435 100644
--- a/src/plugins/platforms/mirclient/qmirclientinput.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp
@@ -156,6 +156,36 @@ static const uint32_t KeyTable[] = {
XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot,
XKB_KEY_dead_hook, Qt::Key_Dead_Hook,
XKB_KEY_dead_horn, Qt::Key_Dead_Horn,
+ XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke,
+ XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma,
+ XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
+ XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave,
+ XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring,
+ XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron,
+ XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
+ XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde,
+ XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve,
+ XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
+ XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
+ XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma,
+ XKB_KEY_dead_currency, Qt::Key_Dead_Currency,
+ XKB_KEY_dead_a, Qt::Key_Dead_a,
+ XKB_KEY_dead_A, Qt::Key_Dead_A,
+ XKB_KEY_dead_e, Qt::Key_Dead_e,
+ XKB_KEY_dead_E, Qt::Key_Dead_E,
+ XKB_KEY_dead_i, Qt::Key_Dead_i,
+ XKB_KEY_dead_I, Qt::Key_Dead_I,
+ XKB_KEY_dead_o, Qt::Key_Dead_o,
+ XKB_KEY_dead_O, Qt::Key_Dead_O,
+ XKB_KEY_dead_u, Qt::Key_Dead_u,
+ XKB_KEY_dead_U, Qt::Key_Dead_U,
+ XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
+ XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
+ XKB_KEY_dead_greek, Qt::Key_Dead_Greek,
+ XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline,
+ XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
+ XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
+ XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
XKB_KEY_script_switch, Qt::Key_Mode_switch,
diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp
index 9750c4f7ca..207db60f3a 100644
--- a/src/plugins/platforms/offscreen/main.cpp
+++ b/src/plugins/platforms/offscreen/main.cpp
@@ -48,7 +48,7 @@ class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "offscreen.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp
index 85422071aa..f0eb69718a 100644
--- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp
@@ -55,8 +55,8 @@ class QOffscreenCursor : public QPlatformCursor
public:
QOffscreenCursor() : m_pos(10, 10) {}
- QPoint pos() const Q_DECL_OVERRIDE { return m_pos; }
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE
+ QPoint pos() const override { return m_pos; }
+ void setPos(const QPoint &pos) override
{
m_pos = pos;
const QWindowList wl = QGuiApplication::topLevelWindows();
@@ -82,7 +82,7 @@ public:
QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0;
}
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE
+ void changeCursor(QCursor *windowCursor, QWindow *window) override
{
Q_UNUSED(windowCursor);
Q_UNUSED(window);
diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h
index 1a9d65972d..541c07384c 100644
--- a/src/plugins/platforms/offscreen/qoffscreencommon.h
+++ b/src/plugins/platforms/offscreen/qoffscreencommon.h
@@ -57,12 +57,12 @@ class QOffscreenScreen : public QPlatformScreen
public:
QOffscreenScreen();
- QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; }
- int depth() const Q_DECL_OVERRIDE { return 32; }
- QImage::Format format() const Q_DECL_OVERRIDE { return QImage::Format_RGB32; }
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor.data(); }
+ QRect geometry() const override { return m_geometry; }
+ int depth() const override { return 32; }
+ QImage::Format format() const override { return QImage::Format_RGB32; }
+ QPlatformCursor *cursor() const override { return m_cursor.data(); }
- QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
static QPlatformWindow *windowContainingCursor;
@@ -75,7 +75,7 @@ public:
class QOffscreenDrag : public QPlatformDrag
{
public:
- Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE { return Qt::IgnoreAction; }
+ Qt::DropAction drag(QDrag *) override { return Qt::IgnoreAction; }
};
#endif
@@ -85,10 +85,10 @@ public:
QOffscreenBackingStore(QWindow *window);
~QOffscreenBackingStore();
- QPaintDevice *paintDevice() 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;
- bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
+ bool scroll(const QRegion &area, int dx, int dy) override;
QPixmap grabWindow(WId window, const QRect &rect) const;
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h
index f72587d11a..c84c1f7c50 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.h
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -54,20 +54,20 @@ public:
QOffscreenIntegration();
~QOffscreenIntegration();
- void initialize() Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ void initialize() override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
#ifndef QT_NO_DRAGANDDROP
- QPlatformDrag *drag() const Q_DECL_OVERRIDE;
+ QPlatformDrag *drag() const override;
#endif
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const override;
+ QPlatformServices *services() const override;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
index aaca74d2fb..5e1c6b799b 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h
@@ -55,9 +55,9 @@ class QOffscreenX11Info;
class QOffscreenX11Integration : public QOffscreenIntegration
{
public:
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
private:
mutable QScopedPointer<QOffscreenX11Connection> m_connection;
@@ -88,14 +88,14 @@ public:
QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context);
~QOffscreenX11GLXContext();
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+ void swapBuffers(QPlatformSurface *surface) override;
+ QFunctionPointer getProcAddress(const char *procName) override;
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
- bool isSharing() const Q_DECL_OVERRIDE;
- bool isValid() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override;
+ bool isSharing() const override;
+ bool isValid() const override;
private:
QScopedPointer<QOffscreenX11GLXContextData> d;
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h
index 0dced9680a..e1f37bb034 100644
--- a/src/plugins/platforms/offscreen/qoffscreenwindow.h
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h
@@ -53,15 +53,15 @@ public:
QOffscreenWindow(QWindow *window);
~QOffscreenWindow();
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowStates states) Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &rect) override;
+ void setWindowState(Qt::WindowStates states) override;
- QMargins frameMargins() const Q_DECL_OVERRIDE;
+ QMargins frameMargins() const override;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void requestActivateWindow() Q_DECL_OVERRIDE;
+ void setVisible(bool visible) override;
+ void requestActivateWindow() override;
- WId winId() const Q_DECL_OVERRIDE;
+ WId winId() const override;
static QOffscreenWindow *windowForWinId(WId id);
diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
index a758bdf7f4..dd7f907ee0 100644
--- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
+++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp
@@ -139,6 +139,7 @@ void QQnxRasterBackingStore::beginPaint(const QRegion &region)
platformWindow()->adjustBufferSize();
if (window()->requestedFormat().alphaBufferSize() > 0) {
+ auto platformScreen = static_cast<QQnxScreen *>(platformWindow()->screen());
for (const QRect &r : region) {
// Clear transparent regions
const int bg[] = {
@@ -149,11 +150,11 @@ void QQnxRasterBackingStore::beginPaint(const QRegion &region)
SCREEN_BLIT_DESTINATION_HEIGHT, r.height(),
SCREEN_BLIT_END
};
- Q_SCREEN_CHECKERROR(screen_fill(platformWindow()->screen()->nativeContext(),
+ Q_SCREEN_CHECKERROR(screen_fill(platformScreen->nativeContext(),
platformWindow()->renderBuffer().nativeBuffer(), bg),
"failed to clear transparent regions");
}
- Q_SCREEN_CHECKERROR(screen_flush_blits(platformWindow()->screen()->nativeContext(),
+ Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(),
SCREEN_WAIT_IDLE), "failed to flush blits");
}
}
diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
index 7f11de228e..dc844189d1 100644
--- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
@@ -141,6 +141,7 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer()
// Check if render buffer is invalid
if (m_currentBufferIndex == -1) {
+ auto platformScreen = static_cast<QQnxScreen *>(screen());
// Get all buffers available for rendering
screen_buffer_t buffers[MAX_BUFFER_COUNT];
const int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS,
@@ -153,11 +154,11 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer()
// Clear Buffer
int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
- Q_SCREEN_CHECKERROR(screen_fill(screen()->nativeContext(), buffers[i], bg),
+ Q_SCREEN_CHECKERROR(screen_fill(platformScreen->nativeContext(), buffers[i], bg),
"Failed to clear window buffer");
}
- Q_SCREEN_CHECKERROR(screen_flush_blits(screen()->nativeContext(), 0),
+ Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), 0),
"Failed to flush blits");
// Use the first available render buffer
@@ -185,7 +186,7 @@ void QQnxRasterWindow::adjustBufferSize()
int QQnxRasterWindow::pixelFormat() const
{
- return screen()->nativeFormat();
+ return static_cast<QQnxScreen *>(screen())->nativeFormat();
}
void QQnxRasterWindow::resetBuffers()
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 2253e3b23d..38b61fd782 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -479,7 +479,7 @@ void QQnxWindow::setParent(const QPlatformWindow *window)
if (newParent == m_parentWindow)
return;
- if (screen()->rootWindow() == this) {
+ if (static_cast<QQnxScreen *>(screen())->rootWindow() == this) {
qWarning("Application window cannot be reparented");
return;
}
@@ -539,7 +539,7 @@ void QQnxWindow::requestActivateWindow()
if (focusWindow == this)
return;
- if (screen()->rootWindow() == this ||
+ if (static_cast<QQnxScreen *>(screen())->rootWindow() == this ||
(focusWindow && findWindow(focusWindow->nativeHandle()))) {
// If the focus window is a child, we can just set the focus of our own window
// group to our window handle
@@ -550,6 +550,7 @@ void QQnxWindow::requestActivateWindow()
QQnxWindow *currentWindow = this;
QList<QQnxWindow*> windowList;
while (currentWindow) {
+ auto platformScreen = static_cast<QQnxScreen *>(screen());
windowList.prepend(currentWindow);
// If we find the focus window, we don't have to go further
if (currentWindow == focusWindow)
@@ -557,9 +558,9 @@ void QQnxWindow::requestActivateWindow()
if (currentWindow->parent()){
currentWindow = static_cast<QQnxWindow*>(currentWindow->parent());
- } else if (screen()->rootWindow() &&
- screen()->rootWindow()->m_windowGroupName == currentWindow->m_parentGroupName) {
- currentWindow = screen()->rootWindow();
+ } else if (platformScreen->rootWindow() &&
+ platformScreen->rootWindow()->m_windowGroupName == currentWindow->m_parentGroupName) {
+ currentWindow = platformScreen->rootWindow();
} else {
currentWindow = 0;
}
@@ -622,6 +623,11 @@ void QQnxWindow::clearMMRendererWindow()
m_mmRendererWindow = 0;
}
+QPlatformScreen *QQnxWindow::screen() const
+{
+ return m_screen;
+}
+
QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle)
{
if (m_window == windowHandle)
@@ -775,7 +781,8 @@ void QQnxWindow::windowPosted()
bool QQnxWindow::shouldMakeFullScreen() const
{
- return ((screen()->rootWindow() == this) && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication));
+ return ((static_cast<QQnxScreen *>(screen())->rootWindow() == this)
+ && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication));
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index f96edc49e4..dfcca78f80 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -94,7 +94,7 @@ public:
void setMMRendererWindow(screen_window_t handle);
void clearMMRendererWindow();
- QQnxScreen *screen() const { return m_screen; }
+ QPlatformScreen *screen() const override;
const QList<QQnxWindow*>& children() const { return m_childWindows; }
QQnxWindow *findWindow(screen_window_t windowHandle);
diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp
index fa65e8c9a4..44fc1c6101 100644
--- a/src/plugins/platforms/vnc/qvnc.cpp
+++ b/src/plugins/platforms/vnc/qvnc.cpp
@@ -476,7 +476,8 @@ void QRfbRawEncoder::write()
// rgn &= QRect(0, 0, server->screen()->geometry().width(),
// server->screen()->geometry().height());
// }
- const QVector<QRect> rects = rgn.rects();
+
+ const auto rectsInRegion = rgn.rectCount();
{
const char tmp[2] = { 0, 0 }; // msg type, padding
@@ -484,16 +485,16 @@ void QRfbRawEncoder::write()
}
{
- const quint16 count = htons(rects.size());
+ const quint16 count = htons(rectsInRegion);
socket->write((char *)&count, sizeof(count));
}
- if (rects.size() <= 0)
+ if (rectsInRegion <= 0)
return;
const QImage screenImage = client->server()->screenImage();
- for (const QRect &tileRect: rects) {
+ for (const QRect &tileRect: rgn) {
const QRfbRect rect(tileRect.x(), tileRect.y(),
tileRect.width(), tileRect.height());
rect.write(socket);
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri
deleted file mode 100644
index 557bdfe307..0000000000
--- a/src/plugins/platforms/windows/accessible/accessible.pri
+++ /dev/null
@@ -1,19 +0,0 @@
-SOURCES += \
- $$PWD/qwindowsaccessibility.cpp \
- $$PWD/comutils.cpp
-
-HEADERS += \
- $$PWD/qwindowsaccessibility.h \
- $$PWD/comutils.h
-
-SOURCES += \
- $$PWD/qwindowsmsaaaccessible.cpp \
- $$PWD/iaccessible2.cpp
-
-HEADERS += \
- $$PWD/qwindowsmsaaaccessible.h \
- $$PWD/iaccessible2.h
-
-include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
-
-mingw: LIBS *= -luuid
diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp
deleted file mode 100644
index 1c072c5e2c..0000000000
--- a/src/plugins/platforms/windows/accessible/comutils.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qt_windows.h>
-
-#include <ocidl.h>
-#include <olectl.h>
-
-#include "comutils.h"
-#include <QtCore/qdatetime.h>
-#include <QtGui/qpixmap.h>
-#include <QtGui/qfont.h>
-
-
-#include <QtCore/qvariant.h>
-#include <QtCore/qbytearray.h>
-#include <QtGui/qcolor.h>
-
-QT_BEGIN_NAMESPACE
-
-static DATE QDateTimeToDATE(const QDateTime &dt)
-{
- if (!dt.isValid() || dt.isNull())
- return 949998; // Special value for no date (01/01/4501)
-
- SYSTEMTIME stime;
- memset(&stime, 0, sizeof(stime));
- QDate date = dt.date();
- QTime time = dt.time();
- if (date.isValid() && !date.isNull()) {
- stime.wDay = WORD(date.day());
- stime.wMonth = WORD(date.month());
- stime.wYear = WORD(date.year());
- }
- if (time.isValid() && !time.isNull()) {
- stime.wMilliseconds = WORD(time.msec());
- stime.wSecond = WORD(time.second());
- stime.wMinute = WORD(time.minute());
- stime.wHour = WORD(time.hour());
- }
-
- double vtime;
- SystemTimeToVariantTime(&stime, &vtime);
-
- return vtime;
-}
-
-inline uint QColorToOLEColor(const QColor &col)
-{
- return qRgba(col.blue(), col.green(), col.red(), 0x00);
-}
-
-bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out)
-{
- QVariant qvar = var;
- // "type" is the expected type, so coerce if necessary
- QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName);
- if (proptype == QVariant::UserType && !typeName.isEmpty()) {
- if (typeName == "short" || typeName == "char")
- proptype = QVariant::Int;
- else if (typeName == "float")
- proptype = QVariant::Double;
- }
- if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) {
- if (qvar.canConvert(int(proptype)))
- qvar.convert(int(proptype));
- else
- qvar = QVariant(proptype);
- }
-
- if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) {
- return QVariant2VARIANT(var, *arg.pvarVal, typeName, false);
- }
-
- if (out && proptype == QVariant::UserType && typeName == "QVariant") {
- VARIANT *pVariant = new VARIANT;
- QVariant2VARIANT(var, *pVariant, QByteArray(), false);
- arg.vt = VT_VARIANT|VT_BYREF;
- arg.pvarVal = pVariant;
- return true;
- }
-
- switch ((int)qvar.type()) {
- case QVariant::String:
- if (out && arg.vt == (VT_BSTR|VT_BYREF)) {
- if (*arg.pbstrVal)
- SysFreeString(*arg.pbstrVal);
- *arg.pbstrVal = QStringToBSTR(qvar.toString());
- arg.vt = VT_BSTR|VT_BYREF;
- } else {
- arg.vt = VT_BSTR;
- arg.bstrVal = QStringToBSTR(qvar.toString());
- if (out) {
- arg.pbstrVal = new BSTR(arg.bstrVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::Int:
- if (out && arg.vt == (VT_I4|VT_BYREF)) {
- *arg.plVal = qvar.toInt();
- } else {
- arg.vt = VT_I4;
- arg.lVal = qvar.toInt();
- if (out) {
- if (typeName == "short") {
- arg.vt = VT_I2;
- arg.piVal = new short(arg.lVal);
- } else if (typeName == "char") {
- arg.vt = VT_I1;
- arg.pcVal= new char(arg.lVal);
- } else {
- arg.plVal = new long(arg.lVal);
- }
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::UInt:
- if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) {
- *arg.puintVal = qvar.toUInt();
- } else {
- arg.vt = VT_UINT;
- arg.uintVal = qvar.toUInt();
- if (out) {
- arg.puintVal = new uint(arg.uintVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::LongLong:
- if (out && arg.vt == (VT_CY|VT_BYREF)) {
- arg.pcyVal->int64 = qvar.toLongLong();
- } else if (out && arg.vt == (VT_I8|VT_BYREF)) {
- *arg.pllVal = qvar.toLongLong();
- } else {
- arg.vt = VT_I8;
- arg.llVal = qvar.toLongLong();
- if (out) {
- arg.pllVal = new LONGLONG(arg.llVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::ULongLong:
- if (out && arg.vt == (VT_CY|VT_BYREF)) {
- arg.pcyVal->int64 = qvar.toULongLong();
- } else if (out && arg.vt == (VT_UI8|VT_BYREF)) {
- *arg.pullVal = qvar.toULongLong();
- } else {
- arg.vt = VT_UI8;
- arg.ullVal = qvar.toULongLong();
- if (out) {
- arg.pullVal = new ULONGLONG(arg.ullVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::Bool:
- if (out && arg.vt == (VT_BOOL|VT_BYREF)) {
- *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
- } else {
- arg.vt = VT_BOOL;
- arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
- if (out) {
- arg.pboolVal = new short(arg.boolVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
- case QVariant::Double:
- if (out && arg.vt == (VT_R8|VT_BYREF)) {
- *arg.pdblVal = qvar.toDouble();
- } else {
- arg.vt = VT_R8;
- arg.dblVal = qvar.toDouble();
- if (out) {
- if (typeName == "float") {
- arg.vt = VT_R4;
- arg.pfltVal = new float(arg.dblVal);
- } else {
- arg.pdblVal = new double(arg.dblVal);
- }
- arg.vt |= VT_BYREF;
- }
- }
- break;
- case QVariant::Color:
- if (out && arg.vt == (VT_COLOR|VT_BYREF)) {
-
- *arg.plVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
- } else {
- arg.vt = VT_COLOR;
- arg.lVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
- if (out) {
- arg.plVal = new long(arg.lVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::Date:
- case QVariant::Time:
- case QVariant::DateTime:
- if (out && arg.vt == (VT_DATE|VT_BYREF)) {
- *arg.pdate = QDateTimeToDATE(qvar.toDateTime());
- } else {
- arg.vt = VT_DATE;
- arg.date = QDateTimeToDATE(qvar.toDateTime());
- if (out) {
- arg.pdate = new DATE(arg.date);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- case QVariant::Invalid: // default-parameters not set
- if (out && arg.vt == (VT_ERROR|VT_BYREF)) {
- *arg.plVal = DISP_E_PARAMNOTFOUND;
- } else {
- arg.vt = VT_ERROR;
- arg.lVal = DISP_E_PARAMNOTFOUND;
- if (out) {
- arg.plVal = new long(arg.lVal);
- arg.vt |= VT_BYREF;
- }
- }
- break;
-
- default:
- return false;
- }
-
- Q_ASSERT(!out || (arg.vt & VT_BYREF));
- return true;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
deleted file mode 100644
index 75af65b5ab..0000000000
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ /dev/null
@@ -1,1640 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
-
-#include "iaccessible2.h"
-#include "qwindowsaccessibility.h"
-#include <QtAccessibilitySupport/private/qaccessiblebridgeutils_p.h>
-#include <QtGui/qaccessible.h>
-#include <QtGui/qclipboard.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
-#include <QtCore/qdebug.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-template <class T>
-static inline T *coTaskMemAllocArray(int size)
-{
- return static_cast<T *>(::CoTaskMemAlloc(sizeof(T) * size_t(size)));
-}
-
-/**************************************************************\
- * AccessibleApplication *
- **************************************************************/
-
-HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name)
-{
- const QString appName = QGuiApplication::applicationName();
- *name = QStringToBSTR(appName);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version)
-{
- const QString appName = QGuiApplication::applicationVersion();
- *version = QStringToBSTR(appName);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name)
-{
- *name = ::SysAllocString(L"Qt");
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
-{
- *version = ::SysAllocString(TEXT(QT_VERSION_STR));
- return S_OK;
-}
-
-
-/**************************************************************\
- * AccessibleRelation *
- **************************************************************/
-AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets,
- QAccessible::Relation relation)
- : m_targets(targets), m_relation(relation)
-{
- Q_ASSERT(m_targets.count());
-}
-
-/* IAccessibleRelation */
-HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType(
- /* [retval][out] */ BSTR *relationType)
-{
- *relationType = relationToBSTR(m_relation);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AccessibleRelation::get_localizedRelationType(
- /* [retval][out] */ BSTR *localizedRelationType)
-{
- // Who ever needs this???
- *localizedRelationType = relationToBSTR(m_relation);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE AccessibleRelation::get_nTargets(
- /* [retval][out] */ long *nTargets)
-{
- // ### always one target
- *nTargets = m_targets.count();
- return S_OK;
-}
-
-/*!
- \internal
- Client allocates and deallocates array
- (see "Special Consideration when using Arrays", in Accessible2.idl)
- */
-HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target(
- /* [in] */ long targetIndex,
- /* [retval][out] */ IUnknown **target)
-{
- if (targetIndex >= 0 && targetIndex < m_targets.count()) {
- QAccessibleInterface *iface = m_targets.at(targetIndex);
- *target = QWindowsAccessibility::wrap(iface);
- if (*target)
- return S_OK;
- return E_FAIL;
- }
- return E_INVALIDARG;
-}
-
-/*!
- \internal
- Client allocates and deallocates \a targets array
- (see "Special Consideration when using Arrays", in Accessible2.idl)
- */
-HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets(
- /* [in] */ long maxTargets,
- /* [length_is][size_is][out] */ IUnknown **targets,
- /* [retval][out] */ long *nTargets)
-{
-
- const int numTargets = qMin(int(maxTargets), m_targets.count());
- for (int i = 0; i < numTargets; ++i) {
- QAccessibleInterface *iface = m_targets.at(i);
- IAccessible *iacc = QWindowsAccessibility::wrap(iface);
- if (!iacc)
- return E_FAIL;
- *targets = iacc;
- ++targets;
- }
- *nTargets = numTargets;
- // \a targets array is allocated by client.
- return numTargets > 0 ? S_OK : S_FALSE;
-}
-
-
-/**************************************************************\
- * *
- * IUnknown *
- * *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface)
-{
- *iface = nullptr;
- QAccessibleInterface *accessible = accessibleInterface();
- if (!accessible)
- return E_NOINTERFACE;
-
- if (SUCCEEDED(QWindowsMsaaAccessible::QueryInterface(id, iface))
- || qWindowsComQueryInterface<IServiceProvider>(this, id, iface)
- || qWindowsComQueryInterface<IAccessible2>(this, id, iface)
- || qWindowsComQueryInterface<IAccessibleComponent>(this, id, iface)) {
- return S_OK;
- }
-
- if (id == IID_IAccessibleAction) {
- if (accessible->actionInterface())
- *iface = static_cast<IAccessibleAction *>(this);
- } else if (id == IID_IAccessibleEditableText) {
- if (accessible->editableTextInterface() ||
- accessible->role() == QAccessible::EditableText)
- {
- *iface = static_cast<IAccessibleEditableText *>(this);
- }
- } else if (id == IID_IAccessibleHyperlink) {
- //*iface = static_cast<IAccessibleHyperlink *>(this);
- } else if (id == IID_IAccessibleHypertext) {
- //*iface = static_cast<IAccessibleHypertext *>(this);
- } else if (id == IID_IAccessibleImage) {
- //*iface = static_cast<IAccessibleImage *>(this);
- } else if (id == IID_IAccessibleTable) {
- //*iface = static_cast<IAccessibleTable *>(this); // not supported
- } else if (id == IID_IAccessibleTable2) {
- if (accessible->tableInterface())
- *iface = static_cast<IAccessibleTable2 *>(this);
- } else if (id == IID_IAccessibleTableCell) {
- if (accessible->tableCellInterface())
- *iface = static_cast<IAccessibleTableCell *>(this);
- } else if (id == IID_IAccessibleText) {
- if (accessible->textInterface())
- *iface = static_cast<IAccessibleText *>(this);
- } else if (id == IID_IAccessibleValue) {
- if (accessible->valueInterface())
- *iface = static_cast<IAccessibleValue *>(this);
- }
- if (*iface) {
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-
-/* Note that IUnknown is inherited from several interfaces. Therefore we must reimplement all its
- functions in the concrete class to avoid ambiguity.
-*/
-ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef()
-{
- return QWindowsMsaaAccessible::AddRef();
-}
-
-ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release()
-{
- return QWindowsMsaaAccessible::Release();
-}
-
-/**************************************************************\
- * *
- * IAccessible2 *
- * *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!nRelations)
- return E_INVALIDARG;
- if (!accessible)
- return E_FAIL;
-
- return getRelationsHelper(0, 0, 0, nRelations);
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!relation)
- return E_INVALIDARG;
- if (!accessible)
- return E_FAIL;
-
- return getRelationsHelper(relation, relationIndex, 1);
-}
-
-/*!
- \internal
- Client allocates and deallocates array
- (see "Special Consideration when using Arrays", in Accessible2.idl)
- */
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations,
- IAccessibleRelation **relations,
- long *nRelations)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- return getRelationsHelper(relations, 0, maxRelations, nRelations);
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- long r = accessible->role();
-
- switch (r) {
- case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break;
- case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break;
- case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break;
- case QAccessible::Paragraph: r = IA2_ROLE_PARAGRAPH; break;
- case QAccessible::Section: r = IA2_ROLE_SECTION; break;
- default: break;
- }
-
- *ia2role = r;
- return S_OK;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/)
-{
- //### Ignore for now
- return E_NOTIMPL;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/)
-{
- //### Ignore for now
- return E_NOTIMPL;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel,
- long *similarItemsInGroup,
- long *positionInGroup)
-{
- // ### Ignore for now. Not sure what this is used for.....
- *groupLevel = 0; // Not applicable
- *similarItemsInGroup = 0; // Not applicable
- *positionInGroup = 0; // Not applicable
- return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- if (!states)
- return E_POINTER;
- QAccessible::State st = accessible->state();
- AccessibleStates ia2states = 0;
- if (st.active)
- ia2states |= IA2_STATE_ACTIVE;
- if (st.invalid)
- ia2states |= IA2_STATE_DEFUNCT;
- if (st.editable)
- ia2states |= IA2_STATE_EDITABLE;
- if (st.multiLine)
- ia2states |= IA2_STATE_MULTI_LINE;
- if (st.selectableText)
- ia2states |= IA2_STATE_SELECTABLE_TEXT;
- if (st.supportsAutoCompletion)
- ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
-
- *states = ia2states;
- return S_OK;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole)
-{
- //###
- *extendedRole = 0;
- return E_NOTIMPL; // mozilla does this
- //return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole)
-{
- //###
- *localizedExtendedRole = 0;
- return E_NOTIMPL; // mozilla does this
- //return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates)
-{
- // Who will ever intepret these values into something meaningful??
- *nExtendedStates = 0;
- return E_NOTIMPL; // mozilla does this
- //return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/,
- BSTR **extendedStates,
- long *nExtendedStates)
-{
- *extendedStates = 0;
- *nExtendedStates = 0;
- return E_NOTIMPL; // mozilla does this
- //return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/,
- BSTR **localizedExtendedStates,
- long *nLocalizedExtendedStates)
-{
- *localizedExtendedStates = 0;
- *nLocalizedExtendedStates = 0;
- return E_NOTIMPL; // mozilla does this
- //return S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- qCDebug(lcQpaAccessibility) << "uniqueID: " << showbase << hex << id;
-
- *outUniqueID = (long)id;
- return int(id) < 0 ? S_OK : S_FALSE;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- return GetWindow(windowHandle);
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- if (!indexInParent)
- return E_INVALIDARG;
- QAccessibleInterface *par = accessible->parent();
- *indexInParent = par ? par->indexOfChild(accessible) : -1;
- if (*indexInParent < 0) {
- qCWarning(lcQpaAccessibility) << "index in parent invalid:" << accessible << "parent:" << par;
- return S_FALSE;
- }
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- IA2Locale res;
- QLocale l;
- res.country = QStringToBSTR(QLocale::countryToString(l.country()));
- res.language = QStringToBSTR(QLocale::languageToString(l.language()));
- res.variant = QStringToBSTR(QString());
- *locale = res;
- return S_OK;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *attributes = 0;//QStringToBSTR(QString());
- return S_FALSE;
-}
-
-/**************************************************************\
- * IAccessibleAction *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *nActions = QAccessibleBridgeUtils::effectiveActionNames(accessible).count();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- return QAccessibleBridgeUtils::performEffectiveAction(accessible, actionName) ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *description = 0;
- const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- if (QAccessibleActionInterface *actionIface = actionInterface())
- *description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
- else
- *description = QStringToBSTR(qAccessibleLocalizedActionDescription(actionName));
-
- return *description ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- Q_UNUSED(nMaxBindings);
- BSTR *arrayOfBindingsToReturn = 0;
- int numBindings = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- const QStringList keyBindings = actionIface->keyBindingsForAction(actionName);
- numBindings = keyBindings.count();
- if (numBindings > 0) {
- // The IDL documents that the client must free with CoTaskMemFree
- arrayOfBindingsToReturn = coTaskMemAllocArray<BSTR>(numBindings);
- std::transform(keyBindings.constBegin(), keyBindings.constEnd(),
- QT_MAKE_CHECKED_ARRAY_ITERATOR(arrayOfBindingsToReturn, numBindings),
- QStringToBSTR);
- }
- }
- *keyBindings = arrayOfBindingsToReturn;
- *nBindings = numBindings;
-
- return numBindings ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *name = 0;
- const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- *name = QStringToBSTR(actionName);
- return *name ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *localizedName = 0;
- const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
-
- const QString actionName = actionNames.at(actionIndex);
- if (QAccessibleActionInterface *actionIface = actionInterface())
- *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
- else
- *localizedName = QStringToBSTR(QAccessibleActionInterface::tr(qPrintable(actionName)));
-
- return *localizedName ? S_OK : S_FALSE;
-}
-
-/**************************************************************\
- * IAccessibleComponent *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QPoint topLeft = accessible->rect().topLeft();
-
- QAccessibleInterface *parentIface = accessible->parent();
- if (parentIface && parentIface->isValid())
- topLeft -= parentIface->rect().topLeft();
- const QPoint nativeTopLeft = QHighDpi::toNativeLocalPosition(topLeft, accessible->window());
-
-
- *x = nativeTopLeft.x();
- *y = nativeTopLeft.y();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- // IA2Color is a typedef for long
- *foreground = static_cast<IA2Color>(accessible->foregroundColor().rgb());
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- // IA2Color is a typedef for long
- *background = static_cast<IA2Color>(accessible->backgroundColor().rgb());
- return S_OK;
-}
-
-/**************************************************************\
- * IAccessibleEditableText *
- **************************************************************/
-#if QT_CONFIG(clipboard)
-/*!
- \internal
-
- if \a endOffset == -1 it means end of the text
-*/
-QString QWindowsIA2Accessible::textForRange(int startOffset, int endOffset) const
-{
- QAccessibleInterface *accessible = accessibleInterface();
-
- if (QAccessibleTextInterface *textIface = accessible->textInterface()) {
- if (endOffset == IA2_TEXT_OFFSET_LENGTH)
- endOffset = textIface->characterCount();
- return textIface->text(startOffset, endOffset);
- }
- QString txt = accessible->text(QAccessible::Value);
- if (endOffset == IA2_TEXT_OFFSET_LENGTH)
- endOffset = txt.length();
- return txt.mid(startOffset, endOffset - startOffset);
-}
-#endif
-
-/*!
- \internal
-*/
-void QWindowsIA2Accessible::replaceTextFallback(long startOffset, long endOffset, const QString &txt)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- QString t = textForRange(0, -1);
- if (endOffset == IA2_TEXT_OFFSET_LENGTH)
- endOffset = t.length();
- if (endOffset - startOffset == 0) {
- t.insert(startOffset, txt);
- } else {
- t.replace(startOffset, endOffset - startOffset, txt);
- }
- accessible->setText(QAccessible::Value, t);
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::copyText(long startOffset, long endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
-#if QT_CONFIG(clipboard)
- const QString t = textForRange(startOffset, endOffset);
- QGuiApplication::clipboard()->setText(t);
- return S_OK;
-#else
- return E_NOTIMPL;
-#endif
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::deleteText(long startOffset, long endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface())
- editableTextIface->deleteText(startOffset, endOffset);
- else
- replaceTextFallback(startOffset, endOffset, QString());
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- const QString txt = QString::fromWCharArray(*text);
- if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface())
- editableTextIface->insertText(offset, txt);
- else
- replaceTextFallback(offset, offset, txt);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::cutText(long startOffset, long endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
-#if QT_CONFIG(clipboard)
- const QString t = textForRange(startOffset, endOffset);
- if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface())
- editableTextIface->deleteText(startOffset, endOffset);
- else
- replaceTextFallback(startOffset, endOffset, QString());
- QGuiApplication::clipboard()->setText(t);
- return S_OK;
-#else
- return E_NOTIMPL;
-#endif
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::pasteText(long offset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
-#if QT_CONFIG(clipboard)
- const QString txt = QGuiApplication::clipboard()->text();
- if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface())
- editableTextIface->insertText(offset, txt);
- else
- replaceTextFallback(offset, offset, txt);
- return S_OK;
-#else
- return E_NOTIMPL;
-#endif
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, long endOffset, BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- const QString txt = QString::fromWCharArray(*text);
- if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface())
- editableTextIface->replaceText(startOffset, endOffset, txt);
- else
- replaceTextFallback(startOffset, endOffset, txt);
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setAttributes(long /*startOffset*/, long /*endOffset*/, BSTR * /*attributes*/)
-{
- return E_NOTIMPL;
-}
-
-
-/**************************************************************\
- * IAccessibleTable2 *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *cell = 0;
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) {
- *cell = QWindowsAccessibility::wrap(qtCell);
- }
- }
- qCDebug(lcQpaAccessibility) << "found cell? " << *cell;
- return *cell ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *captionInterface = 0;
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- if (QAccessibleInterface *iface = tableIface->caption())
- *captionInterface = QWindowsAccessibility::wrap(iface);
- }
- return *captionInterface ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *description = 0;
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- const QString qtDesc = tableIface->columnDescription(column);
- if (!qtDesc.isEmpty())
- *description = QStringToBSTR(qtDesc);
- }
- return *description ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *columnCount = tableIface->columnCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *rowCount = tableIface->rowCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *cellCount = tableIface->selectedCellCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *columnCount = tableIface->selectedColumnCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *rowCount = tableIface->selectedRowCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *description = 0;
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- const QString qtDesc = tableIface->rowDescription(row);
- if (!qtDesc.isEmpty())
- *description = QStringToBSTR(qtDesc);
- }
- return *description ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- Q_UNUSED(cells);
- Q_UNUSED(nSelectedCells);
- if (!accessible)
- return E_FAIL;
-
- QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells();
- return wrapListOfCells(selectedCells, cells, nSelectedCells);
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- const QList<int> selectedIndices = tableIface->selectedColumns();
- const int count = selectedIndices.count();
- *nColumns = count;
- *selectedColumns = Q_NULLPTR;
- if (count) {
- *selectedColumns = coTaskMemAllocArray<long>(count);
- std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(),
- QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedColumns, count));
- }
- return count ? S_OK : S_FALSE;
- }
- return E_FAIL;
-
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- const QList<int> selectedIndices = tableIface->selectedRows();
- const int count = selectedIndices.count();
- *nRows = count;
- *selectedRows = Q_NULLPTR;
- if (count) {
- *selectedRows = coTaskMemAllocArray<long>(count);
- std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(),
- QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedRows, count));
- }
- return count ? S_OK : S_FALSE;
- }
- return E_FAIL;
-
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *summaryInterface = 0;
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- if (QAccessibleInterface *iface = tableIface->summary())
- *summaryInterface = QWindowsAccessibility::wrap(iface);
- }
- return *summaryInterface ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *isSelected = tableIface->isColumnSelected(column);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- *isSelected = tableIface->isRowSelected(row);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- bool ok = tableIface->selectRow(row);
- return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- bool ok = tableIface->selectColumn(column);
- return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- bool ok = tableIface->unselectRow(row);
- return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleTableInterface *tableIface = tableInterface()) {
- bool ok = tableIface->unselectColumn(column);
- return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- return E_NOTIMPL;
-}
-
-/**************************************************************\
- * IAccessibleTableCell *
-\**************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *nColumnsSpanned = tableCellInterface()->columnExtent();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles,
- long *nColumnHeaderCells)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells();
- return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells);
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *columnIndex = tableCellInterface()->columnIndex();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *nRowsSpanned = tableCellInterface()->rowExtent();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles,
- long *nRowHeaderCells)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells();
- return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells);
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *rowIndex = tableCellInterface()->rowIndex();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- *isSelected = tableCellInterface()->isSelected();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column,
- long *rowExtents, long *columnExtents,
- boolean *isSelected)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible || !tableCellInterface())
- return E_FAIL;
-
- *row = tableCellInterface()->rowIndex();
- *column = tableCellInterface()->columnIndex();
- *rowExtents = tableCellInterface()->rowExtent();
- *columnExtents = tableCellInterface()->columnExtent();
- *isSelected = tableCellInterface()->isSelected();
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessibleInterface *tableIface = tableCellInterface()->table();
-
- *table = QWindowsAccessibility::wrap(tableIface);
- return S_OK;
-}
-
-/**************************************************************\
- * IAccessibleText *
-\**************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset,
- long endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- text->addSelection(startOffset, endOffset);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset,
- long *startOffset,
- long *endOffset,
- BSTR *textAttributes)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- const QString attrs = text->attributes(offset, reinterpret_cast<int *>(startOffset),
- reinterpret_cast<int *>(endOffset));
- *textAttributes = QStringToBSTR(attrs);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- *offset = text->cursorPosition();
- return S_OK;
- }
- return E_FAIL;
-}
-
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset,
- enum IA2CoordinateType coordType,
- long *x,
- long *y,
- long *width,
- long *height)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- QRect rect = text->characterRect(offset);
- mapFromScreenPos(coordType, rect.topLeft(), x, y);
- *width = rect.width();
- *height = rect.height();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- *nSelections = text->selectionCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x,
- long y,
- enum IA2CoordinateType coordType,
- long *offset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- QPoint screenPos = mapToScreenPos(coordType, x, y);
- *offset = text->offsetAtPoint(screenPos);
- return (*offset >=0 ? S_OK : S_FALSE);
- }
- return E_FAIL;
-
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex,
- long *startOffset,
- long *endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *text = textInterface()) {
- text->selection(selectionIndex, reinterpret_cast<int *>(startOffset),
- reinterpret_cast<int *>(endOffset));
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset,
- long endOffset,
- BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textif = textInterface()) {
- const QString t = textif->text(startOffset, endOffset);
- if (!t.isEmpty()) {
- *text = QStringToBSTR(t);
- return S_OK;
- }
- return E_INVALIDARG;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset,
- enum IA2TextBoundaryType boundaryType,
- long *startOffset,
- long *endOffset,
- BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- const QString txt =
- textIface->textBeforeOffset(offset, static_cast<QAccessible::TextBoundaryType>(boundaryType),
- reinterpret_cast<int *>(startOffset),
- reinterpret_cast<int *>(endOffset));
- if (!txt.isEmpty()) {
- *text = QStringToBSTR(txt);
- return S_OK;
- }
- return S_FALSE;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset(
- long offset,
- enum IA2TextBoundaryType boundaryType,
- long *startOffset,
- long *endOffset,
- BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- const QString txt =
- textIface->textAfterOffset(offset, static_cast<QAccessible::TextBoundaryType>(boundaryType),
- reinterpret_cast<int *>(startOffset),
- reinterpret_cast<int *>(endOffset));
- if (!txt.isEmpty()) {
- *text = QStringToBSTR(txt);
- return S_OK;
- }
- return S_FALSE;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset,
- enum IA2TextBoundaryType boundaryType,
- long *startOffset,
- long *endOffset,
- BSTR *text)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- const QString txt =
- textIface->textAtOffset(offset, static_cast<QAccessible::TextBoundaryType>(boundaryType),
- reinterpret_cast<int *>(startOffset),
- reinterpret_cast<int *>(endOffset));
- if (!txt.isEmpty()) {
- *text = QStringToBSTR(txt);
- return S_OK;
- }
- return S_FALSE;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- textIface->removeSelection(selectionIndex);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- textIface->setCursorPosition(offset);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex,
- long startOffset,
- long endOffset)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- textIface->setSelection(selectionIndex, startOffset, endOffset);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- *nCharacters = textIface->characterCount();
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex,
- long endIndex,
- enum IA2ScrollType scrollType)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (QAccessibleTextInterface *textIface = textInterface()) {
- Q_UNUSED(scrollType); //###
- textIface->scrollToSubstring(startIndex, endIndex);
- return S_OK;
- }
- return E_FAIL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex,
- long endIndex,
- enum IA2CoordinateType coordinateType,
- long x,
- long y)
-{
- Q_UNUSED(startIndex);
- Q_UNUSED(endIndex);
- Q_UNUSED(coordinateType);
- Q_UNUSED(x);
- Q_UNUSED(y);
-
- return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText)
-{
- Q_UNUSED(newText);
- return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText)
-{
- Q_UNUSED(oldText);
- return E_NOTIMPL;
-}
-
-/**************************************************************\
- * IAccessibleValue *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- if (QAccessibleValueInterface *valueIface = valueInterface()) {
- const QVariant var = valueIface->currentValue();
- if (QVariant2VARIANT(var, *currentValue, QByteArray(), false))
- return S_OK;
-
- }
- currentValue->vt = VT_EMPTY;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- HRESULT hr = S_FALSE;
- if (QAccessibleValueInterface *valueIface = valueInterface()) {
- hr = VariantChangeType(&value, &value, 0, VT_R8);
- if (SUCCEEDED(hr)) {
- // ### works only for numbers (not date, strings, etc)
- valueIface->setCurrentValue(QVariant(value.dblVal));
- }
- }
- return hr;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- if (QAccessibleValueInterface *valueIface = valueInterface()) {
- const QVariant var = valueIface->maximumValue();
- if (QVariant2VARIANT(var, *maximumValue, QByteArray(), false))
- return S_OK;
- }
- maximumValue->vt = VT_EMPTY;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
- if (QAccessibleValueInterface *valueIface = valueInterface()) {
- const QVariant var = valueIface->minimumValue();
- if (QVariant2VARIANT(var, *minimumValue, QByteArray(), false))
- return S_OK;
- }
- minimumValue->vt = VT_EMPTY;
- return S_FALSE;
-}
-
-
-/**************************************************************\
- * IServiceProvider *
- **************************************************************/
-/*!
- \internal
- Reimplemented from IServiceProvider
-*/
-HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface)
-{
- if (!iface)
- return E_POINTER;
- Q_UNUSED(guidService);
- *iface = 0;
- qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << QWindowsAccessibleGuid(riid);
-
-
- if (guidService == IID_IAccessible) {
- if (riid == IID_IServiceProvider) {
- // do not end up calling QueryInterface for IID_IServiceProvider
- *iface = 0;
- } else if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) {
- // The above conditions works with AccProbe and NVDA.
- *iface = static_cast<IAccessible*>(this);
- } else {
- // According to _dicoveringInterfaces Discovery of Interfaces, we should really only
- // enter here if riid == IID_IAccessible2, but some screen readers does not like that,
- // and other servers seems to have realized that. (Chrome and Mozilla for instance,
- // calls QueryInterface more or less in the same way)
-
- // For instance, accProbe discovers IID_IAccessibleTable2 by a QueryService only.
- return QueryInterface(riid, iface);
- }
- }
-
- if (riid == IID_IAccessibleApplication) {
- *iface = new AccessibleApplication;
- return S_OK;
- }
- if (*iface) {
- AddRef();
- return S_OK;
- }
-
- return E_NOINTERFACE;
-}
-
-
-/*!
- \internal
- private function..
- \a maxRelations max number of relations to return in \a relations
- \a relations the array of relations matching
- \a startIndex Index to start to return from,
- it will return only that specific relation in \a relations
-
- If \a relations is null, \a startIndex and \a maxRelations are ignored, causing
- it to return the number of relations in \a nRelations
-*/
-HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- if (nRelations)
- *nRelations = 0;
- typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry;
- QVector<RelationEntry> rels = accessible->relations();
- QMap<QAccessible::Relation, QAccessibleInterface *> relationMap;
- for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it)
- {
- RelationEntry e = *it;
- relationMap.insertMulti(e.second, e.first);
- }
-
- QList<QAccessible::Relation> keys = relationMap.keys();
- const int numRelations = keys.count();
- if (relations) {
- for (int i = startIndex; i < qMin(startIndex + int(maxRelations), numRelations); ++i) {
- QAccessible::Relation relation = keys.at(i);
- QList<QAccessibleInterface*> targets = relationMap.values(relation);
- AccessibleRelation *rel = new AccessibleRelation(targets, relation);
- *relations = rel;
- ++relations;
- }
- }
- if (nRelations)
- *nRelations = numRelations;
-
- return numRelations > 0 ? S_OK : S_FALSE;
-}
-
-
-
-
-/*!
- \internal
- helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible*
- The IAccessible* array is returned as a IUnknown*
-*/
-HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount)
-{
- const int count = inputCells.count();
- // Server allocates array
- *nCellCount = count;
- *outputAccessibles = Q_NULLPTR;
- if (count) {
- *outputAccessibles = coTaskMemAllocArray<IUnknown *>(count);
- std::transform(inputCells.constBegin(), inputCells.constEnd(),
- QT_MAKE_CHECKED_ARRAY_ITERATOR(*outputAccessibles, count),
- QWindowsAccessibility::wrap);
- }
- return count > 0 ? S_OK : S_FALSE;
-}
-
-// Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same
-Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast<IA2Role>(QAccessible::ColorChooser));
-Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast<IA2Role>(QAccessible::Footer));
-Q_STATIC_ASSERT(IA2_ROLE_FORM == static_cast<IA2Role>(QAccessible::Form));
-Q_STATIC_ASSERT(IA2_ROLE_HEADING == static_cast<IA2Role>(QAccessible::Heading));
-Q_STATIC_ASSERT(IA2_ROLE_NOTE == static_cast<IA2Role>(QAccessible::Note));
-Q_STATIC_ASSERT(IA2_ROLE_COMPLEMENTARY_CONTENT == static_cast<IA2Role>(QAccessible::ComplementaryContent));
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
deleted file mode 100644
index d987016e15..0000000000
--- a/src/plugins/platforms/windows/accessible/iaccessible2.h
+++ /dev/null
@@ -1,358 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef IACCESSIBLE2_H
-#define IACCESSIBLE2_H
-
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
-
-#include "qwindowscombase.h"
-#include "qwindowsmsaaaccessible.h"
-#include "comutils.h"
-
-#include "ia2_api_all.h"
-
-#include <servprov.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifdef Q_CC_MINGW
-QT_WARNING_DISABLE_GCC("-Wunused-function") // MinGW 7.X claims it is unused
-// MinGW's __uuidof operator does not work for the Accessible2 interfaces
-template <>
-IID qUuidOf<IAccessibleComponent>() { return IID_IAccessibleComponent; }
-#endif // Q_CC_MINGW
-
-class QWindowsIA2Accessible : public QWindowsMsaaAccessible,
- public IAccessibleAction,
- public IAccessibleComponent,
- public IAccessibleEditableText,
- public IAccessibleTable2,
- public IAccessibleTableCell,
- public IAccessibleText,
- public IAccessibleValue,
- public IServiceProvider
-{
-public:
- QWindowsIA2Accessible(QAccessibleInterface *a) : QWindowsMsaaAccessible(a) {}
-
- /* IUnknown */
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- /* IAccessible2 */
- HRESULT STDMETHODCALLTYPE get_nRelations(long *nRelations);
- HRESULT STDMETHODCALLTYPE get_relation(long relationIndex, IAccessibleRelation **relation);
- HRESULT STDMETHODCALLTYPE get_relations(long maxRelations, IAccessibleRelation **relations, long *nRelations);
- HRESULT STDMETHODCALLTYPE role(long *role);
- HRESULT STDMETHODCALLTYPE scrollTo(enum IA2ScrollType scrollType);
- HRESULT STDMETHODCALLTYPE scrollToPoint(enum IA2CoordinateType coordinateType, long x, long y);
- HRESULT STDMETHODCALLTYPE get_groupPosition(long *groupLevel, long *similarItemsInGroup, long *positionInGroup);
- HRESULT STDMETHODCALLTYPE get_states(AccessibleStates *states);
- HRESULT STDMETHODCALLTYPE get_extendedRole(BSTR *extendedRole);
- HRESULT STDMETHODCALLTYPE get_localizedExtendedRole(BSTR *localizedExtendedRole);
- HRESULT STDMETHODCALLTYPE get_nExtendedStates(long *nExtendedStates);
- HRESULT STDMETHODCALLTYPE get_extendedStates(long maxExtendedStates, BSTR **extendedStates, long *nExtendedStates);
- HRESULT STDMETHODCALLTYPE get_localizedExtendedStates(long maxLocalizedExtendedStates, BSTR **localizedExtendedStates, long *nLocalizedExtendedStates);
- HRESULT STDMETHODCALLTYPE get_uniqueID(long *uniqueID);
- HRESULT STDMETHODCALLTYPE get_windowHandle(HWND *windowHandle);
- HRESULT STDMETHODCALLTYPE get_indexInParent(long *indexInParent);
- HRESULT STDMETHODCALLTYPE get_locale(IA2Locale *locale);
- HRESULT STDMETHODCALLTYPE get_attributes(BSTR *attributes);
-
- /* IAccessibleAction */
- HRESULT STDMETHODCALLTYPE nActions(long *nActions);
- HRESULT STDMETHODCALLTYPE doAction(long actionIndex);
- HRESULT STDMETHODCALLTYPE get_description(long actionIndex, BSTR *description);
- HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings);
- HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name);
- HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex, BSTR *localizedName);
-
- /* IAccessibleComponent */
- HRESULT STDMETHODCALLTYPE get_locationInParent(long *x,long *y);
- HRESULT STDMETHODCALLTYPE get_foreground(IA2Color *foreground);
- HRESULT STDMETHODCALLTYPE get_background(IA2Color *background);
-
- /* IAccessibleEditableText */
- HRESULT STDMETHODCALLTYPE copyText(long startOffset, long endOffset);
- HRESULT STDMETHODCALLTYPE deleteText(long startOffset, long endOffset);
- HRESULT STDMETHODCALLTYPE insertText(long offset, BSTR *text);
- HRESULT STDMETHODCALLTYPE cutText(long startOffset, long endOffset);
- HRESULT STDMETHODCALLTYPE pasteText(long offset);
- HRESULT STDMETHODCALLTYPE replaceText(long startOffset, long endOffset, BSTR *text);
- HRESULT STDMETHODCALLTYPE setAttributes(long startOffset, long endOffset, BSTR *attributes);
-
- /* IAccessibleTable2 */
- HRESULT STDMETHODCALLTYPE get_cellAt( long row, long column, IUnknown **cell);
- HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessibleInterface);
- HRESULT STDMETHODCALLTYPE get_columnDescription( long column, BSTR *description);
- HRESULT STDMETHODCALLTYPE get_nColumns( long *columnCount);
- HRESULT STDMETHODCALLTYPE get_nRows( long *rowCount);
- HRESULT STDMETHODCALLTYPE get_nSelectedCells( long *cellCount);
- HRESULT STDMETHODCALLTYPE get_nSelectedColumns( long *columnCount);
- HRESULT STDMETHODCALLTYPE get_nSelectedRows( long *rowCount);
- HRESULT STDMETHODCALLTYPE get_rowDescription( long row, BSTR *description);
- HRESULT STDMETHODCALLTYPE get_selectedCells( IUnknown ***cells, long *nSelectedCells);
- HRESULT STDMETHODCALLTYPE get_selectedColumns( long **selectedColumns, long *nColumns);
- HRESULT STDMETHODCALLTYPE get_selectedRows( long **selectedRows, long *nRows);
- HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessibleInterface);
- HRESULT STDMETHODCALLTYPE get_isColumnSelected( long column, boolean *isSelected);
- HRESULT STDMETHODCALLTYPE get_isRowSelected( long row, boolean *isSelected);
- HRESULT STDMETHODCALLTYPE selectRow( long row);
- HRESULT STDMETHODCALLTYPE selectColumn( long column);
- HRESULT STDMETHODCALLTYPE unselectRow( long row);
- HRESULT STDMETHODCALLTYPE unselectColumn( long column);
- HRESULT STDMETHODCALLTYPE get_modelChange( IA2TableModelChange *modelChange);
-
- /* IAccessibleTableCell */
- HRESULT STDMETHODCALLTYPE get_columnExtent(long *nColumnsSpanned);
- HRESULT STDMETHODCALLTYPE get_columnHeaderCells(IUnknown ***cellAccessibles, long *nColumnHeaderCells);
- HRESULT STDMETHODCALLTYPE get_columnIndex(long *columnIndex);
- HRESULT STDMETHODCALLTYPE get_rowExtent(long *nRowsSpanned);
- HRESULT STDMETHODCALLTYPE get_rowHeaderCells(IUnknown ***cellAccessibles, long *nRowHeaderCells);
- HRESULT STDMETHODCALLTYPE get_rowIndex(long *rowIndex);
- HRESULT STDMETHODCALLTYPE get_isSelected( boolean *isSelected);
- HRESULT STDMETHODCALLTYPE get_rowColumnExtents(long *row, long *column,
- long *rowExtents, long *columnExtents,
- boolean *isSelected);
- HRESULT STDMETHODCALLTYPE get_table(IUnknown **table);
-
-
- /* IAccessibleText */
- HRESULT STDMETHODCALLTYPE addSelection(long startOffset, long endOffset);
- HRESULT STDMETHODCALLTYPE get_attributes(long offset, long *startOffset,
- long *endOffset, BSTR *textAttributes);
- HRESULT STDMETHODCALLTYPE get_caretOffset(long *offset);
- HRESULT STDMETHODCALLTYPE get_characterExtents(long offset, enum IA2CoordinateType coordType,
- long *x, long *y,
- long *width, long *height);
- HRESULT STDMETHODCALLTYPE get_nSelections(long *nSelections);
- HRESULT STDMETHODCALLTYPE get_offsetAtPoint(long x, long y, enum IA2CoordinateType coordType, long *offset);
- HRESULT STDMETHODCALLTYPE get_selection(long selectionIndex, long *startOffset, long *endOffset);
- HRESULT STDMETHODCALLTYPE get_text(long startOffset, long endOffset, BSTR *text);
- HRESULT STDMETHODCALLTYPE get_textBeforeOffset(long offset, enum IA2TextBoundaryType boundaryType,
- long *startOffset, long *endOffset, BSTR *text);
- HRESULT STDMETHODCALLTYPE get_textAfterOffset(long offset, enum IA2TextBoundaryType boundaryType,
- long *startOffset, long *endOffset, BSTR *text);
- HRESULT STDMETHODCALLTYPE get_textAtOffset(long offset, enum IA2TextBoundaryType boundaryType,
- long *startOffset, long *endOffset, BSTR *text);
- HRESULT STDMETHODCALLTYPE removeSelection(long selectionIndex);
- HRESULT STDMETHODCALLTYPE setCaretOffset(long offset);
- HRESULT STDMETHODCALLTYPE setSelection(long selectionIndex, long startOffset, long endOffset);
- HRESULT STDMETHODCALLTYPE get_nCharacters(long *nCharacters);
- HRESULT STDMETHODCALLTYPE scrollSubstringTo(long startIndex, long endIndex, enum IA2ScrollType scrollType);
- HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(long startIndex, long endIndex,
- enum IA2CoordinateType coordinateType, long x, long y);
- HRESULT STDMETHODCALLTYPE get_newText(IA2TextSegment *newText);
- HRESULT STDMETHODCALLTYPE get_oldText(IA2TextSegment *oldText);
-
- /* IAccessibleValue */
- HRESULT STDMETHODCALLTYPE get_currentValue(VARIANT *currentValue);
- HRESULT STDMETHODCALLTYPE setCurrentValue(VARIANT value);
- HRESULT STDMETHODCALLTYPE get_maximumValue(VARIANT *maximumValue);
- HRESULT STDMETHODCALLTYPE get_minimumValue(VARIANT *minimumValue);
-
- /* IServiceProvider */
- HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppv);
-
- /* private helper functions */
-private:
- inline QAccessibleTextInterface *textInterface() const {
- QAccessibleInterface *accessible = accessibleInterface();
- return accessible ? accessible->textInterface() : static_cast<QAccessibleTextInterface *>(0);
- }
-
- inline QAccessibleActionInterface *actionInterface() const {
- QAccessibleInterface *accessible = accessibleInterface();
- return accessible->actionInterface();
- }
-
- inline QAccessibleValueInterface *valueInterface() const {
- QAccessibleInterface *accessible = accessibleInterface();
- return accessible->valueInterface();
- }
-
- inline QAccessibleTableInterface *tableInterface() const {
- QAccessibleInterface *accessible = accessibleInterface();
- return accessible->tableInterface();
- }
-
- inline QAccessibleTableCellInterface *tableCellInterface() const {
- QAccessibleInterface *accessible = accessibleInterface();
- return accessible->tableCellInterface();
- }
-
- /*!
- \internal
- \a screenPos is in screen relative position
- \a x and \y (out) is in parent relative position if coordType == IA2_COORDTYPE_PARENT_RELATIVE
- */
- void mapFromScreenPos(enum IA2CoordinateType coordType, const QPoint &screenPos, long *x, long *y) const {
- QAccessibleInterface *accessible = accessibleInterface();
- if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) {
- // caller wants relative to parent
- if (QAccessibleInterface *parent = accessible->parent()) {
- const QRect parentScreenRect = parent->rect();
- *x = parentScreenRect.x() - screenPos.x();
- *y = parentScreenRect.y() - screenPos.y();
- return;
- }
- }
- *x = screenPos.x();
- *y = screenPos.y();
- }
-
- /*!
- \internal
- \a x and \y is in parent relative position if coordType == IA2_COORDTYPE_PARENT_RELATIVE
- \return a screen relative position
- */
- QPoint mapToScreenPos(enum IA2CoordinateType coordType, long x, long y) const {
- QAccessibleInterface *accessible = accessibleInterface();
- if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) {
- if (QAccessibleInterface *parent = accessible->parent()) {
- const QRect parentScreenRect = parent->rect();
- return QPoint(parentScreenRect.x() + x, parentScreenRect.y() + y);
- }
- }
- return QPoint(x,y);
- }
-
- HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0);
- HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount);
- QString textForRange(int startOffset, int endOffset) const;
- void replaceTextFallback(long startOffset, long endOffset, const QString &txt);
-
-};
-
-/**************************************************************\
- * AccessibleApplication *
- **************************************************************/
-
-#ifdef Q_CC_MINGW
-// MinGW's __uuidof operator does not work for the IAccessible2 interfaces
-template <>
-IID qUuidOf<IAccessibleApplication>() { return IID_IAccessibleApplication; }
-
-template <>
-IID qUuidOf<IAccessible2>() { return IID_IAccessible2; }
-
-template <>
-IID qUuidOf<IAccessibleRelation>() { return IID_IAccessibleRelation; }
-#endif // Q_CC_MINGW
-
-class AccessibleApplication : public QWindowsComBase<IAccessibleApplication>
-{
-public:
- AccessibleApplication() {}
-
- virtual ~AccessibleApplication() {}
-
- /* IAccessibleApplication */
- HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name);
- HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version);
- HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name);
- HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version);
-};
-
-
-
-/**************************************************************\
- * AccessibleRelation *
- **************************************************************/
-
-
-
-class AccessibleRelation : public QWindowsComBase<IAccessibleRelation>
-{
-public:
- AccessibleRelation(const QList<QAccessibleInterface *> &targets,
- QAccessible::Relation relation);
-
- virtual ~AccessibleRelation() {}
-
- /* IAccessibleRelation */
- HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType);
- HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType);
- HRESULT STDMETHODCALLTYPE get_nTargets(long *nTargets);
- HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target);
- HRESULT STDMETHODCALLTYPE get_targets(long maxTargets, IUnknown **targets, long *nTargets);
-
-private:
- static BSTR relationToBSTR(QAccessible::Relation relation)
- {
- const wchar_t *constRelationString = 0;
- switch (relation) {
- case QAccessible::Label:
- constRelationString = IA2_RELATION_LABEL_FOR;
- break;
- case QAccessible::Labelled:
- constRelationString = IA2_RELATION_LABELLED_BY;
- break;
- case QAccessible::Controller:
- constRelationString = IA2_RELATION_CONTROLLER_FOR;
- break;
- case QAccessible::Controlled:
- constRelationString = IA2_RELATION_CONTROLLED_BY;
- break;
- case QAccessible::AllRelations:
- constRelationString = ( L"AllRelations" );
- break;
- }
-
- if (constRelationString) {
- BSTR bstrVal;
- const UINT wlen = (UINT)wcslen(constRelationString);
- bstrVal = ::SysAllocStringLen(constRelationString, wlen);
- return bstrVal;
- }
- return 0;
- }
-
-
- QList<QAccessibleInterface *> m_targets;
- QAccessible::Relation m_relation;
-};
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_ACCESSIBILITY
-
-#endif // IACCESSIBLE2_H
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
deleted file mode 100644
index d48cb9674f..0000000000
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
-
-
-#include <private/qsystemlibrary_p.h>
-
-#include <QtCore/qlocale.h>
-#include <QtCore/qmap.h>
-#include <QtCore/qpair.h>
-#include <QtCore/qpointer.h>
-#include <QtGui/qaccessible.h>
-#include <QtGui/private/qguiapplication_p.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qplatformintegration.h>
-#include <QtGui/qwindow.h>
-#include <QtGui/qguiapplication.h>
-#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h> // registry helper
-
-#include "qwindowsaccessibility.h"
-#include "iaccessible2.h"
-#include "comutils.h"
-
-#include <oleacc.h>
-
-//#include <uiautomationcoreapi.h>
-#ifndef UiaRootObjectId
-#define UiaRootObjectId -25
-#endif
-
-#include <winuser.h>
-#if !defined(WINABLEAPI)
-# include <winable.h>
-#endif
-
-#include <servprov.h>
-#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
-#include <comdef.h>
-#endif
-
-#include <QtCore/qt_windows.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \!internal
- \class QWindowsAccessibility
-
- Implements QPlatformAccessibility
-
-*/
-QWindowsAccessibility::QWindowsAccessibility()
-{
-}
-
-// Retrieve sound name by checking the icon property of a message box
-static inline QString messageBoxAlertSound(const QObject *messageBox)
-{
- enum MessageBoxIcon { // Keep in sync with QMessageBox::Icon
- Information = 1,
- Warning = 2,
- Critical = 3
- };
- switch (messageBox->property("icon").toInt()) {
- case Information:
- return QStringLiteral("SystemAsterisk");
- case Warning:
- return QStringLiteral("SystemExclamation");
- case Critical:
- return QStringLiteral("SystemHand");
- }
- return QString();
-}
-
-static QString soundFileName(const QString &soundName)
-{
- const QString key = QStringLiteral("AppEvents\\Schemes\\Apps\\.Default\\")
- + soundName + QStringLiteral("\\.Current");
- return QWindowsFontDatabase::readRegistryString(HKEY_CURRENT_USER,
- reinterpret_cast<const wchar_t *>(key.utf16()), L"");
-}
-
-void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
-{
- QString soundName;
- switch (event->type()) {
- case QAccessible::PopupMenuStart:
- soundName = QLatin1String("MenuPopup");
- break;
-
- case QAccessible::MenuCommand:
- soundName = QLatin1String("MenuCommand");
- break;
-
- case QAccessible::Alert:
- soundName = event->object()->inherits("QMessageBox") ?
- messageBoxAlertSound(event->object()) : QStringLiteral("SystemAsterisk");
- break;
- default:
- break;
- }
-
- if (!soundName.isEmpty() && !soundFileName(soundName).isEmpty()) {
- PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0,
- SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
- }
-
- // An event has to be associated with a window,
- // so find the first parent that is a widget and that has a WId
- QAccessibleInterface *iface = event->accessibleInterface();
- if (!isActive() || !iface || !iface->isValid())
- return;
- QWindow *window = QWindowsAccessibility::windowHelper(iface);
-
- if (!window) {
- window = QGuiApplication::focusWindow();
- if (!window)
- return;
- }
-
- QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
- if (!window->handle()) // Called before show(), no native window yet.
- return;
- const HWND hWnd = reinterpret_cast<HWND>(platform->nativeResourceForWindow("handle", window));
-
- if (event->type() != QAccessible::MenuCommand && // MenuCommand is faked
- event->type() != QAccessible::ObjectDestroyed) {
- ::NotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, QAccessible::uniqueId(iface));
- }
-}
-
-QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface)
-{
- QWindow *window = iface->window();
- if (!window) {
- QAccessibleInterface *acc = iface->parent();
- while (acc && acc->isValid() && !window) {
- window = acc->window();
- QAccessibleInterface *par = acc->parent();
- acc = par;
- }
- }
- return window;
-}
-
-/*!
- \internal
- helper to wrap a QAccessibleInterface inside a IAccessible*
-*/
-IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
-{
- if (!acc)
- return 0;
-
- // ### FIXME: maybe we should accept double insertions into the cache
- if (!QAccessible::uniqueId(acc))
- QAccessible::registerAccessibleInterface(acc);
-
- QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc);
- IAccessible *iacc = 0;
- wacc->QueryInterface(IID_IAccessible, reinterpret_cast<void **>(&iacc));
- return iacc;
-}
-
-bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
-{
- if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
- /* For UI Automation */
- } else if (DWORD(lParam) == DWORD(OBJID_CLIENT)) {
- // Start handling accessibility internally
- QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
- // Ignoring all requests while starting up
- // ### Maybe QPA takes care of this???
- if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
- return false;
-
- typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN);
- static PtrLresultFromObject ptrLresultFromObject = 0;
- static bool oleaccChecked = false;
-
- if (!oleaccChecked) {
- oleaccChecked = true;
- ptrLresultFromObject = reinterpret_cast<PtrLresultFromObject>(QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"));
- }
-
- if (ptrLresultFromObject) {
- QWindow *window = QWindowsContext::instance()->findWindow(hwnd);
- if (window) {
- QAccessibleInterface *acc = window->accessibleRoot();
- if (acc) {
- if (IAccessible *iface = wrap(acc)) {
- *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2
- if (*lResult) {
- iface->Release(); // the client will release the object again, and then it will destroy itself
- }
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
deleted file mode 100644
index fe2b9335cb..0000000000
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ /dev/null
@@ -1,1223 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
-
-#include "qwindowsmsaaaccessible.h"
-#include "qwindowsaccessibility.h"
-#include "qwindowscombase.h"
-#include <oleacc.h>
-#include <servprov.h>
-#include <winuser.h>
-#include "comutils.h"
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qmap.h>
-#include <QtCore/qpair.h>
-#include <QtGui/qaccessible.h>
-#include <QtGui/qguiapplication.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <QtGui/qwindow.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
-
-//#include <uiautomationcoreapi.h>
-#ifndef UiaRootObjectId
-#define UiaRootObjectId -25
-#endif
-
-#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
-#include <comdef.h>
-#endif
-
-
-#include <QtCore/qt_windows.h>
-
-
-QT_BEGIN_NAMESPACE
-
-class QWindowsEnumerate : public QWindowsComBase<IEnumVARIANT>
-{
-public:
- QWindowsEnumerate(const QVector<int> &a) : QWindowsComBase<IEnumVARIANT>(0), current(0),array(a) {}
- virtual ~QWindowsEnumerate() {}
-
- HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum);
- HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched);
- HRESULT STDMETHODCALLTYPE Reset();
- HRESULT STDMETHODCALLTYPE Skip(unsigned long celt);
-
-private:
- ULONG current;
- QVector<int> array;
-};
-
-HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum)
-{
- QWindowsEnumerate *penum = 0;
- *ppEnum = 0;
-
- penum = new QWindowsEnumerate(array);
- if (!penum)
- return E_OUTOFMEMORY;
- penum->current = current;
- penum->array = array;
- penum->AddRef();
- *ppEnum = penum;
-
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched)
-{
- if (pCeltFetched)
- *pCeltFetched = 0;
-
- ULONG l;
- for (l = 0; l < celt; l++) {
- VariantInit(&rgVar[l]);
- if (current + 1 > ULONG(array.size())) {
- *pCeltFetched = l;
- return S_FALSE;
- }
-
- rgVar[l].vt = VT_I4;
- rgVar[l].lVal = array[int(current)];
- ++current;
- }
- *pCeltFetched = l;
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset()
-{
- current = 0;
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt)
-{
- current += celt;
- if (current > ULONG(array.size())) {
- current = ULONG(array.size());
- return S_FALSE;
- }
- return S_OK;
-}
-
-#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
-void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface)
-{
- qCDebug(lcQpaAccessibility) << iface << funcName;
-}
-#endif
-
-/**************************************************************\
- * *
- * IUnknown *
- * *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVOID *iface)
-{
- *iface = nullptr;
- const bool result = qWindowsComQueryUnknownInterfaceMulti<IAccessible2>(this, id, iface)
- || qWindowsComQueryInterface<IDispatch>(this, id, iface)
- || qWindowsComQueryInterface<IAccessible>(this, id, iface)
- || qWindowsComQueryInterface<IOleWindow>(this, id, iface);
-
- if (result) {
- qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - "
- << QWindowsAccessibleGuid(id) << ", iface:" << accessibleInterface();
- }
- return result ? S_OK : E_NOINTERFACE;
-}
-
-ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::AddRef()
-{
- return ++ref;
-}
-
-ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::Release()
-{
- if (!--ref) {
- delete this;
- return 0;
- }
- return ref;
-}
-
-
-/*
- IDispatch
-*/
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfoCount(unsigned int * pctinfo)
-{
- // We don't use a type library
- *pctinfo = 0;
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo)
-{
- // We don't use a type library
- *pptinfo = 0;
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid)
-{
-#if !defined(Q_CC_BOR) && !defined(Q_CC_GNU)
- // PROPERTIES: Hierarchical
- if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent"))
- rgdispid[0] = DISPID_ACC_PARENT;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount"))
- rgdispid[0] = DISPID_ACC_CHILDCOUNT;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChild"))
- rgdispid[0] = DISPID_ACC_CHILD;
-
- // PROPERTIES: Descriptional
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accName("))
- rgdispid[0] = DISPID_ACC_NAME;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accValue"))
- rgdispid[0] = DISPID_ACC_VALUE;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription"))
- rgdispid[0] = DISPID_ACC_DESCRIPTION;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accRole"))
- rgdispid[0] = DISPID_ACC_ROLE;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accState"))
- rgdispid[0] = DISPID_ACC_STATE;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp"))
- rgdispid[0] = DISPID_ACC_HELP;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic"))
- rgdispid[0] = DISPID_ACC_HELPTOPIC;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut"))
- rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus"))
- rgdispid[0] = DISPID_ACC_FOCUS;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection"))
- rgdispid[0] = DISPID_ACC_SELECTION;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction"))
- rgdispid[0] = DISPID_ACC_DEFAULTACTION;
-
- // METHODS
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect"))
- rgdispid[0] = DISPID_ACC_SELECT;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation"))
- rgdispid[0] = DISPID_ACC_LOCATION;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate"))
- rgdispid[0] = DISPID_ACC_NAVIGATE;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest"))
- rgdispid[0] = DISPID_ACC_HITTEST;
- else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction"))
- rgdispid[0] = DISPID_ACC_DODEFAULTACTION;
- else
- return DISP_E_UNKNOWNINTERFACE;
-
- return S_OK;
-#else
- Q_UNUSED(rgszNames);
- Q_UNUSED(rgdispid);
-
- return DISP_E_MEMBERNOTFOUND;
-#endif
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember,
- const _GUID &,
- unsigned long,
- unsigned short wFlags,
- tagDISPPARAMS *pDispParams,
- tagVARIANT *pVarResult,
- tagEXCEPINFO *, unsigned int *)
-{
- HRESULT hr = DISP_E_MEMBERNOTFOUND;
-
- switch (dispIdMember)
- {
- case DISPID_ACC_PARENT:
- if (wFlags == DISPATCH_PROPERTYGET) {
- if (!pVarResult)
- return E_INVALIDARG;
- hr = get_accParent(&pVarResult->pdispVal);
- } else {
- hr = DISP_E_MEMBERNOTFOUND;
- }
- break;
-
- case DISPID_ACC_CHILDCOUNT:
- if (wFlags == DISPATCH_PROPERTYGET) {
- if (!pVarResult)
- return E_INVALIDARG;
- hr = get_accChildCount(&pVarResult->lVal);
- } else {
- hr = DISP_E_MEMBERNOTFOUND;
- }
- break;
-
- case DISPID_ACC_CHILD:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_NAME:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else if (wFlags == DISPATCH_PROPERTYPUT)
- hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_VALUE:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else if (wFlags == DISPATCH_PROPERTYPUT)
- hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_DESCRIPTION:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_ROLE:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accRole(pDispParams->rgvarg[0], pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_STATE:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accState(pDispParams->rgvarg[0], pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_HELP:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_HELPTOPIC:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_KEYBOARDSHORTCUT:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_FOCUS:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accFocus(pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_SELECTION:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accSelection(pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_DEFAULTACTION:
- if (wFlags == DISPATCH_PROPERTYGET)
- hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_SELECT:
- if (wFlags == DISPATCH_METHOD)
- hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_LOCATION:
- if (wFlags == DISPATCH_METHOD)
- hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_NAVIGATE:
- if (wFlags == DISPATCH_METHOD)
- hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_HITTEST:
- if (wFlags == DISPATCH_METHOD)
- hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- case DISPID_ACC_DODEFAULTACTION:
- if (wFlags == DISPATCH_METHOD)
- hr = accDoDefaultAction(pDispParams->rgvarg[0]);
- else
- hr = DISP_E_MEMBERNOTFOUND;
- break;
-
- default:
- hr = DISP_E_MEMBERNOTFOUND;
- break;
- }
-
- if (!SUCCEEDED(hr)) {
- return hr;
- }
- return hr;
-}
-
-/*
- IAccessible
-
-IAccessible::accHitTest documents the value returned in pvarID like this:
-
-| *Point location* | *vt member* | *Value member* |
-+========================================================+=============+=========================+
-| Outside of the object's boundaries, and either inside | VT_EMPTY | None. |
-| or outside of the object's bounding rectangle. | | |
-+--------------------------------------------------------+-------------+-------------------------+
-| Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF |
-| child object. | | |
-+--------------------------------------------------------+-------------+-------------------------+
-| Within a child element. | VT_I4 | lVal contains |
-| | | the child ID. |
-+--------------------------------------------------------+-------------+-------------------------+
-| Within a child object. | VT_DISPATCH | pdispVal is set to the |
-| | | child object's IDispatch|
-| | | interface pointer |
-+--------------------------------------------------------+-------------+-------------------------+
-*/
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop),
- QWindowsAccessibility::windowHelper(accessible));
- QAccessibleInterface *child = accessible->childAt(pos.x(), pos.y());
- if (child == 0) {
- // no child found, return this item if it contains the coordinates
- if (accessible->rect().contains(xLeft, yTop)) {
- (*pvarID).vt = VT_I4;
- (*pvarID).lVal = CHILDID_SELF;
- return S_OK;
- }
- } else {
- IAccessible *iface = QWindowsAccessibility::wrap(child);
- if (iface) {
- (*pvarID).vt = VT_DISPATCH;
- (*pvarID).pdispVal = iface;
- return S_OK;
- }
- }
-
- // Did not find anything
- (*pvarID).vt = VT_EMPTY;
- return S_FALSE;
-}
-
-/*
- It is recommended to read
- "Implementing a Microsoft Active Accessibility (MSAA) Server.
- Practical Tips for Developers and How Mozilla Does It"
- (https://developer.mozilla.org/En/Accessibility/Implementing_an_MSAA_Server)
-
- to get an overview of what's important to implement and what parts of MSAA
- can be ignored. All stuff prefixed with "moz" are information from that page.
-*/
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessibleInterface *acc = childPointer(accessible, varID);
- if (!acc || !acc->isValid())
- return E_FAIL;
- const QRect rect = QHighDpi::toNativePixels(acc->rect(),
- QWindowsAccessibility::windowHelper(accessible));
-
- *pxLeft = rect.x();
- *pyTop = rect.y();
- *pcxWidth = rect.width();
- *pcyHeight = rect.height();
-
- return S_OK;
-}
-
-// moz: [important, but no need to implement up/down/left/right]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessibleInterface *acc = 0;
- switch (navDir) {
- case NAVDIR_FIRSTCHILD:
- acc = accessible->child(0);
- break;
- case NAVDIR_LASTCHILD:
- acc = accessible->child(accessible->childCount() - 1);
- break;
- case NAVDIR_NEXT:
- case NAVDIR_PREVIOUS:
- if (!varStart.lVal){
- QAccessibleInterface *parent = accessible->parent();
- if (parent && parent->isValid()) {
- int index = parent->indexOfChild(accessible);
- index += (navDir == NAVDIR_NEXT) ? 1 : -1;
- if (index >= 0 && index < parent->childCount())
- acc = parent->child(index);
- }
- } else {
- int index = varStart.lVal;
- index += (navDir == NAVDIR_NEXT) ? 1 : -1;
- if (index > 0 && index <= accessible->childCount())
- acc = accessible->child(index - 1);
- }
- break;
-
- // Geometrical
- case NAVDIR_UP:
- case NAVDIR_DOWN:
- case NAVDIR_LEFT:
- case NAVDIR_RIGHT: {
- QAccessibleInterface *pIface = accessible->parent();
- if (pIface && pIface->isValid()) {
- const int indexOfOurself = pIface->indexOfChild(accessible);
- QRect startg = accessible->rect();
- QPoint startc = startg.center();
- QAccessibleInterface *candidate = 0;
- unsigned mindist = UINT_MAX; // will work on screen sizes at least up to 46340x46340
- const int sibCount = pIface->childCount();
- for (int i = 0; i < sibCount; ++i) {
- QAccessibleInterface *sibling = 0;
- sibling = pIface->child(i);
- Q_ASSERT(sibling);
- if (i == indexOfOurself || sibling->state().invisible) {
- //ignore ourself and invisible siblings
- continue;
- }
-
- QRect sibg = sibling->rect();
- QPoint sibc = sibg.center();
- QPoint sibp;
- QPoint startp;
- QPoint distp;
- switch (navDir) {
- case NAVDIR_LEFT:
- startp = QPoint(startg.left(), startg.top() + startg.height() / 2);
- sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2);
- if (QPoint(sibc - startc).x() >= 0) {
- continue;
- }
- distp = sibp - startp;
- break;
- case NAVDIR_RIGHT:
- startp = QPoint(startg.right(), startg.top() + startg.height() / 2);
- sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2);
- if (QPoint(sibc - startc).x() <= 0) {
- continue;
- }
- distp = sibp - startp;
- break;
- case NAVDIR_UP:
- startp = QPoint(startg.left() + startg.width() / 2, startg.top());
- sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom());
- if (QPoint(sibc - startc).y() >= 0) {
- continue;
- }
- distp = sibp - startp;
- break;
- case NAVDIR_DOWN:
- startp = QPoint(startg.left() + startg.width() / 2, startg.bottom());
- sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top());
- if (QPoint(sibc - startc).y() <= 0) {
- continue;
- }
- distp = sibp - startp;
- break;
- default:
- break;
- }
-
- // Since we're *comparing* (and not measuring) distances, we can compare the
- // squared distance, (thus, no need to take the sqrt()).
- unsigned dist = distp.x() * distp.x() + distp.y() * distp.y();
- if (dist < mindist) {
- candidate = sibling;
- mindist = dist;
- }
- }
- acc = candidate;
- }
- }
- break;
- default:
- break;
- }
- if (!acc) {
- (*pvarEnd).vt = VT_EMPTY;
- return S_FALSE;
- }
-
- if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
- (*pvarEnd).vt = VT_DISPATCH;
- (*pvarEnd).pdispVal = iface;
- return S_OK;
- }
-
- (*pvarEnd).vt = VT_EMPTY;
- return S_FALSE;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (varChildID.vt != VT_I4)
- return E_INVALIDARG;
-
- QAccessibleInterface *acc = childPointer(accessible, varChildID);
- if (acc && acc->isValid()) {
- *ppdispChild = QWindowsAccessibility::wrap(acc);
- return S_OK;
- }
-
- return E_FAIL;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *pcountChildren = accessible->childCount();
- return S_OK;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessibleInterface *acc = accessible->parent();
- if (acc) {
- if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
- *ppdispParent = iface;
- return S_OK;
- }
- }
-
- *ppdispParent = 0;
- return S_FALSE;
-}
-
-/*
- Properties and methods
-*/
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID)
-{
- Q_UNUSED(varID);
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) {
- const QString def = actionIface->actionNames().value(0);
- if (!def.isEmpty()) {
- actionIface->doAction(def);
- return S_OK;
- }
- }
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
-{
- Q_UNUSED(varID);
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *pszDefaultAction = 0;
- if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) {
- const QString def = actionIface->actionNames().value(0);
- if (!def.isEmpty())
- *pszDefaultAction = QStringToBSTR(def);
- }
- return *pszDefaultAction ? S_OK : S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
-
- QString descr;
- if (varID.lVal) {
- QAccessibleInterface *child = childPointer(accessible, varID);
- if (!child || !child->isValid())
- return E_FAIL;
- descr = child->text(QAccessible::Description);
- } else {
- descr = accessible->text(QAccessible::Description);
- }
- if (descr.size()) {
- *pszDescription = QStringToBSTR(descr);
- return S_OK;
- }
-
- *pszDescription = 0;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QString help;
- if (varID.lVal) {
- QAccessibleInterface *child = childPointer(accessible, varID);
- if (!child || !child->isValid())
- return E_FAIL;
- help = child->text(QAccessible::Help);
- } else {
- help = accessible->text(QAccessible::Help);
- }
- if (help.size()) {
- *pszHelp = QStringToBSTR(help);
- return S_OK;
- }
-
- *pszHelp = 0;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
-{
- return DISP_E_MEMBERNOTFOUND;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
-{
- Q_UNUSED(varID);
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- *pszKeyboardShortcut = 0;
- if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) {
- const QString def = actionIface->actionNames().value(0);
- if (!def.isEmpty()) {
- const QString keyBoardShortCut = actionIface->keyBindingsForAction(def).value(0);
- if (!keyBoardShortCut.isEmpty())
- *pszKeyboardShortcut = QStringToBSTR(keyBoardShortCut);
- }
- }
- return *pszKeyboardShortcut ? S_OK : S_FALSE;
-}
-
-static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAccessible::RelationFlag flag)
-{
- typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationPair;
- QVector<RelationPair> rels = iface->relations(flag);
-
- return rels.value(0).first;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QString name;
- if (varID.lVal) {
- QAccessibleInterface *child = childPointer(accessible, varID);
- if (!child || !child->isValid())
- return E_FAIL;
- name = child->text(QAccessible::Name);
- if (name.isEmpty()) {
- if (QAccessibleInterface *labelInterface = relatedInterface(child, QAccessible::Label)) {
- name = labelInterface->text(QAccessible::Name);
- }
- }
- } else {
- name = accessible->text(QAccessible::Name);
- if (name.isEmpty()) {
- if (QAccessibleInterface *labelInterface = relatedInterface(accessible, QAccessible::Label)) {
- name = labelInterface->text(QAccessible::Name);
- }
- }
- }
-
- QString shortcut = accessible->text(QAccessible::Accelerator);
- if (!shortcut.isEmpty())
- name += QLatin1Char(' ') + shortcut;
-
- if (name.size()) {
- *pszName = QStringToBSTR(name);
- return S_OK;
- }
-
- *pszName = 0;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- return DISP_E_MEMBERNOTFOUND;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessible::Role role;
- if (varID.lVal) {
- QAccessibleInterface *child = childPointer(accessible, varID);
- if (!child || !child->isValid())
- return E_FAIL;
- role = child->role();
- } else {
- role = accessible->role();
- }
-
- if (role != QAccessible::NoRole) {
- if (role >= QAccessible::LayeredPane) {
- // This block should hopefully only be entered if the AT client
- // does not support IAccessible2, since it should prefer IA2::role() then.
- if (role == QAccessible::LayeredPane)
- role = QAccessible::Pane;
- else if (role == QAccessible::WebDocument)
- role = QAccessible::Document;
- else
- role = QAccessible::Client;
- }
- (*pvarRole).vt = VT_I4;
- (*pvarRole).lVal = role;
- } else {
- (*pvarRole).vt = VT_EMPTY;
- }
- return S_OK;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QAccessible::State state;
- if (varID.lVal) {
- QAccessibleInterface *child = childPointer(accessible, varID);
- if (!child || !child->isValid())
- return E_FAIL;
- state = child->state();
- } else {
- state = accessible->state();
- }
-
- LONG st = 0;
- if (state.animated)
- st |= STATE_SYSTEM_ANIMATED;
- if (state.busy)
- st |= STATE_SYSTEM_BUSY;
- if (state.checked)
- st |= STATE_SYSTEM_CHECKED;
- if (state.collapsed)
- st |= STATE_SYSTEM_COLLAPSED;
- if (state.defaultButton)
- st |= STATE_SYSTEM_DEFAULT;
- if (state.expanded)
- st |= STATE_SYSTEM_EXPANDED;
- if (state.extSelectable)
- st |= STATE_SYSTEM_EXTSELECTABLE;
- if (state.focusable)
- st |= STATE_SYSTEM_FOCUSABLE;
- if (state.focused)
- st |= STATE_SYSTEM_FOCUSED;
- if (state.hasPopup)
- st |= STATE_SYSTEM_HASPOPUP;
- if (state.hotTracked)
- st |= STATE_SYSTEM_HOTTRACKED;
- if (state.invisible)
- st |= STATE_SYSTEM_INVISIBLE;
- if (state.linked)
- st |= STATE_SYSTEM_LINKED;
- if (state.marqueed)
- st |= STATE_SYSTEM_MARQUEED;
- if (state.checkStateMixed)
- st |= STATE_SYSTEM_MIXED;
- if (state.movable)
- st |= STATE_SYSTEM_MOVEABLE;
- if (state.multiSelectable)
- st |= STATE_SYSTEM_MULTISELECTABLE;
- if (state.offscreen)
- st |= STATE_SYSTEM_OFFSCREEN;
- if (state.pressed)
- st |= STATE_SYSTEM_PRESSED;
- if (state.passwordEdit)
- st |= STATE_SYSTEM_PROTECTED;
- if (state.readOnly)
- st |= STATE_SYSTEM_READONLY;
- if (state.selectable)
- st |= STATE_SYSTEM_SELECTABLE;
- if (state.selected)
- st |= STATE_SYSTEM_SELECTED;
- if (state.selfVoicing)
- st |= STATE_SYSTEM_SELFVOICING;
- if (state.sizeable)
- st |= STATE_SYSTEM_SIZEABLE;
- if (state.traversed)
- st |= STATE_SYSTEM_TRAVERSED;
- if (state.disabled)
- st |= STATE_SYSTEM_UNAVAILABLE;
-
- (*pvarState).vt = VT_I4;
- (*pvarState).lVal = st;
- return S_OK;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (varID.vt != VT_I4)
- return E_INVALIDARG;
-
- if (!accessible || !accessible->isValid() || varID.lVal) {
- return E_FAIL;
- }
-
- QString value;
- if (accessible->valueInterface()) {
- value = accessible->valueInterface()->currentValue().toString();
- } else {
- value = accessible->text(QAccessible::Value);
- }
- if (!value.isNull()) {
- *pszValue = QStringToBSTR(value);
- return S_OK;
- }
-
- *pszValue = 0;
- qCDebug(lcQpaAccessibility) << "return S_FALSE";
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR value)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
-
- if (!accessible || !accessible->isValid()) {
- return E_FAIL;
- }
-
- QString qstrValue = QString::fromWCharArray(value);
-
- if (accessible->valueInterface()) {
- accessible->valueInterface()->setCurrentValue(qstrValue);
- } else {
- accessible->setText(QAccessible::Value, qstrValue);
- }
-
- return S_OK;
-}
-
-// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VARIANT varID)
-{
- Q_UNUSED(flagsSelect);
- Q_UNUSED(varID);
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- bool res = false;
-
-/*
- ### Check for accessibleTableInterface() or accessibleTextInterface()
-
- ### and if there are no ia2 interfaces we should do nothing??
- if (flagsSelect & SELFLAG_TAKEFOCUS)
- res = accessible()->doAction(SetFocus, varID.lVal, QVariantList());
- if (flagsSelect & SELFLAG_TAKESELECTION) {
- accessible()->doAction(ClearSelection, 0, QVariantList());
- res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList());
- }
- if (flagsSelect & SELFLAG_EXTENDSELECTION)
- res = accessible()->doAction(ExtendSelection, varID.lVal, QVariantList());
- if (flagsSelect & SELFLAG_ADDSELECTION)
- res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList());
- if (flagsSelect & SELFLAG_REMOVESELECTION)
- res = accessible()->doAction(RemoveSelection, varID.lVal, QVariantList());
-*/
- return res ? S_OK : S_FALSE;
-}
-
-/*!
- \internal
- Can return:
-
- +-------------+------------------------------------------------------------------------------+
- | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. |
- +-------------+------------------------------------------------------------------------------+
- | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. |
- +-------------+------------------------------------------------------------------------------+
- | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. |
- +-------------+------------------------------------------------------------------------------+
- | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child |
- | | object that has the keyboard focus. |
- +-------------+------------------------------------------------------------------------------+
- moz: [important]
-*/
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- if (QAccessibleInterface *acc = accessible->focusChild()) {
- if (acc == accessible) {
- (*pvarID).vt = VT_I4;
- (*pvarID).lVal = CHILDID_SELF;
- return S_OK;
- } else {
- if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
- (*pvarID).vt = VT_DISPATCH;
- (*pvarID).pdispVal = iface;
- return S_OK;
- }
- }
- }
- (*pvarID).vt = VT_EMPTY;
- return S_FALSE;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren)
-{
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- int cc = accessible->childCount();
- QVector<int> sel(cc);
- int selIndex = 0;
- for (int i = 0; i < cc; ++i) {
- bool isSelected = false;
- QAccessibleInterface *child = accessible->child(i);
- if (child) {
- isSelected = child->state().selected;
- }
- if (isSelected)
- sel[selIndex++] = i+1;
- }
- sel.resize(selIndex);
- if (sel.isEmpty()) {
- (*pvarChildren).vt = VT_EMPTY;
- return S_FALSE;
- }
- if (sel.size() == 1) {
- (*pvarChildren).vt = VT_I4;
- (*pvarChildren).lVal = sel[0];
- return S_OK;
- }
- IEnumVARIANT *iface = new QWindowsEnumerate(sel);
- IUnknown *uiface;
- iface->QueryInterface(IID_IUnknown, (void**)&uiface);
- (*pvarChildren).vt = VT_UNKNOWN;
- (*pvarChildren).punkVal = uiface;
-
- return S_OK;
-}
-
-/**************************************************************\
- * IOleWindow *
- **************************************************************/
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd)
-{
- *phwnd = 0;
- QAccessibleInterface *accessible = accessibleInterface();
- accessibleDebugClientCalls(accessible);
- if (!accessible)
- return E_FAIL;
-
- QWindow *window = QWindowsAccessibility::windowHelper(accessible);
- if (!window)
- return E_FAIL;
-
- QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
- Q_ASSERT(platform);
- *phwnd = (HWND)platform->nativeResourceForWindow("handle", window);
- qCDebug(lcQpaAccessibility) << "QWindowsAccessible::GetWindow(): " << *phwnd;
- return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL)
-{
- return S_OK;
-}
-
-const char *QWindowsAccessibleGuid::iidToString(const GUID &id)
-{
- const char *result = nullptr;
- if (id == IID_IUnknown)
- result = "IID_IUnknown";
- else if (id == IID_IDispatch)
- result = "IID_IDispatch";
- else if (id == IID_IAccessible)
- result = "IID_IAccessible";
- else if (id == IID_IOleWindow)
- result = "IID_IOleWindow";
- else if (id == IID_IServiceProvider)
- result = "IID_IServiceProvider";
- else if (id == IID_IAccessible2)
- result = "IID_IAccessible2";
- else if (id == IID_IAccessibleAction)
- result = "IID_IAccessibleAction";
- else if (id == IID_IAccessibleApplication)
- result = "IID_IAccessibleApplication";
- else if (id == IID_IAccessibleComponent)
- result = "IID_IAccessibleComponent";
- else if (id == IID_IAccessibleEditableText)
- result = "IID_IAccessibleEditableText";
- else if (id == IID_IAccessibleHyperlink)
- result = "IID_IAccessibleHyperlink";
- else if (id == IID_IAccessibleHypertext)
- result = "IID_IAccessibleHypertext";
- else if (id == IID_IAccessibleImage)
- result = "IID_IAccessibleImage";
- else if (id == IID_IAccessibleRelation)
- result = "IID_IAccessibleRelation";
- else if (id == IID_IAccessibleTable)
- result = "IID_IAccessibleTable";
- else if (id == IID_IAccessibleTable2)
- result = "IID_IAccessibleTable2";
- else if (id == IID_IAccessibleTableCell)
- result = "IID_IAccessibleTableCell";
- else if (id == IID_IAccessibleText)
- result = "IID_IAccessibleText";
- else if (id == IID_IAccessibleValue)
- result = "IID_IAccessibleValue";
- return result;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug, const GUID &);
-
-QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- if (const char *ids = QWindowsAccessibleGuid::iidToString(aguid.guid()))
- d << ids;
- else
- d << aguid.guid();
- return d;
-}
-#endif // !QT_NO_DEBUG_STREAM
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
deleted file mode 100644
index 5380fc2411..0000000000
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QWINDOWSMSAAACCESSIBLE_H
-#define QWINDOWSMSAAACCESSIBLE_H
-
-#include <QtCore/qglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
-
-#include <QtCore/qt_windows.h>
-#include <QtCore/qsharedpointer.h>
-#include <QtGui/qaccessible.h>
-#include <oleacc.h>
-#include "ia2_api_all.h" // IAccessible2 inherits from IAccessible
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_DEBUG_OUTPUT
-#define DEBUG_SHOW_ATCLIENT_COMMANDS
-#endif
-#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
-void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface);
-# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface)
-#else
-# define accessibleDebugClientCalls(iface)
-#endif
-
-QWindow *window_helper(const QAccessibleInterface *iface);
-
-class QWindowsAccessibleGuid // Helper for QDebug, outputs known ids by name.
-{
-public:
- explicit QWindowsAccessibleGuid(const GUID &g) : m_guid(g) {}
- GUID guid () const { return m_guid; }
- static const char *iidToString(const GUID &id);
-
-private:
- GUID m_guid;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid);
-#endif
-
-/**************************************************************\
- * QWindowsAccessible *
- **************************************************************/
-
-class QWindowsMsaaAccessible : public IAccessible2, public IOleWindow
-{
-public:
- QWindowsMsaaAccessible(QAccessibleInterface *a)
- : ref(0)
- {
- id = QAccessible::uniqueId(a);
- }
-
- virtual ~QWindowsMsaaAccessible()
- {
- }
-
- /* IUnknown */
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- /* IDispatch */
- HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *);
- HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **);
- HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *);
- HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *);
-
- /* IAccessible */
- HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID);
- HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID);
- HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd);
- HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild);
- HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren);
- HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent);
-
- HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID);
- HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction);
- HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription);
- HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp);
- HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic);
- HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut);
- HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName);
- HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName);
- HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole);
- HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState);
- HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue);
- HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue);
-
- HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID);
- HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID);
- HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren);
-
- /* IOleWindow */
- HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
- HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
-
-protected:
- QAccessible::Id id;
-
- QAccessibleInterface *accessibleInterface() const
- {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(id);
- if (iface && iface->isValid())
- return iface;
- return 0;
- }
-
- static QAccessibleInterface *childPointer(QAccessibleInterface *parent, VARIANT varID)
- {
- // -1 since windows API always uses 1 for the first child
- Q_ASSERT(parent);
-
- QAccessibleInterface *acc = 0;
- int childIndex = varID.lVal;
- if (childIndex == 0) {
- // Yes, some AT clients (Active Accessibility Object Inspector)
- // actually ask for the same object. As a consequence, we need to clone ourselves:
- acc = parent;
- } else if (childIndex < 0) {
- acc = QAccessible::accessibleInterface((QAccessible::Id)childIndex);
- } else {
- acc = parent->child(childIndex - 1);
- }
- return acc;
- }
-
-private:
- ULONG ref;
-
-};
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_ACCESSIBILITY
-
-#endif // QWINDOWSMSAAACCESSIBLE_H
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index 12cccd124b..ac6a34d7c2 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -40,6 +40,7 @@
#include "qwin10helpers.h"
#include <QtCore/QDebug>
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/private/qsystemlibrary_p.h>
#if defined(Q_CC_MINGW)
@@ -115,7 +116,7 @@ static QWindowsComBaseDLL baseComDll;
bool QWindowsComBaseDLL::init()
{
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10 && !isValid()) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10 && !isValid()) {
QSystemLibrary library(QStringLiteral("combase"));
roGetActivationFactory =
reinterpret_cast<RoGetActivationFactory>(library.resolve("RoGetActivationFactory"));
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 49c7144221..80872c3ea3 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -93,7 +93,7 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
// Windows with alpha: Use blend function to update.
QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()),
- static_cast<const QWindow *>(Q_NULLPTR)));
+ static_cast<const QWindow *>(nullptr)));
QRect dirtyRect = br.translated(offset + frameOffset);
SIZE size = {r.width(), r.height()};
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 9912e03cb9..c146f8ec25 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -53,7 +53,7 @@
#include "qwindowstheme.h"
#include <private/qguiapplication_p.h>
#ifndef QT_NO_ACCESSIBILITY
-# include "accessible/qwindowsaccessibility.h"
+# include "uiautomation/qwindowsuiaaccessibility.h"
#endif
#if QT_CONFIG(sessionmanager)
# include <private/qsessionmanager_p.h>
@@ -98,6 +98,7 @@ Q_LOGGING_CATEGORY(lcQpaDialogs, "qt.qpa.dialogs")
Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus")
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility")
+Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
int QWindowsContext::verbose = 0;
@@ -193,26 +194,14 @@ void QWindowsUser32DLL::init()
getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10) { // Appears in 10.0.14393, October 2016
+ if (QOperatingSystemVersion::current()
+ >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
}
}
-bool QWindowsUser32DLL::initTouch()
-{
- if (!isTouchWindow && QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
- QSystemLibrary library(QStringLiteral("user32"));
- isTouchWindow = (IsTouchWindow)(library.resolve("IsTouchWindow"));
- registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
- unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow"));
- getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
- closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
- }
- return isTouchWindow && registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle;
-}
-
void QWindowsShcoreDLL::init()
{
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
@@ -269,7 +258,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
QWindowsContext::user32dll.init();
QWindowsContext::shcoredll.init();
- if (m_mouseHandler.touchDevice() && QWindowsContext::user32dll.initTouch())
+ if (m_mouseHandler.touchDevice())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
m_displayContext = GetDC(0);
m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY);
@@ -327,11 +316,6 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
if (!touchDevice)
return false;
- if (!QWindowsContext::user32dll.initTouch()) {
- delete touchDevice;
- return false;
- }
-
if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
@@ -454,7 +438,7 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
// QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage.
if (w->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC))
style |= CS_OWNDC;
- if (!(flags & Qt::NoDropShadowWindowHint) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)
+ if (!(flags & Qt::NoDropShadowWindowHint)
&& (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
style |= CS_DROPSHADOW;
}
@@ -757,7 +741,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
// present in the MSVCRT.DLL found on Windows XP (QTBUG-35617).
static inline QString errorMessageFromComError(const _com_error &comError)
{
- TCHAR *message = Q_NULLPTR;
+ TCHAR *message = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, DWORD(comError.Error()), MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
message, 0, NULL);
@@ -872,7 +856,7 @@ static inline bool resizeOnDpiChanged(const QWindow *w)
static bool shouldHaveNonClientDpiScaling(const QWindow *window)
{
- return QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10
+ return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
&& window->isTopLevel()
&& !window->property(QWindowsWindow::embeddedNativeParentHandleProperty).isValid()
#if QT_CONFIG(opengl) // /QTBUG-62901, EnableNonClientDpiScaling has problems with GL
@@ -974,7 +958,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return false;
case QtWindows::AccessibleObjectFromWindowRequest:
#ifndef QT_NO_ACCESSIBILITY
- return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result);
+ return QWindowsUiaAccessibility::handleWmGetObject(hwnd, wParam, lParam, result);
#else
return false;
#endif
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 5c39b6068b..f2ec307be2 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -66,6 +66,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaDialogs)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMenus)
Q_DECLARE_LOGGING_CATEGORY(lcQpaTablet)
Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation)
Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon)
class QWindow;
@@ -84,13 +85,7 @@ class QTouchDevice;
struct QWindowsUser32DLL
{
inline void init();
- inline bool initTouch();
- typedef BOOL (WINAPI *IsTouchWindow)(HWND, PULONG); // Windows 7
- typedef BOOL (WINAPI *RegisterTouchWindow)(HWND, ULONG);
- typedef BOOL (WINAPI *UnregisterTouchWindow)(HWND);
- typedef BOOL (WINAPI *GetTouchInputInfo)(HANDLE, UINT, PVOID, int);
- typedef BOOL (WINAPI *CloseTouchInputHandle)(HANDLE);
typedef BOOL (WINAPI *SetProcessDPIAware)();
typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
@@ -100,13 +95,6 @@ struct QWindowsUser32DLL
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
- // Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC).
- IsTouchWindow isTouchWindow = nullptr;
- RegisterTouchWindow registerTouchWindow = nullptr;
- UnregisterTouchWindow unregisterTouchWindow = nullptr;
- GetTouchInputInfo getTouchInputInfo = nullptr;
- CloseTouchInputHandle closeTouchInputHandle = nullptr;
-
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware = nullptr;
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 1da7de7451..e1a5837201 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -184,7 +184,7 @@ static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1)
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
}
-static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR)
+static QSize systemCursorSize(const QPlatformScreen *screen = nullptr)
{
const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR));
if (screen) {
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 28c7e88a6e..4772f3fce5 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -70,7 +70,7 @@ class CursorHandle
{
Q_DISABLE_COPY(CursorHandle)
public:
- explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {}
+ explicit CursorHandle(HCURSOR hcursor = nullptr) : m_hcursor(hcursor) {}
~CursorHandle()
{
if (m_hcursor)
@@ -113,9 +113,9 @@ public:
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
- static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR);
+ static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
- static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR);
+ static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
static QPoint mousePosition();
static CursorState cursorState();
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index bc78f5054b..70ee708b61 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -601,8 +601,8 @@ QString QWindowsShellItem::path() const
{
if (isFileSystem())
return QDir::cleanPath(QWindowsShellItem::displayName(m_item, SIGDN_FILESYSPATH));
- // Check for a "Library" item (Windows 7)
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7 && isDir())
+ // Check for a "Library" item
+ if (isDir())
return QWindowsShellItem::libraryItemDefaultSaveFolder(m_item);
return QString();
}
@@ -713,7 +713,7 @@ QString QWindowsShellItem::libraryItemDefaultSaveFolder(IShellItem *item)
{
QString result;
if (IShellLibrary *library = sHLoadLibraryFromItem(item, STGM_READ | STGM_SHARE_DENY_WRITE)) {
- IShellItem *item = Q_NULLPTR;
+ IShellItem *item = nullptr;
if (SUCCEEDED(library->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem, reinterpret_cast<void **>(&item)))) {
result = QDir::cleanPath(QWindowsShellItem::displayName(item, SIGDN_FILESYSPATH));
item->Release();
@@ -895,7 +895,7 @@ void QWindowsNativeFileDialogBase::setWindowTitle(const QString &title)
IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
{
if (url.isLocalFile()) {
- IShellItem *result = Q_NULLPTR;
+ IShellItem *result = nullptr;
const QString native = QDir::toNativeSeparators(url.toLocalFile());
const HRESULT hr =
SHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()),
@@ -903,30 +903,30 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
reinterpret_cast<void **>(&result));
if (FAILED(hr)) {
qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
- return Q_NULLPTR;
+ return nullptr;
}
return result;
} else if (url.scheme() == QLatin1String("clsid")) {
// Support for virtual folders via GUID
// (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx)
// specified as "clsid:<GUID>" (without '{', '}').
- IShellItem *result = Q_NULLPTR;
+ IShellItem *result = nullptr;
const auto uuid = QUuid::fromString(url.path());
if (uuid.isNull()) {
qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
- return Q_NULLPTR;
+ return nullptr;
}
PIDLIST_ABSOLUTE idList;
HRESULT hr = SHGetKnownFolderIDList(uuid, 0, 0, &idList);
if (FAILED(hr)) {
qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
- return Q_NULLPTR;
+ return nullptr;
}
hr = SHCreateItemFromIDList(idList, IID_IShellItem, reinterpret_cast<void **>(&result));
CoTaskMemFree(idList);
if (FAILED(hr)) {
qErrnoWarning("%s: SHCreateItemFromIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
- return Q_NULLPTR;
+ return nullptr;
}
return result;
} else {
@@ -2047,7 +2047,7 @@ bool useHelper(QPlatformTheme::DialogType type)
return false;
switch (type) {
case QPlatformTheme::FileDialog:
- return QSysInfo::windowsVersion() >= QSysInfo::WV_XP;
+ return true;
case QPlatformTheme::ColorDialog:
#ifdef USE_NATIVE_COLOR_DIALOG
return true;
@@ -2068,13 +2068,10 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type)
if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs)
return 0;
switch (type) {
- case QPlatformTheme::FileDialog: // Note: "Windows XP Professional x64 Edition has version number WV_5_2 (WV_2003).
- if (QWindowsIntegration::instance()->options() & QWindowsIntegration::XpNativeDialogs
- || QSysInfo::windowsVersion() <= QSysInfo::WV_2003) {
+ case QPlatformTheme::FileDialog:
+ if (QWindowsIntegration::instance()->options() & QWindowsIntegration::XpNativeDialogs)
return new QWindowsXpFileDialogHelper();
- }
- if (QSysInfo::windowsVersion() > QSysInfo::WV_2003)
- return new QWindowsFileDialogHelper();
+ return new QWindowsFileDialogHelper;
case QPlatformTheme::ColorDialog:
#ifdef USE_NATIVE_COLOR_DIALOG
return new QWindowsColorDialogHelper();
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 47878a7169..3e5f2c81d5 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -95,7 +95,7 @@ struct QWindowsLibGLESv2
#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
void *moduleHandle() const { return m_lib; }
#else
- void *moduleHandle() const { return Q_NULLPTR; }
+ void *moduleHandle() const { return nullptr; }
#endif
const GLubyte * (APIENTRY * glGetString)(GLenum name);
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 78368d87de..4bdf3167e4 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -379,9 +379,7 @@ static PIXELFORMATDESCRIPTOR
initPixelFormatDescriptor(&pfd);
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
- pfd.dwFlags = PFD_SUPPORT_OPENGL;
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
- pfd.dwFlags = PFD_SUPPORT_COMPOSITION;
+ pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION;
const bool isPixmap = (additional.formatFlags & QWindowsGLRenderToPixmap) != 0;
pfd.dwFlags |= isPixmap ? PFD_DRAW_TO_BITMAP : PFD_DRAW_TO_WINDOW;
if (!(additional.formatFlags & QWindowsGLDirectRendering))
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 8c228f588e..b9dd2c557e 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -221,6 +221,28 @@ void QWindowsInputContext::setFocusObject(QObject *)
updateEnabled();
}
+HWND QWindowsInputContext::getVirtualKeyboardWindowHandle() const
+{
+ return ::FindWindowA("IPTip_Main_Window", nullptr);
+}
+
+QRectF QWindowsInputContext::keyboardRect() const
+{
+ if (HWND hwnd = getVirtualKeyboardWindowHandle()) {
+ RECT rect;
+ if (::GetWindowRect(hwnd, &rect)) {
+ return QRectF(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+ return QRectF();
+}
+
+bool QWindowsInputContext::isInputPanelVisible() const
+{
+ HWND hwnd = getVirtualKeyboardWindowHandle();
+ return hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd);
+}
+
void QWindowsInputContext::updateEnabled()
{
if (!QGuiApplication::focusObject())
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 617ef30cef..ada1fc0d29 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -79,6 +79,9 @@ public:
void invokeAction(QInputMethod::Action, int cursorPosition) override;
void setFocusObject(QObject *object) override;
+ QRectF keyboardRect() const override;
+ bool isInputPanelVisible() const override;
+
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
bool endComposition(HWND hwnd);
@@ -98,6 +101,7 @@ private:
void startContextComposition();
void endContextComposition();
void updateEnabled();
+ HWND getVirtualKeyboardWindowHandle() const;
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 f9bac3920b..287b65cd5d 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -60,7 +60,7 @@
#include "qwindowsinputcontext.h"
#include "qwindowskeymapper.h"
#ifndef QT_NO_ACCESSIBILITY
-# include "accessible/qwindowsaccessibility.h"
+# include "uiautomation/qwindowsuiaaccessibility.h"
#endif
#include <qpa/qplatformnativeinterface.h>
@@ -151,7 +151,7 @@ struct QWindowsIntegrationPrivate
#endif // QT_NO_OPENGL
QScopedPointer<QPlatformInputContext> m_inputContext;
#ifndef QT_NO_ACCESSIBILITY
- QWindowsAccessibility m_accessibility;
+ QWindowsUiaAccessibility m_accessibility;
#endif
QWindowsServices m_services;
};
@@ -252,7 +252,7 @@ QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
delete m_fontDatabase;
}
-QWindowsIntegration *QWindowsIntegration::m_instance = Q_NULLPTR;
+QWindowsIntegration *QWindowsIntegration::m_instance = nullptr;
QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
d(new QWindowsIntegrationPrivate(paramList))
@@ -266,7 +266,7 @@ QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
QWindowsIntegration::~QWindowsIntegration()
{
- m_instance = Q_NULLPTR;
+ m_instance = nullptr;
}
void QWindowsIntegration::initialize()
@@ -336,7 +336,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
<< " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n';
if (Q_UNLIKELY(!obtained.hwnd))
- return Q_NULLPTR;
+ return nullptr;
QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
Q_ASSERT(result);
@@ -356,7 +356,7 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n
}
QWindowsForeignWindow *result = new QWindowsForeignWindow(window, hwnd);
const QRect obtainedGeometry = result->geometry();
- QScreen *screen = Q_NULLPTR;
+ QScreen *screen = nullptr;
if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
screen = pScreen->screen();
if (screen && screen != window->screen())
@@ -402,7 +402,7 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL.");
if (QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DesktopGl)
return QOpenGLStaticContext::create();
- return Q_NULLPTR;
+ return nullptr;
default:
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 9544fb81f7..814291c54a 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -56,37 +56,6 @@
#include <windowsx.h>
-/* Touch is supported from Windows 7 onwards and data structures
- * are present in the Windows SDK's, but not in older MSVC Express
- * versions. */
-
-#if !defined(TOUCHEVENTF_MOVE)
-
-typedef struct tagTOUCHINPUT {
- LONG x;
- LONG y;
- HANDLE hSource;
- DWORD dwID;
- DWORD dwFlags;
- DWORD dwMask;
- DWORD dwTime;
- ULONG_PTR dwExtraInfo;
- DWORD cxContact;
- DWORD cyContact;
-} TOUCHINPUT, *PTOUCHINPUT;
-typedef TOUCHINPUT const * PCTOUCHINPUT;
-
-# define TOUCHEVENTF_MOVE 0x0001
-# define TOUCHEVENTF_DOWN 0x0002
-# define TOUCHEVENTF_UP 0x0004
-# define TOUCHEVENTF_INRANGE 0x0008
-# define TOUCHEVENTF_PRIMARY 0x0010
-# define TOUCHEVENTF_NOCOALESCE 0x0020
-# define TOUCHEVENTF_PALM 0x0080
-# define TOUCHINPUTMASKF_CONTACTAREA 0x0004
-# define TOUCHINPUTMASKF_EXTRAINFO 0x0002
-#endif // if !defined(TOUCHEVENTF_MOVE)
-
QT_BEGIN_NAMESPACE
static inline void compressMouseMove(MSG *msg)
@@ -154,8 +123,6 @@ static inline QTouchDevice *createTouchDevice()
QT_NID_INTEGRATED_TOUCH = 0x1, QT_NID_EXTERNAL_TOUCH = 0x02,
QT_NID_MULTI_INPUT = 0x40, QT_NID_READY = 0x80 };
- if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7)
- return 0;
const int digitizers = GetSystemMetrics(QT_SM_DIGITIZER);
if (!(digitizers & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH)))
return 0;
@@ -523,9 +490,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
touchPoints.reserve(winTouchPointCount);
Qt::TouchPointStates allStates = 0;
- QWindowsContext::user32dll.getTouchInputInfo(reinterpret_cast<HANDLE>(msg.lParam),
- UINT(msg.wParam),
- winTouchInputs.data(), sizeof(TOUCHINPUT));
+ GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam),
+ UINT(msg.wParam), winTouchInputs.data(), sizeof(TOUCHINPUT));
for (int i = 0; i < winTouchPointCount; ++i) {
const TOUCHINPUT &winTouchInput = winTouchInputs[i];
int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
@@ -566,7 +532,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
touchPoints.append(touchPoint);
}
- QWindowsContext::user32dll.closeTouchInputHandle(reinterpret_cast<HANDLE>(msg.lParam));
+ CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(msg.lParam));
// all touch points released, forget the ids we've seen, they may not be reused
if (allStates == Qt::TouchPointReleased)
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index dc8e97c886..324b00144e 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -134,7 +134,7 @@ void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resourc
return static_cast<const QWindowsCursor *>(pCursor)->hCursor(cursor);
}
}
- return Q_NULLPTR;
+ return nullptr;
}
#endif // !QT_NO_CURSOR
@@ -280,7 +280,7 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
else if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
return QFunctionPointer(QWindowsNativeInterface::isTabletMode);
- return Q_NULLPTR;
+ return nullptr;
}
QVariant QWindowsNativeInterface::gpu() const
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index cfddb3cc71..c0781df973 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -563,7 +563,7 @@ const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const
if (scr->geometry().contains(p))
return scr;
}
- return Q_NULLPTR;
+ return nullptr;
}
const QWindowsScreen *QWindowsScreenManager::screenForHwnd(HWND hwnd) const
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 1d81fa9cd5..854c19ccf8 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -37,6 +37,13 @@
**
****************************************************************************/
+#if defined(WINVER) && WINVER < 0x0601
+# undef WINVER
+#endif
+#if !defined(WINVER)
+# define WINVER 0x0601 // Enable touch functions for MinGW
+#endif
+
#include "qwindowswindow.h"
#include "qwindowscontext.h"
#if QT_CONFIG(draganddrop)
@@ -858,7 +865,7 @@ QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w)
if (QPlatformWindow *pw = w->handle())
return static_cast<QWindowsBaseWindow *>(pw);
}
- return Q_NULLPTR;
+ return nullptr;
}
HWND QWindowsBaseWindow::handleOf(const QWindow *w)
@@ -1113,7 +1120,7 @@ QWindowsWindow::~QWindowsWindow()
{
setFlag(WithinDestroy);
if (testFlag(TouchRegistered))
- QWindowsContext::user32dll.unregisterTouchWindow(m_data.hwnd);
+ UnregisterTouchWindow(m_data.hwnd);
destroyWindow();
destroyIcon();
}
@@ -2064,9 +2071,17 @@ void QWindowsWindow::propagateSizeHints()
bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins)
{
+ WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
+ if ((windowPos->flags & SWP_NOZORDER) == 0) {
+ if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
+ QWindow *parentWindow = qWindow->parent();
+ HWND parentHWND = GetAncestor(windowPos->hwnd, GA_PARENT);
+ HWND desktopHWND = GetDesktopWindow();
+ platformWindow->m_data.embedded = !parentWindow && parentHWND && (parentHWND != desktopHWND);
+ }
+ }
if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
return false;
- WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
if ((windowPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE)))
return false;
const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
@@ -2600,12 +2615,12 @@ void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTou
if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)
&& !testFlag(TouchRegistered)) {
ULONG touchFlags = 0;
- const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags);
+ const bool ret = IsTouchWindow(m_data.hwnd, &touchFlags);
// Return if it is not a touch window or the flags are already set by a hook
// such as HCBT_CREATEWND
if (ret || touchFlags != 0)
return;
- if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, ULONG(touchTypes)))
+ if (RegisterTouchWindow(m_data.hwnd, ULONG(touchTypes)))
setFlag(TouchRegistered);
else
qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName()));
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
new file mode 100644
index 0000000000..907883bf5b
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiaaccessibility.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QWindow>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/qt_windows.h>
+#include <qpa/qplatformintegration.h>
+#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaAccessibility::QWindowsUiaAccessibility()
+{
+}
+
+QWindowsUiaAccessibility::~QWindowsUiaAccessibility()
+{
+}
+
+// Handles UI Automation window messages.
+bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
+{
+ if (lParam == LPARAM(UiaRootObjectId)) {
+
+ // Start handling accessibility internally
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+
+ // Ignoring all requests while starting up / shutting down
+ if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
+ return false;
+
+ if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
+ if (QAccessibleInterface *accessible = window->accessibleRoot()) {
+ QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
+ *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Handles accessibility update notifications.
+void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+ if (!event)
+ return;
+
+ QAccessibleInterface *accessible = event->accessibleInterface();
+ if (!isActive() || !accessible || !accessible->isValid())
+ return;
+
+ // Ensures QWindowsUiaWrapper is properly initialized.
+ if (!QWindowsUiaWrapper::instance()->ready())
+ return;
+
+ // No need to do anything when nobody is listening.
+ if (!QWindowsUiaWrapper::instance()->clientsAreListening())
+ return;
+
+ switch (event->type()) {
+
+ case QAccessible::Focus:
+ QWindowsUiaMainProvider::notifyFocusChange(event);
+ break;
+
+ case QAccessible::StateChanged:
+ QWindowsUiaMainProvider::notifyStateChange(static_cast<QAccessibleStateChangeEvent *>(event));
+ break;
+
+ case QAccessible::ValueChanged:
+ QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
+ break;
+
+ case QAccessible::TextAttributeChanged:
+ case QAccessible::TextColumnChanged:
+ case QAccessible::TextInserted:
+ case QAccessible::TextRemoved:
+ case QAccessible::TextUpdated:
+ case QAccessible::TextSelectionChanged:
+ case QAccessible::TextCaretMoved:
+ QWindowsUiaMainProvider::notifyTextChange(event);
+ break;
+
+ default:
+ break;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
index 8621e93120..bbb81d596b 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -37,27 +37,29 @@
**
****************************************************************************/
-#ifndef QWINDOWSACCESSIBILITY_H
-#define QWINDOWSACCESSIBILITY_H
+#ifndef QWINDOWSUIAACCESSIBILITY_H
+#define QWINDOWSUIAACCESSIBILITY_H
-#include "../qtwindowsglobal.h"
-#include "../qwindowscontext.h"
-#include <qpa/qplatformaccessibility.h>
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
-#include <oleacc.h>
+#include "qwindowscontext.h"
+#include <qpa/qplatformaccessibility.h>
QT_BEGIN_NAMESPACE
-class QWindowsAccessibility : public QPlatformAccessibility
+// Windows plataform accessibility implemented over UI Automation.
+class QWindowsUiaAccessibility : public QPlatformAccessibility
{
public:
- QWindowsAccessibility();
- static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
+ explicit QWindowsUiaAccessibility();
+ virtual ~QWindowsUiaAccessibility();
+ static bool handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
- static IAccessible *wrap(QAccessibleInterface *acc);
- static QWindow *windowHelper(const QAccessibleInterface *iface);
};
QT_END_NAMESPACE
-#endif // QWINDOWSACCESSIBILITY_H
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAACCESSIBILITY_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
new file mode 100644
index 0000000000..1e1fc49c0f
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaBaseProvider::QWindowsUiaBaseProvider(QAccessible::Id id) :
+ m_id(id)
+{
+}
+
+QWindowsUiaBaseProvider::~QWindowsUiaBaseProvider()
+{
+}
+
+QAccessibleInterface *QWindowsUiaBaseProvider::accessibleInterface() const
+{
+ QAccessibleInterface *accessible = QAccessible::accessibleInterface(m_id);
+ if (accessible && accessible->isValid())
+ return accessible;
+ return nullptr;
+}
+
+QAccessible::Id QWindowsUiaBaseProvider::id() const
+{
+ return m_id;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
new file mode 100644
index 0000000000..3ae403e8c5
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIABASEPROVIDER_H
+#define QWINDOWSUIABASEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QPointer>
+
+#include <qwindowscombase.h>
+#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAccessibleInterface;
+class QDebug;
+
+// Base class for UI Automation providers.
+class QWindowsUiaBaseProvider : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWindowsUiaBaseProvider)
+public:
+ explicit QWindowsUiaBaseProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaBaseProvider();
+
+ QAccessibleInterface *accessibleInterface() const;
+ QAccessible::Id id() const;
+
+private:
+ QAccessible::Id m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIABASEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
new file mode 100644
index 0000000000..e0502c00f3
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiagriditemprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaGridItemProvider::QWindowsUiaGridItemProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaGridItemProvider::~QWindowsUiaGridItemProvider()
+{
+}
+
+// Returns the row index of the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_Row(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableCellInterface->rowIndex();
+ return S_OK;
+}
+
+// Returns the column index of the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_Column(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableCellInterface->columnIndex();
+ return S_OK;
+}
+
+// Returns the number of rows occupied by the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_RowSpan(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableCellInterface->rowExtent();
+ return S_OK;
+}
+
+// Returns the number of columns occupied by the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ColumnSpan(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableCellInterface->columnExtent();
+ return S_OK;
+}
+
+// Returns the provider for the cointaining table/tree.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (QAccessibleInterface *table = tableCellInterface->table()) {
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(table);
+ }
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
new file mode 100644
index 0000000000..a93b50ef97
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAGRIDITEMPROVIDER_H
+#define QWINDOWSUIAGRIDITEMPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Grid Item control pattern provider. Used by items within a table/tree.
+class QWindowsUiaGridItemProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IGridItemProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaGridItemProvider)
+public:
+ explicit QWindowsUiaGridItemProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaGridItemProvider();
+
+ // IGridItemProvider
+ HRESULT STDMETHODCALLTYPE get_Row(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_Column(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_RowSpan(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_ColumnSpan(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_ContainingGrid(IRawElementProviderSimple **pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAGRIDITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
new file mode 100644
index 0000000000..65c2df703b
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiagridprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaGridProvider::QWindowsUiaGridProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaGridProvider::~QWindowsUiaGridProvider()
+{
+}
+
+// Returns the provider for an item within a table/tree.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column, IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+ if (!tableInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) {
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell);
+ }
+ }
+ return S_OK;
+}
+
+// Returns the number of rows.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::get_RowCount(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+ if (!tableInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableInterface->rowCount();
+ return S_OK;
+}
+
+// Returns the number of columns.
+HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::get_ColumnCount(int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+ if (!tableInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = tableInterface->columnCount();
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
new file mode 100644
index 0000000000..15521f98b3
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAGRIDPROVIDER_H
+#define QWINDOWSUIAGRIDPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Grid control pattern provider. Used by tables/trees.
+class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IGridProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaGridProvider)
+public:
+ explicit QWindowsUiaGridProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaGridProvider();
+
+ // IGridProvider
+ HRESULT STDMETHODCALLTYPE GetItem(int row, int column, IRawElementProviderSimple **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_RowCount(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_ColumnCount(int *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAGRIDPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
new file mode 100644
index 0000000000..2af883c4f6
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiainvokeprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaInvokeProvider::QWindowsUiaInvokeProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaInvokeProvider::~QWindowsUiaInvokeProvider()
+{
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaInvokeProvider::Invoke()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
new file mode 100644
index 0000000000..2b8a646983
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAINVOKEPROVIDER_H
+#define QWINDOWSUIAINVOKEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Invoke control pattern provider.
+class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IInvokeProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaInvokeProvider)
+public:
+ explicit QWindowsUiaInvokeProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaInvokeProvider();
+
+ // IInvokeProvider
+ HRESULT STDMETHODCALLTYPE Invoke();
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAINVOKEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
new file mode 100644
index 0000000000..46f73f81a0
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -0,0 +1,638 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiavalueprovider.h"
+#include "qwindowsuiarangevalueprovider.h"
+#include "qwindowsuiatextprovider.h"
+#include "qwindowsuiatoggleprovider.h"
+#include "qwindowsuiainvokeprovider.h"
+#include "qwindowsuiaselectionprovider.h"
+#include "qwindowsuiaselectionitemprovider.h"
+#include "qwindowsuiatableprovider.h"
+#include "qwindowsuiatableitemprovider.h"
+#include "qwindowsuiagridprovider.h"
+#include "qwindowsuiagriditemprovider.h"
+#include "qwindowscombase.h"
+#include "qwindowscontext.h"
+#include "qwindowsuiautils.h"
+#include "qwindowsuiaprovidercache.h"
+
+#include <QtCore/QDebug>
+#include <QtGui/QAccessible>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+
+#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
+#include <comdef.h>
+#endif
+
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+// Returns a cached instance of the provider for a specific acessible interface.
+QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
+{
+ if (!accessible)
+ return nullptr;
+
+ QAccessible::Id id = QAccessible::uniqueId(accessible);
+ QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
+ QWindowsUiaMainProvider *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(id));
+
+ if (provider) {
+ provider->AddRef();
+ } else {
+ provider = new QWindowsUiaMainProvider(accessible);
+ providerCache->insert(id, provider);
+ }
+ return provider;
+}
+
+QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount)
+ : QWindowsUiaBaseProvider(QAccessible::uniqueId(a)),
+ m_ref(initialRefCount)
+{
+}
+
+QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
+{
+}
+
+void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
+ }
+ }
+}
+
+void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (event->changedStates().checked || event->changedStates().checkStateMixed) {
+ // Notifies states changes in checkboxes.
+ if (accessible->role() == QAccessible::CheckBox) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ int toggleState = ToggleState_Off;
+ if (accessible->state().checked)
+ toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
+ setVariantI4(toggleState, &newVal);
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal);
+ }
+ }
+ }
+ if (event->changedStates().active) {
+ if (accessible->role() == QAccessible::Window) {
+ // Notifies window opened/closed.
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ if (accessible->state().active) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId);
+ } else {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Window_WindowClosedEventId);
+ }
+ }
+ }
+ }
+ }
+}
+
+void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ // Notifies changes in values of controls supporting the value interface.
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal);
+ }
+ }
+ }
+}
+
+// Notifies changes in text content and selection state of text controls.
+void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (accessible->textInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ if (event->type() == QAccessible::TextSelectionChanged) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
+ } else if (event->type() == QAccessible::TextCaretMoved) {
+ if (!accessible->state().readOnly) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId);
+ }
+ } else {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_Text_TextChangedEventId);
+ }
+ }
+ }
+ }
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
+{
+ if (!iface)
+ return E_INVALIDARG;
+ *iface = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+
+ const bool result = qWindowsComQueryUnknownInterfaceMulti<IRawElementProviderSimple>(this, iid, iface)
+ || qWindowsComQueryInterface<IRawElementProviderSimple>(this, iid, iface)
+ || qWindowsComQueryInterface<IRawElementProviderFragment>(this, iid, iface)
+ || (accessible && hwndForAccessible(accessible) && qWindowsComQueryInterface<IRawElementProviderFragmentRoot>(this, iid, iface));
+ return result ? S_OK : E_NOINTERFACE;
+}
+
+ULONG QWindowsUiaMainProvider::AddRef()
+{
+ return ++m_ref;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsUiaMainProvider::Release()
+{
+ if (!--m_ref) {
+ delete this;
+ return 0;
+ }
+ return m_ref;
+}
+
+HRESULT QWindowsUiaMainProvider::get_ProviderOptions(ProviderOptions *pRetVal)
+{
+ if (!pRetVal)
+ return E_INVALIDARG;
+ // We are STA, (OleInitialize()).
+ *pRetVal = static_cast<ProviderOptions>(ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading);
+ return S_OK;
+}
+
+// Return providers for specific control patterns
+HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idPattern;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ switch (idPattern) {
+ case UIA_TextPatternId:
+ case UIA_TextPattern2Id:
+ // All text controls.
+ if (accessible->textInterface()) {
+ *pRetVal = new QWindowsUiaTextProvider(id());
+ }
+ break;
+ case UIA_ValuePatternId:
+ // All accessible controls return text(QAccessible::Value) (which may be empty).
+ *pRetVal = new QWindowsUiaValueProvider(id());
+ break;
+ case UIA_RangeValuePatternId:
+ // Controls providing a numeric value within a range (e.g., sliders, scroll bars, dials).
+ if (accessible->valueInterface()) {
+ *pRetVal = new QWindowsUiaRangeValueProvider(id());
+ }
+ break;
+ case UIA_TogglePatternId:
+ // Checkbox controls.
+ if (accessible->role() == QAccessible::CheckBox) {
+ *pRetVal = new QWindowsUiaToggleProvider(id());
+ }
+ break;
+ case UIA_SelectionPatternId:
+ // Lists of items.
+ if (accessible->role() == QAccessible::List) {
+ *pRetVal = new QWindowsUiaSelectionProvider(id());
+ }
+ break;
+ case UIA_SelectionItemPatternId:
+ // Items within a list and radio buttons.
+ if ((accessible->role() == QAccessible::RadioButton)
+ || (accessible->role() == QAccessible::ListItem)) {
+ *pRetVal = new QWindowsUiaSelectionItemProvider(id());
+ }
+ break;
+ case UIA_TablePatternId:
+ // Table/tree.
+ if (accessible->tableInterface()
+ && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
+ *pRetVal = new QWindowsUiaTableProvider(id());
+ }
+ break;
+ case UIA_TableItemPatternId:
+ // Item within a table/tree.
+ if (accessible->tableCellInterface()
+ && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
+ *pRetVal = new QWindowsUiaTableItemProvider(id());
+ }
+ break;
+ case UIA_GridPatternId:
+ // Table/tree.
+ if (accessible->tableInterface()
+ && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
+ *pRetVal = new QWindowsUiaGridProvider(id());
+ }
+ break;
+ case UIA_GridItemPatternId:
+ // Item within a table/tree.
+ if (accessible->tableCellInterface()
+ && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
+ *pRetVal = new QWindowsUiaGridItemProvider(id());
+ }
+ break;
+ case UIA_InvokePatternId:
+ // Things that have an invokable action (e.g., simple buttons).
+ if (accessible->actionInterface()) {
+ *pRetVal = new QWindowsUiaInvokeProvider(id());
+ }
+ break;
+ default:
+ break;
+ }
+
+ return S_OK;
+}
+
+HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ clearVariant(pRetVal);
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ bool clientTopLevel = (accessible->role() == QAccessible::Client)
+ && accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
+
+ switch (idProp) {
+ case UIA_ProcessIdPropertyId:
+ // PID
+ setVariantI4(int(GetCurrentProcessId()), pRetVal);
+ break;
+ case UIA_AccessKeyPropertyId:
+ // Accelerator key.
+ setVariantString(accessible->text(QAccessible::Accelerator), pRetVal);
+ break;
+ case UIA_AutomationIdPropertyId:
+ // Automation ID, which can be used by tools to select a specific control in the UI.
+ setVariantString(automationIdForAccessible(accessible), pRetVal);
+ break;
+ case UIA_ClassNamePropertyId:
+ // Class name.
+ if (QObject *o = accessible->object()) {
+ QString className = QLatin1String(o->metaObject()->className());
+ setVariantString(className, pRetVal);
+ }
+ break;
+ case UIA_FrameworkIdPropertyId:
+ setVariantString(QStringLiteral("Qt"), pRetVal);
+ break;
+ case UIA_ControlTypePropertyId:
+ if (clientTopLevel) {
+ // Reports a top-level widget as a window, instead of "custom".
+ setVariantI4(UIA_WindowControlTypeId, pRetVal);
+ } else {
+ // Control type converted from role.
+ setVariantI4(roleToControlTypeId(accessible->role()), pRetVal);
+ }
+ break;
+ case UIA_HelpTextPropertyId:
+ setVariantString(accessible->text(QAccessible::Help), pRetVal);
+ break;
+ case UIA_HasKeyboardFocusPropertyId:
+ setVariantBool(accessible->state().focused, pRetVal);
+ break;
+ case UIA_IsKeyboardFocusablePropertyId:
+ setVariantBool(accessible->state().focusable, pRetVal);
+ break;
+ case UIA_IsOffscreenPropertyId:
+ setVariantBool(false, pRetVal);
+ break;
+ case UIA_IsContentElementPropertyId:
+ setVariantBool(true, pRetVal);
+ break;
+ case UIA_IsControlElementPropertyId:
+ setVariantBool(true, pRetVal);
+ break;
+ case UIA_IsEnabledPropertyId:
+ setVariantBool(!accessible->state().disabled, pRetVal);
+ break;
+ case UIA_IsPasswordPropertyId:
+ setVariantBool(accessible->role() == QAccessible::EditableText
+ && accessible->state().passwordEdit, pRetVal);
+ break;
+ case UIA_IsPeripheralPropertyId:
+ // True for peripheral UIs.
+ if (QWindow *window = windowForAccessible(accessible)) {
+ const Qt::WindowType wt = window->type();
+ setVariantBool(wt == Qt::Popup || wt == Qt::ToolTip || wt == Qt::SplashScreen, pRetVal);
+ }
+ break;
+ case UIA_FullDescriptionPropertyId:
+ setVariantString(accessible->text(QAccessible::Description), pRetVal);
+ break;
+ case UIA_NamePropertyId: {
+ QString name = accessible->text(QAccessible::Name);
+ if (name.isEmpty() && clientTopLevel) {
+ name = QCoreApplication::applicationName();
+ }
+ setVariantString(name, pRetVal);
+ break;
+ }
+ default:
+ break;
+ }
+ return S_OK;
+}
+
+// Generates an ID based on the name of the controls and their parents.
+QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInterface *accessible)
+{
+ QString result;
+ if (accessible) {
+ QObject *obj = accessible->object();
+ while (obj) {
+ QString name = obj->objectName();
+ if (name.isEmpty())
+ return QString();
+ if (!result.isEmpty())
+ result.prepend(QLatin1Char('.'));
+ result.prepend(name);
+ obj = obj->parent();
+ }
+ }
+ return result;
+}
+
+HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ // Returns a host provider only for controls associated with a native window handle. Others should return NULL.
+ if (QAccessibleInterface *accessible = accessibleInterface()) {
+ if (HWND hwnd = hwndForAccessible(accessible)) {
+ return QWindowsUiaWrapper::instance()->hostProviderFromHwnd(hwnd, pRetVal);
+ }
+ }
+ return S_OK;
+}
+
+// Navigates within the tree of accessible controls.
+HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << direction << " this: " << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleInterface *targetacc = nullptr;
+
+ switch (direction) {
+ case NavigateDirection_Parent:
+ targetacc = accessible->parent();
+ if (targetacc && (targetacc->role() == QAccessible::Application)) {
+ targetacc = nullptr; // The app's children are considered top level objects.
+ }
+ break;
+ case NavigateDirection_FirstChild:
+ targetacc = accessible->child(0);
+ break;
+ case NavigateDirection_LastChild:
+ targetacc = accessible->child(accessible->childCount() - 1);
+ break;
+ case NavigateDirection_NextSibling:
+ case NavigateDirection_PreviousSibling:
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (parent->isValid()) {
+ int index = parent->indexOfChild(accessible);
+ index += (direction == NavigateDirection_NextSibling) ? 1 : -1;
+ if (index >= 0 && index < parent->childCount())
+ targetacc = parent->child(index);
+ }
+ }
+ break;
+ }
+
+ if (targetacc)
+ *pRetVal = providerForAccessible(targetacc);
+ return S_OK;
+}
+
+// Returns a unique id assigned to the UI element, used as key by the UI Automation framework.
+HRESULT QWindowsUiaMainProvider::GetRuntimeId(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // The UiaAppendRuntimeId constant is used to make then ID unique
+ // among multiple instances running on the system.
+ int rtId[] = { UiaAppendRuntimeId, int(id()) };
+
+ if ((*pRetVal = SafeArrayCreateVector(VT_I4, 0, 2))) {
+ for (LONG i = 0; i < 2; ++i)
+ SafeArrayPutElement(*pRetVal, &i, &rtId[i]);
+ }
+ return S_OK;
+}
+
+// Returns the bounding rectangle for the accessible control.
+HRESULT QWindowsUiaMainProvider::get_BoundingRectangle(UiaRect *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QWindow *window = windowForAccessible(accessible);
+ if (!window)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ rectToNativeUiaRect(accessible->rect(), window, pRetVal);
+ return S_OK;
+}
+
+HRESULT QWindowsUiaMainProvider::GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+ // No embedded roots.
+ return S_OK;
+}
+
+// Sets focus to the control.
+HRESULT QWindowsUiaMainProvider::SetFocus()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ actionInterface->doAction(QAccessibleActionInterface::setFocusAction());
+ return S_OK;
+}
+
+HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ // Our UI Automation implementation considers the window as the root for
+ // non-native controls/fragments.
+ if (QAccessibleInterface *accessible = accessibleInterface()) {
+ if (QWindow *window = windowForAccessible(accessible)) {
+ if (QAccessibleInterface *rootacc = window->accessibleRoot()) {
+ *pRetVal = providerForAccessible(rootacc);
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Returns a provider for the UI element present at the specified screen coordinates.
+HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << x << y;
+
+ if (!pRetVal) {
+ return E_INVALIDARG;
+ }
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QWindow *window = windowForAccessible(accessible);
+ if (!window)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // Scales coordinates from High DPI screens.
+ UiaPoint uiaPoint = {x, y};
+ QPoint point;
+ nativeUiaPointToPoint(uiaPoint, window, &point);
+
+ QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y());
+
+ if (targetacc) {
+ QAccessibleInterface *acc = targetacc;
+ // Controls can be embedded within grouping elements. By default returns the innermost control.
+ while (acc) {
+ targetacc = acc;
+ // For accessibility tools it may be better to return the text element instead of its subcomponents.
+ if (targetacc->textInterface()) break;
+ acc = acc->childAt(point.x(), point.y());
+ }
+ *pRetVal = providerForAccessible(targetacc);
+ }
+ return S_OK;
+}
+
+// Returns the fragment with focus.
+HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ if (QAccessibleInterface *accessible = accessibleInterface()) {
+ if (QAccessibleInterface *focusacc = accessible->focusChild()) {
+ *pRetVal = providerForAccessible(focusacc);
+ }
+ }
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
new file mode 100644
index 0000000000..893cbf7f8a
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAMAINPROVIDER_H
+#define QWINDOWSUIAMAINPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+#include <QtCore/QPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/qt_windows.h>
+#include <QtGui/QAccessible>
+
+QT_BEGIN_NAMESPACE
+
+// The main UI Automation class.
+class QWindowsUiaMainProvider :
+ public QWindowsUiaBaseProvider,
+ public IRawElementProviderSimple,
+ public IRawElementProviderFragment,
+ public IRawElementProviderFragmentRoot
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWindowsUiaMainProvider)
+public:
+ static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible);
+ explicit QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount = 1);
+ virtual ~QWindowsUiaMainProvider();
+ static void notifyFocusChange(QAccessibleEvent *event);
+ static void notifyStateChange(QAccessibleStateChangeEvent *event);
+ static void notifyValueChange(QAccessibleValueChangeEvent *event);
+ static void notifyTextChange(QAccessibleEvent *event);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ // IRawElementProviderSimple methods
+ HRESULT STDMETHODCALLTYPE get_ProviderOptions(ProviderOptions *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(IRawElementProviderSimple **pRetVal);
+
+ // IRawElementProviderFragment methods
+ HRESULT STDMETHODCALLTYPE Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetRuntimeId(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_BoundingRectangle(UiaRect *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE SetFocus();
+ HRESULT STDMETHODCALLTYPE get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal);
+
+ // IRawElementProviderFragmentRoot methods
+ HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal);
+
+private:
+ QString automationIdForAccessible(const QAccessibleInterface *accessible);
+ ULONG m_ref;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAMAINPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
new file mode 100644
index 0000000000..9f0a1e126f
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiaprovidercache.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+// Private constructor
+QWindowsUiaProviderCache::QWindowsUiaProviderCache()
+{
+}
+
+// shared instance
+QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance()
+{
+ static QWindowsUiaProviderCache providerCache;
+ return &providerCache;
+}
+
+// Returns the provider instance associated with the ID, or nullptr.
+QWindowsUiaBaseProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const
+{
+ return providerTable.value(id);
+}
+
+// Inserts a provider in the cache and associates it with an accessibility ID.
+void QWindowsUiaProviderCache::insert(QAccessible::Id id, QWindowsUiaBaseProvider *provider)
+{
+ remove(id);
+ if (provider) {
+ providerTable[id] = provider;
+ inverseTable[provider] = id;
+ // Connects the destroyed signal to our slot, to remove deleted objects from the cache.
+ QObject::connect(provider, &QObject::destroyed, this, &QWindowsUiaProviderCache::objectDestroyed);
+ }
+}
+
+// Removes deleted provider objects from the cache.
+void QWindowsUiaProviderCache::objectDestroyed(QObject *obj)
+{
+ // We have to use the inverse table to map the object address back to its ID,
+ // since at this point (called from QObject destructor), it has already been
+ // partially destroyed and we cannot treat it as a provider.
+ auto it = inverseTable.find(obj);
+ if (it != inverseTable.end()) {
+ providerTable.remove(*it);
+ inverseTable.remove(obj);
+ }
+}
+
+// Removes a provider with a given id from the cache.
+void QWindowsUiaProviderCache::remove(QAccessible::Id id)
+{
+ inverseTable.remove(providerTable.value(id));
+ providerTable.remove(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
new file mode 100644
index 0000000000..7ad30ac39c
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAPROVIDERCACHE_H
+#define QWINDOWSUIAPROVIDERCACHE_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+#include <QtCore/QHash>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+
+QT_BEGIN_NAMESPACE
+
+// Singleton used to cache provider instances using the accessibility ID as the key.
+class QWindowsUiaProviderCache : public QObject
+{
+ QWindowsUiaProviderCache();
+ Q_OBJECT
+public:
+ static QWindowsUiaProviderCache *instance();
+ QWindowsUiaBaseProvider *providerForId(QAccessible::Id id) const;
+ void insert(QAccessible::Id id, QWindowsUiaBaseProvider *provider);
+ void remove(QAccessible::Id id);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *obj);
+
+private:
+ QHash<QAccessible::Id, QWindowsUiaBaseProvider *> providerTable;
+ QHash<QObject *, QAccessible::Id> inverseTable;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAPROVIDERCACHE_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
new file mode 100644
index 0000000000..0cd09c3f0a
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiarangevalueprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaRangeValueProvider::QWindowsUiaRangeValueProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaRangeValueProvider::~QWindowsUiaRangeValueProvider()
+{
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::SetValue(double val)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+ if (!valueInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ double minimum = valueInterface->minimumValue().toDouble();
+ double maximum = valueInterface->maximumValue().toDouble();
+ if ((val < minimum) || (val > maximum))
+ return E_INVALIDARG;
+
+ valueInterface->setCurrentValue(QVariant(val));
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Value(double *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+ if (!valueInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QVariant varValue = valueInterface->currentValue();
+ *pRetVal = varValue.toDouble();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_IsReadOnly(BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = accessible->state().readOnly;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Maximum(double *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+ if (!valueInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QVariant varValue = valueInterface->maximumValue();
+ *pRetVal = varValue.toDouble();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_Minimum(double *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+ if (!valueInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QVariant varValue = valueInterface->minimumValue();
+ *pRetVal = varValue.toDouble();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_LargeChange(double *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ return get_SmallChange(pRetVal);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_SmallChange(double *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleValueInterface *valueInterface = accessible->valueInterface();
+ if (!valueInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QVariant varValue = valueInterface->minimumStepSize();
+ *pRetVal = varValue.toDouble();
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
new file mode 100644
index 0000000000..f742ef99c2
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIARANGEVALUEPROVIDER_H
+#define QWINDOWSUIARANGEVALUEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Range Value control pattern provider.
+class QWindowsUiaRangeValueProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IRangeValueProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaRangeValueProvider)
+public:
+ explicit QWindowsUiaRangeValueProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaRangeValueProvider();
+
+ // IRangeValueProvider
+ HRESULT STDMETHODCALLTYPE SetValue(double val);
+ HRESULT STDMETHODCALLTYPE get_Value(double *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_Maximum(double *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_Minimum(double *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_LargeChange(double *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_SmallChange(double *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIARANGEVALUEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
new file mode 100644
index 0000000000..45216a6d1c
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiaselectionitemprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaSelectionItemProvider::QWindowsUiaSelectionItemProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaSelectionItemProvider::~QWindowsUiaSelectionItemProvider()
+{
+}
+
+// Selects the element (deselecting all others).
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::Select()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (accessible->role() == QAccessible::RadioButton) {
+ // For radio buttons we just invoke the selection action; others are automatically deselected.
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ } else {
+ // Toggle list item if not already selected. It must be done first to support all selection modes.
+ if (!accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ // Toggle selected siblings.
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ for (int i = 0; i < parent->childCount(); ++i) {
+ if (QAccessibleInterface *sibling = parent->child(i)) {
+ if ((sibling != accessible) && (sibling->state().selected)) {
+ if (QAccessibleActionInterface *siblingAction = sibling->actionInterface()) {
+ siblingAction->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Adds the element to the list of selected elements.
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::AddToSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (accessible->role() == QAccessible::RadioButton) {
+ // For radio buttons we invoke the selection action.
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ } else {
+ // Toggle list item if not already selected.
+ if (!accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+ return S_OK;
+}
+
+// Removes a list item from selection.
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::RemoveFromSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (accessible->role() != QAccessible::RadioButton) {
+ if (accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+
+ return S_OK;
+}
+
+// Returns true if element is currently selected.
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_IsSelected(BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = FALSE;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (accessible->role() == QAccessible::RadioButton)
+ *pRetVal = accessible->state().checked;
+ else
+ *pRetVal = accessible->state().selected;
+ return S_OK;
+}
+
+// Returns the provider for the container element (e.g., the list for the list item).
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContainer(IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // Radio buttons do not require a container.
+ if (accessible->role() == QAccessible::ListItem) {
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (parent->role() == QAccessible::List) {
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent);
+ }
+ }
+ }
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
new file mode 100644
index 0000000000..6a9b5b1e4b
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIASELECTIONITEMPROVIDER_H
+#define QWINDOWSUIASELECTIONITEMPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Selection Item control pattern provider. Used for List items and radio buttons.
+class QWindowsUiaSelectionItemProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ISelectionItemProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaSelectionItemProvider)
+public:
+ explicit QWindowsUiaSelectionItemProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaSelectionItemProvider();
+
+ // ISelectionItemProvider
+ HRESULT STDMETHODCALLTYPE Select();
+ HRESULT STDMETHODCALLTYPE AddToSelection();
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection();
+ HRESULT STDMETHODCALLTYPE get_IsSelected(BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_SelectionContainer(IRawElementProviderSimple **pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIASELECTIONITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
new file mode 100644
index 0000000000..1c06503bfc
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiaselectionprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaSelectionProvider::QWindowsUiaSelectionProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaSelectionProvider::~QWindowsUiaSelectionProvider()
+{
+}
+
+// Returns an array of providers with the selected items.
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // First put selected items in a list, then build a safe array with the right size.
+ QList<QAccessibleInterface *> selectedList;
+ for (int i = 0; i < accessible->childCount(); ++i) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (child->state().selected) {
+ selectedList.append(child);
+ }
+ }
+ }
+
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) {
+ for (LONG i = 0; i < selectedList.size(); ++i) {
+ if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) {
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(childProvider));
+ childProvider->Release();
+ }
+ }
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_CanSelectMultiple(BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = FALSE;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = accessible->state().multiSelectable;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired(BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = FALSE;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // Initially returns false if none are selected. After the first selection, it may be required.
+ bool anySelected = false;
+ for (int i = 0; i < accessible->childCount(); ++i) {
+ if (QAccessibleInterface *child = accessible->child(i)) {
+ if (child->state().selected) {
+ anySelected = true;
+ break;
+ }
+ }
+ }
+
+ *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
new file mode 100644
index 0000000000..5a07a82ac8
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIASELECTIONPROVIDER_H
+#define QWINDOWSUIASELECTIONPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Selection control pattern provider. Used for Lists.
+class QWindowsUiaSelectionProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ISelectionProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaSelectionProvider)
+public:
+ explicit QWindowsUiaSelectionProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaSelectionProvider();
+
+ // ISelectionProvider
+ HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(BOOL *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIASELECTIONPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
new file mode 100644
index 0000000000..3ea29fc86c
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiatableitemprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaTableItemProvider::QWindowsUiaTableItemProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaTableItemProvider::~QWindowsUiaTableItemProvider()
+{
+}
+
+// Returns the providers for the row headers associated with the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QList<QAccessibleInterface *> headers = tableCellInterface->rowHeaderCells();
+
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
+ for (LONG i = 0; i < headers.size(); ++i) {
+ if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
+ headerProvider->Release();
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Returns the providers for the column headers associated with the item.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface();
+ if (!tableCellInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QList<QAccessibleInterface *> headers = tableCellInterface->columnHeaderCells();
+
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
+ for (LONG i = 0; i < headers.size(); ++i) {
+ if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
+ headerProvider->Release();
+ }
+ }
+ }
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
new file mode 100644
index 0000000000..277884c980
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIATABLEITEMPROVIDER_H
+#define QWINDOWSUIATABLEITEMPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Table Item control pattern provider. Used by items within a table/tree.
+class QWindowsUiaTableItemProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ITableItemProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaTableItemProvider)
+public:
+ explicit QWindowsUiaTableItemProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaTableItemProvider();
+
+ // ITableItemProvider
+ HRESULT STDMETHODCALLTYPE GetRowHeaderItems(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(SAFEARRAY **pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIATABLEITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
new file mode 100644
index 0000000000..f79a24536b
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiatableprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaTableProvider::QWindowsUiaTableProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaTableProvider::~QWindowsUiaTableProvider()
+{
+}
+
+// Gets the providers for all the row headers in the table.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetRowHeaders(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+ if (!tableInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QList<QAccessibleInterface *> headers;
+
+ for (int i = 0; i < tableInterface->rowCount(); ++i) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(i, 0)) {
+ if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) {
+ headers.append(tableCellInterface->rowHeaderCells());
+ }
+ }
+ }
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
+ for (LONG i = 0; i < headers.size(); ++i) {
+ if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
+ headerProvider->Release();
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Gets the providers for all the column headers in the table.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetColumnHeaders(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTableInterface *tableInterface = accessible->tableInterface();
+ if (!tableInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QList<QAccessibleInterface *> headers;
+
+ for (int i = 0; i < tableInterface->columnCount(); ++i) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(0, i)) {
+ if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) {
+ headers.append(tableCellInterface->columnHeaderCells());
+ }
+ }
+ }
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
+ for (LONG i = 0; i < headers.size(); ++i) {
+ if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider));
+ headerProvider->Release();
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Returns the primary direction of traversal for the table.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = RowOrColumnMajor_Indeterminate;
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
new file mode 100644
index 0000000000..8cd0acda03
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIATABLEPROVIDER_H
+#define QWINDOWSUIATABLEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Table control pattern provider. Used by tables/trees.
+class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ITableProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaTableProvider)
+public:
+ explicit QWindowsUiaTableProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaTableProvider();
+
+ // ITableProvider
+ HRESULT STDMETHODCALLTYPE GetRowHeaders(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetColumnHeaders(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIATABLEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
new file mode 100644
index 0000000000..e1622933af
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
@@ -0,0 +1,261 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiatextprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaTextProvider::QWindowsUiaTextProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaTextProvider::~QWindowsUiaTextProvider()
+{
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::QueryInterface(REFIID iid, LPVOID *iface)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!iface)
+ return E_INVALIDARG;
+ *iface = nullptr;
+
+ const bool result = qWindowsComQueryUnknownInterfaceMulti<ITextProvider>(this, iid, iface)
+ || qWindowsComQueryInterface<ITextProvider>(this, iid, iface)
+ || qWindowsComQueryInterface<ITextProvider2>(this, iid, iface);
+ return result ? S_OK : E_NOINTERFACE;
+}
+
+// Returns an array of providers for the selected text ranges.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int selCount = textInterface->selectionCount();
+ if (selCount > 0) {
+ // Build a safe array with the text range providers.
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selCount))) {
+ for (LONG i = 0; i < selCount; ++i) {
+ int startOffset = 0, endOffset = 0;
+ textInterface->selection((int)i, &startOffset, &endOffset);
+ QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset);
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
+ textRangeProvider->Release();
+ }
+ }
+ } else {
+ // If there is no selection, we return an array with a single degenerate (empty) text range at the cursor position.
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
+ LONG i = 0;
+ int cursorPosition = textInterface->cursorPosition();
+ QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
+ textRangeProvider->Release();
+ }
+ }
+ return S_OK;
+}
+
+// Returns an array of providers for the visible text ranges.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetVisibleRanges(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // Considering the entire text as visible.
+ if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
+ LONG i = 0;
+ QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
+ SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
+ textRangeProvider->Release();
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromChild(IRawElementProviderSimple * /*childElement*/,
+ ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+ // No children supported.
+ return S_OK;
+}
+
+// Returns a degenerate text range at the specified point.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QWindow *window = windowForAccessible(accessible);
+ if (!window)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QPoint pt;
+ nativeUiaPointToPoint(point, window, &pt);
+
+ int offset = textInterface->offsetAtPoint(pt);
+ if ((offset >= 0) && (offset < textInterface->characterCount())) {
+ *pRetVal = new QWindowsUiaTextRangeProvider(id(), offset, offset);
+ }
+ return S_OK;
+}
+
+// Returns a text range provider for the entire text.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::get_DocumentRange(ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
+ return S_OK;
+}
+
+// Currently supporting single selection.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::get_SupportedTextSelection(SupportedTextSelection *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = SupportedTextSelection_Single;
+ return S_OK;
+}
+
+// Not supporting annotations.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::RangeFromAnnotation(IRawElementProviderSimple * /*annotationElement*/, ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!isActive || !pRetVal)
+ return E_INVALIDARG;
+ *isActive = FALSE;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *isActive = accessible->state().focused;
+
+ int cursorPosition = textInterface->cursorPosition();
+ *pRetVal = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
new file mode 100644
index 0000000000..a6d10027fa
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIATEXTPROVIDER_H
+#define QWINDOWSUIATEXTPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+#include "qwindowsuiatextrangeprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Text control pattern provider. Used for text controls.
+class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ITextProvider2>
+{
+ Q_DISABLE_COPY(QWindowsUiaTextProvider)
+public:
+ explicit QWindowsUiaTextProvider(QAccessible::Id id);
+ ~QWindowsUiaTextProvider();
+
+ // IUnknown overrides
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface);
+
+ // ITextProvider
+ HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetVisibleRanges(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_DocumentRange(ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(SupportedTextSelection *pRetVal);
+
+ // ITextProvider2
+ HRESULT STDMETHODCALLTYPE RangeFromAnnotation(IRawElementProviderSimple *annotationElement, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIATEXTPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
new file mode 100644
index 0000000000..dae7cbdd5f
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiatextrangeprovider.h"
+#include "qwindowsuiamainprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaTextRangeProvider::QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset) :
+ QWindowsUiaBaseProvider(id),
+ m_startOffset(startOffset),
+ m_endOffset(endOffset)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this << startOffset << endOffset;
+}
+
+QWindowsUiaTextRangeProvider::~QWindowsUiaTextRangeProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+}
+
+HRESULT QWindowsUiaTextRangeProvider::AddToSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+ return Select();
+}
+
+HRESULT QWindowsUiaTextRangeProvider::Clone(ITextRangeProvider **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ *pRetVal = new QWindowsUiaTextRangeProvider(id(), m_startOffset, m_endOffset);
+ return S_OK;
+}
+
+// Two ranges are considered equal if their start/end points are the same.
+HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!range || !pRetVal)
+ return E_INVALIDARG;
+
+ QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
+ *pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
+ return S_OK;
+}
+
+// Compare different endpoinds between two providers.
+HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint,
+ int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__
+ << "endpoint=" << endpoint << "targetRange=" << targetRange
+ << "targetEndpoint=" << targetEndpoint << "this: " << this;
+
+ if (!targetRange || !pRetVal)
+ return E_INVALIDARG;
+
+ QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+
+ int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
+ int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
+ targetProvider->m_startOffset : targetProvider->m_endOffset;
+ *pRetVal = point - targetPoint;
+ return S_OK;
+}
+
+// Expands/normalizes the range for a given text unit.
+HRESULT QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "this: " << this;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int len = textInterface->characterCount();
+ if (len < 1) {
+ m_startOffset = 0;
+ m_endOffset = 0;
+ } else {
+ if (unit == TextUnit_Character) {
+ m_startOffset = qBound(0, m_startOffset, len - 1);
+ m_endOffset = m_startOffset + 1;
+ } else {
+ QString text = textInterface->text(0, len);
+ for (int t = m_startOffset; t >= 0; --t) {
+ if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
+ m_startOffset = t;
+ break;
+ }
+ }
+ for (int t = m_startOffset; t < len; ++t) {
+ if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
+ m_endOffset = t + 1;
+ break;
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Not supported.
+HRESULT QWindowsUiaTextRangeProvider::FindAttribute(TEXTATTRIBUTEID /* attributeId */,
+ VARIANT /* val */, BOOL /* backward */,
+ ITextRangeProvider **pRetVal)
+{
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+// Returns the value of a given attribute.
+HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId,
+ VARIANT *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "attributeId=" << attributeId << "this: " << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ clearVariant(pRetVal);
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ switch (attributeId) {
+ case UIA_IsReadOnlyAttributeId:
+ setVariantBool(accessible->state().readOnly, pRetVal);
+ break;
+ case UIA_CaretPositionAttributeId:
+ if (textInterface->cursorPosition() == 0)
+ setVariantI4(CaretPosition_BeginningOfLine, pRetVal);
+ else if (textInterface->cursorPosition() == textInterface->characterCount())
+ setVariantI4(CaretPosition_EndOfLine, pRetVal);
+ else
+ setVariantI4(CaretPosition_Unknown, pRetVal);
+ break;
+ default:
+ break;
+ }
+ return S_OK;
+}
+
+// Returns an array of bounding rectangles for text lines within the range.
+HRESULT QWindowsUiaTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QWindow *window = windowForAccessible(accessible);
+ if (!window)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int len = textInterface->characterCount();
+ QList<QRect> rectList;
+
+ if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset)) {
+ int start, end;
+ textInterface->textAtOffset(m_startOffset, QAccessible::LineBoundary, &start, &end);
+ while ((start >= 0) && (end >= 0)) {
+ int startRange = qMax(start, m_startOffset);
+ int endRange = qMin(end, m_endOffset);
+ if (startRange < endRange) {
+ // Calculates a bounding rectangle for the line and adds it to the list.
+ QRect startRect = textInterface->characterRect(startRange);
+ QRect endRect = textInterface->characterRect(endRange - 1);
+ QRect lineRect(qMin(startRect.x(), endRect.x()),
+ qMin(startRect.y(), endRect.y()),
+ qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()),
+ qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y()));
+ rectList.append(lineRect);
+ }
+ if (end >= len) break;
+ textInterface->textAfterOffset(end + 1, QAccessible::LineBoundary, &start, &end);
+ }
+ }
+
+ if ((*pRetVal = SafeArrayCreateVector(VT_R8, 0, 4 * rectList.size()))) {
+ for (int i = 0; i < rectList.size(); ++i) {
+ // Scale rect for high DPI screens.
+ UiaRect uiaRect;
+ rectToNativeUiaRect(rectList[i], window, &uiaRect);
+ double coords[4] = { uiaRect.left, uiaRect.top, uiaRect.width, uiaRect.height };
+ for (int j = 0; j < 4; ++j) {
+ LONG idx = 4 * i + j;
+ SafeArrayPutElement(*pRetVal, &idx, &coords[j]);
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Returns an array of children elements embedded within the range.
+HRESULT QWindowsUiaTextRangeProvider::GetChildren(SAFEARRAY **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ // Not supporting any children.
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
+ return S_OK;
+}
+
+// Returns a provider for the enclosing element (text to which the range belongs).
+HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible);
+ return S_OK;
+}
+
+// Gets the text within the range.
+HRESULT QWindowsUiaTextRangeProvider::GetText(int maxLength, BSTR *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << maxLength << "this: " << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int len = textInterface->characterCount();
+ QString rangeText;
+ if ((m_startOffset >= 0) && (m_endOffset <= len) && (m_startOffset < m_endOffset))
+ rangeText = textInterface->text(m_startOffset, m_endOffset);
+
+ if ((maxLength > -1) && (rangeText.size() > maxLength))
+ rangeText.truncate(maxLength);
+ *pRetVal = bStrFromQString(rangeText);
+ return S_OK;
+}
+
+// Moves the range a specified number of units (and normalizes it).
+HRESULT QWindowsUiaTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "count=" << count << "this: " << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int len = textInterface->characterCount();
+
+ if (len < 1)
+ return S_OK;
+
+ if (unit == TextUnit_Character) {
+ // Moves the start point, ensuring it lies within the bounds.
+ int start = qBound(0, m_startOffset + count, len - 1);
+ // If range was initially empty, leaves it as is; otherwise, normalizes it to one char.
+ m_endOffset = (m_endOffset > m_startOffset) ? start + 1 : start;
+ *pRetVal = start - m_startOffset; // Returns the actually moved distance.
+ m_startOffset = start;
+ } else {
+ if (count > 0) {
+ MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal);
+ MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal);
+ } else {
+ MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, pRetVal);
+ MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, pRetVal);
+ }
+ }
+ return S_OK;
+}
+
+// Copies the value of an end point from one range to another.
+HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint,
+ ITextRangeProvider *targetRange,
+ TextPatternRangeEndpoint targetEndpoint)
+{
+ if (!targetRange)
+ return E_INVALIDARG;
+
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__
+ << "endpoint=" << endpoint << "targetRange=" << targetRange << "targetEndpoint=" << targetEndpoint << "this: " << this;
+
+ QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+
+ int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
+ targetProvider->m_startOffset : targetProvider->m_endOffset;
+
+ // If the moved endpoint crosses the other endpoint, that one is moved too.
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ m_startOffset = targetPoint;
+ if (m_endOffset < m_startOffset)
+ m_endOffset = m_startOffset;
+ } else {
+ m_endOffset = targetPoint;
+ if (m_endOffset < m_startOffset)
+ m_startOffset = m_endOffset;
+ }
+ return S_OK;
+}
+
+// Moves an endpoint an specific number of units.
+HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint,
+ TextUnit unit, int count,
+ int *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__
+ << "endpoint=" << endpoint << "unit=" << unit << "count=" << count << "this: " << this;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = 0;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int len = textInterface->characterCount();
+
+ if (len < 1)
+ return S_OK;
+
+ if (unit == TextUnit_Character) {
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ int boundedValue = qBound(0, m_startOffset + count, len - 1);
+ *pRetVal = boundedValue - m_startOffset;
+ m_startOffset = boundedValue;
+ m_endOffset = qBound(m_startOffset, m_endOffset, len);
+ } else {
+ int boundedValue = qBound(0, m_endOffset + count, len);
+ *pRetVal = boundedValue - m_endOffset;
+ m_endOffset = boundedValue;
+ m_startOffset = qBound(0, m_startOffset, m_endOffset);
+ }
+ } else {
+ QString text = textInterface->text(0, len);
+ int moved = 0;
+
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ if (count > 0) {
+ for (int t = m_startOffset; (t < len - 1) && (moved < count); ++t) {
+ if (isTextUnitSeparator(unit, text[t]) && !isTextUnitSeparator(unit, text[t + 1])) {
+ m_startOffset = t + 1;
+ ++moved;
+ }
+ }
+ m_endOffset = qBound(m_startOffset, m_endOffset, len);
+ } else {
+ for (int t = m_startOffset - 1; (t >= 0) && (moved > count); --t) {
+ if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
+ m_startOffset = t;
+ --moved;
+ }
+ }
+ }
+ } else {
+ if (count > 0) {
+ for (int t = m_endOffset; (t < len) && (moved < count); ++t) {
+ if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
+ m_endOffset = t + 1;
+ ++moved;
+ }
+ }
+ } else {
+ int end = 0;
+ for (int t = m_endOffset - 2; (t > 0) && (moved > count); --t) {
+ if (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1]))) {
+ end = t + 1;
+ --moved;
+ }
+ }
+ m_endOffset = end;
+ m_startOffset = qBound(0, m_startOffset, m_endOffset);
+ }
+ }
+ *pRetVal = moved;
+ }
+ return S_OK;
+}
+
+HRESULT QWindowsUiaTextRangeProvider::RemoveFromSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ // unselects all
+ return unselect();
+}
+
+// Scrolls the range into view.
+HRESULT QWindowsUiaTextRangeProvider::ScrollIntoView(BOOL alignToTop)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "alignToTop=" << alignToTop << "this: " << this;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ textInterface->scrollToSubstring(m_startOffset, m_endOffset);
+ return S_OK;
+}
+
+// Selects the range.
+HRESULT QWindowsUiaTextRangeProvider::Select()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // unselects all and adds a new selection
+ unselect();
+ textInterface->addSelection(m_startOffset, m_endOffset);
+ return S_OK;
+}
+
+// Not supported.
+HRESULT QWindowsUiaTextRangeProvider::FindTextW(BSTR /* text */, BOOL /* backward */,
+ BOOL /* ignoreCase */,
+ ITextRangeProvider **pRetVal)
+{
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+ return S_OK;
+}
+
+// Removes all selected ranges from the text element.
+HRESULT QWindowsUiaTextRangeProvider::unselect()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleTextInterface *textInterface = accessible->textInterface();
+ if (!textInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ int selCount = textInterface->selectionCount();
+
+ for (int i = selCount - 1; i >= 0; --i)
+ textInterface->removeSelection(i);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
new file mode 100644
index 0000000000..6fe6502c41
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIATEXTRANGEPROVIDER_H
+#define QWINDOWSUIATEXTRANGEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Text Range control pattern provider. Used for text controls.
+class QWindowsUiaTextRangeProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<ITextRangeProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaTextRangeProvider)
+public:
+ explicit QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset);
+ virtual ~QWindowsUiaTextRangeProvider();
+
+ HRESULT STDMETHODCALLTYPE AddToSelection();
+ HRESULT STDMETHODCALLTYPE Clone(ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE Compare(ITextRangeProvider *range, BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint, int *pRetVal);
+ HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(TextUnit unit);
+ HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetBoundingRectangles(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetChildren(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetEnclosingElement(IRawElementProviderSimple **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetText(int maxLength, BSTR *pRetVal);
+ HRESULT STDMETHODCALLTYPE Move(TextUnit unit, int count, int *pRetVal);
+ HRESULT STDMETHODCALLTYPE MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint);
+ HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count, int *pRetVal);
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection();
+ HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop);
+ HRESULT STDMETHODCALLTYPE Select();
+
+private:
+ HRESULT unselect();
+ int m_startOffset;
+ int m_endOffset;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIATEXTRANGEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
new file mode 100644
index 0000000000..01cdfd7e91
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiatoggleprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaToggleProvider::QWindowsUiaToggleProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaToggleProvider::~QWindowsUiaToggleProvider()
+{
+}
+
+// toggles the state by invoking the toggle action
+HRESULT STDMETHODCALLTYPE QWindowsUiaToggleProvider::Toggle()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ return S_OK;
+}
+
+// Gets the current toggle state.
+HRESULT STDMETHODCALLTYPE QWindowsUiaToggleProvider::get_ToggleState(ToggleState *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = ToggleState_Off;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ if (accessible->state().checked)
+ *pRetVal = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
+ else
+ *pRetVal = ToggleState_Off;
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
new file mode 100644
index 0000000000..a0df983e40
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIATOGGLEPROVIDER_H
+#define QWINDOWSUIATOGGLEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Toggle control pattern provider. Used for checkboxes.
+class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IToggleProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaToggleProvider)
+public:
+ explicit QWindowsUiaToggleProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaToggleProvider();
+
+ // IToggleProvider
+ HRESULT STDMETHODCALLTYPE Toggle();
+ HRESULT STDMETHODCALLTYPE get_ToggleState(ToggleState *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIATOGGLEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
new file mode 100644
index 0000000000..89e5075dcb
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+#include "qwindowswindow.h"
+
+#include <QtGui/QWindow>
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <cmath>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWindowsUiAutomation {
+
+// Returns the window containing the element (usually the top window),
+QWindow *windowForAccessible(const QAccessibleInterface *accessible)
+{
+ QWindow *window = accessible->window();
+ if (!window) {
+ QAccessibleInterface *acc = accessible->parent();
+ while (acc && acc->isValid() && !window) {
+ window = acc->window();
+ QAccessibleInterface *par = acc->parent();
+ acc = par;
+ }
+ }
+ return window;
+}
+
+// Returns the native window handle associated with the element, if any.
+// Usually it will be NULL, as Qt5 by default uses alien widgets with no native windows.
+HWND hwndForAccessible(const QAccessibleInterface *accessible)
+{
+ if (QWindow *window = accessible->window()) {
+ if (!accessible->parent() || (accessible->parent()->window() != window)) {
+ return QWindowsBaseWindow::handleOf(window);
+ }
+ }
+ return NULL;
+}
+
+void clearVariant(VARIANT *variant)
+{
+ variant->vt = VT_EMPTY;
+ variant->punkVal = nullptr;
+}
+
+void setVariantI4(int value, VARIANT *variant)
+{
+ variant->vt = VT_I4;
+ variant->lVal = value;
+}
+
+void setVariantBool(bool value, VARIANT *variant)
+{
+ variant->vt = VT_BOOL;
+ variant->boolVal = value ? -1 : 0;
+}
+
+void setVariantDouble(double value, VARIANT *variant)
+{
+ variant->vt = VT_R8;
+ variant->boolVal = value;
+}
+
+BSTR bStrFromQString(const QString &value)
+{
+ return SysAllocString(reinterpret_cast<const wchar_t *>(value.utf16()));
+}
+
+void setVariantString(const QString &value, VARIANT *variant)
+{
+ variant->vt = VT_BSTR;
+ variant->bstrVal = bStrFromQString(value);
+}
+
+// Scales a rect to native coordinates, according to high dpi settings.
+void rectToNativeUiaRect(const QRect &rect, const QWindow *w, UiaRect *uiaRect)
+{
+ if (w && uiaRect) {
+ const qreal factor = QHighDpiScaling::factor(w);
+ uiaRect->left = qreal(rect.x()) * factor;
+ uiaRect->top = qreal(rect.y()) * factor;
+ uiaRect->width = qreal(rect.width()) * factor;
+ uiaRect->height = qreal(rect.height()) * factor;
+ }
+}
+
+// Scales a point from native coordinates, according to high dpi settings.
+void nativeUiaPointToPoint(const UiaPoint &uiaPoint, const QWindow *w, QPoint *point)
+{
+ if (w && point) {
+ const qreal factor = QHighDpiScaling::factor(w);
+ point->setX(int(std::lround(uiaPoint.x / factor)));
+ point->setY(int(std::lround(uiaPoint.y / factor)));
+ }
+}
+
+// Maps an accessibility role ID to an UI Automation control type ID.
+long roleToControlTypeId(QAccessible::Role role)
+{
+ static const QHash<QAccessible::Role, long> mapping {
+ {QAccessible::TitleBar, UIA_TitleBarControlTypeId},
+ {QAccessible::MenuBar, UIA_MenuBarControlTypeId},
+ {QAccessible::ScrollBar, UIA_ScrollBarControlTypeId},
+ {QAccessible::Grip, UIA_ThumbControlTypeId},
+ {QAccessible::Sound, UIA_CustomControlTypeId},
+ {QAccessible::Cursor, UIA_CustomControlTypeId},
+ {QAccessible::Caret, UIA_CustomControlTypeId},
+ {QAccessible::AlertMessage, UIA_CustomControlTypeId},
+ {QAccessible::Window, UIA_WindowControlTypeId},
+ {QAccessible::Client, UIA_CustomControlTypeId},
+ {QAccessible::PopupMenu, UIA_MenuControlTypeId},
+ {QAccessible::MenuItem, UIA_MenuItemControlTypeId},
+ {QAccessible::ToolTip, UIA_ToolTipControlTypeId},
+ {QAccessible::Application, UIA_CustomControlTypeId},
+ {QAccessible::Document, UIA_DocumentControlTypeId},
+ {QAccessible::Pane, UIA_PaneControlTypeId},
+ {QAccessible::Chart, UIA_CustomControlTypeId},
+ {QAccessible::Dialog, UIA_WindowControlTypeId},
+ {QAccessible::Border, UIA_CustomControlTypeId},
+ {QAccessible::Grouping, UIA_GroupControlTypeId},
+ {QAccessible::Separator, UIA_SeparatorControlTypeId},
+ {QAccessible::ToolBar, UIA_ToolBarControlTypeId},
+ {QAccessible::StatusBar, UIA_StatusBarControlTypeId},
+ {QAccessible::Table, UIA_TableControlTypeId},
+ {QAccessible::ColumnHeader, UIA_HeaderControlTypeId},
+ {QAccessible::RowHeader, UIA_HeaderControlTypeId},
+ {QAccessible::Column, UIA_HeaderItemControlTypeId},
+ {QAccessible::Row, UIA_HeaderItemControlTypeId},
+ {QAccessible::Cell, UIA_DataItemControlTypeId},
+ {QAccessible::Link, UIA_HyperlinkControlTypeId},
+ {QAccessible::HelpBalloon, UIA_ToolTipControlTypeId},
+ {QAccessible::Assistant, UIA_CustomControlTypeId},
+ {QAccessible::List, UIA_ListControlTypeId},
+ {QAccessible::ListItem, UIA_ListItemControlTypeId},
+ {QAccessible::Tree, UIA_TreeControlTypeId},
+ {QAccessible::TreeItem, UIA_TreeItemControlTypeId},
+ {QAccessible::PageTab, UIA_TabItemControlTypeId},
+ {QAccessible::PropertyPage, UIA_CustomControlTypeId},
+ {QAccessible::Indicator, UIA_CustomControlTypeId},
+ {QAccessible::Graphic, UIA_ImageControlTypeId},
+ {QAccessible::StaticText, UIA_EditControlTypeId},
+ {QAccessible::EditableText, UIA_EditControlTypeId},
+ {QAccessible::Button, UIA_ButtonControlTypeId},
+ {QAccessible::CheckBox, UIA_CheckBoxControlTypeId},
+ {QAccessible::RadioButton, UIA_RadioButtonControlTypeId},
+ {QAccessible::ComboBox, UIA_ComboBoxControlTypeId},
+ {QAccessible::ProgressBar, UIA_ProgressBarControlTypeId},
+ {QAccessible::Dial, UIA_CustomControlTypeId},
+ {QAccessible::HotkeyField, UIA_CustomControlTypeId},
+ {QAccessible::Slider, UIA_SliderControlTypeId},
+ {QAccessible::SpinBox, UIA_SpinnerControlTypeId},
+ {QAccessible::Canvas, UIA_CustomControlTypeId},
+ {QAccessible::Animation, UIA_CustomControlTypeId},
+ {QAccessible::Equation, UIA_CustomControlTypeId},
+ {QAccessible::ButtonDropDown, UIA_ButtonControlTypeId},
+ {QAccessible::ButtonMenu, UIA_ButtonControlTypeId},
+ {QAccessible::ButtonDropGrid, UIA_ButtonControlTypeId},
+ {QAccessible::Whitespace, UIA_CustomControlTypeId},
+ {QAccessible::PageTabList, UIA_TabControlTypeId},
+ {QAccessible::Clock, UIA_CustomControlTypeId},
+ {QAccessible::Splitter, UIA_CustomControlTypeId},
+ };
+
+ return mapping.value(role, UIA_CustomControlTypeId);
+}
+
+// True if a character can be a separator for a text unit.
+bool isTextUnitSeparator(TextUnit unit, const QChar &ch)
+{
+ return (((unit == TextUnit_Word) || (unit == TextUnit_Format)) && ch.isSpace())
+ || ((unit == TextUnit_Line) && (ch.toLatin1() == '\n'));
+}
+
+} // namespace QWindowsUiAutomation
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
new file mode 100644
index 0000000000..15f4d6e8ba
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAUTILS_H
+#define QWINDOWSUIAUTILS_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include <QtCore/QString>
+#include <QtCore/qt_windows.h>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtGui/QWindow>
+#include <QtCore/QDebug>
+#include <QtCore/QRect>
+#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWindowsUiAutomation {
+
+QWindow *windowForAccessible(const QAccessibleInterface *accessible);
+
+HWND hwndForAccessible(const QAccessibleInterface *accessible);
+
+void rectToNativeUiaRect(const QRect &rect, const QWindow *w, UiaRect *uiaRect);
+
+void nativeUiaPointToPoint(const UiaPoint &uiaPoint, const QWindow *w, QPoint *point);
+
+long roleToControlTypeId(QAccessible::Role role);
+
+bool isTextUnitSeparator(TextUnit unit, const QChar &ch);
+
+void clearVariant(VARIANT *variant);
+
+void setVariantI4(int value, VARIANT *variant);
+
+void setVariantBool(bool value, VARIANT *variant);
+
+void setVariantDouble(double value, VARIANT *variant);
+
+BSTR bStrFromQString(const QString &value);
+
+void setVariantString(const QString &value, VARIANT *variant);
+
+} // namespace QWindowsUiAutomation
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAUTILS_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
new file mode 100644
index 0000000000..ef7d564e22
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiavalueprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaValueProvider::QWindowsUiaValueProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaValueProvider::~QWindowsUiaValueProvider()
+{
+}
+
+// Sets the value associated with the control.
+HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::SetValue(LPCWSTR val)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ // First sets the value as a text.
+ QString strVal = QString::fromUtf16(reinterpret_cast<const ushort *>(val));
+ accessible->setText(QAccessible::Value, strVal);
+
+ // Then, if the control supports the value interface (range value)
+ // and the supplied text can be converted to a number, and that number
+ // lies within the min/max limits, sets it as the control's current (numeric) value.
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ bool ok = false;
+ double numval = strVal.toDouble(&ok);
+ if (ok) {
+ double minimum = valueInterface->minimumValue().toDouble();
+ double maximum = valueInterface->maximumValue().toDouble();
+ if ((numval >= minimum) && (numval <= maximum)) {
+ valueInterface->setCurrentValue(QVariant(numval));
+ }
+ }
+ }
+ return S_OK;
+}
+
+// True for read-only controls.
+HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::get_IsReadOnly(BOOL *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = FALSE;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = accessible->state().readOnly;
+ return S_OK;
+}
+
+// Returns the value in text form.
+HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::get_Value(BSTR *pRetVal)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!pRetVal)
+ return E_INVALIDARG;
+ *pRetVal = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ *pRetVal = bStrFromQString(accessible->text(QAccessible::Value));
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
new file mode 100644
index 0000000000..db54fc0a46
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAVALUEPROVIDER_H
+#define QWINDOWSUIAVALUEPROVIDER_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Value control pattern provider.
+// Supported for all controls that can return text(QAccessible::Value).
+class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IValueProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaValueProvider)
+public:
+ explicit QWindowsUiaValueProvider(QAccessible::Id id);
+ virtual ~QWindowsUiaValueProvider();
+
+ // IValueProvider
+ HRESULT STDMETHODCALLTYPE SetValue(LPCWSTR val);
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE get_Value(BSTR *pRetVal);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSUIAVALUEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
new file mode 100644
index 0000000000..e3071766d9
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
@@ -0,0 +1,43 @@
+qtHaveModule(windowsuiautomation_support-private): \
+ QT += windowsuiautomation_support-private
+
+SOURCES += \
+ $$PWD/qwindowsuiaaccessibility.cpp \
+ $$PWD/qwindowsuiaprovidercache.cpp \
+ $$PWD/qwindowsuiamainprovider.cpp \
+ $$PWD/qwindowsuiabaseprovider.cpp \
+ $$PWD/qwindowsuiavalueprovider.cpp \
+ $$PWD/qwindowsuiatextprovider.cpp \
+ $$PWD/qwindowsuiatextrangeprovider.cpp \
+ $$PWD/qwindowsuiatoggleprovider.cpp \
+ $$PWD/qwindowsuiaselectionprovider.cpp \
+ $$PWD/qwindowsuiaselectionitemprovider.cpp \
+ $$PWD/qwindowsuiainvokeprovider.cpp \
+ $$PWD/qwindowsuiarangevalueprovider.cpp \
+ $$PWD/qwindowsuiatableprovider.cpp \
+ $$PWD/qwindowsuiatableitemprovider.cpp \
+ $$PWD/qwindowsuiagridprovider.cpp \
+ $$PWD/qwindowsuiagriditemprovider.cpp \
+ $$PWD/qwindowsuiautils.cpp
+
+HEADERS += \
+ $$PWD/qwindowsuiaaccessibility.h \
+ $$PWD/qwindowsuiaprovidercache.h \
+ $$PWD/qwindowsuiamainprovider.h \
+ $$PWD/qwindowsuiabaseprovider.h \
+ $$PWD/qwindowsuiavalueprovider.h \
+ $$PWD/qwindowsuiatextprovider.h \
+ $$PWD/qwindowsuiatextrangeprovider.h \
+ $$PWD/qwindowsuiatoggleprovider.h \
+ $$PWD/qwindowsuiaselectionprovider.h \
+ $$PWD/qwindowsuiaselectionitemprovider.h \
+ $$PWD/qwindowsuiainvokeprovider.h \
+ $$PWD/qwindowsuiarangevalueprovider.h \
+ $$PWD/qwindowsuiatableprovider.h \
+ $$PWD/qwindowsuiatableitemprovider.h \
+ $$PWD/qwindowsuiagridprovider.h \
+ $$PWD/qwindowsuiagriditemprovider.h \
+ $$PWD/qwindowsuiautils.h
+
+mingw: LIBS *= -luuid
+
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index b7790a66e3..f4c396f7c5 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -53,7 +53,7 @@ HEADERS += \
$$PWD/qwindowsservices.h \
$$PWD/qwindowsnativeinterface.h \
$$PWD/qwindowsopengltester.h \
- $$PWD/qwindowsthreadpoolrunner.h
+ $$PWD/qwindowsthreadpoolrunner.h \
$$PWD/qwin10helpers.h
INCLUDEPATH += $$PWD
@@ -109,7 +109,7 @@ qtConfig(imageformat_png):RESOURCES += $$PWD/cursors.qrc
RESOURCES += $$PWD/openglblacklists.qrc
-qtConfig(accessibility): include($$PWD/accessible/accessible.pri)
+qtConfig(accessibility): include($$PWD/uiautomation/uiautomation.pri)
qtConfig(combined-angle-lib) {
DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME}
diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.cpp b/src/plugins/platforms/winrt/qwinrtclipboard.cpp
index 117cb515df..05c34b82f8 100644
--- a/src/plugins/platforms/winrt/qwinrtclipboard.cpp
+++ b/src/plugins/platforms/winrt/qwinrtclipboard.cpp
@@ -59,7 +59,7 @@ typedef IEventHandler<IInspectable *> ContentChangedHandler;
QT_BEGIN_NAMESPACE
QWinRTClipboard::QWinRTClipboard()
- : m_mimeData(Q_NULLPTR)
+ : m_mimeData(nullptr)
{
QEventDispatcherWinRT::runOnXamlThread([this]() {
HRESULT hr;
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index 28a5f73e6e..3c918df935 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -89,7 +89,7 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
case Qt::BlankCursor:
hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow]() {
- coreWindow->put_PointerCursor(Q_NULLPTR);
+ coreWindow->put_PointerCursor(nullptr);
return S_OK;
});
RETURN_VOID_IF_FAILED("Failed to set blank native cursor");
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp
index 43c406e1fb..0c918230b3 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.cpp
+++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp
@@ -104,7 +104,7 @@ class DragThreadTransferData : public QObject
public slots:
void handleDrag();
public:
- explicit DragThreadTransferData(QObject *parent = Q_NULLPTR);
+ explicit DragThreadTransferData(QObject *parent = nullptr);
QWindow *window;
QWinRTInternalMimeData *mime;
QPoint point;
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index 62eacba89b..3c90334c8c 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -83,7 +83,7 @@ public:
}
HRESULT __stdcall GetView(IVectorView<HSTRING> **view)
{
- *view = Q_NULLPTR;
+ *view = nullptr;
return E_NOTIMPL;
}
HRESULT __stdcall IndexOf(HSTRING value, quint32 *index, boolean *found)
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index f037c516b5..76efdf6cc8 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -144,7 +144,7 @@ QAbstractFileEngine *QWinRTFileEngineHandler::create(const QString &fileName) co
if (file != d->files.end())
return new QWinRTFileEngine(fileName, file.value().Get());
- return Q_NULLPTR;
+ return nullptr;
}
static HRESULT getDestinationFolder(const QString &fileName, const QString &newFileName,
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index c370c2ec50..7b9502f9ab 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -497,7 +497,7 @@ QWinRTScreen::QWinRTScreen()
Q_D(QWinRTScreen);
qCDebug(lcQpaWindows) << __FUNCTION__;
d->orientation = Qt::PrimaryOrientation;
- d->touchDevice = Q_NULLPTR;
+ d->touchDevice = nullptr;
HRESULT hr;
ComPtr<Xaml::IWindowStatics> windowStatics;
@@ -540,7 +540,7 @@ QWinRTScreen::QWinRTScreen()
Q_ASSERT_SUCCEEDED(hr);
d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
// Set initial pixel density
- onDpiChanged(Q_NULLPTR, Q_NULLPTR);
+ onDpiChanged(nullptr, nullptr);
d->orientation = d->nativeOrientation;
ComPtr<IApplicationViewStatics2> applicationViewStatics;
@@ -764,7 +764,7 @@ void QWinRTScreen::initialize()
Q_ASSERT_SUCCEEDED(hr);
hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
Q_ASSERT_SUCCEEDED(hr);
- onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
+ onOrientationChanged(nullptr, nullptr);
onVisibilityChanged(nullptr, nullptr);
hr = d->redirect->add_PointerRoutedReleased(Callback<RedirectHandler>(this, &QWinRTScreen::onRedirectReleased).Get(), &d->redirectTokens[&ICorePointerRedirector::remove_PointerRoutedReleased]);
@@ -864,7 +864,7 @@ void QWinRTScreen::removeWindow(QWindow *window)
const Qt::WindowType type = window->type();
if (wasTopWindow && type != Qt::Popup && type != Qt::ToolTip && type != Qt::Tool)
- QWindowSystemInterface::handleWindowActivated(Q_NULLPTR, Qt::OtherFocusReason);
+ QWindowSystemInterface::handleWindowActivated(nullptr, Qt::OtherFocusReason);
handleExpose();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
#ifndef QT_NO_DRAGANDDROP
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index a8992450b9..9604b4bbaa 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -70,8 +70,8 @@ public:
qreal devicePixelRatio() const override;
void setWindowState(Qt::WindowStates state) override;
- bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
- bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+ bool setMouseGrabEnabled(bool grab) override;
+ bool setKeyboardGrabEnabled(bool grab) override;
EGLSurface eglSurface() const;
void createEglSurface(EGLDisplay display, EGLConfig config);
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
index 926e5e22df..07e983a499 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h
@@ -69,7 +69,7 @@ public:
#endif
virtual QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const = 0;
- virtual QXcbNativeInterfaceHandler *nativeInterfaceHandler() const { return Q_NULLPTR; }
+ virtual QXcbNativeInterfaceHandler *nativeInterfaceHandler() const { return nullptr; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp
index ac992b859d..e18656c6ec 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp
@@ -56,37 +56,37 @@ QXcbNativeInterfaceHandler::~QXcbNativeInterfaceHandler()
QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForIntegration(const QByteArray &resource) const
{
Q_UNUSED(resource);
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForContext(const QByteArray &resource) const
{
Q_UNUSED(resource);
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForScreen(const QByteArray &resource) const
{
Q_UNUSED(resource);
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForWindow(const QByteArray &resource) const
{
Q_UNUSED(resource);
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForBackingStore(const QByteArray &resource) const
{
Q_UNUSED(resource);
- return Q_NULLPTR;
+ return nullptr;
}
QFunctionPointer QXcbNativeInterfaceHandler::platformFunction(const QByteArray &function) const
{
Q_UNUSED(function);
- return Q_NULLPTR;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
index fe50afa62a..c3ce8d8745 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
@@ -59,6 +59,14 @@ public:
void swapBuffers(QPlatformSurface *surface)
{
QEGLPlatformContext::swapBuffers(surface);
+ if (surface->surface()->surfaceClass() == QSurface::Window) {
+ QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface);
+ // OpenGL context might be bound to a non-gui thread use QueuedConnection to sync
+ // the window from the platformWindow's thread as QXcbWindow is no QObject, an
+ // event is sent to QXcbConnection. (this is faster than a metacall)
+ if (platformWindow->needsSync())
+ platformWindow->postSyncWindowRequest();
+ }
}
bool makeCurrent(QPlatformSurface *surface)
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
index 7aa1d631df..fe18bc24db 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
QXcbEglIntegration::QXcbEglIntegration()
- : m_connection(Q_NULLPTR)
+ : m_connection(nullptr)
, m_egl_display(EGL_NO_DISPLAY)
{
qCDebug(lcQpaGl) << "Xcb EGL gl-integration created";
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp
index 30f5e3a00d..c0e3f820fe 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp
@@ -77,7 +77,7 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbEglNativeInte
default:
break;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForContextFunction QXcbEglNativeInterfaceHandler::nativeResourceFunctionForContext(const QByteArray &resource) const
@@ -90,7 +90,7 @@ QPlatformNativeInterface::NativeResourceForContextFunction QXcbEglNativeInterfac
default:
break;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForWindowFunction QXcbEglNativeInterfaceHandler::nativeResourceFunctionForWindow(const QByteArray &resource) const
@@ -101,7 +101,7 @@ QPlatformNativeInterface::NativeResourceForWindowFunction QXcbEglNativeInterface
default:
break;
}
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbEglNativeInterfaceHandler::eglDisplay()
@@ -114,11 +114,11 @@ void *QXcbEglNativeInterfaceHandler::eglDisplay()
void *QXcbEglNativeInterfaceHandler::eglDisplayForWindow(QWindow *window)
{
Q_ASSERT(window);
- if (window->supportsOpenGL() && window->handle() == Q_NULLPTR)
+ if (window->supportsOpenGL() && window->handle() == nullptr)
return eglDisplay();
else if (window->supportsOpenGL())
return static_cast<QXcbEglWindow *>(window->handle())->glIntegration()->eglDisplay();
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbEglNativeInterfaceHandler::eglContextForContext(QOpenGLContext *context)
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
index 9c3fd26d49..65beac227c 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
QXcbEglWindow::QXcbEglWindow(QWindow *window, QXcbEglIntegration *glIntegration)
: QXcbWindow(window)
, m_glIntegration(glIntegration)
- , m_config(Q_NULLPTR)
+ , m_config(nullptr)
, m_surface(EGL_NO_SURFACE)
{
}
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 3bc8590d36..56a737e882 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -321,7 +321,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
if (!m_context && m_shareContext) {
// re-try without a shared glx context
m_shareContext = 0;
- m_context = glXCreateContext(m_display, visualInfo, Q_NULLPTR, true);
+ m_context = glXCreateContext(m_display, visualInfo, nullptr, true);
}
// Create a temporary window so that we can make the new context current
@@ -470,7 +470,7 @@ static QXcbScreen *screenForPlatformSurface(QPlatformSurface *surface)
} else if (surfaceClass == QSurface::Offscreen) {
return static_cast<QXcbScreen *>(static_cast<QGLXPbuffer *>(surface)->screen());
}
- return Q_NULLPTR;
+ return nullptr;
}
QVariant QGLXContext::nativeHandle() const
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index 377066df61..13f03f8bf3 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE
#endif
QXcbGlxIntegration::QXcbGlxIntegration()
- : m_connection(Q_NULLPTR)
+ : m_connection(nullptr)
, m_glx_first_event(0)
{
qCDebug(lcQpaGl) << "Xcb GLX gl-integration created";
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp
index 638fdd46b5..e9bb4460ff 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp
@@ -72,7 +72,7 @@ QPlatformNativeInterface::NativeResourceForContextFunction QXcbGlxNativeInterfac
default:
break;
}
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbGlxNativeInterfaceHandler::glxContextForContext(QOpenGLContext *context)
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
index 05275cd2c9..5e406017ca 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
@@ -58,7 +58,7 @@ const xcb_visualtype_t *QXcbGlxWindow::createVisual()
{
QXcbScreen *scr = xcbScreen();
if (!scr)
- return Q_NULLPTR;
+ return nullptr;
qCDebug(lcQpaGl) << "Requested format before FBConfig/Visual selection:" << m_format;
@@ -74,7 +74,7 @@ const xcb_visualtype_t *QXcbGlxWindow::createVisual()
XVisualInfo *visualInfo = qglx_findVisualInfo(dpy, scr->screenNumber(), &m_format, GLX_WINDOW_BIT, flags);
if (!visualInfo) {
qWarning() << "No XVisualInfo for format" << m_format;
- return Q_NULLPTR;
+ return nullptr;
}
const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
XFree(visualInfo);
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
index bdf78b5255..9b31998620 100644
--- a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
@@ -121,7 +121,7 @@ void QXcbNativeBackingStore::flush(QWindow *window, const QRegion &region, const
else
#endif
{
- GC gc = XCreateGC(display(), wid, 0, Q_NULLPTR);
+ GC gc = XCreateGC(display(), wid, 0, nullptr);
if (clipRects.size() != 1)
XSetClipRectangles(display(), gc, 0, 0, clipRects.data(), clipRects.size(), YXBanded);
@@ -161,7 +161,7 @@ void QXcbNativeBackingStore::resize(const QSize &size, const QRegion &staticCont
QRect br = staticContents.boundingRect().intersected(QRect(QPoint(0, 0), size));
if (!br.isEmpty()) {
- GC gc = XCreateGC(display(), to, 0, Q_NULLPTR);
+ GC gc = XCreateGC(display(), to, 0, nullptr);
XCopyArea(display(), from, to, gc, br.x(), br.y(), br.width(), br.height(), br.x(), br.y());
XFreeGC(display(), gc);
}
@@ -178,7 +178,7 @@ bool QXcbNativeBackingStore::scroll(const QRegion &area, int dx, int dy)
QRect rect = area.boundingRect();
Pixmap pix = qt_x11PixmapHandle(m_pixmap);
- GC gc = XCreateGC(display(), pix, 0, Q_NULLPTR);
+ GC gc = XCreateGC(display(), pix, 0, nullptr);
XCopyArea(display(), pix, pix, gc,
rect.x(), rect.y(), rect.width(), rect.height(),
rect.x()+dx, rect.y()+dy);
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
index 5338b5fe08..9b01c0a3fc 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
@@ -62,10 +62,10 @@ public:
QX11PaintEngine();
~QX11PaintEngine();
- bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
- bool end() Q_DECL_OVERRIDE;
+ bool begin(QPaintDevice *pdev) override;
+ bool end() override;
- void updateState(const QPaintEngineState &state) Q_DECL_OVERRIDE;
+ void updateState(const QPaintEngineState &state) override;
void updatePen(const QPen &pen);
void updateBrush(const QBrush &brush, const QPointF &pt);
@@ -74,31 +74,31 @@ public:
void updateMatrix(const QTransform &matrix);
void updateClipRegion_dev(const QRegion &region, Qt::ClipOperation op);
- void drawLines(const QLine *lines, int lineCount) Q_DECL_OVERRIDE;
- void drawLines(const QLineF *lines, int lineCount) Q_DECL_OVERRIDE;
+ void drawLines(const QLine *lines, int lineCount) override;
+ void drawLines(const QLineF *lines, int lineCount) override;
- void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE;
- void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE;
+ void drawRects(const QRect *rects, int rectCount) override;
+ void drawRects(const QRectF *rects, int rectCount) override;
- void drawPoints(const QPoint *points, int pointCount) Q_DECL_OVERRIDE;
- void drawPoints(const QPointF *points, int pointCount) Q_DECL_OVERRIDE;
+ void drawPoints(const QPoint *points, int pointCount) override;
+ void drawPoints(const QPointF *points, int pointCount) override;
- void drawEllipse(const QRect &r) Q_DECL_OVERRIDE;
- void drawEllipse(const QRectF &r) Q_DECL_OVERRIDE;
+ void drawEllipse(const QRect &r) override;
+ void drawEllipse(const QRectF &r) override;
- virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE;
- inline void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE
+ virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override;
+ inline void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) override
{ QPaintEngine::drawPolygon(points, pointCount, mode); }
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
- void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) Q_DECL_OVERRIDE;
- void drawPath(const QPainterPath &path) Q_DECL_OVERRIDE;
- void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE;
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
+ void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override;
+ void drawPath(const QPainterPath &path) override;
+ void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
void drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
- Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
+ Qt::ImageConversionFlags flags = Qt::AutoColor) override;
virtual Drawable handle() const;
- inline Type type() const Q_DECL_OVERRIDE { return QPaintEngine::X11; }
+ inline Type type() const override { return QPaintEngine::X11; }
QPainter::RenderHints supportedRenderHints() const;
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
index 8bff9e0d93..7392cbfccf 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
@@ -62,22 +62,22 @@ public:
QX11PlatformPixmap(PixelType pixelType);
~QX11PlatformPixmap();
- QPlatformPixmap *createCompatiblePlatformPixmap() const Q_DECL_OVERRIDE;
- void resize(int width, int height) Q_DECL_OVERRIDE;
- void fromImage(const QImage &img, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
- void copy(const QPlatformPixmap *data, const QRect &rect) Q_DECL_OVERRIDE;
- bool scroll(int dx, int dy, const QRect &rect) Q_DECL_OVERRIDE;
- int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
- void fill(const QColor &fillColor) Q_DECL_OVERRIDE;
- QBitmap mask() const Q_DECL_OVERRIDE;
- void setMask(const QBitmap &mask) Q_DECL_OVERRIDE;
- bool hasAlphaChannel() const Q_DECL_OVERRIDE;
- QPixmap transformed(const QTransform &matrix, Qt::TransformationMode mode) const Q_DECL_OVERRIDE;
- QImage toImage() const Q_DECL_OVERRIDE;
- QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
+ QPlatformPixmap *createCompatiblePlatformPixmap() const override;
+ void resize(int width, int height) override;
+ void fromImage(const QImage &img, Qt::ImageConversionFlags flags) override;
+ void copy(const QPlatformPixmap *data, const QRect &rect) override;
+ bool scroll(int dx, int dy, const QRect &rect) override;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+ void fill(const QColor &fillColor) override;
+ QBitmap mask() const override;
+ void setMask(const QBitmap &mask) override;
+ bool hasAlphaChannel() const override;
+ QPixmap transformed(const QTransform &matrix, Qt::TransformationMode mode) const override;
+ QImage toImage() const override;
+ QImage toImage(const QRect &rect) const override;
+ QPaintEngine *paintEngine() const override;
+ qreal devicePixelRatio() const override;
+ void setDevicePixelRatio(qreal scaleFactor) override;
inline Drawable handle() const { return hd; }
inline Picture x11PictureHandle() const { return picture; }
@@ -129,7 +129,7 @@ inline QX11PlatformPixmap *qt_x11Pixmap(const QPixmap &pixmap)
{
return (pixmap.handle() && pixmap.handle()->classId() == QPlatformPixmap::X11Class)
? static_cast<QX11PlatformPixmap *>(pixmap.handle())
- : Q_NULLPTR;
+ : nullptr;
}
inline Picture qt_x11PictureHandle(const QPixmap &pixmap)
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
index 4a587ceb36..57b1882e4b 100644
--- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
@@ -44,7 +44,7 @@
QT_BEGIN_NAMESPACE
-QXcbX11Data *qt_x11Data = Q_NULLPTR;
+QXcbX11Data *qt_x11Data = nullptr;
void qt_xcb_native_x11_info_init(QXcbConnection *conn)
{
@@ -111,7 +111,7 @@ void qt_xcb_native_x11_info_init(QXcbConnection *conn)
QVector<XRectangle> qt_region_to_xrectangles(const QRegion &r)
{
const int numRects = r.rectCount();
- const QVector<QRect> input = r.rects();
+ const auto input = r.begin();
QVector<XRectangle> output(numRects);
for (int i = 0; i < numRects; ++i) {
const QRect &in = input[i];
@@ -128,7 +128,7 @@ class QXcbX11InfoData : public QSharedData, public QX11InfoData
{};
QXcbX11Info::QXcbX11Info()
- : d(Q_NULLPTR)
+ : d(nullptr)
{}
QXcbX11Info::~QXcbX11Info()
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 420d1ac7c5..1cf45c96d1 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -69,6 +69,8 @@ public:
QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format);
~QXcbShmImage() { destroy(); }
+ void flushScrolledRegion(bool clientSideScroll);
+
bool scroll(const QRegion &area, int dx, int dy);
QImage *image() { return &m_qimage; }
@@ -86,7 +88,8 @@ private:
void destroy();
void ensureGC(xcb_drawable_t dst);
- void flushPixmap(const QRegion &region);
+ void shmPutImage(xcb_drawable_t drawable, const QRegion &region, const QPoint &offset = QPoint());
+ void flushPixmap(const QRegion &region, bool fullRegion = false);
void setClip(const QRegion &region);
xcb_shm_segment_info_t m_shm_info;
@@ -99,18 +102,26 @@ private:
xcb_gcontext_t m_gc;
xcb_drawable_t m_gc_drawable;
- // When using shared memory this is the region currently shared with the server
- QRegion m_dirtyShm;
-
+ // When using shared memory these variables are used only for server-side scrolling.
// When not using shared memory, we maintain a server-side pixmap with the backing
// store as well as repainted content not yet flushed to the pixmap. We only flush
// the regions we need and only when these are marked dirty. This way we can just
// do a server-side copy on expose instead of sending the pixels every time
xcb_pixmap_t m_xcb_pixmap;
QRegion m_pendingFlush;
+
+ // This is the scrolled region which is stored in server-side pixmap
+ QRegion m_scrolledRegion;
+
+ // When using shared memory this is the region currently shared with the server
+ QRegion m_dirtyShm;
+
+ // When not using shared memory this is a temporary buffer which is uploaded
+ // as a pixmap region to server
QByteArray m_flushBuffer;
bool m_hasAlpha;
+ bool m_clientSideScroll;
};
class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer
@@ -145,10 +156,11 @@ private:
QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format)
: QXcbObject(screen->connection())
- , m_graphics_buffer(Q_NULLPTR)
+ , m_graphics_buffer(nullptr)
, m_gc(0)
, m_gc_drawable(0)
, m_xcb_pixmap(0)
+ , m_clientSideScroll(false)
{
const xcb_format_t *fmt = connection()->formatForDepth(depth);
Q_ASSERT(fmt);
@@ -202,13 +214,59 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format);
m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage);
- if (!hasShm()) {
- m_xcb_pixmap = xcb_generate_id(xcb_connection());
- xcb_create_pixmap(xcb_connection(),
- m_xcb_image->depth,
- m_xcb_pixmap,
- screen->screen()->root,
- m_xcb_image->width, m_xcb_image->height);
+ m_xcb_pixmap = xcb_generate_id(xcb_connection());
+ xcb_create_pixmap(xcb_connection(),
+ m_xcb_image->depth,
+ m_xcb_pixmap,
+ screen->screen()->root,
+ m_xcb_image->width, m_xcb_image->height);
+}
+
+void QXcbShmImage::flushScrolledRegion(bool clientSideScroll)
+{
+ if (m_clientSideScroll == clientSideScroll)
+ return;
+
+ m_clientSideScroll = clientSideScroll;
+
+ if (m_scrolledRegion.isNull())
+ return;
+
+ if (hasShm() && m_dirtyShm.intersects(m_scrolledRegion)) {
+ connection()->sync();
+ m_dirtyShm = QRegion();
+ }
+
+ if (m_clientSideScroll) {
+ // Copy scrolled image region from server-side pixmap to client-side memory
+ for (const QRect &rect : m_scrolledRegion) {
+ const int w = rect.width();
+ const int h = rect.height();
+
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_image,
+ xcb_connection(),
+ m_xcb_image->format,
+ m_xcb_pixmap,
+ rect.x(), rect.y(),
+ w, h,
+ ~0u);
+
+ if (reply && reply->depth == m_xcb_image->depth) {
+ const QImage img(xcb_get_image_data(reply.get()), w, h, m_qimage.format());
+
+ QPainter p(&m_qimage);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.drawImage(rect.topLeft(), img);
+ }
+ }
+ m_scrolledRegion = QRegion();
+ } else {
+ // Copy scrolled image region from client-side memory to server-side pixmap
+ ensureGC(m_xcb_pixmap);
+ if (hasShm())
+ shmPutImage(m_xcb_pixmap, m_scrolledRegion);
+ else
+ flushPixmap(m_scrolledRegion, true);
}
}
@@ -216,21 +274,28 @@ extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &o
bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
{
- if (image()->isNull())
- return false;
+ const QRect bounds(QPoint(), size());
+ const QRegion scrollArea(area & bounds);
+ const QPoint delta(dx, dy);
- if (hasShm())
- preparePaint(area);
+ if (m_clientSideScroll) {
+ if (m_qimage.isNull())
+ return false;
- const QPoint delta(dx, dy);
- for (const QRect &rect : area)
- qt_scrollRectInImage(*image(), rect, delta);
+ if (hasShm())
+ preparePaint(scrollArea);
+
+ for (const QRect &rect : scrollArea)
+ qt_scrollRectInImage(m_qimage, rect, delta);
+ } else {
+ if (hasShm())
+ shmPutImage(m_xcb_pixmap, m_pendingFlush.intersected(scrollArea));
+ else
+ flushPixmap(scrollArea);
- if (m_xcb_pixmap) {
- flushPixmap(area);
ensureGC(m_xcb_pixmap);
- const QRect bounds(QPoint(0, 0), size());
- for (const QRect &src : area) {
+
+ for (const QRect &src : scrollArea) {
const QRect dst = src.translated(delta).intersected(bounds);
xcb_copy_area(xcb_connection(),
m_xcb_pixmap,
@@ -242,6 +307,12 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
}
}
+ m_scrolledRegion |= scrollArea.translated(delta).intersected(bounds);
+ if (hasShm()) {
+ m_pendingFlush -= scrollArea;
+ m_pendingFlush -= m_scrolledRegion;
+ }
+
return true;
}
@@ -265,12 +336,10 @@ void QXcbShmImage::destroy()
if (m_gc)
xcb_free_gc(xcb_connection(), m_gc);
delete m_graphics_buffer;
- m_graphics_buffer = Q_NULLPTR;
+ m_graphics_buffer = nullptr;
- if (m_xcb_pixmap) {
- xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
- m_xcb_pixmap = 0;
- }
+ xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
+ m_xcb_pixmap = 0;
}
void QXcbShmImage::ensureGC(xcb_drawable_t dst)
@@ -353,10 +422,35 @@ static inline quint32 round_up_scanline(quint32 base, quint32 pad)
return (base + pad - 1) & -pad;
}
-void QXcbShmImage::flushPixmap(const QRegion &region)
+void QXcbShmImage::shmPutImage(xcb_drawable_t drawable, const QRegion &region, const QPoint &offset)
+{
+ for (const QRect &rect : region) {
+ const QPoint source = rect.translated(offset).topLeft();
+ xcb_shm_put_image(xcb_connection(),
+ drawable,
+ m_gc,
+ m_xcb_image->width,
+ m_xcb_image->height,
+ source.x(), source.y(),
+ rect.width(), rect.height(),
+ rect.x(), rect.y(),
+ m_xcb_image->depth,
+ m_xcb_image->format,
+ 0, // send event?
+ m_shm_info.shmseg,
+ m_xcb_image->data - m_shm_info.shmaddr);
+ }
+ m_dirtyShm |= region.translated(offset);
+}
+
+void QXcbShmImage::flushPixmap(const QRegion &region, bool fullRegion)
{
- const QVector<QRect> rects = m_pendingFlush.intersected(region).rects();
- m_pendingFlush -= region;
+ if (!fullRegion) {
+ auto actualRegion = m_pendingFlush.intersected(region);
+ m_pendingFlush -= region;
+ flushPixmap(actualRegion, true);
+ return;
+ }
xcb_image_t xcb_subimage;
memset(&xcb_subimage, 0, sizeof(xcb_image_t));
@@ -372,7 +466,7 @@ void QXcbShmImage::flushPixmap(const QRegion &region)
const bool needsByteSwap = xcb_subimage.byte_order != m_xcb_image->byte_order;
- for (const QRect &rect : rects) {
+ for (const QRect &rect : region) {
// We must make sure that each request is not larger than max_req_size.
// Each request takes req_size + m_xcb_image->stride * height bytes.
static const uint32_t req_size = sizeof(xcb_put_image_request_t);
@@ -425,16 +519,7 @@ void QXcbShmImage::setClip(const QRegion &region)
static const uint32_t values[] = { XCB_NONE };
xcb_change_gc(xcb_connection(), m_gc, mask, values);
} else {
- const QVector<QRect> qrects = region.rects();
- QVector<xcb_rectangle_t> xcb_rects(qrects.size());
-
- for (int i = 0; i < qrects.size(); i++) {
- xcb_rects[i].x = qrects[i].x();
- xcb_rects[i].y = qrects[i].y();
- xcb_rects[i].width = qrects[i].width();
- xcb_rects[i].height = qrects[i].height();
- }
-
+ const auto xcb_rects = qRegionToXcbRectangleList(region);
xcb_set_clip_rectangles(xcb_connection(),
XCB_CLIP_ORDERING_YX_BANDED,
m_gc,
@@ -445,29 +530,32 @@ void QXcbShmImage::setClip(const QRegion &region)
void QXcbShmImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset)
{
+ Q_ASSERT(!m_clientSideScroll);
+
ensureGC(dst);
setClip(region);
- const QRect bounds = region.boundingRect();
- const QPoint target = bounds.topLeft();
- const QRect source = bounds.translated(offset);
-
if (hasShm()) {
- xcb_shm_put_image(xcb_connection(),
+ // Copy scrolled area on server-side from pixmap to window
+ const QRegion scrolledRegion = m_scrolledRegion.translated(-offset);
+ for (const QRect &rect : scrolledRegion) {
+ const QPoint source = rect.translated(offset).topLeft();
+ xcb_copy_area(xcb_connection(),
+ m_xcb_pixmap,
dst,
m_gc,
- m_xcb_image->width,
- m_xcb_image->height,
source.x(), source.y(),
- source.width(), source.height(),
- target.x(), target.y(),
- m_xcb_image->depth,
- m_xcb_image->format,
- 0, // send event?
- m_shm_info.shmseg,
- m_xcb_image->data - m_shm_info.shmaddr);
- m_dirtyShm |= region.translated(offset);
+ rect.x(), rect.y(),
+ rect.width(), rect.height());
+ }
+
+ // Copy non-scrolled image from client-side memory to server-side window
+ const QRegion notScrolledArea = region - scrolledRegion;
+ shmPutImage(dst, notScrolledArea, offset);
} else {
+ const QRect bounds = region.boundingRect();
+ const QPoint target = bounds.topLeft();
+ const QRect source = bounds.translated(offset);
flushPixmap(region);
xcb_copy_area(xcb_connection(),
m_xcb_pixmap,
@@ -489,9 +577,9 @@ void QXcbShmImage::preparePaint(const QRegion &region)
connection()->sync();
m_dirtyShm = QRegion();
}
- } else {
- m_pendingFlush |= region;
}
+ m_scrolledRegion -= region;
+ m_pendingFlush |= region;
}
QXcbBackingStore::QXcbBackingStore(QWindow *window)
@@ -565,7 +653,7 @@ QImage QXcbBackingStore::toImage() const
QPlatformGraphicsBuffer *QXcbBackingStore::graphicsBuffer() const
{
- return m_image ? m_image->graphicsBuffer() : Q_NULLPTR;
+ return m_image ? m_image->graphicsBuffer() : nullptr;
}
void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
@@ -573,6 +661,8 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
if (!m_image || m_image->size().isEmpty())
return;
+ m_image->flushScrolledRegion(false);
+
QSize imageSize = m_image->size();
QRegion clipped = region;
@@ -603,6 +693,11 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion &region, c
QPlatformTextureList *textures,
bool translucentBackground)
{
+ if (!m_image || m_image->size().isEmpty())
+ return;
+
+ m_image->flushScrolledRegion(true);
+
QPlatformBackingStore::composeAndFlush(window, region, offset, textures, translucentBackground);
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 30ab669432..b091928e8c 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -899,10 +899,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int
connection()->flush();
// sleep 50 ms, so we don't use up CPU cycles all the time.
- struct timeval usleep_tv;
- usleep_tv.tv_sec = 0;
- usleep_tv.tv_usec = 50000;
- select(0, 0, 0, 0, &usleep_tv);
+ QThread::msleep(50);
} while (timer.elapsed() < timeout);
return 0;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 536c709dbe..c5eae20266 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -369,7 +369,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
// If there are no other screens on the same virtual desktop,
// then transform the physical screen into a fake screen.
const QString nameWas = screen->name();
- screen->setOutput(XCB_NONE, Q_NULLPTR);
+ screen->setOutput(XCB_NONE, nullptr);
qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
} else {
// There is more than one screen on the same virtual desktop, remove the screen
@@ -395,7 +395,7 @@ void QXcbConnection::initializeScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
- QXcbScreen *primaryScreen = Q_NULLPTR;
+ QXcbScreen *primaryScreen = nullptr;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@@ -415,7 +415,7 @@ void QXcbConnection::initializeScreens()
qWarning("failed to get the current screen resources");
} else {
xcb_timestamp_t timestamp = 0;
- xcb_randr_output_t *outputs = Q_NULLPTR;
+ xcb_randr_output_t *outputs = nullptr;
int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get());
if (outputCount) {
timestamp = resources_current->config_timestamp;
@@ -487,7 +487,7 @@ void QXcbConnection::initializeScreens()
while (it.rem) {
xcb_xinerama_screen_info_t *screen_info = it.data;
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop,
- XCB_NONE, Q_NULLPTR,
+ XCB_NONE, nullptr,
screen_info, it.index);
siblings << screen;
m_screens << screen;
@@ -498,7 +498,7 @@ void QXcbConnection::initializeScreens()
if (siblings.isEmpty()) {
// If there are no XRandR outputs or XRandR extension is missing,
// then create a fake/legacy screen.
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, nullptr);
qCDebug(lcQpaScreen) << "created fake screen" << screen;
m_screens << screen;
if (m_primaryScreenNumber == xcbScreenNumber) {
@@ -631,7 +631,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
if (m_glIntegration && !m_glIntegration->initialize(this)) {
qCDebug(lcQpaGl) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i);
delete m_glIntegration;
- m_glIntegration = Q_NULLPTR;
+ m_glIntegration = nullptr;
}
}
if (!m_glIntegration)
@@ -689,7 +689,7 @@ QXcbScreen *QXcbConnection::primaryScreen() const
return m_screens.first();
}
- return Q_NULLPTR;
+ return nullptr;
}
void QXcbConnection::addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener)
@@ -983,6 +983,12 @@ static Qt::MouseButtons translateMouseButtons(int s)
return ret;
}
+void QXcbConnection::setButtonState(Qt::MouseButton button, bool down)
+{
+ m_buttonState.setFlag(button, down);
+ m_button = button;
+}
+
Qt::MouseButton QXcbConnection::translateMouseButton(xcb_button_t s)
{
switch (s) {
@@ -1055,7 +1061,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
// the event explicitly contains the state of the three first buttons,
// the rest we need to manage ourselves
m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
- m_buttonState |= translateMouseButton(ev->detail);
+ setButtonState(translateMouseButton(ev->detail), true);
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
@@ -1064,7 +1070,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
m_keyboard->updateXKBStateFromCore(ev->state);
m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
- m_buttonState &= ~translateMouseButton(ev->detail);
+ setButtonState(translateMouseButton(ev->detail), false);
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
@@ -1413,7 +1419,7 @@ void QXcbConnection::setFocusWindow(QWindow *w)
void QXcbConnection::setMouseGrabber(QXcbWindow *w)
{
m_mouseGrabber = w;
- m_mousePressWindow = Q_NULLPTR;
+ m_mousePressWindow = nullptr;
}
void QXcbConnection::setMousePressWindow(QXcbWindow *w)
{
@@ -2070,7 +2076,8 @@ const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
xcb_format_next(&iterator);
}
- return 0;
+ qWarning() << "XCB failed to find an xcb_format_t for depth:" << depth;
+ return nullptr;
}
void QXcbConnection::sync()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 999dc0630c..92825acb6d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -409,6 +409,15 @@ public:
const xcb_setup_t *setup() const { return m_setup; }
const xcb_format_t *formatForDepth(uint8_t depth) const;
+ bool imageNeedsEndianSwap() const
+ {
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ return m_setup->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
+#else
+ return m_setup->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
+#endif
+ }
+
QXcbKeyboard *keyboard() const { return m_keyboard; }
#ifndef QT_NO_CLIPBOARD
@@ -476,8 +485,9 @@ public:
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
xcb_window_t getQtSelectionOwner();
- void setButtonState(Qt::MouseButton button, bool down) { m_buttonState.setFlag(button, down); }
+ void setButtonState(Qt::MouseButton button, bool down);
Qt::MouseButtons buttonState() const { return m_buttonState; }
+ Qt::MouseButton button() const { return m_button; }
Qt::MouseButton translateMouseButton(xcb_button_t s);
QXcbWindow *focusWindow() const { return m_focusWindow; }
@@ -691,6 +701,7 @@ private:
bool has_render_extension = false;
Qt::MouseButtons m_buttonState = 0;
+ Qt::MouseButton m_button = Qt::NoButton;
QXcbWindow *m_focusWindow = nullptr;
QXcbWindow *m_mouseGrabber = nullptr;
@@ -701,6 +712,7 @@ private:
QXcbSystemTrayTracker *m_systemTrayTracker = nullptr;
QXcbGlIntegration *m_glIntegration = nullptr;
bool m_xiGrab = false;
+ QVector<int> m_xiMasterPointerIds;
xcb_window_t m_qtSelectionOwner = 0;
@@ -746,16 +758,18 @@ private:
#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
+struct QStdFreeDeleter {
+ void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
+};
+
#define Q_XCB_REPLY(call, ...) \
- std::unique_ptr<call##_reply_t, decltype(std::free) *>( \
- call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr), \
- std::free \
+ std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
)
#define Q_XCB_REPLY_UNCHECKED(call, ...) \
- std::unique_ptr<call##_reply_t, decltype(std::free) *>( \
- call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr), \
- std::free \
+ std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
)
template <typename T>
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 335ec344d5..ba6481082a 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -52,12 +52,6 @@
void QXcbConnection::initializeXInput2()
{
- // TODO Qt 6 (or perhaps earlier): remove these redundant env variables
- if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT"))
- const_cast<QLoggingCategory&>(lcQpaXInput()).setEnabled(QtDebugMsg, true);
- if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"))
- const_cast<QLoggingCategory&>(lcQpaXInputDevices()).setEnabled(QtDebugMsg, true);
-
Display *xDisplay = static_cast<Display *>(m_xlib_display);
if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
int xiMajor = 2;
@@ -325,12 +319,18 @@ void QXcbConnection::xi2SetupDevices()
Display *xDisplay = static_cast<Display *>(m_xlib_display);
int deviceCount = 0;
XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
+ m_xiMasterPointerIds.clear();
for (int i = 0; i < deviceCount; ++i) {
- // Only non-master pointing devices are relevant here.
- if (devices[i].use != XISlavePointer)
+ XIDeviceInfo deviceInfo = devices[i];
+ if (deviceInfo.use == XIMasterPointer) {
+ m_xiMasterPointerIds.append(deviceInfo.deviceid);
continue;
- xi2SetupDevice(&devices[i], false);
+ }
+ if (deviceInfo.use == XISlavePointer) // only slave pointer devices are relevant here
+ xi2SetupDevice(&deviceInfo, false);
}
+ if (m_xiMasterPointerIds.size() > 1)
+ qCDebug(lcQpaXInputDevices) << "multi-pointer X detected";
XIFreeDeviceInfo(devices);
}
@@ -849,62 +849,54 @@ bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const Q
bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
{
- if (grab && !canGrab())
- return false;
-
- int num_devices = 0;
Display *xDisplay = static_cast<Display *>(xlib_display());
- XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices);
- if (!info)
- return false;
-
- XIEventMask evmask;
- unsigned char mask[XIMaskLen(XI_LASTEVENT)];
- evmask.mask = mask;
- evmask.mask_len = sizeof(mask);
- memset(mask, 0, sizeof(mask));
- evmask.deviceid = XIAllMasterDevices;
-
- XISetMask(mask, XI_ButtonPress);
- XISetMask(mask, XI_ButtonRelease);
- XISetMask(mask, XI_Motion);
- XISetMask(mask, XI_Enter);
- XISetMask(mask, XI_Leave);
- XISetMask(mask, XI_TouchBegin);
- XISetMask(mask, XI_TouchUpdate);
- XISetMask(mask, XI_TouchEnd);
-
- bool grabbed = true;
- for (int i = 0; i < num_devices; i++) {
- int id = info[i].deviceid, n = 0;
- XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n);
- if (deviceInfo) {
- const bool grabbable = deviceInfo->use != XIMasterKeyboard;
- XIFreeDeviceInfo(deviceInfo);
- if (!grabbable)
- continue;
- }
- if (!grab) {
- Status result = XIUngrabDevice(xDisplay, id, CurrentTime);
- if (result != Success) {
- grabbed = false;
- qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result);
- }
- } else {
- Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync,
- XIGrabModeAsync, False, &evmask);
+ bool ok = false;
+
+ if (grab) { // grab
+ XIEventMask evmask;
+ unsigned char mask[XIMaskLen(XI_LASTEVENT)];
+ evmask.mask = mask;
+ evmask.mask_len = sizeof(mask);
+ memset(mask, 0, sizeof(mask));
+ XISetMask(mask, XI_ButtonPress);
+ XISetMask(mask, XI_ButtonRelease);
+ XISetMask(mask, XI_Motion);
+ XISetMask(mask, XI_Enter);
+ XISetMask(mask, XI_Leave);
+ XISetMask(mask, XI_TouchBegin);
+ XISetMask(mask, XI_TouchUpdate);
+ XISetMask(mask, XI_TouchEnd);
+
+ for (int id : m_xiMasterPointerIds) {
+ evmask.deviceid = id;
+ Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None,
+ XIGrabModeAsync, XIGrabModeAsync, False, &evmask);
if (result != Success) {
- grabbed = false;
- qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result);
+ qCDebug(lcQpaXInput, "failed to grab events for device %d on window %x"
+ "(result %d)", id, w, result);
+ } else {
+ // Managed to grab at least one of master pointers, that should be enough
+ // to properly dismiss windows that rely on mouse grabbing.
+ ok = true;
}
}
+ } else { // ungrab
+ for (int id : m_xiMasterPointerIds) {
+ Status result = XIUngrabDevice(xDisplay, id, CurrentTime);
+ if (result != Success)
+ qCDebug(lcQpaXInput, "XIUngrabDevice failed - id: %d (result %d)", id, result);
+ }
+ // XIUngrabDevice does not seem to wait for a reply from X server (similar to
+ // xcb_ungrab_pointer). Ungrabbing won't fail, unless NoSuchExtension error
+ // has occurred due to a programming error somewhere else in the stack. That
+ // would mean that things will crash soon anyway.
+ ok = true;
}
- XIFreeDeviceInfo(info);
-
- m_xiGrab = grabbed;
+ if (ok)
+ m_xiGrab = grab;
- return grabbed;
+ return ok;
}
void QXcbConnection::xi2HandleHierarchyEvent(void *event)
@@ -1342,7 +1334,7 @@ QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id)
if (m_tabletData.at(i).deviceId == id)
return &m_tabletData[i];
}
- return Q_NULLPTR;
+ return nullptr;
}
#endif // QT_CONFIG(tabletevent)
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index da63360333..34b7d0d236 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -255,29 +255,29 @@ static const uint8_t * const cursor_bits20[] = {
forbidden_bits, forbiddenm_bits
};
-static const char * const cursorNames[] = {
- "left_ptr",
- "up_arrow",
- "cross",
- "wait",
- "ibeam",
- "size_ver",
- "size_hor",
- "size_bdiag",
- "size_fdiag",
- "size_all",
- "blank",
- "split_v",
- "split_h",
- "pointing_hand",
- "forbidden",
- "whats_this",
- "left_ptr_watch",
- "openhand",
- "closedhand",
- "copy",
- "move",
- "link"
+static const std::vector<const char *> cursorNames[] = {
+ { "left_ptr", "default", "top_left_arrow", "left_arrow" },
+ { "up_arrow" },
+ { "cross" },
+ { "wait", "watch", "0426c94ea35c87780ff01dc239897213" },
+ { "ibeam", "text", "xterm" },
+ { "size_ver", "ns-resize", "v_double_arrow", "00008160000006810000408080010102" },
+ { "size_hor", "ew-resize", "h_double_arrow", "028006030e0e7ebffc7f7070c0600140" },
+ { "size_bdiag", "nesw-resize", "50585d75b494802d0151028115016902", "fcf1c3c7cd4491d801f1e1c78f100000" },
+ { "size_fdiag", "nwse-resize", "38c5dff7c7b8962045400281044508d2", "c7088f0f3e6c8088236ef8e1e3e70000" },
+ { "size_all" },
+ { "blank" },
+ { "split_v", "row-resize", "sb_v_double_arrow", "2870a09082c103050810ffdffffe0204", "c07385c7190e701020ff7ffffd08103c" },
+ { "split_h", "col-resize", "sb_h_double_arrow", "043a9f68147c53184671403ffa811cc5", "14fef782d02440884392942c11205230" },
+ { "pointing_hand", "pointer", "hand1", "e29285e634086352946a0e7090d73106" },
+ { "forbidden", "not-allowed", "crossed_circle", "circle", "03b6e0fcb3499374a867c041f52298f0" },
+ { "whats_this", "help", "question_arrow", "5c6cd98b3f3ebcb1f9c7f1c204630408", "d9ce0ab605698f320427677b458ad60b" },
+ { "left_ptr_watch", "half-busy", "progress", "00000000000000020006000e7e9ffc3f", "08e8e1c95fe2fc01f976f1e063a24ccd" },
+ { "openhand", "fleur", "5aca4d189052212118709018842178c0", "9d800788f1b08800ae810202380a0822" },
+ { "closedhand", "grabbing", "208530c400c041818281048008011002" },
+ { "dnd-copy", "copy" },
+ { "dnd-move", "move" },
+ { "dnd-link", "link" }
};
QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c)
@@ -535,22 +535,13 @@ static xcb_cursor_t loadCursor(void *dpy, int cshape)
xcb_cursor_t cursor = XCB_NONE;
if (!ptrXcursorLibraryLoadCursor || !dpy)
return cursor;
- switch (cshape) {
- case Qt::DragCopyCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
- break;
- case Qt::DragMoveCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
- break;
- case Qt::DragLinkCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
- break;
- default:
- break;
- }
- if (!cursor) {
- cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+
+ for (const char *cursorName: cursorNames[cshape]) {
+ cursor = ptrXcursorLibraryLoadCursor(dpy, cursorName);
+ if (cursor != XCB_NONE)
+ break;
}
+
return cursor;
}
#endif // QT_CONFIG(xcb_xlib) / QT_CONFIG(library)
@@ -565,7 +556,6 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
if (cshape >= 0 && cshape <= Qt::LastCursor) {
void *dpy = connection()->xlib_display();
- // special case for non-standard dnd-* cursors
cursor = loadCursor(dpy, cshape);
if (!cursor && !m_gtkCursorThemeInitialized && m_screen->xSettings()->initialized()) {
QByteArray gtkCursorTheme = m_screen->xSettings()->setting("Gtk/CursorThemeName").toByteArray();
@@ -598,7 +588,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
}
if (cursor && cshape >= 0 && cshape < Qt::LastCursor && connection()->hasXFixes()) {
- const char *name = cursorNames[cshape];
+ const char *name = cursorNames[cshape].front();
xcb_xfixes_set_cursor_name(conn, cursor, strlen(name), name);
}
@@ -660,7 +650,7 @@ QPoint QXcbCursor::pos() const
void QXcbCursor::setPos(const QPoint &pos)
{
- QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR;
+ QXcbVirtualDesktop *virtualDesktop = nullptr;
queryPointer(connection(), &virtualDesktop, 0);
xcb_warp_pointer(xcb_connection(), XCB_NONE, virtualDesktop->root(), 0, 0, 0, 0, pos.x(), pos.y());
xcb_flush(xcb_connection());
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 1e963268ef..8ea0ebf966 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -211,7 +211,7 @@ void QXcbDrag::startDrag()
setScreen(current_virtual_desktop->screens().constFirst()->screen());
initiatorWindow = QGuiApplicationPrivate::currentMouseWindow;
QBasicDrag::startDrag();
- if (connection()->mouseGrabber() == Q_NULLPTR)
+ if (connection()->mouseGrabber() == nullptr)
shapedPixmapWindow()->setMouseGrabEnabled(true);
}
@@ -315,7 +315,7 @@ void QXcbDrag::move(const QPoint &globalPos)
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
return;
- QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR;
+ QXcbVirtualDesktop *virtualDesktop = nullptr;
QPoint cursorPos;
QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);
QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);
@@ -324,7 +324,7 @@ void QXcbDrag::move(const QPoint &globalPos)
if (virtualDesktop != current_virtual_desktop) {
setUseCompositing(virtualDesktop->compositingActive());
recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);
- if (connection()->mouseGrabber() == Q_NULLPTR)
+ if (connection()->mouseGrabber() == nullptr)
shapedPixmapWindow()->setMouseGrabEnabled(true);
current_virtual_desktop = virtualDesktop;
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 36536e0602..e18a08755b 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qxcbimage.h"
+#include <QtCore/QtEndian>
#include <QtGui/QColor>
#include <QtGui/private/qimage_p.h>
#include <QtGui/private/qdrawhelper_p.h>
@@ -52,47 +53,108 @@ extern "C" {
#undef template
#endif
+#include "qxcbconnection.h"
+#include "qxcbintegration.h"
+
+namespace {
+
+QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask, int blue_mask)
+{
+ if (bits_per_pixel == 32) {
+ switch (depth) {
+ case 32:
+ if (red_mask == 0xff0000 && blue_mask == 0xff)
+ return QImage::Format_ARGB32_Premultiplied;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (red_mask == 0xff && blue_mask == 0xff0000)
+ return QImage::Format_RGBA8888_Premultiplied;
+#else
+ if (red_mask == 0xff000000 && blue_mask == 0xff00)
+ return QImage::Format_RGBA8888_Premultiplied;
+#endif
+ if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
+ return QImage::Format_A2BGR30_Premultiplied;
+ if (red_mask == 0x3ff00000 && blue_mask == 0x3ff)
+ return QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case 30:
+ if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
+ return QImage::Format_BGR30;
+ if (blue_mask == 0x3ff && red_mask == 0x3ff00000)
+ return QImage::Format_RGB30;
+ break;
+ case 24:
+ if (red_mask == 0xff0000 && blue_mask == 0xff)
+ return QImage::Format_RGB32;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (red_mask == 0xff && blue_mask == 0xff0000)
+ return QImage::Format_RGBX8888;
+#else
+ if (red_mask == 0xff000000 && blue_mask == 0xff00)
+ return QImage::Format_RGBX8888;
+#endif
+ break;
+ }
+ } else if (bits_per_pixel == 16) {
+ if (depth == 16 && red_mask == 0xf800 && blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+ if (depth == 15 && red_mask == 0x7c00 && blue_mask == 0x1f)
+ return QImage::Format_RGB555;
+ }
+ return QImage::Format_Invalid;
+}
+
+} // namespace
+
QT_BEGIN_NAMESPACE
-QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth,
- const xcb_visualtype_t *visual)
+bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual,
+ QImage::Format *imageFormat, bool *needsRgbSwap)
{
+ Q_ASSERT(connection && visual && imageFormat);
+
+ if (needsRgbSwap)
+ *needsRgbSwap = false;
+ *imageFormat = QImage::Format_Invalid;
+
+ if (depth == 8) {
+ if (visual->_class == XCB_VISUAL_CLASS_GRAY_SCALE) {
+ *imageFormat = QImage::Format_Grayscale8;
+ return true;
+ }
+#if QT_CONFIG(xcb_native_painting)
+ if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled()) {
+ *imageFormat = QImage::Format_Indexed8;
+ return true;
+ }
+#endif
+ return false;
+ }
+
const xcb_format_t *format = connection->formatForDepth(depth);
+ if (!format)
+ return false;
+
+ const bool connectionEndianSwap = connection->imageNeedsEndianSwap();
+ // We swap the masks and see if we can recognize it as a host format
+ const quint32 red_mask = connectionEndianSwap ? qbswap(visual->red_mask) : visual->red_mask;
+ const quint32 blue_mask = connectionEndianSwap ? qbswap(visual->blue_mask) : visual->blue_mask;
- if (!visual || !format)
- return QImage::Format_Invalid;
-
- if (depth == 32 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_ARGB32_Premultiplied;
-
- if (depth == 30 && format->bits_per_pixel == 32 && visual->red_mask == 0x3ff
- && visual->green_mask == 0x0ffc00 && visual->blue_mask == 0x3ff00000)
- return QImage::Format_BGR30;
-
- if (depth == 30 && format->bits_per_pixel == 32 && visual->blue_mask == 0x3ff
- && visual->green_mask == 0x0ffc00 && visual->red_mask == 0x3ff00000)
- return QImage::Format_RGB30;
-
- if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
- return QImage::Format_RGB32;
-
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
- if (depth == 24 && format->bits_per_pixel == 32 && visual->blue_mask == 0xff0000
- && visual->green_mask == 0xff00 && visual->red_mask == 0xff)
- return QImage::Format_RGBX8888;
- } else {
- if (depth == 24 && format->bits_per_pixel == 32 && visual->blue_mask == 0xff00
- && visual->green_mask == 0xff0000 && visual->red_mask == 0xff000000)
- return QImage::Format_RGBX8888;
+ *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, red_mask, blue_mask);
+ if (*imageFormat != QImage::Format_Invalid)
+ return true;
+
+ if (needsRgbSwap) {
+ *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, blue_mask, red_mask);
+ if (*imageFormat != QImage::Format_Invalid) {
+ *needsRgbSwap = true;
+ return true;
+ }
}
- if (depth == 16 && format->bits_per_pixel == 16 && visual->red_mask == 0xf800
- && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f)
- return QImage::Format_RGB16;
+ qWarning("Unsupported screen format: depth: %d, bits_per_pixel: %d, red_mask: %x, blue_mask: %x", depth, format->bits_per_pixel, red_mask, blue_mask);
- return QImage::Format_Invalid;
+ return false;
}
QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap,
@@ -112,44 +174,14 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
QPixmap result;
- QImage::Format format = qt_xcb_imageFormatForVisual(connection, depth, visual);
- if (format != QImage::Format_Invalid) {
+ QImage::Format format;
+ bool needsRgbSwap;
+ if (qt_xcb_imageFormatForVisual(connection, depth, visual, &format, &needsRgbSwap)) {
uint32_t bytes_per_line = length / height;
QImage image(const_cast<uint8_t *>(data), width, height, bytes_per_line, format);
- uint8_t image_byte_order = connection->setup()->image_byte_order;
-
- // we may have to swap the byte order
- if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
- || (QSysInfo::ByteOrder == QSysInfo::BigEndian && image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST))
- {
- for (int i=0; i < image.height(); i++) {
- switch (format) {
- case QImage::Format_RGB16: {
- ushort *p = (ushort*)image.scanLine(i);
- ushort *end = p + image.width();
- while (p < end) {
- *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
- p++;
- }
- break;
- }
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32_Premultiplied:
- case QImage::Format_RGBX8888: {
- uint *p = (uint*)image.scanLine(i);
- uint *end = p + image.width();
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- break;
- }
- default:
- Q_ASSERT(false);
- }
- }
- }
+
+ if (needsRgbSwap)
+ image = std::move(image).rgbSwapped();
// fix-up alpha channel
if (format == QImage::Format_RGB32 || format == QImage::Format_RGBX8888) {
diff --git a/src/plugins/platforms/xcb/qxcbimage.h b/src/plugins/platforms/xcb/qxcbimage.h
index a9071a45de..d718089ec2 100644
--- a/src/plugins/platforms/xcb/qxcbimage.h
+++ b/src/plugins/platforms/xcb/qxcbimage.h
@@ -48,8 +48,8 @@
QT_BEGIN_NAMESPACE
-QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection,
- uint8_t depth, const xcb_visualtype_t *visual);
+bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual,
+ QImage::Format *imageFormat, bool *needsRgbSwap = nullptr);
QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap,
int width, int height, int depth,
const xcb_visualtype_t *visual);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 10f3000dd2..471287eb44 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -121,7 +121,7 @@ static bool runningUnderDebugger()
#endif
}
-QXcbIntegration *QXcbIntegration::m_instance = Q_NULLPTR;
+QXcbIntegration *QXcbIntegration::m_instance = nullptr;
QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
: m_services(new QGenericUnixServices)
@@ -222,7 +222,7 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
QXcbIntegration::~QXcbIntegration()
{
qDeleteAll(m_connections);
- m_instance = Q_NULLPTR;
+ m_instance = nullptr;
}
QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
@@ -274,7 +274,7 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
if (!glIntegration) {
qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
- return Q_NULLPTR;
+ return nullptr;
}
return glIntegration->createPlatformOpenGLContext(context);
}
@@ -296,7 +296,7 @@ QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffs
QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
if (!glIntegration) {
qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled");
- return Q_NULLPTR;
+ return nullptr;
}
return glIntegration->createPlatformOffscreenSurface(surface);
}
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index e24bd07b6f..2ed66394c9 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -59,18 +59,85 @@
#undef KeyRelease
#endif
+#if QT_CONFIG(xcb_xlib)
+#include <X11/Xutil.h>
+#undef KeyPress
+#undef KeyRelease
+#endif
+
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
-#ifndef XK_dead_hook
-#define XK_dead_hook 0xFE61
+#ifndef XK_dead_a
+#define XK_dead_a 0xFE80
+#endif
+
+#ifndef XK_dead_A
+#define XK_dead_A 0xFE81
+#endif
+
+#ifndef XK_dead_e
+#define XK_dead_e 0xFE82
+#endif
+
+#ifndef XK_dead_E
+#define XK_dead_E 0xFE83
+#endif
+
+#ifndef XK_dead_i
+#define XK_dead_i 0xFE84
+#endif
+
+#ifndef XK_dead_I
+#define XK_dead_I 0xFE85
+#endif
+
+#ifndef XK_dead_o
+#define XK_dead_o 0xFE86
+#endif
+
+#ifndef XK_dead_O
+#define XK_dead_O 0xFE87
+#endif
+
+#ifndef XK_dead_u
+#define XK_dead_u 0xFE88
+#endif
+
+#ifndef XK_dead_U
+#define XK_dead_U 0xFE89
+#endif
+
+#ifndef XK_dead_small_schwa
+#define XK_dead_small_schwa 0xFE8A
+#endif
+
+#ifndef XK_dead_capital_schwa
+#define XK_dead_capital_schwa 0xFE8B
+#endif
+
+#ifndef XK_dead_greek
+#define XK_dead_greek 0xFE8C
+#endif
+
+#ifndef XK_dead_lowline
+#define XK_dead_lowline 0xFE90
+#endif
+
+#ifndef XK_dead_aboveverticalline
+#define XK_dead_aboveverticalline 0xFE91
#endif
-#ifndef XK_dead_horn
-#define XK_dead_horn 0xFE62
+#ifndef XK_dead_belowverticalline
+#define XK_dead_belowverticalline 0xFE92
#endif
+#ifndef XK_dead_longsolidusoverlay
+#define XK_dead_longsolidusoverlay 0xFE93
+#endif
+
+
#ifndef XK_Codeinput
#define XK_Codeinput 0xFF37
#endif
@@ -429,6 +496,36 @@ static const unsigned int KeyTbl[] = {
XK_dead_belowdot, Qt::Key_Dead_Belowdot,
XK_dead_hook, Qt::Key_Dead_Hook,
XK_dead_horn, Qt::Key_Dead_Horn,
+ XK_dead_stroke, Qt::Key_Dead_Stroke,
+ XK_dead_abovecomma, Qt::Key_Dead_Abovecomma,
+ XK_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
+ XK_dead_doublegrave, Qt::Key_Dead_Doublegrave,
+ XK_dead_belowring, Qt::Key_Dead_Belowring,
+ XK_dead_belowmacron, Qt::Key_Dead_Belowmacron,
+ XK_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
+ XK_dead_belowtilde, Qt::Key_Dead_Belowtilde,
+ XK_dead_belowbreve, Qt::Key_Dead_Belowbreve,
+ XK_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
+ XK_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
+ XK_dead_belowcomma, Qt::Key_Dead_Belowcomma,
+ XK_dead_currency, Qt::Key_Dead_Currency,
+ XK_dead_a, Qt::Key_Dead_a,
+ XK_dead_A, Qt::Key_Dead_A,
+ XK_dead_e, Qt::Key_Dead_e,
+ XK_dead_E, Qt::Key_Dead_E,
+ XK_dead_i, Qt::Key_Dead_i,
+ XK_dead_I, Qt::Key_Dead_I,
+ XK_dead_o, Qt::Key_Dead_o,
+ XK_dead_O, Qt::Key_Dead_O,
+ XK_dead_u, Qt::Key_Dead_u,
+ XK_dead_U, Qt::Key_Dead_U,
+ XK_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
+ XK_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
+ XK_dead_greek, Qt::Key_Dead_Greek,
+ XK_dead_lowline, Qt::Key_Dead_Lowline,
+ XK_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
+ XK_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
+ XK_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
// Special keys from X.org - This include multimedia keys,
// wireless/bluetooth/uwb keys, special launcher keys, etc.
@@ -678,9 +775,303 @@ void QXcbKeyboard::printKeymapError(const char *error) const
"directory contains recent enough contents, to update please see http://cgit.freedesktop.org/xkeyboard-config/ .");
}
+#if QT_CONFIG(xcb_xlib)
+/* Look at a pair of unshifted and shifted key symbols.
+ * If the 'unshifted' symbol is uppercase and there is no shifted symbol,
+ * return the matching lowercase symbol; otherwise return 0.
+ * The caller can then use the previously 'unshifted' symbol as the new
+ * 'shifted' (uppercase) symbol and the symbol returned by the function
+ * as the new 'unshifted' (lowercase) symbol.) */
+static xcb_keysym_t getUnshiftedXKey(xcb_keysym_t unshifted, xcb_keysym_t shifted)
+{
+ if (shifted != XKB_KEY_NoSymbol) // Has a shifted symbol
+ return 0;
+
+ KeySym xlower;
+ KeySym xupper;
+ /* libxkbcommon >= 0.8.0 will have public API functions providing
+ * functionality equivalent to XConvertCase(), use these once the
+ * minimal libxkbcommon version is high enough. After that the
+ * xcb-xlib dependency can be removed */
+ XConvertCase(static_cast<KeySym>(unshifted), &xlower, &xupper);
+
+ if (xlower != xupper // Check if symbol is cased
+ && unshifted == static_cast<xcb_keysym_t>(xupper)) { // Unshifted must be upper case
+ return static_cast<xcb_keysym_t>(xlower);
+ }
+ return 0;
+}
+
+static QByteArray symbolsGroupString(const xcb_keysym_t *symbols, int count)
+{
+ // Don't output trailing NoSymbols
+ while (count > 0 && symbols[count - 1] == XKB_KEY_NoSymbol)
+ count--;
+
+ QByteArray groupString;
+ for (int symIndex = 0; symIndex < count; symIndex++) {
+ xcb_keysym_t sym = symbols[symIndex];
+ char symString[64];
+ if (sym == XKB_KEY_NoSymbol)
+ strcpy(symString, "NoSymbol");
+ else
+ xkb_keysym_get_name(sym, symString, sizeof(symString));
+
+ if (!groupString.isEmpty())
+ groupString += ", ";
+ groupString += symString;
+ }
+ return groupString;
+}
+
+struct xkb_keymap *QXcbKeyboard::keymapFromCore()
+{
+ /* Construct an XKB keymap string from information queried from
+ * the X server */
+ QByteArray keymap;
+ keymap += "xkb_keymap {\n";
+
+ const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
+ const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
+
+ // Generate symbolic names from keycodes
+ {
+ keymap +=
+ "xkb_keycodes \"core\" {\n"
+ "\tminimum = " + QByteArray::number(minKeycode) + ";\n"
+ "\tmaximum = " + QByteArray::number(maxKeycode) + ";\n";
+ for (int code = minKeycode; code <= maxKeycode; code++) {
+ auto codeStr = QByteArray::number(code);
+ keymap += "<K" + codeStr + "> = " + codeStr + ";\n";
+ }
+ /* TODO: indicators?
+ */
+ keymap += "};\n"; // xkb_keycodes
+ }
+
+ /* Set up default types (xkbcommon automatically assigns these to
+ * symbols, but doesn't have shift info) */
+ keymap +=
+ "xkb_types \"core\" {\n"
+ "virtual_modifiers NumLock,Alt,LevelThree;\n"
+ "type \"ONE_LEVEL\" {\n"
+ "modifiers= none;\n"
+ "level_name[Level1] = \"Any\";\n"
+ "};\n"
+ "type \"TWO_LEVEL\" {\n"
+ "modifiers= Shift;\n"
+ "map[Shift]= Level2;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Shift\";\n"
+ "};\n"
+ "type \"ALPHABETIC\" {\n"
+ "modifiers= Shift+Lock;\n"
+ "map[Shift]= Level2;\n"
+ "map[Lock]= Level2;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Caps\";\n"
+ "};\n"
+ "type \"KEYPAD\" {\n"
+ "modifiers= Shift+NumLock;\n"
+ "map[Shift]= Level2;\n"
+ "map[NumLock]= Level2;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Number\";\n"
+ "};\n"
+ "type \"FOUR_LEVEL\" {\n"
+ "modifiers= Shift+LevelThree;\n"
+ "map[Shift]= Level2;\n"
+ "map[LevelThree]= Level3;\n"
+ "map[Shift+LevelThree]= Level4;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Shift\";\n"
+ "level_name[Level3] = \"Alt Base\";\n"
+ "level_name[Level4] = \"Shift Alt\";\n"
+ "};\n"
+ "type \"FOUR_LEVEL_ALPHABETIC\" {\n"
+ "modifiers= Shift+Lock+LevelThree;\n"
+ "map[Shift]= Level2;\n"
+ "map[Lock]= Level2;\n"
+ "map[LevelThree]= Level3;\n"
+ "map[Shift+LevelThree]= Level4;\n"
+ "map[Lock+LevelThree]= Level4;\n"
+ "map[Shift+Lock+LevelThree]= Level3;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Shift\";\n"
+ "level_name[Level3] = \"Alt Base\";\n"
+ "level_name[Level4] = \"Shift Alt\";\n"
+ "};\n"
+ "type \"FOUR_LEVEL_SEMIALPHABETIC\" {\n"
+ "modifiers= Shift+Lock+LevelThree;\n"
+ "map[Shift]= Level2;\n"
+ "map[Lock]= Level2;\n"
+ "map[LevelThree]= Level3;\n"
+ "map[Shift+LevelThree]= Level4;\n"
+ "map[Lock+LevelThree]= Level3;\n"
+ "preserve[Lock+LevelThree]= Lock;\n"
+ "map[Shift+Lock+LevelThree]= Level4;\n"
+ "preserve[Shift+Lock+LevelThree]= Lock;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Shift\";\n"
+ "level_name[Level3] = \"Alt Base\";\n"
+ "level_name[Level4] = \"Shift Alt\";\n"
+ "};\n"
+ "type \"FOUR_LEVEL_KEYPAD\" {\n"
+ "modifiers= Shift+NumLock+LevelThree;\n"
+ "map[Shift]= Level2;\n"
+ "map[NumLock]= Level2;\n"
+ "map[LevelThree]= Level3;\n"
+ "map[Shift+LevelThree]= Level4;\n"
+ "map[NumLock+LevelThree]= Level4;\n"
+ "map[Shift+NumLock+LevelThree]= Level3;\n"
+ "level_name[Level1] = \"Base\";\n"
+ "level_name[Level2] = \"Number\";\n"
+ "level_name[Level3] = \"Alt Base\";\n"
+ "level_name[Level4] = \"Alt Number\";\n"
+ "};\n"
+ "};\n"; // xkb_types
+
+ // Generate mapping between symbolic names and keysyms
+ {
+ QVector<xcb_keysym_t> xkeymap;
+ int keysymsPerKeycode = 0;
+ {
+ int keycodeCount = maxKeycode - minKeycode + 1;
+ if (auto keymapReply = Q_XCB_REPLY(xcb_get_keyboard_mapping, xcb_connection(),
+ minKeycode, keycodeCount)) {
+ keysymsPerKeycode = keymapReply->keysyms_per_keycode;
+ int numSyms = keycodeCount * keysymsPerKeycode;
+ auto keymapPtr = xcb_get_keyboard_mapping_keysyms(keymapReply.get());
+ xkeymap.resize(numSyms);
+ for (int i = 0; i < numSyms; i++)
+ xkeymap[i] = keymapPtr[i];
+ }
+ }
+ if (xkeymap.isEmpty())
+ return nullptr;
+
+ KeysymModifierMap keysymMods(keysymsToModifiers());
+ static const char *const builtinModifiers[] =
+ { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
+
+ /* Level 3 symbols (e.g. AltGr+something) seem to come in two flavors:
+ * - as a proper level 3 in group 1, at least on recent X.org versions
+ * - 'disguised' as group 2, on 'legacy' X servers
+ * In the 2nd case, remap group 2 to level 3, that seems to work better
+ * in practice */
+ bool mapGroup2ToLevel3 = keysymsPerKeycode < 5;
+
+ keymap += "xkb_symbols \"core\" {\n";
+ for (int code = minKeycode; code <= maxKeycode; code++) {
+ auto codeMap = xkeymap.constData() + (code - minKeycode) * keysymsPerKeycode;
+
+ const int maxGroup1 = 4; // We only support 4 shift states anyway
+ const int maxGroup2 = 2; // Only 3rd and 4th keysym are group 2
+ xcb_keysym_t symbolsGroup1[maxGroup1];
+ xcb_keysym_t symbolsGroup2[maxGroup2];
+ for (int i = 0; i < maxGroup1 + maxGroup2; i++) {
+ xcb_keysym_t sym = i < keysymsPerKeycode ? codeMap[i] : XKB_KEY_NoSymbol;
+ if (mapGroup2ToLevel3) {
+ // Merge into single group
+ if (i < maxGroup1)
+ symbolsGroup1[i] = sym;
+ } else {
+ // Preserve groups
+ if (i < 2)
+ symbolsGroup1[i] = sym;
+ else if (i < 4)
+ symbolsGroup2[i - 2] = sym;
+ else
+ symbolsGroup1[i - 2] = sym;
+ }
+ }
+
+ /* Fix symbols so the unshifted and shifted symbols have
+ * lower resp. upper case */
+ if (auto lowered = getUnshiftedXKey(symbolsGroup1[0], symbolsGroup1[1])) {
+ symbolsGroup1[1] = symbolsGroup1[0];
+ symbolsGroup1[0] = lowered;
+ }
+ if (auto lowered = getUnshiftedXKey(symbolsGroup2[0], symbolsGroup2[1])) {
+ symbolsGroup2[1] = symbolsGroup2[0];
+ symbolsGroup2[0] = lowered;
+ }
+
+ QByteArray groupStr1 = symbolsGroupString(symbolsGroup1, maxGroup1);
+ if (groupStr1.isEmpty())
+ continue;
+
+ keymap += "key <K" + QByteArray::number(code) + "> { ";
+ keymap += "symbols[Group1] = [ " + groupStr1 + " ]";
+ QByteArray groupStr2 = symbolsGroupString(symbolsGroup2, maxGroup2);
+ if (!groupStr2.isEmpty())
+ keymap += ", symbols[Group2] = [ " + groupStr2 + " ]";
+
+ // See if this key code is for a modifier
+ xcb_keysym_t modifierSym = XKB_KEY_NoSymbol;
+ for (int symIndex = 0; symIndex < keysymsPerKeycode; symIndex++) {
+ xcb_keysym_t sym = codeMap[symIndex];
+
+ if (sym == XKB_KEY_Alt_L
+ || sym == XKB_KEY_Meta_L
+ || sym == XKB_KEY_Mode_switch
+ || sym == XKB_KEY_Super_L
+ || sym == XKB_KEY_Super_R
+ || sym == XKB_KEY_Hyper_L
+ || sym == XKB_KEY_Hyper_R) {
+ modifierSym = sym;
+ break;
+ }
+ }
+
+ // AltGr
+ if (modifierSym == XKB_KEY_Mode_switch)
+ keymap += ", virtualMods=LevelThree";
+ keymap += " };\n"; // key
+
+ // Generate modifier mappings
+ int modNum = keysymMods.value(modifierSym, -1);
+ if (modNum != -1) {
+ // Here modNum is always < 8 (see keysymsToModifiers())
+ keymap += QByteArray("modifier_map ") + builtinModifiers[modNum]
+ + " { <K" + QByteArray::number(code) + "> };\n";
+ }
+ }
+ // TODO: indicators?
+ keymap += "};\n"; // xkb_symbols
+ }
+
+ // We need an "Alt" modifier, provide via the xkb_compatibility section
+ keymap +=
+ "xkb_compatibility \"core\" {\n"
+ "virtual_modifiers NumLock,Alt,LevelThree;\n"
+ "interpret Alt_L+AnyOf(all) {\n"
+ "virtualModifier= Alt;\n"
+ "action= SetMods(modifiers=modMapMods,clearLocks);\n"
+ "};\n"
+ "interpret Alt_R+AnyOf(all) {\n"
+ "virtualModifier= Alt;\n"
+ "action= SetMods(modifiers=modMapMods,clearLocks);\n"
+ "};\n"
+ "};\n";
+
+ /* TODO: There is an issue with modifier state not being handled
+ * correctly if using Xming with XKEYBOARD disabled. */
+
+ keymap += "};\n"; // xkb_keymap
+
+ return xkb_keymap_new_from_buffer(xkb_context,
+ keymap.constData(),
+ keymap.size(),
+ XKB_KEYMAP_FORMAT_TEXT_V1,
+ static_cast<xkb_keymap_compile_flags>(0));
+}
+#endif
+
void QXcbKeyboard::updateKeymap()
{
m_config = true;
+ m_keymap_is_core = false;
// set xkb context object
if (!xkb_context) {
if (qEnvironmentVariableIsSet("QT_XKB_CONFIG_ROOT")) {
@@ -714,9 +1105,23 @@ void QXcbKeyboard::updateKeymap()
}
#endif
if (!xkb_keymap) {
- // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names
+ // Read xkb RMLVO (rules, models, layouts, variants and options) names
readXKBConfig();
- xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0);
+#if QT_CONFIG(xcb_xlib)
+ bool rmlvo_is_incomplete = !xkb_names.rules || !(*xkb_names.rules)
+ || !xkb_names.model || !(*xkb_names.model)
+ || !xkb_names.layout || !(*xkb_names.layout);
+ if (rmlvo_is_incomplete) {
+ // Try to build xkb map from core mapping information
+ xkb_keymap = keymapFromCore();
+ m_keymap_is_core = xkb_keymap != 0;
+ }
+#endif
+ if (!xkb_keymap) {
+ // Compile a keymap from RMLVO
+ xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names,
+ static_cast<xkb_keymap_compile_flags> (0));
+ }
if (!xkb_keymap) {
// last fallback is to used hard-coded keymap name, see DEFAULT_XKB_* in xkbcommon.pri
qWarning() << "Qt: Could not determine keyboard configuration data"
@@ -908,9 +1313,11 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
// If user layouts don't contain any layout that results in a latin key, we query a
// key from "US" layout, this allows for latin-key-based shorcuts to work even when
// users have only one (non-latin) layout set.
+ // But don't do this if using keymap obtained through the core protocol, as the key
+ // codes may not match up with those expected by the XKB keymap.
xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
- if (sym == XKB_KEY_NoSymbol && !m_hasLatinLayout) {
+ if (sym == XKB_KEY_NoSymbol && !m_hasLatinLayout && !m_keymap_is_core) {
if (!latin_keymap) {
const struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 };
latin_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0);
@@ -1117,7 +1524,7 @@ int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modi
modifiers |= Qt::KeypadModifier;
} else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
&& text.unicode()->unicode() != 0x7f
- && !(keysym >= XK_dead_grave && keysym <= XK_dead_currency)) {
+ && !(keysym >= XK_dead_grave && keysym <= XK_dead_longsolidusoverlay)) {
code = text.unicode()->toUpper().unicode();
} else {
// any other keys
@@ -1289,20 +1696,56 @@ void QXcbKeyboard::updateVModToRModMapping()
#endif
}
+// Small helper: set modifier bit, if modifier position is valid
+static inline void applyModifier(uint *mask, int modifierBit)
+{
+ if (modifierBit >= 0 && modifierBit < 8)
+ *mask |= 1 << modifierBit;
+}
+
void QXcbKeyboard::updateModifiers()
{
+ memset(&rmod_masks, 0, sizeof(rmod_masks));
+
+ // Compute X modifier bits for Qt modifiers
+ KeysymModifierMap keysymMods(keysymsToModifiers());
+ applyModifier(&rmod_masks.alt, keysymMods.value(XK_Alt_L, -1));
+ applyModifier(&rmod_masks.alt, keysymMods.value(XK_Alt_R, -1));
+ applyModifier(&rmod_masks.meta, keysymMods.value(XK_Meta_L, -1));
+ applyModifier(&rmod_masks.meta, keysymMods.value(XK_Meta_R, -1));
+ applyModifier(&rmod_masks.altgr, keysymMods.value(XK_Mode_switch, -1));
+ applyModifier(&rmod_masks.super, keysymMods.value(XK_Super_L, -1));
+ applyModifier(&rmod_masks.super, keysymMods.value(XK_Super_R, -1));
+ applyModifier(&rmod_masks.hyper, keysymMods.value(XK_Hyper_L, -1));
+ applyModifier(&rmod_masks.hyper, keysymMods.value(XK_Hyper_R, -1));
+
+ resolveMaskConflicts();
+}
+
+// Small helper: check if an array of xcb_keycode_t contains a certain code
+static inline bool keycodes_contains(xcb_keycode_t *codes, xcb_keycode_t which)
+{
+ while (*codes != XCB_NO_SYMBOL) {
+ if (*codes == which) return true;
+ codes++;
+ }
+ return false;
+}
+
+QXcbKeyboard::KeysymModifierMap QXcbKeyboard::keysymsToModifiers()
+{
// The core protocol does not provide a convenient way to determine the mapping
// of modifier bits. Clients must retrieve and search the modifier map to determine
// the keycodes bound to each modifier, and then retrieve and search the keyboard
// mapping to determine the keysyms bound to the keycodes. They must repeat this
// process for all modifiers whenever any part of the modifier mapping is changed.
- memset(&rmod_masks, 0, sizeof(rmod_masks));
- xcb_connection_t *conn = xcb_connection();
- auto modMapReply = Q_XCB_REPLY(xcb_get_modifier_mapping, conn);
+ KeysymModifierMap map;
+
+ auto modMapReply = Q_XCB_REPLY(xcb_get_modifier_mapping, xcb_connection());
if (!modMapReply) {
qWarning("Qt: failed to get modifier mapping");
- return;
+ return map;
}
// for Alt and Meta L and R are the same
@@ -1318,34 +1761,62 @@ void QXcbKeyboard::updateModifiers()
modKeyCodes[i] = xcb_key_symbols_get_keycode(m_key_symbols, symbols[i]);
xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply.get());
- const int w = modMapReply->keycodes_per_modifier;
- for (size_t i = 0; i < numSymbols; ++i) {
- for (int bit = 0; bit < 8; ++bit) {
- uint mask = 1 << bit;
- for (int x = 0; x < w; ++x) {
- xcb_keycode_t keyCode = modMap[x + bit * w];
- xcb_keycode_t *itk = modKeyCodes[i];
- while (itk && *itk != XCB_NO_SYMBOL)
- if (*itk++ == keyCode) {
- uint sym = symbols[i];
- if ((sym == XK_Alt_L || sym == XK_Alt_R))
- rmod_masks.alt = mask;
- if ((sym == XK_Meta_L || sym == XK_Meta_R))
- rmod_masks.meta = mask;
- if (sym == XK_Mode_switch)
- rmod_masks.altgr = mask;
- if ((sym == XK_Super_L) || (sym == XK_Super_R))
- rmod_masks.super = mask;
- if ((sym == XK_Hyper_L) || (sym == XK_Hyper_R))
- rmod_masks.hyper = mask;
- }
+ const int modMapLength = xcb_get_modifier_mapping_keycodes_length(modMapReply.get());
+ /* For each modifier of "Shift, Lock, Control, Mod1, Mod2, Mod3,
+ * Mod4, and Mod5" the modifier map contains keycodes_per_modifier
+ * key codes that are associated with a modifier.
+ *
+ * As an example, take this 'xmodmap' output:
+ * xmodmap: up to 4 keys per modifier, (keycodes in parentheses):
+ *
+ * shift Shift_L (0x32), Shift_R (0x3e)
+ * lock Caps_Lock (0x42)
+ * control Control_L (0x25), Control_R (0x69)
+ * mod1 Alt_L (0x40), Alt_R (0x6c), Meta_L (0xcd)
+ * mod2 Num_Lock (0x4d)
+ * mod3
+ * mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf)
+ * mod5 ISO_Level3_Shift (0x5c), Mode_switch (0xcb)
+ *
+ * The corresponding raw modifier map would contain keycodes for:
+ * Shift_L (0x32), Shift_R (0x3e), 0, 0,
+ * Caps_Lock (0x42), 0, 0, 0,
+ * Control_L (0x25), Control_R (0x69), 0, 0,
+ * Alt_L (0x40), Alt_R (0x6c), Meta_L (0xcd), 0,
+ * Num_Lock (0x4d), 0, 0, 0,
+ * 0,0,0,0,
+ * Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf),
+ * ISO_Level3_Shift (0x5c), Mode_switch (0xcb), 0, 0
+ */
+
+ /* Create a map between a modifier keysym (as per the symbols array)
+ * and the modifier bit it's associated with (if any).
+ * As modMap contains key codes, search modKeyCodes for a match;
+ * if one is found we can look up the associated keysym.
+ * Together with the modifier index this will be used
+ * to compute a mapping between X modifier bits and Qt's
+ * modifiers (Alt, Ctrl etc). */
+ for (int i = 0; i < modMapLength; i++) {
+ if (modMap[i] == XCB_NO_SYMBOL)
+ continue;
+ // Get key symbol for key code
+ for (size_t k = 0; k < numSymbols; k++) {
+ if (modKeyCodes[k] && keycodes_contains(modKeyCodes[k], modMap[i])) {
+ // Key code is for modifier. Record mapping
+ xcb_keysym_t sym = symbols[k];
+ /* As per modMap layout explanation above, dividing
+ * by keycodes_per_modifier gives the 'row' in the
+ * modifier map, which in turn is the modifier bit. */
+ map[sym] = i / modMapReply->keycodes_per_modifier;
+ break;
}
}
}
for (size_t i = 0; i < numSymbols; ++i)
free(modKeyCodes[i]);
- resolveMaskConflicts();
+
+ return map;
}
void QXcbKeyboard::resolveMaskConflicts()
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 7f1c51fab8..7ee8e9e90d 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -94,8 +94,13 @@ protected:
void readXKBConfig();
void clearXKBConfig();
+#if QT_CONFIG(xcb_xlib)
+ struct xkb_keymap *keymapFromCore();
+#endif
// when XKEYBOARD not present on the X server
void updateModifiers();
+ typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
+ KeysymModifierMap keysymsToModifiers();
// when XKEYBOARD is present on the X server
void updateVModMapping();
void updateVModToRModMapping();
@@ -107,6 +112,7 @@ private:
void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
bool m_config = false;
+ bool m_keymap_is_core = false;
xcb_keycode_t m_autorepeat_code = 0;
struct xkb_context *xkb_context = nullptr;
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index 2848446098..58e2e8c0e6 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -160,9 +160,10 @@ QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, con
return atoms;
}
-QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
+QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &d, const QString &format,
QVariant::Type requestedType, const QByteArray &encoding)
{
+ QByteArray data = d;
QString atomName = mimeAtomToString(connection, a);
// qDebug() << "mimeConvertDataToFormat" << format << atomName << data;
@@ -182,8 +183,11 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
// special cases for string types
if (format == QLatin1String("text/plain")) {
- if (a == connection->atom(QXcbAtom::UTF8_STRING))
+ if (data.endsWith('\0'))
+ data.chop(1);
+ if (a == connection->atom(QXcbAtom::UTF8_STRING)) {
return QString::fromUtf8(data);
+ }
if (a == XCB_ATOM_STRING ||
a == connection->atom(QXcbAtom::TEXT))
return QString::fromLatin1(data);
@@ -221,6 +225,9 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
}
}
}
+ // 8 byte encoding, remove a possible 0 at the end
+ if (data.endsWith('\0'))
+ data.chop(1);
}
if (atomName == format)
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index caa9499c45..d989761297 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -101,7 +101,7 @@ QXcbNativeInterface::QXcbNativeInterface() :
static inline QXcbSystemTrayTracker *systemTrayTracker(const QScreen *s)
{
if (!s)
- return Q_NULLPTR;
+ return nullptr;
return static_cast<const QXcbScreen *>(s->handle())->connection()->systemTrayTracker();
}
@@ -194,7 +194,7 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceStr
{
if (!screen) {
qWarning("nativeResourceForScreen: null screen");
- return Q_NULLPTR;
+ return nullptr;
}
QByteArray lowerCaseResource = resourceString.toLower();
@@ -236,7 +236,7 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceStr
break;
case CompositingEnabled:
if (QXcbVirtualDesktop *vd = xcbScreen->virtualDesktop())
- result = vd->compositingActive() ? this : Q_NULLPTR;
+ result = vd->compositingActive() ? this : nullptr;
break;
default:
break;
@@ -294,7 +294,7 @@ void *QXcbNativeInterface::nativeResourceForCursor(const QByteArray &resource, c
}
}
}
- return Q_NULLPTR;
+ return nullptr;
}
#endif // !QT_NO_CURSOR
@@ -323,7 +323,7 @@ QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::
QPlatformNativeInterface::NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(lowerCaseResource);
if (func)
return func;
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
@@ -390,13 +390,13 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
if (function == QXcbScreenFunctions::virtualDesktopNumberIdentifier())
return QFunctionPointer(QXcbScreenFunctions::VirtualDesktopNumber(QXcbScreen::virtualDesktopNumberStatic));
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
{
if (!screen)
- return Q_NULLPTR;
+ return nullptr;
return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
}
@@ -404,7 +404,7 @@ void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen)
{
if (!screen)
- return Q_NULLPTR;
+ return nullptr;
return reinterpret_cast<void *>(quintptr(screen->connection()->netWmUserTime()));
}
@@ -412,7 +412,7 @@ void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen)
void *QXcbNativeInterface::getTimestamp(const QXcbScreen *screen)
{
if (!screen)
- return Q_NULLPTR;
+ return nullptr;
return reinterpret_cast<void *>(quintptr(screen->connection()->getTimestamp()));
}
@@ -452,7 +452,7 @@ void *QXcbNativeInterface::display()
if (defaultConnection)
return defaultConnection->xlib_display();
#endif
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::connection()
@@ -525,10 +525,10 @@ QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window)
QXcbScreen *screen;
if (window) {
QScreen *qs = window->screen();
- screen = static_cast<QXcbScreen *>(qs ? qs->handle() : Q_NULLPTR);
+ screen = static_cast<QXcbScreen *>(qs ? qs->handle() : nullptr);
} else {
QScreen *qs = QGuiApplication::primaryScreen();
- screen = static_cast<QXcbScreen *>(qs ? qs->handle() : Q_NULLPTR);
+ screen = static_cast<QXcbScreen *>(qs ? qs->handle() : nullptr);
}
return screen;
}
@@ -537,23 +537,23 @@ void *QXcbNativeInterface::displayForWindow(QWindow *window)
{
#if QT_CONFIG(xcb_xlib)
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen ? screen->connection()->xlib_display() : Q_NULLPTR;
+ return screen ? screen->connection()->xlib_display() : nullptr;
#else
Q_UNUSED(window);
- return Q_NULLPTR;
+ return nullptr;
#endif
}
void *QXcbNativeInterface::connectionForWindow(QWindow *window)
{
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen ? screen->xcb_connection() : Q_NULLPTR;
+ return screen ? screen->xcb_connection() : nullptr;
}
void *QXcbNativeInterface::screenForWindow(QWindow *window)
{
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen ? screen->screen() : Q_NULLPTR;
+ return screen ? screen->screen() : nullptr;
}
void QXcbNativeInterface::addHandler(QXcbNativeInterfaceHandler *handler)
@@ -575,7 +575,7 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterfa
if (result)
return result;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::handlerNativeResourceFunctionForContext(const QByteArray &resource) const
@@ -586,7 +586,7 @@ QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::
if (result)
return result;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::handlerNativeResourceFunctionForScreen(const QByteArray &resource) const
@@ -597,7 +597,7 @@ QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::h
if (result)
return result;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::handlerNativeResourceFunctionForWindow(const QByteArray &resource) const
@@ -608,7 +608,7 @@ QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::h
if (result)
return result;
}
- return Q_NULLPTR;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::handlerNativeResourceFunctionForBackingStore(const QByteArray &resource) const
@@ -619,7 +619,7 @@ QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterf
if (result)
return result;
}
- return Q_NULLPTR;
+ return nullptr;
}
QFunctionPointer QXcbNativeInterface::handlerPlatformFunction(const QByteArray &function) const
@@ -630,7 +630,7 @@ QFunctionPointer QXcbNativeInterface::handlerPlatformFunction(const QByteArray &
if (func)
return func;
}
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::handlerNativeResourceForIntegration(const QByteArray &resource) const
@@ -638,7 +638,7 @@ void *QXcbNativeInterface::handlerNativeResourceForIntegration(const QByteArray
NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(resource);
if (func)
return func();
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::handlerNativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) const
@@ -646,7 +646,7 @@ void *QXcbNativeInterface::handlerNativeResourceForContext(const QByteArray &res
NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(resource);
if (func)
return func(context);
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::handlerNativeResourceForScreen(const QByteArray &resource, QScreen *screen) const
@@ -654,7 +654,7 @@ void *QXcbNativeInterface::handlerNativeResourceForScreen(const QByteArray &reso
NativeResourceForScreenFunction func = handlerNativeResourceFunctionForScreen(resource);
if (func)
return func(screen);
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::handlerNativeResourceForWindow(const QByteArray &resource, QWindow *window) const
@@ -662,7 +662,7 @@ void *QXcbNativeInterface::handlerNativeResourceForWindow(const QByteArray &reso
NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(resource);
if (func)
return func(window);
- return Q_NULLPTR;
+ return nullptr;
}
void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore) const
@@ -670,7 +670,7 @@ void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray
NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource);
if (func)
return func(backingStore);
- return Q_NULLPTR;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 67c96b2d80..e3d9bc7a3d 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -140,7 +140,7 @@ QXcbScreen *QXcbVirtualDesktop::screenAt(const QPoint &pos) const
if (screen->virtualDesktop() == this && screen->geometry().contains(pos))
return screen;
}
- return Q_NULLPTR;
+ return nullptr;
}
void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
@@ -590,7 +590,9 @@ QRect QXcbScreen::availableGeometry() const
QImage::Format QXcbScreen::format() const
{
- return qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual));
+ QImage::Format format;
+ qt_xcb_imageFormatForVisual(connection(), screen()->root_depth, visualForId(screen()->root_visual), &format);
+ return format;
}
QDpi QXcbScreen::virtualDpi() const
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 842738b622..4a9b1bd209 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -140,7 +140,7 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo,
- const xcb_xinerama_screen_info_t *xineramaScreenInfo = Q_NULLPTR, int xineramaScreenIdx = -1);
+ const xcb_xinerama_screen_info_t *xineramaScreenInfo = nullptr, int xineramaScreenIdx = -1);
~QXcbScreen();
QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 81a54f5887..46698de158 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -51,6 +51,7 @@
#include "qxcbscreen.h"
#include "qxcbdrag.h"
#include "qxcbkeyboard.h"
+#include "qxcbimage.h"
#include "qxcbwmsupport.h"
#include "qxcbimage.h"
#include "qxcbnativeinterface.h"
@@ -176,80 +177,23 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask, bool *rgbSwap)
+void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual)
{
- if (rgbSwap)
- *rgbSwap = false;
- switch (depth) {
- case 32:
- if (blue_mask == 0xff)
- return QImage::Format_ARGB32_Premultiplied;
- if (red_mask == 0x3ff)
- return QImage::Format_A2BGR30_Premultiplied;
- if (blue_mask == 0x3ff)
- return QImage::Format_A2RGB30_Premultiplied;
- if (red_mask == 0xff) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_ARGB32_Premultiplied;
- }
- break;
- case 30:
- if (red_mask == 0x3ff)
- return QImage::Format_BGR30;
- if (blue_mask == 0x3ff)
- return QImage::Format_RGB30;
- break;
- case 24:
- if (blue_mask == 0xff)
- return QImage::Format_RGB32;
- if (red_mask == 0xff) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB32;
- }
- break;
- case 16:
- if (blue_mask == 0x1f)
- return QImage::Format_RGB16;
- if (red_mask == 0x1f) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB16;
- }
- break;
- case 15:
- if (blue_mask == 0x1f)
- return QImage::Format_RGB555;
- if (red_mask == 0x1f) {
- if (rgbSwap)
- *rgbSwap = true;
- return QImage::Format_RGB555;
- }
- break;
-#if QT_CONFIG(xcb_native_painting)
- case 8:
- if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled())
- return QImage::Format_Indexed8;
- break;
-#endif
- default:
- break;
- }
- qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask);
+ if (qt_xcb_imageFormatForVisual(connection(), m_depth, visual, &m_imageFormat, &m_imageRgbSwap))
+ return;
- switch (depth) {
+ switch (m_depth) {
+ case 32:
case 24:
qWarning("Using RGB32 fallback, if this works your X11 server is reporting a bad screen format.");
- return QImage::Format_RGB32;
+ m_imageFormat = QImage::Format_RGB32;
+ break;
case 16:
qWarning("Using RGB16 fallback, if this works your X11 server is reporting a bad screen format.");
- return QImage::Format_RGB16;
+ m_imageFormat = QImage::Format_RGB16;
default:
break;
}
-
- return QImage::Format_Invalid;
}
static inline bool positionIncludesFrame(QWindow *w)
@@ -287,7 +231,7 @@ static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s)
if (!mapper || errCode < 0) {
mapper = QTextCodec::codecForName("latin1");
if (!mapper || !mapper->canEncode(s))
- return Q_NULLPTR;
+ return nullptr;
#endif
static QByteArray qcs;
qcs = s.toLatin1();
@@ -322,7 +266,7 @@ static QWindow *childWindowAt(QWindow *win, const QPoint &p)
&& win->geometry().contains(win->parent()->mapFromGlobal(p))) {
return win;
}
- return Q_NULLPTR;
+ return nullptr;
}
static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
@@ -381,7 +325,7 @@ void QXcbWindow::create()
}
if (!visual)
visual = platformScreen->visualForId(m_visualId);
- m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
+ setImageFormatForVisual(visual);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -418,7 +362,7 @@ void QXcbWindow::create()
resolveFormat(platformScreen->surfaceFormatFor(window()->requestedFormat()));
- const xcb_visualtype_t *visual = Q_NULLPTR;
+ const xcb_visualtype_t *visual = nullptr;
if (connection()->hasDefaultVisualId()) {
visual = platformScreen->visualForId(connection()->defaultVisualId());
@@ -451,7 +395,7 @@ void QXcbWindow::create()
m_visualId = visual->visual_id;
m_depth = platformScreen->depthOfVisual(m_visualId);
- m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
+ setImageFormatForVisual(visual);
quint32 mask = XCB_CW_BACK_PIXMAP
| XCB_CW_BORDER_PIXEL
@@ -641,7 +585,7 @@ void QXcbWindow::destroy()
if (connection()->focusWindow() == this)
doFocusOut();
if (connection()->mouseGrabber() == this)
- connection()->setMouseGrabber(Q_NULLPTR);
+ connection()->setMouseGrabber(nullptr);
if (m_syncCounter && m_usingSyncProtocol)
xcb_sync_destroy_counter(xcb_connection(), m_syncCounter);
@@ -700,6 +644,15 @@ void QXcbWindow::setGeometry(const QRect &rect)
qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
};
xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values));
+ if (window()->parent() && !window()->transientParent()) {
+ // Wait for server reply for parented windows to ensure that a few window
+ // moves will come as a one event. This is important when native widget is
+ // moved a few times in X and Y directions causing native scroll. Widget
+ // must get single event to not trigger unwanted widget position changes
+ // and then expose events causing backingstore flushes with incorrect
+ // offset causing image crruption.
+ connection()->sync();
+ }
}
xcb_flush(xcb_connection());
@@ -877,12 +830,12 @@ void QXcbWindow::hide()
xcb_flush(xcb_connection());
if (connection()->mouseGrabber() == this)
- connection()->setMouseGrabber(Q_NULLPTR);
+ connection()->setMouseGrabber(nullptr);
if (QPlatformWindow *w = connection()->mousePressWindow()) {
// Unset mousePressWindow when it (or one of its parents) is unmapped
while (w) {
if (w == this) {
- connection()->setMousePressWindow(Q_NULLPTR);
+ connection()->setMousePressWindow(nullptr);
break;
}
w = w->parent();
@@ -900,7 +853,7 @@ void QXcbWindow::hide()
// Find the top level window at cursor position.
// Don't use QGuiApplication::topLevelAt(): search only the virtual siblings of this window's screen
- QWindow *enterWindow = Q_NULLPTR;
+ QWindow *enterWindow = nullptr;
const auto screens = xcbScreen()->virtualSiblings();
for (QPlatformScreen *screen : screens) {
if (screen->geometry().contains(cursorPos)) {
@@ -2000,13 +1953,14 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
return;
if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
- if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
+ xcb_atom_t protocolAtom = event->data.data32[0];
+ if (protocolAtom == atom(QXcbAtom::WM_DELETE_WINDOW)) {
QWindowSystemInterface::handleCloseEvent(window());
- } else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) {
+ } else if (protocolAtom == atom(QXcbAtom::WM_TAKE_FOCUS)) {
connection()->setTime(event->data.data32[1]);
relayFocusToModalWindow();
return;
- } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
+ } else if (protocolAtom == atom(QXcbAtom::_NET_WM_PING)) {
if (event->window == xcbScreen()->root())
return;
@@ -2015,20 +1969,23 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
reply.response_type = XCB_CLIENT_MESSAGE;
reply.window = xcbScreen()->root();
- xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
+ xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+ (const char *)&reply);
xcb_flush(xcb_connection());
- } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
+ } else if (protocolAtom == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
connection()->setTime(event->data.data32[1]);
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
if (m_usingSyncProtocol)
m_syncState = SyncReceived;
#ifndef QT_NO_WHATSTHIS
- } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) {
+ } else if (protocolAtom == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) {
QWindowSystemInterface::handleEnterWhatsThisEvent();
#endif
} else {
- qWarning() << "QXcbWindow: Unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
+ qCWarning(lcQpaXcb, "Unhandled WM_PROTOCOLS (%s)",
+ connection()->atomName(protocolAtom).constData());
}
#ifndef QT_NO_DRAGANDDROP
} else if (event->type == atom(QXcbAtom::XdndEnter)) {
@@ -2056,7 +2013,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
|| event->type == atom(QXcbAtom::_GTK_LOAD_ICONTHEMES)) {
//silence the _COMPIZ and _GTK messages for now
} else {
- qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type);
+ qCWarning(lcQpaXcb) << "Unhandled client message: " << connection()->atomName(event->type);
}
}
@@ -2165,7 +2122,8 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
}
void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
- int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source)
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source)
{
const bool isWheel = detail >= 4 && detail <= 7;
if (!isWheel && window() != QGuiApplication::focusWindow()) {
@@ -2214,11 +2172,12 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
connection()->setMousePressWindow(this);
- handleMouseEvent(timestamp, local, global, modifiers, source);
+ handleMouseEvent(timestamp, local, global, modifiers, type, source);
}
void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
- int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source)
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source)
{
QPoint local(event_x, event_y);
QPoint global(root_x, root_y);
@@ -2229,9 +2188,9 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
}
if (connection()->buttonState() == Qt::NoButton)
- connection()->setMousePressWindow(Q_NULLPTR);
+ connection()->setMousePressWindow(nullptr);
- handleMouseEvent(timestamp, local, global, modifiers, source);
+ handleMouseEvent(timestamp, local, global, modifiers, type, source);
}
static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
@@ -2254,7 +2213,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
return true;
}
-static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR)
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr)
{
return ((doCheckUnGrabAncestor(conn)
&& mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
@@ -2263,7 +2222,7 @@ static bool ignoreLeaveEvent(quint8 mode, quint8 detail, QXcbConnection *conn =
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
}
-static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = Q_NULLPTR)
+static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = nullptr)
{
return ((doCheckUnGrabAncestor(conn)
&& mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR)
@@ -2332,7 +2291,8 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
}
void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
- Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source)
+ Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source)
{
QPoint local(event_x, event_y);
QPoint global(root_x, root_y);
@@ -2340,33 +2300,34 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i
// "mousePressWindow" can be NULL i.e. if a window will be grabbed or unmapped, so set it again here.
// Unset "mousePressWindow" when mouse button isn't pressed - in some cases the release event won't arrive.
const bool isMouseButtonPressed = (connection()->buttonState() != Qt::NoButton);
- const bool hasMousePressWindow = (connection()->mousePressWindow() != Q_NULLPTR);
+ const bool hasMousePressWindow = (connection()->mousePressWindow() != nullptr);
if (isMouseButtonPressed && !hasMousePressWindow)
connection()->setMousePressWindow(this);
else if (hasMousePressWindow && !isMouseButtonPressed)
- connection()->setMousePressWindow(Q_NULLPTR);
+ connection()->setMousePressWindow(nullptr);
- handleMouseEvent(timestamp, local, global, modifiers, source);
+ handleMouseEvent(timestamp, local, global, modifiers, type, source);
}
void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
{
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
handleButtonPressEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
- modifiers, event->time);
+ modifiers, event->time, QEvent::MouseButtonPress);
}
void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
{
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
handleButtonReleaseEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
- modifiers, event->time);
+ modifiers, event->time, QEvent::MouseButtonRelease);
}
void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
{
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
- handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, event->time);
+ handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers,
+ event->time, QEvent::MouseMove);
}
#if QT_CONFIG(xinput2)
@@ -2417,18 +2378,18 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName);
conn->setButtonState(button, true);
- handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
+ handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonPress, source);
break;
case XI_ButtonRelease:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName);
conn->setButtonState(button, false);
- handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
+ handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonRelease, source);
break;
case XI_Motion:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName);
- handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, source);
+ handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, QEvent::MouseMove, source);
break;
default:
qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
@@ -2473,10 +2434,13 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
QXcbWindow *QXcbWindow::toWindow() { return this; }
void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
- Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)
+ Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source)
{
connection()->setTime(time);
- QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttonState(), modifiers, source);
+ Qt::MouseButton button = type == QEvent::MouseMove ? Qt::NoButton : connection()->button();
+ QWindowSystemInterface::handleMouseEvent(window(), time, local, global,
+ connection()->buttonState(), button,
+ type, modifiers, source);
}
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
@@ -2526,7 +2490,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
m_lastWindowStateEvent = newState;
m_windowState = newState;
if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
- connection()->setMouseGrabber(Q_NULLPTR);
+ connection()->setMouseGrabber(nullptr);
}
return;
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
@@ -2594,7 +2558,10 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
if (!grab && connection()->mouseGrabber() == this)
- connection()->setMouseGrabber(Q_NULLPTR);
+ connection()->setMouseGrabber(nullptr);
+
+ if (grab && !connection()->canGrab())
+ return false;
#if QT_CONFIG(xinput2)
if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) {
@@ -2604,8 +2571,6 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
return result;
}
#endif
- if (grab && !connection()->canGrab())
- return false;
if (!grab) {
xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
@@ -2812,6 +2777,15 @@ void QXcbWindow::setOpacity(qreal level)
(uchar *)&value);
}
+QVector<xcb_rectangle_t> qRegionToXcbRectangleList(const QRegion &region)
+{
+ QVector<xcb_rectangle_t> rects;
+ rects.reserve(region.rectCount());
+ for (const QRect &r : region)
+ rects.push_back(qRectToXCBRectangle(r));
+ return rects;
+}
+
void QXcbWindow::setMask(const QRegion &region)
{
if (!connection()->hasXShape())
@@ -2820,10 +2794,7 @@ void QXcbWindow::setMask(const QRegion &region)
xcb_shape_mask(connection()->xcb_connection(), XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_BOUNDING, xcb_window(), 0, 0, XCB_NONE);
} else {
- QVector<xcb_rectangle_t> rects;
- rects.reserve(region.rectCount());
- for (const QRect &r : region)
- rects.push_back(qRectToXCBRectangle(r));
+ const auto rects = qRegionToXcbRectangleList(region);
xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
xcb_window(), 0, 0, rects.size(), &rects[0]);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 1ce9b0a42f..638ab26cea 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -146,7 +146,7 @@ public:
QXcbWindow *toWindow() override;
void handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
- Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
+ Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source);
void updateNetWmUserTime(xcb_timestamp_t timestamp);
@@ -188,6 +188,7 @@ public Q_SLOTS:
protected:
virtual void resolveFormat(const QSurfaceFormat &format) { m_format = format; }
virtual const xcb_visualtype_t *createVisual();
+ void setImageFormatForVisual(const xcb_visualtype_t *visual);
QXcbScreen *parentScreen();
@@ -220,13 +221,16 @@ protected:
bool compressExposeEvent(QRegion &exposeRegion);
void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
- int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
void handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
- int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
- Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
+ Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
+ QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
void handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y,
quint8 mode, quint8 detail, xcb_timestamp_t timestamp);
@@ -292,6 +296,8 @@ protected:
void create() override {} // No-op
};
+QVector<xcb_rectangle_t> qRegionToXcbRectangleList(const QRegion &region);
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QXcbWindow*)
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index 01d493156d..a2c56a3dcf 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -4,6 +4,8 @@ QT += core-private gui-private xcb_qpa_lib-private
DEFINES += QT_NO_FOREACH
+macos: CONFIG += no_app_extension_api_only
+
SOURCES = \
qxcbmain.cpp
OTHER_FILES += xcb.json README
diff --git a/src/plugins/platformthemes/flatpak/flatpak.json b/src/plugins/platformthemes/flatpak/flatpak.json
new file mode 100644
index 0000000000..71f834fd08
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/flatpak.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "flatpak" ]
+}
diff --git a/src/plugins/platformthemes/flatpak/flatpak.pro b/src/plugins/platformthemes/flatpak/flatpak.pro
new file mode 100644
index 0000000000..1e5dbb7a6c
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/flatpak.pro
@@ -0,0 +1,17 @@
+TARGET = qflatpak
+
+PLUGIN_TYPE = platformthemes
+PLUGIN_EXTENDS = -
+PLUGIN_CLASS_NAME = QFlatpakThemePlugin
+load(qt_plugin)
+
+QT += core-private dbus gui-private theme_support-private
+
+HEADERS += \
+ qflatpaktheme.h \
+ qflatpakfiledialog_p.h
+
+SOURCES += \
+ main.cpp \
+ qflatpaktheme.cpp \
+ qflatpakfiledialog.cpp
diff --git a/src/plugins/platformthemes/flatpak/main.cpp b/src/plugins/platformthemes/flatpak/main.cpp
new file mode 100644
index 0000000000..7888eed8b2
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformthemeplugin.h>
+#include "qflatpaktheme.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFlatpakThemePlugin : public QPlatformThemePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "flatpak.json")
+
+public:
+ QPlatformTheme *create(const QString &key, const QStringList &params) override;
+};
+
+QPlatformTheme *QFlatpakThemePlugin::create(const QString &key, const QStringList &params)
+{
+ Q_UNUSED(params);
+ if (!key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive))
+ return new QFlatpakTheme;
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
new file mode 100644
index 0000000000..c51223186e
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qflatpakfiledialog_p.h"
+
+#include <QtCore/qeventloop.h>
+
+#include <QtDBus/QtDBus>
+#include <QDBusConnection>
+#include <QDBusMessage>
+#include <QDBusPendingCall>
+#include <QDBusPendingCallWatcher>
+#include <QDBusPendingReply>
+
+#include <QMetaType>
+#include <QMimeType>
+#include <QMimeDatabase>
+#include <QWindow>
+
+QT_BEGIN_NAMESPACE
+
+QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::FilterCondition &filterCondition)
+{
+ arg.beginStructure();
+ arg << filterCondition.type << filterCondition.pattern;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::FilterCondition &filterCondition)
+{
+ uint type;
+ QString filterPattern;
+ arg.beginStructure();
+ arg >> type >> filterPattern;
+ filterCondition.type = (QFlatpakFileDialog::ConditionType)type;
+ filterCondition.pattern = filterPattern;
+ arg.endStructure();
+
+ return arg;
+}
+
+QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::Filter filter)
+{
+ arg.beginStructure();
+ arg << filter.name << filter.filterConditions;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::Filter &filter)
+{
+ QString name;
+ QFlatpakFileDialog::FilterConditionList filterConditions;
+ arg.beginStructure();
+ arg >> name >> filterConditions;
+ filter.name = name;
+ filter.filterConditions = filterConditions;
+ arg.endStructure();
+
+ return arg;
+}
+
+class QFlatpakFileDialogPrivate
+{
+public:
+ WId winId = 0;
+ bool modal = false;
+ bool multipleFiles = false;
+ bool saveFile = false;
+ QString acceptLabel;
+ QString directory;
+ QString title;
+ QStringList nameFilters;
+ QStringList mimeTypesFilters;
+ QStringList selectedFiles;
+};
+
+QFlatpakFileDialog::QFlatpakFileDialog()
+ : QPlatformFileDialogHelper()
+ , d_ptr(new QFlatpakFileDialogPrivate)
+{
+}
+
+QFlatpakFileDialog::~QFlatpakFileDialog()
+{
+}
+
+void QFlatpakFileDialog::initializeDialog()
+{
+ Q_D(QFlatpakFileDialog);
+
+ if (options()->fileMode() == QFileDialogOptions::ExistingFiles)
+ d->multipleFiles = true;
+
+ if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
+ d->acceptLabel = options()->labelText(QFileDialogOptions::Accept);
+
+ if (!options()->windowTitle().isEmpty())
+ d->title = options()->windowTitle();
+
+ if (options()->acceptMode() == QFileDialogOptions::AcceptSave)
+ d->saveFile = true;
+
+ if (!options()->nameFilters().isEmpty())
+ d->nameFilters = options()->nameFilters();
+
+ if (!options()->mimeTypeFilters().isEmpty())
+ d->mimeTypesFilters = options()->mimeTypeFilters();
+
+ setDirectory(options()->initialDirectory());
+}
+
+bool QFlatpakFileDialog::defaultNameFilterDisables() const
+{
+ return false;
+}
+
+void QFlatpakFileDialog::setDirectory(const QUrl &directory)
+{
+ Q_D(QFlatpakFileDialog);
+
+ d->directory = directory.path();
+}
+
+QUrl QFlatpakFileDialog::directory() const
+{
+ Q_D(const QFlatpakFileDialog);
+
+ return d->directory;
+}
+
+void QFlatpakFileDialog::selectFile(const QUrl &filename)
+{
+ Q_D(QFlatpakFileDialog);
+
+ d->selectedFiles << filename.path();
+}
+
+QList<QUrl> QFlatpakFileDialog::selectedFiles() const
+{
+ Q_D(const QFlatpakFileDialog);
+
+ QList<QUrl> files;
+ for (const QString &file : d->selectedFiles) {
+ files << QUrl(file);
+ }
+ return files;
+}
+
+void QFlatpakFileDialog::setFilter()
+{
+ // TODO
+}
+
+void QFlatpakFileDialog::selectNameFilter(const QString &filter)
+{
+ Q_UNUSED(filter);
+ // TODO
+}
+
+QString QFlatpakFileDialog::selectedNameFilter() const
+{
+ // TODO
+ return QString();
+}
+
+void QFlatpakFileDialog::exec()
+{
+ Q_D(const QFlatpakFileDialog);
+
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+ QLatin1String("org.freedesktop.portal.FileChooser"),
+ d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
+ QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId);
+
+ QVariantMap options;
+ if (!d->acceptLabel.isEmpty())
+ options.insert(QLatin1String("accept_label"), d->acceptLabel);
+
+ options.insert(QLatin1String("modal"), d->modal);
+ options.insert(QLatin1String("multiple"), d->multipleFiles);
+
+ if (d->saveFile) {
+ if (!d->directory.isEmpty())
+ options.insert(QLatin1String("current_folder"), d->directory.toLatin1());
+
+ if (!d->selectedFiles.isEmpty())
+ options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1());
+ }
+
+ // Insert filters
+ qDBusRegisterMetaType<FilterCondition>();
+ qDBusRegisterMetaType<FilterConditionList>();
+ qDBusRegisterMetaType<Filter>();
+ qDBusRegisterMetaType<FilterList>();
+
+ FilterList filterList;
+
+ if (!d->mimeTypesFilters.isEmpty()) {
+ for (const QString &mimeTypefilter : d->mimeTypesFilters) {
+ QMimeDatabase mimeDatabase;
+ QMimeType mimeType = mimeDatabase.mimeTypeForName(mimeTypefilter);
+
+ // Creates e.g. (1, "image/png")
+ FilterCondition filterCondition;
+ filterCondition.type = MimeType;
+ filterCondition.pattern = mimeTypefilter;
+
+ // Creates e.g. [((1, "image/png"))]
+ FilterConditionList filterConditions;
+ filterConditions << filterCondition;
+
+ // Creates e.g. [("Images", [((1, "image/png"))])]
+ Filter filter;
+ filter.name = mimeType.comment();
+ filter.filterConditions = filterConditions;
+
+ filterList << filter;
+ }
+ } else if (!d->nameFilters.isEmpty()) {
+ for (const QString &filter : d->nameFilters) {
+ // Do parsing:
+ // Supported format is ("Images (*.png *.jpg)")
+ QRegularExpression regexp(QPlatformFileDialogHelper::filterRegExp);
+ QRegularExpressionMatch match = regexp.match(filter);
+ if (match.hasMatch()) {
+ QString userVisibleName = match.captured(1);
+ QStringList filterStrings = match.captured(2).split(QLatin1String(" "));
+
+ FilterConditionList filterConditions;
+ for (const QString &filterString : filterStrings) {
+ FilterCondition filterCondition;
+ filterCondition.type = GlobalPattern;
+ filterCondition.pattern = filterString;
+ filterConditions << filterCondition;
+ }
+
+ Filter filter;
+ filter.name = userVisibleName;
+ filter.filterConditions = filterConditions;
+
+ filterList << filter;
+ }
+ }
+ }
+
+ if (!filterList.isEmpty())
+ options.insert(QLatin1String("filters"), QVariant::fromValue(filterList));
+
+ // TODO choices a(ssa(ss)s)
+ // List of serialized combo boxes to add to the file chooser.
+
+ message << parentWindowId << d->title << options;
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError()) {
+ Q_EMIT reject();
+ } else {
+ QDBusConnection::sessionBus().connect(nullptr,
+ reply.value().path(),
+ QLatin1String("org.freedesktop.portal.Request"),
+ QLatin1String("Response"),
+ this,
+ SLOT(gotResponse(uint,QVariantMap)));
+ }
+ });
+
+ // HACK we have to avoid returning until we emit that the dialog was accepted or rejected
+ QEventLoop loop;
+ loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+ loop.connect(this, SIGNAL(reject()), SLOT(quit()));
+ loop.exec();
+}
+
+void QFlatpakFileDialog::hide()
+{
+}
+
+bool QFlatpakFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+ Q_D(QFlatpakFileDialog);
+ Q_UNUSED(windowFlags);
+
+ initializeDialog();
+
+ d->modal = windowModality != Qt::NonModal;
+ d->winId = parent ? parent->winId() : 0;
+
+ return true;
+}
+
+void QFlatpakFileDialog::gotResponse(uint response, const QVariantMap &results)
+{
+ Q_D(QFlatpakFileDialog);
+
+ if (!response) {
+ if (results.contains(QLatin1String("uris")))
+ d->selectedFiles = results.value(QLatin1String("uris")).toStringList();
+
+ Q_EMIT accept();
+ } else {
+ Q_EMIT reject();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
new file mode 100644
index 0000000000..8f65d07e62
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QFLATPAKFILEDIALOG_P_H
+#define QFLATPAKFILEDIALOG_P_H
+
+#include <qpa/qplatformdialoghelper.h>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+class QFlatpakFileDialogPrivate;
+
+class QFlatpakFileDialog : public QPlatformFileDialogHelper
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFlatpakFileDialog)
+public:
+ enum ConditionType : uint {
+ GlobalPattern = 0,
+ MimeType = 1
+ };
+ // Filters a(sa(us))
+ // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
+ struct FilterCondition {
+ ConditionType type;
+ QString pattern; // E.g. '*ico' or 'image/png'
+ };
+ typedef QVector<FilterCondition> FilterConditionList;
+
+ struct Filter {
+ QString name; // E.g. 'Images' or 'Text
+ FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')]
+ };
+ typedef QVector<Filter> FilterList;
+
+ QFlatpakFileDialog();
+ ~QFlatpakFileDialog();
+
+ bool defaultNameFilterDisables() const override;
+ QUrl directory() const override;
+ void setDirectory(const QUrl &directory) override;
+ void selectFile(const QUrl &filename) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override;
+ void selectNameFilter(const QString &filter) override;
+ QString selectedNameFilter() const override;
+
+ void exec() override;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
+
+private Q_SLOTS:
+ void gotResponse(uint response, const QVariantMap &results);
+
+private:
+ void initializeDialog();
+
+ QScopedPointer<QFlatpakFileDialogPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterCondition);
+Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterConditionList);
+Q_DECLARE_METATYPE(QFlatpakFileDialog::Filter);
+Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterList);
+
+#endif // QFLATPAKFILEDIALOG_P_H
+
diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
new file mode 100644
index 0000000000..04abd707e1
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qflatpaktheme.h"
+#include "qflatpakfiledialog_p.h"
+
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme_p.h>
+#include <qpa/qplatformthemefactory_p.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFlatpakThemePrivate : public QPlatformThemePrivate
+{
+public:
+ QFlatpakThemePrivate()
+ : QPlatformThemePrivate()
+ { }
+
+ ~QFlatpakThemePrivate()
+ {
+ delete baseTheme;
+ }
+
+ QPlatformTheme *baseTheme;
+};
+
+QFlatpakTheme::QFlatpakTheme()
+ : d_ptr(new QFlatpakThemePrivate)
+{
+ Q_D(QFlatpakTheme);
+
+ QStringList themeNames;
+ themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
+ // 1) Look for a theme plugin.
+ for (const QString &themeName : qAsConst(themeNames)) {
+ d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr);
+ if (d->baseTheme)
+ break;
+ }
+
+ // 2) If no theme plugin was found ask the platform integration to
+ // create a theme
+ if (!d->baseTheme) {
+ for (const QString &themeName : qAsConst(themeNames)) {
+ d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
+ if (d->baseTheme)
+ break;
+ }
+ // No error message; not having a theme plugin is allowed.
+ }
+
+ // 3) Fall back on the built-in "null" platform theme.
+ if (!d->baseTheme)
+ d->baseTheme = new QPlatformTheme;
+}
+
+QPlatformMenuItem* QFlatpakTheme::createPlatformMenuItem() const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->createPlatformMenuItem();
+
+ return QPlatformTheme::createPlatformMenuItem();
+}
+
+QPlatformMenu* QFlatpakTheme::createPlatformMenu() const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->createPlatformMenu();
+
+ return QPlatformTheme::createPlatformMenu();
+}
+
+QPlatformMenuBar* QFlatpakTheme::createPlatformMenuBar() const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->createPlatformMenuBar();
+
+ return QFlatpakTheme::createPlatformMenuBar();
+}
+
+void QFlatpakTheme::showPlatformMenuBar()
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->showPlatformMenuBar();
+
+ return QFlatpakTheme::showPlatformMenuBar();
+}
+
+bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (type == FileDialog)
+ return true;
+
+ if (d->baseTheme)
+ return d->baseTheme->usePlatformNativeDialog(type);
+
+ return QFlatpakTheme::usePlatformNativeDialog(type);
+}
+
+QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (type == FileDialog)
+ return new QFlatpakFileDialog;
+
+ if (d->baseTheme)
+ return d->baseTheme->createPlatformDialogHelper(type);
+
+ return QFlatpakTheme::createPlatformDialogHelper(type);
+}
+
+#ifndef QT_NO_SYSTEMTRAYICON
+QPlatformSystemTrayIcon* QFlatpakTheme::createPlatformSystemTrayIcon() const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->createPlatformSystemTrayIcon();
+
+ return QPlatformTheme::createPlatformSystemTrayIcon();
+}
+#endif
+
+const QPalette *QFlatpakTheme::palette(Palette type) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->palette(type);
+
+ return QPlatformTheme::palette(type);
+}
+
+const QFont* QFlatpakTheme::font(Font type) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->font(type);
+
+ return QPlatformTheme::font(type);
+}
+
+QVariant QFlatpakTheme::themeHint(ThemeHint hint) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->themeHint(hint);
+
+ return QPlatformTheme::themeHint(hint);
+}
+
+QPixmap QFlatpakTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->standardPixmap(sp, size);
+
+ return QPlatformTheme::standardPixmap(sp, size);
+}
+
+QIcon QFlatpakTheme::fileIcon(const QFileInfo &fileInfo,
+ QPlatformTheme::IconOptions iconOptions) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->fileIcon(fileInfo, iconOptions);
+
+ return QPlatformTheme::fileIcon(fileInfo, iconOptions);
+}
+
+QIconEngine * QFlatpakTheme::createIconEngine(const QString &iconName) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->createIconEngine(iconName);
+
+ return QPlatformTheme::createIconEngine(iconName);
+}
+
+QList<QKeySequence> QFlatpakTheme::keyBindings(QKeySequence::StandardKey key) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->keyBindings(key);
+
+ return QPlatformTheme::keyBindings(key);
+}
+
+QString QFlatpakTheme::standardButtonText(int button) const
+{
+ Q_D(const QFlatpakTheme);
+
+ if (d->baseTheme)
+ return d->baseTheme->standardButtonText(button);
+
+ return QPlatformTheme::standardButtonText(button);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.h b/src/plugins/platformthemes/flatpak/qflatpaktheme.h
new file mode 100644
index 0000000000..fcaac5b673
--- /dev/null
+++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFLATPAKTHEME_H
+#define QFLATPAKTHEME_H
+
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFlatpakThemePrivate;
+
+class QFlatpakTheme : public QPlatformTheme
+{
+ Q_DECLARE_PRIVATE(QFlatpakTheme)
+public:
+ QFlatpakTheme();
+
+ QPlatformMenuItem *createPlatformMenuItem() const override;
+ QPlatformMenu *createPlatformMenu() const override;
+ QPlatformMenuBar *createPlatformMenuBar() const override;
+ void showPlatformMenuBar() override;
+
+ bool usePlatformNativeDialog(DialogType type) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+
+#ifndef QT_NO_SYSTEMTRAYICON
+ QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
+#endif
+
+ const QPalette *palette(Palette type = SystemPalette) const override;
+
+ const QFont *font(Font type = SystemFont) const override;
+
+ QVariant themeHint(ThemeHint hint) const override;
+
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
+ QIcon fileIcon(const QFileInfo &fileInfo,
+ QPlatformTheme::IconOptions iconOptions = 0) const;
+
+ QIconEngine *createIconEngine(const QString &iconName) const override;
+
+ QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const override;
+
+ QString standardButtonText(int button) const override;
+
+private:
+ QScopedPointer<QFlatpakThemePrivate> d_ptr;
+ Q_DISABLE_COPY(QFlatpakTheme)
+};
+
+QT_END_NAMESPACE
+
+#endif // QFLATPAKTHEME_H
diff --git a/src/plugins/platformthemes/gtk3/main.cpp b/src/plugins/platformthemes/gtk3/main.cpp
index c4cd66c33b..fb1c425d8e 100644
--- a/src/plugins/platformthemes/gtk3/main.cpp
+++ b/src/plugins/platformthemes/gtk3/main.cpp
@@ -48,7 +48,7 @@ class QGtk3ThemePlugin : public QPlatformThemePlugin
Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "gtk3.json")
public:
- QPlatformTheme *create(const QString &key, const QStringList &params) Q_DECL_OVERRIDE;
+ QPlatformTheme *create(const QString &key, const QStringList &params) override;
};
QPlatformTheme *QGtk3ThemePlugin::create(const QString &key, const QStringList &params)
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
index ba43046e04..e78a7fc6d1 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.h
@@ -63,12 +63,12 @@ public:
QGtk3ColorDialogHelper();
~QGtk3ColorDialogHelper();
- bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
- void exec() Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override;
+ void exec() override;
+ void hide() override;
- void setCurrentColor(const QColor &color) Q_DECL_OVERRIDE;
- QColor currentColor() const Q_DECL_OVERRIDE;
+ void setCurrentColor(const QColor &color) override;
+ QColor currentColor() const override;
private Q_SLOTS:
void onAccepted();
@@ -88,18 +88,18 @@ public:
QGtk3FileDialogHelper();
~QGtk3FileDialogHelper();
- bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
- void exec() Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override;
+ void exec() override;
+ void hide() override;
- bool defaultNameFilterDisables() const Q_DECL_OVERRIDE;
- void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
- QUrl directory() const Q_DECL_OVERRIDE;
- void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- void setFilter() Q_DECL_OVERRIDE;
- void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE;
- QString selectedNameFilter() const Q_DECL_OVERRIDE;
+ bool defaultNameFilterDisables() const override;
+ void setDirectory(const QUrl &directory) override;
+ QUrl directory() const override;
+ void selectFile(const QUrl &filename) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override;
+ void selectNameFilter(const QString &filter) override;
+ QString selectedNameFilter() const override;
private Q_SLOTS:
void onAccepted();
@@ -128,12 +128,12 @@ public:
QGtk3FontDialogHelper();
~QGtk3FontDialogHelper();
- bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) Q_DECL_OVERRIDE;
- void exec() Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override;
+ void exec() override;
+ void hide() override;
- void setCurrentFont(const QFont &font) Q_DECL_OVERRIDE;
- QFont currentFont() const Q_DECL_OVERRIDE;
+ void setCurrentFont(const QFont &font) override;
+ QFont currentFont() const override;
private Q_SLOTS:
void onAccepted();
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.h b/src/plugins/platformthemes/gtk3/qgtk3theme.h
index 52036680c6..8f03b84bb6 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.h
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.h
@@ -49,14 +49,14 @@ class QGtk3Theme : public QGnomeTheme
public:
QGtk3Theme();
- virtual QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE;
- virtual QString gtkFontName() const Q_DECL_OVERRIDE;
+ virtual QVariant themeHint(ThemeHint hint) const override;
+ virtual QString gtkFontName() const override;
- bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
+ bool usePlatformNativeDialog(DialogType type) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
- QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE;
- QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE;
+ QPlatformMenu* createPlatformMenu() const override;
+ QPlatformMenuItem* createPlatformMenuItem() const override;
static const char *name;
};
diff --git a/src/plugins/platformthemes/platformthemes.pro b/src/plugins/platformthemes/platformthemes.pro
index 0e2812bed3..ebf92ba9d5 100644
--- a/src/plugins/platformthemes/platformthemes.pro
+++ b/src/plugins/platformthemes/platformthemes.pro
@@ -1,4 +1,6 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += widgets-private
+qtConfig(dbus): SUBDIRS += flatpak
+
qtHaveModule(widgets):qtConfig(gtk3): SUBDIRS += gtk3
diff --git a/src/plugins/printsupport/cups/main.cpp b/src/plugins/printsupport/cups/main.cpp
index 39309a0031..cf263a7f52 100644
--- a/src/plugins/printsupport/cups/main.cpp
+++ b/src/plugins/printsupport/cups/main.cpp
@@ -52,7 +52,7 @@ class QCupsPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
public:
QStringList keys() const;
- QPlatformPrinterSupport *create(const QString &) Q_DECL_OVERRIDE;
+ QPlatformPrinterSupport *create(const QString &) override;
};
QStringList QCupsPrinterSupportPlugin::keys() const
diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp
index 6a4eecb06d..763f676e41 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp
@@ -104,10 +104,9 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v
break;
case PPK_QPageLayout: {
QPageLayout pageLayout = value.value<QPageLayout>();
- if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) {
+ if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution) || d->m_printDevice.supportsCustomPageSizes())) {
d->m_pageLayout = pageLayout;
- // Replace the page size with the CUPS page size
- d->setPageSize(d->m_printDevice.supportedPageSize(pageLayout.pageSize()));
+ d->setPageSize(pageLayout.pageSize());
}
break;
}
@@ -239,9 +238,12 @@ void QCupsPrintEnginePrivate::closePrintDevice()
cupsOptStruct.append(opt);
}
- // Print the file.
+ // Print the file
+ // Cups expect the printer original name without instance, the full name is used only to retrieve the configuration
+ const auto parts = printerName.splitRef(QLatin1Char('/'));
+ const auto printerOriginalName = parts.at(0);
cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0;
- cupsPrintFile(printerName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(),
+ cupsPrintFile(printerOriginalName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(),
title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr);
QFile::remove(tempFile);
diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h
index 0ebf6e7a0f..c99c48c7ea 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -72,8 +72,8 @@ public:
virtual ~QCupsPrintEngine();
// reimplementations QPdfPrintEngine
- void setProperty(PrintEnginePropertyKey key, const QVariant &value) Q_DECL_OVERRIDE;
- QVariant property(PrintEnginePropertyKey key) const Q_DECL_OVERRIDE;
+ void setProperty(PrintEnginePropertyKey key, const QVariant &value) override;
+ QVariant property(PrintEnginePropertyKey key) const override;
// end reimplementations QPdfPrintEngine
private:
@@ -87,8 +87,8 @@ public:
QCupsPrintEnginePrivate(QPrinter::PrinterMode m);
~QCupsPrintEnginePrivate();
- bool openPrintDevice() Q_DECL_OVERRIDE;
- void closePrintDevice() Q_DECL_OVERRIDE;
+ bool openPrintDevice() override;
+ void closePrintDevice() override;
private:
Q_DISABLE_COPY(QCupsPrintEnginePrivate)
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
index df6507d324..42de28aec0 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
@@ -64,12 +64,12 @@ public:
QCupsPrinterSupport();
~QCupsPrinterSupport();
- QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) Q_DECL_OVERRIDE;
- QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) Q_DECL_OVERRIDE;
+ QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
+ QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override;
- QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE;
- QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE;
- QString defaultPrintDeviceId() const Q_DECL_OVERRIDE;
+ QPrintDevice createPrintDevice(const QString &id) override;
+ QStringList availablePrintDeviceIds() const override;
+ QString defaultPrintDeviceId() const override;
private:
QString cupsOption(int i, const QString &key) const;
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index 9efa83d409..340b1a1ff4 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -42,6 +42,8 @@
#include <QtCore/QMimeDatabase>
#include <qdebug.h>
+#include "private/qcups_p.h" // Only needed for PDPK_*
+
#ifndef QT_LINUXBASE // LSB merges everything into cups.h
#include <cups/language.h>
#endif
@@ -421,6 +423,46 @@ QPrint::ColorMode QPpdPrintDevice::defaultColorMode() const
return QPrint::GrayScale;
}
+QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) const
+{
+ if (key == PDPK_PpdFile)
+ return QVariant::fromValue<ppd_file_t *>(m_ppd);
+ else if (key == PDPK_CupsJobPriority)
+ return printerOption(QStringLiteral("job-priority"));
+ else if (key == PDPK_CupsJobSheets)
+ return printerOption(QStringLiteral("job-sheets"));
+ else if (key == PDPK_CupsJobBilling)
+ return printerOption(QStringLiteral("job-billing"));
+ else if (key == PDPK_CupsJobHoldUntil)
+ return printerOption(QStringLiteral("job-hold-until"));
+
+ return QPlatformPrintDevice::property(key);
+}
+
+bool QPpdPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value)
+{
+ if (key == PDPK_PpdOption) {
+ const QStringList values = value.toStringList();
+ if (values.count() == 2) {
+ ppdMarkOption(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+ return true;
+ }
+ }
+
+ return QPlatformPrintDevice::setProperty(key, value);
+}
+
+bool QPpdPrintDevice::isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const
+{
+ if (key == PDPK_PpdChoiceIsInstallableConflict) {
+ const QStringList values = params.toStringList();
+ if (values.count() == 2)
+ return ppdInstallableConflict(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+ }
+
+ return QPlatformPrintDevice::isFeatureAvailable(key, params);
+}
+
#ifndef QT_NO_MIMETYPE
void QPpdPrintDevice::loadMimeTypes() const
{
@@ -452,7 +494,7 @@ void QPpdPrintDevice::loadPrinter()
}
// Get the print instance and PPD file
- m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance);
+ m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance.isNull() ? nullptr : m_cupsInstance.constData());
if (m_cupsDest) {
const char *ppdFile = cupsGetPPD(m_cupsName);
if (ppdFile) {
@@ -461,6 +503,8 @@ void QPpdPrintDevice::loadPrinter()
}
if (m_ppd) {
ppdMarkDefaults(m_ppd);
+ cupsMarkOptions(m_ppd, m_cupsDest->num_options, m_cupsDest->options);
+ ppdLocalize(m_ppd);
} else {
cupsFreeDests(1, m_cupsDest);
m_cupsDest = 0;
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h
index fab7077ce4..9867083bd7 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.h
+++ b/src/plugins/printsupport/cups/qppdprintdevice.h
@@ -69,35 +69,39 @@ public:
explicit QPpdPrintDevice(const QString &id);
virtual ~QPpdPrintDevice();
- bool isValid() const Q_DECL_OVERRIDE;
- bool isDefault() const Q_DECL_OVERRIDE;
+ bool isValid() const override;
+ bool isDefault() const override;
- QPrint::DeviceState state() const Q_DECL_OVERRIDE;
+ QPrint::DeviceState state() const override;
- QPageSize defaultPageSize() const Q_DECL_OVERRIDE;
+ QPageSize defaultPageSize() const override;
QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
- int resolution) const Q_DECL_OVERRIDE;
+ int resolution) const override;
- int defaultResolution() const Q_DECL_OVERRIDE;
+ int defaultResolution() const override;
- QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE;
+ QPrint::InputSlot defaultInputSlot() const override;
- QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE;
+ QPrint::OutputBin defaultOutputBin() const override;
- QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE;
+ QPrint::DuplexMode defaultDuplexMode() const override;
- QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE;
+ QPrint::ColorMode defaultColorMode() const override;
+
+ QVariant property(QPrintDevice::PrintDevicePropertyKey key) const override;
+ bool setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value) override;
+ bool isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const override;
protected:
- void loadPageSizes() const Q_DECL_OVERRIDE;
- void loadResolutions() const Q_DECL_OVERRIDE;
- void loadInputSlots() const Q_DECL_OVERRIDE;
- void loadOutputBins() const Q_DECL_OVERRIDE;
- void loadDuplexModes() const Q_DECL_OVERRIDE;
- void loadColorModes() const Q_DECL_OVERRIDE;
+ void loadPageSizes() const override;
+ void loadResolutions() const override;
+ void loadInputSlots() const override;
+ void loadOutputBins() const override;
+ void loadDuplexModes() const override;
+ void loadColorModes() const override;
#ifndef QT_NO_MIMETYPE
- void loadMimeTypes() const Q_DECL_OVERRIDE;
+ void loadMimeTypes() const override;
#endif
private:
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index 1cb14514ee..b1589c0738 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -87,13 +87,13 @@ static LPDEVMODE getDevmode(HANDLE hPrinter, const QString &printerId)
// Allocate the required DEVMODE buffer
LONG dmSize = DocumentProperties(NULL, hPrinter, printerIdUtf16, NULL, NULL, 0);
if (dmSize <= 0)
- return Q_NULLPTR;
+ return nullptr;
LPDEVMODE pDevMode = reinterpret_cast<LPDEVMODE>(malloc(dmSize));
// Get the default DevMode
LONG result = DocumentProperties(NULL, hPrinter, printerIdUtf16, pDevMode, NULL, DM_OUT_BUFFER);
if (result != IDOK) {
free(pDevMode);
- pDevMode = Q_NULLPTR;
+ pDevMode = nullptr;
}
return pDevMode;
}
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h
index d95a4316cc..6b51ee8785 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.h
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h
@@ -64,34 +64,34 @@ public:
explicit QWindowsPrintDevice(const QString &id);
virtual ~QWindowsPrintDevice();
- bool isValid() const Q_DECL_OVERRIDE;
- bool isDefault() const Q_DECL_OVERRIDE;
+ bool isValid() const override;
+ bool isDefault() const override;
- QPrint::DeviceState state() const Q_DECL_OVERRIDE;
+ QPrint::DeviceState state() const override;
- QPageSize defaultPageSize() const Q_DECL_OVERRIDE;
+ QPageSize defaultPageSize() const override;
QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation,
- int resolution) const Q_DECL_OVERRIDE;
+ int resolution) const override;
- int defaultResolution() const Q_DECL_OVERRIDE;
+ int defaultResolution() const override;
- QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE;
+ QPrint::InputSlot defaultInputSlot() const override;
- QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE;
+ QPrint::DuplexMode defaultDuplexMode() const override;
- QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE;
+ QPrint::ColorMode defaultColorMode() const override;
static QStringList availablePrintDeviceIds();
static QString defaultPrintDeviceId();
protected:
- void loadPageSizes() const Q_DECL_OVERRIDE;
- void loadResolutions() const Q_DECL_OVERRIDE;
- void loadInputSlots() const Q_DECL_OVERRIDE;
- void loadOutputBins() const Q_DECL_OVERRIDE;
- void loadDuplexModes() const Q_DECL_OVERRIDE;
- void loadColorModes() const Q_DECL_OVERRIDE;
+ void loadPageSizes() const override;
+ void loadResolutions() const override;
+ void loadInputSlots() const override;
+ void loadOutputBins() const override;
+ void loadDuplexModes() const override;
+ void loadColorModes() const override;
private:
HANDLE m_hPrinter;
diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h
index 84b60a8207..c42e7aa551 100644
--- a/src/plugins/printsupport/windows/qwindowsprintersupport.h
+++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h
@@ -50,12 +50,12 @@ public:
QWindowsPrinterSupport();
~QWindowsPrinterSupport();
- QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) Q_DECL_OVERRIDE;
- QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) Q_DECL_OVERRIDE;
+ QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
+ QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override;
- QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE;
- QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE;
- QString defaultPrintDeviceId() const Q_DECL_OVERRIDE;
+ QPrintDevice createPrintDevice(const QString &id) override;
+ QStringList availablePrintDeviceIds() const override;
+ QString defaultPrintDeviceId() const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/sqldrivers/db2/qsql_db2.cpp b/src/plugins/sqldrivers/db2/qsql_db2.cpp
index 2bfd99cfa9..1d7e985731 100644
--- a/src/plugins/sqldrivers/db2/qsql_db2.cpp
+++ b/src/plugins/sqldrivers/db2/qsql_db2.cpp
@@ -92,24 +92,24 @@ class QDB2Result: public QSqlResult
public:
QDB2Result(const QDB2Driver *drv);
~QDB2Result();
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool prepare(const QString &query) override;
+ bool exec() override;
+ QVariant handle() const override;
protected:
- QVariant data(int field) Q_DECL_OVERRIDE;
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- bool fetch(int i) Q_DECL_OVERRIDE;
- bool fetchNext() Q_DECL_OVERRIDE;
- bool fetchFirst() Q_DECL_OVERRIDE;
- bool fetchLast() Q_DECL_OVERRIDE;
- bool isNull(int i) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- void detachFromResultSet() Q_DECL_OVERRIDE;
- bool nextResult() Q_DECL_OVERRIDE;
+ QVariant data(int field) override;
+ bool reset(const QString &query) override;
+ bool fetch(int i) override;
+ bool fetchNext() override;
+ bool fetchFirst() override;
+ bool fetchLast() override;
+ bool isNull(int i) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
+ void virtual_hook(int id, void *data) override;
+ void detachFromResultSet() override;
+ bool nextResult() override;
};
class QDB2ResultPrivate: public QSqlResultPrivate
@@ -156,7 +156,7 @@ static SQLTCHAR* qToTChar(const QString& str)
return (SQLTCHAR*)str.utf16();
}
-static QString qWarnDB2Handle(int handleType, SQLHANDLE handle)
+static QString qWarnDB2Handle(int handleType, SQLHANDLE handle, int *errorCode)
{
SQLINTEGER nativeCode;
SQLSMALLINT msgLen;
@@ -171,22 +171,51 @@ static QString qWarnDB2Handle(int handleType, SQLHANDLE handle)
(SQLTCHAR*) description,
SQL_MAX_MESSAGE_LENGTH - 1, /* in bytes, not in characters */
&msgLen);
- if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (errorCode)
+ *errorCode = nativeCode;
return QString(qFromTChar(description));
+ }
return QString();
}
-static QString qDB2Warn(const QDB2DriverPrivate* d)
+static QString qDB2Warn(const QDB2DriverPrivate* d, QStringList *errorCodes = nullptr)
{
- return (qWarnDB2Handle(SQL_HANDLE_ENV, d->hEnv) + QLatin1Char(' ')
- + qWarnDB2Handle(SQL_HANDLE_DBC, d->hDbc));
+ int errorCode = 0;
+ QString error = qWarnDB2Handle(SQL_HANDLE_ENV, d->hEnv, &errorCode);
+ if (errorCodes && errorCode != 0) {
+ *errorCodes << QString::number(errorCode);
+ errorCode = 0;
+ }
+ if (!error.isEmpty())
+ error += QLatin1Char(' ');
+ error += qWarnDB2Handle(SQL_HANDLE_DBC, d->hDbc, &errorCode);
+ if (errorCodes && errorCode != 0)
+ *errorCodes << QString::number(errorCode);
+ return error;
}
-static QString qDB2Warn(const QDB2ResultPrivate* d)
+static QString qDB2Warn(const QDB2ResultPrivate* d, QStringList *errorCodes = nullptr)
{
- return (qWarnDB2Handle(SQL_HANDLE_ENV, d->drv_d_func()->hEnv) + QLatin1Char(' ')
- + qWarnDB2Handle(SQL_HANDLE_DBC, d->drv_d_func()->hDbc)
- + qWarnDB2Handle(SQL_HANDLE_STMT, d->hStmt));
+ int errorCode = 0;
+ QString error = qWarnDB2Handle(SQL_HANDLE_ENV, d->drv_d_func()->hEnv, &errorCode);
+ if (errorCodes && errorCode != 0) {
+ *errorCodes << QString::number(errorCode);
+ errorCode = 0;
+ }
+ if (!error.isEmpty())
+ error += QLatin1Char(' ');
+ error += qWarnDB2Handle(SQL_HANDLE_DBC, d->drv_d_func()->hDbc, &errorCode);
+ if (errorCodes && errorCode != 0) {
+ *errorCodes << QString::number(errorCode);
+ errorCode = 0;
+ }
+ if (!error.isEmpty())
+ error += QLatin1Char(' ');
+ error += qWarnDB2Handle(SQL_HANDLE_STMT, d->hStmt, &errorCode);
+ if (errorCodes && errorCode != 0)
+ *errorCodes << QString::number(errorCode);
+ return error;
}
static void qSqlWarning(const QString& message, const QDB2DriverPrivate* d)
@@ -204,13 +233,19 @@ static void qSqlWarning(const QString& message, const QDB2ResultPrivate* d)
static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
const QDB2DriverPrivate* p)
{
- return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type);
+ QStringList errorCodes;
+ const QString error = qDB2Warn(p, &errorCodes);
+ return QSqlError(QStringLiteral("QDB2: ") + err, error, type,
+ errorCodes.join(QLatin1Char(';')));
}
static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
const QDB2ResultPrivate* p)
{
- return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type);
+ QStringList errorCodes;
+ const QString error = qDB2Warn(p, &errorCodes);
+ return QSqlError(QStringLiteral("QDB2: ") + err, error, type,
+ errorCodes.join(QLatin1Char(';')));
}
static QVariant::Type qDecodeDB2Type(SQLSMALLINT sqltype)
diff --git a/src/plugins/sqldrivers/db2/qsql_db2_p.h b/src/plugins/sqldrivers/db2/qsql_db2_p.h
index fa6d739479..79ae54ab2d 100644
--- a/src/plugins/sqldrivers/db2/qsql_db2_p.h
+++ b/src/plugins/sqldrivers/db2/qsql_db2_p.h
@@ -75,24 +75,24 @@ public:
explicit QDB2Driver(QObject* parent = 0);
QDB2Driver(Qt::HANDLE env, Qt::HANDLE con, QObject* parent = 0);
~QDB2Driver();
- bool hasFeature(DriverFeature) const Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlRecord record(const QString &tableName) const Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType type) const Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &tablename) const Q_DECL_OVERRIDE;
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
- QString formatValue(const QSqlField &field, bool trimStrings) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature) const override;
+ void close() override;
+ QSqlRecord record(const QString &tableName) const override;
+ QStringList tables(QSql::TableType type) const override;
+ QSqlResult *createResult() const override;
+ QSqlIndex primaryIndex(const QString &tablename) const override;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
+ QString formatValue(const QSqlField &field, bool trimStrings) const override;
+ QVariant handle() const override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port,
- const QString& connOpts) Q_DECL_OVERRIDE;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ const QString& connOpts) override;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
private:
bool setAutoCommit(bool autoCommit);
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
index c50fc7916a..d89051191c 100644
--- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
+++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
@@ -356,16 +356,16 @@ class QIBaseResult : public QSqlCachedResult
public:
explicit QIBaseResult(const QIBaseDriver* db);
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool prepare(const QString &query) override;
+ bool exec() override;
+ QVariant handle() const override;
protected:
- bool gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) Q_DECL_OVERRIDE;
- bool reset (const QString &query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
+ bool gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) override;
+ bool reset (const QString &query) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
};
class QIBaseResultPrivate: public QSqlCachedResultPrivate
@@ -388,7 +388,8 @@ public:
return false;
q->setLastError(QSqlError(QCoreApplication::translate("QIBaseResult", msg),
- imsg, typ, int(sqlcode)));
+ imsg, typ,
+ sqlcode != -1 ? QString::number(sqlcode) : QString()));
return true;
}
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase_p.h b/src/plugins/sqldrivers/ibase/qsql_ibase_p.h
index c7cee41462..295f6c0cec 100644
--- a/src/plugins/sqldrivers/ibase/qsql_ibase_p.h
+++ b/src/plugins/sqldrivers/ibase/qsql_ibase_p.h
@@ -74,36 +74,36 @@ public:
explicit QIBaseDriver(QObject *parent = 0);
explicit QIBaseDriver(isc_db_handle connection, QObject *parent = 0);
virtual ~QIBaseDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port,
- const QString &connOpts) Q_DECL_OVERRIDE;
+ const QString &connOpts) override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port) { return open(db, user, password, host, port, QString()); }
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
+ void close() override;
+ QSqlResult *createResult() const override;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
+ QStringList tables(QSql::TableType) const override;
- QSqlRecord record(const QString& tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &table) const Q_DECL_OVERRIDE;
+ QSqlRecord record(const QString& tablename) const override;
+ QSqlIndex primaryIndex(const QString &table) const override;
- QString formatValue(const QSqlField &field, bool trimStrings) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ QString formatValue(const QSqlField &field, bool trimStrings) const override;
+ QVariant handle() const override;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
- bool subscribeToNotification(const QString &name) Q_DECL_OVERRIDE;
- bool unsubscribeFromNotification(const QString &name) Q_DECL_OVERRIDE;
- QStringList subscribedToNotifications() const Q_DECL_OVERRIDE;
+ bool subscribeToNotification(const QString &name) override;
+ bool unsubscribeFromNotification(const QString &name) override;
+ QStringList subscribedToNotifications() const override;
private Q_SLOTS:
void qHandleEventNotification(void* updatedResultBuffer);
diff --git a/src/plugins/sqldrivers/mysql/main.cpp b/src/plugins/sqldrivers/mysql/main.cpp
index 00d9c5bb34..d8d70483ef 100644
--- a/src/plugins/sqldrivers/mysql/main.cpp
+++ b/src/plugins/sqldrivers/mysql/main.cpp
@@ -51,7 +51,7 @@ class QMYSQLDriverPlugin : public QSqlDriverPlugin
public:
QMYSQLDriverPlugin();
- QSqlDriver* create(const QString &) Q_DECL_OVERRIDE;
+ QSqlDriver* create(const QString &) override;
};
QMYSQLDriverPlugin::QMYSQLDriverPlugin()
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 365f89957a..53a72779a9 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -175,26 +175,26 @@ public:
explicit QMYSQLResult(const QMYSQLDriver *db);
~QMYSQLResult();
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant handle() const override;
protected:
void cleanup();
- bool fetch(int i) Q_DECL_OVERRIDE;
- bool fetchNext() Q_DECL_OVERRIDE;
- bool fetchLast() Q_DECL_OVERRIDE;
- bool fetchFirst() Q_DECL_OVERRIDE;
- QVariant data(int field) Q_DECL_OVERRIDE;
- bool isNull(int field) Q_DECL_OVERRIDE;
- bool reset (const QString& query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QVariant lastInsertId() const Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- bool nextResult() Q_DECL_OVERRIDE;
+ bool fetch(int i) override;
+ bool fetchNext() override;
+ bool fetchLast() override;
+ bool fetchFirst() override;
+ QVariant data(int field) override;
+ bool isNull(int field) override;
+ bool reset (const QString& query) override;
+ int size() override;
+ int numRowsAffected() override;
+ QVariant lastInsertId() const override;
+ QSqlRecord record() const override;
+ void virtual_hook(int id, void *data) override;
+ bool nextResult() override;
#if MYSQL_VERSION_ID >= 40108
- bool prepare(const QString &stmt) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
+ bool prepare(const QString &stmt) override;
+ bool exec() override;
#endif
};
@@ -269,7 +269,7 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
const char *cerr = p->mysql ? mysql_error(p->mysql) : 0;
return QSqlError(QLatin1String("QMYSQL: ") + err,
p->tc ? toUnicode(p->tc, cerr) : QString::fromLatin1(cerr),
- type, mysql_errno(p->mysql));
+ type, QString::number(mysql_errno(p->mysql)));
}
@@ -349,7 +349,7 @@ static QSqlError qMakeStmtError(const QString& err, QSqlError::ErrorType type,
const char *cerr = mysql_stmt_error(stmt);
return QSqlError(QLatin1String("QMYSQL3: ") + err,
QString::fromLatin1(cerr),
- type, mysql_stmt_errno(stmt));
+ type, QString::number(mysql_stmt_errno(stmt)));
}
static bool qIsBlob(int t)
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql_p.h b/src/plugins/sqldrivers/mysql/qsql_mysql_p.h
index 7641f9aa34..48b04fb1f5 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql_p.h
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql_p.h
@@ -78,29 +78,29 @@ public:
explicit QMYSQLDriver(QObject *parent=0);
explicit QMYSQLDriver(MYSQL *con, QObject * parent=0);
~QMYSQLDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString & db,
const QString & user,
const QString & password,
const QString & host,
int port,
- const QString& connOpts) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString& tablename) const Q_DECL_OVERRIDE;
- QSqlRecord record(const QString& tablename) const Q_DECL_OVERRIDE;
+ const QString& connOpts) override;
+ void close() override;
+ QSqlResult *createResult() const override;
+ QStringList tables(QSql::TableType) const override;
+ QSqlIndex primaryIndex(const QString& tablename) const override;
+ QSqlRecord record(const QString& tablename) const override;
QString formatValue(const QSqlField &field,
- bool trimStrings) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ bool trimStrings) const override;
+ QVariant handle() const override;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
- bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const override;
protected:
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
private:
void init();
};
diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp
index 9ce2fc1b55..272e1bc083 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci.cpp
+++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp
@@ -55,6 +55,7 @@
#include <qvarlengtharray.h>
#include <qvector.h>
#include <qdebug.h>
+#include <qtimezone.h>
// This is needed for oracle oci when compiling with mingw-w64 headers
#if defined(__MINGW64_VERSION_MAJOR) && defined(_WIN64)
@@ -112,9 +113,6 @@ static const ub2 qOraCharset = OCI_UCS2ID;
typedef QVarLengthArray<sb2, 32> IndicatorArray;
typedef QVarLengthArray<ub2, 32> SizeArray;
-static QByteArray qMakeOraDate(const QDateTime& dt);
-static QDateTime qMakeDate(const char* oraDate);
-
static QByteArray qMakeOCINumber(const qlonglong &ll, OCIError *err);
static QByteArray qMakeOCINumber(const qulonglong& ull, OCIError* err);
@@ -156,6 +154,60 @@ QOCIRowId::~QOCIRowId()
OCIDescriptorFree(id, OCI_DTYPE_ROWID);
}
+class QOCIDateTime
+{
+public:
+ QOCIDateTime(OCIEnv *env, OCIError *err, const QDateTime &dt = QDateTime());
+ ~QOCIDateTime();
+ OCIDateTime *dateTime;
+ static QDateTime fromOCIDateTime(OCIEnv *env, OCIError *err, OCIDateTime *dt);
+};
+
+QOCIDateTime::QOCIDateTime(OCIEnv *env, OCIError *err, const QDateTime &dt)
+ : dateTime(nullptr)
+{
+ OCIDescriptorAlloc(env, reinterpret_cast<void**>(&dateTime), OCI_DTYPE_TIMESTAMP_TZ, 0, 0);
+ if (dt.isValid()) {
+ const QDate date = dt.date();
+ const QTime time = dt.time();
+ // Zone in +hh:mm format (stripping UTC prefix from OffsetName)
+ QString timeZone = dt.timeZone().displayName(dt, QTimeZone::OffsetName).mid(3);
+ const OraText *tz = reinterpret_cast<const OraText *>(timeZone.utf16());
+ OCIDateTimeConstruct(env, err, dateTime, date.year(), date.month(), date.day(), time.hour(),
+ time.minute(), time.second(), time.msec() * 1000000,
+ const_cast<OraText *>(tz), timeZone.length() * sizeof(QChar));
+ }
+}
+
+QOCIDateTime::~QOCIDateTime()
+{
+ if (dateTime != nullptr)
+ OCIDescriptorFree(dateTime, OCI_DTYPE_TIMESTAMP_TZ);
+}
+
+QDateTime QOCIDateTime::fromOCIDateTime(OCIEnv *env, OCIError *err, OCIDateTime *dateTime)
+{
+ sb2 year;
+ ub1 month, day, hour, minute, second;
+ ub4 nsec;
+ sb1 tzHour, tzMinute;
+
+ OCIDateTimeGetDate(env, err, dateTime, &year, &month, &day);
+ OCIDateTimeGetTime(env, err, dateTime, &hour, &minute, &second, &nsec);
+ OCIDateTimeGetTimeZoneOffset(env, err, dateTime, &tzHour, &tzMinute);
+ int secondsOffset = (qAbs(tzHour) * 60 + tzMinute) * 60;
+ if (tzHour < 0)
+ secondsOffset = -secondsOffset;
+ // OCIDateTimeGetTime gives "fractions of second" as nanoseconds
+ return QDateTime(QDate(year, month, day), QTime(hour, minute, second, nsec / 1000000),
+ Qt::OffsetFromUTC, secondsOffset);
+}
+
+struct TempStorage {
+ QList<QByteArray> rawData;
+ QList<QOCIDateTime *> dateTimes;
+};
+
typedef QSharedDataPointer<QOCIRowId> QOCIRowIdPointer;
QT_BEGIN_INCLUDE_NAMESPACE
Q_DECLARE_METATYPE(QOCIRowIdPointer)
@@ -193,19 +245,19 @@ class QOCIResult: public QSqlCachedResult
public:
QOCIResult(const QOCIDriver *db);
~QOCIResult();
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool prepare(const QString &query) override;
+ bool exec() override;
+ QVariant handle() const override;
protected:
- bool gotoNext(ValueCache &values, int index) Q_DECL_OVERRIDE;
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- QVariant lastInsertId() const Q_DECL_OVERRIDE;
- bool execBatch(bool arrayBind = false) Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ bool gotoNext(ValueCache &values, int index) override;
+ bool reset(const QString &query) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
+ QVariant lastInsertId() const override;
+ bool execBatch(bool arrayBind = false) override;
+ void virtual_hook(int id, void *data) override;
bool fetchNext() override;
};
@@ -228,11 +280,11 @@ public:
void setStatementAttributes();
int bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos,
- const QVariant &val, dvoid *indPtr, ub2 *tmpSize, QList<QByteArray> &tmpStorage);
+ const QVariant &val, dvoid *indPtr, ub2 *tmpSize, TempStorage &tmpStorage);
int bindValues(QVector<QVariant> &values, IndicatorArray &indicators, SizeArray &tmpSizes,
- QList<QByteArray> &tmpStorage);
+ TempStorage &tmpStorage);
void outValues(QVector<QVariant> &values, IndicatorArray &indicators,
- QList<QByteArray> &tmpStorage);
+ TempStorage &tmpStorage);
inline bool isOutValue(int i) const
{ Q_Q(const QOCIResult); return q->bindValueType(i) & QSql::Out; }
inline bool isBinaryValue(int i) const
@@ -305,7 +357,7 @@ void QOCIResultPrivate::setStatementAttributes()
}
int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, int pos,
- const QVariant &val, dvoid *indPtr, ub2 *tmpSize, QList<QByteArray> &tmpStorage)
+ const QVariant &val, dvoid *indPtr, ub2 *tmpSize, TempStorage &tmpStorage)
{
int r = OCI_SUCCESS;
void *data = const_cast<void *>(val.constData());
@@ -323,14 +375,15 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
case QVariant::Time:
case QVariant::Date:
case QVariant::DateTime: {
- QByteArray ba = qMakeOraDate(val.toDateTime());
+ QOCIDateTime *ptr = new QOCIDateTime(env, err, val.toDateTime());
r = OCIBindByPos(sql, hbnd, err,
pos + 1,
- ba.data(),
- ba.size(),
- SQLT_DAT, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
- tmpStorage.append(ba);
- break; }
+ &ptr->dateTime,
+ sizeof(OCIDateTime *),
+ SQLT_TIMESTAMP_TZ, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
+ tmpStorage.dateTimes.append(ptr);
+ break;
+ }
case QVariant::Int:
r = OCIBindByPos(sql, hbnd, err,
pos + 1,
@@ -357,7 +410,7 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
ba.data(),
ba.size(),
SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
- tmpStorage.append(ba);
+ tmpStorage.rawData.append(ba);
break;
}
case QVariant::ULongLong:
@@ -368,7 +421,7 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
ba.data(),
ba.size(),
SQLT_VNU, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
- tmpStorage.append(ba);
+ tmpStorage.rawData.append(ba);
break;
}
case QVariant::Double:
@@ -438,7 +491,7 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
}
if (r == OCI_SUCCESS)
setCharset(*hbnd, OCI_HTYPE_BIND);
- tmpStorage.append(ba);
+ tmpStorage.rawData.append(ba);
break;
} // default case
} // switch
@@ -448,7 +501,7 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
}
int QOCIResultPrivate::bindValues(QVector<QVariant> &values, IndicatorArray &indicators,
- SizeArray &tmpSizes, QList<QByteArray> &tmpStorage)
+ SizeArray &tmpSizes, TempStorage &tmpStorage)
{
int r = OCI_SUCCESS;
for (int i = 0; i < values.count(); ++i) {
@@ -466,27 +519,30 @@ int QOCIResultPrivate::bindValues(QVector<QVariant> &values, IndicatorArray &ind
}
// will assign out value and remove its temp storage.
-static void qOraOutValue(QVariant &value, QList<QByteArray> &storage, OCIError* err)
+static void qOraOutValue(QVariant &value, TempStorage &tmpStorage, OCIEnv *env, OCIError* err)
{
switch (value.type()) {
case QVariant::Time:
- value = qMakeDate(storage.takeFirst()).time();
+ value = QOCIDateTime::fromOCIDateTime(env, err,
+ tmpStorage.dateTimes.takeFirst()->dateTime).time();
break;
case QVariant::Date:
- value = qMakeDate(storage.takeFirst()).date();
+ value = QOCIDateTime::fromOCIDateTime(env, err,
+ tmpStorage.dateTimes.takeFirst()->dateTime).date();
break;
case QVariant::DateTime:
- value = qMakeDate(storage.takeFirst());
+ value = QOCIDateTime::fromOCIDateTime(env, err,
+ tmpStorage.dateTimes.takeFirst()->dateTime);
break;
case QVariant::LongLong:
- value = qMakeLongLong(storage.takeFirst(), err);
+ value = qMakeLongLong(tmpStorage.rawData.takeFirst(), err);
break;
case QVariant::ULongLong:
- value = qMakeULongLong(storage.takeFirst(), err);
+ value = qMakeULongLong(tmpStorage.rawData.takeFirst(), err);
break;
case QVariant::String:
value = QString(
- reinterpret_cast<const QChar *>(storage.takeFirst().constData()));
+ reinterpret_cast<const QChar *>(tmpStorage.rawData.takeFirst().constData()));
break;
default:
break; //nothing
@@ -494,14 +550,14 @@ static void qOraOutValue(QVariant &value, QList<QByteArray> &storage, OCIError*
}
void QOCIResultPrivate::outValues(QVector<QVariant> &values, IndicatorArray &indicators,
- QList<QByteArray> &tmpStorage)
+ TempStorage &tmpStorage)
{
for (int i = 0; i < values.count(); ++i) {
if (!isOutValue(i))
continue;
- qOraOutValue(values[i], tmpStorage, err);
+ qOraOutValue(values[i], tmpStorage, env, err);
QVariant::Type typ = values.at(i).type();
if (indicators[i] == -1) // NULL
@@ -588,7 +644,8 @@ QSqlError qMakeError(const QString& errString, QSqlError::ErrorType type, OCIErr
{
int errorCode = 0;
const QString oraErrorString = qOraWarn(err, &errorCode);
- return QSqlError(errString, oraErrorString, type, errorCode);
+ return QSqlError(errString, oraErrorString, type,
+ errorCode != -1 ? QString::number(errorCode) : QString());
}
QVariant::Type qDecodeOCIType(const QString& ocitype, QSql::NumericalPrecisionPolicy precisionPolicy)
@@ -693,11 +750,9 @@ QVariant::Type qDecodeOCIType(int ocitype, QSql::NumericalPrecisionPolicy precis
break;
case SQLT_DAT:
case SQLT_ODT:
-#ifdef SQLT_TIMESTAMP
case SQLT_TIMESTAMP:
case SQLT_TIMESTAMP_TZ:
case SQLT_TIMESTAMP_LTZ:
-#endif
type = QVariant::DateTime;
break;
default:
@@ -724,27 +779,6 @@ static QSqlField qFromOraInf(const OraFieldInfo &ofi)
}
/*!
- \internal
-
- Convert QDateTime to the internal Oracle DATE format NB!
- It does not handle BCE dates.
-*/
-QByteArray qMakeOraDate(const QDateTime& dt)
-{
- QByteArray ba;
- ba.resize(7);
- int year = dt.date().year();
- ba[0]= (year / 100) + 100; // century
- ba[1]= (year % 100) + 100; // year
- ba[2]= dt.date().month();
- ba[3]= dt.date().day();
- ba[4]= dt.time().hour() + 1;
- ba[5]= dt.time().minute() + 1;
- ba[6]= dt.time().second() + 1;
- return ba;
-}
-
-/*!
\internal
Convert qlonglong to the internal Oracle OCINumber format.
@@ -794,22 +828,6 @@ qulonglong qMakeULongLong(const char* ociNumber, OCIError* err)
return qull;
}
-QDateTime qMakeDate(const char* oraDate)
-{
- int century = uchar(oraDate[0]);
- if(century >= 100){
- int year = uchar(oraDate[1]);
- year = ((century-100)*100) + (year-100);
- int month = oraDate[2];
- int day = oraDate[3];
- int hour = oraDate[4] - 1;
- int min = oraDate[5] - 1;
- int sec = oraDate[6] - 1;
- return QDateTime(QDate(year,month,day), QTime(hour,min,sec));
- }
- return QDateTime();
-}
-
class QOCICols
{
public:
@@ -832,7 +850,7 @@ private:
class OraFieldInf
{
public:
- OraFieldInf(): data(0), len(0), ind(0), typ(QVariant::Invalid), oraType(0), def(0), lob(0)
+ OraFieldInf() : data(0), len(0), ind(0), typ(QVariant::Invalid), oraType(0), def(0), lob(0), dataPtr(nullptr)
{}
~OraFieldInf();
char *data;
@@ -842,6 +860,7 @@ private:
ub4 oraType;
OCIDefine *def;
OCILobLocator *lob;
+ void *dataPtr;
};
QVector<OraFieldInf> fieldInf;
@@ -856,6 +875,20 @@ QOCICols::OraFieldInf::~OraFieldInf()
if (r != 0)
qWarning("QOCICols: Cannot free LOB descriptor");
}
+ if (dataPtr) {
+ switch (typ) {
+ case QVariant::Date:
+ case QVariant::Time:
+ case QVariant::DateTime: {
+ int r = OCIDescriptorFree(dataPtr, OCI_DTYPE_TIMESTAMP_TZ);
+ if (r != OCI_SUCCESS)
+ qWarning("QOCICols: Cannot free OCIDateTime descriptor");
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
QOCICols::QOCICols(int size, QOCIResultPrivate* dp)
@@ -902,13 +935,18 @@ QOCICols::QOCICols(int size, QOCIResultPrivate* dp)
switch (ofi.type) {
case QVariant::DateTime:
+ r = OCIDescriptorAlloc(d->env, (void **)&fieldInf[idx].dataPtr, OCI_DTYPE_TIMESTAMP_TZ, 0, 0);
+ if (r != OCI_SUCCESS) {
+ qWarning("QOCICols: Unable to allocate the OCIDateTime descriptor");
+ break;
+ }
r = OCIDefineByPos(d->sql,
&dfn,
d->err,
count,
- create(idx, dataSize+1),
- dataSize+1,
- SQLT_DAT,
+ &fieldInf[idx].dataPtr,
+ sizeof(OCIDateTime *),
+ SQLT_TIMESTAMP_TZ,
&(fieldInf[idx].ind),
0, 0, OCI_DEFAULT);
break;
@@ -1323,11 +1361,10 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
fieldTypes.append(tp == QVariant::List ? boundValues.at(i).toList().value(0).type()
: tp);
}
-
- QList<QByteArray> tmpStorage;
SizeArray tmpSizes(columnCount);
QVector<QOCIBatchColumn> columns(columnCount);
QOCIBatchCleanupHandler cleaner(columns);
+ TempStorage tmpStorage;
// figuring out buffer sizes
for (i = 0; i < columnCount; ++i) {
@@ -1364,8 +1401,8 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
case QVariant::Time:
case QVariant::Date:
case QVariant::DateTime:
- col.bindAs = SQLT_DAT;
- col.maxLen = 7;
+ col.bindAs = SQLT_TIMESTAMP_TZ;
+ col.maxLen = sizeof(OCIDateTime *);
break;
case QVariant::Int:
@@ -1433,7 +1470,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
for (uint row = 0; row < col.recordCount; ++row) {
const QVariant &val = boundValues.at(i).toList().at(row);
- if (val.isNull()){
+ if (val.isNull() && !d->isOutValue(i)) {
columns[i].indicators[row] = -1;
columns[i].lengths[row] = 0;
} else {
@@ -1444,9 +1481,8 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
case QVariant::Date:
case QVariant::DateTime:{
columns[i].lengths[row] = columns[i].maxLen;
- const QByteArray ba = qMakeOraDate(val.toDateTime());
- Q_ASSERT(ba.size() == int(columns[i].maxLen));
- memcpy(dataPtr, ba.constData(), columns[i].maxLen);
+ QOCIDateTime *date = new QOCIDateTime(d->env, d->err, val.toDateTime());
+ *reinterpret_cast<OCIDateTime**>(dataPtr) = date->dateTime;
break;
}
case QVariant::Int:
@@ -1582,7 +1618,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
QVariant::Type tp = boundValues.at(i).type();
if (tp != QVariant::List) {
- qOraOutValue(boundValues[i], tmpStorage, d->err);
+ qOraOutValue(boundValues[i], tmpStorage, d->env, d->err);
if (*columns[i].indicators == -1)
boundValues[i] = QVariant(tp);
continue;
@@ -1594,16 +1630,16 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
for (uint r = 0; r < columns[i].recordCount; ++r){
if (columns[i].indicators[r] == -1) {
- (*list)[r] = QVariant();
+ (*list)[r] = QVariant(fieldTypes[i]);
continue;
}
switch(columns[i].bindAs) {
- case SQLT_DAT:
- (*list)[r] = qMakeDate(data + r * columns[i].maxLen);
+ case SQLT_TIMESTAMP_TZ:
+ (*list)[r] = QOCIDateTime::fromOCIDateTime(d->env, d->err,
+ *reinterpret_cast<OCIDateTime **>(data + r * columns[i].maxLen));
break;
-
case SQLT_INT:
(*list)[r] = *reinterpret_cast<int*>(data + r * columns[i].maxLen);
break;
@@ -1647,6 +1683,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
d->q_func()->setAt(QSql::BeforeFirstRow);
d->q_func()->setActive(true);
+ qDeleteAll(tmpStorage.dateTimes);
return true;
}
@@ -1755,7 +1792,8 @@ void QOCICols::getValues(QVector<QVariant> &v, int index)
switch (fld.typ) {
case QVariant::DateTime:
- v[index + i] = QVariant(qMakeDate(fld.data));
+ v[index + i] = QVariant(QOCIDateTime::fromOCIDateTime(d->env, d->err,
+ reinterpret_cast<OCIDateTime *>(fld.dataPtr)));
break;
case QVariant::Double:
case QVariant::Int:
@@ -1985,7 +2023,7 @@ bool QOCIResult::exec()
ub2 stmtType=0;
ub4 iters;
ub4 mode;
- QList<QByteArray> tmpStorage;
+ TempStorage tmpStorage;
IndicatorArray indicators(boundValueCount());
SizeArray tmpSizes(boundValueCount());
@@ -2056,7 +2094,7 @@ bool QOCIResult::exec()
if (hasOutValues())
d->outValues(boundValues(), indicators, tmpStorage);
-
+ qDeleteAll(tmpStorage.dateTimes);
return true;
}
diff --git a/src/plugins/sqldrivers/oci/qsql_oci_p.h b/src/plugins/sqldrivers/oci/qsql_oci_p.h
index 69911f4bee..295c131f1a 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci_p.h
+++ b/src/plugins/sqldrivers/oci/qsql_oci_p.h
@@ -84,21 +84,21 @@ public:
const QString &password,
const QString &host,
int port,
- const QString &connOpts) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
- QSqlRecord record(const QString &tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString& tablename) const Q_DECL_OVERRIDE;
+ const QString &connOpts) override;
+ void close() override;
+ QSqlResult *createResult() const override;
+ QStringList tables(QSql::TableType) const override;
+ QSqlRecord record(const QString &tablename) const override;
+ QSqlIndex primaryIndex(const QString& tablename) const override;
QString formatValue(const QSqlField &field,
- bool trimStrings) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
- QString escapeIdentifier(const QString &identifier, IdentifierType) const Q_DECL_OVERRIDE;
+ bool trimStrings) const override;
+ QVariant handle() const override;
+ QString escapeIdentifier(const QString &identifier, IdentifierType) const override;
protected:
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index c32a29c5e7..547eb2043d 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -163,27 +163,27 @@ public:
QODBCResult(const QODBCDriver *db);
virtual ~QODBCResult();
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
+ bool prepare(const QString &query) override;
+ bool exec() override;
- QVariant lastInsertId() const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant lastInsertId() const override;
+ QVariant handle() const override;
protected:
- bool fetchNext() Q_DECL_OVERRIDE;
- bool fetchFirst() Q_DECL_OVERRIDE;
- bool fetchLast() Q_DECL_OVERRIDE;
- bool fetchPrevious() Q_DECL_OVERRIDE;
- bool fetch(int i) Q_DECL_OVERRIDE;
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- QVariant data(int field) Q_DECL_OVERRIDE;
- bool isNull(int field) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- void detachFromResultSet() Q_DECL_OVERRIDE;
- bool nextResult() Q_DECL_OVERRIDE;
+ bool fetchNext() override;
+ bool fetchFirst() override;
+ bool fetchLast() override;
+ bool fetchPrevious() override;
+ bool fetch(int i) override;
+ bool reset(const QString &query) override;
+ QVariant data(int field) override;
+ bool isNull(int field) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
+ void virtual_hook(int id, void *data) override;
+ void detachFromResultSet() override;
+ bool nextResult() override;
};
class QODBCResultPrivate: public QSqlResultPrivate
@@ -335,7 +335,8 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const
{
int nativeCode = -1;
QString message = qODBCWarn(p, &nativeCode);
- return QSqlError(QLatin1String("QODBC3: ") + err, message, type, nativeCode);
+ return QSqlError(QLatin1String("QODBC3: ") + err, message, type,
+ nativeCode != -1 ? QString::number(nativeCode) : QString());
}
static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
@@ -343,7 +344,8 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
{
int nativeCode = -1;
QString message = qODBCWarn(p, &nativeCode);
- return QSqlError(QLatin1String("QODBC3: ") + err, qODBCWarn(p), type, nativeCode);
+ return QSqlError(QLatin1String("QODBC3: ") + err, qODBCWarn(p), type,
+ nativeCode != -1 ? QString::number(nativeCode) : QString());
}
static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned = true)
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc_p.h b/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
index f4ce8bc243..ea0aa6fc8b 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc_p.h
@@ -92,30 +92,30 @@ public:
explicit QODBCDriver(QObject *parent=0);
QODBCDriver(SQLHANDLE env, SQLHANDLE con, QObject * parent=0);
virtual ~QODBCDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
- QSqlRecord record(const QString &tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &tablename) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
+ void close() override;
+ QSqlResult *createResult() const override;
+ QStringList tables(QSql::TableType) const override;
+ QSqlRecord record(const QString &tablename) const override;
+ QSqlIndex primaryIndex(const QString &tablename) const override;
+ QVariant handle() const override;
QString formatValue(const QSqlField &field,
- bool trimStrings) const Q_DECL_OVERRIDE;
+ bool trimStrings) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port,
- const QString &connOpts) Q_DECL_OVERRIDE;
+ const QString &connOpts) override;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
- bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const override;
protected:
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
private:
bool endTrans();
diff --git a/src/plugins/sqldrivers/psql/main.cpp b/src/plugins/sqldrivers/psql/main.cpp
index 7657fcbfdf..c5d546f6ff 100644
--- a/src/plugins/sqldrivers/psql/main.cpp
+++ b/src/plugins/sqldrivers/psql/main.cpp
@@ -51,7 +51,7 @@ class QPSQLDriverPlugin : public QSqlDriverPlugin
public:
QPSQLDriverPlugin();
- QSqlDriver* create(const QString &) Q_DECL_OVERRIDE;
+ QSqlDriver* create(const QString &) override;
};
QPSQLDriverPlugin::QPSQLDriverPlugin()
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index 35b0f9a3e3..6f105f79ca 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -125,6 +125,14 @@ inline void qPQfreemem(void *buffer)
PQfreemem(buffer);
}
+/* Missing declaration of PGRES_SINGLE_TUPLE for PSQL below 9.2 */
+#if !defined PG_VERSION_NUM || PG_VERSION_NUM-0 < 90200
+static const int PGRES_SINGLE_TUPLE = 9;
+#endif
+
+typedef int StatementId;
+static const StatementId InvalidStatementId = 0;
+
class QPSQLResultPrivate;
class QPSQLResult: public QSqlResult
@@ -135,23 +143,25 @@ public:
QPSQLResult(const QPSQLDriver *db);
~QPSQLResult();
- QVariant handle() const Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ QVariant handle() const override;
+ void virtual_hook(int id, void *data) override;
protected:
void cleanup();
- bool fetch(int i) Q_DECL_OVERRIDE;
- bool fetchFirst() Q_DECL_OVERRIDE;
- bool fetchLast() Q_DECL_OVERRIDE;
- QVariant data(int i) Q_DECL_OVERRIDE;
- bool isNull(int field) Q_DECL_OVERRIDE;
- bool reset (const QString &query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- QVariant lastInsertId() const Q_DECL_OVERRIDE;
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
+ bool fetch(int i) override;
+ bool fetchFirst() override;
+ bool fetchLast() override;
+ bool fetchNext() override;
+ bool nextResult() override;
+ QVariant data(int i) override;
+ bool isNull(int field) override;
+ bool reset (const QString &query) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
+ QVariant lastInsertId() const override;
+ bool prepare(const QString &query) override;
+ bool exec() override;
};
class QPSQLDriverPrivate : public QSqlDriverPrivate
@@ -164,7 +174,9 @@ public:
pro(QPSQLDriver::Version6),
sn(0),
pendingNotifyCheck(false),
- hasBackslashEscape(false)
+ hasBackslashEscape(false),
+ stmtCount(0),
+ currentStmtId(InvalidStatementId)
{ dbmsType = QSqlDriver::PostgreSQL; }
PGconn *connection;
@@ -174,10 +186,19 @@ public:
QStringList seid;
mutable bool pendingNotifyCheck;
bool hasBackslashEscape;
+ int stmtCount;
+ StatementId currentStmtId;
void appendTables(QStringList &tl, QSqlQuery &t, QChar type);
- PGresult * exec(const char * stmt) const;
- PGresult * exec(const QString & stmt) const;
+ PGresult *exec(const char *stmt);
+ PGresult *exec(const QString &stmt);
+ StatementId sendQuery(const QString &stmt);
+ bool setSingleRowMode() const;
+ PGresult *getResult(StatementId stmtId) const;
+ void finishQuery(StatementId stmtId);
+ void discardResults() const;
+ StatementId generateStatementId();
+ void checkPendingNotifications() const;
QPSQLDriver::Protocol getPSQLVersion();
bool setEncodingUtf8();
void setDatestyle();
@@ -187,18 +208,11 @@ public:
void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
{
- QString query;
- if (pro >= QPSQLDriver::Version7_3) {
- query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "
- "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "
- "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "
- "and (pg_class.relname !~ '^pg_') "
- "and (pg_namespace.nspname != 'information_schema') ").arg(type);
- } else {
- query = QString::fromLatin1("select relname, null from pg_class where (relkind = '%1') "
- "and (relname !~ '^Inv') "
- "and (relname !~ '^pg_') ").arg(type);
- }
+ QString query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "
+ "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "
+ "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "
+ "and (pg_class.relname !~ '^pg_') "
+ "and (pg_namespace.nspname != 'information_schema')").arg(type);
t.exec(query);
while (t.next()) {
QString schema = t.value(1).toString();
@@ -209,20 +223,89 @@ void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
}
}
-PGresult * QPSQLDriverPrivate::exec(const char * stmt) const
+PGresult *QPSQLDriverPrivate::exec(const char *stmt)
{
- Q_Q(const QPSQLDriver);
+ // PQexec() silently discards any prior query results that the application didn't eat.
PGresult *result = PQexec(connection, stmt);
- if (seid.size() && !pendingNotifyCheck) {
- pendingNotifyCheck = true;
- QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0));
+ currentStmtId = result ? generateStatementId() : InvalidStatementId;
+ checkPendingNotifications();
+ return result;
+}
+
+PGresult *QPSQLDriverPrivate::exec(const QString &stmt)
+{
+ return exec((isUtf8 ? stmt.toUtf8() : stmt.toLocal8Bit()).constData());
+}
+
+StatementId QPSQLDriverPrivate::sendQuery(const QString &stmt)
+{
+ // Discard any prior query results that the application didn't eat.
+ // This is required for PQsendQuery()
+ discardResults();
+ const int result = PQsendQuery(connection,
+ (isUtf8 ? stmt.toUtf8() : stmt.toLocal8Bit()).constData());
+ currentStmtId = result ? generateStatementId() : InvalidStatementId;
+ return currentStmtId;
+}
+
+bool QPSQLDriverPrivate::setSingleRowMode() const
+{
+ // Activates single-row mode for last sent query, see:
+ // https://www.postgresql.org/docs/9.2/static/libpq-single-row-mode.html
+ // This method should be called immediately after the sendQuery() call.
+#if defined PG_VERSION_NUM && PG_VERSION_NUM-0 >= 90200
+ return PQsetSingleRowMode(connection) > 0;
+#else
+ return false;
+#endif
+}
+
+PGresult *QPSQLDriverPrivate::getResult(StatementId stmtId) const
+{
+ // Make sure the results of stmtId weren't discaded. This might
+ // happen for forward-only queries if somebody executed another
+ // SQL query on the same db connection.
+ if (stmtId != currentStmtId) {
+ // If you change the following warning, remember to update it
+ // on sql-driver.html page too.
+ qWarning("QPSQLDriver::getResult: Query results lost - "
+ "probably discarded on executing another SQL query.");
+ return nullptr;
}
+ PGresult *result = PQgetResult(connection);
+ checkPendingNotifications();
return result;
}
-PGresult * QPSQLDriverPrivate::exec(const QString & stmt) const
+void QPSQLDriverPrivate::finishQuery(StatementId stmtId)
+{
+ if (stmtId != InvalidStatementId && stmtId == currentStmtId) {
+ discardResults();
+ currentStmtId = InvalidStatementId;
+ }
+}
+
+void QPSQLDriverPrivate::discardResults() const
+{
+ while (PGresult *result = PQgetResult(connection))
+ PQclear(result);
+}
+
+StatementId QPSQLDriverPrivate::generateStatementId()
{
- return exec(isUtf8 ? stmt.toUtf8().constData() : stmt.toLocal8Bit().constData());
+ int stmtId = ++stmtCount;
+ if (stmtId <= 0)
+ stmtId = stmtCount = 1;
+ return stmtId;
+}
+
+void QPSQLDriverPrivate::checkPendingNotifications() const
+{
+ Q_Q(const QPSQLDriver);
+ if (seid.size() && !pendingNotifyCheck) {
+ pendingNotifyCheck = true;
+ QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0));
+ }
}
class QPSQLResultPrivate : public QSqlResultPrivate
@@ -234,14 +317,19 @@ public:
: QSqlResultPrivate(q, drv),
result(0),
currentSize(-1),
+ canFetchMoreRows(false),
+ stmtId(InvalidStatementId),
preparedQueriesEnabled(false)
{ }
- QString fieldSerial(int i) const Q_DECL_OVERRIDE { return QLatin1Char('$') + QString::number(i + 1); }
+ QString fieldSerial(int i) const override { return QLatin1Char('$') + QString::number(i + 1); }
void deallocatePreparedStmt();
PGresult *result;
+ QList<PGresult*> nextResultSets;
int currentSize;
+ bool canFetchMoreRows;
+ StatementId stmtId;
bool preparedQueriesEnabled;
QString preparedStmtId;
@@ -264,21 +352,45 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
bool QPSQLResultPrivate::processResults()
{
Q_Q(QPSQLResult);
- if (!result)
+ if (!result) {
+ q->setSelect(false);
+ q->setActive(false);
+ currentSize = -1;
+ canFetchMoreRows = false;
+ if (stmtId != drv_d_func()->currentStmtId) {
+ q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
+ "Query results lost - probably discarded on executing "
+ "another SQL query."), QSqlError::StatementError, drv_d_func(), result));
+ }
return false;
-
+ }
int status = PQresultStatus(result);
- if (status == PGRES_TUPLES_OK) {
+ switch (status) {
+ case PGRES_TUPLES_OK:
q->setSelect(true);
q->setActive(true);
- currentSize = PQntuples(result);
+ currentSize = q->isForwardOnly() ? -1 : PQntuples(result);
+ canFetchMoreRows = false;
+ return true;
+ case PGRES_SINGLE_TUPLE:
+ q->setSelect(true);
+ q->setActive(true);
+ currentSize = -1;
+ canFetchMoreRows = true;
return true;
- } else if (status == PGRES_COMMAND_OK) {
+ case PGRES_COMMAND_OK:
q->setSelect(false);
q->setActive(true);
currentSize = -1;
+ canFetchMoreRows = false;
return true;
+ default:
+ break;
}
+ q->setSelect(false);
+ q->setActive(false);
+ currentSize = -1;
+ canFetchMoreRows = false;
q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
"Unable to create query"), QSqlError::StatementError, drv_d_func(), result));
return false;
@@ -368,9 +480,15 @@ void QPSQLResult::cleanup()
Q_D(QPSQLResult);
if (d->result)
PQclear(d->result);
- d->result = 0;
+ d->result = nullptr;
+ while (!d->nextResultSets.isEmpty())
+ PQclear(d->nextResultSets.takeFirst());
+ if (d->stmtId != InvalidStatementId)
+ d->drv_d_func()->finishQuery(d->stmtId);
+ d->stmtId = InvalidStatementId;
setAt(QSql::BeforeFirstRow);
d->currentSize = -1;
+ d->canFetchMoreRows = false;
setActive(false);
}
@@ -381,23 +499,150 @@ bool QPSQLResult::fetch(int i)
return false;
if (i < 0)
return false;
- if (i >= d->currentSize)
- return false;
if (at() == i)
return true;
+
+ if (isForwardOnly()) {
+ if (i < at())
+ return false;
+ bool ok = true;
+ while (ok && i > at())
+ ok = fetchNext();
+ return ok;
+ }
+
+ if (i >= d->currentSize)
+ return false;
setAt(i);
return true;
}
bool QPSQLResult::fetchFirst()
{
+ Q_D(const QPSQLResult);
+ if (!isActive())
+ return false;
+ if (at() == 0)
+ return true;
+
+ if (isForwardOnly()) {
+ if (at() == QSql::BeforeFirstRow) {
+ // First result has been already fetched by exec() or
+ // nextResult(), just check it has at least one row.
+ if (d->result && PQntuples(d->result) > 0) {
+ setAt(0);
+ return true;
+ }
+ }
+ return false;
+ }
+
return fetch(0);
}
bool QPSQLResult::fetchLast()
{
Q_D(const QPSQLResult);
- return fetch(PQntuples(d->result) - 1);
+ if (!isActive())
+ return false;
+
+ if (isForwardOnly()) {
+ // Cannot seek to last row in forwardOnly mode, so we have to use brute force
+ int i = at();
+ if (i == QSql::AfterLastRow)
+ return false;
+ if (i == QSql::BeforeFirstRow)
+ i = 0;
+ while (fetchNext())
+ ++i;
+ setAt(i);
+ return true;
+ }
+
+ return fetch(d->currentSize - 1);
+}
+
+bool QPSQLResult::fetchNext()
+{
+ Q_D(QPSQLResult);
+ if (!isActive())
+ return false;
+
+ const int currentRow = at(); // Small optimalization
+ if (currentRow == QSql::BeforeFirstRow)
+ return fetchFirst();
+ if (currentRow == QSql::AfterLastRow)
+ return false;
+
+ if (isForwardOnly()) {
+ if (!d->canFetchMoreRows)
+ return false;
+ PQclear(d->result);
+ d->result = d->drv_d_func()->getResult(d->stmtId);
+ if (!d->result) {
+ setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
+ "Unable to get result"), QSqlError::StatementError, d->drv_d_func(), d->result));
+ d->canFetchMoreRows = false;
+ return false;
+ }
+ int status = PQresultStatus(d->result);
+ switch (status) {
+ case PGRES_SINGLE_TUPLE:
+ // Fetched next row of current result set
+ Q_ASSERT(PQntuples(d->result) == 1);
+ Q_ASSERT(d->canFetchMoreRows);
+ setAt(currentRow + 1);
+ return true;
+ case PGRES_TUPLES_OK:
+ // In single-row mode PGRES_TUPLES_OK means end of current result set
+ Q_ASSERT(PQntuples(d->result) == 0);
+ d->canFetchMoreRows = false;
+ return false;
+ default:
+ setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
+ "Unable to get result"), QSqlError::StatementError, d->drv_d_func(), d->result));
+ d->canFetchMoreRows = false;
+ return false;
+ }
+ }
+
+ if (currentRow + 1 >= d->currentSize)
+ return false;
+ setAt(currentRow + 1);
+ return true;
+}
+
+bool QPSQLResult::nextResult()
+{
+ Q_D(QPSQLResult);
+ if (!isActive())
+ return false;
+
+ setAt(QSql::BeforeFirstRow);
+
+ if (isForwardOnly()) {
+ if (d->canFetchMoreRows) {
+ // Skip all rows from current result set
+ while (d->result && PQresultStatus(d->result) == PGRES_SINGLE_TUPLE) {
+ PQclear(d->result);
+ d->result = d->drv_d_func()->getResult(d->stmtId);
+ }
+ d->canFetchMoreRows = false;
+ // Check for unexpected errors
+ if (d->result && PQresultStatus(d->result) == PGRES_FATAL_ERROR)
+ return d->processResults();
+ }
+ // Fetch first result from next result set
+ if (d->result)
+ PQclear(d->result);
+ d->result = d->drv_d_func()->getResult(d->stmtId);
+ return d->processResults();
+ }
+
+ if (d->result)
+ PQclear(d->result);
+ d->result = d->nextResultSets.isEmpty() ? nullptr : d->nextResultSets.takeFirst();
+ return d->processResults();
}
QVariant QPSQLResult::data(int i)
@@ -407,11 +652,12 @@ QVariant QPSQLResult::data(int i)
qWarning("QPSQLResult::data: column %d out of range", i);
return QVariant();
}
+ const int currentRow = isForwardOnly() ? 0 : at();
int ptype = PQftype(d->result, i);
QVariant::Type type = qDecodePSQLType(ptype);
- const char *val = PQgetvalue(d->result, at(), i);
- if (PQgetisnull(d->result, at(), i))
+ if (PQgetisnull(d->result, currentRow, i))
return QVariant(type);
+ const char *val = PQgetvalue(d->result, currentRow, i);
switch (type) {
case QVariant::Bool:
return QVariant((bool)(val[0] == 't'));
@@ -495,8 +741,8 @@ QVariant QPSQLResult::data(int i)
bool QPSQLResult::isNull(int field)
{
Q_D(const QPSQLResult);
- PQgetvalue(d->result, at(), field);
- return PQgetisnull(d->result, at(), field);
+ const int currentRow = isForwardOnly() ? 0 : at();
+ return PQgetisnull(d->result, currentRow, field);
}
bool QPSQLResult::reset (const QString& query)
@@ -507,7 +753,23 @@ bool QPSQLResult::reset (const QString& query)
return false;
if (!driver()->isOpen() || driver()->isOpenError())
return false;
- d->result = d->drv_d_func()->exec(query);
+
+ d->stmtId = d->drv_d_func()->sendQuery(query);
+ if (d->stmtId == InvalidStatementId) {
+ setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
+ "Unable to send query"), QSqlError::StatementError, d->drv_d_func()));
+ return false;
+ }
+
+ if (isForwardOnly())
+ setForwardOnly(d->drv_d_func()->setSingleRowMode());
+
+ d->result = d->drv_d_func()->getResult(d->stmtId);
+ if (!isForwardOnly()) {
+ // Fetch all result sets right away
+ while (PGresult *nextResultSet = d->drv_d_func()->getResult(d->stmtId))
+ d->nextResultSets.append(nextResultSet);
+ }
return d->processResults();
}
@@ -553,10 +815,17 @@ QSqlRecord QPSQLResult::record() const
f.setName(QString::fromUtf8(PQfname(d->result, i)));
else
f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
- QSqlQuery qry(driver()->createResult());
- if (qry.exec(QStringLiteral("SELECT relname FROM pg_class WHERE pg_class.oid = %1")
- .arg(PQftable(d->result, i))) && qry.next()) {
- f.setTableName(qry.value(0).toString());
+
+ // WARNING: We cannot execute any other SQL queries on
+ // the same db connection while forward-only mode is active
+ // (this would discard all results of forward-only query).
+ // So we just skip this...
+ if (!isForwardOnly()) {
+ QSqlQuery qry(driver()->createResult());
+ if (qry.exec(QStringLiteral("SELECT relname FROM pg_class WHERE pg_class.oid = %1")
+ .arg(PQftable(d->result, i))) && qry.next()) {
+ f.setTableName(qry.value(0).toString());
+ }
}
int ptype = PQftype(d->result, i);
f.setType(qDecodePSQLType(ptype));
@@ -675,8 +944,22 @@ bool QPSQLResult::exec()
else
stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId, params);
- d->result = d->drv_d_func()->exec(stmt);
+ d->stmtId = d->drv_d_func()->sendQuery(stmt);
+ if (d->stmtId == InvalidStatementId) {
+ setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
+ "Unable to send query"), QSqlError::StatementError, d->drv_d_func()));
+ return false;
+ }
+
+ if (isForwardOnly())
+ setForwardOnly(d->drv_d_func()->setSingleRowMode());
+ d->result = d->drv_d_func()->getResult(d->stmtId);
+ if (!isForwardOnly()) {
+ // Fetch all result sets right away
+ while (PGresult *nextResultSet = d->drv_d_func()->getResult(d->stmtId))
+ d->nextResultSets.append(nextResultSet);
+ }
return d->processResults();
}
@@ -895,6 +1178,8 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
case LastInsertId:
case LowPrecisionNumbers:
case EventNotifications:
+ case MultipleResultSets:
+ case BLOB:
return true;
case PreparedQueries:
case PositionalPlaceholders:
@@ -903,11 +1188,8 @@ bool QPSQLDriver::hasFeature(DriverFeature f) const
case NamedPlaceholders:
case SimpleLocking:
case FinishQuery:
- case MultipleResultSets:
case CancelQuery:
return false;
- case BLOB:
- return d->pro >= QPSQLDriver::Version7_1;
case Unicode:
return d->isUtf8;
}
@@ -1004,7 +1286,7 @@ QSqlResult *QPSQLDriver::createResult() const
bool QPSQLDriver::beginTransaction()
{
- Q_D(const QPSQLDriver);
+ Q_D(QPSQLDriver);
if (!isOpen()) {
qWarning("QPSQLDriver::beginTransaction: Database not open");
return false;
@@ -1101,12 +1383,10 @@ static void qSplitTableName(QString &tablename, QString &schema)
QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
{
- Q_D(const QPSQLDriver);
QSqlIndex idx(tablename);
if (!isOpen())
return idx;
QSqlQuery i(createResult());
- QString stmt;
QString tbl = tablename;
QString schema;
@@ -1122,42 +1402,20 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
else
schema = std::move(schema).toLower();
- if (d->pro == QPSQLDriver::Version6) {
- stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname "
- "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
- "where pg_cl.relname = '%1_pkey' "
- "and pg_cl.oid = pg_ind.indexrelid "
- "and pg_att2.attrelid = pg_ind.indexrelid "
- "and pg_att1.attrelid = pg_ind.indrelid "
- "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
- "order by pg_att2.attnum");
- } else if (d->pro == QPSQLDriver::Version7 || d->pro == QPSQLDriver::Version7_1) {
- stmt = QLatin1String("select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
- "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
- "where pg_cl.relname = '%1_pkey' "
- "and pg_cl.oid = pg_ind.indexrelid "
- "and pg_att2.attrelid = pg_ind.indexrelid "
- "and pg_att1.attrelid = pg_ind.indrelid "
- "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
- "order by pg_att2.attnum");
- } else if (d->pro >= QPSQLDriver::Version7_3) {
- stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_class.relname "
- "FROM pg_attribute, pg_class "
- "WHERE %1 pg_class.oid IN "
- "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
- " (SELECT oid FROM pg_class WHERE relname = '%2')) "
- "AND pg_attribute.attrelid = pg_class.oid "
- "AND pg_attribute.attisdropped = false "
- "ORDER BY pg_attribute.attnum");
- if (schema.isEmpty())
- stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND"));
- else
- stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema));
- } else {
- qFatal("QPSQLDriver::primaryIndex(tablename): unknown PSQL version, query statement not set");
- }
+ QString stmt = QLatin1String("SELECT pg_attribute.attname, pg_attribute.atttypid::int, "
+ "pg_class.relname "
+ "FROM pg_attribute, pg_class "
+ "WHERE %1 pg_class.oid IN "
+ "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
+ "(SELECT oid FROM pg_class WHERE relname = '%2')) "
+ "AND pg_attribute.attrelid = pg_class.oid "
+ "AND pg_attribute.attisdropped = false "
+ "ORDER BY pg_attribute.attnum");
+ if (schema.isEmpty())
+ stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND"));
+ else
+ stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
+ "pg_namespace where pg_namespace.nspname = '%1') AND").arg(schema));
i.exec(stmt.arg(tbl));
while (i.isActive() && i.next()) {
@@ -1170,7 +1428,6 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
QSqlRecord QPSQLDriver::record(const QString& tablename) const
{
- Q_D(const QPSQLDriver);
QSqlRecord info;
if (!isOpen())
return info;
@@ -1189,105 +1446,44 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
else
schema = std::move(schema).toLower();
- QString stmt;
- if (d->pro == QPSQLDriver::Version6) {
- stmt = QLatin1String("select pg_attribute.attname, int(pg_attribute.atttypid), "
- "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
- "int(pg_attribute.attrelid), pg_attribute.attnum "
- "from pg_class, pg_attribute "
- "where pg_class.relname = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ");
- } else if (d->pro == QPSQLDriver::Version7) {
- stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
- "pg_attribute.attrelid::int, pg_attribute.attnum "
- "from pg_class, pg_attribute "
- "where pg_class.relname = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ");
- } else if (d->pro == QPSQLDriver::Version7_1) {
- stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
- "pg_attrdef.adsrc "
- "from pg_class, pg_attribute "
- "left join pg_attrdef on (pg_attrdef.adrelid = "
- "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
- "where pg_class.relname = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid "
- "order by pg_attribute.attnum ");
- } else if (d->pro >= QPSQLDriver::Version7_3) {
- stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
- "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
- "pg_attrdef.adsrc "
- "from pg_class, pg_attribute "
- "left join pg_attrdef on (pg_attrdef.adrelid = "
- "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
- "where %1 "
- "and pg_class.relname = '%2' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid "
- "and pg_attribute.attisdropped = false "
- "order by pg_attribute.attnum ");
- if (schema.isEmpty())
- stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)"));
- else
- stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
- "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
- } else {
- qFatal("QPSQLDriver::record(tablename): unknown PSQL version, query statement not set");
- }
+ QString stmt = QLatin1String("select pg_attribute.attname, pg_attribute.atttypid::int, "
+ "pg_attribute.attnotnull, pg_attribute.attlen, pg_attribute.atttypmod, "
+ "pg_attrdef.adsrc "
+ "from pg_class, pg_attribute "
+ "left join pg_attrdef on (pg_attrdef.adrelid = "
+ "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
+ "where %1 "
+ "and pg_class.relname = '%2' "
+ "and pg_attribute.attnum > 0 "
+ "and pg_attribute.attrelid = pg_class.oid "
+ "and pg_attribute.attisdropped = false "
+ "order by pg_attribute.attnum");
+ if (schema.isEmpty())
+ stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)"));
+ else
+ stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
+ "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
QSqlQuery query(createResult());
query.exec(stmt.arg(tbl));
- if (d->pro >= QPSQLDriver::Version7_1) {
- while (query.next()) {
- int len = query.value(3).toInt();
- int precision = query.value(4).toInt();
- // swap length and precision if length == -1
- if (len == -1 && precision > -1) {
- len = precision - 4;
- precision = -1;
- }
- QString defVal = query.value(5).toString();
- if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
- defVal = defVal.mid(1, defVal.length() - 2);
- QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
- f.setRequired(query.value(2).toBool());
- f.setLength(len);
- f.setPrecision(precision);
- f.setDefaultValue(defVal);
- f.setSqlType(query.value(1).toInt());
- info.append(f);
- }
- } else {
- // Postgres < 7.1 cannot handle outer joins
- while (query.next()) {
- QString defVal;
- QString stmt2 = QLatin1String("select pg_attrdef.adsrc from pg_attrdef where "
- "pg_attrdef.adrelid = %1 and pg_attrdef.adnum = %2 ");
- QSqlQuery query2(createResult());
- query2.exec(stmt2.arg(query.value(5).toInt()).arg(query.value(6).toInt()));
- if (query2.isActive() && query2.next())
- defVal = query2.value(0).toString();
- if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
- defVal = defVal.mid(1, defVal.length() - 2);
- int len = query.value(3).toInt();
- int precision = query.value(4).toInt();
- // swap length and precision if length == -1
- if (len == -1 && precision > -1) {
- len = precision - 4;
- precision = -1;
- }
- QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
- f.setRequired(query.value(2).toBool());
- f.setLength(len);
- f.setPrecision(precision);
- f.setDefaultValue(defVal);
- f.setSqlType(query.value(1).toInt());
- info.append(f);
+ while (query.next()) {
+ int len = query.value(3).toInt();
+ int precision = query.value(4).toInt();
+ // swap length and precision if length == -1
+ if (len == -1 && precision > -1) {
+ len = precision - 4;
+ precision = -1;
}
+ QString defVal = query.value(5).toString();
+ if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
+ defVal = defVal.mid(1, defVal.length() - 2);
+ QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
+ f.setRequired(query.value(2).toBool());
+ f.setLength(len);
+ f.setPrecision(precision);
+ f.setDefaultValue(defVal);
+ f.setSqlType(query.value(1).toInt());
+ info.append(f);
}
return info;
diff --git a/src/plugins/sqldrivers/psql/qsql_psql_p.h b/src/plugins/sqldrivers/psql/qsql_psql_p.h
index f5cb2e9bd0..2873a9f851 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql_p.h
+++ b/src/plugins/sqldrivers/psql/qsql_psql_p.h
@@ -98,34 +98,34 @@ public:
explicit QPSQLDriver(QObject *parent=0);
explicit QPSQLDriver(PGconn *conn, QObject *parent=0);
~QPSQLDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString & db,
const QString & user,
const QString & password,
const QString & host,
int port,
- const QString& connOpts) Q_DECL_OVERRIDE;
- bool isOpen() const Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString& tablename) const Q_DECL_OVERRIDE;
- QSqlRecord record(const QString& tablename) const Q_DECL_OVERRIDE;
+ const QString& connOpts) override;
+ bool isOpen() const override;
+ void close() override;
+ QSqlResult *createResult() const override;
+ QStringList tables(QSql::TableType) const override;
+ QSqlIndex primaryIndex(const QString& tablename) const override;
+ QSqlRecord record(const QString& tablename) const override;
Protocol protocol() const;
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant handle() const override;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
- QString formatValue(const QSqlField &field, bool trimStrings) const Q_DECL_OVERRIDE;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
+ QString formatValue(const QSqlField &field, bool trimStrings) const override;
- bool subscribeToNotification(const QString &name) Q_DECL_OVERRIDE;
- bool unsubscribeFromNotification(const QString &name) Q_DECL_OVERRIDE;
- QStringList subscribedToNotifications() const Q_DECL_OVERRIDE;
+ bool subscribeToNotification(const QString &name) override;
+ bool unsubscribeFromNotification(const QString &name) override;
+ QStringList subscribedToNotifications() const override;
protected:
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
private Q_SLOTS:
void _q_handleNotification(int);
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index 444b18686a..d1a6582c5a 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -123,19 +123,19 @@ class QSQLiteResult : public QSqlCachedResult
public:
explicit QSQLiteResult(const QSQLiteDriver* db);
~QSQLiteResult();
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant handle() const override;
protected:
- bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) Q_DECL_OVERRIDE;
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- bool prepare(const QString &query) Q_DECL_OVERRIDE;
- bool exec() Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QVariant lastInsertId() const Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- void detachFromResultSet() Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) override;
+ bool reset(const QString &query) override;
+ bool prepare(const QString &query) override;
+ bool exec() override;
+ int size() override;
+ int numRowsAffected() override;
+ QVariant lastInsertId() const override;
+ QSqlRecord record() const override;
+ void detachFromResultSet() override;
+ void virtual_hook(int id, void *data) override;
};
class QSQLiteDriverPrivate : public QSqlDriverPrivate
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h b/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
index ca969a4b53..61be4c937f 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite_p.h
@@ -75,28 +75,28 @@ public:
explicit QSQLiteDriver(QObject *parent = 0);
explicit QSQLiteDriver(sqlite3 *connection, QObject *parent = 0);
~QSQLiteDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString & db,
const QString & user,
const QString & password,
const QString & host,
int port,
- const QString & connOpts) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
+ const QString & connOpts) override;
+ void close() override;
+ QSqlResult *createResult() const override;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
+ QStringList tables(QSql::TableType) const override;
- QSqlRecord record(const QString& tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &table) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
- QString escapeIdentifier(const QString &identifier, IdentifierType) const Q_DECL_OVERRIDE;
+ QSqlRecord record(const QString& tablename) const override;
+ QSqlIndex primaryIndex(const QString &table) const override;
+ QVariant handle() const override;
+ QString escapeIdentifier(const QString &identifier, IdentifierType) const override;
- bool subscribeToNotification(const QString &name) Q_DECL_OVERRIDE;
- bool unsubscribeFromNotification(const QString &name) Q_DECL_OVERRIDE;
- QStringList subscribedToNotifications() const Q_DECL_OVERRIDE;
+ bool subscribeToNotification(const QString &name) override;
+ bool unsubscribeFromNotification(const QString &name) override;
+ QStringList subscribedToNotifications() const override;
private Q_SLOTS:
void handleNotification(const QString &tableName, qint64 rowid);
};
diff --git a/src/plugins/sqldrivers/sqlite/smain.cpp b/src/plugins/sqldrivers/sqlite/smain.cpp
index 2ad466a61e..092813990c 100644
--- a/src/plugins/sqldrivers/sqlite/smain.cpp
+++ b/src/plugins/sqldrivers/sqlite/smain.cpp
@@ -51,7 +51,7 @@ class QSQLiteDriverPlugin : public QSqlDriverPlugin
public:
QSQLiteDriverPlugin();
- QSqlDriver* create(const QString &) Q_DECL_OVERRIDE;
+ QSqlDriver* create(const QString &) override;
};
QSQLiteDriverPlugin::QSQLiteDriverPlugin()
diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
index 93f47e3f13..390f05c7aa 100644
--- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
@@ -107,16 +107,16 @@ class QSQLite2Result : public QSqlCachedResult
public:
explicit QSQLite2Result(const QSQLite2Driver* db);
~QSQLite2Result();
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant handle() const override;
protected:
- bool gotoNext(QSqlCachedResult::ValueCache &row, int idx) Q_DECL_OVERRIDE;
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
- void detachFromResultSet() Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ bool gotoNext(QSqlCachedResult::ValueCache &row, int idx) override;
+ bool reset(const QString &query) override;
+ int size() override;
+ int numRowsAffected() override;
+ QSqlRecord record() const override;
+ void detachFromResultSet() override;
+ void virtual_hook(int id, void *data) override;
};
class QSQLite2ResultPrivate: public QSqlCachedResultPrivate
@@ -178,7 +178,8 @@ void QSQLite2ResultPrivate::finalize()
if (err) {
q->setLastError(QSqlError(QCoreApplication::translate("QSQLite2Result",
"Unable to fetch results"), QString::fromLatin1(err),
- QSqlError::StatementError, res));
+ QSqlError::StatementError,
+ res != -1 ? QString::number(res) : QString()));
sqlite_freemem(err);
}
currentMachine = 0;
diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h
index 83b248ec6a..48c64536f1 100644
--- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h
+++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2_p.h
@@ -79,29 +79,29 @@ public:
explicit QSQLite2Driver(QObject *parent = 0);
explicit QSQLite2Driver(sqlite *connection, QObject *parent = 0);
~QSQLite2Driver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port,
- const QString &connOpts) Q_DECL_OVERRIDE;
+ const QString &connOpts) override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port) { return open(db, user, password, host, port, QString()); }
- void close() Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
+ void close() override;
+ QSqlResult *createResult() const override;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
+ QStringList tables(QSql::TableType) const override;
- QSqlRecord record(const QString &tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &table) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
- QString escapeIdentifier(const QString &identifier, IdentifierType) const Q_DECL_OVERRIDE;
+ QSqlRecord record(const QString &tablename) const override;
+ QSqlIndex primaryIndex(const QString &table) const override;
+ QVariant handle() const override;
+ QString escapeIdentifier(const QString &identifier, IdentifierType) const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/sqldrivers/tds/qsql_tds.cpp b/src/plugins/sqldrivers/tds/qsql_tds.cpp
index 670198af81..ad95b097ef 100644
--- a/src/plugins/sqldrivers/tds/qsql_tds.cpp
+++ b/src/plugins/sqldrivers/tds/qsql_tds.cpp
@@ -132,7 +132,8 @@ QT_BEGIN_NAMESPACE
QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, int errNo = -1)
{
- return QSqlError(QLatin1String("QTDS: ") + err, QString(), type, errNo);
+ return QSqlError(QLatin1String("QTDS: ") + err, QString(), type,
+ errNo != -1 ? QString::number(errNo) : QString());
}
class QTDSDriverPrivate : public QSqlDriverPrivate
@@ -163,15 +164,15 @@ class QTDSResult : public QSqlCachedResult
public:
explicit QTDSResult(const QTDSDriver* db);
~QTDSResult();
- QVariant handle() const Q_DECL_OVERRIDE;
+ QVariant handle() const override;
protected:
void cleanup();
- bool reset(const QString &query) Q_DECL_OVERRIDE;
- int size() Q_DECL_OVERRIDE;
- int numRowsAffected() Q_DECL_OVERRIDE;
- bool gotoNext(QSqlCachedResult::ValueCache &values, int index) Q_DECL_OVERRIDE;
- QSqlRecord record() const Q_DECL_OVERRIDE;
+ bool reset(const QString &query) override;
+ int size() override;
+ int numRowsAffected() override;
+ bool gotoNext(QSqlCachedResult::ValueCache &values, int index) override;
+ QSqlRecord record() const override;
};
class QTDSResultPrivate: public QSqlCachedResultPrivate
diff --git a/src/plugins/sqldrivers/tds/qsql_tds_p.h b/src/plugins/sqldrivers/tds/qsql_tds_p.h
index d0914455a2..948e3c7024 100644
--- a/src/plugins/sqldrivers/tds/qsql_tds_p.h
+++ b/src/plugins/sqldrivers/tds/qsql_tds_p.h
@@ -88,29 +88,29 @@ public:
explicit QTDSDriver(QObject* parent = 0);
QTDSDriver(LOGINREC* rec, const QString& host, const QString &db, QObject* parent = 0);
~QTDSDriver();
- bool hasFeature(DriverFeature f) const Q_DECL_OVERRIDE;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
const QString &host,
int port,
- const QString &connOpts) Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
- QStringList tables(QSql::TableType) const Q_DECL_OVERRIDE;
- QSqlResult *createResult() const Q_DECL_OVERRIDE;
- QSqlRecord record(const QString &tablename) const Q_DECL_OVERRIDE;
- QSqlIndex primaryIndex(const QString &tablename) const Q_DECL_OVERRIDE;
+ const QString &connOpts) override;
+ void close() override;
+ QStringList tables(QSql::TableType) const override;
+ QSqlResult *createResult() const override;
+ QSqlRecord record(const QString &tablename) const override;
+ QSqlIndex primaryIndex(const QString &tablename) const override;
QString formatValue(const QSqlField &field,
- bool trimStrings) const Q_DECL_OVERRIDE;
- QVariant handle() const Q_DECL_OVERRIDE;
+ bool trimStrings) const override;
+ QVariant handle() const override;
- QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE;
+ QString escapeIdentifier(const QString &identifier, IdentifierType type) const override;
protected:
- bool beginTransaction() Q_DECL_OVERRIDE;
- bool commitTransaction() Q_DECL_OVERRIDE;
- bool rollbackTransaction() Q_DECL_OVERRIDE;
+ bool beginTransaction() override;
+ bool commitTransaction() override;
+ bool rollbackTransaction() override;
private:
void init();
};
diff --git a/src/plugins/styles/mac/qmacstyle.qdoc b/src/plugins/styles/mac/qmacstyle.qdoc
index fcbc813844..30b3d7775f 100644
--- a/src/plugins/styles/mac/qmacstyle.qdoc
+++ b/src/plugins/styles/mac/qmacstyle.qdoc
@@ -87,7 +87,7 @@
/*!
- \enum QMacStyle::WidgetSizePolicy
+ \enum QStyleHelper::WidgetSizePolicy
\value SizeSmall
\value SizeLarge
@@ -123,7 +123,7 @@
\reimp
*/
-/*! \fn int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
+/*! \fn int QMacStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
\reimp
*/
@@ -131,7 +131,7 @@
\reimp
*/
-/*! \fn int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const
+/*! \fn int QMacStyle::styleHint(QStyle::StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const
\reimp
*/
@@ -139,11 +139,11 @@
\reimp
*/
-/*! \fn QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+/*! \fn QPixmap QMacStyle::standardPixmap(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
\reimp
*/
-/*! \fn void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy)
+/*! \fn void QStyleHelper::setWidgetSizePolicy(const QWidget *widget, QStyleHelper::WidgetSizePolicy policy)
\obsolete
@@ -151,41 +151,41 @@
or Qt::WA_MacNormalSize instead.
*/
-/*! \fn QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt = 0)
+/*! \fn QStyleHelper::WidgetSizePolicy QStyleHelper::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt)
\obsolete
Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize,
or Qt::WA_MacNormalSize instead.
*/
-/*! \fn void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
+/*! \fn void QMacStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
\reimp
*/
-/*! \fn void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const
+/*! \fn void QMacStyle::drawControl(QStyle::ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const
\reimp
*/
-/*! \fn QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const
+/*! \fn QRect QMacStyle::subElementRect(QStyle::SubElement sr, const QStyleOption *opt, const QWidget *widget) const
\reimp
*/
-/*! \fn void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
+/*! \fn void QMacStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const
\reimp
*/
-/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const
+/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const
\reimp
*/
-/*! \fn QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const
+/*! \fn QRect QMacStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, const QWidget *widget) const
\reimp
*/
-/*! \fn QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const
+/*! \fn QSize QMacStyle::sizeFromContents(QStyle::ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const
\reimp
*/
@@ -197,7 +197,7 @@
\reimp
*/
-/*! \fn QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const
+/*! \fn QIcon QMacStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const
\reimp
*/
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index db02ab1fe9..7972167cfa 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -596,8 +596,7 @@ static QString qt_mac_removeMnemonics(const QString &original)
int currPos = 0;
int l = original.length();
while (l) {
- if (original.at(currPos) == QLatin1Char('&')
- && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) {
+ if (original.at(currPos) == QLatin1Char('&')) {
++currPos;
--l;
if (l == 0)
@@ -922,7 +921,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
height = qMax(height, qMax(iconSize.height(), pmSize.height()));
}
if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) {
- int text_width = bt->fontMetrics().width(bt->text()),
+ int text_width = bt->fontMetrics().horizontalAdvance(bt->text()),
text_height = bt->fontMetrics().height();
if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) {
width = qMax(width, text_width);
@@ -1127,46 +1126,33 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h
static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4");
const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio);
QPixmap focusRingPixmap;
- const qreal size = radius * 2 + 5;
if (!QPixmapCache::find(key, focusRingPixmap)) {
+ const qreal size = radius * 2 + 5;
focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio);
focusRingPixmap.fill(Qt::transparent);
focusRingPixmap.setDevicePixelRatio(pixelRatio);
- {
- const CGFloat focusRingWidth = radius > 0 ? 3.5 : 6;
- QMacAutoReleasePool pool;
- QMacCGContext ctx(&focusRingPixmap);
- setupNSGraphicsContext(ctx, NO);
-
- CGContextBeginTransparencyLayer(ctx, NULL);
- CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below
-
- CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size);
- NSBezierPath *focusRingPath;
- if (radius > 0) {
- const CGFloat roundedRectInset = -1.5;
- focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSRectFromCGRect(CGRectInset(focusRingRect, roundedRectInset, roundedRectInset))
- xRadius:radius
- yRadius:radius];
- } else {
- const CGFloat outerClipInset = -focusRingWidth / 2;
- NSBezierPath *focusRingClipPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(CGRectInset(focusRingRect, outerClipInset, outerClipInset))];
- const CGFloat innerClipInset = 1;
- NSBezierPath *focusRingInnerClipPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(CGRectInset(focusRingRect, innerClipInset, innerClipInset))];
- [focusRingClipPath appendBezierPath:focusRingInnerClipPath.bezierPathByReversingPath];
- [focusRingClipPath setClip];
- focusRingPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(focusRingRect)];
- focusRingPath.lineJoinStyle = NSRoundLineJoinStyle;
- }
- focusRingPath.lineWidth = focusRingWidth;
- [[NSColor keyboardFocusIndicatorColor] setStroke];
- [focusRingPath stroke];
+ static const qreal focusRingWidth = 3.5;
+ const auto focusRingRect = QRectF(hMargin, vMargin, size, size);
+ QPainterPath focusRingPath;
+ focusRingPath.setFillRule(Qt::OddEvenFill);
+ const auto innerRect = radius > 0 ? focusRingRect : focusRingRect.adjusted(0.5, 0.5, -0.5, -0.5);
+ if (radius > 0)
+ focusRingPath.addRoundedRect(innerRect, radius, radius);
+ else
+ focusRingPath.addRect(innerRect);
+
+ const auto outterRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
+ const auto outterRadius = radius + focusRingWidth;
+ focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius);
+
+ QPainter pp(&focusRingPixmap);
+ pp.setOpacity(0.5);
+ pp.setRenderHint(QPainter::Antialiasing);
+ const auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
+ pp.fillPath(focusRingPath, focusRingColor);
- CGContextEndTransparencyLayer(ctx);
- restoreNSGraphicsContext(ctx);
- }
QPixmapCache::insert(key, focusRingPixmap);
}
@@ -1201,6 +1187,57 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h
QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize));
}
+void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
+{
+ static const auto focusRingWidth = 3.5;
+
+ QPainterPath focusRingPath;
+ qreal hOffset = 0.0;
+ qreal vOffset = 0.0;
+ switch (cw.first) {
+ case Button_CheckBox: {
+ const auto cbInnerRadius = (cw.second == QStyleHelper::SizeMini ? 2.0 : 3.0);
+ const auto cbSize = cw.second == QStyleHelper::SizeLarge ? 13 :
+ cw.second == QStyleHelper::SizeSmall ? 11 : 9; // As measured
+ hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 2.5 :
+ cw.second == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured
+ vOffset = 0.5 * qreal(targetRect.height() - cbSize);
+ const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize);
+ const auto cbOutterRadius = cbInnerRadius + focusRingWidth;
+ const auto cbOutterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
+ focusRingPath.setFillRule(Qt::OddEvenFill);
+ focusRingPath.addRoundedRect(cbOutterRect, cbOutterRadius, cbOutterRadius);
+ focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius);
+ break;
+ }
+ case Button_RadioButton: {
+ const auto rbSize = cw.second == QStyleHelper::SizeLarge ? 15 :
+ cw.second == QStyleHelper::SizeSmall ? 13 : 9; // As measured
+ hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 1.5 :
+ cw.second == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured
+ vOffset = 0.5 * qreal(targetRect.height() - rbSize);
+ const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize);
+ const auto rbOutterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
+ focusRingPath.setFillRule(Qt::OddEvenFill);
+ focusRingPath.addEllipse(rbInnerRect);
+ focusRingPath.addEllipse(rbOutterRect);
+ break;
+ }
+ default:
+ Q_UNUSED(vMargin);
+ Q_UNREACHABLE();
+ }
+
+ const auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
+
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing);
+ p->setOpacity(0.5);
+ p->translate(hOffset, vOffset);
+ p->fillPath(focusRingPath, focusRingColor);
+ p->restore();
+}
+
#if QT_CONFIG(tabbar)
void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const
{
@@ -1956,19 +1993,8 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, DrawRectBlock drawRectBlock) const
{
QPoint offset;
- if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeLarge))
- offset.setY(2);
- else if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeSmall))
- offset = QPoint(-1, 2);
- else if (widget == CocoaControl(Button_RadioButton, QStyleHelper::SizeMini))
- offset.setY(2);
- else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall)
- || widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeLarge))
+ if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall))
offset.setY(1);
- else if (widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeSmall))
- offset.setX(-1);
- else if (widget == CocoaControl(Button_CheckBox, QStyleHelper::SizeMini))
- offset = QPoint(7, 5);
else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeMini))
offset = QPoint(2, -1);
else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeLarge))
@@ -2325,7 +2351,15 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_CheckBoxLabelSpacing:
case PM_RadioButtonLabelSpacing:
- ret = 2;
+ ret = [=] {
+ if (opt) {
+ if (opt->state & State_Mini)
+ return 4;
+ if (opt->state & State_Small)
+ return 3;
+ }
+ return 2;
+ } ();
break;
case PM_MenuScrollerHeight:
ret = 15; // I hate having magic numbers in here...
@@ -2964,6 +2998,9 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
// min/max/close buttons on windows don't show tool tips
ret = false;
break;
+ case SH_ComboBox_AllowWheelScrolling:
+ ret = false;
+ break;
default:
ret = QCommonStyle::styleHint(sh, opt, w, hret);
break;
@@ -3264,49 +3301,28 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_IndicatorViewItemCheck:
case PE_IndicatorRadioButton:
case PE_IndicatorCheckBox: {
- bool drawColorless = tds == kThemeStateInactive;
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = tds;
- if (drawColorless)
- bdi.state = kThemeStateActive;
- bdi.adornment = kThemeDrawIndicatorOnly;
- if (opt->state & State_HasFocus)
- bdi.adornment |= kThemeAdornmentFocus;
- bool isRadioButton = (pe == PE_IndicatorRadioButton);
- switch (d->aquaSizeConstrain(opt, w)) {
- case QStyleHelper::SizeDefault:
- case QStyleHelper::SizeLarge:
- if (isRadioButton)
- bdi.kind = kThemeRadioButton;
- else
- bdi.kind = kThemeCheckBox;
- break;
- case QStyleHelper::SizeMini:
- if (isRadioButton)
- bdi.kind = kThemeMiniRadioButton;
- else
- bdi.kind = kThemeMiniCheckBox;
- break;
- case QStyleHelper::SizeSmall:
- if (isRadioButton)
- bdi.kind = kThemeSmallRadioButton;
- else
- bdi.kind = kThemeSmallCheckBox;
- break;
- }
- if (opt->state & State_NoChange)
- bdi.value = kThemeButtonMixed;
- else if (opt->state & State_On)
- bdi.value = kThemeButtonOn;
- else
- bdi.value = kThemeButtonOff;
- CGRect macRect = opt->rect.toCGRect();
- const QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind);
- if (!drawColorless)
- HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0);
- else
- d->drawColorlessButton(macRect, &bdi, cw, p, opt);
+ const bool isEnabled = opt->state & State_Enabled;
+ const bool isPressed = opt->state & State_Sunken;
+ const bool isRadioButton = (pe == PE_IndicatorRadioButton);
+ const auto ct = isRadioButton ? QMacStylePrivate::Button_RadioButton : QMacStylePrivate::Button_CheckBox;
+ const auto cs = d->effectiveAquaSizeConstrain(opt, w);
+ const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
+ auto *tb = static_cast<NSButton *>(d->cocoaControl(cw));
+ tb.enabled = isEnabled;
+ tb.state = (opt->state & State_NoChange) ? NSMixedState :
+ (opt->state & State_On) ? NSOnState : NSOffState;
+ [tb highlight:isPressed];
+ const auto vOffset = [=] {
+ // As measured
+ if (cs == QStyleHelper::SizeMini)
+ return ct == QMacStylePrivate::Button_CheckBox ? -0.5 : 0.5;
+
+ return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0;
+ } ();
+ d->drawNSViewInRect(cw, tb, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ CGContextTranslateCTM(ctx, 0, vOffset);
+ [tb.cell drawInteriorWithFrame:rect inView:tb];
+ });
break; }
case PE_FrameFocusRect:
// Use the our own focus widget stuff.
@@ -3793,7 +3809,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
}
- const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4;
+ const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 3;
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w);
const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height);
@@ -4126,9 +4142,28 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
break;
#endif
case CE_FocusFrame: {
+ const auto *ff = qobject_cast<const QFocusFrame *>(w);
+ const auto *ffw = ff ? ff->widget() : nullptr;
+ const auto ct = [=] {
+ if (ffw) {
+ if (ffw->inherits("QCheckBox"))
+ return QMacStylePrivate::Button_CheckBox;
+ if (ffw->inherits("QRadioButton"))
+ return QMacStylePrivate::Button_RadioButton;
+ }
+
+ return QMacStylePrivate::Box; // Not really, just make it the default
+ } ();
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);
- d->drawFocusRing(p, opt->rect, hMargin, vMargin);
+ if (ct == QMacStylePrivate::Box) {
+ d->drawFocusRing(p, opt->rect, hMargin, vMargin);
+ } else if (ffw) {
+ const auto cs = ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini :
+ ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall :
+ QStyleHelper::SizeLarge;
+ d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs));
+ }
break; }
case CE_MenuEmptyArea:
// Skip: PE_PanelMenu fills in everything
@@ -4283,9 +4318,39 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// and then the combo inherits it and passes it onward. At that point the resolve mask
// is very, very weak. This makes it stonger.
myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF());
+#if 0
+ // QTBUG-65653: This doesn't look good enough, especially on non-retina displays.
+ // Worked around below while waiting for a proper fix in QCoreTextFontEngine.
p->setFont(myFont);
p->drawText(xpos, yPos, mi->rect.width() - xm - tabwidth + 1,
mi->rect.height(), text_flags, s);
+#else
+ QMacCGContext cgCtx(p);
+ d->setupNSGraphicsContext(cgCtx, YES);
+
+ // Respect the menu item palette as set in the style option.
+ const auto pc = p->pen().color();
+ NSColor *c = [NSColor colorWithSRGBRed:pc.redF()
+ green:pc.greenF()
+ blue:pc.blueF()
+ alpha:pc.alphaF()];
+
+ // Respect the menu item action font as set in the style option.
+ const auto *fontEngine = QFontPrivate::get(myFont)->engineForScript(QChar::Script_Common);
+ Q_ASSERT(fontEngine);
+ if (fontEngine->type() == QFontEngine::Multi) {
+ fontEngine = static_cast<const QFontEngineMulti *>(fontEngine)->engine(0);
+ Q_ASSERT(fontEngine);
+ }
+ Q_ASSERT(fontEngine->type() == QFontEngine::Mac);
+ NSFont *f = (NSFont *)(CTFontRef)fontEngine->handle();
+
+ s = qt_mac_removeMnemonics(s);
+ [s.toNSString() drawInRect:CGRectMake(xpos, yPos, mi->rect.width() - xm - tabwidth + 1, mi->rect.height())
+ withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c }];
+
+ d->restoreNSGraphicsContext(cgCtx);
+#endif
}
p->restore();
}
@@ -5533,10 +5598,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QRect br = p->clipRegion().boundingRect();
int x = br.x(),
y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2);
- if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2))
+ if (br.width() <= (p->fontMetrics().horizontalAdvance(titlebar->text) + iw * 2))
x += iw;
else
- x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2;
+ x += br.width() / 2 - p->fontMetrics().horizontalAdvance(titlebar->text) / 2;
if (iw) {
int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
p->drawPixmap(x - iw, y,
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 078509d551..8eee80ce50 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -270,6 +270,7 @@ public:
void resolveCurrentNSView(QWindow *window) const;
void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const;
+ void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const;
#if QT_CONFIG(tabbar)
void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const;
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 4c982c14f4..cf344c8f88 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -54,7 +54,6 @@
#include <private/qapplication_p.h>
#include <qpa/qplatformnativeinterface.h>
-#include <qdesktopwidget.h>
#if QT_CONFIG(toolbutton)
#include <qtoolbutton.h>
#endif
@@ -186,7 +185,6 @@ HRGN XPThemeData::mask(QWidget *widget)
// QWindowsXPStylePrivate -------------------------------------------------------------------------
// Static initializations
-QPixmap *QWindowsXPStylePrivate::tabbody = 0;
HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = 0;
HTHEME QWindowsXPStylePrivate::m_themes[NThemes];
bool QWindowsXPStylePrivate::use_xp = false;
@@ -266,8 +264,6 @@ void QWindowsXPStylePrivate::cleanup(bool force)
use_xp = false;
cleanupHandleMap();
- delete tabbody;
- tabbody = 0;
}
/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch),
@@ -404,41 +400,16 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget)
return hwnd;
// Find top level with native window (there might be dialogs that do not have one).
- const auto topLevels = QApplication::topLevelWidgets();
- for (const QWidget *toplevel : topLevels) {
- if (toplevel->windowHandle() && toplevel->windowHandle()->handle())
- if (const HWND topLevelHwnd = QApplicationPrivate::getHWNDForWidget(toplevel))
- return topLevelHwnd;
+ const auto allWindows = QGuiApplication::allWindows();
+ for (const QWindow *window : allWindows) {
+ if (window->isTopLevel() && window->type() != Qt::Desktop && window->handle() != nullptr)
+ return reinterpret_cast<HWND>(window->winId());
}
return GetDesktopWindow();
}
/*! \internal
- Returns the pointer to a tab widgets body pixmap, scaled to the
- height of the screen. This way the theme engine doesn't need to
- scale the body for every time we ask for it. (Speed optimization)
-*/
-const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget)
-{
- if (!tabbody) {
- XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY);
- const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
-
- tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height());
- QPainter painter(tabbody);
- theme.rect = QRect(QPoint(0, 0), size);
- drawBackground(theme);
- // We fill with the last line of the themedata, that
- // way we don't get a tiled pixmap inside big tabs
- QPixmap temp(size.width(), 1);
- painter.drawPixmap(0, 0, temp, 0, size.height() - 1, -1, -1);
- painter.drawTiledPixmap(0, size.height(), size.width(), tabbody->height() - size.height(), temp);
- }
- return tabbody;
-}
-
-/*! \internal
Returns a native buffer (DIB section) of at least the size of
( \a x , \a y ). The buffer has a 32 bit depth, to not lose
the alpha values on proper alpha-pixmaps.
@@ -564,16 +535,6 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
}
/*! \internal
- Sets the parts region on a window.
-*/
-void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData)
-{
- HRGN hrgn = themeData.mask(widget);
- if (hrgn && widget)
- SetWindowRgn(winId(widget), hrgn, true);
-}
-
-/*! \internal
Returns \c true if the native doublebuffer contains pixels with
varying alpha value.
*/
@@ -760,10 +721,8 @@ static QRegion scaleRegion(const QRegion &region, qreal factor)
{
if (region.isEmpty() || qFuzzyCompare(factor, qreal(1)))
return region;
- if (region.rectCount() == 1)
- return QRegion(scaleRect(QRectF(region.boundingRect()), factor).toRect());
QRegion result;
- foreach (const QRect &rect, region.rects())
+ for (const QRect &rect : region)
result += QRectF(QPointF(rect.topLeft()) * factor, QSizeF(rect.size() * factor)).toRect();
return result;
}
@@ -3963,6 +3922,40 @@ QWindowsXPStyle::QWindowsXPStyle(QWindowsXPStylePrivate &dd) : QWindowsStyle(dd)
{
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const XPThemeData &t)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "XPThemeData(" << t.widget << ", theme=#" << t.theme << ", " << t.htheme
+ << ", partId=" << t.partId << ", stateId=" << t.stateId << ", rect=" << t.rect
+ << ", mirrorHorizontally=" << t.mirrorHorizontally << ", mirrorVertically="
+ << t.mirrorVertically << ", noBorder=" << t.noBorder << ", noContent=" << t.noContent
+ << ", rotate=" << t.rotate << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const ThemeMapKey &k)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "ThemeMapKey(theme=#" << k.theme
+ << ", partId=" << k.partId << ", stateId=" << k.stateId
+ << ", noBorder=" << k.noBorder << ", noContent=" << k.noContent << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const ThemeMapData &td)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "ThemeMapData(alphaType=" << td.alphaType
+ << ", dataValid=" << td.dataValid << ", partIsTransparent=" << td.partIsTransparent
+ << ", hasAlphaChannel=" << td.hasAlphaChannel << ", wasAlphaSwapped=" << td.wasAlphaSwapped
+ << ", hadInvalidAlpha=" << td.hadInvalidAlpha << ')';
+ return d;
+}
+#endif // QT_NO_DEBUG_STREAM
// Debugging code ---------------------------------------------------------------------[ START ]---
// The code for this point on is not compiled by default, but only used as assisting
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
index 721a734829..60f9d7e9b7 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
@@ -64,6 +64,8 @@
QT_BEGIN_NAMESPACE
+class QDebug;
+
// TMT_TEXTSHADOWCOLOR is wrongly defined in mingw
#if TMT_TEXTSHADOWCOLOR != 3818
#undef TMT_TEXTSHADOWCOLOR
@@ -181,6 +183,12 @@ struct ThemeMapData {
hasAlphaChannel(false), wasAlphaSwapped(false), hadInvalidAlpha(false) {}
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const XPThemeData &t);
+QDebug operator<<(QDebug d, const ThemeMapKey &k);
+QDebug operator<<(QDebug d, const ThemeMapData &td);
+#endif
+
class QWindowsXPStylePrivate : public QWindowsStylePrivate
{
Q_DECLARE_PUBLIC(QWindowsXPStyle)
@@ -224,7 +232,6 @@ public:
void init(bool force = false);
void cleanup(bool force = false);
void cleanupHandleMap();
- const QPixmap *tabBody(QWidget *widget);
HBITMAP buffer(int w = 0, int h = 0);
HDC bufferHDC()
@@ -236,7 +243,6 @@ public:
bool isTransparent(XPThemeData &themeData);
QRegion region(XPThemeData &themeData);
- void setTransparency(QWidget *widget, XPThemeData &themeData);
bool drawBackground(XPThemeData &themeData);
bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio);
bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio);
@@ -269,7 +275,6 @@ private:
static QBasicAtomicInt ref;
static bool use_xp;
- static QPixmap *tabbody;
QHash<ThemeMapKey, ThemeMapData> alphaCache;
HDC bufferDC;