summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/bearer/bearer.pro2
-rw-r--r--src/plugins/bearer/connman/main.cpp2
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.cpp6
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.h2
-rw-r--r--src/plugins/bearer/connman/qconnmanservice_linux.cpp12
-rw-r--r--src/plugins/bearer/connman/qconnmanservice_linux_p.h2
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm30
-rw-r--r--src/plugins/bearer/generic/main.cpp4
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp121
-rw-r--r--src/plugins/bearer/generic/qgenericengine.h4
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp6
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux_p.h2
-rw-r--r--src/plugins/bearer/networkmanager/main.cpp2
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp6
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h2
-rw-r--r--src/plugins/bearer/qbearerengine_impl.h4
-rw-r--r--src/plugins/bearer/qnetworksession_impl.cpp6
-rw-r--r--src/plugins/bearer/qnetworksession_impl.h4
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp3
-rw-r--r--src/plugins/imageformats/gif/main.cpp4
-rw-r--r--src/plugins/imageformats/gif/main.h4
-rw-r--r--src/plugins/imageformats/ico/main.cpp4
-rw-r--r--src/plugins/imageformats/ico/main.h4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp67
-rw-r--r--src/plugins/imageformats/jpeg/main.cpp4
-rw-r--r--src/plugins/imageformats/jpeg/main.h4
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.json2
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.pro2
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp235
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h4
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp3
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp259
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h46
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxy.cpp29
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibusproxy.h23
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.cpp116
-rw-r--r--src/plugins/platforminputcontexts/ibus/qibustypes.h33
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp59
-rw-r--r--src/plugins/platforms/android/androidjniinput.h2
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp23
-rw-r--r--src/plugins/platforms/android/androidjnimain.h1
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp8
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp10
-rw-r--r--src/plugins/platforms/android/qandroidplatformfontdatabase.cpp6
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h1
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp4
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/main.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h14
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm48
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm15
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm12
-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/qcocoaglcontext.mm21
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm29
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoainputcontext.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h53
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm56
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h42
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm19
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.h12
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm27
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h34
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaservices.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm3
-rw-r--r--[-rwxr-xr-x]src/plugins/platforms/cocoa/qcocoasystemtrayicon.h20
-rw-r--r--[-rwxr-xr-x]src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm112
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm3
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h6
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm110
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm6
-rw-r--r--src/plugins/platforms/cocoa/qt_mac_p.h11
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp13
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp3
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.cpp2
-rw-r--r--src/plugins/platforms/directfb/qdirectfbconvenience.cpp2
-rw-r--r--[-rwxr-xr-x]src/plugins/platforms/eglfs/cursor-atlas.pngbin2236 -> 2236 bytes
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp31
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp54
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h9
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro23
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp409
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h97
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp (renamed from src/plugins/platforms/cocoa/qcocoaautoreleasepool.h)24
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.json3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro23
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp93
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h (renamed from src/plugins/platforms/windows/qwindowsguieventdispatcher.h)30
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp (renamed from src/plugins/platforms/kms/qkmswindow.h)21
-rw-r--r--src/plugins/platforms/eglfs/eglfs_device_lib.pro9
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp11
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.cpp502
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.h141
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp39
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.h8
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp352
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h65
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp98
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h18
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp111
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.h31
-rw-r--r--src/plugins/platforms/haiku/qhaikuclipboard.cpp45
-rw-r--r--src/plugins/platforms/haiku/qhaikuclipboard.h4
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.cpp17
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm12
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm4
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h3
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm44
-rw-r--r--src/plugins/platforms/ios/qiosfileengineassetslibrary.mm40
-rw-r--r--src/plugins/platforms/ios/qiosglobal.h2
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm4
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm2
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm14
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm4
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h2
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm33
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm49
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm8
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h4
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm26
-rw-r--r--src/plugins/platforms/ios/quiview.mm33
-rw-r--r--src/plugins/platforms/kms/kms.json3
-rw-r--r--src/plugins/platforms/kms/kms.pro37
-rw-r--r--src/plugins/platforms/kms/main.cpp58
-rw-r--r--src/plugins/platforms/kms/qkmsbackingstore.cpp217
-rw-r--r--src/plugins/platforms/kms/qkmsbackingstore.h72
-rw-r--r--src/plugins/platforms/kms/qkmscontext.cpp136
-rw-r--r--src/plugins/platforms/kms/qkmscontext.h71
-rw-r--r--src/plugins/platforms/kms/qkmscursor.cpp116
-rw-r--r--src/plugins/platforms/kms/qkmscursor.h66
-rw-r--r--src/plugins/platforms/kms/qkmsdevice.cpp118
-rw-r--r--src/plugins/platforms/kms/qkmsdevice.h81
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.cpp204
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.h108
-rw-r--r--src/plugins/platforms/kms/qkmsnativeinterface.cpp135
-rw-r--r--src/plugins/platforms/kms/qkmsnativeinterface.h64
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp275
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h122
-rw-r--r--src/plugins/platforms/kms/qkmswindow.cpp66
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp11
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.cpp41
-rw-r--r--src/plugins/platforms/mirclient/mirclient.json3
-rw-r--r--src/plugins/platforms/mirclient/mirclient.pro47
-rw-r--r--src/plugins/platforms/mirclient/qmirclientbackingstore.cpp146
-rw-r--r--src/plugins/platforms/mirclient/qmirclientbackingstore.h70
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.cpp305
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.h88
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.cpp156
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.cpp520
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.h78
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.cpp264
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.h99
-rw-r--r--src/plugins/platforms/mirclient/qmirclientlogging.h60
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp134
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplatformservices.cpp72
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplatformservices.h54
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplugin.cpp56
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplugin.h53
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.cpp296
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.h84
-rw-r--r--src/plugins/platforms/mirclient/qmirclienttheme.cpp64
-rw-r--r--src/plugins/platforms/mirclient/qmirclienttheme.h54
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp454
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h80
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp21
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp1
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp2
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json51
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp41
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp46
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp330
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h77
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp161
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h10
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp45
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp65
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp201
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp77
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp53
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h4
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp15
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp111
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp43
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeimage.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsscaling.cpp71
-rw-r--r--src/plugins/platforms/windows/qwindowsscaling.h106
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp64
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h20
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp204
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h49
-rw-r--r--src/plugins/platforms/windows/windows.pri4
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp14
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp33
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.cpp153
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.h22
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp299
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.h12
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp15
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h6
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.cpp190
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.h31
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp172
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.h68
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp100
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp595
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h54
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.cpp189
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp245
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h13
-rw-r--r--src/plugins/platforms/winrt/winrt.pro22
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp12
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro2
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp63
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp341
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h14
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp160
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp58
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp120
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h20
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp119
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp195
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h42
-rw-r--r--src/plugins/platforms/xcb/qxcbsessionmanager.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp328
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h22
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxlibconvenience.cpp63
-rw-r--r--src/plugins/platforms/xcb/qxlibconvenience.h49
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro9
-rw-r--r--src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h5
-rw-r--r--src/plugins/plugins.pro13
-rw-r--r--src/plugins/printsupport/cocoa/main.cpp4
-rw-r--r--src/plugins/printsupport/cups/main.cpp4
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine.cpp8
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h4
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp5
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport_p.h3
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.cpp7
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.h5
-rw-r--r--src/plugins/printsupport/printsupport.pro5
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp4
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.h3
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/button/core_button_inactive.pngbin2428 -> 2428 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/button/core_button_pressed.pngbin3221 -> 3221 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.pngbin2776 -> 2776 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.pngbin1315 -> 1315 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.pngbin394 -> 394 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/listitem/core_listitem_active.pngbin164 -> 164 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.pngbin135 -> 135 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.pngbin1802 -> 1802 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.pngbin4245 -> 4245 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.pngbin5460 -> 5460 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.pngbin1242 -> 1242 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.pngbin6577 -> 6577 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/button/core_button_inactive.pngbin2262 -> 2262 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/button/core_button_pressed.pngbin2853 -> 2853 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.pngbin2478 -> 2478 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.pngbin1315 -> 1315 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.pngbin394 -> 394 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/listitem/core_listitem_active.pngbin164 -> 164 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.pngbin136 -> 136 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.pngbin1724 -> 1724 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.pngbin3968 -> 3968 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.pngbin4777 -> 4777 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.pngbin1245 -> 1245 bytes
-rw-r--r--[-rwxr-xr-x]src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.pngbin6593 -> 6593 bytes
-rw-r--r--src/plugins/styles/bb10style/qpixmapstyle.cpp27
330 files changed, 10536 insertions, 5627 deletions
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro
index 2239d52737..a1434fc2ea 100644
--- a/src/plugins/bearer/bearer.pro
+++ b/src/plugins/bearer/bearer.pro
@@ -8,7 +8,7 @@ TEMPLATE = subdirs
#win32:SUBDIRS += nla
win32:SUBDIRS += generic
blackberry:SUBDIRS += blackberry
-win32:!wince: SUBDIRS += nativewifi
+win32:!wince:!winrt: SUBDIRS += nativewifi
mac:contains(QT_CONFIG, corewlan):SUBDIRS += corewlan
mac:SUBDIRS += generic
android:!android-no-sdk:SUBDIRS += android
diff --git a/src/plugins/bearer/connman/main.cpp b/src/plugins/bearer/connman/main.cpp
index a84121e89b..f1e9d763a7 100644
--- a/src/plugins/bearer/connman/main.cpp
+++ b/src/plugins/bearer/connman/main.cpp
@@ -36,7 +36,6 @@
#include <QtCore/qdebug.h>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -78,4 +77,3 @@ QT_END_NAMESPACE
#include "main.moc"
#endif
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp
index 7911857ff5..b7cc5f949c 100644
--- a/src/plugins/bearer/connman/qconnmanengine.cpp
+++ b/src/plugins/bearer/connman/qconnmanengine.cpp
@@ -46,7 +46,6 @@
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -122,8 +121,10 @@ QList<QNetworkConfigurationPrivate *> QConnmanEngine::getConfigurations()
QMutexLocker locker(&mutex);
QList<QNetworkConfigurationPrivate *> fetchedConfigurations;
QNetworkConfigurationPrivate* cpPriv = 0;
+ const int numFoundConfigurations = foundConfigurations.count();
+ fetchedConfigurations.reserve(numFoundConfigurations);
- for (int i = 0; i < foundConfigurations.count(); ++i) {
+ for (int i = 0; i < numFoundConfigurations; ++i) {
QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate;
cpPriv = foundConfigurations.at(i);
@@ -556,4 +557,3 @@ void QConnmanEngine::reEvaluateCellular()
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/connman/qconnmanengine.h b/src/plugins/bearer/connman/qconnmanengine.h
index 2c1f5490e3..8c79b22bf9 100644
--- a/src/plugins/bearer/connman/qconnmanengine.h
+++ b/src/plugins/bearer/connman/qconnmanengine.h
@@ -53,7 +53,6 @@
#include <QMap>
#include <QVariant>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -135,7 +134,6 @@ protected:
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
#endif
diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp
index 155e6970fa..10d8285a4a 100644
--- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp
+++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp
@@ -45,7 +45,6 @@
#include "qconnmanservice_linux_p.h"
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -175,11 +174,10 @@ void QConnmanManagerInterface::connectNotify(const QMetaMethod &signal)
void QConnmanManagerInterface::onServicesChanged(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed)
{
- ConnmanMap connmanobj;
servicesList.clear(); //connman list changes order
- Q_FOREACH (connmanobj, changed) {
+ Q_FOREACH (const ConnmanMap &connmanobj, changed) {
const QString svcPath(connmanobj.objectPath.path());
- servicesList << svcPath;
+ servicesList << svcPath;
}
Q_EMIT servicesChanged(changed, removed);
@@ -221,7 +219,7 @@ QStringList QConnmanManagerInterface::getTechnologies()
QDBusPendingReply<ConnmanMapList> reply = call(QLatin1String("GetTechnologies"));
reply.waitForFinished();
if (!reply.isError()) {
- Q_FOREACH (ConnmanMap map, reply.value()) {
+ Q_FOREACH (const ConnmanMap &map, reply.value()) {
if (!technologiesMap.contains(map.objectPath.path())) {
technologyAdded(map.objectPath, map.propertyMap);
}
@@ -237,7 +235,7 @@ QStringList QConnmanManagerInterface::getServices()
QDBusPendingReply<ConnmanMapList> reply = call(QLatin1String("GetServices"));
reply.waitForFinished();
if (!reply.isError()) {
- Q_FOREACH (ConnmanMap map, reply.value()) {
+ Q_FOREACH (const ConnmanMap &map, reply.value()) {
servicesList << map.objectPath.path();
}
}
@@ -504,5 +502,3 @@ void QConnmanTechnologyInterface::scanReply(QDBusPendingCallWatcher *call)
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
-
diff --git a/src/plugins/bearer/connman/qconnmanservice_linux_p.h b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
index 49ca9f391c..1a10a2260a 100644
--- a/src/plugins/bearer/connman/qconnmanservice_linux_p.h
+++ b/src/plugins/bearer/connman/qconnmanservice_linux_p.h
@@ -58,7 +58,6 @@
#include <QtDBus/QDBusContext>
#include <QMap>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
#ifndef __CONNMAN_DBUS_H
@@ -219,6 +218,5 @@ private:
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
#endif //QCONNMANSERVICE_H
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index eb756db39e..6d16b59d35 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -77,12 +77,11 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
- (id) init
{
[locker lock];
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
notificationCenter = [NSNotificationCenter defaultCenter];
currentInterface = [CWInterface interfaceWithName:nil];
[notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil];
[locker unlock];
- [autoreleasepool release];
return self;
}
@@ -154,7 +153,7 @@ void QScanThread::quit()
void QScanThread::run()
{
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
QStringList found;
mutex.lock();
CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)];
@@ -236,7 +235,6 @@ void QScanThread::run()
}
}
emit networksChanged();
- [autoreleasepool release];
}
QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
@@ -276,7 +274,7 @@ void QScanThread::getUserConfigurations()
{
QMutexLocker locker(&mutex);
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
userProfiles.clear();
NSSet *wifiInterfaces = [CWInterface interfaceNames];
@@ -357,7 +355,6 @@ void QScanThread::getUserConfigurations()
}
}
}
- [autoreleasepool release];
}
QString QScanThread::getSsidFromNetworkName(const QString &name)
@@ -436,7 +433,7 @@ QCoreWlanEngine::~QCoreWlanEngine()
void QCoreWlanEngine::initialize()
{
QMutexLocker locker(&mutex);
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
if ([[CWInterface interfaceNames] count] > 0 && !listener) {
listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init];
@@ -448,7 +445,6 @@ void QCoreWlanEngine::initialize()
storeSession = NULL;
startNetworkChangeLoop();
- [autoreleasepool release];
}
@@ -469,7 +465,7 @@ bool QCoreWlanEngine::hasIdentifier(const QString &id)
void QCoreWlanEngine::connectToId(const QString &id)
{
QMutexLocker locker(&mutex);
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
QString interfaceString = getInterfaceFromId(id);
CWInterface *wifiInterface =
@@ -541,7 +537,6 @@ void QCoreWlanEngine::connectToId(const QString &id)
locker.unlock();
emit connectionError(id, InterfaceLookupError);
- [autoreleasepool release];
}
void QCoreWlanEngine::disconnectFromId(const QString &id)
@@ -554,7 +549,7 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
emit connectionError(id, DisconnectionError);
return;
}
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(interfaceString)];
@@ -563,14 +558,13 @@ void QCoreWlanEngine::disconnectFromId(const QString &id)
[wifiInterface disassociate];
QTimer::singleShot(1000, this,SLOT(checkDisconnect()));
- [autoreleasepool release];
}
void QCoreWlanEngine::checkDisconnect()
{
QMutexLocker locker(&mutex);
if (!disconnectedInterfaceString.isEmpty()) {
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
CWInterface *wifiInterface =
[CWInterface interfaceWithName: QCFString::toNSString(disconnectedInterfaceString)];
@@ -582,7 +576,6 @@ void QCoreWlanEngine::checkDisconnect()
emit connectionError(id, DisconnectionError);
locker.relock();
}
- [autoreleasepool release];
disconnectedInterfaceString.clear();
}
}
@@ -597,7 +590,7 @@ void QCoreWlanEngine::doRequestUpdate()
{
QMutexLocker locker(&mutex);
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
NSSet *wifiInterfaces = [CWInterface interfaceNames];
for (NSString *ifName in wifiInterfaces) {
@@ -607,7 +600,6 @@ void QCoreWlanEngine::doRequestUpdate()
locker.unlock();
if ([wifiInterfaces count] == 0)
networksChanged();
- [autoreleasepool release];
}
bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
@@ -615,12 +607,11 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
QMutexLocker locker(&mutex);
bool haswifi = false;
if(hasWifi) {
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)];
if (defaultInterface.powerOn) {
haswifi = true;
}
- [autoreleasepool release];
}
return haswifi;
}
@@ -814,7 +805,7 @@ quint64 QCoreWlanEngine::bytesReceived(const QString &id)
quint64 QCoreWlanEngine::startTime(const QString &identifier)
{
QMutexLocker locker(&mutex);
- NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QMacAutoReleasePool pool;
quint64 timestamp = 0;
NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist";
@@ -861,7 +852,6 @@ quint64 QCoreWlanEngine::startTime(const QString &identifier)
}
}
}
- [autoreleasepool release];
return timestamp;
}
diff --git a/src/plugins/bearer/generic/main.cpp b/src/plugins/bearer/generic/main.cpp
index 112c7420e1..4f79807128 100644
--- a/src/plugins/bearer/generic/main.cpp
+++ b/src/plugins/bearer/generic/main.cpp
@@ -37,8 +37,6 @@
#include <QtCore/qdebug.h>
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
class QGenericEnginePlugin : public QBearerEnginePlugin
@@ -72,5 +70,3 @@ QBearerEngine *QGenericEnginePlugin::create(const QString &key) const
QT_END_NAMESPACE
#include "main.moc"
-
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
index e1b3d79b38..1e424dc223 100644
--- a/src/plugins/bearer/generic/qgenericengine.cpp
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -44,14 +44,34 @@
#include <QtCore/qdebug.h>
#include <QtCore/private/qcoreapplication_p.h>
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
#include "../platformdefs_win.h"
#endif
#ifdef Q_OS_WINCE
typedef ULONG NDIS_OID, *PNDIS_OID;
-#include <nuiouser.h>
-#endif
+# ifndef QT_NO_WINCE_NUIOUSER
+# include <nuiouser.h>
+# endif
+#endif // Q_OS_WINCE
+
+#ifdef Q_OS_WINRT
+#include <qfunctions_winrt.h>
+
+#include <wrl.h>
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <windows.networking.connectivity.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Networking;
+using namespace ABI::Windows::Networking::Connectivity;
+// needed as interface is used as parameter name in qGetInterfaceType
+#undef interface
+#endif // Q_OS_WINRT
#ifdef Q_OS_LINUX
#include <sys/socket.h>
@@ -61,19 +81,17 @@ typedef ULONG NDIS_OID, *PNDIS_OID;
#include <unistd.h>
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
#ifndef QT_NO_NETWORKINTERFACE
static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interface)
{
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
DWORD bytesWritten;
NDIS_MEDIUM medium;
NDIS_PHYSICAL_MEDIUM physicalMedium;
-#ifdef Q_OS_WINCE
+#if defined(Q_OS_WINCE) && !defined(QT_NO_WINCE_NUIOUSER)
NDISUIO_QUERY_OID nicGetOid;
HANDLE handle = CreateFile((PTCHAR)NDISUIO_DEVICE_NAME, 0,
FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
@@ -87,7 +105,7 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf
bytesWritten = 0;
-#ifdef Q_OS_WINCE
+#if defined(Q_OS_WINCE) && !defined(QT_NO_WINCE_NUIOUSER)
ZeroMemory(&nicGetOid, sizeof(NDISUIO_QUERY_OID));
nicGetOid.Oid = OID_GEN_MEDIA_SUPPORTED;
nicGetOid.ptcDeviceName = (PTCHAR)interface.utf16();
@@ -105,7 +123,7 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf
bytesWritten = 0;
-#ifdef Q_OS_WINCE
+#if defined(Q_OS_WINCE) && !defined(QT_NO_WINCE_NUIOUSER)
medium = NDIS_MEDIUM( *(LPDWORD)nicGetOid.Data );
ZeroMemory(&nicGetOid, sizeof(NDISUIO_QUERY_OID));
@@ -163,6 +181,87 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf
if (result >= 0 && request.ifr_hwaddr.sa_family == ARPHRD_ETHER)
return QNetworkConfiguration::BearerEthernet;
+#elif defined(Q_OS_WINRT)
+ ComPtr<INetworkInformationStatics> networkInfoStatics;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &networkInfoStatics);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<ConnectionProfile *>> connectionProfiles;
+ hr = networkInfoStatics->GetConnectionProfiles(&connectionProfiles);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (!connectionProfiles)
+ return QNetworkConfiguration::BearerUnknown;
+
+ unsigned int size;
+ hr = connectionProfiles->get_Size(&size);
+ Q_ASSERT_SUCCEEDED(hr);
+ for (unsigned int i = 0; i < size; ++i) {
+ ComPtr<IConnectionProfile> profile;
+ hr = connectionProfiles->GetAt(i, &profile);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<INetworkAdapter> adapter;
+ hr = profile->get_NetworkAdapter(&adapter);
+ // Indicates that no internet connection is available/the device is in airplane mode
+ if (hr == E_INVALIDARG)
+ return QNetworkConfiguration::BearerUnknown;
+ Q_ASSERT_SUCCEEDED(hr);
+ GUID id;
+ hr = adapter->get_NetworkAdapterId(&id);
+ Q_ASSERT_SUCCEEDED(hr);
+ OLECHAR adapterName[39]={0};
+ int length = StringFromGUID2(id, adapterName, 39);
+ // "length - 1" as we have to remove the null terminator from it in order to compare
+ if (!length
+ || QString::fromRawData(reinterpret_cast<const QChar *>(adapterName), length - 1) != interface)
+ continue;
+
+ ComPtr<IConnectionProfile2> profile2;
+ hr = profile.As(&profile2);
+ Q_ASSERT_SUCCEEDED(hr);
+ boolean isWLan;
+ hr = profile2->get_IsWlanConnectionProfile(&isWLan);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (isWLan)
+ return QNetworkConfiguration::BearerWLAN;
+
+ boolean isWWan;
+ hr = profile2->get_IsWwanConnectionProfile(&isWWan);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (isWWan) {
+ ComPtr<IWwanConnectionProfileDetails> details;
+ hr = profile2->get_WwanConnectionProfileDetails(&details);
+ Q_ASSERT_SUCCEEDED(hr);
+ WwanDataClass dataClass;
+ hr = details->GetCurrentDataClass(&dataClass);
+ Q_ASSERT_SUCCEEDED(hr);
+ switch (dataClass) {
+ case WwanDataClass_Edge:
+ case WwanDataClass_Gprs:
+ return QNetworkConfiguration::Bearer2G;
+ case WwanDataClass_Umts:
+ return QNetworkConfiguration::BearerWCDMA;
+ case WwanDataClass_LteAdvanced:
+ return QNetworkConfiguration::BearerLTE;
+ case WwanDataClass_Hsdpa:
+ case WwanDataClass_Hsupa:
+ return QNetworkConfiguration::BearerHSPA;
+ case WwanDataClass_Cdma1xRtt:
+ case WwanDataClass_Cdma3xRtt:
+ case WwanDataClass_CdmaUmb:
+ return QNetworkConfiguration::BearerCDMA2000;
+ case WwanDataClass_Cdma1xEvdv:
+ case WwanDataClass_Cdma1xEvdo:
+ case WwanDataClass_Cdma1xEvdoRevA:
+ case WwanDataClass_Cdma1xEvdoRevB:
+ return QNetworkConfiguration::BearerEVDO;
+ case WwanDataClass_Custom:
+ case WwanDataClass_None:
+ default:
+ return QNetworkConfiguration::BearerUnknown;
+ }
+ }
+ return QNetworkConfiguration::BearerEthernet;
+ }
#else
Q_UNUSED(interface);
#endif
@@ -243,9 +342,11 @@ void QGenericEngine::doRequestUpdate()
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
+#ifndef Q_OS_WINRT
// ignore WLAN interface handled in separate engine
if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
continue;
+#endif
uint identifier;
if (interface.index())
@@ -385,5 +486,3 @@ bool QGenericEngine::requiresPolling() const
}
QT_END_NAMESPACE
-
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h
index 9acd6c4c2e..4b99c90051 100644
--- a/src/plugins/bearer/generic/qgenericengine.h
+++ b/src/plugins/bearer/generic/qgenericengine.h
@@ -39,8 +39,6 @@
#include <QMap>
#include <QTimer>
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
class QNetworkConfigurationPrivate;
@@ -82,7 +80,5 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_BEARERMANAGEMENT
-
#endif
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
index 6e427544fa..e9e91f9855 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
@@ -45,7 +45,6 @@
#include "qofonoservice_linux_p.h"
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QDBusArgument &operator<<(QDBusArgument &argument, const ObjectPathProperties &item)
@@ -98,7 +97,7 @@ QStringList QOfonoManagerInterface::getModems()
QDBusPendingReply<PathPropertiesList> reply = callWithArgumentList(QDBus::Block, QLatin1String("GetModems"), argumentList);
reply.waitForFinished();
if (!reply.isError()) {
- foreach (ObjectPathProperties modem, reply.value()) {
+ foreach (const ObjectPathProperties &modem, reply.value()) {
modemList << modem.path.path();
}
}
@@ -261,7 +260,7 @@ QStringList QOfonoDataConnectionManagerInterface::contexts()
QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts"));
reply.waitForFinished();
if (!reply.isError()) {
- foreach (ObjectPathProperties context, reply.value()) {
+ foreach (const ObjectPathProperties &context, reply.value()) {
contextList << context.path.path();
}
}
@@ -382,4 +381,3 @@ QString QOfonoConnectionContextInterface::name()
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
index b051b8feaa..57ea089ec8 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
@@ -57,7 +57,6 @@
#include <QtDBus/QDBusContext>
#include <QMap>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
#define OFONO_SERVICE "org.ofono"
@@ -193,6 +192,5 @@ private slots:
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
#endif //QOFONOSERVICE_H
diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp
index 8a872cf08f..0d22846c44 100644
--- a/src/plugins/bearer/networkmanager/main.cpp
+++ b/src/plugins/bearer/networkmanager/main.cpp
@@ -37,7 +37,6 @@
#include <QtCore/qdebug.h>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -77,4 +76,3 @@ QT_END_NAMESPACE
#include "main.moc"
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index e662d5f2d3..3b8a85a26b 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -49,7 +49,6 @@
#include <QDBusReply>
#include "../linux_common/qofonoservice_linux_p.h"
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -846,7 +845,7 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
while (i.hasNext()) {
i.next();
- const QString path = i.key() +"/"+contextPart;
+ const QString path = i.key() + QLatin1Char('/') +contextPart;
if (isActiveContext(path)) {
cpPriv->state |= QNetworkConfiguration::Active;
break;
@@ -1025,7 +1024,7 @@ QNetworkConfiguration::BearerType QNetworkManagerEngine::currentBearerType(const
QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
while (i.hasNext()) {
i.next();
- QString contextPath = i.key() +"/"+contextPart;
+ QString contextPath = i.key() + QLatin1Char('/') +contextPart;
if (i.value()->contexts().contains(contextPath)) {
@@ -1129,4 +1128,3 @@ void QNetworkManagerEngine::ofonoUnRegistered(const QString &)
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
index 3d90fcd0e5..1f578890dc 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -54,7 +54,6 @@
#include <QMap>
#include <QVariant>
-#ifndef QT_NO_BEARERMANAGEMENT
#ifndef QT_NO_DBUS
QT_BEGIN_NAMESPACE
@@ -150,7 +149,6 @@ private:
QT_END_NAMESPACE
#endif // QT_NO_DBUS
-#endif // QT_NO_BEARERMANAGEMENT
#endif
diff --git a/src/plugins/bearer/qbearerengine_impl.h b/src/plugins/bearer/qbearerengine_impl.h
index 6db4d8c6b2..a343474f2c 100644
--- a/src/plugins/bearer/qbearerengine_impl.h
+++ b/src/plugins/bearer/qbearerengine_impl.h
@@ -36,8 +36,6 @@
#include <QtNetwork/private/qbearerengine_p.h>
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
class QBearerEngineImpl : public QBearerEngine
@@ -74,6 +72,4 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QBearerEngineImpl::ConnectionError)
-#endif // QT_NO_BEARERMANAGEMENT
-
#endif // QBEARERENGINE_IMPL_H
diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp
index f3f3729504..8139040f84 100644
--- a/src/plugins/bearer/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/qnetworksession_impl.cpp
@@ -42,8 +42,6 @@
#include <QtCore/qmutex.h>
#include <QtCore/qstringlist.h>
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
static QBearerEngineImpl *getEngineFromId(const QString &id)
@@ -281,7 +279,7 @@ quint64 QNetworkSessionPrivateImpl::bytesReceived() const
quint64 QNetworkSessionPrivateImpl::activeTime() const
{
if (state == QNetworkSession::Connected && startTime != Q_UINT64_C(0))
- return QDateTime::currentDateTime().toTime_t() - startTime;
+ return QDateTime::currentDateTimeUtc().toTime_t() - startTime;
return Q_UINT64_C(0);
}
@@ -423,5 +421,3 @@ void QNetworkSessionPrivateImpl::decrementTimeout()
}
QT_END_NAMESPACE
-
-#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h
index 87a2b29bd4..a26b05ab3b 100644
--- a/src/plugins/bearer/qnetworksession_impl.h
+++ b/src/plugins/bearer/qnetworksession_impl.h
@@ -50,8 +50,6 @@
#include <QtNetwork/private/qnetworkconfigmanager_p.h>
#include <QtNetwork/private/qnetworksession_p.h>
-#ifndef QT_NO_BEARERMANAGEMENT
-
QT_BEGIN_NAMESPACE
class QBearerEngineImpl;
@@ -123,6 +121,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_BEARERMANAGEMENT
-
#endif // QNETWORKSESSION_IMPL_H
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
index 5211ed8381..2b42889cb1 100644
--- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp
+++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
@@ -202,7 +202,7 @@ void QTuioHandler::process2DCurAlive(const QOscMessage &message)
for (int i = 1; i < arguments.count(); ++i) {
if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) {
- qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ")";
+ qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
return;
}
@@ -317,6 +317,7 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message)
return;
QList<QWindowSystemInterface::TouchPoint> tpl;
+ tpl.reserve(m_activeCursors.size() + m_deadCursors.size());
foreach (const QTuioCursor &tc, m_activeCursors) {
QWindowSystemInterface::TouchPoint tp = cursorToTouchPoint(tc, win);
diff --git a/src/plugins/imageformats/gif/main.cpp b/src/plugins/imageformats/gif/main.cpp
index 8181900adb..62c4f4b597 100644
--- a/src/plugins/imageformats/gif/main.cpp
+++ b/src/plugins/imageformats/gif/main.cpp
@@ -34,8 +34,6 @@
#include <qimageiohandler.h>
#include <qstringlist.h>
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
#include "main.h"
#ifdef QT_NO_IMAGEFORMAT_GIF
@@ -69,6 +67,4 @@ QImageIOHandler *QGifPlugin::create(QIODevice *device, const QByteArray &format)
return handler;
}
-#endif // QT_NO_IMAGEFORMATPLUGIN
-
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/gif/main.h b/src/plugins/imageformats/gif/main.h
index 1b02d5eaf6..56e0655b1f 100644
--- a/src/plugins/imageformats/gif/main.h
+++ b/src/plugins/imageformats/gif/main.h
@@ -34,8 +34,6 @@
#include <qimageiohandler.h>
#include <qstringlist.h>
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
#ifdef QT_NO_IMAGEFORMAT_GIF
#undef QT_NO_IMAGEFORMAT_GIF
#endif
@@ -56,5 +54,3 @@ public:
};
QT_END_NAMESPACE
-
-#endif // QT_NO_IMAGEFORMATPLUGIN
diff --git a/src/plugins/imageformats/ico/main.cpp b/src/plugins/imageformats/ico/main.cpp
index 80182fb665..03448d4ae1 100644
--- a/src/plugins/imageformats/ico/main.cpp
+++ b/src/plugins/imageformats/ico/main.cpp
@@ -33,8 +33,6 @@
#include "main.h"
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
QT_BEGIN_NAMESPACE
QImageIOPlugin::Capabilities QICOPlugin::capabilities(QIODevice *device, const QByteArray &format) const
@@ -63,5 +61,3 @@ QImageIOHandler *QICOPlugin::create(QIODevice *device, const QByteArray &format)
}
QT_END_NAMESPACE
-
-#endif /* QT_NO_IMAGEFORMATPLUGIN */
diff --git a/src/plugins/imageformats/ico/main.h b/src/plugins/imageformats/ico/main.h
index a254a626d1..d17dbe824d 100644
--- a/src/plugins/imageformats/ico/main.h
+++ b/src/plugins/imageformats/ico/main.h
@@ -34,8 +34,6 @@
#include <qimageiohandler.h>
#include <qdebug.h>
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
#ifdef QT_NO_IMAGEFORMAT_ICO
#undef QT_NO_IMAGEFORMAT_ICO
#endif
@@ -53,5 +51,3 @@ public:
};
QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 4cb5e22bf7..19525397fa 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -96,13 +96,14 @@ public:
QImage iconAt(int index);
static bool canRead(QIODevice *iodev);
- static QList<QImage> read(QIODevice * device);
+ static QVector<QImage> read(QIODevice *device);
- static bool write(QIODevice * device, const QList<QImage> & images);
+ static bool write(QIODevice *device, const QVector<QImage> &images);
+
+ bool readIconEntry(int index, ICONDIRENTRY * iconEntry);
private:
bool readHeader();
- bool readIconEntry(int index, ICONDIRENTRY * iconEntry);
bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header);
void findColorInfo(QImage & image);
@@ -341,7 +342,7 @@ bool ICOReader::readHeader()
bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry)
{
- if (iod) {
+ if (readHeader()) {
if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) {
return readIconDirEntry(iod, iconEntry);
}
@@ -558,10 +559,10 @@ QImage ICOReader::iconAt(int index)
if (icoAttrib.ncolors > 256) //color table can't be more than 256
return img;
icoAttrib.w = iconEntry.bWidth;
- if (icoAttrib.w == 0)
+ if (icoAttrib.w == 0) // means 256 pixels
icoAttrib.w = header.biWidth;
icoAttrib.h = iconEntry.bHeight;
- if (icoAttrib.h == 0)
+ if (icoAttrib.h == 0) // means 256 pixels
icoAttrib.h = header.biHeight/2;
QImage::Format format = QImage::Format_ARGB32;
@@ -612,12 +613,14 @@ QImage ICOReader::iconAt(int index)
\sa write()
*/
-QList<QImage> ICOReader::read(QIODevice * device)
+QVector<QImage> ICOReader::read(QIODevice *device)
{
- QList<QImage> images;
+ QVector<QImage> images;
ICOReader reader(device);
- for (int i = 0; i < reader.count(); i++)
+ const int N = reader.count();
+ images.reserve(N);
+ for (int i = 0; i < N; i++)
images += reader.iconAt(i);
return images;
@@ -636,7 +639,7 @@ QList<QImage> ICOReader::read(QIODevice * device)
\sa read()
*/
-bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
+bool ICOReader::write(QIODevice *device, const QVector<QImage> &images)
{
bool retValue = false;
@@ -656,10 +659,11 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
for (int i=0; i<id.idCount; i++) {
QImage image = images[i];
- // Scale down the image if it is larger than 128 pixels in either width or height
- if (image.width() > 128 || image.height() > 128)
+ // Scale down the image if it is larger than 256 pixels in either width or height
+ // because this is a maximum size of image in the ICO file.
+ if (image.width() > 256 || image.height() > 256)
{
- image = image.scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ image = image.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QImage maskImage(image.width(), image.height(), QImage::Format_Mono);
image = image.convertToFormat(QImage::Format_ARGB32);
@@ -776,25 +780,37 @@ QtIcoHandler::~QtIcoHandler()
QVariant QtIcoHandler::option(ImageOption option) const
{
- if (option == Size) {
- QIODevice *device = QImageIOHandler::device();
- qint64 oldPos = device->pos();
+ if (option == Size || option == ImageFormat) {
ICONDIRENTRY iconEntry;
- if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) {
- if (readIconDirEntry(device, &iconEntry)) {
- device->seek(oldPos);
- return QSize(iconEntry.bWidth, iconEntry.bHeight);
+ if (m_pICOReader->readIconEntry(m_currentIconIndex, &iconEntry)) {
+ switch (option) {
+ case Size:
+ return QSize(iconEntry.bWidth ? iconEntry.bWidth : 256,
+ iconEntry.bHeight ? iconEntry.bHeight : 256);
+
+ case ImageFormat:
+ switch (iconEntry.wBitCount) {
+ case 2:
+ return QImage::Format_Mono;
+ case 24:
+ return QImage::Format_RGB32;
+ case 32:
+ return QImage::Format_ARGB32;
+ default:
+ return QImage::Format_Indexed8;
+ }
+ break;
+ default:
+ break;
}
}
- if (!device->isSequential())
- device->seek(oldPos);
}
return QVariant();
}
bool QtIcoHandler::supportsOption(ImageOption option) const
{
- return option == Size;
+ return (option == Size || option == ImageFormat);
}
/*!
@@ -849,7 +865,7 @@ bool QtIcoHandler::read(QImage *image)
bool QtIcoHandler::write(const QImage &image)
{
QIODevice *device = QImageIOHandler::device();
- QList<QImage> imgs;
+ QVector<QImage> imgs;
imgs.append(image);
return ICOReader::write(device, imgs);
}
@@ -879,9 +895,10 @@ bool QtIcoHandler::jumpToImage(int imageNumber)
{
if (imageNumber < imageCount()) {
m_currentIconIndex = imageNumber;
+ return true;
}
- return imageNumber < imageCount();
+ return false;
}
/*! \reimp
diff --git a/src/plugins/imageformats/jpeg/main.cpp b/src/plugins/imageformats/jpeg/main.cpp
index d009707fa0..c8a575cb43 100644
--- a/src/plugins/imageformats/jpeg/main.cpp
+++ b/src/plugins/imageformats/jpeg/main.cpp
@@ -33,8 +33,6 @@
#include "main.h"
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
#ifdef QT_NO_IMAGEFORMAT_JPEG
#undef QT_NO_IMAGEFORMAT_JPEG
#endif
@@ -68,5 +66,3 @@ QImageIOHandler *QJpegPlugin::create(QIODevice *device, const QByteArray &format
}
QT_END_NAMESPACE
-
-#endif // QT_NO_IMAGEFORMATPLUGIN
diff --git a/src/plugins/imageformats/jpeg/main.h b/src/plugins/imageformats/jpeg/main.h
index 2d79c84666..77ee33faca 100644
--- a/src/plugins/imageformats/jpeg/main.h
+++ b/src/plugins/imageformats/jpeg/main.h
@@ -34,8 +34,6 @@
#include <qimageiohandler.h>
#include <qstringlist.h>
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-
#ifdef QT_NO_IMAGEFORMAT_JPEG
#undef QT_NO_IMAGEFORMAT_JPEG
#endif
@@ -52,5 +50,3 @@ public:
};
QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforminputcontexts/compose/compose.json b/src/plugins/platforminputcontexts/compose/compose.json
index 2daf89ed30..fb95f1bfb0 100644
--- a/src/plugins/platforminputcontexts/compose/compose.json
+++ b/src/plugins/platforminputcontexts/compose/compose.json
@@ -1,3 +1,3 @@
{
- "Keys": [ "compose" ]
+ "Keys": [ "compose", "xim" ]
}
diff --git a/src/plugins/platforminputcontexts/compose/compose.pro b/src/plugins/platforminputcontexts/compose/compose.pro
index a9da36c473..a4b5280e64 100644
--- a/src/plugins/platforminputcontexts/compose/compose.pro
+++ b/src/plugins/platforminputcontexts/compose/compose.pro
@@ -5,7 +5,7 @@ PLUGIN_EXTENDS = -
PLUGIN_CLASS_NAME = QComposePlatformInputContextPlugin
load(qt_plugin)
-QT += gui-private
+QT += core-private gui-private
DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index 65020eb848..ad9877eb25 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -36,8 +36,12 @@
#include <QtCore/QByteArray>
#include <QtCore/QTextCodec>
#include <QtCore/QDebug>
+#include <QtCore/QDir>
#include <QtCore/QStringList>
#include <QtCore/QString>
+#include <QtCore/QSaveFile>
+#include <QtCore/QStandardPaths>
+#include <private/qcore_unix_p.h>
#include <algorithm>
@@ -48,12 +52,191 @@
#include <strings.h> // strncasecmp
#include <clocale> // LC_CTYPE
+static const quint32 SupportedCacheVersion = 1;
+
+/*
+ In short on how and why the "Compose" file is cached:
+
+ The "Compose" file is large, for en_US it's likely located at:
+ /usr/share/X11/locale/en_US.UTF-8/Compose
+ and it has about 6000 string lines.
+ Q(Gui)Applications parse this file each time they're created. On modern CPUs
+ it incurs a 4-10 ms startup penalty of each Qt gui app, on older CPUs -
+ tens of ms or more.
+ Since the "Compose" file (almost) never changes using a pre-parsed
+ cache file instead of the "Compose" file is a good idea to improve Qt5
+ application startup time by about 5+ ms (or tens of ms on older CPUs).
+
+ The cache file contains the contents of the QComposeCacheFileHeader struct at the
+ beginning followed by the pre-parsed contents of the "Compose" file.
+
+ struct QComposeCacheFileHeader stores
+ (a) The cache version - in the unlikely event that some day one might need
+ to break compatibility.
+ (b) The (cache) file size.
+ (c) The lastModified field tracks if anything changed since the last time
+ the cache file was saved.
+ If anything did change then we read the compose file and save (cache) it
+ in binary/pre-parsed format, which should happen extremely rarely if at all.
+*/
+
+struct QComposeCacheFileHeader
+{
+ quint32 cacheVersion;
+ // The compiler will add 4 padding bytes anyway.
+ // Reserve them explicitly to possibly use in the future.
+ quint32 reserved;
+ quint64 fileSize;
+ qint64 lastModified;
+};
+
+// localHostName() copied from qtbase/src/corelib/io/qlockfile_unix.cpp
+static QByteArray localHostName()
+{
+ QByteArray hostName(512, Qt::Uninitialized);
+ if (gethostname(hostName.data(), hostName.size()) == -1)
+ return QByteArray();
+ hostName.truncate(strlen(hostName.data()));
+ return hostName;
+}
+
+/*
+ Reads metadata about the Compose file. Later used to determine if the
+ compose cache should be updated. The fileSize field will be zero on failure.
+*/
+static QComposeCacheFileHeader readFileMetadata(const QString &path)
+{
+ QComposeCacheFileHeader info;
+ info.reserved = 0;
+ info.fileSize = 0;
+ const QByteArray pathBytes = QFile::encodeName(path);
+ QT_STATBUF st;
+ if (QT_STAT(pathBytes.data(), &st) != 0)
+ return info;
+ info.lastModified = st.st_mtime;
+ info.fileSize = st.st_size;
+ return info;
+}
+
+static const QString getCacheFilePath()
+{
+ QFile machineIdFile("/var/lib/dbus/machine-id");
+ QString machineId;
+ if (machineIdFile.exists()) {
+ if (machineIdFile.open(QIODevice::ReadOnly))
+ machineId = QString::fromLatin1(machineIdFile.readAll().trimmed());
+ }
+ if (machineId.isEmpty())
+ machineId = localHostName();
+ const QString dirPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
+
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ return dirPath + QLatin1String("/qt_compose_cache_big_endian_") + machineId;
+ return dirPath + QLatin1String("/qt_compose_cache_little_endian_") + machineId;
+}
+
+// Returns empty vector on failure
+static QVector<QComposeTableElement> loadCache(const QComposeCacheFileHeader &composeInfo)
+{
+ QVector<QComposeTableElement> vec;
+ const QString cacheFilePath = getCacheFilePath();
+ QFile inputFile(cacheFilePath);
+
+ if (!inputFile.open(QIODevice::ReadOnly))
+ return vec;
+ QComposeCacheFileHeader cacheInfo;
+ // use a "buffer" variable to make the line after this one more readable.
+ char *buffer = reinterpret_cast<char*>(&cacheInfo);
+
+ if (inputFile.read(buffer, sizeof cacheInfo) != sizeof cacheInfo)
+ return vec;
+ if (cacheInfo.fileSize == 0)
+ return vec;
+ // using "!=" just in case someone replaced with a backup that existed before
+ if (cacheInfo.lastModified != composeInfo.lastModified)
+ return vec;
+ if (cacheInfo.cacheVersion != SupportedCacheVersion)
+ return vec;
+ const QByteArray pathBytes = QFile::encodeName(cacheFilePath);
+ QT_STATBUF st;
+ if (QT_STAT(pathBytes.data(), &st) != 0)
+ return vec;
+ const off_t fileSize = st.st_size;
+ if (fileSize > 1024 * 1024 * 5) {
+ // The cache file size is usually about 150KB, so if its size is over
+ // say 5MB then somebody inflated the file, abort.
+ return vec;
+ }
+ const off_t bufferSize = fileSize - (sizeof cacheInfo);
+ const size_t elemSize = sizeof (struct QComposeTableElement);
+ const int elemCount = bufferSize / elemSize;
+ const QByteArray ba = inputFile.read(bufferSize);
+ const char *data = ba.data();
+ // Since we know the number of the (many) elements and their size in
+ // advance calling vector.reserve(..) seems reasonable.
+ vec.reserve(elemCount);
+
+ for (int i = 0; i < elemCount; i++) {
+ const QComposeTableElement *elem =
+ reinterpret_cast<const QComposeTableElement*>(data + (i * elemSize));
+ vec.push_back(*elem);
+ }
+ return vec;
+}
+
+// Returns true on success, false otherwise.
+static bool saveCache(const QComposeCacheFileHeader &info, const QVector<QComposeTableElement> &vec)
+{
+ const QString filePath = getCacheFilePath();
+ QSaveFile outputFile(filePath);
+
+ if (!outputFile.open(QIODevice::WriteOnly))
+ return false;
+ const char *data = reinterpret_cast<const char*>(&info);
+
+ if (outputFile.write(data, sizeof info) != sizeof info)
+ return false;
+ data = reinterpret_cast<const char*>(vec.constData());
+ const qint64 size = vec.size() * (sizeof (struct QComposeTableElement));
+
+ if (outputFile.write(data, size) != size)
+ return false;
+ return outputFile.commit();
+}
+
TableGenerator::TableGenerator() : m_state(NoErrors),
m_systemComposeDir(QString())
{
initPossibleLocations();
- findComposeFile();
- orderComposeTable();
+ QString composeFilePath = findComposeFile();
+#ifdef DEBUG_GENERATOR
+// don't use cache when in debug mode.
+ if (!composeFilePath.isEmpty())
+ qDebug() << "Using Compose file from: " << composeFilePath;
+#else
+ QComposeCacheFileHeader fileInfo = readFileMetadata(composeFilePath);
+ if (fileInfo.fileSize != 0)
+ m_composeTable = loadCache(fileInfo);
+#endif
+ if (m_composeTable.isEmpty() && cleanState()) {
+ if (composeFilePath.isEmpty()) {
+ m_state = MissingComposeFile;
+ } else {
+ QFile composeFile(composeFilePath);
+ composeFile.open(QIODevice::ReadOnly);
+ parseComposeFile(&composeFile);
+ orderComposeTable();
+ if (m_composeTable.isEmpty()) {
+ m_state = EmptyTable;
+#ifndef DEBUG_GENERATOR
+// don't save cache when in debug mode
+ } else {
+ fileInfo.cacheVersion = SupportedCacheVersion;
+ saveCache(fileInfo, m_composeTable);
+#endif
+ }
+ }
+ }
#ifdef DEBUG_GENERATOR
printComposeTable();
#endif
@@ -76,53 +259,39 @@ void TableGenerator::initPossibleLocations()
m_possibleLocations.append(QStringLiteral(X11_PREFIX "/lib/X11/locale"));
}
-void TableGenerator::findComposeFile()
+QString TableGenerator::findComposeFile()
{
- bool found = false;
// check if XCOMPOSEFILE points to a Compose file
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
- QString composeFile(qgetenv("XCOMPOSEFILE"));
- if (composeFile.endsWith(QLatin1String("Compose")))
- found = processFile(composeFile);
+ QString path(qgetenv("XCOMPOSEFILE"));
+ if (path.endsWith(QLatin1String("Compose")))
+ return path;
else
qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file");
-#ifdef DEBUG_GENERATOR
- if (found)
- qDebug() << "Using Compose file from: " << composeFile;
-#endif
}
+
// check if user’s home directory has a file named .XCompose
- if (!found && cleanState()) {
- QString composeFile = qgetenv("HOME") + QStringLiteral("/.XCompose");
- if (QFile(composeFile).exists())
- found = processFile(composeFile);
-#ifdef DEBUG_GENERATOR
- if (found)
- qDebug() << "Using Compose file from: " << composeFile;
-#endif
+ if (cleanState()) {
+ QString path = qgetenv("HOME") + QStringLiteral("/.XCompose");
+ if (QFile(path).exists())
+ return path;
}
+
// check for the system provided compose files
- if (!found && cleanState()) {
+ if (cleanState()) {
QString table = composeTableForLocale();
if (cleanState()) {
if (table.isEmpty())
// no table mappings for the system's locale in the compose.dir
m_state = UnsupportedLocale;
- else
- found = processFile(systemComposeDir() + QLatin1Char('/') + table);
-#ifdef DEBUG_GENERATOR
- if (found)
- qDebug() << "Using Compose file from: " <<
- systemComposeDir() + QLatin1Char('/') + table;
-#endif
+ else {
+ QString path = QDir(systemComposeDir()).filePath(table);
+ if (QFile(path).exists())
+ return path;
+ }
}
}
-
- if (found && m_composeTable.isEmpty())
- m_state = EmptyTable;
-
- if (!found)
- m_state = MissingComposeFile;
+ return QString();
}
QString TableGenerator::composeTableForLocale()
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
index 468da4cad1..8ad081bea5 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.h
@@ -43,6 +43,8 @@
//#define DEBUG_GENERATOR
+/* Whenever QComposeTableElement gets modified supportedCacheVersion
+ from qtablegenerator.cpp must be bumped. */
struct QComposeTableElement {
uint keys[QT_KEYSEQUENCE_MAX_LEN];
uint value;
@@ -107,7 +109,7 @@ protected:
void parseKeySequence(char *line);
void parseIncludeInstruction(QString line);
- void findComposeFile();
+ QString findComposeFile();
bool findSystemComposeDir();
QString systemComposeDir();
QString composeTableForLocale();
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
index 96f6424ba2..15c98ed006 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp
@@ -52,7 +52,8 @@ QComposeInputContext *QComposePlatformInputContextPlugin::create(const QString &
{
Q_UNUSED(paramList);
- if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0)
+ if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0
+ || system.compare(system, QLatin1String("xim"), Qt::CaseInsensitive) == 0)
return new QComposeInputContext;
return 0;
}
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
index 673942b5d9..a952123576 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
@@ -39,6 +39,10 @@
#include <qwindow.h>
#include <qevent.h>
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+
#include "qibusproxy.h"
#include "qibusinputcontextproxy.h"
#include "qibustypes.h"
@@ -48,6 +52,10 @@
#include <QtDBus>
+#ifndef IBUS_RELEASE_MASK
+#define IBUS_RELEASE_MASK (1 << 30)
+#endif
+
QT_BEGIN_NAMESPACE
enum { debug = 0 };
@@ -63,29 +71,51 @@ public:
delete connection;
}
+ static QString getSocketPath();
static QDBusConnection *createConnection();
+ void initBus();
+ void createBusProxy();
+
QDBusConnection *connection;
QIBusProxy *bus;
QIBusInputContextProxy *context;
bool valid;
+ bool busConnected;
QString predit;
bool needsSurroundingText;
+ QLocale locale;
};
QIBusPlatformInputContext::QIBusPlatformInputContext ()
: d(new QIBusPlatformInputContextPrivate())
{
- 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(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
- connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired()));
+ QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath();
+ QFile file(socketPath);
+ if (file.open(QFile::ReadOnly)) {
+ // If KDE session save is used or restart ibus-daemon,
+ // the applications could run before ibus-daemon runs.
+ // We watch the getSocketPath() to get the launching ibus-daemon.
+ m_socketWatcher.addPath(socketPath);
+ connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString)));
}
+
+ m_timer.setSingleShot(true);
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus()));
+
+ connectToContextSignals();
+
QInputMethod *p = qApp->inputMethod();
connect(p, SIGNAL(cursorRectangleChanged()), this, SLOT(cursorRectChanged()));
+ m_eventFilterUseSynchronousMode = false;
+ if (qEnvironmentVariableIsSet("IBUS_ENABLE_SYNC_MODE")) {
+ bool ok;
+ int enableSync = qgetenv("IBUS_ENABLE_SYNC_MODE").toInt(&ok);
+ if (ok && enableSync == 1)
+ m_eventFilterUseSynchronousMode = true;
+ }
}
QIBusPlatformInputContext::~QIBusPlatformInputContext (void)
@@ -100,7 +130,7 @@ bool QIBusPlatformInputContext::isValid() const
void QIBusPlatformInputContext::invokeAction(QInputMethod::Action a, int)
{
- if (!d->valid)
+ if (!d->busConnected)
return;
if (a == QInputMethod::Click)
@@ -111,7 +141,7 @@ void QIBusPlatformInputContext::reset()
{
QPlatformInputContext::reset();
- if (!d->valid)
+ if (!d->busConnected)
return;
d->context->Reset();
@@ -122,7 +152,7 @@ void QIBusPlatformInputContext::commit()
{
QPlatformInputContext::commit();
- if (!d->valid)
+ if (!d->busConnected)
return;
QObject *input = qApp->focusObject();
@@ -176,7 +206,7 @@ void QIBusPlatformInputContext::update(Qt::InputMethodQueries q)
void QIBusPlatformInputContext::cursorRectChanged()
{
- if (!d->valid)
+ if (!d->busConnected)
return;
QRect r = qApp->inputMethod()->cursorRectangle().toRect();
@@ -194,7 +224,7 @@ void QIBusPlatformInputContext::cursorRectChanged()
void QIBusPlatformInputContext::setFocusObject(QObject *object)
{
- if (!d->valid)
+ if (!d->busConnected)
return;
if (debug)
@@ -272,33 +302,205 @@ void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars)
QCoreApplication::sendEvent(input, &event);
}
-bool
-QIBusPlatformInputContext::x11FilterEvent(uint keyval, uint keycode, uint state, bool press)
+bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
{
- if (!d->valid)
+ if (!d->busConnected)
return false;
if (!inputMethodAccepted())
return false;
- if (!press)
- return false;
+ const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
+ quint32 sym = keyEvent->nativeVirtualKey();
+ quint32 code = keyEvent->nativeScanCode();
+ quint32 state = keyEvent->nativeModifiers();
+ quint32 ibusState = state;
+
+ if (keyEvent->type() != QEvent::KeyPress)
+ ibusState |= IBUS_RELEASE_MASK;
+
+ QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code - 8, ibusState);
+
+ if (m_eventFilterUseSynchronousMode || reply.isFinished()) {
+ bool retval = reply.value();
+ qCDebug(qtQpaInputMethods) << "filterEvent return" << code << sym << state << retval;
+ return retval;
+ }
+
+ Qt::KeyboardModifiers modifiers = keyEvent->modifiers();
+ const int qtcode = keyEvent->key();
+
+ // From QKeyEvent::modifiers()
+ switch (qtcode) {
+ case Qt::Key_Shift:
+ modifiers ^= Qt::ShiftModifier;
+ break;
+ case Qt::Key_Control:
+ modifiers ^= Qt::ControlModifier;
+ break;
+ case Qt::Key_Alt:
+ modifiers ^= Qt::AltModifier;
+ break;
+ case Qt::Key_Meta:
+ modifiers ^= Qt::MetaModifier;
+ break;
+ case Qt::Key_AltGr:
+ modifiers ^= Qt::GroupSwitchModifier;
+ break;
+ }
+
+ QVariantList args;
+ args << QVariant::fromValue(keyEvent->timestamp());
+ args << QVariant::fromValue(static_cast<uint>(keyEvent->type()));
+ args << QVariant::fromValue(qtcode);
+ args << QVariant::fromValue(code) << QVariant::fromValue(sym) << QVariant::fromValue(state);
+ args << QVariant::fromValue(keyEvent->text());
+ args << QVariant::fromValue(keyEvent->isAutoRepeat());
+
+ QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, QGuiApplication::focusWindow(), modifiers, args);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &QIBusPlatformInputContext::filterEventFinished);
+
+ return true;
+}
+
+void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *call)
+{
+ QIBusFilterEventWatcher *watcher = (QIBusFilterEventWatcher *) call;
+ QDBusPendingReply<bool> reply = *call;
+
+ if (reply.isError()) {
+ call->deleteLater();
+ return;
+ }
+
+ // Use watcher's window instead of the current focused window
+ // since there is a time lag until filterEventFinished() returns.
+ QWindow *window = watcher->window();
+
+ if (!window) {
+ call->deleteLater();
+ return;
+ }
+
+ Qt::KeyboardModifiers modifiers = watcher->modifiers();
+ QVariantList args = watcher->arguments();
+ const ulong time = static_cast<const ulong>(args.at(0).toUInt());
+ const QEvent::Type type = static_cast<const QEvent::Type>(args.at(1).toUInt());
+ const int qtcode = args.at(2).toInt();
+ const quint32 code = args.at(3).toUInt();
+ const quint32 sym = args.at(4).toUInt();
+ const quint32 state = args.at(5).toUInt();
+ const QString string = args.at(6).toString();
+ const bool isAutoRepeat = args.at(7).toBool();
+
+ // copied from QXcbKeyboard::handleKeyEvent()
+ bool retval = reply.value();
+ qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << retval;
+ if (!retval) {
+ if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu
+ && window != NULL) {
+ const QPoint globalPos = window->screen()->handle()->cursor()->pos();
+ const QPoint pos = window->mapFromGlobal(globalPos);
+ QWindowSystemInterface::handleContextMenuEvent(window, false, pos,
+ globalPos, modifiers);
+ }
+ QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
+ code, sym, state, string, isAutoRepeat);
+
+ }
+ call->deleteLater();
+}
+
+QLocale QIBusPlatformInputContext::locale() const
+{
+ return d->locale;
+}
+
+void QIBusPlatformInputContext::socketChanged(const QString &str)
+{
+ qCDebug(qtQpaInputMethods) << "socketChanged";
+ Q_UNUSED (str);
+
+ m_timer.stop();
+
+ if (d->context)
+ disconnect(d->context);
+ if (d->bus && d->bus->isValid())
+ disconnect(d->bus);
+ if (d->connection)
+ d->connection->disconnectFromBus(QLatin1String("QIBusProxy"));
- keycode -= 8; // ###
- QDBusReply<bool> reply = d->context->ProcessKeyEvent(keyval, keycode, state);
+ m_timer.start(100);
+}
-// qDebug() << "x11FilterEvent return" << reply.value();
+// When getSocketPath() is modified, the bus is not established yet
+// so use m_timer.
+void QIBusPlatformInputContext::connectToBus()
+{
+ qCDebug(qtQpaInputMethods) << "QIBusPlatformInputContext::connectToBus";
+ d->initBus();
+ connectToContextSignals();
- return reply.value();
+ if (m_socketWatcher.files().size() == 0)
+ m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath());
+}
+
+void QIBusPlatformInputContext::globalEngineChanged(const QString &engine_name)
+{
+ if (!d->bus || !d->bus->isValid())
+ return;
+
+ QIBusEngineDesc desc = d->bus->getGlobalEngine();
+ Q_ASSERT(engine_name == desc.engine_name);
+ QLocale locale(desc.language);
+ if (d->locale != locale) {
+ d->locale = locale;
+ emitLocaleChanged();
+ }
+}
+
+void QIBusPlatformInputContext::connectToContextSignals()
+{
+ if (d->bus && d->bus->isValid()) {
+ connect(d->bus, SIGNAL(GlobalEngineChanged(QString)), this, SLOT(globalEngineChanged(QString)));
+ }
+
+ 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(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint)));
+ connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired()));
+ }
}
QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
- : connection(createConnection()),
+ : connection(0),
bus(0),
context(0),
valid(false),
+ busConnected(false),
needsSurroundingText(false)
{
+ valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty();
+ if (!valid)
+ return;
+ initBus();
+
+ if (bus && bus->isValid()) {
+ QIBusEngineDesc desc = bus->getGlobalEngine();
+ locale = QLocale(desc.language);
+ }
+}
+
+void QIBusPlatformInputContextPrivate::initBus()
+{
+ connection = createConnection();
+ busConnected = false;
+ createBusProxy();
+}
+
+void QIBusPlatformInputContextPrivate::createBusProxy()
+{
if (!connection || !connection->isConnected())
return;
@@ -334,13 +536,13 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate()
context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS|IBUS_CAP_SURROUNDING_TEXT);
if (debug)
- qDebug(">>>> valid!");
- valid = true;
+ qDebug(">>>> bus connected!");
+ busConnected = true;
}
-QDBusConnection *QIBusPlatformInputContextPrivate::createConnection()
+QString QIBusPlatformInputContextPrivate::getSocketPath()
{
- QByteArray display(getenv("DISPLAY"));
+ QByteArray display(qgetenv("DISPLAY"));
QByteArray host = "unix";
QByteArray displayNumber = "0";
@@ -356,9 +558,14 @@ QDBusConnection *QIBusPlatformInputContextPrivate::createConnection()
if (debug)
qDebug() << "host=" << host << "displayNumber" << displayNumber;
- QFile file(QDir::homePath() + QLatin1String("/.config/ibus/bus/") +
+ return QDir::homePath() + QLatin1String("/.config/ibus/bus/") +
QLatin1String(QDBusConnection::localMachineId()) +
- QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber));
+ QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber);
+}
+
+QDBusConnection *QIBusPlatformInputContextPrivate::createConnection()
+{
+ QFile file(getSocketPath());
if (!file.open(QFile::ReadOnly))
return 0;
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
index 816da8d377..824e9c2073 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
@@ -35,11 +35,44 @@
#include <qpa/qplatforminputcontext.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/QLocale>
+#include <QtDBus/qdbuspendingreply.h>
+#include <QFileSystemWatcher>
+#include <QTimer>
+#include <QWindow>
+
QT_BEGIN_NAMESPACE
class QIBusPlatformInputContextPrivate;
class QDBusVariant;
+class QIBusFilterEventWatcher: public QDBusPendingCallWatcher
+{
+public:
+ explicit QIBusFilterEventWatcher(const QDBusPendingCall &call,
+ QObject *parent = 0,
+ QWindow *window = 0,
+ const Qt::KeyboardModifiers modifiers = 0,
+ const QVariantList arguments = QVariantList())
+ : QDBusPendingCallWatcher(call, parent)
+ , m_window(window)
+ , m_modifiers(modifiers)
+ , m_arguments(arguments)
+ {}
+ ~QIBusFilterEventWatcher()
+ {}
+
+ inline QWindow *window() const { return m_window; }
+ inline const Qt::KeyboardModifiers modifiers() const { return m_modifiers; }
+ inline const QVariantList arguments() const { return m_arguments; }
+
+private:
+ QPointer<QWindow> m_window;
+ const Qt::KeyboardModifiers m_modifiers;
+ const QVariantList m_arguments;
+};
+
class QIBusPlatformInputContext : public QPlatformInputContext
{
Q_OBJECT
@@ -54,8 +87,8 @@ public:
void reset() Q_DECL_OVERRIDE;
void commit() Q_DECL_OVERRIDE;
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
-
- Q_INVOKABLE bool x11FilterEvent(uint keyval, uint keycode, uint state, bool press);
+ bool filterEvent(const QEvent *event) Q_DECL_OVERRIDE;
+ QLocale locale() const Q_DECL_OVERRIDE;
public Q_SLOTS:
void commitText(const QDBusVariant &text);
@@ -63,9 +96,18 @@ public Q_SLOTS:
void cursorRectChanged();
void deleteSurroundingText(int offset, uint n_chars);
void surroundingTextRequired();
+ void filterEventFinished(QDBusPendingCallWatcher *call);
+ void socketChanged(const QString &str);
+ void connectToBus();
+ void globalEngineChanged(const QString &engine_name);
private:
QIBusPlatformInputContextPrivate *d;
+ bool m_eventFilterUseSynchronousMode;
+ QFileSystemWatcher m_socketWatcher;
+ QTimer m_timer;
+
+ void connectToContextSignals();
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
index e6b255a06d..9efa6f7eb0 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.cpp
@@ -9,6 +9,8 @@
* before re-generating it.
*/
+#include <QtDBus/qdbusextratypes.h>
+
#include "qibusproxy.h"
/*
@@ -18,9 +20,36 @@
QIBusProxy::QIBusProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
+ this->connection().connect(service,
+ path,
+ this->interface(), // interface
+ QStringLiteral("GlobalEngineChanged"),
+ QStringList(),
+ QString(), // signature
+ this, SLOT(globalEngineChanged(QString)));
}
QIBusProxy::~QIBusProxy()
{
}
+QIBusEngineDesc QIBusProxy::getGlobalEngine()
+{
+ QIBusEngineDesc desc;
+ QDBusReply<QDBusVariant> reply = GetGlobalEngine();
+ QVariant variant = reply.value().variant();
+ if (!variant.isValid())
+ return desc;
+ QVariant child = variant.value<QDBusVariant>().variant();
+ if (!child.isValid())
+ return desc;
+ const QDBusArgument argument = child.value<QDBusArgument>();
+ argument >> desc;
+ return desc;
+}
+
+void QIBusProxy::globalEngineChanged(const QString &engine_name)
+{
+ emit GlobalEngineChanged(engine_name);
+}
+
diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxy.h b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
index 69443a524d..bbaebe1b96 100644
--- a/src/plugins/platforminputcontexts/ibus/qibusproxy.h
+++ b/src/plugins/platforminputcontexts/ibus/qibusproxy.h
@@ -20,6 +20,8 @@
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
+#include "qibustypes.h"
+
/*
* Proxy class for interface org.freedesktop.IBus
*/
@@ -29,6 +31,8 @@ class QIBusProxy: public QDBusAbstractInterface
public:
static inline const char *staticInterfaceName()
{ return "org.freedesktop.IBus"; }
+ static inline QString dbusInterfaceProperties()
+ { return QStringLiteral("org.freedesktop.DBus.Properties"); }
public:
QIBusProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
@@ -82,7 +86,26 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("RegisterComponent"), argumentList);
}
+ inline QDBusPendingReply<QDBusVariant> GetGlobalEngine()
+ {
+ if (!this->isValid() || this->service().isEmpty() || this->path().isEmpty())
+ return QDBusMessage::createError(this->lastError());
+
+ QDBusMessage msg = QDBusMessage::createMethodCall(this->service(),
+ this->path(),
+ dbusInterfaceProperties(),
+ QStringLiteral("Get"));
+ msg << this->interface() << QStringLiteral("GlobalEngine");
+ return this->connection().asyncCall(msg, this->timeout());
+ }
+
+ QIBusEngineDesc getGlobalEngine();
+
+private:
+ void globalEngineChanged(const QString &engine_name);
+
Q_SIGNALS: // SIGNALS
+ void GlobalEngineChanged(const QString &engine_name);
};
#endif
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
index d6be6cbb31..7cf3b24570 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp
@@ -37,6 +37,9 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(qtQpaInputMethods, "qt.qpa.input.methods")
+Q_LOGGING_CATEGORY(qtQpaInputMethodsSerialize, "qt.qpa.input.methods.serialize")
+
QIBusSerializable::QIBusSerializable()
{
}
@@ -202,7 +205,7 @@ QDBusArgument &operator<<(QDBusArgument &argument, const QIBusAttributeList &att
const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &attrList)
{
-// qDebug() << "QIBusAttributeList::fromDBusArgument()" << arg.currentSignature();
+ qCDebug(qtQpaInputMethodsSerialize) << "QIBusAttributeList::fromDBusArgument()" << arg.currentSignature();
arg.beginStructure();
arg >> static_cast<QIBusSerializable &>(attrList);
@@ -225,9 +228,10 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &at
QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
{
QHash<QPair<int, int>, QTextCharFormat> rangeAttrs;
+ const int numAttributes = attributes.size();
// Merge text fomats for identical ranges into a single QTextFormat.
- for (int i = 0; i < attributes.size(); ++i) {
+ for (int i = 0; i < numAttributes; ++i) {
const QIBusAttribute &attr = attributes.at(i);
const QTextCharFormat &format = attr.format();
@@ -239,8 +243,9 @@ QList<QInputMethodEvent::Attribute> QIBusAttributeList::imAttributes() const
// Assemble list in original attribute order.
QList<QInputMethodEvent::Attribute> imAttrs;
+ imAttrs.reserve(numAttributes);
- for (int i = 0; i < attributes.size(); ++i) {
+ for (int i = 0; i < numAttributes; ++i) {
const QIBusAttribute &attr = attributes.at(i);
const QTextFormat &format = attr.format();
@@ -275,7 +280,7 @@ QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text)
const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text)
{
-// qDebug() << "QIBusText::fromDBusArgument()" << arg.currentSignature();
+ qCDebug(qtQpaInputMethodsSerialize) << "QIBusText::fromDBusArgument()" << argument.currentSignature();
argument.beginStructure();
argument >> static_cast<QIBusSerializable &>(text);
@@ -289,4 +294,107 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text)
return argument;
}
+QIBusEngineDesc::QIBusEngineDesc()
+ : engine_name(""),
+ longname(""),
+ description(""),
+ language(""),
+ license(""),
+ author(""),
+ icon(""),
+ layout(""),
+ rank(0),
+ hotkeys(""),
+ symbol(""),
+ setup(""),
+ layout_variant(""),
+ layout_option(""),
+ version(""),
+ textdomain(""),
+ iconpropkey("")
+{
+ name = "IBusEngineDesc";
+}
+
+QIBusEngineDesc::~QIBusEngineDesc()
+{
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusEngineDesc &desc)
+{
+ argument.beginStructure();
+
+ argument << static_cast<const QIBusSerializable &>(desc);
+
+ argument << desc.engine_name;
+ argument << desc.longname;
+ argument << desc.description;
+ argument << desc.language;
+ argument << desc.license;
+ argument << desc.author;
+ argument << desc.icon;
+ argument << desc.layout;
+ argument << desc.rank;
+ argument << desc.hotkeys;
+ argument << desc.symbol;
+ argument << desc.setup;
+ argument << desc.layout_variant;
+ argument << desc.layout_option;
+ argument << desc.version;
+ argument << desc.textdomain;
+ argument << desc.iconpropkey;
+
+ argument.endStructure();
+ return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusEngineDesc &desc)
+{
+ qCDebug(qtQpaInputMethodsSerialize) << "QIBusEngineDesc::fromDBusArgument()" << argument.currentSignature();
+ argument.beginStructure();
+
+ argument >> static_cast<QIBusSerializable &>(desc);
+
+ argument >> desc.engine_name;
+ argument >> desc.longname;
+ argument >> desc.description;
+ argument >> desc.language;
+ argument >> desc.license;
+ argument >> desc.author;
+ argument >> desc.icon;
+ argument >> desc.layout;
+ argument >> desc.rank;
+ argument >> desc.hotkeys;
+ argument >> desc.symbol;
+ argument >> desc.setup;
+ // Previous IBusEngineDesc supports the arguments between engine_name
+ // and setup.
+ if (argument.currentSignature() == "") {
+ argument.endStructure();
+ return argument;
+ }
+ argument >> desc.layout_variant;
+ argument >> desc.layout_option;
+ // Previous IBusEngineDesc supports the arguments between engine_name
+ // and layout_option.
+ if (argument.currentSignature() == "") {
+ argument.endStructure();
+ return argument;
+ }
+ argument >> desc.version;
+ if (argument.currentSignature() == "") {
+ argument.endStructure();
+ return argument;
+ }
+ argument >> desc.textdomain;
+ if (argument.currentSignature() == "") {
+ argument.endStructure();
+ return argument;
+ }
+ argument >> desc.iconpropkey;
+
+ argument.endStructure();
+ return argument;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.h b/src/plugins/platforminputcontexts/ibus/qibustypes.h
index cb0d9ff2aa..b4145863bc 100644
--- a/src/plugins/platforminputcontexts/ibus/qibustypes.h
+++ b/src/plugins/platforminputcontexts/ibus/qibustypes.h
@@ -37,9 +37,13 @@
#include <qevent.h>
#include <QDBusArgument>
#include <QTextCharFormat>
+#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(qtQpaInputMethods)
+Q_DECLARE_LOGGING_CATEGORY(qtQpaInputMethodsSerialize)
+
class QIBusSerializable
{
public:
@@ -100,6 +104,31 @@ public:
QIBusAttributeList attributes;
};
+class QIBusEngineDesc : public QIBusSerializable
+{
+public:
+ QIBusEngineDesc();
+ ~QIBusEngineDesc();
+
+ QString engine_name;
+ QString longname;
+ QString description;
+ QString language;
+ QString license;
+ QString author;
+ QString icon;
+ QString layout;
+ unsigned int rank;
+ QString hotkeys;
+ QString symbol;
+ QString setup;
+ QString layout_variant;
+ QString layout_option;
+ QString version;
+ QString textdomain;
+ QString iconpropkey;
+};
+
QDBusArgument &operator<<(QDBusArgument &argument, const QIBusSerializable &object);
const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusSerializable &object);
@@ -112,11 +141,15 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &at
QDBusArgument &operator<<(QDBusArgument &argument, const QIBusText &text);
const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusText &text);
+QDBusArgument &operator<<(QDBusArgument &argument, const QIBusEngineDesc &desc);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusEngineDesc &desc);
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QIBusSerializable)
Q_DECLARE_METATYPE(QIBusAttribute)
Q_DECLARE_METATYPE(QIBusAttributeList)
Q_DECLARE_METATYPE(QIBusText)
+Q_DECLARE_METATYPE(QIBusEngineDesc)
#endif
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 8ee3ff88d1..8982787ec9 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -70,18 +70,20 @@ namespace QtAndroidInput
candidatesEnd);
}
- void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints)
+ void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
{
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
"showSoftwareKeyboard",
- "(IIIII)V",
+ "(IIIIII)V",
left,
top,
width,
height,
- inputHints);
+ inputHints,
+ enterKeyType
+ );
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints;
+ qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
#endif
}
@@ -238,6 +240,52 @@ namespace QtAndroidInput
QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints);
}
+ static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint deviceId, jlong time, jint action,
+ jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure)
+ {
+ QPointF globalPosF(x, y);
+ QPoint globalPos((int)x, (int)y);
+ QWindow *tlw = topLevelWindowAt(globalPos);
+ QPointF localPos = tlw ? (globalPosF - tlw->position()) : globalPosF;
+
+ // Galaxy Note with plain Android:
+ // 0 1 0 stylus press
+ // 2 1 0 stylus drag
+ // 1 1 0 stylus release
+ // 0 1 2 stylus press with side-button held
+ // 2 1 2 stylus drag with side-button held
+ // 1 1 2 stylus release with side-button held
+ // Galaxy Note 4 with Samsung firmware:
+ // 0 1 0 stylus press
+ // 2 1 0 stylus drag
+ // 1 1 0 stylus release
+ // 211 1 2 stylus press with side-button held
+ // 213 1 2 stylus drag with side-button held
+ // 212 1 2 stylus release with side-button held
+ // when action == ACTION_UP (1) it's a release; otherwise we say which button is pressed
+ Qt::MouseButtons buttons = Qt::NoButton;
+ switch (action) {
+ case 1: // ACTION_UP
+ case 212: // stylus release while side-button held on Galaxy Note 4
+ buttons = Qt::NoButton;
+ break;
+ default: // action is press or drag
+ if (buttonState == 0)
+ buttons = Qt::LeftButton;
+ else // 2 means RightButton
+ buttons = Qt::MouseButtons(buttonState);
+ break;
+ }
+
+#ifdef QT_DEBUG_ANDROID_STYLUS
+ qDebug() << action << pointerType << buttonState << '@' << x << y << "pressure" << pressure << ": buttons" << buttons;
+#endif
+
+ QWindowSystemInterface::handleTabletEvent(tlw, ulong(time),
+ localPos, globalPosF, QTabletEvent::Stylus, pointerType,
+ buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier);
+ }
+
static int mapAndroidKey(int key)
{
// 0--9 0x00000007 -- 0x00000010
@@ -633,7 +681,7 @@ namespace QtAndroidInput
return Qt::Key_AudioCycleTrack;
default:
- qWarning() << "Unhandled key code " << key << "!";
+ qWarning() << "Unhandled key code " << key << '!';
return 0;
}
}
@@ -702,6 +750,7 @@ namespace QtAndroidInput
{"mouseUp", "(III)V", (void *)mouseUp},
{"mouseMove", "(III)V", (void *)mouseMove},
{"longPress", "(III)V", (void *)longPress},
+ {"tabletEvent", "(IIJIIIFFF)V", (void *)tabletEvent},
{"keyDown", "(IIIZ)V", (void *)keyDown},
{"keyUp", "(IIIZ)V", (void *)keyUp},
{"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged}
diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h
index b5a2ef06e4..d737dc9c98 100644
--- a/src/plugins/platforms/android/androidjniinput.h
+++ b/src/plugins/platforms/android/androidjniinput.h
@@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE
namespace QtAndroidInput
{
// Software keyboard support
- void showSoftwareKeyboard(int top, int left, int width, int height, int inputHints);
+ void showSoftwareKeyboard(int top, int left, int width, int height, int inputHints, int enterKeyType);
void resetSoftwareKeyboard();
void hideSoftwareKeyboard();
bool isSoftwareKeyboardVisible();
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index a04bf1eccb..d419e42cd5 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -55,6 +55,7 @@
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/private/qjni_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -109,6 +110,7 @@ static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr;
static int m_desktopWidthPixels = 0;
static int m_desktopHeightPixels = 0;
static double m_scaledDensity = 0;
+static double m_density = 1.0;
static volatile bool m_pauseApplication;
@@ -157,6 +159,11 @@ namespace QtAndroid
return m_scaledDensity;
}
+ double pixelDensity()
+ {
+ return m_density;
+ }
+
JavaVM *javaVM()
{
return m_javaVM;
@@ -292,7 +299,7 @@ namespace QtAndroid
QString manufacturer = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString();
QString model = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString();
- return manufacturer + QStringLiteral(" ") + model;
+ return manufacturer + QLatin1Char(' ') + model;
}
int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth)
@@ -432,7 +439,6 @@ static void *startMainMethod(void */*data*/)
params[i] = static_cast<const char *>(m_applicationParams[i].constData());
int ret = m_main(m_applicationParams.length(), const_cast<char **>(params.data()));
- Q_UNUSED(ret);
if (m_mainLibraryHnd) {
int res = dlclose(m_mainLibraryHnd);
@@ -448,6 +454,8 @@ static void *startMainMethod(void */*data*/)
if (vm != 0)
vm->DetachCurrentThread();
+ // We must call exit() to ensure that all global objects will be destructed
+ exit(ret);
return 0;
}
@@ -546,7 +554,8 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface,
static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
jint widthPixels, jint heightPixels,
jint desktopWidthPixels, jint desktopHeightPixels,
- jdouble xdpi, jdouble ydpi, jdouble scaledDensity)
+ jdouble xdpi, jdouble ydpi,
+ jdouble scaledDensity, jdouble density)
{
// Android does not give us the correct screen size for immersive mode, but
// the surface does have the right size
@@ -557,6 +566,7 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
m_desktopWidthPixels = desktopWidthPixels;
m_desktopHeightPixels = desktopHeightPixels;
m_scaledDensity = scaledDensity;
+ m_density = density;
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,
@@ -600,6 +610,11 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state
return;
}
+ if (state == Qt::ApplicationActive)
+ QtAndroidPrivate::handleResume();
+ else if (state == Qt::ApplicationInactive)
+ QtAndroidPrivate::handlePause();
+
if (state <= Qt::ApplicationInactive) {
// NOTE: sometimes we will receive two consecutive suspended notifications,
// In the second suspended notification, QWindowSystemInterface::flushWindowSystemEvents()
@@ -677,7 +692,7 @@ static JNINativeMethod methods[] = {
{"startQtApplication", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)startQtApplication},
{"quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin},
{"terminateQt", "()V", (void *)terminateQt},
- {"setDisplayMetrics", "(IIIIDDD)V", (void *)setDisplayMetrics},
+ {"setDisplayMetrics", "(IIIIDDDD)V", (void *)setDisplayMetrics},
{"setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface},
{"updateWindow", "()V", (void *)updateWindow},
{"updateApplicationState", "(I)V", (void *)updateApplicationState},
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 4d037f4b74..cdedeb38f8 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -71,6 +71,7 @@ namespace QtAndroid
int desktopWidthPixels();
int desktopHeightPixels();
double scaledDensity();
+ double pixelDensity();
JavaVM *javaVM();
AAssetManager *assetManager();
jclass applicationClass();
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index 64be75b63f..6ad3d2dc9a 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -122,8 +122,8 @@ public:
m_assetFile = 0;
m_assetDir = asset;
m_fileName = fileName;
- if (!m_fileName.endsWith(QChar(QLatin1Char('/'))))
- m_fileName += "/";
+ if (!m_fileName.endsWith(QLatin1Char('/')))
+ m_fileName += QLatin1Char('/');
}
~AndroidAbstractFileEngine()
@@ -231,8 +231,8 @@ public:
return;
m_fileName = file;
- if (!m_fileName.endsWith(QChar(QLatin1Char('/'))))
- m_fileName += "/";
+ if (!m_fileName.endsWith(QLatin1Char('/')))
+ m_fileName += QLatin1Char('/');
close();
}
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index d264f74d66..e3ea048e84 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -342,7 +342,7 @@ QAndroidInputContext::QAndroidInputContext()
if (clazz == NULL) {
qCritical() << "Native registration unable to find class '"
<< QtNativeInputConnectionClassName
- << "'";
+ << '\'';
return;
}
@@ -350,7 +350,7 @@ QAndroidInputContext::QAndroidInputContext()
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
qCritical() << "RegisterNatives failed for '"
<< QtNativeInputConnectionClassName
- << "'";
+ << '\'';
return;
}
@@ -358,7 +358,7 @@ QAndroidInputContext::QAndroidInputContext()
if (clazz == NULL) {
qCritical() << "Native registration unable to find class '"
<< QtExtractedTextClassName
- << "'";
+ << '\'';
return;
}
@@ -545,7 +545,9 @@ void QAndroidInputContext::showInputPanel()
rect.top(),
rect.width(),
rect.height(),
- query->value(Qt::ImHints).toUInt());
+ query->value(Qt::ImHints).toUInt(),
+ query->value(Qt::ImEnterKeyType).toUInt()
+ );
}
void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)
diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
index be1a3d7bdf..a8bbec9400 100644
--- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
+++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
@@ -69,11 +69,11 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami
{
QStringList result;
if (styleHint == QFont::Monospace || styleHint == QFont::Courier)
- result.append(QString(qgetenv("QT_ANDROID_FONTS_MONOSPACE")).split(";"));
+ result.append(QString(qgetenv("QT_ANDROID_FONTS_MONOSPACE")).split(QLatin1Char(';')));
else if (styleHint == QFont::Serif)
- result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(";"));
+ result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
else
- result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(";"));
+ result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';')));
result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
return result;
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 7a509e4d61..209ce2f7db 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -382,6 +382,11 @@ QDpi QAndroidPlatformScreen::logicalDpi() const
return QDpi(lDpi, lDpi);
}
+qreal QAndroidPlatformScreen::pixelDensity() const
+{
+ return QtAndroid::pixelDensity();
+}
+
Qt::ScreenOrientation QAndroidPlatformScreen::orientation() const
{
return QAndroidPlatformIntegration::m_orientation;
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index f4f9cedb70..1b7bc91c83 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -95,6 +95,7 @@ protected:
private:
QDpi logicalDpi() const;
+ qreal pixelDensity() const;
Qt::ScreenOrientation orientation() const;
Qt::ScreenOrientation nativeOrientation() const;
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index 3e2ae7c939..71a3f910d2 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -31,6 +31,7 @@
**
****************************************************************************/
+#include "androidjnimain.h"
#include "androidjnimenu.h"
#include "qandroidplatformtheme.h"
#include "qandroidplatformmenubar.h"
@@ -216,6 +217,7 @@ QJsonObject AndroidStyle::loadStyleData()
static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
{
+ double pixelDensity = qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") ? QtAndroid::pixelDensity() : 1.0;
std::shared_ptr<AndroidStyle> style(new AndroidStyle);
style->m_styleData = AndroidStyle::loadStyleData();
if (style->m_styleData.isEmpty())
@@ -245,7 +247,7 @@ static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
// Font size (in pixels)
attributeIterator = item.find(QLatin1String("TextAppearance_textSize"));
if (attributeIterator != item.constEnd())
- font.setPixelSize(int(attributeIterator.value().toDouble()));
+ font.setPixelSize(int(attributeIterator.value().toDouble() / pixelDensity));
// Font style
attributeIterator = item.find(QLatin1String("TextAppearance_textStyle"));
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index ad6cb3a1fc..ba0e6b001a 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -12,7 +12,6 @@ OBJECTIVE_SOURCES += main.mm \
qcocoawindow.mm \
qnsview.mm \
qnsviewaccessibility.mm \
- qcocoaautoreleasepool.mm \
qnswindowdelegate.mm \
qcocoanativeinterface.mm \
qcocoaeventdispatcher.mm \
@@ -48,7 +47,6 @@ HEADERS += qcocoaintegration.h \
qcocoabackingstore.h \
qcocoawindow.h \
qnsview.h \
- qcocoaautoreleasepool.h \
qnswindowdelegate.h \
qcocoanativeinterface.h \
qcocoaeventdispatcher.h \
diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm
index b7e8fa1fca..43ff715161 100644
--- a/src/plugins/platforms/cocoa/main.mm
+++ b/src/plugins/platforms/cocoa/main.mm
@@ -50,11 +50,9 @@ public:
QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
- Q_UNUSED(paramList);
-
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (system.compare(QLatin1String("cocoa"), Qt::CaseInsensitive) == 0)
- return new QCocoaIntegration;
+ return new QCocoaIntegration(paramList);
return 0;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index 061dfac156..228643ab26 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -38,6 +38,8 @@
#include <QtGui>
#include <qpa/qplatformaccessibility.h>
+#ifndef QT_NO_ACCESSIBILITY
+
QT_BEGIN_NAMESPACE
class QCocoaAccessibility : public QPlatformAccessibility
@@ -45,10 +47,10 @@ class QCocoaAccessibility : public QPlatformAccessibility
public:
QCocoaAccessibility();
~QCocoaAccessibility();
- void notifyAccessibilityUpdate(QAccessibleEvent *event);
- void setRootObject(QObject *o);
- void initialize();
- void cleanup();
+ void notifyAccessibilityUpdate(QAccessibleEvent *event) Q_DECL_OVERRIDE;
+ void setRootObject(QObject *o) Q_DECL_OVERRIDE;
+ void initialize() Q_DECL_OVERRIDE;
+ void cleanup() Q_DECL_OVERRIDE;
};
namespace QCocoaAccessible {
@@ -85,4 +87,6 @@ id getValueAttribute(QAccessibleInterface *interface);
QT_END_NAMESPACE
-#endif
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QCOCOAACCESIBILITY_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 03f585d19d..4e901ba015 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -37,6 +37,8 @@
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
+
QCocoaAccessibility::QCocoaAccessibility()
{
@@ -374,5 +376,7 @@ id getValueAttribute(QAccessibleInterface *interface)
} // namespace QCocoaAccessible
+#endif // QT_NO_ACCESSIBILITY
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 9f56d306f4..73aeae129b 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -37,6 +37,8 @@
#include "qt_mac_p.h"
+#ifndef QT_NO_ACCESSIBILITY
+
#import <Cocoa/Cocoa.h>
#import <AppKit/NSAccessibility.h>
@@ -56,4 +58,6 @@
QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
-#endif
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // QCOCOAACCESIBILITYELEMENT_H
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 6769f4ab0c..b55393c7dc 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -42,6 +42,8 @@
QT_USE_NAMESPACE
+#ifndef QT_NO_ACCESSIBILITY
+
static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0)
{
Q_ASSERT(line == -1 || offset == -1);
@@ -588,3 +590,5 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of
}
@end
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
index 04e51d5392..abaaba91a5 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
@@ -100,6 +100,7 @@
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate;
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
- (void) removeAppleEventHandlers;
+- (bool) inLaunch;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate);
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 6c673a4f5d..caa8884661 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -221,12 +221,8 @@ QT_END_NAMESPACE
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
QWindow *topLevelWindow = topLevels.at(i);
- // Widgets have alreay received a CloseEvent from the QApplication
- // QCloseEvent handler. (see canQuit above). Prevent running the
- // CloseEvent logic twice, call close() directly.
- if (topLevelWindow->inherits("QWidgetWindow"))
- topLevelWindow->close();
- else
+ // Already closed windows will not have a platform window, skip those
+ if (topLevelWindow->handle())
QWindowSystemInterface::handleCloseEvent(topLevelWindow);
}
QWindowSystemInterface::flushWindowSystemEvents();
@@ -284,6 +280,11 @@ QT_END_NAMESPACE
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
}
+- (bool) inLaunch
+{
+ return inLaunch;
+}
+
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Q_UNUSED(aNotification);
diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm
deleted file mode 100644
index 8f30365186..0000000000
--- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qcocoaautoreleasepool.h"
-
-QT_BEGIN_NAMESPACE
-
-QCocoaAutoReleasePool::QCocoaAutoReleasePool()
-{
- pool = [[NSAutoreleasePool alloc] init];
-}
-
-QCocoaAutoReleasePool::~QCocoaAutoReleasePool()
-{
- [pool release];
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 3737584c4c..5a199de4a5 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -49,12 +49,12 @@ public:
QCocoaBackingStore(QWindow *window);
~QCocoaBackingStore();
- QPaintDevice *paintDevice();
- void flush(QWindow *widget, const QRegion &region, const QPoint &offset);
- QImage toImage() const;
- void resize (const QSize &size, const QRegion &);
- bool scroll(const QRegion &area, int dx, int dy);
- void beginPaint(const QRegion &region);
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ void flush(QWindow *widget, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ QImage toImage() const Q_DECL_OVERRIDE;
+ void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE;
+ bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;
qreal getBackingStoreDevicePixelRatio();
private:
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h
index e3df9a99b1..e53942b068 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.h
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h
@@ -47,10 +47,10 @@ class QCocoaClipboard : public QObject, public QPlatformClipboard
public:
QCocoaClipboard();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
- void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
- bool supportsMode(QClipboard::Mode mode) const;
- bool ownsMode(QClipboard::Mode mode) const;
+ 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;
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 3183705330..705f97cd2a 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h
@@ -43,14 +43,14 @@ class QCocoaColorDialogHelper : public QPlatformColorDialogHelper
{
public:
QCocoaColorDialogHelper();
- virtual ~QCocoaColorDialogHelper();
+ ~QCocoaColorDialogHelper();
- void exec();
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
- void hide();
+ void exec() Q_DECL_OVERRIDE;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
+ void hide() Q_DECL_OVERRIDE;
- void setCurrentColor(const QColor&);
- QColor currentColor() const;
+ void setCurrentColor(const QColor&) Q_DECL_OVERRIDE;
+ QColor currentColor() const Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index cc6cbaf59e..d104939f0c 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -47,9 +47,9 @@ public:
QCocoaCursor();
~QCocoaCursor();
- virtual void changeCursor(QCursor *cursor, QWindow *window);
- virtual QPoint pos() const;
- virtual void setPos(const QPoint &position);
+ void changeCursor(QCursor *cursor, QWindow *window) Q_DECL_OVERRIDE;
+ QPoint pos() const Q_DECL_OVERRIDE;
+ void setPos(const QPoint &position) Q_DECL_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 f08386d18e..8e38181c29 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -34,7 +34,6 @@
#include "qcocoacursor.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include <QtGui/QBitmap>
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
index e087fcee26..c1eeb34679 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.h
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -47,13 +47,13 @@ class QCocoaDrag : public QPlatformDrag
{
public:
QCocoaDrag();
- virtual ~QCocoaDrag();
+ ~QCocoaDrag();
- virtual QMimeData *platformDropData();
- virtual Qt::DropAction drag(QDrag *m_drag);
+ QMimeData *platformDropData() Q_DECL_OVERRIDE;
+ Qt::DropAction drag(QDrag *m_drag) Q_DECL_OVERRIDE;
- virtual Qt::DropAction defaultAction(Qt::DropActions possibleActions,
- Qt::KeyboardModifiers modifiers) const;
+ Qt::DropAction defaultAction(Qt::DropActions possibleActions,
+ Qt::KeyboardModifiers modifiers) const Q_DECL_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 4466d28128..8aa7a6b583 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -127,16 +127,17 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest);
NSPoint event_location = [m_lastEvent locationInWindow];
- NSPoint local_point = [m_lastView convertPoint:event_location fromView:nil];
- local_point.x -= hotSpot.x();
+ NSWindow *theWindow = [m_lastEvent window];
+ Q_ASSERT(theWindow != nil);
+ event_location.x -= hotSpot.x();
CGFloat flippedY = pm.height() - hotSpot.y();
- local_point.y += flippedY;
- NSSize mouseOffset = NSMakeSize(0.0, 0.0);
+ event_location.y -= flippedY;
+ NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0);
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- [m_lastView dragImage:nsimage
- at:local_point
- offset:mouseOffset
+ [theWindow dragImage:nsimage
+ at:event_location
+ offset:mouseOffset_unused
event:m_lastEvent
pasteboard:pboard
source:m_lastView
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 13a8c89dbb..8a2a478a72 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -80,12 +80,11 @@
//
#include <QtCore/qabstracteventdispatcher.h>
-#include <QtCore/qhash.h>
#include <QtCore/qstack.h>
#include <QtGui/qwindowdefs.h>
#include <QtCore/private/qabstracteventdispatcher_p.h>
+#include <QtCore/private/qcfsocketnotifier_p.h>
#include <QtCore/private/qtimerinfo_unix_p.h>
-#include <QtPlatformSupport/private/qcfsocketnotifier_p.h>
#include <CoreFoundation/CoreFoundation.h>
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 52b2e23345..1865624d57 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -66,13 +66,11 @@
****************************************************************************/
#include "qcocoaeventdispatcher.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qguiapplication.h"
#include "qevent.h"
-#include "qhash.h"
#include "qmutex.h"
#include "qsocketnotifier.h"
#include <qpa/qplatformwindow.h>
@@ -365,7 +363,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
if (d->interrupt)
break;
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
NSEvent* event = 0;
// First, send all previously excluded input events, if any:
@@ -623,7 +621,7 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
continue;
if (!info.session) {
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(info.window->handle());
NSWindow *nswindow = cocoaWindow->nativeWindow();
if (!nswindow)
@@ -671,7 +669,7 @@ void QCocoaEventDispatcherPrivate::updateChildrenWorksWhenModal()
// Make the dialog children of the window
// active. And make the dialog children of
// the previous modal dialog unactive again:
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
int size = cocoaModalSessionStack.size();
if (size > 0){
if (QWindow *prevModal = cocoaModalSessionStack[size-1].window)
@@ -692,7 +690,7 @@ void QCocoaEventDispatcherPrivate::cleanupModalSessions()
// point they were marked as stopped), is that ending a session
// when no other session runs below it on the stack will make cocoa
// drop some events on the floor.
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
int stackSize = cocoaModalSessionStack.size();
for (int i=stackSize-1; i>=0; --i) {
@@ -927,7 +925,7 @@ void QCocoaEventDispatcherPrivate::cancelWaitForMoreEvents()
{
// In case the event dispatcher is waiting for more
// events somewhere, we post a dummy event to wake it up:
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
modifierFlags:0 timestamp:0. windowNumber:0 context:0
subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 4ece1b5a22..9dc013ba4d 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -53,7 +53,6 @@
#include <qvarlengtharray.h>
#include <stdlib.h>
#include <qabstracteventdispatcher.h>
-#include "qcocoaautoreleasepool.h"
#include <QDir>
#include <qpa/qplatformnativeinterface.h>
@@ -557,7 +556,7 @@ QCocoaFileDialogHelper::~QCocoaFileDialogHelper()
{
if (!mDelegate)
return;
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
[mDelegate release];
mDelegate = 0;
}
@@ -589,9 +588,6 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_filterSelected(int menuInd
emit filterSelected(menuIndex >= 0 && menuIndex < filters.size() ? filters.at(menuIndex) : QString());
}
-extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp
-extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp
-
void QCocoaFileDialogHelper::setDirectory(const QUrl &directory)
{
if (mDelegate)
@@ -687,7 +683,7 @@ bool QCocoaFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate()
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
const SharedPointerFileDialogOptions &opts = options();
const QList<QUrl> selectedFiles = opts->initiallySelectedFiles();
@@ -737,7 +733,7 @@ void QCocoaFileDialogHelper::exec()
// QEventLoop has been interrupted, and the second-most event loop has not
// yet been reactivated (regardless if [NSApp run] is still on the stack)),
// showing a native modal dialog will fail.
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if ([mDelegate runApplicationModalPanel])
emit accept();
else
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
index 5a241bc242..23266cfa79 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h
@@ -45,13 +45,13 @@ public:
QCocoaFontDialogHelper();
~QCocoaFontDialogHelper();
- void exec();
+ void exec() Q_DECL_OVERRIDE;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent);
- void hide();
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE;
+ void hide() Q_DECL_OVERRIDE;
- void setCurrentFont(const QFont &);
- QFont currentFont() const;
+ void setCurrentFont(const QFont &) Q_DECL_OVERRIDE;
+ QFont currentFont() const Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 2c8a3e39f3..fa6db018a7 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -50,22 +50,22 @@ public:
QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
~QCocoaGLContext();
- QSurfaceFormat format() const;
+ QSurfaceFormat format() const Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface);
+ void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- bool makeCurrent(QPlatformSurface *surface);
- void doneCurrent();
+ bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
- void (*getProcAddress(const QByteArray &procName)) ();
+ void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE;
void update();
static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format);
NSOpenGLContext *nsOpenGLContext() const;
- bool isSharing() const;
- bool isValid() const;
+ bool isSharing() const Q_DECL_OVERRIDE;
+ bool isValid() const Q_DECL_OVERRIDE;
void windowWasHidden();
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index a3c72c58b9..0f9b8b900d 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -33,7 +33,6 @@
#include "qcocoaglcontext.h"
#include "qcocoawindow.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoahelpers.h"
#include <qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
@@ -145,21 +144,27 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
if (m_format.renderableType() != QSurfaceFormat::OpenGL)
return;
- QCocoaAutoReleasePool pool; // For the SG Canvas render thread
+ QMacAutoReleasePool pool; // For the SG Canvas render thread
+ // create native context for the requested pixel format and share
NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(m_format));
m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
+ m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext];
- m_context = [NSOpenGLContext alloc];
- [m_context initWithFormat:pixelFormat shareContext:m_shareContext];
-
+ // retry without sharing on context creation failure.
if (!m_context && m_shareContext) {
- // try without shared context
m_shareContext = nil;
- [m_context initWithFormat:pixelFormat shareContext:nil];
+ m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+ if (m_context)
+ qWarning("QCocoaGLContext: Falling back to unshared context.");
}
+ // give up if we still did not get a native context
[pixelFormat release];
+ if (!m_context) {
+ qWarning("QCocoaGLContext: Failed to create context.");
+ return;
+ }
const GLint interval = format.swapInterval() >= 0 ? format.swapInterval() : 1;
[m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
@@ -218,7 +223,7 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
{
Q_ASSERT(surface->surface()->supportsOpenGL());
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
setActiveWindow(window);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 5f97e2996c..f51c21ee9b 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -33,7 +33,6 @@
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include <QtCore>
#include <QtGui>
@@ -270,10 +269,14 @@ bool operator<(const KeyPair &entry, const Qt::Key &key)
return entry.qtKey < key;
}
-static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2)
+struct qtKey2CocoaKeySortLessThan
{
- return entry1.qtKey < entry2.qtKey;
-}
+ typedef bool result_type;
+ Q_DECL_CONSTEXPR result_type operator()(const KeyPair &entry1, const KeyPair &entry2) const Q_DECL_NOTHROW
+ {
+ return entry1.qtKey < entry2.qtKey;
+ }
+};
static const int NumEntries = 59;
static const KeyPair entries[NumEntries] = {
@@ -353,7 +356,7 @@ QChar qt_mac_qtKey2CocoaKey(Qt::Key key)
mustInit = false;
for (int i=0; i<NumEntries; ++i)
rev_entries[i] = entries[i];
- std::sort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan);
+ std::sort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan());
}
const QVector<KeyPair>::iterator i
= std::lower_bound(rev_entries.begin(), rev_entries.end(), key);
@@ -619,7 +622,7 @@ QString qt_mac_applicationName()
if (appName.isEmpty()) {
QString arg0 = QGuiApplicationPrivate::instance()->appName();
if (arg0.contains("/")) {
- QStringList parts = arg0.split("/");
+ QStringList parts = arg0.split(QLatin1Char('/'));
appName = parts.at(parts.count() - 1);
} else {
appName = arg0;
@@ -630,11 +633,15 @@ QString qt_mac_applicationName()
int qt_mac_mainScreenHeight()
{
- QCocoaAutoReleasePool pool;
- // The first screen in the screens array is documented
- // to have the (0,0) origin.
- NSRect screenFrame = [[[NSScreen screens] firstObject] frame];
- return screenFrame.size.height;
+ 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.
+ NSRect screenFrame = [[screens objectAtIndex: 0] frame];
+ return screenFrame.size.height;
+ }
+ return 0;
}
int qt_mac_flipYCoordinate(int y)
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h
index abe45344a9..054c4795cb 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h
@@ -35,6 +35,7 @@
#define QCOCOAINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
+#include <QtCore/QLocale>
#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
@@ -46,9 +47,12 @@ public:
explicit QCocoaInputContext();
~QCocoaInputContext();
- virtual bool isValid() const { return true; }
+ bool isValid() const Q_DECL_OVERRIDE { return true; }
- virtual void reset();
+ void reset() Q_DECL_OVERRIDE;
+
+ QLocale locale() const Q_DECL_OVERRIDE { return m_locale; }
+ void updateLocale();
private Q_SLOTS:
void connectSignals();
@@ -56,6 +60,7 @@ private Q_SLOTS:
private:
QPointer<QWindow> mWindow;
+ QLocale m_locale;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
index c22fe8774b..7d01826ffe 100644
--- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm
@@ -34,9 +34,10 @@
#include "qnsview.h"
#include "qcocoainputcontext.h"
#include "qcocoanativeinterface.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoawindow.h"
+#include <Carbon/Carbon.h>
+
#include <QtCore/QRect>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
@@ -77,6 +78,7 @@ QCocoaInputContext::QCocoaInputContext()
, mWindow(QGuiApplication::focusWindow())
{
QMetaObject::invokeMethod(this, "connectSignals", Qt::QueuedConnection);
+ updateLocale();
}
QCocoaInputContext::~QCocoaInputContext()
@@ -98,7 +100,7 @@ void QCocoaInputContext::reset()
if (!view)
return;
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (NSTextInputContext *ctxt = [NSTextInputContext currentInputContext]) {
[ctxt discardMarkedText];
[view unmarkText];
@@ -117,4 +119,20 @@ void QCocoaInputContext::focusObjectChanged(QObject *focusObject)
mWindow = QGuiApplication::focusWindow();
}
+void QCocoaInputContext::updateLocale()
+{
+ TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
+ CFArrayRef languages = (CFArrayRef) TISGetInputSourceProperty(source, kTISPropertyInputSourceLanguages);
+ if (CFArrayGetCount(languages) > 0) {
+ CFStringRef langRef = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
+ QString name = QCFString::toQString(langRef);
+ QLocale locale(name);
+ if (m_locale != locale) {
+ m_locale = locale;
+ emitLocaleChanged();
+ }
+ CFRelease(langRef);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 8b5d78826c..e7e21c356a 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -36,7 +36,6 @@
#include <Cocoa/Cocoa.h>
-#include "qcocoaautoreleasepool.h"
#include "qcocoacursor.h"
#include "qcocoawindow.h"
#include "qcocoanativeinterface.h"
@@ -74,6 +73,7 @@ public:
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;
// ----------------------------------------------------
// Additional methods
@@ -98,34 +98,42 @@ public:
class QCocoaIntegration : public QPlatformIntegration
{
public:
- QCocoaIntegration();
+ enum Option {
+ UseFreeTypeFontEngine = 0x1
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ QCocoaIntegration(const QStringList &paramList);
~QCocoaIntegration();
static QCocoaIntegration *instance();
+ Options options() const;
- bool hasCapability(QPlatformIntegration::Capability cap) const;
- QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
#ifndef QT_NO_OPENGL
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
#endif
- QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const;
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
- QCoreTextFontDatabase *fontDatabase() const;
- QCocoaNativeInterface *nativeInterface() const;
- QCocoaInputContext *inputContext() const;
- QCocoaAccessibility *accessibility() const;
- QCocoaClipboard *clipboard() const;
- QCocoaDrag *drag() const;
+ QCoreTextFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QCocoaNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
+#ifndef QT_NO_ACCESSIBILITY
+ QCocoaAccessibility *accessibility() const Q_DECL_OVERRIDE;
+#endif
+ QCocoaClipboard *clipboard() const Q_DECL_OVERRIDE;
+ QCocoaDrag *drag() const Q_DECL_OVERRIDE;
- QStringList themeNames() const;
- QPlatformTheme *createPlatformTheme(const QString &name) const;
- QCocoaServices *services() const;
- QVariant styleHint(StyleHint hint) const;
+ 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;
- Qt::KeyboardModifiers queryKeyboardModifiers() const;
- QList<int> possibleKeys(const QKeyEvent *event) const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
+ QList<int> possibleKeys(const QKeyEvent *event) const Q_DECL_OVERRIDE;
void updateScreens();
QCocoaScreen *screenAtIndex(int index);
@@ -139,13 +147,14 @@ public:
QCocoaWindow *activePopupWindow() const;
QList<QCocoaWindow *> *popupWindowStack();
- void setApplicationIcon(const QIcon &icon) const;
+ void setApplicationIcon(const QIcon &icon) const Q_DECL_OVERRIDE;
private:
static QCocoaIntegration *mInstance;
+ Options mOptions;
QScopedPointer<QCoreTextFontDatabase> mFontDb;
- QScopedPointer<QCocoaInputContext> mInputContext;
+ QScopedPointer<QPlatformInputContext> mInputContext;
#ifndef QT_NO_ACCESSIBILITY
QScopedPointer<QCocoaAccessibility> mAccessibility;
#endif
@@ -161,6 +170,8 @@ private:
QList<QCocoaWindow *> m_popupWindowStack;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCocoaIntegration::Options)
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index c8f6dd05db..6bec6b191d 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -33,7 +33,6 @@
#include "qcocoaintegration.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoawindow.h"
#include "qcocoabackingstore.h"
#include "qcocoanativeinterface.h"
@@ -48,7 +47,9 @@
#include "qcocoamimetypes.h"
#include "qcocoaaccessibility.h"
+#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
#include <QtCore/qcoreapplication.h>
#include <IOKit/graphics/IOGraphicsLib.h>
@@ -137,11 +138,21 @@ void QCocoaScreen::updateGeometry()
qreal QCocoaScreen::devicePixelRatio() const
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
NSScreen * screen = osScreen();
return qreal(screen ? [screen backingScaleFactor] : 1.0);
}
+QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const
+{
+ QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
+ if (type == QPlatformScreen::Subpixel_None) {
+ // Every OSX machine has RGB pixels unless a peculiar or rotated non-Apple screen is attached
+ type = QPlatformScreen::Subpixel_RGB;
+ }
+ return type;
+}
+
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
NSPoint screenPoint = qt_mac_flipPoint(point);
@@ -244,11 +255,25 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height
return windowPixmap;
}
+static QCocoaIntegration::Options parseOptions(const QStringList &paramList)
+{
+ QCocoaIntegration::Options options;
+ foreach (const QString &param, paramList) {
+#ifndef QT_NO_FREETYPE
+ if (param == QLatin1String("fontengine=freetype"))
+ options |= QCocoaIntegration::UseFreeTypeFontEngine;
+ else
+#endif
+ qWarning() << "Unknown option" << param;
+ }
+ return options;
+}
+
QCocoaIntegration *QCocoaIntegration::mInstance = 0;
-QCocoaIntegration::QCocoaIntegration()
- : mFontDb(new QCoreTextFontDatabase())
- , mInputContext(new QCocoaInputContext)
+QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
+ : mOptions(parseOptions(paramList))
+ , mFontDb(new QCoreTextFontDatabase(mOptions.testFlag(UseFreeTypeFontEngine)))
#ifndef QT_NO_ACCESSIBILITY
, mAccessibility(new QCocoaAccessibility)
#endif
@@ -262,8 +287,12 @@ QCocoaIntegration::QCocoaIntegration()
qWarning("Creating multiple Cocoa platform integrations is not supported");
mInstance = this;
+ QString icStr = QPlatformInputContextFactory::requested();
+ icStr.isNull() ? mInputContext.reset(new QCocoaInputContext)
+ : mInputContext.reset(QPlatformInputContextFactory::create(icStr));
+
initResources();
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
qApp->setAttribute(Qt::AA_DontUseNativeMenuBar, false);
@@ -314,7 +343,7 @@ QCocoaIntegration::~QCocoaIntegration()
qt_resetNSApplicationSendEvent();
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
// remove the apple event handlers installed by QCocoaApplicationDelegate
QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
@@ -342,6 +371,11 @@ QCocoaIntegration *QCocoaIntegration::instance()
return mInstance;
}
+QCocoaIntegration::Options QCocoaIntegration::options() const
+{
+ return mOptions;
+}
+
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted ones
*/
@@ -463,19 +497,17 @@ QCocoaNativeInterface *QCocoaIntegration::nativeInterface() const
return mNativeInterface.data();
}
-QCocoaInputContext *QCocoaIntegration::inputContext() const
+QPlatformInputContext *QCocoaIntegration::inputContext() const
{
return mInputContext.data();
}
+#ifndef QT_NO_ACCESSIBILITY
QCocoaAccessibility *QCocoaIntegration::accessibility() const
{
-#ifndef QT_NO_ACCESSIBILITY
return mAccessibility.data();
-#else
- return 0;
-#endif
}
+#endif
QCocoaClipboard *QCocoaIntegration::clipboard() const
{
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index 59807deb5a..eccc5230b5 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -49,29 +49,29 @@ public:
QCocoaMenu();
~QCocoaMenu();
- inline virtual void setTag(quintptr tag)
- { m_tag = tag; }
- inline virtual quintptr tag() const
- { return m_tag; }
-
- void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before);
- void removeMenuItem(QPlatformMenuItem *menuItem);
- void syncMenuItem(QPlatformMenuItem *menuItem);
- void setEnabled(bool enabled);
- bool isEnabled() const;
- void setVisible(bool visible);
- void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item);
- void dismiss();
-
- void syncSeparatorsCollapsible(bool enable);
+ void setTag(quintptr tag) Q_DECL_OVERRIDE
+ { m_tag = tag; }
+ quintptr tag() const Q_DECL_OVERRIDE
+ { return m_tag; }
+
+ 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 syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE;
void syncModalState(bool modal);
- virtual void setIcon(const QIcon &icon) { Q_UNUSED(icon) }
+ void setIcon(const QIcon &icon) Q_DECL_OVERRIDE { Q_UNUSED(icon) }
- void setText(const QString &text);
- void setMinimumWidth(int width);
- void setFont(const QFont &font);
+ void setText(const QString &text) Q_DECL_OVERRIDE;
+ void setMinimumWidth(int width) Q_DECL_OVERRIDE;
+ void setFont(const QFont &font) Q_DECL_OVERRIDE;
inline NSMenu *nsMenu() const
{ return m_nativeMenu; }
@@ -80,8 +80,8 @@ public:
inline bool isVisible() const { return m_visible; }
- virtual QPlatformMenuItem *menuItemAt(int position) const;
- virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const;
+ QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
QList<QCocoaMenuItem *> items() const;
QList<QCocoaMenuItem *> merged() const;
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index a6157bdc3a..aa7a09805a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -34,7 +34,6 @@
#include "qcocoamenu.h"
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include <QtCore/QtDebug>
#include <QtCore/qmetaobject.h>
@@ -235,7 +234,7 @@ QCocoaMenu::QCocoaMenu() :
m_menuBar(0),
m_containingMenuItem(0)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
m_delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this];
m_nativeItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
@@ -255,7 +254,7 @@ QCocoaMenu::~QCocoaMenu()
if (m_containingMenuItem)
m_containingMenuItem->clearMenu(this);
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
[m_nativeItem setSubmenu:nil];
[m_nativeMenu release];
[m_delegate release];
@@ -264,7 +263,7 @@ QCocoaMenu::~QCocoaMenu()
void QCocoaMenu::setText(const QString &text)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QString stripped = qt_mac_removeAmpersandEscapes(text);
[m_nativeMenu setTitle:QCFString::toNSString(stripped)];
[m_nativeItem setTitle:QCFString::toNSString(stripped)];
@@ -286,7 +285,7 @@ void QCocoaMenu::setFont(const QFont &font)
void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
QCocoaMenuItem *beforeItem = static_cast<QCocoaMenuItem *>(before);
@@ -340,7 +339,7 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
if (!m_menuItems.contains(cocoaItem)) {
qWarning() << Q_FUNC_INFO << "Menu does not contain the item to be removed";
@@ -370,7 +369,7 @@ QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const
void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
if (!m_menuItems.contains(cocoaItem)) {
qWarning() << Q_FUNC_INFO << "Item does not belong to this menu";
@@ -399,7 +398,7 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
void QCocoaMenu::syncSeparatorsCollapsible(bool enable)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (enable) {
bool previousIsSeparator = true; // setting to true kills all the separators placed at the top.
NSMenuItem *previousItem = nil;
@@ -457,7 +456,7 @@ void QCocoaMenu::setVisible(bool visible)
void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QPoint pos = QPoint(targetRect.left(), targetRect.top() + targetRect.height());
QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0;
@@ -583,7 +582,7 @@ QList<QCocoaMenuItem *> QCocoaMenu::merged() const
void QCocoaMenu::syncModalState(bool modal)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (!m_enabled)
modal = true;
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h
index b5ee21ca52..d5f75abf34 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.h
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.h
@@ -48,13 +48,13 @@ class QCocoaMenuBar : public QPlatformMenuBar
Q_OBJECT
public:
QCocoaMenuBar();
- virtual ~QCocoaMenuBar();
+ ~QCocoaMenuBar();
- virtual void insertMenu(QPlatformMenu *menu, QPlatformMenu* before);
- virtual void removeMenu(QPlatformMenu *menu);
- virtual void syncMenu(QPlatformMenu *menuItem);
- virtual void handleReparent(QWindow *newParentWindow);
- virtual QPlatformMenu *menuForTag(quintptr tag) const;
+ 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;
inline NSMenu *nsMenu() const
{ return m_nativeMenu; }
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 764a01370d..7775cdbde6 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -37,7 +37,7 @@
#include "qcocoawindow.h"
#include "qcocoamenuloader.h"
#include "qcocoaapplication.h" // for custom application category
-#include "qcocoaautoreleasepool.h"
+#include "qcocoaapplicationdelegate.h"
#include <QtGui/QGuiApplication>
#include <QtCore/QDebug>
@@ -83,7 +83,7 @@ QCocoaMenuBar::~QCocoaMenuBar()
void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (beforeMenu) {
NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()];
@@ -126,7 +126,7 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor
void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (menu->menuBar() == this)
menu->setMenuBar(0);
@@ -147,7 +147,7 @@ void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu)
void QCocoaMenuBar::syncMenu(QPlatformMenu *menu)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenu *cocoaMenu = static_cast<QCocoaMenu *>(menu);
Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items())
@@ -260,13 +260,26 @@ void QCocoaMenuBar::resetKnownMenuItemsToQt()
void QCocoaMenuBar::updateMenuBarImmediately()
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenuBar *mb = findGlobalMenubar();
QCocoaWindow *cw = findWindowForMenubar();
QWindow *win = cw ? cw->window() : 0;
- if (win && (win->flags() & Qt::Popup) == Qt::Popup)
- return; // context menus, comboboxes, etc. don't need to update the menubar
+ if (win && (win->flags() & Qt::Popup) == Qt::Popup) {
+ // context menus, comboboxes, etc. don't need to update the menubar,
+ // but if an application has only Qt::Tool window(s) on start,
+ // we still have to update the menubar.
+ if ((win->flags() & Qt::WindowType_Mask) != Qt::Tool)
+ return;
+ typedef QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) AppDelegate;
+ NSApplication *app = [NSApplication sharedApplication];
+ if (![app.delegate isKindOfClass:[AppDelegate class]])
+ return;
+ // We apply this logic _only_ during the startup.
+ AppDelegate *appDelegate = app.delegate;
+ if (!appDelegate.inLaunch)
+ return;
+ }
if (cw && cw->menubar())
mb = cw->menubar();
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index 5c85824ab8..289f38fd18 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -60,27 +60,27 @@ class QCocoaMenuItem : public QPlatformMenuItem
{
public:
QCocoaMenuItem();
- virtual ~QCocoaMenuItem();
+ ~QCocoaMenuItem();
- inline virtual void setTag(quintptr tag)
+ void setTag(quintptr tag) Q_DECL_OVERRIDE
{ m_tag = tag; }
- inline virtual quintptr tag() const
+ quintptr tag() const Q_DECL_OVERRIDE
{ return m_tag; }
- void setText(const QString &text);
- void setIcon(const QIcon &icon);
- void setMenu(QPlatformMenu *menu);
- void setVisible(bool isVisible);
- void setIsSeparator(bool isSeparator);
- void setFont(const QFont &font);
- void setRole(MenuRole role);
- void setShortcut(const QKeySequence& shortcut);
- void setCheckable(bool checkable) { Q_UNUSED(checkable) }
- void setChecked(bool isChecked);
- void setEnabled(bool isEnabled);
- void setIconSize(int size);
-
- void setNativeContents(WId item);
+ 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 setShortcut(const QKeySequence& shortcut) Q_DECL_OVERRIDE;
+ 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 setNativeContents(WId item) Q_DECL_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 f288ab85c0..0fc1bff325 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -37,7 +37,6 @@
#include "qcocoamenubar.h"
#include "messages.h"
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include "qt_mac_p.h"
#include "qcocoaapplication.h" // for custom application category
#include "qcocoamenuloader.h"
@@ -104,7 +103,7 @@ QCocoaMenuItem::QCocoaMenuItem() :
QCocoaMenuItem::~QCocoaMenuItem()
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
SET_COCOA_MENU_ANCESTOR(m_menu, 0);
@@ -139,7 +138,7 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
m_menu->setContainingMenuItem(0);
}
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
m_menu = static_cast<QCocoaMenu *>(menu);
if (m_menu) {
SET_COCOA_MENU_ANCESTOR(m_menu, this);
@@ -198,6 +197,8 @@ void QCocoaMenuItem::setEnabled(bool enabled)
void QCocoaMenuItem::setNativeContents(WId item)
{
NSView *itemView = (NSView *)item;
+ if (m_itemView == itemView)
+ return;
[m_itemView release];
m_itemView = [itemView retain];
[m_itemView setAutoresizesSubviews:YES];
@@ -302,8 +303,8 @@ NSMenuItem *QCocoaMenuItem::sync()
if (!m_native) {
m_native = [[NSMenuItem alloc] initWithTitle:QCFString::toNSString(m_text)
- action:nil
- keyEquivalent:@""];
+ action:nil
+ keyEquivalent:@""];
[m_native setTag:reinterpret_cast<NSInteger>(this)];
}
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 2250f7c084..d018c05635 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -67,6 +67,8 @@ public:
static void *nsOpenGLContextForContext(QOpenGLContext* context);
#endif
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_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 205a49d25a..41ea1fa49c 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -58,6 +58,8 @@
#include <qpa/qplatformprintersupport.h>
#endif
+#include <QtPlatformHeaders/qcocoawindowfunctions.h>
+
#include <Cocoa/Cocoa.h>
QT_BEGIN_NAMESPACE
@@ -217,6 +219,14 @@ void *QCocoaNativeInterface::nsOpenGLContextForContext(QOpenGLContext* context)
}
#endif
+QFunctionPointer QCocoaNativeInterface::platformFunction(const QByteArray &function) const
+{
+ if (function == QCocoaWindowFunctions::bottomLeftClippedByNSWindowOffsetIdentifier())
+ return QFunctionPointer(QCocoaWindowFunctions::BottomLeftClippedByNSWindowOffset(QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic));
+
+ return Q_NULLPTR;
+}
+
void QCocoaNativeInterface::addToMimeList(void *macPasteboardMime)
{
qt_mac_addToGlobalMimeList(reinterpret_cast<QMacInternalPasteboardMime *>(macPasteboardMime));
@@ -234,7 +244,7 @@ void QCocoaNativeInterface::registerDraggedTypes(const QStringList &types)
void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaMenu *cocoaPlatformMenu = static_cast<QCocoaMenu *>(platformMenu);
NSMenu *menu = cocoaPlatformMenu->nsMenu();
[NSApp QT_MANGLE_NAMESPACE(qt_setDockMenu): menu];
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index 4d319e149b..b0d04f6f82 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -100,7 +100,7 @@ QCocoaPrintDevice::~QCocoaPrintDevice()
{
if (m_ppd)
ppdClose(m_ppd);
- foreach (PMPaper paper, m_macPapers.values())
+ foreach (PMPaper paper, m_macPapers)
PMRelease(paper);
// Releasing the session appears to also release the printer
if (m_session)
@@ -154,7 +154,7 @@ QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const
void QCocoaPrintDevice::loadPageSizes() const
{
m_pageSizes.clear();
- foreach (PMPaper paper, m_macPapers.values())
+ foreach (PMPaper paper, m_macPapers)
PMRelease(paper);
m_macPapers.clear();
m_printableMargins.clear();
diff --git a/src/plugins/platforms/cocoa/qcocoaservices.h b/src/plugins/platforms/cocoa/qcocoaservices.h
index 331fe810fa..1a447c6242 100644
--- a/src/plugins/platforms/cocoa/qcocoaservices.h
+++ b/src/plugins/platforms/cocoa/qcocoaservices.h
@@ -41,8 +41,8 @@ QT_BEGIN_NAMESPACE
class QCocoaServices : public QPlatformServices
{
public:
- bool openUrl(const QUrl &url);
- bool openDocument(const QUrl &url);
+ bool openUrl(const QUrl &url) Q_DECL_OVERRIDE;
+ bool openDocument(const QUrl &url) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 65cc9bc38b..93f8b2ba6f 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -33,7 +33,6 @@
#include "qcocoasystemsettings.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoahelpers.h"
#include <QtCore/private/qcore_mac_p.h>
@@ -45,7 +44,7 @@ QT_BEGIN_NAMESPACE
QColor qt_mac_colorForTheme(ThemeBrush brush)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCFType<CGColorRef> cgClr = 0;
HIThemeBrushCreateCGColor(brush, &cgClr);
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
index b5f038094f..cdfd92c0aa 100755..100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
@@ -51,17 +51,17 @@ class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon
public:
QCocoaSystemTrayIcon() : m_sys(0) {}
- virtual void init();
- virtual void cleanup();
- virtual void updateIcon(const QIcon &icon);
- virtual void updateToolTip(const QString &toolTip);
- virtual void updateMenu(QPlatformMenu *menu);
- virtual QRect geometry() const;
- virtual void showMessage(const QString &title, const QString &msg,
- const QIcon& icon, MessageIcon iconType, int secs);
+ 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 showMessage(const QString &title, const QString &msg,
+ const QIcon& icon, MessageIcon iconType, int secs) Q_DECL_OVERRIDE;
- virtual bool isSystemTrayAvailable() const;
- virtual bool supportsMessages() const;
+ bool isSystemTrayAvailable() const Q_DECL_OVERRIDE;
+ bool supportsMessages() const Q_DECL_OVERRIDE;
private:
QSystemTrayIconSys *m_sys;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 713758cc7e..a3ffb5be66 100755..100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -252,6 +252,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
}
NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap));
+ [nsimage setTemplate:icon.isMask()];
[(NSImageView*)[[m_sys->item item] view] setImage: nsimage];
[nsimage release];
}
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 11749e14de..4b73d0af08 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -47,7 +47,6 @@
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include <QtCore/qfileinfo.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -253,7 +252,7 @@ QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &siz
QPlatformTheme::IconOptions iconOptions) const
{
Q_UNUSED(iconOptions);
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFile:QCFString::toNSString(fileInfo.canonicalFilePath())];
if (!iconImage)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 455d4a8580..05e6cf3c9e 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -227,6 +227,9 @@ public:
void updateExposedGeometry();
QWindow *childWindowAt(QPoint windowPoint);
bool shouldRefuseKeyWindowAndFirstResponder();
+
+ static QPoint bottomLeftClippedByNSWindowOffsetStatic(QWindow *window);
+ QPoint bottomLeftClippedByNSWindowOffset() const;
protected:
void recreateWindow(const QPlatformWindow *parentWindow);
QCocoaNSWindow *createNSWindow();
@@ -234,7 +237,7 @@ protected:
bool shouldUseNSPanel();
- QRect windowGeometry() const;
+ QRect nativeWindowGeometry() const;
QCocoaWindow *parentCocoaWindow() const;
void syncWindowState(Qt::WindowState newState);
void reinsertChildWindow(QCocoaWindow *child);
@@ -245,6 +248,8 @@ public: // for QNSView
friend class QCocoaBackingStore;
friend class QCocoaNativeInterface;
+ void removeMonitor();
+
NSView *m_contentView;
QNSView *m_qtView;
QCocoaNSWindow *m_nsWindow;
@@ -265,10 +270,10 @@ public: // for QNSView
QPointer<QWindow> m_enterLeaveTargetWindow;
bool m_windowUnderMouse;
- bool m_ignoreWindowShouldClose;
bool m_inConstructor;
bool m_inSetVisible;
bool m_inSetGeometry;
+ bool m_inSetStyleMask;
#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 809acdd87e..a545dbddd5 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -33,7 +33,6 @@
#include "qcocoawindow.h"
#include "qcocoaintegration.h"
#include "qnswindowdelegate.h"
-#include "qcocoaautoreleasepool.h"
#include "qcocoaeventdispatcher.h"
#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
@@ -346,10 +345,10 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_synchedWindowState(Qt::WindowActive)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
- , m_ignoreWindowShouldClose(false)
, m_inConstructor(true)
, m_inSetVisible(false)
, m_inSetGeometry(false)
+ , m_inSetStyleMask(false)
#ifndef QT_NO_OPENGL
, m_glContext(0)
#endif
@@ -373,7 +372,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QCocoaWindow::QCocoaWindow" << this;
#endif
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (tlw->type() == Qt::ForeignWindow) {
NSView *foreignView = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>());
@@ -409,7 +408,7 @@ QCocoaWindow::~QCocoaWindow()
qDebug() << "QCocoaWindow::~QCocoaWindow" << this;
#endif
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
[m_nsWindow setContentView:nil];
[m_nsWindow.helper detachFromPlatformWindow];
if (m_isNSWindowChild) {
@@ -419,6 +418,8 @@ QCocoaWindow::~QCocoaWindow()
[m_contentView removeFromSuperview];
}
+ removeMonitor();
+
// Make sure to disconnect observer in all case if view is valid
// to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute
if (m_qtView) {
@@ -499,7 +500,7 @@ QRect QCocoaWindow::geometry() const
void QCocoaWindow::setCocoaGeometry(const QRect &rect)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (m_contentViewIsEmbedded) {
QPlatformWindow::setGeometry(rect);
@@ -604,7 +605,7 @@ void QCocoaWindow::show(bool becauseOfAncestor)
&& !m_hiddenByClipping) { // ... NOR clipped
if (m_isNSWindowChild) {
m_hiddenByAncestor = false;
- setCocoaGeometry(window()->geometry());
+ setCocoaGeometry(windowGeometry());
}
if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status
[m_nsWindow orderFront:nil];
@@ -623,7 +624,7 @@ void QCocoaWindow::setVisible(bool visible)
m_inSetVisible = true;
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QCocoaWindow *parentCocoaWindow = 0;
if (window()->transientParent())
parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle());
@@ -643,7 +644,7 @@ void QCocoaWindow::setVisible(bool visible)
if (parentCocoaWindow) {
// The parent window might have moved while this window was hidden,
// update the window geometry if there is a parent.
- setGeometry(window()->geometry());
+ setGeometry(windowGeometry());
if (window()->type() == Qt::Popup) {
// QTBUG-30266: a window should not be resizable while a transient popup is open
@@ -696,6 +697,7 @@ void QCocoaWindow::setVisible(bool visible)
&& [m_nsWindow isKindOfClass:[NSPanel class]]) {
[(NSPanel *)m_nsWindow setWorksWhenModal:YES];
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]);
QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
@@ -744,10 +746,7 @@ void QCocoaWindow::setVisible(bool visible)
} else {
[m_contentView setHidden:YES];
}
- if (monitor && window()->type() == Qt::Popup) {
- [NSEvent removeMonitor:monitor];
- monitor = nil;
- }
+ removeMonitor();
if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
@@ -861,8 +860,8 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
// no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected
// that the button would be removed in the latter case, but disabling it is more
// in line with the platform style guidelines.
- bool fixedSizeNoZoom = (window()->minimumSize().isValid() && window()->maximumSize().isValid()
- && window()->minimumSize() == window()->maximumSize());
+ bool fixedSizeNoZoom = (windowMinimumSize().isValid() && windowMaximumSize().isValid()
+ && windowMinimumSize() == windowMaximumSize());
bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint) && !(flags & Qt::WindowMaximizeButtonHint));
[[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)];
}
@@ -872,20 +871,27 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
if (m_nsWindow && !m_isNSWindowChild) {
NSUInteger styleMask = windowStyleMask(flags);
NSInteger level = this->windowLevel(flags);
+ // While setting style mask we can have -updateGeometry calls on a content
+ // view with null geometry, reporting an invalid coordinates as a result.
+ m_inSetStyleMask = true;
[m_nsWindow setStyleMask:styleMask];
+ m_inSetStyleMask = false;
[m_nsWindow setLevel:level];
setWindowShadow(flags);
- if (!(styleMask & NSBorderlessWindowMask)) {
+ if (!(flags & Qt::FramelessWindowHint)) {
setWindowTitle(window()->title());
}
Qt::WindowType type = window()->type();
if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior];
- if (flags & Qt::WindowFullscreenButtonHint)
+ if (flags & Qt::WindowFullscreenButtonHint) {
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
- else
+ behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
+ } else {
+ behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
+ }
[m_nsWindow setCollectionBehavior:behavior];
}
setWindowZoomButton(flags);
@@ -902,7 +908,7 @@ void QCocoaWindow::setWindowState(Qt::WindowState state)
void QCocoaWindow::setWindowTitle(const QString &title)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (!m_nsWindow)
return;
@@ -913,7 +919,7 @@ void QCocoaWindow::setWindowTitle(const QString &title)
void QCocoaWindow::setWindowFilePath(const QString &filePath)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (!m_nsWindow)
return;
@@ -923,7 +929,7 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
void QCocoaWindow::setWindowIcon(const QIcon &icon)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
if (iconButton == nil) {
@@ -1041,26 +1047,26 @@ bool QCocoaWindow::isOpaque() const
void QCocoaWindow::propagateSizeHints()
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
if (!m_nsWindow)
return;
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QCocoaWindow::propagateSizeHints" << this;
- qDebug() << " min/max " << window()->minimumSize() << window()->maximumSize();
- qDebug() << "size increment" << window()->sizeIncrement();
- qDebug() << " basesize" << window()->baseSize();
- qDebug() << " geometry" << geometry();
+ qDebug() << " min/max" << windowMinimumSize() << windowMaximumSize();
+ qDebug() << "size increment" << windowSizeIncrement();
+ qDebug() << " basesize" << windowBaseSize();
+ qDebug() << " geometry" << windowGeometry();
#endif
// Set the minimum content size.
- const QSize minimumSize = window()->minimumSize();
+ const QSize minimumSize = windowMinimumSize();
if (!minimumSize.isValid()) // minimumSize is (-1, -1) when not set. Make that (0, 0) for Cocoa.
[m_nsWindow setContentMinSize : NSMakeSize(0.0, 0.0)];
[m_nsWindow setContentMinSize : NSMakeSize(minimumSize.width(), minimumSize.height())];
// Set the maximum content size.
- const QSize maximumSize = window()->maximumSize();
+ const QSize maximumSize = windowMaximumSize();
[m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())];
// The window may end up with a fixed size; in this case the zoom button should be disabled.
@@ -1068,13 +1074,14 @@ void QCocoaWindow::propagateSizeHints()
// sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be
// resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case.
- if (!window()->sizeIncrement().isEmpty())
- [m_nsWindow setResizeIncrements : qt_mac_toNSSize(window()->sizeIncrement())];
+ const QSize sizeIncrement = windowSizeIncrement();
+ if (!sizeIncrement.isEmpty())
+ [m_nsWindow setResizeIncrements : qt_mac_toNSSize(sizeIncrement)];
else
[m_nsWindow setResizeIncrements : NSMakeSize(1.0, 1.0)];
QRect rect = geometry();
- QSize baseSize = window()->baseSize();
+ QSize baseSize = windowBaseSize();
if (!baseSize.isNull() && baseSize.isValid()) {
[m_nsWindow setFrame:NSMakeRect(rect.x(), rect.y(), baseSize.width(), baseSize.height()) display:YES];
}
@@ -1211,9 +1218,10 @@ void QCocoaWindow::windowDidEndLiveResize()
bool QCocoaWindow::windowShouldClose()
{
- // might have been set from qnsview.mm
- if (m_ignoreWindowShouldClose)
- return false;
+ // This callback should technically only determine if the window
+ // should (be allowed to) close, but since our QPA API to determine
+ // that also involves actually closing the window we do both at the
+ // same time, instead of doing the latter in windowWillClose.
bool accepted = false;
QWindowSystemInterface::handleCloseEvent(window(), &accepted);
QWindowSystemInterface::flushWindowSystemEvents();
@@ -1320,7 +1328,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
| NSWindowCollectionBehaviorFullScreenAuxiliary;
m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone;
m_nsWindow.collectionBehavior = collectionBehavior;
- setCocoaGeometry(window()->geometry());
+ setCocoaGeometry(windowGeometry());
QList<QCocoaWindow *> &siblings = m_parentCocoaWindow->m_childWindows;
if (siblings.contains(this)) {
@@ -1334,7 +1342,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
} else {
// Child windows have no NSWindow, link the NSViews instead.
[m_parentCocoaWindow->m_contentView addSubview : m_contentView];
- QRect rect = window()->geometry();
+ QRect rect = windowGeometry();
// Prevent setting a (0,0) window size; causes opengl context
// "Invalid Drawable" warnings.
if (rect.isNull())
@@ -1387,9 +1395,9 @@ bool QCocoaWindow::shouldUseNSPanel()
QCocoaNSWindow * QCocoaWindow::createNSWindow()
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
- QRect rect = initialGeometry(window(), window()->geometry(), defaultWindowWidth, defaultWindowHeight);
+ QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight);
NSRect frame = qt_mac_flipRect(rect);
Qt::WindowType type = window()->type();
@@ -1476,8 +1484,16 @@ void QCocoaWindow::removeChildWindow(QCocoaWindow *child)
[m_nsWindow removeChildWindow:child->m_nsWindow];
}
+void QCocoaWindow::removeMonitor()
+{
+ if (!monitor)
+ return;
+ [NSEvent removeMonitor:monitor];
+ monitor = nil;
+}
+
// Returns the current global screen geometry for the nswindow associated with this window.
-QRect QCocoaWindow::windowGeometry() const
+QRect QCocoaWindow::nativeWindowGeometry() const
{
if (!m_nsWindow || m_isNSWindowChild)
return geometry();
@@ -1560,7 +1576,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
if (m_normalGeometry.width() < 0) {
m_oldWindowFlags = m_windowFlags;
window()->setFlags(window()->flags() | Qt::FramelessWindowHint);
- m_normalGeometry = windowGeometry();
+ m_normalGeometry = nativeWindowGeometry();
setGeometry(screen->geometry());
m_presentationOptions = [NSApp presentationOptions];
[NSApp setPresentationOptions : m_presentationOptions | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock];
@@ -1827,6 +1843,24 @@ bool QCocoaWindow::shouldRefuseKeyWindowAndFirstResponder()
return false;
}
+QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic(QWindow *window)
+{
+ if (window->handle())
+ return static_cast<QCocoaWindow *>(window->handle())->bottomLeftClippedByNSWindowOffset();
+ return QPoint();
+}
+
+QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffset() const
+{
+ if (!m_contentView)
+ return QPoint();
+ const NSPoint origin = [m_contentView isFlipped] ? NSMakePoint(0, [m_contentView frame].size.height)
+ : NSMakePoint(0, 0);
+ const NSRect visibleRect = [m_contentView visibleRect];
+
+ return QPoint(visibleRect.origin.x, -visibleRect.origin.y + (origin.y - visibleRect.size.height));
+}
+
QMargins QCocoaWindow::frameMargins() const
{
NSRect frameW = [m_nsWindow frame];
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index 3d88a8d5df..f4fd32ffd1 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -43,7 +43,6 @@
#include <stdlib.h>
#include <string.h>
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
QT_BEGIN_NAMESPACE
@@ -555,7 +554,7 @@ QMacPasteboard::sync() const
QString qt_mac_get_pasteboardString(PasteboardRef paste)
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
NSPasteboard *pb = nil;
CFStringRef pbname;
if (PasteboardCopyName(paste, &pbname) == noErr) {
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 6e7ebcc37c..6099add6bb 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -173,7 +173,7 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
if (_touchCount != _currentTouches.size()) {
// Remove all instances, and basically start from scratch:
touchPoints.clear();
- foreach (QCocoaTouch *qcocoaTouch, _currentTouches.values()) {
+ foreach (QCocoaTouch *qcocoaTouch, _currentTouches) {
if (!_updateInternalStateOnly) {
qcocoaTouch->_touchPoint.state = Qt::TouchPointReleased;
touchPoints.insert(qcocoaTouch->_touchPoint.id, qcocoaTouch->_touchPoint);
@@ -190,7 +190,7 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
// touch now (and refake a begin for it later, if needed).
if (_updateInternalStateOnly && !wasUpdateInternalStateOnly && !_currentTouches.isEmpty()) {
- QCocoaTouch *qcocoaTouch = _currentTouches.values().first();
+ QCocoaTouch *qcocoaTouch = _currentTouches.cbegin().value();
qcocoaTouch->_touchPoint.state = Qt::TouchPointReleased;
touchPoints.insert(qcocoaTouch->_touchPoint.id, qcocoaTouch->_touchPoint);
// Since this last touch also will end up being the first
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 14a61554a3..50b456cab7 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -75,7 +75,10 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
bool m_resendKeyEvent;
bool m_scrolling;
+ bool m_updatingDrag;
bool m_exposedOnMoveToWindow;
+ NSEvent *m_currentlyInterpretedKeyEvent;
+ bool m_isMenuView;
}
- (id)init;
@@ -93,8 +96,10 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)notifyWindowStateChanged:(Qt::WindowState)newState;
- (void)windowNotification : (NSNotification *) windowNotification;
- (void)notifyWindowWillZoom:(BOOL)willZoom;
+- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
- (void)viewDidHide;
- (void)viewDidUnhide;
+- (void)removeFromSuperview;
- (BOOL)isFlipped;
- (BOOL)acceptsFirstResponder;
@@ -131,7 +136,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
-- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
- (void)registerDragTypes;
- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 1ec33df744..3faa292ae0 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -39,9 +39,9 @@
#include "qnsview.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
-#include "qcocoaautoreleasepool.h"
#include "qmultitouch_mac_p.h"
#include "qcocoadrag.h"
+#include "qcocoainputcontext.h"
#include <qpa/qplatformintegration.h>
#include <qpa/qwindowsysteminterface.h>
@@ -153,6 +153,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self];
m_resendKeyEvent = false;
m_scrolling = false;
+ m_updatingDrag = false;
+ m_currentlyInterpretedKeyEvent = 0;
if (!touchDevice) {
touchDevice = new QTouchDevice;
@@ -160,6 +162,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition | QTouchDevice::MouseEmulation);
QWindowSystemInterface::registerTouchDevice(touchDevice);
}
+
+ m_isMenuView = false;
}
return self;
}
@@ -213,6 +217,11 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
name:NSViewFrameDidChangeNotification
object:self];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+
return self;
}
@@ -269,11 +278,11 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void)viewDidMoveToWindow
{
+ m_isMenuView = [self.window.className isEqualToString:@"NSCarbonMenuWindow"];
if (self.window) {
// This is the case of QWidgetAction's generated QWidget inserted in an NSMenu.
// 10.9 and newer get the NSWindowDidChangeOcclusionStateNotification
- if ((!_q_NSWindowDidChangeOcclusionStateNotification
- && [self.window.className isEqualToString:@"NSCarbonMenuWindow"])) {
+ if (!_q_NSWindowDidChangeOcclusionStateNotification && m_isMenuView) {
m_exposedOnMoveToWindow = true;
m_platformWindow->exposeWindow();
}
@@ -347,6 +356,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry())
return;
+ // It can happen that self.window is nil (if we are changing
+ // styleMask from/to borderless and content view is being re-parented)
+ // - this results in an invalid coordinates.
+ if (m_platformWindow->m_inSetStyleMask && !self.window)
+ return;
+
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry;
#endif
@@ -396,7 +411,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
NSString *notificationName = [windowNotification name];
if (notificationName == NSWindowDidBecomeKeyNotification) {
- if (!m_platformWindow->windowIsPopupType())
+ if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
QWindowSystemInterface::handleWindowActivated(m_window);
} else if (notificationName == NSWindowDidResignKeyNotification) {
// key window will be non-nil if another window became key... do not
@@ -405,7 +420,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
NSWindow *keyWindow = [NSApp keyWindow];
if (!keyWindow) {
// no new key window, go ahead and set the active window to zero
- if (!m_platformWindow->windowIsPopupType())
+ if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
QWindowSystemInterface::handleWindowActivated(0);
}
} else if (notificationName == NSWindowDidMiniaturizeNotification
@@ -456,6 +471,15 @@ QT_WARNING_POP
}
}
+- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification
+{
+ Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
+ if (([NSApp keyWindow] == [self window]) && [[self window] firstResponder] == self) {
+ QCocoaInputContext *ic = qobject_cast<QCocoaInputContext *>(QCocoaIntegration::instance()->inputContext());
+ ic->updateLocale();
+ }
+}
+
- (void)notifyWindowWillZoom:(BOOL)willZoom
{
Qt::WindowState newState = willZoom ? Qt::WindowMaximized : Qt::WindowNoState;
@@ -474,6 +498,12 @@ QT_WARNING_POP
m_platformWindow->exposeWindow();
}
+- (void)removeFromSuperview
+{
+ QMacAutoReleasePool pool;
+ [super removeFromSuperview];
+}
+
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore;
@@ -615,13 +645,15 @@ QT_WARNING_POP
{
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
return NO;
- if (!m_platformWindow->windowIsPopupType())
+ if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
return YES;
}
- (BOOL)acceptsFirstResponder
{
+ if (m_isMenuView)
+ return NO;
if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
return NO;
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
@@ -852,7 +884,7 @@ QT_WARNING_POP
{
[super updateTrackingAreas];
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
// NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early
if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea])
@@ -1435,41 +1467,42 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff))
text = QCFString::toQString(characters);
- QWindow *focusWindow = [self topLevelWindow];
+ QWindow *window = [self topLevelWindow];
+
+ // Popups implicitly grab key events; forward to the active popup if there is one.
+ // This allows popups to e.g. intercept shortcuts and close the popup in response.
+ if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
+ if (!popup->m_windowFlags.testFlag(Qt::ToolTip))
+ window = popup->window();
+ }
if (eventType == QEvent::KeyPress) {
if (m_composingText.isEmpty()) {
- QKeyEvent override(QEvent::ShortcutOverride, keyCode, modifiers,
- nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1);
- override.setTimestamp(timestamp);
- m_sendKeyEvent = !QWindowSystemInterface::tryHandleShortcutOverrideEvent(focusWindow, &override);
+ m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode,
+ modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1);
}
QObject *fo = QGuiApplication::focusObject();
if (m_sendKeyEvent && fo) {
- // if escape is pressed we don't want interpretKeyEvents to close a dialog. This will be done via QWindowSystemInterface
- if (keyCode == Qt::Key_Escape)
- m_platformWindow->m_ignoreWindowShouldClose = true;
-
QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
if (QCoreApplication::sendEvent(fo, &queryEvent)) {
bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool();
Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) {
// pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call
+ m_currentlyInterpretedKeyEvent = nsevent;
[self interpretKeyEvents:[NSArray arrayWithObject:nsevent]];
+ m_currentlyInterpretedKeyEvent = 0;
}
}
-
- m_platformWindow->m_ignoreWindowShouldClose = false;;
}
if (m_resendKeyEvent)
m_sendKeyEvent = true;
}
if (m_sendKeyEvent && m_composingText.isEmpty())
- QWindowSystemInterface::handleExtendedKeyEvent(focusWindow, timestamp, QEvent::Type(eventType), keyCode, modifiers,
+ QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers,
nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false);
m_sendKeyEvent = false;
@@ -1490,21 +1523,23 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
[self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
}
-- (BOOL)performKeyEquivalent:(NSEvent *)nsevent
+- (void)cancelOperation:(id)sender
{
- NSString *chars = [nsevent charactersIgnoringModifiers];
+ Q_UNUSED(sender);
- if ([nsevent type] == NSKeyDown && [chars length] > 0) {
- QChar ch = [chars characterAtIndex:0];
- Qt::Key qtKey = qt_mac_cocoaKey2QtKey(ch);
- // check for Command + Key_Period
- if ([nsevent modifierFlags] & NSCommandKeyMask
- && qtKey == Qt::Key_Period) {
- [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
- return YES;
- }
- }
- return [super performKeyEquivalent:nsevent];
+ NSEvent *currentEvent = [NSApp currentEvent];
+ if (!currentEvent || currentEvent.type != NSKeyDown)
+ return;
+
+ // Handling the key event may recurse back here through interpretKeyEvents
+ // (when IM is enabled), so we need to guard against that.
+ if (currentEvent == m_currentlyInterpretedKeyEvent)
+ return;
+
+ // Send Command+Key_Period and Escape as normal keypresses so that
+ // the key sequence is delivered through Qt. That way clients can
+ // intercept the shortcut and override its effect.
+ [self handleKeyEvent:currentEvent eventType:int(QEvent::KeyPress)];
}
- (void)flagsChanged:(NSEvent *)nsevent
@@ -1793,7 +1828,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
-(void)registerDragTypes
{
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
QStringList customTypes = qt_mac_enabledDraggedTypes();
if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
if (currentCustomDragTypes == 0)
@@ -1891,6 +1926,9 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
// Make sure the cursor is updated correctly if the mouse does not move and window is under cursor
// by creating a fake move event
+ if (m_updatingDrag)
+ return;
+
const QPoint mousePos(QCursor::pos());
CGEventRef moveEvent(CGEventCreateMouseEvent(
NULL, kCGEventMouseMoved,
@@ -1908,7 +1946,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
- return [self handleDrag : sender];
+ m_updatingDrag = true;
+ const NSDragOperation ret([self handleDrag : sender]);
+ m_updatingDrag = false;
+
+ return ret;
}
// Sends drag update to Qt, return the action
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index 93f0817aad..1f15da5b3b 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -44,6 +44,8 @@
#import <AppKit/NSAccessibility.h>
+#ifndef QT_NO_ACCESSIBILITY
+
@implementation QNSView (QNSViewAccessibility)
- (id)childAccessibleElement {
@@ -80,3 +82,5 @@
}
@end
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index 9e8fe8f1c8..edd1d656f0 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -38,7 +38,6 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
-#include "qcocoaautoreleasepool.h"
#ifndef QT_NO_PRINTER
@@ -212,6 +211,9 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
case QPaintDevice::PdmDevicePixelRatio:
val = 1;
break;
+ case QPaintDevice::PdmDevicePixelRatioScaled:
+ val = 1 * QPaintDevice::devicePixelRatioFScale();
+ break;
default:
val = 0;
qWarning("QPrinter::metric: Invalid metric command");
@@ -230,7 +232,7 @@ void QMacPrintEnginePrivate::initialize()
q->gccaps = paintEngine->gccaps;
- QCocoaAutoReleasePool pool;
+ QMacAutoReleasePool pool;
printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]];
QList<int> resolutions = m_printDevice->supportedResolutions();
diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h
index e210f0221f..576e0f9729 100644
--- a/src/plugins/platforms/cocoa/qt_mac_p.h
+++ b/src/plugins/platforms/cocoa/qt_mac_p.h
@@ -103,17 +103,6 @@ public:
}
};
-class Q_WIDGETS_EXPORT QMacCocoaAutoReleasePool
-{
-private:
- void *pool;
-public:
- QMacCocoaAutoReleasePool();
- ~QMacCocoaAutoReleasePool();
-
- inline void *handle() const { return pool; }
-};
-
QString qt_mac_removeMnemonics(const QString &original); //implemented in qmacstyle_mac.cpp
class Q_WIDGETS_EXPORT QMacWindowChangeEvent
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index 20dde476c1..3bd6e76c52 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -39,12 +39,12 @@
#include "qwindowsdirect2dwindow.h"
#include "qwindowscontext.h"
-#include "qwindowsguieventdispatcher.h"
#include <qplatformdefs.h>
#include <QtCore/QCoreApplication>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
+#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
QT_BEGIN_NAMESPACE
@@ -219,12 +219,11 @@ QWindowsDirect2DIntegration::~QWindowsDirect2DIntegration()
return static_cast<QWindowsDirect2DIntegration *>(QWindowsIntegration::instance());
}
- QPlatformWindow *QWindowsDirect2DIntegration::createPlatformWindow(QWindow *window) const
- {
- QWindowsWindowData data = createWindowData(window);
- return data.hwnd ? new QWindowsDirect2DWindow(window, data)
- : Q_NULLPTR;
- }
+
+QWindowsWindow *QWindowsDirect2DIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const
+{
+ return new QWindowsDirect2DWindow(window, data);
+}
QPlatformNativeInterface *QWindowsDirect2DIntegration::nativeInterface() const
{
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
index 6b7b3fbea2..64042cab0a 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
@@ -52,7 +52,6 @@ public:
static QWindowsDirect2DIntegration *instance();
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
@@ -60,6 +59,9 @@ public:
QWindowsDirect2DContext *direct2DContext() const;
+protected:
+ QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const Q_DECL_OVERRIDE;
+
private:
explicit QWindowsDirect2DIntegration(const QStringList &paramList);
bool init();
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
index fee9ad88fa..40709fc3d0 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
@@ -113,6 +113,9 @@ int QWindowsDirect2DPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric)
case QPaintDevice::PdmDevicePixelRatio:
return 1;
break;
+ case QPaintDevice::PdmDevicePixelRatioScaled:
+ return 1 * devicePixelRatioFScale();
+ break;
case QPaintDevice::PdmWidthMM:
case QPaintDevice::PdmHeightMM:
return -1;
diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
index 4deac969e4..b87310ed76 100644
--- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
@@ -473,7 +473,7 @@ IDirectFBSurface *QDirectFbTextureGlyphCache::sourceSurface()
case QImage::Format_Mono:
desc.pixelformat = DSPF_A1;
break;
- case QImage::Format_Indexed8:
+ case QImage::Format_Alpha8:
desc.pixelformat = DSPF_A8;
break;
default:
diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
index e635d4fd22..e1d97d9628 100644
--- a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
@@ -217,7 +217,7 @@ Qt::KeyboardModifiers QDirectFbConvenience::keyboardModifiers(DFBInputDeviceModi
modifiers |= Qt::ControlModifier;
}
if (mask & DIMM_META) {
- modifiers | Qt::MetaModifier;
+ modifiers |= Qt::MetaModifier;
}
return modifiers;
}
diff --git a/src/plugins/platforms/eglfs/cursor-atlas.png b/src/plugins/platforms/eglfs/cursor-atlas.png
index 40c5b6ef4f..40c5b6ef4f 100755..100644
--- a/src/plugins/platforms/eglfs/cursor-atlas.png
+++ b/src/plugins/platforms/eglfs/cursor-atlas.png
Binary files differ
diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
index 0adbb0d49f..266a97dff5 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
@@ -1,7 +1,9 @@
TEMPLATE = subdirs
contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11
-contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms
+contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms
+contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_egldevice
contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm
contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali
contains(QT_CONFIG, eglfs_viv): SUBDIRS += eglfs_viv
+contains(QT_CONFIG, eglfs_viv_wl): SUBDIRS += eglfs_viv_wl
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
index 98797e2106..2026b6a6c6 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
@@ -12,6 +12,9 @@ CONFIG += egl
LIBS += -lbcm_host
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
+# Avoid X11 header collision
+DEFINES += MESA_EGL_NO_X11_HEADERS
+
SOURCES += $$PWD/qeglfsbrcmmain.cpp \
$$PWD/qeglfsbrcmintegration.cpp
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
index 18a66e34f5..c29d64c06d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
@@ -191,6 +191,12 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
return Q_NULLPTR;
}
+ // Skip disconnected output
+ if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
+ qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName;
+ return Q_NULLPTR;
+ }
+
// Get the current mode on the current crtc
drmModeModeInfo crtc_mode;
memset(&crtc_mode, 0, sizeof crtc_mode);
@@ -208,11 +214,12 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
}
QList<drmModeModeInfo> modes;
+ modes.reserve(connector->count_modes);
qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes;
for (int i = 0; i < connector->count_modes; i++) {
const drmModeModeInfo &mode = connector->modes[i];
qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
- << "@" << mode.vrefresh << "hz";
+ << '@' << mode.vrefresh << "hz";
modes << connector->modes[i];
}
@@ -271,7 +278,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
int height = modes[selected_mode].vdisplay;
int refresh = modes[selected_mode].vrefresh;
qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
- << "@" << refresh << "hz for output" << connectorName;
+ << '@' << refresh << "hz for output" << connectorName;
}
QEglFSKmsOutput output = {
@@ -282,7 +289,9 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
selected_mode,
false,
drmModeGetCrtc(m_dri_fd, crtc_id),
- modes
+ modes,
+ connector->subpixel,
+ connectorProperty(connector, QByteArrayLiteral("DPMS"))
};
m_crtc_allocator |= (1 << output.crtc_id);
@@ -291,6 +300,22 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
return new QEglFSKmsScreen(m_integration, this, output, pos);
}
+drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
+{
+ drmModePropertyPtr prop;
+
+ for (int i = 0; i < connector->count_props; i++) {
+ prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
+ if (!prop)
+ continue;
+ if (strcmp(prop->name, name.constData()) == 0)
+ return prop;
+ drmModeFreeProperty(prop);
+ }
+
+ return Q_NULLPTR;
+}
+
void QEglFSKmsDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
{
Q_UNUSED(fd);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
index 23fca934e5..411f9a7200 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h
@@ -78,6 +78,7 @@ private:
int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos);
+ drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
static void pageFlipHandler(int fd,
unsigned int sequence,
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
index 45224ccb87..d1814fb85d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
@@ -36,8 +36,8 @@
#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
#include "qeglfskmscursor.h"
+#include "qeglfscursor.h"
-#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/QJsonDocument>
@@ -176,7 +176,7 @@ QPlatformCursor *QEglFSKmsIntegration::createCursor(QPlatformScreen *screen) con
if (m_hwCursor)
return Q_NULLPTR;
else
- return new QEGLPlatformCursor(screen);
+ return new QEglFSCursor(screen);
}
void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
index 5e49c224a0..60586f98a7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
@@ -35,11 +35,11 @@
#include "qeglfskmsscreen.h"
#include "qeglfskmsdevice.h"
#include "qeglfskmscursor.h"
+#include "qeglfsintegration.h"
#include <QtCore/QLoggingCategory>
#include <QtGui/private/qguiapplication_p.h>
-#include <QtPlatformSupport/private/qeglplatformintegration_p.h>
#include <QtPlatformSupport/private/qfbvthandler_p.h>
QT_BEGIN_NAMESPACE
@@ -50,17 +50,13 @@ class QEglFSKmsInterruptHandler : public QObject
{
public:
QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) {
- m_vtHandler = static_cast<QEGLPlatformIntegration *>(QGuiApplicationPrivate::platformIntegration())->vtHandler();
+ m_vtHandler = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->vtHandler();
connect(m_vtHandler, &QFbVtHandler::interrupted, this, &QEglFSKmsInterruptHandler::restoreVideoMode);
- connect(m_vtHandler, &QFbVtHandler::suspendRequested, this, &QEglFSKmsInterruptHandler::handleSuspendRequest);
+ connect(m_vtHandler, &QFbVtHandler::aboutToSuspend, this, &QEglFSKmsInterruptHandler::restoreVideoMode);
}
public slots:
void restoreVideoMode() { m_screen->restoreMode(); }
- void handleSuspendRequest() {
- m_screen->restoreMode();
- m_vtHandler->suspend();
- }
private:
QFbVtHandler *m_vtHandler;
@@ -119,6 +115,7 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
, m_output(output)
, m_pos(position)
, m_cursor(Q_NULLPTR)
+ , m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
{
m_siblings << this;
@@ -126,6 +123,10 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
QEglFSKmsScreen::~QEglFSKmsScreen()
{
+ if (m_output.dpms_prop) {
+ drmModeFreeProperty(m_output.dpms_prop);
+ m_output.dpms_prop = Q_NULLPTR;
+ }
restoreMode();
if (m_output.saved_crtc) {
drmModeFreeCrtc(m_output.saved_crtc);
@@ -266,10 +267,12 @@ void QEglFSKmsScreen::flip()
&m_output.connector_id, 1,
&m_output.modes[m_output.mode]);
- if (ret)
+ if (ret) {
qErrnoWarning("Could not set DRM mode!");
- else
+ } else {
m_output.mode_set = true;
+ setPowerState(PowerStateOn);
+ }
}
int ret = drmModePageFlip(m_device->fd(),
@@ -314,4 +317,37 @@ qreal QEglFSKmsScreen::refreshRate() const
return refresh > 0 ? refresh : 60;
}
+QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const
+{
+ switch (m_output.subpixel) {
+ default:
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ case DRM_MODE_SUBPIXEL_NONE:
+ return Subpixel_None;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ return Subpixel_RGB;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ return Subpixel_BGR;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ return Subpixel_VRGB;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ return Subpixel_VBGR;
+ }
+}
+
+QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
+{
+ return m_powerState;
+}
+
+void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state)
+{
+ if (!m_output.dpms_prop)
+ return;
+
+ drmModeConnectorSetProperty(m_device->fd(), m_output.connector_id,
+ m_output.dpms_prop->prop_id, (int)state);
+ m_powerState = state;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
index 4c1b0d02ad..7fd6ccaa31 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
@@ -60,6 +60,8 @@ struct QEglFSKmsOutput
bool mode_set;
drmModeCrtcPtr saved_crtc;
QList<drmModeModeInfo> modes;
+ int subpixel;
+ drmModePropertyPtr dpms_prop;
};
class QEglFSKmsScreen : public QEglFSScreen
@@ -103,6 +105,11 @@ public:
QEglFSKmsOutput &output() { return m_output; }
void restoreMode();
+ SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
+
+ QPlatformScreen::PowerState powerState() const Q_DECL_OVERRIDE;
+ void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE;
+
private:
QEglFSKmsIntegration *m_integration;
QEglFSKmsDevice *m_device;
@@ -117,6 +124,8 @@ private:
QList<QPlatformScreen *> m_siblings;
+ PowerState m_powerState;
+
struct FrameBuffer {
FrameBuffer() : fb(0) {}
uint32_t fb;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json
new file mode 100644
index 0000000000..169ba1eb02
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "eglfs_kms_egldevice" ]
+}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
new file mode 100644
index 0000000000..393ddd14a5
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
@@ -0,0 +1,23 @@
+TARGET = qeglfs-kms-egldevice-integration
+
+PLUGIN_TYPE = egldeviceintegrations
+PLUGIN_CLASS_NAME = QEglFSKmsEglDeviceIntegrationPlugin
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private eglfs_device_lib-private
+
+INCLUDEPATH += $$PWD/../..
+
+DEFINES += MESA_EGL_NO_X11_HEADERS
+
+CONFIG += egl
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
+
+SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \
+ $$PWD/qeglfskmsegldeviceintegration.cpp
+
+HEADERS += $$PWD/qeglfskmsegldeviceintegration.h
+
+OTHER_FILES += $$PWD/eglfs_kms_egldevice.json
+
+LIBS += -ldrm
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
new file mode 100644
index 0000000000..1ddcb3b862
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -0,0 +1,409 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfskmsegldeviceintegration.h"
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
+
+QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
+ : m_dri_fd(-1)
+ , m_egl_device(EGL_NO_DEVICE_EXT)
+ , m_egl_display(EGL_NO_DISPLAY)
+ , m_drm_connector(Q_NULLPTR)
+ , m_drm_encoder(Q_NULLPTR)
+ , m_drm_crtc(0)
+ , m_funcs(Q_NULLPTR)
+{
+ qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
+}
+
+void QEglFSKmsEglDeviceIntegration::platformInit()
+{
+ if (!query_egl_device())
+ qFatal("Could not set up EGL device!");
+
+ const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT);
+ if (!deviceName)
+ qFatal("Failed to query device name from EGLDevice");
+
+ qCDebug(qLcEglfsKmsDebug, "Opening %s", deviceName);
+
+ m_dri_fd = drmOpen(deviceName, Q_NULLPTR);
+ if (m_dri_fd < 0)
+ qFatal("Could not open DRM device");
+
+ if (!setup_kms())
+ qFatal("Could not set up KMS on device %s!", m_device.constData());
+
+ qCDebug(qLcEglfsKmsDebug, "DRM/KMS initialized");
+}
+
+void QEglFSKmsEglDeviceIntegration::platformDestroy()
+{
+ if (qt_safe_close(m_dri_fd) == -1)
+ qErrnoWarning("Could not close DRM device");
+
+ m_dri_fd = -1;
+
+ delete m_funcs;
+ m_funcs = Q_NULLPTR;
+}
+
+EGLNativeDisplayType QEglFSKmsEglDeviceIntegration::platformDisplay() const
+{
+ return static_cast<EGLNativeDisplayType>(m_egl_device);
+}
+
+EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
+{
+ qCDebug(qLcEglfsKmsDebug, "Creating display");
+
+ EGLDisplay display;
+
+ if (m_funcs->has_egl_platform_device) {
+ display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, Q_NULLPTR);
+ } else {
+ qWarning("EGL_EXT_platform_device not available, falling back to legacy path!");
+ display = eglGetDisplay(nativeDisplay);
+ }
+
+ if (display == EGL_NO_DISPLAY)
+ qFatal("Could not get EGL display");
+
+ EGLint major, minor;
+ if (!eglInitialize(display, &major, &minor))
+ qFatal("Could not initialize egl display");
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API))
+ qFatal("Failed to bind EGL_OPENGL_ES_API\n");
+
+ return display;
+}
+
+QSizeF QEglFSKmsEglDeviceIntegration::physicalScreenSize() const
+{
+ return QSizeF(m_drm_connector->mmWidth, m_drm_connector->mmHeight);
+}
+
+QSize QEglFSKmsEglDeviceIntegration::screenSize() const
+{
+ return QSize(m_drm_mode.hdisplay, m_drm_mode.vdisplay);
+}
+
+int QEglFSKmsEglDeviceIntegration::screenDepth() const
+{
+ return 32;
+}
+
+QSurfaceFormat QEglFSKmsEglDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
+{
+ QSurfaceFormat format(inputFormat);
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ format.setRedBufferSize(8);
+ format.setGreenBufferSize(8);
+ format.setBlueBufferSize(8);
+ return format;
+}
+
+EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const
+{
+ return EGL_STREAM_BIT_KHR;
+}
+
+class QEglJetsonTK1Window : public QEglFSWindow
+{
+public:
+ QEglJetsonTK1Window(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration)
+ : QEglFSWindow(w)
+ , m_integration(integration)
+ , m_egl_stream(EGL_NO_STREAM_KHR)
+ { }
+
+ void invalidateSurface() Q_DECL_OVERRIDE;
+ void resetSurface() Q_DECL_OVERRIDE;
+
+ const QEglFSKmsEglDeviceIntegration *m_integration;
+ EGLStreamKHR m_egl_stream;
+ EGLint m_latency;
+};
+
+void QEglJetsonTK1Window::invalidateSurface()
+{
+ QEglFSWindow::invalidateSurface();
+ m_integration->m_funcs->destroy_stream(screen()->display(), m_egl_stream);
+}
+
+void QEglJetsonTK1Window::resetSurface()
+{
+ qCDebug(qLcEglfsKmsDebug, "Creating stream");
+
+ EGLDisplay display = screen()->display();
+ EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT;
+ EGLint count;
+
+ m_egl_stream = m_integration->m_funcs->create_stream(display, Q_NULLPTR);
+ if (m_egl_stream == EGL_NO_STREAM_KHR) {
+ qWarning("resetSurface: Couldn't create EGLStream for native window");
+ return;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Created stream %p on display %p", m_egl_stream, display);
+
+ if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) {
+ qWarning("No output layers found");
+ return;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Output has %d layers", count);
+
+ QVector<EGLOutputLayerEXT> layers;
+ layers.resize(count);
+ EGLint actualCount;
+ if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, layers.data(), count, &actualCount)) {
+ qWarning("Failed to get layers");
+ return;
+ }
+
+ for (int i = 0; i < actualCount; ++i) {
+ EGLAttrib id;
+ if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) {
+ qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id);
+ if (id == EGLAttrib(m_integration->m_drm_crtc))
+ layer = layers[i];
+ } else if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) {
+ // Not used yet, just for debugging.
+ qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - plane %d", i, layers[i], (int) id);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - unknown", i, layers[i]);
+ }
+ }
+
+ QByteArray reqLayerIndex = qgetenv("QT_QPA_EGLFS_LAYER_INDEX");
+ if (!reqLayerIndex.isEmpty()) {
+ int idx = reqLayerIndex.toInt();
+ if (idx >= 0 && idx < layers.count())
+ layer = layers[idx];
+ }
+
+ if (layer == EGL_NO_OUTPUT_LAYER_EXT) {
+ qWarning("resetSurface: Couldn't get EGLOutputLayer for native window");
+ return;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Using layer %p", layer);
+
+ if (!m_integration->m_funcs->stream_consumer_output(display, m_egl_stream, layer))
+ qWarning("resetSurface: Unable to connect stream");
+
+ m_config = QEglFSIntegration::chooseConfig(display, m_integration->surfaceFormatFor(window()->requestedFormat()));
+ m_format = q_glFormatFromConfig(display, m_config);
+ qCDebug(qLcEglfsKmsDebug) << "Stream producer format is" << m_format;
+
+ const int w = m_integration->screenSize().width();
+ const int h = m_integration->screenSize().height();
+ qCDebug(qLcEglfsKmsDebug, "Creating stream producer surface of size %dx%d", w, h);
+
+ const EGLint stream_producer_attribs[] = {
+ EGL_WIDTH, w,
+ EGL_HEIGHT, h,
+ EGL_NONE
+ };
+
+ m_surface = m_integration->m_funcs->create_stream_producer_surface(display, m_config, m_egl_stream, stream_producer_attribs);
+ if (m_surface == EGL_NO_SURFACE)
+ return;
+
+ qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface);
+}
+
+QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
+{
+ QEglJetsonTK1Window *eglWindow = new QEglJetsonTK1Window(window, this);
+
+ m_funcs->initialize(eglWindow->screen()->display());
+ if (!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream
+ && m_funcs->has_egl_stream_producer_eglsurface && m_funcs->has_egl_stream_consumer_egloutput))
+ qFatal("Required extensions missing!");
+
+ return eglWindow;
+}
+
+bool QEglFSKmsEglDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case QPlatformIntegration::ThreadedPixmaps:
+ case QPlatformIntegration::OpenGL:
+ case QPlatformIntegration::ThreadedOpenGL:
+ case QPlatformIntegration::BufferQueueingOpenGL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const
+{
+ static bool mode_set = false;
+
+ if (!mode_set) {
+ mode_set = true;
+
+ drmModeCrtcPtr currentMode = drmModeGetCrtc(m_dri_fd, m_drm_crtc);
+ const bool alreadySet = currentMode
+ && currentMode->width == m_drm_mode.hdisplay
+ && currentMode->height == m_drm_mode.vdisplay;
+ if (currentMode)
+ drmModeFreeCrtc(currentMode);
+ if (alreadySet) {
+ qCDebug(qLcEglfsKmsDebug, "Mode already set");
+ return;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Setting mode");
+ int ret = drmModeSetCrtc(m_dri_fd, m_drm_crtc,
+ -1, 0, 0,
+ &m_drm_connector->connector_id, 1,
+ const_cast<const drmModeModeInfoPtr>(&m_drm_mode));
+ if (ret)
+ qFatal("drmModeSetCrtc failed");
+ }
+}
+
+qreal QEglFSKmsEglDeviceIntegration::refreshRate() const
+{
+ quint32 refresh = m_drm_mode.vrefresh;
+ return refresh > 0 ? refresh : 60;
+}
+
+bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const
+{
+ // Returning false disables the usage of EGL_KHR_surfaceless_context even when the
+ // extension is available. This is just what we need since, at least with NVIDIA
+ // 352.00 making a null surface current with a context breaks.
+ return false;
+}
+
+bool QEglFSKmsEglDeviceIntegration::setup_kms()
+{
+ drmModeRes *resources;
+ drmModeConnector *connector;
+ drmModeEncoder *encoder;
+ quint32 crtc = 0;
+ int i;
+
+ resources = drmModeGetResources(m_dri_fd);
+ if (!resources) {
+ qWarning("drmModeGetResources failed");
+ return false;
+ }
+
+ for (i = 0; i < resources->count_connectors; i++) {
+ connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
+ if (!connector)
+ continue;
+
+ if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0)
+ break;
+
+ drmModeFreeConnector(connector);
+ }
+
+ if (i == resources->count_connectors) {
+ qWarning("No currently active connector found.");
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Using connector with type %d", connector->connector_type);
+
+ for (i = 0; i < resources->count_encoders; i++) {
+ encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]);
+ if (!encoder)
+ continue;
+
+ if (encoder->encoder_id == connector->encoder_id)
+ break;
+
+ drmModeFreeEncoder(encoder);
+ }
+
+ for (int j = 0; j < resources->count_crtcs; j++) {
+ if ((encoder->possible_crtcs & (1 << j))) {
+ crtc = resources->crtcs[j];
+ break;
+ }
+ }
+
+ if (crtc == 0)
+ qFatal("No suitable CRTC available");
+
+ m_drm_connector = connector;
+ m_drm_encoder = encoder;
+ m_drm_mode = connector->modes[0];
+ m_drm_crtc = crtc;
+
+ qCDebug(qLcEglfsKmsDebug).noquote() << "Using crtc" << m_drm_crtc
+ << "with mode" << m_drm_mode.hdisplay << "x" << m_drm_mode.vdisplay
+ << "@" << m_drm_mode.vrefresh;
+
+ drmModeFreeResources(resources);
+
+ return true;
+}
+
+bool QEglFSKmsEglDeviceIntegration::query_egl_device()
+{
+ m_funcs = new QEGLStreamConvenience;
+ if (!m_funcs->has_egl_device_base)
+ qFatal("EGL_EXT_device_base missing");
+
+ EGLint num_devices = 0;
+ if (m_funcs->query_devices(1, &m_egl_device, &num_devices) != EGL_TRUE) {
+ qWarning("eglQueryDevicesEXT failed: eglError: %x", eglGetError());
+ return false;
+ }
+
+ qCDebug(qLcEglfsKmsDebug, "Found %d EGL devices", num_devices);
+
+ if (num_devices < 1 || m_egl_device == EGL_NO_DEVICE_EXT) {
+ qWarning("eglQueryDevicesEXT could not find any EGL devices");
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
new file mode 100644
index 0000000000..a89a65ca55
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSKMSEGLDEVICEINTEGRATION_H
+#define QEGLFSKMSEGLDEVICEINTEGRATION_H
+
+#include "qeglfsdeviceintegration.h"
+#include "qeglfswindow.h"
+#include "qeglfsintegration.h"
+
+#include <QtPlatformSupport/private/qdevicediscovery_p.h>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+#include <QtCore/private/qcore_unix_p.h>
+#include <QtCore/QScopedPointer>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qguiapplication.h>
+#include <QDebug>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <QtPlatformSupport/private/qeglstreamconvenience_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsEglDeviceIntegration : public QEGLDeviceIntegration
+{
+public:
+ QEglFSKmsEglDeviceIntegration();
+
+ void platformInit() Q_DECL_OVERRIDE;
+ void platformDestroy() Q_DECL_OVERRIDE;
+ EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
+ EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE;
+ QSizeF physicalScreenSize() const Q_DECL_OVERRIDE;
+ QSize screenSize() const Q_DECL_OVERRIDE;
+ int screenDepth() const Q_DECL_OVERRIDE;
+ qreal refreshRate() const Q_DECL_OVERRIDE;
+ QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE;
+ EGLint surfaceType() const Q_DECL_OVERRIDE;
+ QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE;
+ bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE;
+
+ bool setup_kms();
+ bool query_egl_device();
+
+ // device bits
+ QByteArray m_device;
+ int m_dri_fd;
+ EGLDeviceEXT m_egl_device;
+ EGLDisplay m_egl_display;
+
+ // KMS bits
+ drmModeConnector *m_drm_connector;
+ drmModeEncoder *m_drm_encoder;
+ drmModeModeInfo m_drm_mode;
+ quint32 m_drm_crtc;
+
+ // EGLStream infrastructure
+ QEGLStreamConvenience *m_funcs;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp
index 8b2a9f3788..f987ae38a6 100644
--- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
@@ -31,23 +31,19 @@
**
****************************************************************************/
-#ifndef QCOCOAAUTORELEASEPOOL_H
-#define QCOCOAAUTORELEASEPOOL_H
-
-#undef slots
-#include <qglobal.h>
-#include <Cocoa/Cocoa.h>
+#include "qeglfskmsegldeviceintegration.h"
QT_BEGIN_NAMESPACE
-class QCocoaAutoReleasePool
+
+class QEglFSKmsEglDeviceIntegrationPlugin : public QEGLDeviceIntegrationPlugin
{
-public:
- QCocoaAutoReleasePool();
- ~QCocoaAutoReleasePool();
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms_egldevice.json")
-private:
- NSAutoreleasePool *pool;
+public:
+ QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsEglDeviceIntegration; }
};
+
QT_END_NAMESPACE
-#endif // QCOCOAAUTORELEASEPOOL_H
+#include "qeglfskmsegldevicemain.moc"
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp
index 455d78035a..43decdf849 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp
@@ -32,7 +32,6 @@
****************************************************************************/
#include "qeglfsmaliintegration.h"
-#include <EGL/fbdev_window.h>
#include <unistd.h>
#include <fcntl.h>
@@ -43,6 +42,11 @@
QT_BEGIN_NAMESPACE
+struct fbdev_window {
+ unsigned short width;
+ unsigned short height;
+};
+
void QEglFSMaliIntegration::platformInit()
{
// Keep the non-overridden base class functions based on fb0 working.
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.json
new file mode 100644
index 0000000000..ced5245fa0
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "eglfs_viv_wl" ]
+}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro
new file mode 100644
index 0000000000..26b6a2e9ea
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro
@@ -0,0 +1,23 @@
+TARGET = qeglfs-viv-wl-integration
+
+PLUGIN_TYPE = egldeviceintegrations
+PLUGIN_CLASS_NAME = QEglFSVivWaylandIntegrationPlugin
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private eglfs_device_lib-private
+
+INCLUDEPATH += $$PWD/../..
+CONFIG += egl
+DEFINES += LINUX=1 EGL_API_FB=1
+LIBS += -lGAL
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
+
+SOURCES += $$PWD/qeglfsvivwlmain.cpp \
+ $$PWD/qeglfsvivwlintegration.cpp
+
+HEADERS += $$PWD/qeglfsvivwlintegration.h
+
+OTHER_FILES += $$PWD/eglfs_viv_wl.json
+
+CONFIG += link_pkgconfig
+PKGCONFIG_PRIVATE += wayland-server
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
new file mode 100644
index 0000000000..9eebcc772a
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfsvivwlintegration.h"
+#include <EGL/eglvivante.h>
+#include <QDebug>
+
+#include <wayland-server.h>
+
+QT_BEGIN_NAMESPACE
+
+void QEglFSVivWaylandIntegration::platformInit()
+{
+ QEGLDeviceIntegration::platformInit();
+
+ int width, height;
+
+ bool multiBufferNotEnabledYet = qEnvironmentVariableIsEmpty("FB_MULTI_BUFFER");
+ bool multiBuffer = qEnvironmentVariableIsEmpty("QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER");
+ if (multiBufferNotEnabledYet && multiBuffer) {
+ qWarning() << "QEglFSVivWaylandIntegration will set environment variable FB_MULTI_BUFFER=2 to enable double buffering and vsync.\n"
+ << "If this is not desired, you can override this via: export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=1";
+ qputenv("FB_MULTI_BUFFER", "2");
+ }
+
+ mWaylandDisplay = wl_display_create();
+ mNativeDisplay = fbGetDisplay(mWaylandDisplay);
+ fbGetDisplayGeometry(mNativeDisplay, &width, &height);
+ mScreenSize.setHeight(height);
+ mScreenSize.setWidth(width);
+}
+
+QSize QEglFSVivWaylandIntegration::screenSize() const
+{
+ return mScreenSize;
+}
+
+EGLNativeDisplayType QEglFSVivWaylandIntegration::platformDisplay() const
+{
+ return mNativeDisplay;
+}
+
+EGLNativeWindowType QEglFSVivWaylandIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format)
+{
+ Q_UNUSED(window)
+ Q_UNUSED(format)
+
+ EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height());
+ return eglWindow;
+}
+
+void QEglFSVivWaylandIntegration::destroyNativeWindow(EGLNativeWindowType window)
+{
+ fbDestroyWindow(window);
+}
+
+void *QEglFSVivWaylandIntegration::wlDisplay() const
+{
+ return mWaylandDisplay;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
index 3389139461..677a1b6337 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
@@ -31,30 +31,30 @@
**
****************************************************************************/
-#ifndef QWINDOWSGUIEVENTDISPATCHER_H
-#define QWINDOWSGUIEVENTDISPATCHER_H
+#ifndef QEGLFSVIVINTEGRATION_H
+#define QEGLFSVIVINTEGRATION_H
-#include "qtwindows_additional.h"
-
-#include <QtCore/private/qeventdispatcher_win_p.h>
+#include "qeglfsdeviceintegration.h"
+struct wl_display;
QT_BEGIN_NAMESPACE
-class QWindowsGuiEventDispatcher : public QEventDispatcherWin32
+class QEglFSVivWaylandIntegration : public QEGLDeviceIntegration
{
- Q_OBJECT
public:
- explicit QWindowsGuiEventDispatcher(QObject *parent = 0);
-
- static const char *windowsMessageName(UINT msg);
-
- bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
- void sendPostedEvents() Q_DECL_OVERRIDE;
+ void platformInit() Q_DECL_OVERRIDE;
+ QSize screenSize() const Q_DECL_OVERRIDE;
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE;
+ void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
+ EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
+ void *wlDisplay() const Q_DECL_OVERRIDE;
private:
- QEventLoop::ProcessEventsFlags m_flags;
+ QSize mScreenSize;
+ EGLNativeDisplayType mNativeDisplay;
+ wl_display *mWaylandDisplay;
};
QT_END_NAMESPACE
-#endif // QWINDOWSGUIEVENTDISPATCHER_H
+#endif
diff --git a/src/plugins/platforms/kms/qkmswindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp
index aec6d55b5d..a48aa08e40 100644
--- a/src/plugins/platforms/kms/qkmswindow.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp
@@ -31,27 +31,20 @@
**
****************************************************************************/
-#ifndef QKMSWINDOW_H
-#define QKMSWINDOW_H
-
-#include <qpa/qplatformwindow.h>
+#include "qeglfsdeviceintegration.h"
+#include "qeglfsvivwlintegration.h"
QT_BEGIN_NAMESPACE
-class QKmsWindow : public QPlatformWindow
+class QEglFSVivWaylandIntegrationPlugin : public QEGLDeviceIntegrationPlugin
{
- Q_DECLARE_PRIVATE(QPlatformWindow)
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_viv_wl.json")
public:
- QKmsWindow(QWindow *window);
-
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
-
-private:
- QPlatformScreen *m_screen;
+ QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSVivWaylandIntegration; }
};
QT_END_NAMESPACE
-#endif // QKMSWINDOW_H
+#include "qeglfsvivwlmain.moc"
diff --git a/src/plugins/platforms/eglfs/eglfs_device_lib.pro b/src/plugins/platforms/eglfs/eglfs_device_lib.pro
index 729290706d..4fe2ce4897 100644
--- a/src/plugins/platforms/eglfs/eglfs_device_lib.pro
+++ b/src/plugins/platforms/eglfs/eglfs_device_lib.pro
@@ -6,13 +6,6 @@
TARGET = QtEglDeviceIntegration
CONFIG += no_module_headers internal_module
-MODULE_INCLUDES = \
- \$\$QT_MODULE_INCLUDE_BASE \
- \$\$QT_MODULE_INCLUDE_BASE/QtQGui
-MODULE_PRIVATE_INCLUDES = \
- \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION \
- \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION/QtGui
-
load(qt_module)
QT += core-private gui-private platformsupport-private
@@ -26,6 +19,7 @@ DEFINES += QT_BUILD_EGL_DEVICE_LIB
SOURCES += $$PWD/qeglfsintegration.cpp \
$$PWD/qeglfswindow.cpp \
$$PWD/qeglfsscreen.cpp \
+ $$PWD/qeglfscursor.cpp \
$$PWD/qeglfshooks.cpp \
$$PWD/qeglfscontext.cpp \
$$PWD/qeglfsoffscreenwindow.cpp \
@@ -34,6 +28,7 @@ SOURCES += $$PWD/qeglfsintegration.cpp \
HEADERS += $$PWD/qeglfsintegration.h \
$$PWD/qeglfswindow.h \
$$PWD/qeglfsscreen.h \
+ $$PWD/qeglfscursor.h \
$$PWD/qeglfshooks.h \
$$PWD/qeglfscontext.h \
$$PWD/qeglfsoffscreenwindow.h \
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 9216b7a85d..6fcdae7ad2 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -32,21 +32,20 @@
****************************************************************************/
#include <QtGui/QSurface>
-#include <QtDebug>
-
-#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include "qeglfscontext.h"
#include "qeglfswindow.h"
#include "qeglfshooks.h"
-#include "qeglfscontext.h"
+#include "qeglfscursor.h"
QT_BEGIN_NAMESPACE
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
EGLConfig *config, const QVariant &nativeHandle)
- : QEGLPlatformContext(format, share, display, config, nativeHandle),
+ : QEGLPlatformContext(format, share, display, config, nativeHandle,
+ qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags(0) : QEGLPlatformContext::NoSurfaceless),
m_tempWindow(0)
{
}
@@ -91,7 +90,7 @@ void QEglFSContext::swapBuffers(QPlatformSurface *surface)
// draw the cursor
if (surface->surface()->surfaceClass() == QSurface::Window) {
QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
- if (QEGLPlatformCursor *cursor = qobject_cast<QEGLPlatformCursor *>(window->screen()->cursor()))
+ if (QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(window->screen()->cursor()))
cursor->paintOnScreen();
}
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.cpp b/src/plugins/platforms/eglfs/qeglfscursor.cpp
new file mode 100644
index 0000000000..eea130a754
--- /dev/null
+++ b/src/plugins/platforms/eglfs/qeglfscursor.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfscursor.h"
+#include "qeglfsintegration.h"
+#include "qeglfsscreen.h"
+
+#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qopenglvertexarrayobject_p.h>
+
+#ifndef GL_VERTEX_ARRAY_BINDING
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QEglFSCursor::QEglFSCursor(QPlatformScreen *screen)
+ : m_visible(true),
+ m_screen(static_cast<QEglFSScreen *>(screen)),
+ m_program(0),
+ m_textureEntry(0),
+ m_deviceListener(0),
+ m_updateRequested(false)
+{
+ QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
+ if (!hideCursorVal.isEmpty())
+ m_visible = hideCursorVal.toInt() == 0;
+ if (!m_visible)
+ return;
+
+ // Try to load the cursor atlas. If this fails, m_visible is set to false and
+ // paintOnScreen() and setCurrentCursor() become no-ops.
+ initCursorAtlas();
+
+ // initialize the cursor
+#ifndef QT_NO_CURSOR
+ QCursor cursor(Qt::ArrowCursor);
+ setCurrentCursor(&cursor);
+#endif
+
+ m_deviceListener = new QEglFSCursorDeviceListener(this);
+ connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged,
+ m_deviceListener, &QEglFSCursorDeviceListener::onDeviceListChanged);
+ updateMouseStatus();
+}
+
+QEglFSCursor::~QEglFSCursor()
+{
+ resetResources();
+ delete m_deviceListener;
+}
+
+void QEglFSCursor::updateMouseStatus()
+{
+ m_visible = m_deviceListener->hasMouse();
+}
+
+bool QEglFSCursorDeviceListener::hasMouse() const
+{
+ return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0;
+}
+
+void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type)
+{
+ if (type == QInputDeviceManager::DeviceTypePointer)
+ m_cursor->updateMouseStatus();
+}
+
+void QEglFSCursor::resetResources()
+{
+ if (QOpenGLContext::currentContext()) {
+ delete m_program;
+ glDeleteTextures(1, &m_cursor.customCursorTexture);
+ glDeleteTextures(1, &m_cursorAtlas.texture);
+ }
+ m_program = 0;
+ m_cursor.customCursorTexture = 0;
+ m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull();
+ m_cursorAtlas.texture = 0;
+}
+
+void QEglFSCursor::createShaderPrograms()
+{
+ static const char *textureVertexProgram =
+ "attribute highp vec2 vertexCoordEntry;\n"
+ "attribute highp vec2 textureCoordEntry;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " textureCoord = textureCoordEntry;\n"
+ " gl_Position = vec4(vertexCoordEntry, 1.0, 1.0);\n"
+ "}\n";
+
+ static const char *textureFragmentProgram =
+ "uniform sampler2D texture;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
+ "}\n";
+
+ m_program = new QOpenGLShaderProgram;
+ m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ m_program->bindAttributeLocation("vertexCoordEntry", 0);
+ m_program->bindAttributeLocation("textureCoordEntry", 1);
+ m_program->link();
+
+ m_textureEntry = m_program->uniformLocation("texture");
+}
+
+void QEglFSCursor::createCursorTexture(uint *texture, const QImage &image)
+{
+ if (!*texture)
+ glGenTextures(1, texture);
+ glBindTexture(GL_TEXTURE_2D, *texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, image.width(), image.height(), 0 /* border */,
+ GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
+}
+
+void QEglFSCursor::initCursorAtlas()
+{
+ static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR");
+ if (json.isEmpty())
+ json = ":/cursor.json";
+
+ QFile file(QString::fromUtf8(json));
+ if (!file.open(QFile::ReadOnly)) {
+ m_visible = false;
+ return;
+ }
+
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ QJsonObject object = doc.object();
+
+ QString atlas = object.value(QLatin1String("image")).toString();
+ Q_ASSERT(!atlas.isEmpty());
+
+ const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble();
+ Q_ASSERT(cursorsPerRow);
+ m_cursorAtlas.cursorsPerRow = cursorsPerRow;
+
+ const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray();
+ Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1);
+ for (int i = 0; i < hotSpots.count(); i++) {
+ QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble());
+ m_cursorAtlas.hotSpots << hotSpot;
+ }
+
+ QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow;
+ m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow);
+ m_cursorAtlas.width = image.width();
+ m_cursorAtlas.height = image.height();
+ m_cursorAtlas.image = image;
+}
+
+#ifndef QT_NO_CURSOR
+void QEglFSCursor::changeCursor(QCursor *cursor, QWindow *window)
+{
+ Q_UNUSED(window);
+ const QRect oldCursorRect = cursorRect();
+ if (setCurrentCursor(cursor))
+ update(oldCursorRect | cursorRect());
+}
+
+bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
+{
+ if (!m_visible)
+ return false;
+
+ const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+ if (m_cursor.shape == newShape && newShape != Qt::BitmapCursor)
+ return false;
+
+ if (m_cursor.shape == Qt::BitmapCursor) {
+ m_cursor.customCursorImage = QImage();
+ m_cursor.customCursorPending = false;
+ }
+ m_cursor.shape = newShape;
+ if (newShape != Qt::BitmapCursor) { // standard cursor
+ const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,
+ hs = (float)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;
+ m_cursor.textureRect = QRectF(ws * (m_cursor.shape % m_cursorAtlas.cursorsPerRow),
+ hs * (m_cursor.shape / m_cursorAtlas.cursorsPerRow),
+ ws, hs);
+ m_cursor.hotSpot = m_cursorAtlas.hotSpots[m_cursor.shape];
+ m_cursor.texture = m_cursorAtlas.texture;
+ m_cursor.size = QSize(m_cursorAtlas.cursorWidth, m_cursorAtlas.cursorHeight);
+ } else {
+ QImage image = cursor->pixmap().toImage();
+ m_cursor.textureRect = QRectF(0, 0, 1, 1);
+ m_cursor.hotSpot = cursor->hotSpot();
+ m_cursor.texture = 0; // will get updated in the next render()
+ m_cursor.size = image.size();
+ m_cursor.customCursorImage = image;
+ m_cursor.customCursorPending = true;
+ }
+
+ return true;
+}
+#endif
+
+class CursorUpdateEvent : public QEvent
+{
+public:
+ CursorUpdateEvent(const QPoint &pos, const QRegion &rgn)
+ : QEvent(QEvent::Type(QEvent::User + 1)),
+ m_pos(pos),
+ m_region(rgn)
+ { }
+ QPoint pos() const { return m_pos; }
+ QRegion region() const { return m_region; }
+
+private:
+ QPoint m_pos;
+ QRegion m_region;
+};
+
+bool QEglFSCursor::event(QEvent *e)
+{
+ if (e->type() == QEvent::User + 1) {
+ CursorUpdateEvent *ev = static_cast<CursorUpdateEvent *>(e);
+ m_updateRequested = false;
+ QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region());
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+ return true;
+ }
+ return QPlatformCursor::event(e);
+}
+
+void QEglFSCursor::update(const QRegion &rgn)
+{
+ if (!m_updateRequested) {
+ // Must not flush the window system events directly from here since we are likely to
+ // be a called directly from QGuiApplication's processMouseEvents. Flushing events
+ // could cause reentering by dispatching more queued mouse events.
+ m_updateRequested = true;
+ QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn));
+ }
+}
+
+QRect QEglFSCursor::cursorRect() const
+{
+ return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
+}
+
+QPoint QEglFSCursor::pos() const
+{
+ return m_cursor.pos;
+}
+
+void QEglFSCursor::setPos(const QPoint &pos)
+{
+ QGuiApplicationPrivate::inputDeviceManager()->setCursorPos(pos);
+ const QRect oldCursorRect = cursorRect();
+ m_cursor.pos = pos;
+ update(oldCursorRect | cursorRect());
+ m_screen->handleCursorMove(m_cursor.pos);
+}
+
+void QEglFSCursor::pointerEvent(const QMouseEvent &event)
+{
+ if (event.type() != QEvent::MouseMove)
+ return;
+ const QRect oldCursorRect = cursorRect();
+ m_cursor.pos = event.screenPos().toPoint();
+ update(oldCursorRect | cursorRect());
+ m_screen->handleCursorMove(m_cursor.pos);
+}
+
+void QEglFSCursor::paintOnScreen()
+{
+ if (!m_visible)
+ return;
+
+ const QRectF cr = cursorRect();
+ const QRect screenRect(m_screen->geometry());
+ const GLfloat x1 = 2 * (cr.left() / screenRect.width()) - 1;
+ const GLfloat x2 = 2 * (cr.right() / screenRect.width()) - 1;
+ const GLfloat y1 = 1 - (cr.top() / screenRect.height()) * 2;
+ const GLfloat y2 = 1 - (cr.bottom() / screenRect.height()) * 2;
+ QRectF r(QPointF(x1, y1), QPointF(x2, y2));
+
+ draw(r);
+}
+
+// In order to prevent breaking code doing custom OpenGL rendering while
+// expecting the state in the context unchanged, save and restore all the state
+// we touch. The exception is Qt Quick where the scenegraph is known to be able
+// to deal with the changes we make.
+struct StateSaver
+{
+ StateSaver() {
+ f = QOpenGLContext::currentContext()->functions();
+ vaoHelper = new QOpenGLVertexArrayObjectHelper(QOpenGLContext::currentContext());
+
+ static bool windowsChecked = false;
+ static bool shouldSave = true;
+ if (!windowsChecked) {
+ windowsChecked = true;
+ QWindowList windows = QGuiApplication::allWindows();
+ if (!windows.isEmpty() && windows[0]->inherits("QQuickWindow"))
+ shouldSave = false;
+ }
+ saved = shouldSave;
+ if (!shouldSave)
+ return;
+
+ f->glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ f->glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
+ f->glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ f->glGetIntegerv(GL_FRONT_FACE, &frontFace);
+ cull = f->glIsEnabled(GL_CULL_FACE);
+ depthTest = f->glIsEnabled(GL_DEPTH_TEST);
+ blend = f->glIsEnabled(GL_BLEND);
+ f->glGetIntegerv(GL_BLEND_SRC_RGB, blendFunc);
+ f->glGetIntegerv(GL_BLEND_SRC_ALPHA, blendFunc + 1);
+ f->glGetIntegerv(GL_BLEND_DST_RGB, blendFunc + 2);
+ f->glGetIntegerv(GL_BLEND_DST_ALPHA, blendFunc + 3);
+ f->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBuf);
+ if (vaoHelper->isValid())
+ f->glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vao);
+ for (int i = 0; i < 2; ++i) {
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &va[i].enabled);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &va[i].size);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &va[i].type);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &va[i].normalized);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &va[i].stride);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &va[i].buffer);
+ f->glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &va[i].pointer);
+ }
+ }
+ ~StateSaver() {
+ if (saved) {
+ f->glUseProgram(program);
+ f->glBindTexture(GL_TEXTURE_2D, texture);
+ f->glActiveTexture(activeTexture);
+ f->glFrontFace(frontFace);
+ if (cull)
+ f->glEnable(GL_CULL_FACE);
+ else
+ f->glDisable(GL_CULL_FACE);
+ if (depthTest)
+ f->glEnable(GL_DEPTH_TEST);
+ else
+ f->glDisable(GL_DEPTH_TEST);
+ if (blend)
+ f->glEnable(GL_BLEND);
+ else
+ f->glDisable(GL_BLEND);
+ f->glBlendFuncSeparate(blendFunc[0], blendFunc[1], blendFunc[2], blendFunc[3]);
+ f->glBindBuffer(GL_ARRAY_BUFFER, arrayBuf);
+ if (vaoHelper->isValid())
+ vaoHelper->glBindVertexArray(vao);
+ for (int i = 0; i < 2; ++i) {
+ if (va[i].enabled)
+ f->glEnableVertexAttribArray(i);
+ else
+ f->glDisableVertexAttribArray(i);
+ f->glBindBuffer(GL_ARRAY_BUFFER, va[i].buffer);
+ f->glVertexAttribPointer(i, va[i].size, va[i].type, va[i].normalized, va[i].stride, va[i].pointer);
+ }
+ }
+ delete vaoHelper;
+ }
+ QOpenGLFunctions *f;
+ QOpenGLVertexArrayObjectHelper *vaoHelper;
+ bool saved;
+ GLint program;
+ GLint texture;
+ GLint activeTexture;
+ GLint frontFace;
+ bool cull;
+ bool depthTest;
+ bool blend;
+ GLint blendFunc[4];
+ GLint vao;
+ GLint arrayBuf;
+ struct { GLint enabled, type, size, normalized, stride, buffer; GLvoid *pointer; } va[2];
+};
+
+void QEglFSCursor::draw(const QRectF &r)
+{
+ StateSaver stateSaver;
+
+ if (!m_program) {
+ // one time initialization
+ initializeOpenGLFunctions();
+
+ createShaderPrograms();
+
+ if (!m_cursorAtlas.texture) {
+ createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);
+
+ if (m_cursor.shape != Qt::BitmapCursor)
+ m_cursor.texture = m_cursorAtlas.texture;
+ }
+ }
+
+ if (m_cursor.shape == Qt::BitmapCursor && m_cursor.customCursorPending) {
+ // upload the custom cursor
+ createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage);
+ m_cursor.texture = m_cursor.customCursorTexture;
+ m_cursor.customCursorPending = false;
+ }
+
+ Q_ASSERT(m_cursor.texture);
+
+ m_program->bind();
+
+ const GLfloat x1 = r.left();
+ const GLfloat x2 = r.right();
+ const GLfloat y1 = r.top();
+ const GLfloat y2 = r.bottom();
+ const GLfloat cursorCoordinates[] = {
+ x1, y2,
+ x2, y2,
+ x1, y1,
+ x2, y1
+ };
+
+ const GLfloat s1 = m_cursor.textureRect.left();
+ const GLfloat s2 = m_cursor.textureRect.right();
+ const GLfloat t1 = m_cursor.textureRect.top();
+ const GLfloat t2 = m_cursor.textureRect.bottom();
+ const GLfloat textureCoordinates[] = {
+ s1, t2,
+ s2, t2,
+ s1, t1,
+ s2, t1
+ };
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_cursor.texture);
+
+ if (stateSaver.vaoHelper->isValid())
+ stateSaver.vaoHelper->glBindVertexArray(0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ m_program->setAttributeArray(0, cursorCoordinates, 2);
+ m_program->setAttributeArray(1, textureCoordinates, 2);
+
+ m_program->setUniformValue(m_textureEntry, 0);
+
+ glDisable(GL_CULL_FACE);
+ glFrontFace(GL_CCW);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST); // disable depth testing to make sure cursor is always on top
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ m_program->disableAttributeArray(0);
+ m_program->disableAttributeArray(1);
+ m_program->release();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.h b/src/plugins/platforms/eglfs/qeglfscursor.h
new file mode 100644
index 0000000000..be5db41b37
--- /dev/null
+++ b/src/plugins/platforms/eglfs/qeglfscursor.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSCURSOR_H
+#define QEGLFSCURSOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qeglfsglobal.h"
+#include <qpa/qplatformcursor.h>
+#include <qpa/qplatformscreen.h>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/private/qinputdevicemanager_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLShaderProgram;
+class QEglFSCursor;
+class QEglFSScreen;
+
+class QEglFSCursorDeviceListener : public QObject
+{
+ Q_OBJECT
+
+public:
+ QEglFSCursorDeviceListener(QEglFSCursor *cursor) : m_cursor(cursor) { }
+ bool hasMouse() const;
+
+public slots:
+ void onDeviceListChanged(QInputDeviceManager::DeviceType type);
+
+private:
+ QEglFSCursor *m_cursor;
+};
+
+class Q_EGLFS_EXPORT QEglFSCursor : public QPlatformCursor, protected QOpenGLFunctions
+{
+ Q_OBJECT
+public:
+ QEglFSCursor(QPlatformScreen *screen);
+ ~QEglFSCursor();
+
+#ifndef QT_NO_CURSOR
+ void changeCursor(QCursor *cursor, QWindow *widget) Q_DECL_OVERRIDE;
+#endif
+ void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
+ QPoint pos() const Q_DECL_OVERRIDE;
+ void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+
+ QRect cursorRect() const;
+ void paintOnScreen();
+ void resetResources();
+
+ void updateMouseStatus();
+
+private:
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+#ifndef QT_NO_CURSOR
+ bool setCurrentCursor(QCursor *cursor);
+#endif
+ void draw(const QRectF &rect);
+ void update(const QRegion &region);
+ void createShaderPrograms();
+ void createCursorTexture(uint *texture, const QImage &image);
+ void initCursorAtlas();
+
+ // current cursor information
+ struct Cursor {
+ Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0), customCursorPending(false) { }
+ uint texture; // a texture from 'image' or the atlas
+ Qt::CursorShape shape;
+ QRectF textureRect; // normalized rect inside texture
+ QSize size; // size of the cursor
+ QPoint hotSpot;
+ QImage customCursorImage;
+ QPoint pos; // current cursor position
+ uint customCursorTexture;
+ bool customCursorPending;
+ } m_cursor;
+
+ // cursor atlas information
+ struct CursorAtlas {
+ CursorAtlas() : cursorsPerRow(0), texture(0), cursorWidth(0), cursorHeight(0) { }
+ int cursorsPerRow;
+ uint texture;
+ int width, height; // width and height of the atlas
+ int cursorWidth, cursorHeight; // width and height of cursors inside the atlas
+ QList<QPoint> hotSpots;
+ QImage image; // valid until it's uploaded
+ } m_cursorAtlas;
+
+ bool m_visible;
+ QEglFSScreen *m_screen;
+ QOpenGLShaderProgram *m_program;
+ int m_textureEntry;
+ QEglFSCursorDeviceListener *m_deviceListener;
+ bool m_updateRequested;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSCURSOR_H
diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
index 359b90f205..064b9f6306 100644
--- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
@@ -33,8 +33,9 @@
#include "qeglfsdeviceintegration.h"
#include "qeglfsintegration.h"
+#include "qeglfscursor.h"
+#include "qeglfswindow.h"
#include <QtPlatformSupport/private/qeglconvenience_p.h>
-#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
#include <QGuiApplication>
#include <private/qguiapplication_p.h>
#include <QScreen>
@@ -99,6 +100,7 @@ QStringList QEGLDeviceIntegrationFactory::keys(const QString &pluginPath)
qCDebug(qLcEglDevDebug) << "EGL device integration plugin keys:" << list;
return list;
#else
+ Q_UNUSED(pluginPath);
return QStringList();
#endif
}
@@ -117,6 +119,9 @@ QEGLDeviceIntegration *QEGLDeviceIntegrationFactory::create(const QString &key,
qCDebug(qLcEglDevDebug) << "Using EGL device integration" << key;
else
qCWarning(qLcEglDevDebug) << "Failed to load EGL device integration" << key;
+#else
+ Q_UNUSED(key);
+ Q_UNUSED(pluginPath);
#endif
return integration;
}
@@ -171,6 +176,11 @@ EGLNativeDisplayType QEGLDeviceIntegration::platformDisplay() const
return EGL_DEFAULT_DISPLAY;
}
+EGLDisplay QEGLDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
+{
+ return eglGetDisplay(nativeDisplay);
+}
+
bool QEGLDeviceIntegration::usesDefaultScreen()
{
return true;
@@ -209,6 +219,11 @@ QDpi QEGLDeviceIntegration::logicalDpi() const
25.4 * s.height() / ps.height());
}
+qreal QEGLDeviceIntegration::pixelDensity() const
+{
+ return logicalDpi().first / qreal(100);
+}
+
Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const
{
return Qt::PrimaryOrientation;
@@ -234,6 +249,11 @@ qreal QEGLDeviceIntegration::refreshRate() const
return q_refreshRateFromFb(framebuffer);
}
+EGLint QEGLDeviceIntegration::surfaceType() const
+{
+ return EGL_WINDOW_BIT;
+}
+
QSurfaceFormat QEGLDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
{
QSurfaceFormat format = inputFormat;
@@ -253,6 +273,11 @@ bool QEGLDeviceIntegration::filterConfig(EGLDisplay, EGLConfig) const
return true;
}
+QEglFSWindow *QEGLDeviceIntegration::createWindow(QWindow *window) const
+{
+ return new QEglFSWindow(window);
+}
+
EGLNativeWindowType QEGLDeviceIntegration::createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
const QSurfaceFormat &format)
@@ -282,7 +307,7 @@ bool QEGLDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap)
QPlatformCursor *QEGLDeviceIntegration::createCursor(QPlatformScreen *screen) const
{
- return new QEGLPlatformCursor(screen);
+ return new QEglFSCursor(screen);
}
void QEGLDeviceIntegration::waitForVSync(QPlatformSurface *surface) const
@@ -309,4 +334,14 @@ bool QEGLDeviceIntegration::supportsPBuffers() const
return true;
}
+bool QEGLDeviceIntegration::supportsSurfacelessContexts() const
+{
+ return true;
+}
+
+void *QEGLDeviceIntegration::wlDisplay() const
+{
+ return Q_NULLPTR;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
index 260fc313f7..5ec98b37d1 100644
--- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
@@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
class QPlatformSurface;
+class QEglFSWindow;
#define QEGLDeviceIntegrationFactoryInterface_iid "org.qt-project.qt.qpa.egl.QEGLDeviceIntegrationFactoryInterface.5.5"
@@ -67,18 +68,22 @@ public:
virtual void platformInit();
virtual void platformDestroy();
virtual EGLNativeDisplayType platformDisplay() const;
+ virtual EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay);
virtual bool usesDefaultScreen();
virtual void screenInit();
virtual void screenDestroy();
virtual QSizeF physicalScreenSize() const;
virtual QSize screenSize() const;
virtual QDpi logicalDpi() const;
+ virtual qreal pixelDensity() const;
virtual Qt::ScreenOrientation nativeOrientation() const;
virtual Qt::ScreenOrientation orientation() const;
virtual int screenDepth() const;
virtual QImage::Format screenFormat() const;
virtual qreal refreshRate() const;
virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const;
+ virtual EGLint surfaceType() const;
+ virtual QEglFSWindow *createWindow(QWindow *window) const;
virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
const QSurfaceFormat &format);
@@ -92,6 +97,9 @@ public:
virtual QByteArray fbDeviceName() const;
virtual int framebufferIndex() const;
virtual bool supportsPBuffers() const;
+ virtual bool supportsSurfacelessContexts() const;
+
+ virtual void *wlDisplay() const;
};
class Q_EGLFS_EXPORT QEGLDeviceIntegrationPlugin : public QObject
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 5eb8485dc7..2086ce56e2 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -39,19 +39,46 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
-#include <qpa/qplatformcursor.h>
+#include <QtGui/QWindow>
+#include <QtCore/QLoggingCategory>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
#include "qeglfsintegration.h"
#include "qeglfswindow.h"
#include "qeglfshooks.h"
#include "qeglfscontext.h"
#include "qeglfsoffscreenwindow.h"
+#include "qeglfscursor.h"
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixservices_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qfbvthandler_p.h>
+#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h>
+
#include <QtPlatformHeaders/QEGLNativeContext>
+#ifndef QT_NO_LIBINPUT
+#include <QtPlatformSupport/private/qlibinputhandler_p.h>
+#endif
+
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
+#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
+#include <QtPlatformSupport/private/qevdevtouchmanager_p.h>
+#endif
+
+#if !defined(QT_NO_TSLIB) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+#include <QtPlatformSupport/private/qtslib_p.h>
+#endif
+
+#include <QtPlatformHeaders/qeglfsfunctions.h>
+
#include <EGL/egl.h>
static void initResources()
@@ -64,21 +91,18 @@ static void initResources()
QT_BEGIN_NAMESPACE
QEglFSIntegration::QEglFSIntegration()
+ : m_display(EGL_NO_DISPLAY),
+ m_inputContext(0),
+ m_fontDb(new QGenericUnixFontDatabase),
+ m_services(new QGenericUnixServices),
+ m_kbdMgr(0),
+ m_disableInputHandlers(false)
{
- mDisableInputHandlers = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DISABLE_INPUT");
+ m_disableInputHandlers = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DISABLE_INPUT");
initResources();
}
-bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const
-{
- // We assume that devices will have more and not less capabilities
- if (qt_egl_device_integration()->hasCapability(cap))
- return true;
-
- return QEGLPlatformIntegration::hasCapability(cap);
-}
-
void QEglFSIntegration::addScreen(QPlatformScreen *screen)
{
screenAdded(screen);
@@ -93,65 +117,316 @@ void QEglFSIntegration::initialize()
{
qt_egl_device_integration()->platformInit();
- QEGLPlatformIntegration::initialize();
+ m_display = qt_egl_device_integration()->createDisplay(nativeDisplay());
+ if (m_display == EGL_NO_DISPLAY)
+ qFatal("Could not open egl display");
- if (!mDisableInputHandlers)
- createInputHandlers();
+ EGLint major, minor;
+ if (!eglInitialize(m_display, &major, &minor))
+ qFatal("Could not initialize egl display");
+
+ m_inputContext = QPlatformInputContextFactory::create();
+
+ m_vtHandler.reset(new QFbVtHandler);
if (qt_egl_device_integration()->usesDefaultScreen())
addScreen(new QEglFSScreen(display()));
else
qt_egl_device_integration()->screenInit();
+
+ // Input code may rely on the screens, so do it only after the screen init.
+ if (!m_disableInputHandlers)
+ createInputHandlers();
}
void QEglFSIntegration::destroy()
{
foreach (QWindow *w, qGuiApp->topLevelWindows())
w->destroy();
+
qt_egl_device_integration()->screenDestroy();
- if (display() != EGL_NO_DISPLAY)
- eglTerminate(display());
+
+ if (m_display != EGL_NO_DISPLAY)
+ eglTerminate(m_display);
+
qt_egl_device_integration()->platformDestroy();
}
-EGLNativeDisplayType QEglFSIntegration::nativeDisplay() const
+QAbstractEventDispatcher *QEglFSIntegration::createEventDispatcher() const
{
- return qt_egl_device_integration()->platformDisplay();
+ return createUnixEventDispatcher();
}
-QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const
+QPlatformServices *QEglFSIntegration::services() const
{
- return new QEglFSWindow(window);
+ return m_services.data();
}
-QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format,
- QPlatformOpenGLContext *shareContext,
- EGLDisplay display,
- QVariant *nativeHandle) const
+QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
{
+ return m_fontDb.data();
+}
+
+QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ QOpenGLCompositorBackingStore *bs = new QOpenGLCompositorBackingStore(window);
+ if (!window->handle())
+ window->create();
+ static_cast<QEglFSWindow *>(window->handle())->setBackingStore(bs);
+ return bs;
+}
+
+QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
+{
+ QWindowSystemInterface::flushWindowSystemEvents();
+ QEglFSWindow *w = qt_egl_device_integration()->createWindow(window);
+ w->create();
+ if (window->type() != Qt::ToolTip)
+ w->requestActivateWindow();
+ return w;
+}
+
+QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ // If there is a "root" window into which raster and QOpenGLWidget content is
+ // composited, all other contexts must share with its context.
+ QOpenGLContext *compositingContext = QOpenGLCompositor::instance()->context();
+ EGLDisplay dpy = context->screen() ? static_cast<QEglFSScreen *>(context->screen()->handle())->display() : display();
+ QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle();
+ QVariant nativeHandle = context->nativeHandle();
+
QEglFSContext *ctx;
- QSurfaceFormat adjustedFormat = qt_egl_device_integration()->surfaceFormatFor(format);
- if (!nativeHandle || nativeHandle->isNull()) {
- EGLConfig config = QEglFSIntegration::chooseConfig(display, adjustedFormat);
- ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant());
+ QSurfaceFormat adjustedFormat = qt_egl_device_integration()->surfaceFormatFor(context->format());
+ if (nativeHandle.isNull()) {
+ EGLConfig config = QEglFSIntegration::chooseConfig(dpy, adjustedFormat);
+ ctx = new QEglFSContext(adjustedFormat, share, dpy, &config, QVariant());
} else {
- ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle);
+ ctx = new QEglFSContext(adjustedFormat, share, dpy, 0, nativeHandle);
}
- *nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display));
+ nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), dpy));
+
+ context->setNativeHandle(nativeHandle);
return ctx;
}
-QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display,
- const QSurfaceFormat &format,
- QOffscreenSurface *surface) const
+QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ EGLDisplay dpy = surface->screen() ? static_cast<QEglFSScreen *>(surface->screen()->handle())->display() : display();
+ QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(surface->requestedFormat());
+ if (qt_egl_device_integration()->supportsPBuffers()) {
+ QEGLPlatformContext::Flags flags = 0;
+ if (!qt_egl_device_integration()->supportsSurfacelessContexts())
+ flags |= QEGLPlatformContext::NoSurfaceless;
+ return new QEGLPbuffer(dpy, fmt, surface, flags);
+ } else {
+ return new QEglFSOffscreenWindow(dpy, fmt, surface);
+ }
+ // Never return null. Multiple QWindows are not supported by this plugin.
+}
+
+bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ // We assume that devices will have more and not less capabilities
+ if (qt_egl_device_integration()->hasCapability(cap))
+ return true;
+
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL: return true;
+ case ThreadedOpenGL: return true;
+ case WindowManagement: return false;
+ case RasterGLSurface: return true;
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformNativeInterface *QEglFSIntegration::nativeInterface() const
+{
+ return const_cast<QEglFSIntegration *>(this);
+}
+
+enum ResourceType {
+ EglDisplay,
+ EglWindow,
+ EglContext,
+ EglConfig,
+ NativeDisplay,
+ XlibDisplay,
+ WaylandDisplay
+};
+
+static int resourceType(const QByteArray &key)
{
- QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(format);
- if (qt_egl_device_integration()->supportsPBuffers())
- return new QEGLPbuffer(display, fmt, surface);
+ static const QByteArray names[] = { // match ResourceType
+ QByteArrayLiteral("egldisplay"),
+ QByteArrayLiteral("eglwindow"),
+ QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("eglconfig"),
+ QByteArrayLiteral("nativedisplay"),
+ QByteArrayLiteral("display"),
+ QByteArrayLiteral("server_wl_display")
+ };
+ const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
+ const QByteArray *result = std::find(names, end, key);
+ if (result == end)
+ result = std::find(names, end, key.toLower());
+ return int(result - names);
+}
+
+void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglDisplay:
+ result = display();
+ break;
+ case NativeDisplay:
+ result = reinterpret_cast<void*>(nativeDisplay());
+ break;
+ case WaylandDisplay:
+ result = qt_egl_device_integration()->wlDisplay();
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEglFSIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case XlibDisplay:
+ // Play nice when using the x11 hooks: Be compatible with xcb that allows querying
+ // the X Display pointer, which is nothing but our native display.
+ result = reinterpret_cast<void*>(nativeDisplay());
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglDisplay:
+ if (window && window->handle())
+ result = static_cast<QEglFSScreen *>(window->handle()->screen())->display();
+ else
+ result = display();
+ break;
+ case EglWindow:
+ if (window && window->handle())
+ result = reinterpret_cast<void*>(static_cast<QEglFSWindow *>(window->handle())->eglWindow());
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
+{
+ void *result = 0;
+
+ switch (resourceType(resource)) {
+ case EglContext:
+ if (context->handle())
+ result = static_cast<QEglFSContext *>(context->handle())->eglContext();
+ break;
+ case EglConfig:
+ if (context->handle())
+ result = static_cast<QEglFSContext *>(context->handle())->eglConfig();
+ break;
+ case EglDisplay:
+ if (context->handle())
+ result = static_cast<QEglFSContext *>(context->handle())->eglDisplay();
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static void *eglContextForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+
+ QEglFSContext *handle = static_cast<QEglFSContext *>(context->handle());
+ if (!handle)
+ return 0;
+
+ return handle->eglContext();
+}
+
+QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "get_egl_context")
+ return NativeResourceForContextFunction(eglContextForContext);
+
+ return 0;
+}
+
+QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function) const
+{
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
+ return QFunctionPointer(loadKeymapStatic);
+#else
+ Q_UNUSED(function)
+#endif
+
+ return 0;
+}
+
+void QEglFSIntegration::loadKeymapStatic(const QString &filename)
+{
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ QEglFSIntegration *self = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ if (self->m_kbdMgr)
+ self->m_kbdMgr->loadKeymap(filename);
else
- return new QEglFSOffscreenWindow(display, fmt, surface);
+ qWarning("QEglFSIntegration: Cannot load keymap, no keyboard handler found");
+#else
+ Q_UNUSED(filename);
+#endif
+}
- // Never return null. Multiple QWindows are not supported by this plugin.
+void QEglFSIntegration::createInputHandlers()
+{
+#ifndef QT_NO_LIBINPUT
+ if (!qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) {
+ new QLibInputHandler(QLatin1String("libinput"), QString());
+ return;
+ }
+#endif
+
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
+ m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
+ new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
+#ifndef QT_NO_TSLIB
+ const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB");
+ if (useTslib)
+ new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */);
+ else
+#endif // QT_NO_TSLIB
+ new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this);
+#endif
+}
+
+EGLNativeDisplayType QEglFSIntegration::nativeDisplay() const
+{
+ return qt_egl_device_integration()->platformDisplay();
}
EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
@@ -167,6 +442,7 @@ EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceForm
};
Chooser chooser(display);
+ chooser.setSurfaceType(qt_egl_device_integration()->surfaceType());
chooser.setSurfaceFormat(format);
return chooser.chooseConfig();
}
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index 11b643d540..98c7ee9f78 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -34,41 +34,72 @@
#ifndef QEGLFSINTEGRATION_H
#define QEGLFSINTEGRATION_H
-#include <QtPlatformSupport/private/qeglplatformintegration_p.h>
+#include <QtCore/QVariant>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformscreen.h>
#include <EGL/egl.h>
#include "qeglfsglobal.h"
QT_BEGIN_NAMESPACE
-class Q_EGLFS_EXPORT QEglFSIntegration : public QEGLPlatformIntegration
+class QEglFSWindow;
+class QEglFSContext;
+class QFbVtHandler;
+class QEvdevKeyboardManager;
+
+class Q_EGLFS_EXPORT QEglFSIntegration : public QPlatformIntegration, public QPlatformNativeInterface
{
public:
QEglFSIntegration();
- void addScreen(QPlatformScreen *screen);
- void removeScreen(QPlatformScreen *screen);
-
void initialize() Q_DECL_OVERRIDE;
void destroy() Q_DECL_OVERRIDE;
+ EGLDisplay display() const { return m_display; }
+
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QPlatformServices *services() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; }
+
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
+
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
+ QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
-protected:
- QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QEGLPlatformContext *createContext(const QSurfaceFormat &format,
- QPlatformOpenGLContext *shareContext,
- EGLDisplay display,
- QVariant *nativeHandle) const Q_DECL_OVERRIDE;
- QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
- const QSurfaceFormat &format,
- QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
- EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
+ // QPlatformNativeInterface
+ void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
+
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+
+ QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
+
+ void addScreen(QPlatformScreen *screen);
+ void removeScreen(QPlatformScreen *screen);
+
+ static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format);
private:
- bool mDisableInputHandlers;
+ EGLNativeDisplayType nativeDisplay() const;
+ void createInputHandlers();
+ static void loadKeymapStatic(const QString &filename);
+
+ EGLDisplay m_display;
+ QPlatformInputContext *m_inputContext;
+ QScopedPointer<QPlatformFontDatabase> m_fontDb;
+ QScopedPointer<QPlatformServices> m_services;
+ QScopedPointer<QFbVtHandler> m_vtHandler;
+ QEvdevKeyboardManager *m_kbdMgr;
+ bool m_disableInputHandlers;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index 1b6e2307f8..a14e68b667 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -32,7 +32,10 @@
****************************************************************************/
#include <QtCore/qtextstream.h>
-#include <QtGui/qpa/qplatformcursor.h>
+#include <QtGui/qwindow.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformcursor.h>
+#include <QtPlatformSupport/private/qopenglcompositor_p.h>
#include "qeglfsscreen.h"
#include "qeglfswindow.h"
@@ -41,7 +44,7 @@
QT_BEGIN_NAMESPACE
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
- : QEGLPlatformScreen(dpy),
+ : m_dpy(dpy),
m_surface(EGL_NO_SURFACE),
m_cursor(0)
{
@@ -51,6 +54,7 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
QEglFSScreen::~QEglFSScreen()
{
delete m_cursor;
+ QOpenGLCompositor::destroy();
}
QRect QEglFSScreen::geometry() const
@@ -78,6 +82,11 @@ QDpi QEglFSScreen::logicalDpi() const
return qt_egl_device_integration()->logicalDpi();
}
+qreal QEglFSScreen::pixelDensity() const
+{
+ return qt_egl_device_integration()->pixelDensity();
+}
+
Qt::ScreenOrientation QEglFSScreen::nativeOrientation() const
{
return qt_egl_device_integration()->nativeOrientation();
@@ -103,4 +112,89 @@ void QEglFSScreen::setPrimarySurface(EGLSurface surface)
m_surface = surface;
}
+void QEglFSScreen::handleCursorMove(const QPoint &pos)
+{
+ const QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
+ const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
+
+ // Generate enter and leave events like a real windowing system would do.
+ if (windows.isEmpty())
+ return;
+
+ // First window is always fullscreen.
+ if (windows.count() == 1) {
+ QWindow *window = windows[0]->sourceWindow();
+ if (m_pointerWindow != window) {
+ m_pointerWindow = window;
+ QWindowSystemInterface::handleEnterEvent(window, window->mapFromGlobal(pos), pos);
+ }
+ return;
+ }
+
+ QWindow *enter = 0, *leave = 0;
+ for (int i = windows.count() - 1; i >= 0; --i) {
+ QWindow *window = windows[i]->sourceWindow();
+ const QRect geom = window->geometry();
+ if (geom.contains(pos)) {
+ if (m_pointerWindow != window) {
+ leave = m_pointerWindow;
+ m_pointerWindow = window;
+ enter = window;
+ }
+ break;
+ }
+ }
+
+ if (enter && leave)
+ QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos);
+}
+
+QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) const
+{
+ QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
+ const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
+ Q_ASSERT(!windows.isEmpty());
+
+ QImage img;
+
+ if (static_cast<QEglFSWindow *>(windows.first()->sourceWindow()->handle())->isRaster()) {
+ // Request the compositor to render everything into an FBO and read it back. This
+ // is of course slow, but it's safe and reliable. It will not include the mouse
+ // cursor, which is a plus.
+ img = compositor->grab();
+ } else {
+ // Just a single OpenGL window without compositing. Do not support this case for now. Doing
+ // glReadPixels is not an option since it would read from the back buffer which may have
+ // undefined content when calling right after a swapBuffers (unless preserved swap is
+ // available and enabled, but we have no support for that).
+ qWarning("grabWindow: Not supported for non-composited OpenGL content. Use QQuickWindow::grabWindow() instead.");
+ return QPixmap();
+ }
+
+ if (!wid) {
+ const QSize screenSize = geometry().size();
+ if (width < 0)
+ width = screenSize.width() - x;
+ if (height < 0)
+ height = screenSize.height() - y;
+ return QPixmap::fromImage(img).copy(x, y, width, height);
+ }
+
+ foreach (QOpenGLCompositorWindow *w, windows) {
+ const QWindow *window = w->sourceWindow();
+ if (window->winId() == wid) {
+ const QRect geom = window->geometry();
+ if (width < 0)
+ width = geom.width() - x;
+ if (height < 0)
+ height = geom.height() - y;
+ QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
+ rect &= window->geometry();
+ return QPixmap::fromImage(img).copy(rect);
+ }
+ }
+
+ return QPixmap();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h
index 07b6ff63ef..8f1d87ea25 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.h
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.h
@@ -35,7 +35,7 @@
#define QEGLFSSCREEN_H
#include "qeglfsglobal.h"
-#include <QtPlatformSupport/private/qeglplatformscreen_p.h>
+#include <QtCore/QPointer>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
@@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
class QEglFSWindow;
class QOpenGLContext;
-class Q_EGLFS_EXPORT QEglFSScreen : public QEGLPlatformScreen
+class Q_EGLFS_EXPORT QEglFSScreen : public QPlatformScreen
{
public:
QEglFSScreen(EGLDisplay display);
@@ -55,6 +55,7 @@ public:
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
+ qreal pixelDensity() const Q_DECL_OVERRIDE;
Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
@@ -62,16 +63,23 @@ public:
qreal refreshRate() const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+
EGLSurface primarySurface() const { return m_surface; }
-protected:
- void setPrimarySurface(EGLSurface surface);
+ EGLDisplay display() const { return m_dpy; }
+
+ void handleCursorMove(const QPoint &pos);
private:
- friend class QEglFSWindow;
+ void setPrimarySurface(EGLSurface surface);
+ EGLDisplay m_dpy;
+ QPointer<QWindow> m_pointerWindow;
EGLSurface m_surface;
QPlatformCursor *m_cursor;
+
+ friend class QEglFSWindow;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index c0d51c94a5..8301be8c17 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -37,21 +37,23 @@
#include <private/qguiapplication_p.h>
#include <QtGui/private/qopenglcontext_p.h>
#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
+#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h>
#include "qeglfswindow.h"
+#include "qeglfscursor.h"
#include "qeglfshooks.h"
-#include <QtDebug>
-
QT_BEGIN_NAMESPACE
QEglFSWindow::QEglFSWindow(QWindow *w)
- : QEGLPlatformWindow(w)
- , m_surface(0)
- , m_window(0)
- , m_flags(0)
+ : QPlatformWindow(w),
+ m_backingStore(0),
+ m_raster(false),
+ m_winId(0),
+ m_surface(EGL_NO_SURFACE),
+ m_window(0),
+ m_flags(0)
{
}
@@ -60,12 +62,34 @@ QEglFSWindow::~QEglFSWindow()
destroy();
}
+static WId newWId()
+{
+ static WId id = 0;
+
+ if (id == std::numeric_limits<WId>::max())
+ qWarning("QEGLPlatformWindow: Out of window IDs");
+
+ return ++id;
+}
+
void QEglFSWindow::create()
{
if (m_flags.testFlag(Created))
return;
- QEGLPlatformWindow::create();
+ m_winId = newWId();
+
+ // Save the original surface type before changing to OpenGLSurface.
+ m_raster = (window()->surfaceType() == QSurface::RasterSurface);
+ if (m_raster) // change to OpenGL, but not for RasterGLSurface
+ window()->setSurfaceType(QSurface::OpenGLSurface);
+
+ if (window()->type() == Qt::Desktop) {
+ QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
+ QPlatformWindow::setGeometry(fullscreenRect);
+ QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
+ return;
+ }
m_flags = Created;
@@ -96,13 +120,14 @@ void QEglFSWindow::create()
setGeometry(QRect()); // will become fullscreen
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
- EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display();
- QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
- m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
- m_format = q_glFormatFromConfig(display, m_config, platformFormat);
-
resetSurface();
+ if (m_surface == EGL_NO_SURFACE) {
+ EGLint error = eglGetError();
+ eglTerminate(screen->display());
+ qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
+ }
+
screen->setPrimarySurface(m_surface);
if (isRaster()) {
@@ -120,7 +145,7 @@ void QEglFSWindow::destroy()
{
QEglFSScreen *screen = this->screen();
if (m_flags.testFlag(HasNativeWindow)) {
- QEGLPlatformCursor *cursor = qobject_cast<QEGLPlatformCursor *>(screen->cursor());
+ QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(screen->cursor());
if (cursor)
cursor->resetResources();
@@ -134,15 +159,10 @@ void QEglFSWindow::destroy()
QOpenGLCompositor::instance()->removeWindow(this);
}
-// The virtual functions resetSurface and invalidateSurface may get overridden
-// in derived classes, for example in the Android port, to perform the native
-// window and surface creation differently.
-
void QEglFSWindow::invalidateSurface()
{
if (m_surface != EGL_NO_SURFACE) {
- EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
- eglDestroySurface(display, m_surface);
+ eglDestroySurface(screen()->display(), m_surface);
m_surface = EGL_NO_SURFACE;
}
qt_egl_device_integration()->destroyNativeWindow(m_window);
@@ -151,15 +171,13 @@ void QEglFSWindow::invalidateSurface()
void QEglFSWindow::resetSurface()
{
- QEglFSScreen *nativeScreen = static_cast<QEglFSScreen *>(screen());
- EGLDisplay display = nativeScreen->display();
- m_window = qt_egl_device_integration()->createNativeWindow(this, nativeScreen->geometry().size(), m_format);
+ EGLDisplay display = screen()->display();
+ QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
+
+ m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
+ m_window = qt_egl_device_integration()->createNativeWindow(this, screen()->geometry().size(), m_format);
m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL);
- if (m_surface == EGL_NO_SURFACE) {
- EGLint error = eglGetError();
- eglTerminate(display);
- qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
- }
}
void QEglFSWindow::setVisible(bool visible)
@@ -265,4 +283,41 @@ QEglFSScreen *QEglFSWindow::screen() const
return static_cast<QEglFSScreen *>(QPlatformWindow::screen());
}
+bool QEglFSWindow::isRaster() const
+{
+ return m_raster || window()->surfaceType() == QSurface::RasterGLSurface;
+}
+
+QWindow *QEglFSWindow::sourceWindow() const
+{
+ return window();
+}
+
+const QPlatformTextureList *QEglFSWindow::textures() const
+{
+ if (m_backingStore)
+ return m_backingStore->textures();
+
+ return 0;
+}
+
+void QEglFSWindow::endCompositing()
+{
+ if (m_backingStore)
+ m_backingStore->notifyComposited();
+}
+
+WId QEglFSWindow::winId() const
+{
+ return m_winId;
+}
+
+void QEglFSWindow::setOpacity(qreal)
+{
+ if (!isRaster())
+ qWarning("QEglFSWindow: Cannot set opacity for non-raster windows");
+
+ // Nothing to do here. The opacity is stored in the QWindow.
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h
index f9d207c153..806b21de0a 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.h
+++ b/src/plugins/platforms/eglfs/qeglfswindow.h
@@ -37,17 +37,23 @@
#include "qeglfsintegration.h"
#include "qeglfsscreen.h"
#include "qeglfsglobal.h"
-#include <QtPlatformSupport/private/qeglplatformwindow_p.h>
+
+#include <qpa/qplatformwindow.h>
+#include <QtPlatformSupport/private/qopenglcompositor_p.h>
+#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
-class Q_EGLFS_EXPORT QEglFSWindow : public QEGLPlatformWindow
+class QOpenGLCompositorBackingStore;
+class QPlatformTextureList;
+
+class Q_EGLFS_EXPORT QEglFSWindow : public QPlatformWindow, public QOpenGLCompositorWindow
{
public:
QEglFSWindow(QWindow *w);
~QEglFSWindow();
- void create() Q_DECL_OVERRIDE;
+ void create();
void destroy();
void setGeometry(const QRect &) Q_DECL_OVERRIDE;
@@ -58,13 +64,15 @@ public:
void lower() Q_DECL_OVERRIDE;
void propagateSizeHints() Q_DECL_OVERRIDE { }
- void setOpacity(qreal) Q_DECL_OVERRIDE { }
void setMask(const QRegion &) Q_DECL_OVERRIDE { }
bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
bool setMouseGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
+ void setOpacity(qreal) Q_DECL_OVERRIDE;
+ WId winId() const Q_DECL_OVERRIDE;
QSurfaceFormat format() const Q_DECL_OVERRIDE;
- EGLNativeWindowType eglWindow() const Q_DECL_OVERRIDE;
+
+ EGLNativeWindowType eglWindow() const;
EGLSurface surface() const;
QEglFSScreen *screen() const;
@@ -73,11 +81,22 @@ public:
virtual void invalidateSurface() Q_DECL_OVERRIDE;
virtual void resetSurface();
+ QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; }
+ void setBackingStore(QOpenGLCompositorBackingStore *backingStore) { m_backingStore = backingStore; }
+ bool isRaster() const;
+
+ QWindow *sourceWindow() const Q_DECL_OVERRIDE;
+ const QPlatformTextureList *textures() const Q_DECL_OVERRIDE;
+ void endCompositing() Q_DECL_OVERRIDE;
+
protected:
+ QOpenGLCompositorBackingStore *m_backingStore;
+ bool m_raster;
+ WId m_winId;
+
EGLSurface m_surface;
EGLNativeWindowType m_window;
-private:
EGLConfig m_config;
QSurfaceFormat m_format;
diff --git a/src/plugins/platforms/haiku/qhaikuclipboard.cpp b/src/plugins/platforms/haiku/qhaikuclipboard.cpp
index f3aa9dc36e..a2d7e96d71 100644
--- a/src/plugins/platforms/haiku/qhaikuclipboard.cpp
+++ b/src/plugins/platforms/haiku/qhaikuclipboard.cpp
@@ -41,6 +41,8 @@
#include <Clipboard.h>
QHaikuClipboard::QHaikuClipboard()
+ : m_systemMimeData(Q_NULLPTR)
+ , m_userMimeData(Q_NULLPTR)
{
if (be_clipboard)
be_clipboard->StartWatching(BMessenger(this));
@@ -50,17 +52,26 @@ QHaikuClipboard::~QHaikuClipboard()
{
if (be_clipboard)
be_clipboard->StopWatching(BMessenger(this));
+
+ delete m_userMimeData;
+ delete m_systemMimeData;
}
QMimeData *QHaikuClipboard::mimeData(QClipboard::Mode mode)
{
- QMimeData *mimeData = new QMimeData();
-
if (mode != QClipboard::Clipboard)
- return mimeData;
+ return 0;
+
+ if (m_userMimeData)
+ return m_userMimeData;
if (!be_clipboard->Lock())
- return mimeData;
+ return 0;
+
+ if (!m_systemMimeData)
+ m_systemMimeData = new QMimeData();
+ else
+ m_systemMimeData->clear();
const BMessage *clipboard = be_clipboard->Data();
if (clipboard) {
@@ -76,11 +87,11 @@ QMimeData *QHaikuClipboard::mimeData(QClipboard::Mode mode)
if (dataLen && (status == B_OK)) {
const QString format = QString::fromLatin1(name);
if (format == QStringLiteral("text/plain")) {
- mimeData->setText(QString::fromLocal8Bit(reinterpret_cast<const char*>(data), dataLen));
+ m_systemMimeData->setText(QString::fromLocal8Bit(reinterpret_cast<const char*>(data), dataLen));
} else if (format == QStringLiteral("text/html")) {
- mimeData->setHtml(QString::fromLocal8Bit(reinterpret_cast<const char*>(data), dataLen));
+ m_systemMimeData->setHtml(QString::fromLocal8Bit(reinterpret_cast<const char*>(data), dataLen));
} else {
- mimeData->setData(format, QByteArray(reinterpret_cast<const char*>(data), dataLen));
+ m_systemMimeData->setData(format, QByteArray(reinterpret_cast<const char*>(data), dataLen));
}
}
}
@@ -88,7 +99,7 @@ QMimeData *QHaikuClipboard::mimeData(QClipboard::Mode mode)
be_clipboard->Unlock();
- return mimeData;
+ return m_systemMimeData;
}
void QHaikuClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
@@ -96,6 +107,14 @@ void QHaikuClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
if (mode != QClipboard::Clipboard)
return;
+ if (mimeData) {
+ if (m_systemMimeData == mimeData)
+ return;
+
+ if (m_userMimeData == mimeData)
+ return;
+ }
+
if (!be_clipboard->Lock())
return;
@@ -115,6 +134,10 @@ void QHaikuClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
qWarning("Unable to store mime data on clipboard");
be_clipboard->Unlock();
+
+ m_userMimeData = mimeData;
+
+ emitChanged(QClipboard::Clipboard);
}
bool QHaikuClipboard::supportsMode(QClipboard::Mode mode) const
@@ -131,8 +154,12 @@ bool QHaikuClipboard::ownsMode(QClipboard::Mode mode) const
void QHaikuClipboard::MessageReceived(BMessage* message)
{
- if (message->what == B_CLIPBOARD_CHANGED)
+ if (message->what == B_CLIPBOARD_CHANGED) {
+ delete m_userMimeData;
+ m_userMimeData = Q_NULLPTR;
+
emitChanged(QClipboard::Clipboard);
+ }
BHandler::MessageReceived(message);
}
diff --git a/src/plugins/platforms/haiku/qhaikuclipboard.h b/src/plugins/platforms/haiku/qhaikuclipboard.h
index 0dc2bfdd3b..3c1f92c615 100644
--- a/src/plugins/platforms/haiku/qhaikuclipboard.h
+++ b/src/plugins/platforms/haiku/qhaikuclipboard.h
@@ -55,6 +55,10 @@ public:
// override from BHandler to catch change notifications from Haiku clipboard
void MessageReceived(BMessage* message) Q_DECL_OVERRIDE;
+
+private:
+ QMimeData *m_systemMimeData;
+ QMimeData *m_userMimeData;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.cpp b/src/plugins/platforms/haiku/qhaikuwindow.cpp
index 5768e1cb40..9622d12111 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.cpp
+++ b/src/plugins/platforms/haiku/qhaikuwindow.cpp
@@ -130,6 +130,7 @@ QHaikuWindow::QHaikuWindow(QWindow *window)
if (!m_window)
qFatal("QHaikuWindow: failed to create window");
+ setGeometry(rect);
setWindowFlags(window->flags());
}
@@ -164,13 +165,13 @@ void QHaikuWindow::setVisible(bool visible)
{
if (visible) {
m_window->Show();
+
+ window()->requestActivate();
+
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), window()->geometry().size()));
} else {
m_window->Hide();
}
-
- window()->requestActivate();
-
- QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
}
bool QHaikuWindow::isExposed() const
@@ -306,10 +307,8 @@ void QHaikuWindow::haikuWindowMoved(const QPoint &pos)
const QRect newGeometry(pos, geometry().size());
QPlatformWindow::setGeometry(newGeometry);
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(true);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
- QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(false);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
}
void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
@@ -317,10 +316,8 @@ void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
const QRect newGeometry(geometry().topLeft(), size);
QPlatformWindow::setGeometry(newGeometry);
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(true);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
- QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
- QWindowSystemInterface::setSynchronousWindowsSystemEvents(false);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
if ((m_windowState == Qt::WindowMaximized) && !zoomInProgress) {
// the user has resized the window while maximized -> reset maximized flag
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
index 92799f80c1..7a37e213bd 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -43,7 +43,7 @@
@implementation QIOSApplicationStateListener
-- (id) init
+- (id)init
{
self = [super init];
if (self) {
@@ -75,7 +75,7 @@
return self;
}
-- (void) dealloc
+- (void)dealloc
{
[[NSNotificationCenter defaultCenter]
removeObserver:self
@@ -92,12 +92,12 @@
[super dealloc];
}
-- (void) applicationDidBecomeActive
+- (void)applicationDidBecomeActive
{
[self handleApplicationStateChanged:UIApplicationStateActive];
}
-- (void) applicationWillResignActive
+- (void)applicationWillResignActive
{
// Note that UIApplication is still UIApplicationStateActive at this
// point, but since there is no separate notification for the inactive
@@ -105,12 +105,12 @@
[self handleApplicationStateChanged:UIApplicationStateInactive];
}
-- (void) applicationDidEnterBackground
+- (void)applicationDidEnterBackground
{
[self handleApplicationStateChanged:UIApplicationStateBackground];
}
-- (void) handleApplicationStateChanged:(UIApplicationState) uiApplicationState
+- (void)handleApplicationStateChanged:(UIApplicationState)uiApplicationState
{
// We may receive application state changes after QCoreApplication has
// gone down, as the block we schedule on the main queue keeps the
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index 192ee67689..e0c6ec5d72 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -62,7 +62,7 @@
@implementation QUIClipboard
--(id)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
+- (id)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
{
self = [super init];
if (self) {
@@ -87,7 +87,7 @@
return self;
}
--(void)dealloc
+- (void)dealloc
{
[[NSNotificationCenter defaultCenter]
removeObserver:self
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
index fdaa7e68fe..98977eb670 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -34,7 +34,7 @@
#ifndef QIOSEVENTDISPATCHER_H
#define QIOSEVENTDISPATCHER_H
-#include <QtPlatformSupport/private/qeventdispatcher_cf_p.h>
+#include <QtCore/private/qeventdispatcher_cf_p.h>
QT_BEGIN_NAMESPACE
@@ -46,6 +46,7 @@ public:
explicit QIOSEventDispatcher(QObject *parent = 0);
bool processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
+ bool processPostedEvents() Q_DECL_OVERRIDE;
void handleRunLoopExit(CFRunLoopActivity activity);
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index fc12e83a81..0e9f176487 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -39,6 +39,8 @@
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qthread_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import <Foundation/NSProcessInfo.h>
@@ -198,7 +200,7 @@ namespace
bool debugStackUsage = false;
}
-extern "C" int __attribute__((weak)) main(int argc, char *argv[])
+extern "C" int qt_main_wrapper(int argc, char *argv[])
{
@autoreleasepool {
size_t defaultStackSize = 512 * kBytesPerKiloByte; // Same as secondary threads
@@ -233,18 +235,7 @@ enum SetJumpResult
kJumpedFromUserMainTrampoline,
};
-// We define qtmn so that user_main_trampoline() will not cause
-// missing symbols in the case of hybrid applications that don't
-// use our main wrapper. Since the symbol is weak, it will not
-// get used or cause a clash in the normal Qt application usecase,
-// where we rename main to qtmn before linking.
-extern "C" int __attribute__((weak)) qtmn(int argc, char *argv[])
-{
- Q_UNUSED(argc);
- Q_UNUSED(argv);
-
- Q_UNREACHABLE();
-}
+extern "C" int main(int argc, char *argv[]);
static void __attribute__((noinline, noreturn)) user_main_trampoline()
{
@@ -263,7 +254,7 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline()
qFatal("Could not convert argv[%d] to C string", i);
}
- int exitCode = qtmn(argc, argv);
+ int exitCode = main(argc, argv);
delete[] argv;
qEventDispatcherDebug() << "Returned from main with exit code " << exitCode;
@@ -293,7 +284,7 @@ static bool rootLevelRunLoopIntegration()
@implementation QIOSApplicationStateTracker
-+ (void) load
++ (void)load
{
[[NSNotificationCenter defaultCenter]
addObserver:self
@@ -323,7 +314,7 @@ static bool rootLevelRunLoopIntegration()
# error "Unknown processor family"
#endif
-+ (void) applicationDidFinishLaunching
++ (void)applicationDidFinishLaunching
{
if (!isQtApplication())
return;
@@ -377,7 +368,7 @@ static bool rootLevelRunLoopIntegration()
// four bits of the exit code (exit(3) will only pass on the lower 8 bits).
static const char kApplicationWillTerminateExitCode = SIGTERM | 0x80;
-+ (void) applicationWillTerminate
++ (void)applicationWillTerminate
{
if (!isQtApplication())
return;
@@ -472,6 +463,25 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
return processedEvents;
}
+/*!
+ Override of the CoreFoundation posted events runloop source callback
+ so that we can send window system (QPA) events in addition to sending
+ normal Qt events.
+*/
+bool QIOSEventDispatcher::processPostedEvents()
+{
+ // Don't send window system events if the base CF dispatcher has determined
+ // that events should not be sent for this pass of the runloop source.
+ if (!QEventDispatcherCoreFoundation::processPostedEvents())
+ return false;
+
+ qEventDispatcherDebug() << "Sending window system events for " << m_processEvents.flags; qIndent();
+ QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
+ qUnIndent();
+
+ return true;
+}
+
void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
{
Q_UNUSED(activity);
diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
index 761a89c989..bb12c164d6 100644
--- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
@@ -48,20 +48,29 @@ static QThreadStorage<QPointer<QIOSAssetData> > g_assetDataCache;
static const int kBufferSize = 10;
static ALAsset *kNoAsset = 0;
-static void ensureAuthorizationDialogNotBlocked()
+static bool ensureAuthorizationDialogNotBlocked()
{
if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusNotDetermined)
- return;
+ return true;
+
if (static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec)
- return;
-
- // Since authorization status has not been determined, the user will be asked
- // to authorize the app. But since main has not finished, the dialog will be held
- // back until the launch completes. To avoid a dead-lock below, we start an event
- // loop to complete the launch.
- QEventLoop loop;
- QTimer::singleShot(1, &loop, &QEventLoop::quit);
- loop.exec();
+ return true;
+
+ if ([NSThread isMainThread]) {
+ // The dialog is about to show, but since main has not finished, the dialog will be held
+ // back until the launch completes. This is problematic since we cannot successfully return
+ // back to the caller before the asset is ready, which also includes showing the dialog. To
+ // work around this, we create an event loop to that will complete the launch (return from the
+ // applicationDidFinishLaunching callback). But this will only work if we're on the main thread.
+ QEventLoop loop;
+ QTimer::singleShot(1, &loop, &QEventLoop::quit);
+ loop.exec();
+ } else {
+ NSLog(@"QIOSFileEngine: unable to show assets authorization dialog from non-gui thread before QApplication is executing.");
+ return false;
+ }
+
+ return true;
}
// -------------------------------------------------------------------------
@@ -80,8 +89,10 @@ public:
, m_writeIndex(0)
, m_nextAssetReady(false)
{
- ensureAuthorizationDialogNotBlocked();
- startEnumerate();
+ if (!ensureAuthorizationDialogNotBlocked())
+ writeAsset(kNoAsset);
+ else
+ startEnumerate();
}
~QIOSAssetEnumerator()
@@ -186,7 +197,8 @@ public:
, m_assetUrl(assetUrl)
, m_assetLibrary(0)
{
- ensureAuthorizationDialogNotBlocked();
+ if (!ensureAuthorizationDialogNotBlocked())
+ return;
if (QIOSAssetData *assetData = g_assetDataCache.localData()) {
// It's a common pattern that QFiles pointing to the same path are created and destroyed
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
index 86b784618f..544f9e0a42 100644
--- a/src/plugins/platforms/ios/qiosglobal.h
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -68,7 +68,7 @@ int infoPlistValue(NSString* key, int defaultValue);
QT_END_NAMESPACE
@interface UIResponder (QtFirstResponder)
-+(id)currentFirstResponder;
++ (id)currentFirstResponder;
@end
class FirstResponderCandidate : public QScopedValueRollback<UIResponder *>
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index ef24abbfd9..f5b971391d 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -133,7 +133,7 @@ int infoPlistValue(NSString* key, int defaultValue)
@end
@implementation QtFirstResponderEvent
-- (void) dealloc
+- (void)dealloc
{
self.firstResponder = 0;
[super dealloc];
@@ -158,7 +158,7 @@ int infoPlistValue(NSString* key, int defaultValue)
@implementation UIResponder (QtFirstResponder)
-+(id)currentFirstResponder
++ (id)currentFirstResponder
{
QtFirstResponderEvent *event = [[[QtFirstResponderEvent alloc] init] autorelease];
[[UIApplication sharedApplication] sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event];
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 090df66e0d..d03c589b2a 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -579,7 +579,7 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
{
// Mask for properties that we are interested in and see if any of them changed
- updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImPlatformData);
+ updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImEnterKeyType | Qt::ImPlatformData);
qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject();
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 8395db81ff..0e3da8dce8 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -89,10 +89,11 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
+ UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease];
- if (![screens containsObject:[UIScreen mainScreen]]) {
+ if (![screens containsObject:mainScreen]) {
// Fallback for iOS 7.1 (QTBUG-42345)
- [screens insertObject:[UIScreen mainScreen] atIndex:0];
+ [screens insertObject:mainScreen atIndex:0];
}
for (UIScreen *screen in screens)
@@ -103,7 +104,10 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
- m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition);
+ QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
+ if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
+ touchCapabilities |= QTouchDevice::Pressure;
+ m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
QMacInternalPasteboardMime::initializeMimeTypes();
}
@@ -219,6 +223,10 @@ QPlatformServices *QIOSIntegration::services() const
QVariant QIOSIntegration::styleHint(StyleHint hint) const
{
switch (hint) {
+ case PasswordMaskDelay:
+ // this number is based on timing the native delay
+ // since there is no API to get it
+ return 2000;
case ShowIsMaximized:
return true;
case SetFocusOnTouchRelease:
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 09395805bf..7aea3729fd 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -165,7 +165,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
[self reloadAllComponents];
}
--(void)listenForKeyboardWillHideNotification:(BOOL)listen
+- (void)listenForKeyboardWillHideNotification:(BOOL)listen
{
if (listen) {
[[NSNotificationCenter defaultCenter]
@@ -179,7 +179,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
}
}
--(void)dealloc
+- (void)dealloc
{
[self listenForKeyboardWillHideNotification:NO];
self.toolbar = 0;
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index a0aa922a31..f31be9756c 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -73,7 +73,7 @@ private:
QRect m_geometry;
QRect m_availableGeometry;
int m_depth;
- uint m_unscaledDpi;
+ uint m_pixelDensity;
QSizeF m_physicalSize;
QIOSOrientationListener *m_orientationListener;
};
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 324133074b..5cb06d591d 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -104,12 +104,12 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@public
QIOSScreen *m_screen;
}
-- (id) initWithQIOSScreen:(QIOSScreen *)screen;
+- (id)initWithQIOSScreen:(QIOSScreen *)screen;
@end
@implementation QIOSOrientationListener
-- (id) initWithQIOSScreen:(QIOSScreen *)screen
+- (id)initWithQIOSScreen:(QIOSScreen *)screen
{
self = [super init];
if (self) {
@@ -123,7 +123,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
return self;
}
-- (void) dealloc
+- (void)dealloc
{
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
@@ -132,7 +132,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
[super dealloc];
}
-- (void) orientationChanged:(NSNotification *)notification
+- (void)orientationChanged:(NSNotification *)notification
{
Q_UNUSED(notification);
m_screen->updateProperties();
@@ -170,23 +170,28 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
if (screen == [UIScreen mainScreen]) {
QString deviceIdentifier = deviceModelIdentifier();
- if (deviceIdentifier == QLatin1String("iPhone2,1") /* iPhone 3GS */
- || deviceIdentifier == QLatin1String("iPod3,1") /* iPod touch 3G */) {
+ // Based on https://en.wikipedia.org/wiki/List_of_iOS_devices#Display
+
+ // iPhone (1st gen), 3G, 3GS, and iPod Touch (1st–3rd gen) are 18-bit devices
+ if (deviceIdentifier.contains(QRegularExpression("^(iPhone1,[12]|iPhone2,1|iPod[1-3],1)$")))
m_depth = 18;
- } else {
+ else
m_depth = 24;
- }
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
- && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
- m_unscaledDpi = 132;
+ if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2)$"))) {
+ // iPhone 6 Plus or iPhone 6S Plus
+ m_pixelDensity = 401;
+ } else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) {
+ // All iPads except the iPad Mini series
+ m_pixelDensity = 132 * devicePixelRatio();
} else {
- m_unscaledDpi = 163; // Regular iPhone DPI
+ // All non-Plus iPhones, and iPad Minis
+ m_pixelDensity = 163 * devicePixelRatio();
}
} else {
// External display, hard to say
m_depth = 24;
- m_unscaledDpi = 96;
+ m_pixelDensity = 96;
}
for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) {
@@ -249,7 +254,7 @@ void QIOSScreen::updateProperties()
if (m_geometry != previousGeometry) {
const qreal millimetersPerInch = 25.4;
- m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch;
+ m_physicalSize = QSizeF(m_geometry.size() * devicePixelRatio()) / m_pixelDensity * millimetersPerInch;
}
// At construction time, we don't yet have an associated QScreen, but we still want
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index f3ea68cdc4..9ca5e22b90 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -92,12 +92,12 @@
return [QUITextPosition positionWithIndex:(self.range.location + self.range.length)];
}
-- (NSRange) range
+- (NSRange)range
{
return _range;
}
--(BOOL)isEmpty
+- (BOOL)isEmpty
{
return (self.range.length == 0);
}
@@ -111,7 +111,7 @@
@implementation WrapperView
--(id)initWithView:(UIView *)view
+- (id)initWithView:(UIView *)view
{
if (self = [self init]) {
[self addSubview:view];
@@ -143,7 +143,7 @@
// retained, we ensure that all messages sent to the view during
// its lifetime in a window hierarcy will be able to traverse the
// responder chain.
--(void)willMoveToWindow:(UIWindow *)window
+- (void)willMoveToWindow:(UIWindow *)window
{
if (window)
[[self nextResponder] retain];
@@ -170,9 +170,31 @@
QVariantMap platformData = m_configuredImeState->value(Qt::ImPlatformData).toMap();
Qt::InputMethodHints hints = Qt::InputMethodHints(m_configuredImeState->value(Qt::ImHints).toUInt());
- self.returnKeyType = platformData.value(kImePlatformDataReturnKeyType).isValid() ?
- UIReturnKeyType(platformData.value(kImePlatformDataReturnKeyType).toInt()) :
- (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone;
+ Qt::EnterKeyType enterKeyType = Qt::EnterKeyType(m_configuredImeState->value(Qt::ImEnterKeyType).toUInt());
+
+ switch (enterKeyType) {
+ case Qt::EnterKeyReturn:
+ self.returnKeyType = UIReturnKeyDefault;
+ break;
+ case Qt::EnterKeyDone:
+ self.returnKeyType = UIReturnKeyDone;
+ break;
+ case Qt::EnterKeyGo:
+ self.returnKeyType = UIReturnKeyGo;
+ break;
+ case Qt::EnterKeySend:
+ self.returnKeyType = UIReturnKeySend;
+ break;
+ case Qt::EnterKeySearch:
+ self.returnKeyType = UIReturnKeySearch;
+ break;
+ case Qt::EnterKeyNext:
+ self.returnKeyType = UIReturnKeyNext;
+ break;
+ default:
+ self.returnKeyType = (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone;
+ break;
+ }
self.secureTextEntry = BOOL(hints & Qt::ImhHiddenText);
self.autocorrectionType = (hints & Qt::ImhNoPredictiveText) ?
@@ -238,7 +260,7 @@
}
// Based on what we set up in initWithInputContext above
- updatedProperties &= (Qt::ImHints | Qt::ImPlatformData);
+ updatedProperties &= (Qt::ImHints | Qt::ImEnterKeyType | Qt::ImPlatformData);
if (!updatedProperties)
return NO;
@@ -546,17 +568,17 @@
return m_inputContext->imeState().currentState.value(query);
}
--(id<UITextInputTokenizer>)tokenizer
+- (id<UITextInputTokenizer>)tokenizer
{
return [[[UITextInputStringTokenizer alloc] initWithTextInput:id<UITextInput>(self)] autorelease];
}
--(UITextPosition *)beginningOfDocument
+- (UITextPosition *)beginningOfDocument
{
return [QUITextPosition positionWithIndex:0];
}
--(UITextPosition *)endOfDocument
+- (UITextPosition *)endOfDocument
{
int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
return [QUITextPosition positionWithIndex:endPosition];
@@ -841,7 +863,7 @@
return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey];
}
--(NSDictionary *)markedTextStyle
+- (NSDictionary *)markedTextStyle
{
return [NSDictionary dictionary];
}
@@ -860,7 +882,8 @@
if ([text isEqualToString:@"\n"]) {
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
- if (self.returnKeyType == UIReturnKeyDone)
+ if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
+ || self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
[self resignFirstResponder];
return;
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 62f5387979..94d894bba7 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -143,7 +143,7 @@
if (uiWindow.screen != [UIScreen mainScreen] && self.subviews.count == 1) {
// Removing the last view of an external screen, go back to mirror mode
- uiWindow.screen = nil;
+ uiWindow.screen = [UIScreen mainScreen];
uiWindow.hidden = YES;
}
}
@@ -296,13 +296,13 @@
// -------------------------------------------------------------------------
--(BOOL)shouldAutorotate
+- (BOOL)shouldAutorotate
{
return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
}
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0)
--(NSUInteger)supportedInterfaceOrientations
+- (NSUInteger)supportedInterfaceOrientations
{
// As documented by Apple in the iOS 6.0 release notes, setStatusBarOrientation:animated:
// only works if the supportedInterfaceOrientations of the view controller is 0, making
@@ -315,7 +315,7 @@
#endif
#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_6_0)
--(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
Q_UNUSED(interfaceOrientation);
return [self shouldAutorotate];
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
index a690e12c7d..c76e3a6a1e 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.h
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -42,8 +42,8 @@
@property (readonly) QAccessible::Id axid;
-- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
-+ (QMacAccessibilityElement *) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
+- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
++ (QMacAccessibilityElement *)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
@end
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index 2cecfc1126..3bac1ca88d 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -37,7 +37,7 @@
@implementation QMacAccessibilityElement
-- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
{
Q_ASSERT((int)anId < 0);
self = [super initWithAccessibilityContainer: view];
@@ -47,7 +47,7 @@
return self;
}
-+ (id) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
++ (id)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
{
Q_ASSERT(anId);
if (!anId)
@@ -64,17 +64,17 @@
return element;
}
-- (void) invalidate
+- (void)invalidate
{
[self release];
}
-- (BOOL) isAccessibilityElement
+- (BOOL)isAccessibilityElement
{
return YES;
}
-- (NSString*) accessibilityLabel
+- (NSString*)accessibilityLabel
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
@@ -85,7 +85,7 @@
return iface->text(QAccessible::Name).toNSString();
}
-- (NSString*) accessibilityHint
+- (NSString*)accessibilityHint
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
@@ -95,7 +95,7 @@
return iface->text(QAccessible::Description).toNSString();
}
-- (NSString*) accessibilityValue
+- (NSString*)accessibilityValue
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
@@ -119,7 +119,7 @@
return [super accessibilityHint];
}
-- (CGRect) accessibilityFrame
+- (CGRect)accessibilityFrame
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
@@ -131,7 +131,7 @@
return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
}
-- (UIAccessibilityTraits) accessibilityTraits
+- (UIAccessibilityTraits)accessibilityTraits
{
UIAccessibilityTraits traits = UIAccessibilityTraitNone;
@@ -156,7 +156,7 @@
return traits;
}
-- (BOOL) accessibilityActivate
+- (BOOL)accessibilityActivate
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface()) {
@@ -171,21 +171,21 @@
return NO; // fall back to sending mouse clicks
}
-- (void) accessibilityIncrement
+- (void)accessibilityIncrement
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface())
action->doAction(QAccessibleActionInterface::increaseAction());
}
-- (void) accessibilityDecrement
+- (void)accessibilityDecrement
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface())
action->doAction(QAccessibleActionInterface::decreaseAction());
}
-- (BOOL) accessibilityScroll : (UIAccessibilityScrollDirection) direction
+- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
QAccessibleActionInterface *action = iface->actionInterface();
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 87dc3b9dcb..53b3d30327 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -50,7 +50,7 @@
return [CAEAGLLayer class];
}
--(id)initWithQIOSWindow:(QIOSWindow *)window
+- (id)initWithQIOSWindow:(QIOSWindow *)window
{
if (self = [self initWithFrame:toCGRect(window->geometry())])
m_qioswindow = window;
@@ -280,6 +280,19 @@
// -------------------------------------------------------------------------
+- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
+{
+ [super traitCollectionDidChange: previousTraitCollection];
+
+ QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice();
+ QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities();
+ if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
+ touchCapabilities |= QTouchDevice::Pressure;
+ else
+ touchCapabilities &= ~QTouchDevice::Pressure;
+ touchDevice->setCapabilities(touchCapabilities);
+}
+
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput)
@@ -289,6 +302,8 @@
- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
{
+ bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure;
+
foreach (UITouch *uiTouch, m_activeTouches.keys()) {
QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
if (![touches containsObject:uiTouch]) {
@@ -309,14 +324,22 @@
touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(),
globalScreenPosition.y() / screenSize.height());
- // We don't claim that our touch device supports QTouchDevice::Pressure,
- // but fill in a meaningfull value in case clients use it anyways.
- touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
+ if (supportsPressure) {
+ // Note: iOS will deliver touchesBegan with a touch force of 0, which
+ // we will reflect/propagate as a 0 pressure, but there is no clear
+ // alternative, as we don't want to wait for a touchedMoved before
+ // sending a touch press event to Qt, just to have a valid pressure.
+ 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.
+ touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
+ }
}
}
}
-- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
+- (void)sendTouchEventWithTimestamp:(ulong)timeStamp
{
// Send touch event synchronously
QIOSIntegration *iosIntegration = QIOSIntegration::instance();
diff --git a/src/plugins/platforms/kms/kms.json b/src/plugins/platforms/kms/kms.json
deleted file mode 100644
index be662226ae..0000000000
--- a/src/plugins/platforms/kms/kms.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "kms" ]
-}
diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
deleted file mode 100644
index baa8778153..0000000000
--- a/src/plugins/platforms/kms/kms.pro
+++ /dev/null
@@ -1,37 +0,0 @@
-TARGET = qkms
-
-PLUGIN_TYPE = platforms
-PLUGIN_CLASS_NAME = QKmsIntegrationPlugin
-!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
-load(qt_plugin)
-
-QT += core-private gui-private platformsupport-private
-qtHaveModule(opengl):QT += opengl-private
-
-DEFINES += MESA_EGL_NO_X11_HEADERS __GBM__
-
-CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase
-
-PKGCONFIG += libdrm libudev egl gbm glesv2
-
-SOURCES = main.cpp \
- qkmsintegration.cpp \
- qkmsscreen.cpp \
- qkmscontext.cpp \
- qkmswindow.cpp \
- qkmscursor.cpp \
- qkmsdevice.cpp \
- qkmsbackingstore.cpp \
- qkmsnativeinterface.cpp
-
-HEADERS = qkmsintegration.h \
- qkmsscreen.h \
- qkmscontext.h \
- qkmswindow.h \
- qkmscursor.h \
- qkmsdevice.h \
- qkmsbackingstore.h \
- qkmsnativeinterface.h
-
-OTHER_FILES += \
- kms.json
diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp
deleted file mode 100644
index 565ac7a7d4..0000000000
--- a/src/plugins/platforms/kms/main.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qpa/qplatformintegrationplugin.h>
-#include "qkmsintegration.h"
-
-QT_BEGIN_NAMESPACE
-
-class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "kms.json")
-public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
-};
-
-QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const QStringList& paramList)
-{
- Q_UNUSED(paramList);
- if (!system.compare(QLatin1String("kms"), Qt::CaseInsensitive))
- return new QKmsIntegration;
-
- return 0;
-}
-
-QT_END_NAMESPACE
-
-#include "main.moc"
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.cpp b/src/plugins/platforms/kms/qkmsbackingstore.cpp
deleted file mode 100644
index 6e5a3f9192..0000000000
--- a/src/plugins/platforms/kms/qkmsbackingstore.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsbackingstore.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOpenGLShaderProgram>
-#include <QtGui/QScreen>
-
-QT_BEGIN_NAMESPACE
-
-QKmsBackingStore::QKmsBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
- , m_context(new QOpenGLContext)
- , m_texture(0)
- , m_program(0)
- , m_initialized(false)
-{
- m_context->setFormat(window->requestedFormat());
- m_context->setScreen(window->screen());
- m_context->create();
-}
-
-QKmsBackingStore::~QKmsBackingStore()
-{
- delete m_program;
- if (m_texture)
- glDeleteTextures(1, &m_texture);
-
- delete m_context;
-}
-
-QPaintDevice *QKmsBackingStore::paintDevice()
-{
- return &m_image;
-}
-
-void QKmsBackingStore::beginPaint(const QRegion &rgn)
-{
- m_dirty |= rgn;
-}
-
-void QKmsBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
-{
- Q_UNUSED(region)
- Q_UNUSED(offset)
-
- m_context->makeCurrent(window);
-
- if (!m_initialized) {
- initializeOpenGLFunctions();
- m_initialized = true;
- }
-
- if (!m_program) {
- static const char *textureVertexProgram =
- "attribute highp vec2 vertexCoordEntry;\n"
- "attribute highp vec2 textureCoordEntry;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " textureCoord = textureCoordEntry;\n"
- " gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n"
- "}\n";
-
- static const char *textureFragmentProgram =
- "uniform sampler2D texture;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
- "}\n";
-
- m_program = new QOpenGLShaderProgram;
-
- m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
- m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
- m_program->bindAttributeLocation("vertexCoordEntry", 0);
- m_program->bindAttributeLocation("textureCoordEntry", 1);
- m_program->link();
- }
-
- m_program->bind();
-
- QRectF r = window->geometry();
- QRectF sr = window->screen()->geometry();
-
- GLfloat x1 = (r.left() / sr.width()) * 2 - 1;
- GLfloat x2 = (r.right() / sr.width()) * 2 - 1;
- GLfloat y1 = -1 * ((r.top() / sr.height()) * 2 - 1);
- GLfloat y2 = -1 * ((r.bottom() / sr.height()) * 2 - 1);
-
- const GLfloat vertexCoordinates[] = {
- x1, y1,
- x2, y1,
- x2, y2,
- x1, y2
- };
-
- const GLfloat textureCoordinates[] = {
- 0, 0,
- 1, 0,
- 1, 1,
- 0, 1
- };
-
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
-
- glBindTexture(GL_TEXTURE_2D, m_texture);
-
- if (!m_dirty.isNull()) {
- QRect imageRect = m_image.rect();
- QRegion fixed;
- Q_FOREACH (const QRect &rect, m_dirty.rects()) {
- // intersect with image rect to be sure
- QRect r = imageRect & rect;
- // if the rect is wide enough it's cheaper to just
- // extend it instead of doing an image copy
- if (r.width() >= imageRect.width() / 2) {
- r.setX(0);
- r.setWidth(imageRect.width());
- }
- fixed |= r;
- }
-
- Q_FOREACH (const QRect &rect, fixed.rects()) {
- // if the sub-rect is full-width we can pass the image data directly to
- // OpenGL instead of copying, since there's no gap between scanlines
- if (rect.width() == imageRect.width()) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(),
- rect.width(), rect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- m_image.constScanLine(rect.y()));
- } else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(),
- rect.width(), rect.height(),
- GL_RGBA, GL_UNSIGNED_BYTE,
- m_image.copy(rect).constBits());
- }
- }
-
- m_dirty = QRegion();
- }
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- m_program->release();
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
-
- m_context->swapBuffers(window);
-
- m_context->doneCurrent();
-}
-
-void QKmsBackingStore::resize(const QSize &size, const QRegion &staticContents)
-{
- Q_UNUSED(staticContents)
-
- m_image = QImage(size, QImage::Format_RGB32);
-
- m_context->makeCurrent(window());
-
- if (!m_initialized) {
- initializeOpenGLFunctions();
- m_initialized = true;
- }
-
- if (m_texture)
- glDeleteTextures(1, &m_texture);
-
- glGenTextures(1, &m_texture);
- glBindTexture(GL_TEXTURE_2D, m_texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(),
- 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h
deleted file mode 100644
index a34b10d3d9..0000000000
--- a/src/plugins/platforms/kms/qkmsbackingstore.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBACKINGSTORE_KMS_H
-#define QBACKINGSTORE_KMS_H
-
-#include <qpa/qplatformbackingstore.h>
-#include <QtGui/QOpenGLFunctions>
-#include <QImage>
-
-QT_BEGIN_NAMESPACE
-
-class QOpenGLContext;
-class QOpenGLShaderProgram;
-
-class QKmsBackingStore : public QPlatformBackingStore, public QOpenGLFunctions
-{
-public:
- QKmsBackingStore(QWindow *window);
- ~QKmsBackingStore();
-
- QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
-
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
-
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
- void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
-
- QImage toImage() const Q_DECL_OVERRIDE { return m_image; }
-
-private:
- QOpenGLContext *m_context;
- QImage m_image;
- uint m_texture;
- QOpenGLShaderProgram *m_program;
- QRegion m_dirty;
- bool m_initialized;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp
deleted file mode 100644
index e00835fbac..0000000000
--- a/src/plugins/platforms/kms/qkmscontext.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-#include "qkmscontext.h"
-#include "qkmswindow.h"
-#include "qkmsintegration.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device)
- : m_device(device)
-{
- EGLDisplay display = m_device->eglDisplay();
- EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format()));
- m_format = q_glFormatFromConfig(display, config);
-
- //Initialize EGLContext
- static EGLint contextAttribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, context->format().majorVersion(),
- EGL_NONE
- };
-
- eglBindAPI(EGL_OPENGL_ES_API);
-
- EGLContext share = EGL_NO_CONTEXT;
- if (context->shareContext())
- share = static_cast<QKmsContext *>(context->shareContext()->handle())->eglContext();
-
- m_eglContext = eglCreateContext(display, config, share, contextAttribs);
- if (m_eglContext == EGL_NO_CONTEXT) {
- qWarning("QKmsContext::QKmsContext(): eglError: %x, this: %p",
- eglGetError(), this);
- m_eglContext = 0;
- }
-}
-
-bool QKmsContext::isValid() const
-{
- return m_eglContext != EGL_NO_CONTEXT;
-}
-
-bool QKmsContext::makeCurrent(QPlatformSurface *surface)
-{
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- EGLDisplay display = m_device->eglDisplay();
- EGLSurface eglSurface;
-
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
- QKmsScreen *screen = static_cast<QKmsScreen *>(QPlatformScreen::platformScreenForWindow(window->window()));
- eglSurface = screen->eglSurface();
- screen->waitForPageFlipComplete();
- } else {
- eglSurface = static_cast<QKmsOffscreenWindow *>(surface)->surface();
- }
-
- bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext);
- if (!ok)
- qWarning("QKmsContext::makeCurrent(): eglError: %x, this: %p",
- eglGetError(), this);
-
- return true;
-}
-
-void QKmsContext::doneCurrent()
-{
- bool ok = eglMakeCurrent(m_device->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- if (!ok)
- qWarning("QKmsContext::doneCurrent(): eglError: %x, this: %p",
- eglGetError(), this);
-
-}
-
-void QKmsContext::swapBuffers(QPlatformSurface *surface)
-{
- //Cast context to a window surface and get the screen the context
- //is on and call swapBuffers on that screen.
- QPlatformWindow *window = static_cast<QPlatformWindow *>(surface);
- QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window()));
- screen->swapBuffers();
-}
-
-void (*QKmsContext::getProcAddress(const QByteArray &procName)) ()
-{
- return eglGetProcAddress(procName.data());
-}
-
-
-EGLContext QKmsContext::eglContext() const
-{
- return m_eglContext;
-}
-
-QSurfaceFormat QKmsContext::format() const
-{
- return m_format;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h
deleted file mode 100644
index 59cf9b1e34..0000000000
--- a/src/plugins/platforms/kms/qkmscontext.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSCONTEXT_H
-#define QKMSCONTEXT_H
-
-#include <qpa/qplatformopenglcontext.h>
-
-#define EGL_EGLEXT_PROTOTYPES 1
-#include <EGL/egl.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsDevice;
-
-class QKmsContext : public QPlatformOpenGLContext
-{
-public:
- QKmsContext(QOpenGLContext *context, QKmsDevice *device);
-
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE;
-
- bool isValid() const Q_DECL_OVERRIDE;
-
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
-
- EGLContext eglContext() const;
-
-private:
- EGLContext m_eglContext;
- QSurfaceFormat m_format;
-
- QKmsDevice *m_device;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSCONTEXT_H
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
deleted file mode 100644
index 44212cd3c8..0000000000
--- a/src/plugins/platforms/kms/qkmscursor.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-//#include <QDebug>
-#include "qkmscursor.h"
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef DRM_CAP_CURSOR_WIDTH
-#define DRM_CAP_CURSOR_WIDTH 0x8
-#endif
-
-#ifndef DRM_CAP_CURSOR_HEIGHT
-#define DRM_CAP_CURSOR_HEIGHT 0x9
-#endif
-
-QKmsCursor::QKmsCursor(QKmsScreen *screen)
- : m_screen(screen),
- m_graphicsBufferManager(screen->device()->gbmDevice()),
- m_cursorImage(new QPlatformCursorImage(0, 0, 0, 0, 0, 0)),
- m_moved(false),
- m_cursorSize(64, 64)
-{
- uint64_t value = 0;
- if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &value))
- m_cursorSize.setWidth(value);
- if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &value))
- m_cursorSize.setHeight(value);
-
- m_cursorBufferObject = gbm_bo_create(m_graphicsBufferManager, m_cursorSize.width(), m_cursorSize.height(),
- GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
-}
-
-QKmsCursor::~QKmsCursor()
-{
- drmModeSetCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0, 0);
- gbm_bo_destroy(m_cursorBufferObject);
-}
-
-void QKmsCursor::pointerEvent(const QMouseEvent &event)
-{
- m_moved = true;
- int status = drmModeMoveCursor(m_screen->device()->fd(),
- m_screen->crtcId(),
- event.globalX(),
- event.globalY());
- if (status) {
- qWarning("failed to move cursor: %d", status);
- }
-}
-
-void QKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
-{
- Q_UNUSED(window)
-
- if (!m_moved)
- drmModeMoveCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0);
-
- const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor;
- if (newShape != Qt::BitmapCursor) {
- m_cursorImage->set(newShape);
- } else {
- m_cursorImage->set(windowCursor->pixmap().toImage(),
- windowCursor->hotSpot().x(),
- windowCursor->hotSpot().y());
- }
-
- if (m_cursorImage->image()->width() > m_cursorSize.width() || m_cursorImage->image()->width() > m_cursorSize.height())
- qWarning("cursor larger than %dx%d, cursor truncated", m_cursorSize.width(), m_cursorSize.height());
-
- QImage cursorImage = m_cursorImage->image()->convertToFormat(QImage::Format_ARGB32)
- .copy(0, 0, m_cursorSize.width(), m_cursorSize.height());
- gbm_bo_write(m_cursorBufferObject, cursorImage.constBits(), cursorImage.byteCount());
-
- quint32 handle = gbm_bo_get_handle(m_cursorBufferObject).u32;
- int status = drmModeSetCursor(m_screen->device()->fd(),
- m_screen->crtcId(), handle,
- m_cursorSize.width(), m_cursorSize.height());
-
- if (status) {
- qWarning("failed to set cursor: %d", status);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h
deleted file mode 100644
index 9aadf407c0..0000000000
--- a/src/plugins/platforms/kms/qkmscursor.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSCURSOR_H
-#define QKMSCURSOR_H
-
-#include <qpa/qplatformcursor.h>
-
-struct gbm_device;
-struct gbm_bo;
-
-QT_BEGIN_NAMESPACE
-
-class QKmsScreen;
-
-class QKmsCursor : public QPlatformCursor
-{
-public:
- QKmsCursor(QKmsScreen *screen);
- ~QKmsCursor();
-
- void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
- void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE;
-
-private:
- QKmsScreen *m_screen;
- gbm_device *m_graphicsBufferManager;
- gbm_bo *m_cursorBufferObject;
- QPlatformCursorImage *m_cursorImage;
- bool m_moved;
- QSize m_cursorSize;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSCURSOR_H
diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp
deleted file mode 100644
index 74fa59c16a..0000000000
--- a/src/plugins/platforms/kms/qkmsdevice.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-//#include <QDebug>
-#include "qkmsscreen.h"
-#include "qkmsdevice.h"
-
-#include "qkmsintegration.h"
-
-#include <QtCore/QSocketNotifier>
-#include <QtCore/private/qcore_unix_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsDevice::QKmsDevice(const QString &path, QKmsIntegration *parent) :
- QObject(0), m_integration(parent)
-{
- m_fd = QT_OPEN(path.toLatin1().constData(), O_RDWR);
- if (m_fd < 0) {
- qWarning("Could not open %s.", path.toLatin1().constData());
- qFatal("No DRM display device");
- }
-
- m_graphicsBufferManager = gbm_create_device(m_fd);
- m_eglDisplay = eglGetDisplay(m_graphicsBufferManager);
-
- if (m_eglDisplay == EGL_NO_DISPLAY) {
- qWarning("Could not open EGL display");
- qFatal("EGL error");
- }
-
- EGLint major;
- EGLint minor;
- if (!eglInitialize(m_eglDisplay, &major, &minor)) {
- qWarning("Could not initialize EGL display");
- qFatal("EGL error");
- }
-
- createScreens();
-
-// QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
-// connect(notifier, SIGNAL(activated(int)), this, SLOT(handlePageFlipCompleted()));
-}
-
-QKmsDevice::~QKmsDevice()
-{
-}
-
-void QKmsDevice::createScreens()
-{
- drmModeRes *resources = drmModeGetResources(m_fd);
- if (!resources)
- qFatal("drmModeGetResources failed");
-
- //Iterate connectors and create screens on each one active
- for (int i = 0; i < resources->count_connectors; i++) {
- drmModeConnector *connector = 0;
- connector = drmModeGetConnector(m_fd, resources->connectors[i]);
- if (connector && connector->connection == DRM_MODE_CONNECTED) {
- m_integration->addScreen(new QKmsScreen(this, resources, connector));
- }
- drmModeFreeConnector(connector);
- }
- drmModeFreeResources(resources);
-}
-
-void QKmsDevice::handlePageFlipCompleted()
-{
- drmEventContext eventContext;
-
- memset(&eventContext, 0, sizeof eventContext);
- eventContext.version = DRM_EVENT_CONTEXT_VERSION;
- eventContext.page_flip_handler = QKmsDevice::pageFlipHandler;
- drmHandleEvent(m_fd, &eventContext);
-
-}
-
-void QKmsDevice::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
-{
- Q_UNUSED(fd)
- Q_UNUSED(frame)
- Q_UNUSED(sec)
- Q_UNUSED(usec)
-
- QKmsScreen *screen = static_cast<QKmsScreen *>(data);
- screen->handlePageFlipped();
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsdevice.h b/src/plugins/platforms/kms/qkmsdevice.h
deleted file mode 100644
index d5e33cb8c7..0000000000
--- a/src/plugins/platforms/kms/qkmsdevice.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSDEVICE_H
-#define QKMSDEVICE_H
-
-#include <stddef.h>
-
-extern "C" {
-#include <gbm.h>
-}
-#include <EGL/egl.h>
-
-#include <QObject>
-
-struct gbm_device;
-
-QT_BEGIN_NAMESPACE
-
-class QKmsIntegration;
-
-class QKmsDevice : public QObject
-{
- Q_OBJECT
-public:
- explicit QKmsDevice(const QString &path, QKmsIntegration *parent);
- ~QKmsDevice();
-
- EGLDisplay eglDisplay() { return m_eglDisplay; }
- gbm_device *gbmDevice() { return m_graphicsBufferManager; }
- int fd() const { return m_fd; }
-
- static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *data);
-
-public slots:
- void handlePageFlipCompleted();
-private:
- void createScreens();
-
- QKmsIntegration *m_integration;
-
- EGLDisplay m_eglDisplay;
- EGLContext m_eglContext;
- gbm_device *m_graphicsBufferManager;
- int m_fd;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSDEVICE_H
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
deleted file mode 100644
index f48c868ae5..0000000000
--- a/src/plugins/platforms/kms/qkmsintegration.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsintegration.h"
-#include "qkmsdevice.h"
-#include "qkmsscreen.h"
-#include "qkmswindow.h"
-#include "qkmsbackingstore.h"
-#include "qkmscontext.h"
-#include "qkmsnativeinterface.h"
-
-#if !defined(QT_NO_EVDEV)
-#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
-#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
-#include <QtPlatformSupport/private/qevdevtouch_p.h>
-#endif
-
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
-#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtPlatformSupport/private/qfbvthandler_p.h>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QScreen>
-#include <QtGui/QOffscreenSurface>
-#include <qpa/qplatformoffscreensurface.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsIntegration::QKmsIntegration()
- : QPlatformIntegration(),
- m_fontDatabase(new QGenericUnixFontDatabase()),
- m_nativeInterface(new QKmsNativeInterface),
- m_vtHandler(0),
- m_deviceDiscovery(0)
-{
-}
-
-QKmsIntegration::~QKmsIntegration()
-{
- delete m_deviceDiscovery;
- foreach (QKmsDevice *device, m_devices) {
- delete device;
- }
- foreach (QPlatformScreen *screen, m_screens) {
- destroyScreen(screen);
- }
- delete m_fontDatabase;
- delete m_vtHandler;
-}
-
-void QKmsIntegration::initialize()
-{
- qputenv("EGL_PLATFORM", "drm");
- m_vtHandler = new QFbVtHandler;
-
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_DRM | QDeviceDiscovery::Device_DRM_PrimaryGPU, 0);
- if (m_deviceDiscovery) {
- QStringList devices = m_deviceDiscovery->scanConnectedDevices();
- foreach (const QString &device, devices)
- addDevice(device);
-
- connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString)));
- connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString)));
- }
-
-#if !defined(QT_NO_EVDEV)
- new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
- new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
- new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
-#endif
-}
-
-void QKmsIntegration::addDevice(const QString &deviceNode)
-{
- m_devices.append(new QKmsDevice(deviceNode, this));
-}
-
-void QKmsIntegration::removeDevice(const QString &deviceNode)
-{
- // TODO: support hot-plugging some day?
- Q_UNUSED(deviceNode);
-}
-
-bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
-{
- switch (cap) {
- case ThreadedPixmaps: return true;
- case OpenGL: return true;
- case ThreadedOpenGL: return false;
- case RasterGLSurface: return true;
- default: return QPlatformIntegration::hasCapability(cap);
- }
-}
-
-QPlatformOpenGLContext *QKmsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(context->screen()->handle());
- return new QKmsContext(context, screen->device());
-}
-
-QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const
-{
- QKmsWindow *w = new QKmsWindow(window);
- w->requestActivateWindow();
- return w;
-}
-
-QPlatformBackingStore *QKmsIntegration::createPlatformBackingStore(QWindow *window) const
-{
- return new QKmsBackingStore(window);
-}
-
-// Neither a pbuffer nor a hidden QWindow is suitable. Just use an additional, small gbm surface.
-QKmsOffscreenWindow::QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
- : QPlatformOffscreenSurface(offscreenSurface)
- , m_format(format)
- , m_display(display)
- , m_surface(EGL_NO_SURFACE)
- , m_window(0)
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(offscreenSurface->screen()->handle());
- m_window = gbm_surface_create(screen->device()->gbmDevice(),
- 10, 10,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_RENDERING);
- if (!m_window) {
- qWarning("QKmsOffscreenWindow: Failed to create native window");
- return;
- }
-
- EGLConfig config = q_configFromGLFormat(m_display, m_format);
- m_surface = eglCreateWindowSurface(m_display, config, m_window, 0);
- if (m_surface != EGL_NO_SURFACE)
- m_format = q_glFormatFromConfig(m_display, config);
-}
-
-QKmsOffscreenWindow::~QKmsOffscreenWindow()
-{
- if (m_surface != EGL_NO_SURFACE)
- eglDestroySurface(m_display, m_surface);
- if (m_window)
- gbm_surface_destroy((gbm_surface *) m_window);
-}
-
-QPlatformOffscreenSurface *QKmsIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
-{
- QKmsScreen *screen = static_cast<QKmsScreen *>(surface->screen()->handle());
- return new QKmsOffscreenWindow(screen->device()->eglDisplay(), QKmsScreen::tweakFormat(surface->format()), surface);
-}
-
-QPlatformFontDatabase *QKmsIntegration::fontDatabase() const
-{
- return m_fontDatabase;
-}
-
-void QKmsIntegration::addScreen(QKmsScreen *screen)
-{
- m_screens.append(screen);
- screenAdded(screen);
-}
-
-QAbstractEventDispatcher *QKmsIntegration::createEventDispatcher() const
-{
- return createUnixEventDispatcher();
-}
-
-QPlatformNativeInterface *QKmsIntegration::nativeInterface() const
-{
- return m_nativeInterface;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h
deleted file mode 100644
index bcf9ac7296..0000000000
--- a/src/plugins/platforms/kms/qkmsintegration.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QPLATFORMINTEGRATION_KMS_H
-#define QPLATFORMINTEGRATION_KMS_H
-
-#include <qpa/qplatformintegration.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <qpa/qplatformoffscreensurface.h>
-#include <QtPlatformSupport/private/qdevicediscovery_p.h>
-#include <EGL/egl.h>
-
-QT_BEGIN_NAMESPACE
-
-class QKmsScreen;
-class QKmsDevice;
-class QFbVtHandler;
-
-class QKmsOffscreenWindow : public QPlatformOffscreenSurface
-{
-public:
- QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface);
- ~QKmsOffscreenWindow();
-
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; }
-
- EGLSurface surface() const { return m_surface; }
-
-private:
- QSurfaceFormat m_format;
- EGLDisplay m_display;
- EGLSurface m_surface;
- EGLNativeWindowType m_window;
-};
-
-class QKmsIntegration : public QObject, public QPlatformIntegration
-{
- Q_OBJECT
-
-public:
- QKmsIntegration();
- ~QKmsIntegration();
-
- void initialize() Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
-
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
-
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
-
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
-
- void addScreen(QKmsScreen *screen);
- QObject *createDevice(const char *);
-
-private slots:
- void addDevice(const QString &deviceNode);
- void removeDevice(const QString &deviceNode);
-
-private:
- QStringList findDrmDevices();
-
- QList<QPlatformScreen *> m_screens;
- QList<QKmsDevice *> m_devices;
- QPlatformFontDatabase *m_fontDatabase;
- QPlatformNativeInterface *m_nativeInterface;
- QFbVtHandler *m_vtHandler;
- QDeviceDiscovery *m_deviceDiscovery;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp
deleted file mode 100644
index 1538a7f8c3..0000000000
--- a/src/plugins/platforms/kms/qkmsnativeinterface.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qguiapplication_p.h>
-#include "qkmsnativeinterface.h"
-#include "qkmsdevice.h"
-
-#include "qscreen.h"
-#include "qkmscontext.h"
-#include <QOpenGLContext>
-
-class QKmsResourceMap : public QMap<QByteArray, QKmsNativeInterface::ResourceType>
-{
-public:
- QKmsResourceMap()
- :QMap<QByteArray, QKmsNativeInterface::ResourceType>()
- {
- insert("egldisplay", QKmsNativeInterface::EglDisplay);
- insert("eglcontext", QKmsNativeInterface::EglContext);
- }
-};
-
-Q_GLOBAL_STATIC(QKmsResourceMap, qKmsResourceMap)
-
-void *QKmsNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
-{
- QByteArray lowerCaseResource = resourceString.toLower();
- ResourceType resource = qKmsResourceMap()->value(lowerCaseResource);
- void *result = 0;
- switch (resource) {
- case EglDisplay:
- result = eglDisplay();
- break;
- default:
- result = 0;
- }
- return result;
-
-}
-void *QKmsNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
-{
- QByteArray lowerCaseResource = resourceString.toLower();
- ResourceType resource = qKmsResourceMap()->value(lowerCaseResource);
- void *result = 0;
- switch (resource) {
- case EglDisplay:
- result = eglDisplayForWindow(window);
- break;
- case EglContext:
- result = eglContextForWindow(window);
- break;
- default:
- result = 0;
- }
- return result;
-}
-
-QPlatformNativeInterface::NativeResourceForContextFunction QKmsNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
-{
- QByteArray lowerCaseResource = resource.toLower();
- if (lowerCaseResource == "get_egl_context") {
- return eglContextForContext;
- }
- return 0;
-}
-
-void *QKmsNativeInterface::eglDisplay()
-{
- //QKmsIntegration *integration = static_cast<QKmsIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QKmsScreen *screen = static_cast<QKmsScreen *>(QGuiApplication::primaryScreen()->handle());
- if (!screen || !screen->device())
- return 0;
- return screen->device()->eglDisplay();
-}
-
-void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window)
-{
- QKmsScreen *screen = qPlatformScreenForWindow(window);
- if (!screen)
- return 0;
- QKmsDevice *device = screen->device();
- if (!device)
- return 0;
- return device->eglDisplay();
-}
-
-void *QKmsNativeInterface::eglContextForWindow(QWindow *)
-{
- return 0;
-}
-
-QKmsScreen *QKmsNativeInterface::qPlatformScreenForWindow(QWindow *window)
-{
- QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
- return static_cast<QKmsScreen *>(screen->handle());
-}
-
-void *QKmsNativeInterface::eglContextForContext(QOpenGLContext *context)
-{
- Q_ASSERT(context);
-
- QKmsContext *eglPlatformContext = static_cast<QKmsContext *>(context->handle());
-
- return eglPlatformContext->eglContext();
-}
diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.h b/src/plugins/platforms/kms/qkmsnativeinterface.h
deleted file mode 100644
index 56879d0a3a..0000000000
--- a/src/plugins/platforms/kms/qkmsnativeinterface.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSNATIVEINTERFACE_H
-#define QKMSNATIVEINTERFACE_H
-
-#include "qkmsscreen.h"
-
-#include <qpa/qplatformnativeinterface.h>
-
-class QKmsNativeInterface : public QPlatformNativeInterface
-{
-public:
- enum ResourceType {
- EglDisplay,
- EglContext
- };
-
- void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
-
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
-
- void *eglDisplay();
- void *eglDisplayForWindow(QWindow *window);
- void *eglContextForWindow(QWindow *window);
- static void *eglContextForContext(QOpenGLContext *context);
-
-private:
- static QKmsScreen *qPlatformScreenForWindow(QWindow *window);
-};
-
-
-#endif // QKMSNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
deleted file mode 100644
index 6392b99cd5..0000000000
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmsscreen.h"
-#include "qkmscursor.h"
-#include "qkmsdevice.h"
-#include "qkmscontext.h"
-
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
-#include <QCoreApplication>
-#include <QtDebug>
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.kms.screen")
-
-//Fallback mode (taken from Wayland DRM demo compositor)
-static drmModeModeInfo builtin_1024x768 = {
- 63500, //clock
- 1024, 1072, 1176, 1328, 0,
- 768, 771, 775, 798, 0,
- 59920,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
- 0,
- "1024x768"
-};
-
-QKmsScreen::QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector)
- : m_device(device),
- m_current_bo(0),
- m_next_bo(0),
- m_connectorId(connector->connector_id),
- m_depth(32),
- m_format(QImage::Format_Invalid),
- m_eglWindowSurface(EGL_NO_SURFACE),
- m_modeSet(false)
-{
- m_cursor = new QKmsCursor(this);
- initializeScreenMode(resources, connector);
-}
-
-QKmsScreen::~QKmsScreen()
-{
- delete m_cursor;
- drmModeSetCrtc(m_device->fd(), m_oldCrtc->crtc_id, m_oldCrtc->buffer_id,
- m_oldCrtc->x, m_oldCrtc->y,
- &m_connectorId, 1, &m_oldCrtc->mode);
- drmModeFreeCrtc(m_oldCrtc);
- if (m_eglWindowSurface != EGL_NO_SURFACE)
- eglDestroySurface(m_device->eglDisplay(), m_eglWindowSurface);
- gbm_surface_destroy(m_gbmSurface);
-}
-
-QRect QKmsScreen::geometry() const
-{
- return m_geometry;
-}
-
-int QKmsScreen::depth() const
-{
- return m_depth;
-}
-
-QImage::Format QKmsScreen::format() const
-{
- return m_format;
-}
-
-QSizeF QKmsScreen::physicalSize() const
-{
- return m_physicalSize;
-}
-
-QPlatformCursor *QKmsScreen::cursor() const
-{
- return m_cursor;
-}
-
-void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector)
-{
- //Determine optimal mode for screen
- drmModeModeInfo *mode = 0;
- for (int i = 0; i < connector->count_modes; ++i) {
- if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
- mode = &connector->modes[i];
- break;
- }
- }
- if (!mode) {
- if (connector->count_modes > 0)
- mode = &connector->modes[0];
- else
- mode = &builtin_1024x768;
- }
-
- drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
- if (encoder == 0)
- qFatal("No encoder for connector.");
-
- int i;
- for (i = 0; i < resources->count_crtcs; i++) {
- if (encoder->possible_crtcs & (1 << i))
- break;
- }
- if (i == resources->count_crtcs)
- qFatal("No usable crtc for encoder.");
-
- m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id);
-
- m_crtcId = resources->crtcs[i];
- m_mode = *mode;
- m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
- qCDebug(lcQpaScreen) << "kms initialized with geometry" << m_geometry;
- m_depth = 32;
- m_format = QImage::Format_RGB32;
- m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);
-
- m_gbmSurface = gbm_surface_create(m_device->gbmDevice(),
- m_mode.hdisplay, m_mode.vdisplay,
- GBM_BO_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-
- qCDebug(lcQpaScreen) << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
- //Cleanup
- drmModeFreeEncoder(encoder);
-}
-
-QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format)
-{
- QSurfaceFormat fmt = format;
- fmt.setRedBufferSize(8);
- fmt.setGreenBufferSize(8);
- fmt.setBlueBufferSize(8);
- if (fmt.alphaBufferSize() != -1)
- fmt.setAlphaBufferSize(8);
- return fmt;
-}
-
-void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format)
-{
- EGLDisplay display = m_device->eglDisplay();
- EGLConfig config = q_configFromGLFormat(display, tweakFormat(format));
-
- m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL);
- qCDebug(lcQpaScreen) << "created window surface";
- m_surfaceFormat = q_glFormatFromConfig(display, config);
-}
-
-void QKmsScreen::swapBuffers()
-{
- eglSwapBuffers(m_device->eglDisplay(), m_eglWindowSurface);
-
- m_next_bo = gbm_surface_lock_front_buffer(m_gbmSurface);
- if (!m_next_bo)
- qFatal("kms: Failed to lock front buffer");
-
- performPageFlip();
-}
-
-void QKmsScreen::performPageFlip()
-{
- if (!m_next_bo)
- return;
-
- uint32_t width = gbm_bo_get_width(m_next_bo);
- uint32_t height = gbm_bo_get_height(m_next_bo);
- uint32_t stride = gbm_bo_get_stride(m_next_bo);
- uint32_t handle = gbm_bo_get_handle(m_next_bo).u32;
-
- uint32_t fb_id;
- int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32,
- stride, handle, &fb_id);
- if (ret) {
- qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d",
- m_device->fd(), width, height, stride, handle, ret);
- }
-
- if (!m_modeSet) {
- //Set the Mode of the screen.
- int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id,
- 0, 0, &m_connectorId, 1, &m_mode);
- if (ret)
- qFatal("failed to set mode");
- m_modeSet = true;
-
- // Initialize cursor
-
- static int hideCursor = qEnvironmentVariableIntValue("QT_QPA_KMS_HIDECURSOR");
- if (!hideCursor) {
- QCursor cursor(Qt::ArrowCursor);
- m_cursor->changeCursor(&cursor, 0);
- }
- }
-
- int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
- fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, this);
- if (pageFlipStatus)
- {
- qWarning("Pageflip status: %d", pageFlipStatus);
- gbm_surface_release_buffer(m_gbmSurface, m_next_bo);
- m_next_bo = 0;
- }
-}
-
-void QKmsScreen::handlePageFlipped()
-{
- if (m_current_bo)
- gbm_surface_release_buffer(m_gbmSurface, m_current_bo);
-
- m_current_bo = m_next_bo;
- m_next_bo = 0;
-}
-
-QKmsDevice * QKmsScreen::device() const
-{
- return m_device;
-}
-
-void QKmsScreen::waitForPageFlipComplete()
-{
- while (m_next_bo) {
-#if 0
- //Check manually if there is something to be read on the device
- //as there are senarios where the signal is not received (starvation)
- fd_set fdSet;
- timeval timeValue;
- int returnValue;
-
- FD_ZERO(&fdSet);
- FD_SET(m_device->fd(), &fdSet);
- timeValue.tv_sec = 0;
- timeValue.tv_usec = 1000;
-
- returnValue = select(1, &fdSet, 0, 0, &timeValue);
- printf("select returns %d\n", returnValue);
-#endif
-
- m_device->handlePageFlipCompleted();
- }
-}
-
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
deleted file mode 100644
index c52d0211b3..0000000000
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QKMSSCREEN_H
-#define QKMSSCREEN_H
-
-#include <stddef.h>
-
-#define EGL_EGLEXT_PROTOTYPES 1
-#define GL_GLEXT_PROTOTYPES 1
-
-extern "C" {
-#include <gbm.h>
-#include <xf86drmMode.h>
-#include <xf86drm.h>
-}
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <QtGui/qopengl.h>
-#include <QtGui/qsurfaceformat.h>
-#include <QtCore/qloggingcategory.h>
-
-#include <qpa/qplatformscreen.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
-
-class QKmsCursor;
-class QKmsDevice;
-class QKmsContext;
-
-class QKmsScreen : public QPlatformScreen
-{
-public:
- QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector);
- ~QKmsScreen();
-
- QRect geometry() const Q_DECL_OVERRIDE;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
- QSizeF physicalSize() const Q_DECL_OVERRIDE;
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
-
- quint32 crtcId() const { return m_crtcId; }
- QKmsDevice *device() const;
-
- void initializeWithFormat(const QSurfaceFormat &format);
-
- //Called by context for each screen
- void swapBuffers();
- void handlePageFlipped();
-
- EGLSurface eglSurface() const { return m_eglWindowSurface; }
-
- void waitForPageFlipComplete();
-
- static QSurfaceFormat tweakFormat(const QSurfaceFormat &format);
-
- QSurfaceFormat surfaceFormat() const { return m_surfaceFormat; }
-
-private:
- void performPageFlip();
- void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector);
-
- QKmsDevice *m_device;
- gbm_bo *m_current_bo;
- gbm_bo *m_next_bo;
- quint32 m_connectorId;
-
- quint32 m_crtcId;
- drmModeModeInfo m_mode;
- QRect m_geometry;
- QSizeF m_physicalSize;
- int m_depth;
- QImage::Format m_format;
-
- drmModeCrtcPtr m_oldCrtc;
-
- QKmsCursor *m_cursor;
-
- gbm_surface *m_gbmSurface;
- EGLSurface m_eglWindowSurface;
-
- bool m_modeSet;
- QSurfaceFormat m_surfaceFormat;
-};
-
-QT_END_NAMESPACE
-
-#endif // QKMSSCREEN_H
diff --git a/src/plugins/platforms/kms/qkmswindow.cpp b/src/plugins/platforms/kms/qkmswindow.cpp
deleted file mode 100644
index 3b01dfedca..0000000000
--- a/src/plugins/platforms/kms/qkmswindow.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkmswindow.h"
-#include "qkmsscreen.h"
-
-#include <qpa/qwindowsysteminterface.h>
-#include <qpa/qplatformwindow_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QKmsWindow::QKmsWindow(QWindow *window)
- : QPlatformWindow(window)
-{
- Q_D(QPlatformWindow);
- m_screen = QPlatformScreen::platformScreenForWindow(window);
- static_cast<QKmsScreen *>(m_screen)->initializeWithFormat(window->requestedFormat());
- setGeometry(d->rect); // rect is set to window->geometry() in base ctor
-}
-
-void QKmsWindow::setGeometry(const QRect &rect)
-{
- // All windows must be fullscreen
- QRect fullscreenRect = m_screen->availableGeometry();
- if (rect != fullscreenRect)
- QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
-
- QPlatformWindow::setGeometry(fullscreenRect);
-}
-
-QSurfaceFormat QKmsWindow::format() const
-{
- return static_cast<QKmsScreen *>(m_screen)->surfaceFormat();
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index ccf86dafb2..8c8c8a15ea 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -46,6 +46,10 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
+#ifndef QT_NO_LIBINPUT
+#include <QtPlatformSupport/private/qlibinputhandler_p.h>
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
@@ -130,6 +134,13 @@ QPlatformServices *QLinuxFbIntegration::services() const
void QLinuxFbIntegration::createInputHandlers()
{
+#ifndef QT_NO_LIBINPUT
+ if (!qEnvironmentVariableIntValue("QT_QPA_FB_NO_LIBINPUT")) {
+ new QLibInputHandler(QLatin1String("libinput"), QString());
+ return;
+ }
+#endif
+
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this);
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
index ef96985f1a..1bcb22618e 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
@@ -37,7 +37,15 @@
#include "qminimaleglbackingstore.h"
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+
+#if defined(Q_OS_UNIX)
+# include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#elif defined(Q_OS_WINRT)
+# include <QtCore/private/qeventdispatcher_winrt_p.h>
+# include <QtGui/qpa/qwindowsysteminterface.h>
+#elif defined(Q_OS_WIN)
+# include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
+#endif
#include <qpa/qplatformwindow.h>
#include <QtGui/QSurfaceFormat>
@@ -48,6 +56,29 @@
QT_BEGIN_NAMESPACE
+#ifdef Q_OS_WINRT
+namespace {
+class QWinRTEventDispatcher : public QEventDispatcherWinRT {
+public:
+ QWinRTEventDispatcher() {}
+
+protected:
+ bool hasPendingEvents() Q_DECL_OVERRIDE
+ {
+ return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued();
+ }
+
+ bool sendPostedEvents(QEventLoop::ProcessEventsFlags flags)
+ {
+ bool didProcess = QEventDispatcherWinRT::sendPostedEvents(flags);
+ if (!(flags & QEventLoop::ExcludeUserInputEvents))
+ didProcess |= QWindowSystemInterface::sendWindowSystemEvents(flags);
+ return didProcess;
+ }
+};
+} // anonymous namespace
+#endif // Q_OS_WINRT
+
QMinimalEglIntegration::QMinimalEglIntegration()
: mFontDb(new QGenericUnixFontDatabase()), mScreen(new QMinimalEglScreen(EGL_DEFAULT_DISPLAY))
{
@@ -104,7 +135,15 @@ QPlatformFontDatabase *QMinimalEglIntegration::fontDatabase() const
QAbstractEventDispatcher *QMinimalEglIntegration::createEventDispatcher() const
{
+#if defined(Q_OS_UNIX)
return createUnixEventDispatcher();
+#elif defined(Q_OS_WINRT)
+ return new QWinRTEventDispatcher;
+#elif defined(Q_OS_WIN)
+ return new QWindowsGuiEventDispatcher;
+#else
+ return Q_NULLPTR;
+#endif
}
QVariant QMinimalEglIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
diff --git a/src/plugins/platforms/mirclient/mirclient.json b/src/plugins/platforms/mirclient/mirclient.json
new file mode 100644
index 0000000000..c31558a2f1
--- /dev/null
+++ b/src/plugins/platforms/mirclient/mirclient.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "mirclient" ]
+}
diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro
new file mode 100644
index 0000000000..033ce579b9
--- /dev/null
+++ b/src/plugins/platforms/mirclient/mirclient.pro
@@ -0,0 +1,47 @@
+TARGET = mirclient
+TEMPLATE = lib
+
+PLUGIN_TYPE = platforms
+PLUGIN_CLASS_NAME = MirServerIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private dbus
+
+CONFIG += qpa/genericunixfontdatabase
+
+DEFINES += MESA_EGL_NO_X11_HEADERS
+# CONFIG += c++11 # only enables C++0x
+QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
+QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined
+
+CONFIG += link_pkgconfig
+PKGCONFIG += egl mirclient ubuntu-platform-api
+
+SOURCES = \
+ qmirclientbackingstore.cpp \
+ qmirclientclipboard.cpp \
+ qmirclientglcontext.cpp \
+ qmirclientinput.cpp \
+ qmirclientintegration.cpp \
+ qmirclientnativeinterface.cpp \
+ qmirclientplatformservices.cpp \
+ qmirclientplugin.cpp \
+ qmirclientscreen.cpp \
+ qmirclienttheme.cpp \
+ qmirclientwindow.cpp
+
+HEADERS = \
+ qmirclientbackingstore.h \
+ qmirclientclipboard.h \
+ qmirclientglcontext.h \
+ qmirclientinput.h \
+ qmirclientintegration.h \
+ qmirclientlogging.h \
+ qmirclientnativeinterface.h \
+ qmirclientorientationchangeevent_p.h \
+ qmirclientplatformservices.h \
+ qmirclientplugin.h \
+ qmirclientscreen.h \
+ qmirclienttheme.h \
+ qmirclientwindow.h
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
new file mode 100644
index 0000000000..daa0b229ec
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientbackingstore.h"
+#include "qmirclientlogging.h"
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/private/qopengltextureblitter_p.h>
+#include <QtGui/qopenglfunctions.h>
+
+QMirClientBackingStore::QMirClientBackingStore(QWindow* window)
+ : QPlatformBackingStore(window)
+ , mContext(new QOpenGLContext)
+ , mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))
+ , mBlitter(new QOpenGLTextureBlitter)
+{
+ mContext->setFormat(window->requestedFormat());
+ mContext->setScreen(window->screen());
+ mContext->create();
+
+ window->setSurfaceType(QSurface::OpenGLSurface);
+}
+
+QMirClientBackingStore::~QMirClientBackingStore()
+{
+}
+
+void QMirClientBackingStore::flush(QWindow* window, const QRegion& region, const QPoint& offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+ mContext->makeCurrent(window);
+ glViewport(0, 0, window->width(), window->height());
+
+ updateTexture();
+
+ if (!mBlitter->isCreated())
+ mBlitter->create();
+
+ mBlitter->bind();
+ mBlitter->setSwizzleRB(true);
+ mBlitter->blit(mTexture->textureId(), QMatrix4x4(), QOpenGLTextureBlitter::OriginTopLeft);
+ mBlitter->release();
+
+ mContext->swapBuffers(window);
+}
+
+void QMirClientBackingStore::updateTexture()
+{
+ if (mDirty.isNull())
+ return;
+
+ if (!mTexture->isCreated()) {
+ mTexture->setMinificationFilter(QOpenGLTexture::Nearest);
+ mTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
+ mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
+ mTexture->setData(mImage, QOpenGLTexture::DontGenerateMipMaps);
+ mTexture->create();
+ }
+ mTexture->bind();
+
+ QRegion fixed;
+ QRect imageRect = mImage.rect();
+
+ Q_FOREACH (const QRect &rect, mDirty.rects()) {
+ // intersect with image rect to be sure
+ QRect r = imageRect & rect;
+
+ // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
+ if (r.width() >= imageRect.width() / 2) {
+ r.setX(0);
+ r.setWidth(imageRect.width());
+ }
+
+ fixed |= r;
+ }
+
+ Q_FOREACH (const QRect &rect, fixed.rects()) {
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there is no gap between scanlines
+ if (rect.width() == imageRect.width()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ mImage.constScanLine(rect.y()));
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ mImage.copy(rect).constBits());
+ }
+ }
+ /* End of code taken from QEGLPlatformBackingStore */
+
+ mDirty = QRegion();
+}
+
+
+void QMirClientBackingStore::beginPaint(const QRegion& region)
+{
+ mDirty |= region;
+}
+
+void QMirClientBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)
+{
+ mImage = QImage(size, QImage::Format_RGB32);
+
+ if (mTexture->isCreated())
+ mTexture->destroy();
+}
+
+QPaintDevice* QMirClientBackingStore::paintDevice()
+{
+ return &mImage;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.h b/src/plugins/platforms/mirclient/qmirclientbackingstore.h
new file mode 100644
index 0000000000..22b8bf9bc5
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientbackingstore.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTBACKINGSTORE_H
+#define QMIRCLIENTBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+
+class QOpenGLContext;
+class QOpenGLTexture;
+class QOpenGLTextureBlitter;
+
+class QMirClientBackingStore : public QPlatformBackingStore
+{
+public:
+ QMirClientBackingStore(QWindow* window);
+ virtual ~QMirClientBackingStore();
+
+ // QPlatformBackingStore methods.
+ void beginPaint(const QRegion&) override;
+ void flush(QWindow* window, const QRegion& region, const QPoint& offset) override;
+ void resize(const QSize& size, const QRegion& staticContents) override;
+ QPaintDevice* paintDevice() override;
+
+protected:
+ void updateTexture();
+
+private:
+ QScopedPointer<QOpenGLContext> mContext;
+ QScopedPointer<QOpenGLTexture> mTexture;
+ QScopedPointer<QOpenGLTextureBlitter> mBlitter;
+ QImage mImage;
+ QRegion mDirty;
+};
+
+#endif // QMIRCLIENTBACKINGSTORE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
new file mode 100644
index 0000000000..aa2ddf2103
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientclipboard.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QStringList>
+#include <QDBusInterface>
+#include <QDBusPendingCallWatcher>
+#include <QDBusPendingReply>
+
+// FIXME(loicm) The clipboard data format is not defined by Ubuntu Platform API
+// which makes it impossible to have non-Qt applications communicate with Qt
+// applications through the clipboard API. The solution would be to have
+// Ubuntu Platform define the data format or propose an API that supports
+// embedding different mime types in the clipboard.
+
+// Data format:
+// number of mime types (sizeof(int))
+// data layout ((4 * sizeof(int)) * number of mime types)
+// mime type string offset (sizeof(int))
+// mime type string size (sizeof(int))
+// data offset (sizeof(int))
+// data size (sizeof(int))
+// data (n bytes)
+
+namespace {
+
+const int maxFormatsCount = 16;
+const int maxBufferSize = 4 * 1024 * 1024; // 4 Mb
+
+}
+
+QMirClientClipboard::QMirClientClipboard()
+ : mMimeData(new QMimeData)
+ , mIsOutdated(true)
+ , mUpdatesDisabled(false)
+ , mDBusSetupDone(false)
+{
+}
+
+QMirClientClipboard::~QMirClientClipboard()
+{
+ delete mMimeData;
+}
+
+void QMirClientClipboard::requestDBusClipboardContents()
+{
+ if (!mDBusSetupDone) {
+ setupDBus();
+ }
+
+ if (!mPendingGetContentsCall.isNull())
+ return;
+
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents");
+
+ mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
+
+ QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*)));
+}
+
+void QMirClientClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call)
+{
+ Q_ASSERT(call == mPendingGetContentsCall.data());
+
+ QDBusPendingReply<QByteArray> reply = *call;
+ if (reply.isError()) {
+ qCritical("QMirClientClipboard - Failed to get system clipboard contents via D-Bus. %s, %s",
+ qPrintable(reply.error().name()), qPrintable(reply.error().message()));
+ // TODO: Might try again later a number of times...
+ } else {
+ QByteArray serializedMimeData = reply.argumentAt<0>();
+ updateMimeData(serializedMimeData);
+ }
+ call->deleteLater();
+}
+
+void QMirClientClipboard::onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher *call)
+{
+ QDBusPendingReply<void> reply = *call;
+ if (reply.isError()) {
+ qCritical("QMirClientClipboard - Failed to set the system clipboard contents via D-Bus. %s, %s",
+ qPrintable(reply.error().name()), qPrintable(reply.error().message()));
+ // TODO: Might try again later a number of times...
+ }
+ call->deleteLater();
+}
+
+void QMirClientClipboard::updateMimeData(const QByteArray &serializedMimeData)
+{
+ if (mUpdatesDisabled)
+ return;
+
+ QMimeData *newMimeData = deserializeMimeData(serializedMimeData);
+ if (newMimeData) {
+ delete mMimeData;
+ mMimeData = newMimeData;
+ mIsOutdated = false;
+ emitChanged(QClipboard::Clipboard);
+ } else {
+ qWarning("QMirClientClipboard - Got invalid serialized mime data. Ignoring it.");
+ }
+}
+
+void QMirClientClipboard::setupDBus()
+{
+ QDBusConnection dbusConnection = QDBusConnection::sessionBus();
+
+ bool ok = dbusConnection.connect(
+ "com.canonical.QtMir",
+ "/com/canonical/QtMir/Clipboard",
+ "com.canonical.QtMir.Clipboard",
+ "ContentsChanged",
+ this, SLOT(updateMimeData(QByteArray)));
+ if (!ok) {
+ qCritical("QMirClientClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard.");
+ }
+
+ mDBusClipboard = new QDBusInterface("com.canonical.QtMir",
+ "/com/canonical/QtMir/Clipboard",
+ "com.canonical.QtMir.Clipboard",
+ dbusConnection);
+
+ mDBusSetupDone = true;
+}
+
+QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const
+{
+ const QStringList formats = mimeData->formats();
+ const int formatCount = qMin(formats.size(), maxFormatsCount);
+ const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int));
+ int bufferSize = headerSize;
+
+ for (int i = 0; i < formatCount; i++)
+ bufferSize += formats[i].size() + mimeData->data(formats[i]).size();
+
+ QByteArray serializedMimeData;
+ if (bufferSize <= maxBufferSize) {
+ // Serialize data.
+ serializedMimeData.resize(bufferSize);
+ {
+ char *buffer = serializedMimeData.data();
+ int* header = reinterpret_cast<int*>(serializedMimeData.data());
+ int offset = headerSize;
+ header[0] = formatCount;
+ for (int i = 0; i < formatCount; i++) {
+ const int formatOffset = offset;
+ const int formatSize = formats[i].size();
+ const int dataOffset = offset + formatSize;
+ const int dataSize = mimeData->data(formats[i]).size();
+ memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize);
+ memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize);
+ header[i*4+1] = formatOffset;
+ header[i*4+2] = formatSize;
+ header[i*4+3] = dataOffset;
+ header[i*4+4] = dataSize;
+ offset += formatSize + dataSize;
+ }
+ }
+ } else {
+ qWarning("QMirClientClipboard: Not sending contents (%d bytes) to the global clipboard as it's"
+ " bigger than the maximum allowed size of %d bytes", bufferSize, maxBufferSize);
+ }
+
+ return serializedMimeData;
+}
+
+QMimeData *QMirClientClipboard::deserializeMimeData(const QByteArray &serializedMimeData) const
+{
+ if (static_cast<std::size_t>(serializedMimeData.size()) < sizeof(int)) {
+ // Data is invalid
+ return nullptr;
+ }
+
+ QMimeData *mimeData = new QMimeData;
+
+ const char* const buffer = serializedMimeData.constData();
+ const int* const header = reinterpret_cast<const int*>(serializedMimeData.constData());
+
+ const int count = qMin(header[0], maxFormatsCount);
+
+ for (int i = 0; i < count; i++) {
+ const int formatOffset = header[i*4+1];
+ const int formatSize = header[i*4+2];
+ const int dataOffset = header[i*4+3];
+ const int dataSize = header[i*4+4];
+
+ if (formatOffset + formatSize <= serializedMimeData.size()
+ && dataOffset + dataSize <= serializedMimeData.size()) {
+
+ QString mimeType = QString::fromLatin1(&buffer[formatOffset], formatSize);
+ QByteArray mimeDataBytes(&buffer[dataOffset], dataSize);
+
+ mimeData->setData(mimeType, mimeDataBytes);
+ }
+ }
+
+ return mimeData;
+}
+
+QMimeData* QMirClientClipboard::mimeData(QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return nullptr;
+
+ if (mIsOutdated && mPendingGetContentsCall.isNull()) {
+ requestDBusClipboardContents();
+ }
+
+ // Return whatever we have at the moment instead of blocking until we have something.
+ //
+ // This might be called during app startup just for the sake of checking if some
+ // "Paste" UI control should be enabled or not.
+ // We will emit QClipboard::changed() once we finally have something.
+ return mMimeData;
+}
+
+void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return;
+
+ if (!mPendingGetContentsCall.isNull()) {
+ // Ignore whatever comes from the system clipboard as we are going to change it anyway
+ QObject::disconnect(mPendingGetContentsCall.data(), 0, this, 0);
+ mUpdatesDisabled = true;
+ mPendingGetContentsCall->waitForFinished();
+ mUpdatesDisabled = false;
+ delete mPendingGetContentsCall.data();
+ }
+
+ QByteArray serializedMimeData = serializeMimeData(mimeData);
+ if (!serializedMimeData.isEmpty()) {
+ setDBusClipboardContents(serializedMimeData);
+ }
+
+ mMimeData = mimeData;
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const
+{
+ return mode == QClipboard::Clipboard;
+}
+
+bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardContents)
+{
+ if (!mPendingSetContentsCall.isNull()) {
+ // Ignore any previous set call as we are going to overwrite it anyway
+ QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0);
+ mUpdatesDisabled = true;
+ mPendingSetContentsCall->waitForFinished();
+ mUpdatesDisabled = false;
+ delete mPendingSetContentsCall.data();
+ }
+
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents);
+
+ mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
+
+ QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*)));
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.h b/src/plugins/platforms/mirclient/qmirclientclipboard.h
new file mode 100644
index 0000000000..d3d3d400d2
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientclipboard.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTCLIPBOARD_H
+#define QMIRCLIENTCLIPBOARD_H
+
+#include <qpa/qplatformclipboard.h>
+
+#include <QMimeData>
+#include <QPointer>
+class QDBusInterface;
+class QDBusPendingCallWatcher;
+
+class QMirClientClipboard : public QObject, public QPlatformClipboard
+{
+ Q_OBJECT
+public:
+ QMirClientClipboard();
+ virtual ~QMirClientClipboard();
+
+ // QPlatformClipboard methods.
+ 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;
+
+ void requestDBusClipboardContents();
+
+private Q_SLOTS:
+ void onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*);
+ void onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*);
+ void updateMimeData(const QByteArray &serializedMimeData);
+
+private:
+ void setupDBus();
+
+ QByteArray serializeMimeData(QMimeData *mimeData) const;
+ QMimeData *deserializeMimeData(const QByteArray &serializedMimeData) const;
+
+ void setDBusClipboardContents(const QByteArray &clipboardContents);
+
+ QMimeData *mMimeData;
+ bool mIsOutdated;
+
+ QPointer<QDBusInterface> mDBusClipboard;
+
+ QPointer<QDBusPendingCallWatcher> mPendingGetContentsCall;
+ QPointer<QDBusPendingCallWatcher> mPendingSetContentsCall;
+
+ bool mUpdatesDisabled;
+ bool mDBusSetupDone;
+};
+
+#endif // QMIRCLIENTCLIPBOARD_H
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
new file mode 100644
index 0000000000..bfba5051e5
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientglcontext.h"
+#include "qmirclientwindow.h"
+#include "qmirclientlogging.h"
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+
+#if !defined(QT_NO_DEBUG)
+static void printOpenGLESConfig() {
+ static bool once = true;
+ if (once) {
+ const char* string = (const char*) glGetString(GL_VENDOR);
+ LOG("OpenGL ES vendor: %s", string);
+ string = (const char*) glGetString(GL_RENDERER);
+ LOG("OpenGL ES renderer: %s", string);
+ string = (const char*) glGetString(GL_VERSION);
+ LOG("OpenGL ES version: %s", string);
+ string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
+ LOG("OpenGL ES Shading Language version: %s", string);
+ string = (const char*) glGetString(GL_EXTENSIONS);
+ LOG("OpenGL ES extensions: %s", string);
+ once = false;
+ }
+}
+#endif
+
+static EGLenum api_in_use()
+{
+#ifdef QTUBUNTU_USE_OPENGL
+ return EGL_OPENGL_API;
+#else
+ return EGL_OPENGL_ES_API;
+#endif
+}
+
+QMirClientOpenGLContext::QMirClientOpenGLContext(QMirClientScreen* screen, QMirClientOpenGLContext* share)
+{
+ ASSERT(screen != NULL);
+ mEglDisplay = screen->eglDisplay();
+ mScreen = screen;
+
+ // Create an OpenGL ES 2 context.
+ QVector<EGLint> attribs;
+ attribs.append(EGL_CONTEXT_CLIENT_VERSION);
+ attribs.append(2);
+ attribs.append(EGL_NONE);
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+
+ mEglContext = eglCreateContext(mEglDisplay, screen->eglConfig(), share ? share->eglContext() : EGL_NO_CONTEXT,
+ attribs.constData());
+ DASSERT(mEglContext != EGL_NO_CONTEXT);
+}
+
+QMirClientOpenGLContext::~QMirClientOpenGLContext()
+{
+ ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE);
+}
+
+bool QMirClientOpenGLContext::makeCurrent(QPlatformSurface* surface)
+{
+ DASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ EGLSurface eglSurface = static_cast<QMirClientWindow*>(surface)->eglSurface();
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext) == EGL_TRUE);
+ printOpenGLESConfig();
+#endif
+ return true;
+}
+
+void QMirClientOpenGLContext::doneCurrent()
+{
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE);
+#endif
+}
+
+void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface)
+{
+ QMirClientWindow *ubuntuWindow = static_cast<QMirClientWindow*>(surface);
+
+ EGLSurface eglSurface = ubuntuWindow->eglSurface();
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglSwapBuffers(mEglDisplay, eglSurface);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
+#endif
+
+ // "Technique" copied from mir, in examples/eglapp.c around line 96
+ EGLint newBufferWidth = -1;
+ EGLint newBufferHeight = -1;
+ /*
+ * Querying the surface (actually the current buffer) dimensions here is
+ * the only truly safe way to be sure that the dimensions we think we
+ * have are those of the buffer being rendered to. But this should be
+ * improved in future; https://bugs.launchpad.net/mir/+bug/1194384
+ */
+ eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &newBufferWidth);
+ eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &newBufferHeight);
+
+ ubuntuWindow->onBuffersSwapped_threadSafe(newBufferWidth, newBufferHeight);
+}
+
+void (*QMirClientOpenGLContext::getProcAddress(const QByteArray& procName)) ()
+{
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+#endif
+ return eglGetProcAddress(procName.constData());
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/plugins/platforms/mirclient/qmirclientglcontext.h
new file mode 100644
index 0000000000..cc40298259
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTGLCONTEXT_H
+#define QMIRCLIENTGLCONTEXT_H
+
+#include <qpa/qplatformopenglcontext.h>
+#include "qmirclientscreen.h"
+
+class QMirClientOpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ QMirClientOpenGLContext(QMirClientScreen* screen, QMirClientOpenGLContext* share);
+ virtual ~QMirClientOpenGLContext();
+
+ // QPlatformOpenGLContext methods.
+ QSurfaceFormat format() const override { return mScreen->surfaceFormat(); }
+ void swapBuffers(QPlatformSurface* surface) override;
+ bool makeCurrent(QPlatformSurface* surface) override;
+ void doneCurrent() override;
+ bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; }
+ void (*getProcAddress(const QByteArray& procName)) ();
+
+ EGLContext eglContext() const { return mEglContext; }
+
+private:
+ QMirClientScreen* mScreen;
+ EGLContext mEglContext;
+ EGLDisplay mEglDisplay;
+};
+
+#endif // QMIRCLIENTGLCONTEXT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp
new file mode 100644
index 0000000000..56bc21f420
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp
@@ -0,0 +1,520 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Local
+#include "qmirclientinput.h"
+#include "qmirclientintegration.h"
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclientwindow.h"
+#include "qmirclientlogging.h"
+#include "qmirclientorientationchangeevent_p.h"
+
+// Qt
+#if !defined(QT_NO_DEBUG)
+#include <QtCore/QThread>
+#endif
+#include <QtCore/qglobal.h>
+#include <QtCore/QCoreApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatforminputcontext.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+
+#include <mir_toolkit/mir_client_library.h>
+
+#define LOG_EVENTS 0
+
+// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
+static const uint32_t KeyTable[] = {
+ XKB_KEY_Escape, Qt::Key_Escape,
+ XKB_KEY_Tab, Qt::Key_Tab,
+ XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
+ XKB_KEY_BackSpace, Qt::Key_Backspace,
+ XKB_KEY_Return, Qt::Key_Return,
+ XKB_KEY_Insert, Qt::Key_Insert,
+ XKB_KEY_Delete, Qt::Key_Delete,
+ XKB_KEY_Clear, Qt::Key_Delete,
+ XKB_KEY_Pause, Qt::Key_Pause,
+ XKB_KEY_Print, Qt::Key_Print,
+
+ XKB_KEY_Home, Qt::Key_Home,
+ XKB_KEY_End, Qt::Key_End,
+ XKB_KEY_Left, Qt::Key_Left,
+ XKB_KEY_Up, Qt::Key_Up,
+ XKB_KEY_Right, Qt::Key_Right,
+ XKB_KEY_Down, Qt::Key_Down,
+ XKB_KEY_Prior, Qt::Key_PageUp,
+ XKB_KEY_Next, Qt::Key_PageDown,
+
+ XKB_KEY_Shift_L, Qt::Key_Shift,
+ XKB_KEY_Shift_R, Qt::Key_Shift,
+ XKB_KEY_Shift_Lock, Qt::Key_Shift,
+ XKB_KEY_Control_L, Qt::Key_Control,
+ XKB_KEY_Control_R, Qt::Key_Control,
+ XKB_KEY_Meta_L, Qt::Key_Meta,
+ XKB_KEY_Meta_R, Qt::Key_Meta,
+ XKB_KEY_Alt_L, Qt::Key_Alt,
+ XKB_KEY_Alt_R, Qt::Key_Alt,
+ XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
+ XKB_KEY_Num_Lock, Qt::Key_NumLock,
+ XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
+ XKB_KEY_Super_L, Qt::Key_Super_L,
+ XKB_KEY_Super_R, Qt::Key_Super_R,
+ XKB_KEY_Menu, Qt::Key_Menu,
+ XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
+ XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
+ XKB_KEY_Help, Qt::Key_Help,
+
+ XKB_KEY_KP_Space, Qt::Key_Space,
+ XKB_KEY_KP_Tab, Qt::Key_Tab,
+ XKB_KEY_KP_Enter, Qt::Key_Enter,
+ XKB_KEY_KP_Home, Qt::Key_Home,
+ XKB_KEY_KP_Left, Qt::Key_Left,
+ XKB_KEY_KP_Up, Qt::Key_Up,
+ XKB_KEY_KP_Right, Qt::Key_Right,
+ XKB_KEY_KP_Down, Qt::Key_Down,
+ XKB_KEY_KP_Prior, Qt::Key_PageUp,
+ XKB_KEY_KP_Next, Qt::Key_PageDown,
+ XKB_KEY_KP_End, Qt::Key_End,
+ XKB_KEY_KP_Begin, Qt::Key_Clear,
+ XKB_KEY_KP_Insert, Qt::Key_Insert,
+ XKB_KEY_KP_Delete, Qt::Key_Delete,
+ XKB_KEY_KP_Equal, Qt::Key_Equal,
+ XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
+ XKB_KEY_KP_Add, Qt::Key_Plus,
+ XKB_KEY_KP_Separator, Qt::Key_Comma,
+ XKB_KEY_KP_Subtract, Qt::Key_Minus,
+ XKB_KEY_KP_Decimal, Qt::Key_Period,
+ XKB_KEY_KP_Divide, Qt::Key_Slash,
+
+ XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
+ XKB_KEY_Multi_key, Qt::Key_Multi_key,
+ XKB_KEY_Codeinput, Qt::Key_Codeinput,
+ XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
+ XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
+ XKB_KEY_script_switch, Qt::Key_Mode_switch,
+ XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
+ XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
+ XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
+ XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
+
+ 0, 0
+};
+
+class QMirClientEvent : public QEvent
+{
+public:
+ QMirClientEvent(QMirClientWindow* window, const MirEvent *event, QEvent::Type type)
+ : QEvent(type), window(window) {
+ nativeEvent = mir_event_ref(event);
+ }
+ ~QMirClientEvent()
+ {
+ mir_event_unref(nativeEvent);
+ }
+
+ QPointer<QMirClientWindow> window;
+ const MirEvent *nativeEvent;
+};
+
+QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration)
+ : QObject(nullptr)
+ , mIntegration(integration)
+ , mEventFilterType(static_cast<QMirClientNativeInterface*>(
+ integration->nativeInterface())->genericEventFilterType())
+ , mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
+{
+ // Initialize touch device.
+ mTouchDevice = new QTouchDevice;
+ mTouchDevice->setType(QTouchDevice::TouchScreen);
+ mTouchDevice->setCapabilities(
+ QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
+ QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+}
+
+QMirClientInput::~QMirClientInput()
+{
+ // Qt will take care of deleting mTouchDevice.
+}
+
+#if (LOG_EVENTS != 0)
+static const char* nativeEventTypeToStr(MirEventType t)
+{
+ switch (t)
+ {
+ case mir_event_type_key:
+ return "mir_event_type_key";
+ case mir_event_type_motion:
+ return "mir_event_type_motion";
+ case mir_event_type_surface:
+ return "mir_event_type_surface";
+ case mir_event_type_resize:
+ return "mir_event_type_resize";
+ case mir_event_type_prompt_session_state_change:
+ return "mir_event_type_prompt_session_state_change";
+ case mir_event_type_orientation:
+ return "mir_event_type_orientation";
+ case mir_event_type_close_surface:
+ return "mir_event_type_close_surface";
+ case mir_event_type_input:
+ return "mir_event_type_input";
+ default:
+ DLOG("Invalid event type %d", t);
+ return "invalid";
+ }
+}
+#endif // LOG_EVENTS != 0
+
+void QMirClientInput::customEvent(QEvent* event)
+{
+ DASSERT(QThread::currentThread() == thread());
+ QMirClientEvent* ubuntuEvent = static_cast<QMirClientEvent*>(event);
+ const MirEvent *nativeEvent = ubuntuEvent->nativeEvent;
+
+ if ((ubuntuEvent->window == nullptr) || (ubuntuEvent->window->window() == nullptr)) {
+ qWarning() << "Attempted to deliver an event to a non-existent window, ignoring.";
+ return;
+ }
+
+ // Event filtering.
+ long result;
+ if (QWindowSystemInterface::handleNativeEvent(
+ ubuntuEvent->window->window(), mEventFilterType,
+ const_cast<void *>(static_cast<const void *>(nativeEvent)), &result) == true) {
+ DLOG("event filtered out by native interface");
+ return;
+ }
+
+ #if (LOG_EVENTS != 0)
+ LOG("QMirClientInput::customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
+ #endif
+
+ // Event dispatching.
+ switch (mir_event_get_type(nativeEvent))
+ {
+ case mir_event_type_input:
+ dispatchInputEvent(ubuntuEvent->window->window(), mir_event_get_input_event(nativeEvent));
+ break;
+ case mir_event_type_resize:
+ {
+ Q_ASSERT(ubuntuEvent->window->screen() == mIntegration->screen());
+
+ auto resizeEvent = mir_event_get_resize_event(nativeEvent);
+
+ mIntegration->screen()->handleWindowSurfaceResize(
+ mir_resize_event_get_width(resizeEvent),
+ mir_resize_event_get_height(resizeEvent));
+
+ ubuntuEvent->window->handleSurfaceResize(mir_resize_event_get_width(resizeEvent),
+ mir_resize_event_get_height(resizeEvent));
+ break;
+ }
+ case mir_event_type_surface:
+ {
+ auto surfaceEvent = mir_event_get_surface_event(nativeEvent);
+ if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) {
+ ubuntuEvent->window->handleSurfaceFocusChange(mir_surface_event_get_attribute_value(surfaceEvent) ==
+ mir_surface_focused);
+ }
+ break;
+ }
+ case mir_event_type_orientation:
+ dispatchOrientationEvent(ubuntuEvent->window->window(), mir_event_get_orientation_event(nativeEvent));
+ break;
+ case mir_event_type_close_surface:
+ QWindowSystemInterface::handleCloseEvent(ubuntuEvent->window->window());
+ break;
+ default:
+ DLOG("unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
+ }
+}
+
+void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent *event)
+{
+ QWindow *window = platformWindow->window();
+
+ QCoreApplication::postEvent(this, new QMirClientEvent(
+ platformWindow, event, mEventType));
+
+ if ((window->flags().testFlag(Qt::WindowTransparentForInput)) && window->parent()) {
+ QCoreApplication::postEvent(this, new QMirClientEvent(
+ static_cast<QMirClientWindow*>(platformWindow->QPlatformWindow::parent()),
+ event, mEventType));
+ }
+}
+
+void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *ev)
+{
+ switch (mir_input_event_get_type(ev))
+ {
+ case mir_input_event_type_key:
+ dispatchKeyEvent(window, ev);
+ break;
+ case mir_input_event_type_touch:
+ dispatchTouchEvent(window, ev);
+ break;
+ case mir_input_event_type_pointer:
+ dispatchPointerEvent(window, ev);
+ break;
+ default:
+ break;
+ }
+}
+
+void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev)
+{
+ const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
+
+ // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
+ // needs to be fixed as soon as the compat input lib adds query support.
+ const float kMaxPressure = 1.28;
+ const QRect kWindowGeometry = window->geometry();
+ QList<QWindowSystemInterface::TouchPoint> touchPoints;
+
+
+ // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
+ // as Qt::TouchPointMoved
+ const unsigned int kPointerCount = mir_touch_event_point_count(tev);
+ for (unsigned int i = 0; i < kPointerCount; ++i) {
+ QWindowSystemInterface::TouchPoint touchPoint;
+
+ const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();
+ const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
+ const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
+ const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
+ const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
+ touchPoint.id = mir_touch_event_id(tev, i);
+ touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
+ touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
+ touchPoint.pressure = kP / kMaxPressure;
+
+ MirTouchAction touch_action = mir_touch_event_action(tev, i);
+ switch (touch_action)
+ {
+ case mir_touch_action_down:
+ touchPoint.state = Qt::TouchPointPressed;
+ break;
+ case mir_touch_action_up:
+ touchPoint.state = Qt::TouchPointReleased;
+ break;
+ case mir_touch_action_change:
+ default:
+ touchPoint.state = Qt::TouchPointMoved;
+ }
+
+ touchPoints.append(touchPoint);
+ }
+
+ ulong timestamp = mir_input_event_get_event_time(ev) / 1000000;
+ QWindowSystemInterface::handleTouchEvent(window, timestamp,
+ mTouchDevice, touchPoints);
+}
+
+static uint32_t translateKeysym(uint32_t sym, char *string, size_t size)
+{
+ Q_UNUSED(size);
+ string[0] = '\0';
+
+ if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35)
+ return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
+
+ for (int i = 0; KeyTable[i]; i += 2) {
+ if (sym == KeyTable[i])
+ return KeyTable[i + 1];
+ }
+
+ string[0] = sym;
+ string[1] = '\0';
+ return toupper(sym);
+}
+
+namespace
+{
+Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers)
+{
+ Qt::KeyboardModifiers q_modifiers = Qt::NoModifier;
+ if (modifiers & mir_input_event_modifier_shift) {
+ q_modifiers |= Qt::ShiftModifier;
+ }
+ if (modifiers & mir_input_event_modifier_ctrl) {
+ q_modifiers |= Qt::ControlModifier;
+ }
+ if (modifiers & mir_input_event_modifier_alt) {
+ q_modifiers |= Qt::AltModifier;
+ }
+ if (modifiers & mir_input_event_modifier_meta) {
+ q_modifiers |= Qt::MetaModifier;
+ }
+ return q_modifiers;
+}
+}
+
+void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event)
+{
+ const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
+
+ ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
+ xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
+
+ // Key modifier and unicode index mapping.
+ auto modifiers = qt_modifiers_from_mir(mir_keyboard_event_modifiers(key_event));
+
+ MirKeyboardAction action = mir_keyboard_event_action(key_event);
+ QEvent::Type keyType = action == mir_keyboard_action_up
+ ? QEvent::KeyRelease : QEvent::KeyPress;
+
+ char s[2];
+ int sym = translateKeysym(xk_sym, s, sizeof(s));
+ QString text = QString::fromLatin1(s);
+
+ bool is_auto_rep = action == mir_keyboard_action_repeat;
+
+ QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ if (context) {
+ QKeyEvent qKeyEvent(keyType, sym, modifiers, text, is_auto_rep);
+ qKeyEvent.setTimestamp(timestamp);
+ if (context->filterEvent(&qKeyEvent)) {
+ DLOG("key event filtered out by input context");
+ return;
+ }
+ }
+
+ QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text, is_auto_rep);
+}
+
+namespace
+{
+Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
+{
+ Qt::MouseButtons buttons = Qt::NoButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
+ buttons |= Qt::LeftButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
+ buttons |= Qt::RightButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
+ buttons |= Qt::MidButton;
+
+ // TODO: Should mir back and forward buttons exist?
+ // should they be Qt::X button 1 and 2?
+ return buttons;
+}
+}
+
+void QMirClientInput::dispatchPointerEvent(QWindow *window, const MirInputEvent *ev)
+{
+ auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
+
+ auto pev = mir_input_event_get_pointer_event(ev);
+ auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
+ auto buttons = extract_buttons(pev);
+
+ auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
+ mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
+
+ QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */,
+ buttons, modifiers);
+}
+
+#if (LOG_EVENTS != 0)
+static const char* nativeOrientationDirectionToStr(MirOrientation orientation)
+{
+ switch (orientation) {
+ case mir_orientation_normal:
+ return "Normal";
+ break;
+ case mir_orientation_left:
+ return "Left";
+ break;
+ case mir_orientation_inverted:
+ return "Inverted";
+ break;
+ case mir_orientation_right:
+ return "Right";
+ break;
+ default:
+ return "INVALID!";
+ }
+}
+#endif
+
+void QMirClientInput::dispatchOrientationEvent(QWindow *window, const MirOrientationEvent *event)
+{
+ MirOrientation mir_orientation = mir_orientation_event_get_direction(event);
+ #if (LOG_EVENTS != 0)
+ // Orientation event logging.
+ LOG("ORIENTATION direction: %s", nativeOrientationDirectionToStr(mir_orientation));
+ #endif
+
+ if (!window->screen()) {
+ DLOG("Window has no associated screen, dropping orientation event");
+ return;
+ }
+
+ OrientationChangeEvent::Orientation orientation;
+ switch (mir_orientation) {
+ case mir_orientation_normal:
+ orientation = OrientationChangeEvent::TopUp;
+ break;
+ case mir_orientation_left:
+ orientation = OrientationChangeEvent::LeftUp;
+ break;
+ case mir_orientation_inverted:
+ orientation = OrientationChangeEvent::TopDown;
+ break;
+ case mir_orientation_right:
+ orientation = OrientationChangeEvent::RightUp;
+ break;
+ default:
+ DLOG("No such orientation %d", mir_orientation);
+ return;
+ }
+
+ // Dispatch orientation event to [Platform]Screen, as that is where Qt reads it. Screen will handle
+ // notifying Qt of the actual orientation change - done to prevent multiple Windows each creating
+ // an identical orientation change event and passing it directly to Qt.
+ // [Platform]Screen can also factor in the native orientation.
+ QCoreApplication::postEvent(static_cast<QMirClientScreen*>(window->screen()->handle()),
+ new OrientationChangeEvent(OrientationChangeEvent::mType, orientation));
+}
+
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h
new file mode 100644
index 0000000000..c987d18c12
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientinput.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTINPUT_H
+#define QMIRCLIENTINPUT_H
+
+// Qt
+#include <qpa/qwindowsysteminterface.h>
+
+#include <mir_toolkit/mir_client_library.h>
+
+class QMirClientClientIntegration;
+class QMirClientWindow;
+
+class QMirClientInput : public QObject
+{
+ Q_OBJECT
+
+public:
+ QMirClientInput(QMirClientClientIntegration* integration);
+ virtual ~QMirClientInput();
+
+ // QObject methods.
+ void customEvent(QEvent* event) override;
+
+ void postEvent(QMirClientWindow* window, const MirEvent *event);
+ QMirClientClientIntegration* integration() const { return mIntegration; }
+
+protected:
+ void dispatchKeyEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchPointerEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchTouchEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchInputEvent(QWindow *window, const MirInputEvent *event);
+
+ void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event);
+
+private:
+ QMirClientClientIntegration* mIntegration;
+ QTouchDevice* mTouchDevice;
+ const QByteArray mEventFilterType;
+ const QEvent::Type mEventType;
+};
+
+#endif // QMIRCLIENTINPUT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
new file mode 100644
index 0000000000..a234f4eac6
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Qt
+#include <QGuiApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatforminputcontext.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QOpenGLContext>
+
+// Local
+#include "qmirclientbackingstore.h"
+#include "qmirclientclipboard.h"
+#include "qmirclientglcontext.h"
+#include "qmirclientinput.h"
+#include "qmirclientintegration.h"
+#include "qmirclientlogging.h"
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclienttheme.h"
+#include "qmirclientwindow.h"
+
+// platform-api
+#include <ubuntu/application/lifecycle_delegate.h>
+#include <ubuntu/application/id.h>
+#include <ubuntu/application/options.h>
+
+static void resumedCallback(const UApplicationOptions *options, void* context)
+{
+ Q_UNUSED(options)
+ Q_UNUSED(context)
+ DASSERT(context != NULL);
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::ApplicationActivate));
+}
+
+static void aboutToStopCallback(UApplicationArchive *archive, void* context)
+{
+ Q_UNUSED(archive)
+ DASSERT(context != NULL);
+ QMirClientClientIntegration* integration = static_cast<QMirClientClientIntegration*>(context);
+ integration->inputContext()->hideInputPanel();
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::ApplicationDeactivate));
+}
+
+QMirClientClientIntegration::QMirClientClientIntegration()
+ : QPlatformIntegration()
+ , mNativeInterface(new QMirClientNativeInterface)
+ , mFontDb(new QGenericUnixFontDatabase)
+ , mServices(new QMirClientPlatformServices)
+ , mClipboard(new QMirClientClipboard)
+ , mScaleFactor(1.0)
+{
+ setupOptions();
+ setupDescription();
+
+ // Create new application instance
+ mInstance = u_application_instance_new_from_description_with_options(mDesc, mOptions);
+
+ if (mInstance == nullptr)
+ qFatal("QMirClientClientIntegration: connection to Mir server failed. Check that a Mir server is\n"
+ "running, and the correct socket is being used and is accessible. The shell may have\n"
+ "rejected the incoming connection, so check its log file");
+
+ // Create default screen.
+ mScreen = new QMirClientScreen(u_application_instance_get_mir_connection(mInstance));
+ screenAdded(mScreen);
+
+ // Initialize input.
+ if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_INPUT")) {
+ mInput = new QMirClientInput(this);
+ mInputContext = QPlatformInputContextFactory::create();
+ } else {
+ mInput = nullptr;
+ mInputContext = nullptr;
+ }
+
+ // compute the scale factor
+ const int defaultGridUnit = 8;
+ int gridUnit = defaultGridUnit;
+ QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
+ if (!gridUnitString.isEmpty()) {
+ bool ok;
+ gridUnit = gridUnitString.toInt(&ok);
+ if (!ok) {
+ gridUnit = defaultGridUnit;
+ }
+ }
+ mScaleFactor = static_cast<qreal>(gridUnit) / defaultGridUnit;
+}
+
+QMirClientClientIntegration::~QMirClientClientIntegration()
+{
+ delete mInput;
+ delete mInputContext;
+ delete mScreen;
+ delete mServices;
+}
+
+QPlatformServices *QMirClientClientIntegration::services() const
+{
+ return mServices;
+}
+
+void QMirClientClientIntegration::setupOptions()
+{
+ QStringList args = QCoreApplication::arguments();
+ int argc = args.size() + 1;
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc - 1; i++)
+ argv[i] = qstrdup(args.at(i).toLocal8Bit());
+ argv[argc - 1] = nullptr;
+
+ mOptions = u_application_options_new_from_cmd_line(argc - 1, argv);
+
+ for (int i = 0; i < argc; i++)
+ delete [] argv[i];
+ delete [] argv;
+}
+
+void QMirClientClientIntegration::setupDescription()
+{
+ mDesc = u_application_description_new();
+ UApplicationId* id = u_application_id_new_from_stringn("QtUbuntu", 8);
+ u_application_description_set_application_id(mDesc, id);
+
+ UApplicationLifecycleDelegate* delegate = u_application_lifecycle_delegate_new();
+ u_application_lifecycle_delegate_set_application_resumed_cb(delegate, &resumedCallback);
+ u_application_lifecycle_delegate_set_application_about_to_stop_cb(delegate, &aboutToStopCallback);
+ u_application_lifecycle_delegate_set_context(delegate, this);
+ u_application_description_set_application_lifecycle_delegate(mDesc, delegate);
+}
+
+QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const
+{
+ return const_cast<QMirClientClientIntegration*>(this)->createPlatformWindow(window);
+}
+
+QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window)
+{
+ QPlatformWindow* platformWindow = new QMirClientWindow(
+ window, mClipboard, static_cast<QMirClientScreen*>(mScreen), mInput, u_application_instance_get_mir_connection(mInstance));
+ platformWindow->requestActivateWindow();
+ return platformWindow;
+}
+
+bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps:
+ return true;
+ break;
+
+ case OpenGL:
+ return true;
+ break;
+
+ case ThreadedOpenGL:
+ if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) {
+ return true;
+ } else {
+ DLOG("ubuntumirclient: disabled threaded OpenGL");
+ return false;
+ }
+ break;
+
+ default:
+ return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QAbstractEventDispatcher *QMirClientClientIntegration::createEventDispatcher() const
+{
+ return createUnixEventDispatcher();
+}
+
+QPlatformBackingStore* QMirClientClientIntegration::createPlatformBackingStore(QWindow* window) const
+{
+ return new QMirClientBackingStore(window);
+}
+
+QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
+ QOpenGLContext* context) const
+{
+ return const_cast<QMirClientClientIntegration*>(this)->createPlatformOpenGLContext(context);
+}
+
+QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
+ QOpenGLContext* context)
+{
+ return new QMirClientOpenGLContext(static_cast<QMirClientScreen*>(context->screen()->handle()),
+ static_cast<QMirClientOpenGLContext*>(context->shareHandle()));
+}
+
+QStringList QMirClientClientIntegration::themeNames() const
+{
+ return QStringList(QMirClientTheme::name);
+}
+
+QPlatformTheme* QMirClientClientIntegration::createPlatformTheme(const QString& name) const
+{
+ Q_UNUSED(name);
+ return new QMirClientTheme;
+}
+
+QVariant QMirClientClientIntegration::styleHint(StyleHint hint) const
+{
+ switch (hint) {
+ case QPlatformIntegration::StartDragDistance: {
+ // default is 10 pixels (see QPlatformTheme::defaultThemeHint)
+ return 10.0 * mScaleFactor;
+ }
+ case QPlatformIntegration::PasswordMaskDelay: {
+ // return time in milliseconds - 1 second
+ return QVariant(1000);
+ }
+ default:
+ break;
+ }
+ return QPlatformIntegration::styleHint(hint);
+}
+
+QPlatformClipboard* QMirClientClientIntegration::clipboard() const
+{
+ return mClipboard.data();
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h
new file mode 100644
index 0000000000..2960209691
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTINTEGRATION_H
+#define QMIRCLIENTINTEGRATION_H
+
+#include <qpa/qplatformintegration.h>
+#include <QSharedPointer>
+
+#include "qmirclientplatformservices.h"
+
+// platform-api
+#include <ubuntu/application/description.h>
+#include <ubuntu/application/instance.h>
+
+class QMirClientClipboard;
+class QMirClientInput;
+class QMirClientScreen;
+
+class QMirClientClientIntegration : public QPlatformIntegration {
+public:
+ QMirClientClientIntegration();
+ virtual ~QMirClientClientIntegration();
+
+ // QPlatformIntegration methods.
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ QPlatformNativeInterface* nativeInterface() const override { return mNativeInterface; }
+ QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override;
+ QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override;
+ QPlatformFontDatabase* fontDatabase() const override { return mFontDb; }
+ QStringList themeNames() const override;
+ QPlatformTheme* createPlatformTheme(const QString& name) const override;
+ QVariant styleHint(StyleHint hint) const override;
+ QPlatformServices *services() const override;
+ QPlatformWindow* createPlatformWindow(QWindow* window) const override;
+ QPlatformInputContext* inputContext() const override { return mInputContext; }
+ QPlatformClipboard* clipboard() const override;
+
+ QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context);
+ QPlatformWindow* createPlatformWindow(QWindow* window);
+ QMirClientScreen* screen() const { return mScreen; }
+
+private:
+ void setupOptions();
+ void setupDescription();
+
+ QPlatformNativeInterface* mNativeInterface;
+ QPlatformFontDatabase* mFontDb;
+
+ QMirClientPlatformServices* mServices;
+
+ QMirClientScreen* mScreen;
+ QMirClientInput* mInput;
+ QPlatformInputContext* mInputContext;
+ QSharedPointer<QMirClientClipboard> mClipboard;
+ qreal mScaleFactor;
+
+ // Platform API stuff
+ UApplicationOptions* mOptions;
+ UApplicationDescription* mDesc;
+ UApplicationInstance* mInstance;
+};
+
+#endif // QMIRCLIENTINTEGRATION_H
diff --git a/src/plugins/platforms/mirclient/qmirclientlogging.h b/src/plugins/platforms/mirclient/qmirclientlogging.h
new file mode 100644
index 0000000000..80914d28b9
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientlogging.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTLOGGING_H
+#define QMIRCLIENTLOGGING_H
+
+// Logging and assertion macros.
+#define LOG(...) qDebug(__VA_ARGS__)
+#define LOG_IF(cond,...) do { if (cond) qDebug(__VA_ARGS__); } while (0)
+#define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+#define NOT_REACHED() qt_assert("Not reached!",__FILE__,__LINE__)
+
+// Logging and assertion macros are compiled out for release builds.
+#if !defined(QT_NO_DEBUG)
+#define DLOG(...) LOG(__VA_ARGS__)
+#define DLOG_IF(cond,...) LOG_IF((cond), __VA_ARGS__)
+#define DASSERT(cond) ASSERT((cond))
+#define DNOT_REACHED() NOT_REACHED()
+#else
+#define DLOG(...) qt_noop()
+#define DLOG_IF(cond,...) qt_noop()
+#define DASSERT(cond) qt_noop()
+#define DNOT_REACHED() qt_noop()
+#endif
+
+#endif // QMIRCLIENTLOGGING_H
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
new file mode 100644
index 0000000000..a0bb932df3
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Qt
+#include <private/qguiapplication_p.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qscreen.h>
+#include <QtCore/QMap>
+
+// Local
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclientglcontext.h"
+
+class QMirClientResourceMap : public QMap<QByteArray, QMirClientNativeInterface::ResourceType>
+{
+public:
+ QMirClientResourceMap()
+ : QMap<QByteArray, QMirClientNativeInterface::ResourceType>() {
+ insert("egldisplay", QMirClientNativeInterface::EglDisplay);
+ insert("eglcontext", QMirClientNativeInterface::EglContext);
+ insert("nativeorientation", QMirClientNativeInterface::NativeOrientation);
+ insert("display", QMirClientNativeInterface::Display);
+ }
+};
+
+Q_GLOBAL_STATIC(QMirClientResourceMap, ubuntuResourceMap)
+
+QMirClientNativeInterface::QMirClientNativeInterface()
+ : mGenericEventFilterType(QByteArrayLiteral("Event"))
+ , mNativeOrientation(nullptr)
+{
+}
+
+QMirClientNativeInterface::~QMirClientNativeInterface()
+{
+ delete mNativeOrientation;
+ mNativeOrientation = nullptr;
+}
+
+void* QMirClientNativeInterface::nativeResourceForContext(
+ const QByteArray& resourceString, QOpenGLContext* context)
+{
+ if (!context)
+ return nullptr;
+
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return nullptr;
+
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+
+ if (kResourceType == QMirClientNativeInterface::EglContext)
+ return static_cast<QMirClientOpenGLContext*>(context->handle())->eglContext();
+ else
+ return nullptr;
+}
+
+void* QMirClientNativeInterface::nativeResourceForWindow(const QByteArray& resourceString, QWindow* window)
+{
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return NULL;
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+ if (kResourceType == QMirClientNativeInterface::EglDisplay) {
+ if (window) {
+ return static_cast<QMirClientScreen*>(window->screen()->handle())->eglDisplay();
+ } else {
+ return static_cast<QMirClientScreen*>(
+ QGuiApplication::primaryScreen()->handle())->eglDisplay();
+ }
+ } else if (kResourceType == QMirClientNativeInterface::NativeOrientation) {
+ // Return the device's native screen orientation.
+ if (window) {
+ QMirClientScreen *ubuntuScreen = static_cast<QMirClientScreen*>(window->screen()->handle());
+ mNativeOrientation = new Qt::ScreenOrientation(ubuntuScreen->nativeOrientation());
+ } else {
+ QPlatformScreen *platformScreen = QGuiApplication::primaryScreen()->handle();
+ mNativeOrientation = new Qt::ScreenOrientation(platformScreen->nativeOrientation());
+ }
+ return mNativeOrientation;
+ } else {
+ return NULL;
+ }
+}
+
+void* QMirClientNativeInterface::nativeResourceForScreen(const QByteArray& resourceString, QScreen* screen)
+{
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return NULL;
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+ if (kResourceType == QMirClientNativeInterface::Display) {
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ return static_cast<QMirClientScreen*>(screen->handle())->eglNativeDisplay();
+ } else
+ return NULL;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
new file mode 100644
index 0000000000..84f03bb915
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTNATIVEINTERFACE_H
+#define QMIRCLIENTNATIVEINTERFACE_H
+
+#include <qpa/qplatformnativeinterface.h>
+
+class QMirClientNativeInterface : public QPlatformNativeInterface {
+public:
+ enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display };
+
+ QMirClientNativeInterface();
+ ~QMirClientNativeInterface();
+
+ // QPlatformNativeInterface methods.
+ void* nativeResourceForContext(const QByteArray& resourceString,
+ QOpenGLContext* context) override;
+ void* nativeResourceForWindow(const QByteArray& resourceString,
+ QWindow* window) override;
+ void* nativeResourceForScreen(const QByteArray& resourceString,
+ QScreen* screen) override;
+
+ // New methods.
+ const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; }
+
+private:
+ const QByteArray mGenericEventFilterType;
+ Qt::ScreenOrientation* mNativeOrientation;
+};
+
+#endif // QMIRCLIENTNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
new file mode 100644
index 0000000000..24d7307faa
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+#define QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+
+#include <QEvent>
+#include "qmirclientlogging.h"
+
+class OrientationChangeEvent : public QEvent {
+public:
+ enum Orientation {
+ Undefined = 0,
+ TopUp,
+ TopDown,
+ LeftUp,
+ RightUp,
+ FaceUp,
+ FaceDown
+ };
+
+ OrientationChangeEvent(QEvent::Type type, Orientation orientation)
+ : QEvent(type)
+ , mOrientation(orientation)
+ {
+ }
+
+ static const QEvent::Type mType;
+ Orientation mOrientation;
+};
+
+#endif // QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp b/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
new file mode 100644
index 0000000000..d0260c79d3
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientplatformservices.h"
+
+#include <QUrl>
+
+#include <ubuntu/application/url_dispatcher/service.h>
+#include <ubuntu/application/url_dispatcher/session.h>
+
+bool QMirClientPlatformServices::openUrl(const QUrl &url)
+{
+ return callDispatcher(url);
+}
+
+bool QMirClientPlatformServices::openDocument(const QUrl &url)
+{
+ return callDispatcher(url);
+}
+
+bool QMirClientPlatformServices::callDispatcher(const QUrl &url)
+{
+ UAUrlDispatcherSession* session = ua_url_dispatcher_session();
+ if (!session)
+ return false;
+
+ ua_url_dispatcher_session_open(session, url.toEncoded().constData(), NULL, NULL);
+
+ free(session);
+
+ // We are returning true here because the other option
+ // is spawning a nested event loop and wait for the
+ // callback. But there is no guarantee on how fast
+ // the callback is going to be so we prefer to avoid the
+ // nested event loop. Long term plan is improve Qt API
+ // to support an async openUrl
+ return true;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.h b/src/plugins/platforms/mirclient/qmirclientplatformservices.h
new file mode 100644
index 0000000000..64a0432d06
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplatformservices.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTPLATFORMSERVICES_H
+#define QMIRCLIENTPLATFORMSERVICES_H
+
+#include <qpa/qplatformservices.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+
+class QMirClientPlatformServices : public QPlatformServices {
+public:
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
+
+private:
+ bool callDispatcher(const QUrl &url);
+};
+
+#endif // QMIRCLIENTPLATFORMSERVICES_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
new file mode 100644
index 0000000000..203a1cbfd8
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientplugin.h"
+#include "qmirclientintegration.h"
+
+QStringList QMirClientIntegrationPlugin::keys() const
+{
+ QStringList list;
+ list << "mirclient";
+ return list;
+}
+
+QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system,
+ const QStringList &)
+{
+ if (system.toLower() == "mirclient") {
+ return new QMirClientClientIntegration;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.h b/src/plugins/platforms/mirclient/qmirclientplugin.h
new file mode 100644
index 0000000000..a6f1a1081a
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplugin.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTPLUGIN_H
+#define QMIRCLIENTPLUGIN_H
+
+#include <qpa/qplatformintegrationplugin.h>
+
+class QMirClientIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirclient.json")
+
+public:
+ QStringList keys() const;
+ QPlatformIntegration* create(const QString&, const QStringList&);
+};
+
+#endif // QMIRCLIENTPLUGIN_H
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
new file mode 100644
index 0000000000..5c4b1cd0d6
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <mir_toolkit/mir_client_library.h>
+
+// Qt
+#include <QCoreApplication>
+#include <QtCore/qmath.h>
+#include <QScreen>
+#include <QThread>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+
+// local
+#include "qmirclientscreen.h"
+#include "qmirclientlogging.h"
+#include "qmirclientorientationchangeevent_p.h"
+
+#include "memory"
+
+static const int kSwapInterval = 1;
+
+#if !defined(QT_NO_DEBUG)
+
+static const char *orientationToStr(Qt::ScreenOrientation orientation) {
+ switch (orientation) {
+ case Qt::PrimaryOrientation:
+ return "primary";
+ case Qt::PortraitOrientation:
+ return "portrait";
+ case Qt::LandscapeOrientation:
+ return "landscape";
+ case Qt::InvertedPortraitOrientation:
+ return "inverted portrait";
+ case Qt::InvertedLandscapeOrientation:
+ return "inverted landscape";
+ default:
+ return "INVALID!";
+ }
+}
+
+static void printEglConfig(EGLDisplay display, EGLConfig config) {
+ DASSERT(display != EGL_NO_DISPLAY);
+ DASSERT(config != nullptr);
+ static const struct { const EGLint attrib; const char* name; } kAttribs[] = {
+ { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" },
+ { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" },
+ { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" },
+ { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" },
+ { EGL_RED_SIZE, "EGL_RED_SIZE" },
+ { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" },
+ { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" },
+ { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" },
+ { EGL_CONFIG_ID, "EGL_CONFIG_ID" },
+ { EGL_LEVEL, "EGL_LEVEL" },
+ { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" },
+ { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" },
+ { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" },
+ { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" },
+ { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" },
+ { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" },
+ { EGL_SAMPLES, "EGL_SAMPLES" },
+ { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" },
+ { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" },
+ { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" },
+ { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" },
+ { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" },
+ { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" },
+ { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" },
+ { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" },
+ { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" },
+ { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" },
+ { -1, NULL }
+ };
+ const char* string = eglQueryString(display, EGL_VENDOR);
+ LOG("EGL vendor: %s", string);
+ string = eglQueryString(display, EGL_VERSION);
+ LOG("EGL version: %s", string);
+ string = eglQueryString(display, EGL_EXTENSIONS);
+ LOG("EGL extensions: %s", string);
+ LOG("EGL configuration attibutes:");
+ for (int index = 0; kAttribs[index].attrib != -1; index++) {
+ EGLint value;
+ if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value))
+ LOG(" %s: %d", kAttribs[index].name, static_cast<int>(value));
+ }
+}
+#endif
+
+
+const QEvent::Type OrientationChangeEvent::mType =
+ static_cast<QEvent::Type>(QEvent::registerEventType());
+
+static const MirDisplayOutput *find_active_output(
+ const MirDisplayConfiguration *conf)
+{
+ const MirDisplayOutput *output = NULL;
+ for (uint32_t d = 0; d < conf->num_outputs; d++)
+ {
+ const MirDisplayOutput *out = conf->outputs + d;
+
+ if (out->used &&
+ out->connected &&
+ out->num_modes &&
+ out->current_mode < out->num_modes)
+ {
+ output = out;
+ break;
+ }
+ }
+
+ return output;
+}
+
+QMirClientScreen::QMirClientScreen(MirConnection *connection)
+ : mFormat(QImage::Format_RGB32)
+ , mDepth(32)
+ , mSurfaceFormat()
+ , mEglDisplay(EGL_NO_DISPLAY)
+ , mEglConfig(nullptr)
+{
+ // Initialize EGL.
+ ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE);
+
+ mEglNativeDisplay = mir_connection_get_egl_native_display(connection);
+ ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
+ ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
+
+ // Configure EGL buffers format.
+ mSurfaceFormat.setRedBufferSize(8);
+ mSurfaceFormat.setGreenBufferSize(8);
+ mSurfaceFormat.setBlueBufferSize(8);
+ mSurfaceFormat.setAlphaBufferSize(8);
+ mSurfaceFormat.setDepthBufferSize(24);
+ mSurfaceFormat.setStencilBufferSize(8);
+ if (!qEnvironmentVariableIsEmpty("QTUBUNTU_MULTISAMPLE")) {
+ mSurfaceFormat.setSamples(4);
+ DLOG("ubuntumirclient: setting MSAA to 4 samples");
+ }
+#ifdef QTUBUNTU_USE_OPENGL
+ mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+#else
+ mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+#endif
+ mEglConfig = q_configFromGLFormat(mEglDisplay, mSurfaceFormat, true);
+
+ #if !defined(QT_NO_DEBUG)
+ printEglConfig(mEglDisplay, mEglConfig);
+ #endif
+
+ // Set vblank swap interval.
+ int swapInterval = kSwapInterval;
+ QByteArray swapIntervalString = qgetenv("QTUBUNTU_SWAPINTERVAL");
+ if (!swapIntervalString.isEmpty()) {
+ bool ok;
+ swapInterval = swapIntervalString.toInt(&ok);
+ if (!ok)
+ swapInterval = kSwapInterval;
+ }
+ DLOG("ubuntumirclient: setting swap interval to %d", swapInterval);
+ eglSwapInterval(mEglDisplay, swapInterval);
+
+ // Get screen resolution.
+ auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };
+ using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;
+ configUp displayConfig(mir_connection_create_display_config(connection), configDeleter);
+ ASSERT(displayConfig != nullptr);
+
+ auto const displayOutput = find_active_output(displayConfig.get());
+ ASSERT(displayOutput != nullptr);
+
+ const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode];
+ const int kScreenWidth = mode->horizontal_resolution;
+ const int kScreenHeight = mode->vertical_resolution;
+ DASSERT(kScreenWidth > 0 && kScreenHeight > 0);
+
+ DLOG("ubuntumirclient: screen resolution: %dx%d", kScreenWidth, kScreenHeight);
+
+ mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight);
+
+ DLOG("QQMirClientScreen::QQMirClientScreen (this=%p)", this);
+
+ // Set the default orientation based on the initial screen dimmensions.
+ mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
+
+ // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait
+ mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
+}
+
+QMirClientScreen::~QMirClientScreen()
+{
+ eglTerminate(mEglDisplay);
+}
+
+void QMirClientScreen::customEvent(QEvent* event) {
+ DASSERT(QThread::currentThread() == thread());
+
+ OrientationChangeEvent* oReadingEvent = static_cast<OrientationChangeEvent*>(event);
+ switch (oReadingEvent->mOrientation) {
+ case OrientationChangeEvent::LeftUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::InvertedPortraitOrientation : Qt::LandscapeOrientation;
+ break;
+ }
+ case OrientationChangeEvent::TopUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::LandscapeOrientation : Qt::PortraitOrientation;
+ break;
+ }
+ case OrientationChangeEvent::RightUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::PortraitOrientation : Qt::InvertedLandscapeOrientation;
+ break;
+ }
+ case OrientationChangeEvent::TopDown: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::InvertedLandscapeOrientation : Qt::InvertedPortraitOrientation;
+ break;
+ }
+ default: {
+ DLOG("QMirClientScreen::customEvent - Unknown orientation.");
+ return;
+ }
+ }
+
+ // Raise the event signal so that client apps know the orientation changed
+ DLOG("QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation));
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
+}
+
+void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeight)
+{
+ if ((windowWidth > windowHeight && mGeometry.width() < mGeometry.height())
+ || (windowWidth < windowHeight && mGeometry.width() > mGeometry.height())) {
+
+ // The window aspect ratio differ's from the screen one. This means that
+ // unity8 has rotated the window in its scene.
+ // As there's no way to express window rotation in Qt's API, we have
+ // Flip QScreen's dimensions so that orientation properties match
+ // (primaryOrientation particularly).
+ // FIXME: This assumes a phone scenario. Won't work, or make sense,
+ // on the desktop
+
+ QRect currGeometry = mGeometry;
+ mGeometry.setWidth(currGeometry.height());
+ mGeometry.setHeight(currGeometry.width());
+
+ DLOG("QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)",
+ mGeometry.width(), mGeometry.height());
+ QWindowSystemInterface::handleScreenGeometryChange(screen(),
+ mGeometry /* newGeometry */,
+ mGeometry /* newAvailableGeometry */);
+
+ if (mGeometry.width() < mGeometry.height()) {
+ mCurrentOrientation = Qt::PortraitOrientation;
+ } else {
+ mCurrentOrientation = Qt::LandscapeOrientation;
+ }
+ DLOG("QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation));
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h
new file mode 100644
index 0000000000..5d9325354f
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTSCREEN_H
+#define QMIRCLIENTSCREEN_H
+
+#include <qpa/qplatformscreen.h>
+#include <QSurfaceFormat>
+#include <EGL/egl.h>
+
+struct MirConnection;
+
+class QMirClientScreen : public QObject, public QPlatformScreen
+{
+ Q_OBJECT
+public:
+ QMirClientScreen(MirConnection *connection);
+ virtual ~QMirClientScreen();
+
+ // QPlatformScreen methods.
+ QImage::Format format() const override { return mFormat; }
+ int depth() const override { return mDepth; }
+ QRect geometry() const override { return mGeometry; }
+ QRect availableGeometry() const override { return mGeometry; }
+ Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
+ Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
+
+ // New methods.
+ QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; }
+ EGLDisplay eglDisplay() const { return mEglDisplay; }
+ EGLConfig eglConfig() const { return mEglConfig; }
+ EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
+ void handleWindowSurfaceResize(int width, int height);
+
+ // QObject methods.
+ void customEvent(QEvent* event);
+
+private:
+ QRect mGeometry;
+ Qt::ScreenOrientation mNativeOrientation;
+ Qt::ScreenOrientation mCurrentOrientation;
+ QImage::Format mFormat;
+ int mDepth;
+ QSurfaceFormat mSurfaceFormat;
+ EGLDisplay mEglDisplay;
+ EGLConfig mEglConfig;
+ EGLNativeDisplayType mEglNativeDisplay;
+};
+
+#endif // QMIRCLIENTSCREEN_H
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.cpp b/src/plugins/platforms/mirclient/qmirclienttheme.cpp
new file mode 100644
index 0000000000..c15da23945
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclienttheme.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclienttheme.h"
+
+#include <QtCore/QVariant>
+
+const char *QMirClientTheme::name = "ubuntu";
+
+QMirClientTheme::QMirClientTheme()
+{
+}
+
+QMirClientTheme::~QMirClientTheme()
+{
+}
+
+QVariant QMirClientTheme::themeHint(ThemeHint hint) const
+{
+ if (hint == QPlatformTheme::SystemIconThemeName) {
+ QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
+ if (iconTheme.isEmpty()) {
+ return QVariant(QStringLiteral("ubuntu-mobile"));
+ } else {
+ return QVariant(QString(iconTheme));
+ }
+ } else {
+ return QGenericUnixTheme::themeHint(hint);
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.h b/src/plugins/platforms/mirclient/qmirclienttheme.h
new file mode 100644
index 0000000000..8f330395a0
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclienttheme.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTTHEME_H
+#define QMIRCLIENTTHEME_H
+
+#include <QtPlatformSupport/private/qgenericunixthemes_p.h>
+
+class QMirClientTheme : public QGenericUnixTheme
+{
+public:
+ static const char* name;
+ QMirClientTheme();
+ virtual ~QMirClientTheme();
+
+ // From QPlatformTheme
+ QVariant themeHint(ThemeHint hint) const override;
+};
+
+#endif // QMIRCLIENTTHEME_H
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
new file mode 100644
index 0000000000..3d1e5377e5
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
@@ -0,0 +1,454 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Local
+#include "qmirclientclipboard.h"
+#include "qmirclientinput.h"
+#include "qmirclientwindow.h"
+#include "qmirclientscreen.h"
+#include "qmirclientlogging.h"
+
+// Qt
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QSize>
+#include <QtMath>
+
+// Platform API
+#include <ubuntu/application/instance.h>
+
+#include <EGL/egl.h>
+
+#define IS_OPAQUE_FLAG 1
+
+namespace
+{
+MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
+{
+ switch (state) {
+ case Qt::WindowNoState:
+ return mir_surface_state_restored;
+
+ case Qt::WindowFullScreen:
+ return mir_surface_state_fullscreen;
+
+ case Qt::WindowMaximized:
+ return mir_surface_state_maximized;
+
+ case Qt::WindowMinimized:
+ return mir_surface_state_minimized;
+
+ default:
+ LOG("Unexpected Qt::WindowState: %d", state);
+ return mir_surface_state_restored;
+ }
+}
+
+#if !defined(QT_NO_DEBUG)
+const char *qtWindowStateToStr(Qt::WindowState state)
+{
+ switch (state) {
+ case Qt::WindowNoState:
+ return "NoState";
+
+ case Qt::WindowFullScreen:
+ return "FullScreen";
+
+ case Qt::WindowMaximized:
+ return "Maximized";
+
+ case Qt::WindowMinimized:
+ return "Minimized";
+
+ default:
+ return "!?";
+ }
+}
+#endif
+
+} // anonymous namespace
+
+class QMirClientWindowPrivate
+{
+public:
+ void createEGLSurface(EGLNativeWindowType nativeWindow);
+ void destroyEGLSurface();
+ int panelHeight();
+
+ QMirClientScreen* screen;
+ EGLSurface eglSurface;
+ WId id;
+ QMirClientInput* input;
+ Qt::WindowState state;
+ MirConnection *connection;
+ MirSurface* surface;
+ QSize bufferSize;
+ QMutex mutex;
+ QSharedPointer<QMirClientClipboard> clipboard;
+};
+
+static void eventCallback(MirSurface* surface, const MirEvent *event, void* context)
+{
+ (void) surface;
+ DASSERT(context != NULL);
+ QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
+ platformWindow->priv()->input->postEvent(platformWindow, event);
+}
+
+static void surfaceCreateCallback(MirSurface* surface, void* context)
+{
+ DASSERT(context != NULL);
+ QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
+ platformWindow->priv()->surface = surface;
+
+ mir_surface_set_event_handler(surface, eventCallback, context);
+}
+
+QMirClientWindow::QMirClientWindow(QWindow* w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen* screen,
+ QMirClientInput* input, MirConnection* connection)
+ : QObject(nullptr), QPlatformWindow(w)
+{
+ DASSERT(screen != NULL);
+
+ d = new QMirClientWindowPrivate;
+ d->screen = screen;
+ d->eglSurface = EGL_NO_SURFACE;
+ d->input = input;
+ d->state = window()->windowState();
+ d->connection = connection;
+ d->clipboard = clipboard;
+
+ static int id = 1;
+ d->id = id++;
+
+ // Use client geometry if set explicitly, use available screen geometry otherwise.
+ QPlatformWindow::setGeometry(window()->geometry().isValid() && window()->geometry() != screen->geometry() ?
+ window()->geometry() : screen->availableGeometry());
+ createWindow();
+ DLOG("QMirClientWindow::QMirClientWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input);
+}
+
+QMirClientWindow::~QMirClientWindow()
+{
+ DLOG("QMirClientWindow::~QMirClientWindow");
+ d->destroyEGLSurface();
+
+ mir_surface_release_sync(d->surface);
+
+ delete d;
+}
+
+void QMirClientWindowPrivate::createEGLSurface(EGLNativeWindowType nativeWindow)
+{
+ DLOG("QMirClientWindowPrivate::createEGLSurface (this=%p, nativeWindow=%p)",
+ this, reinterpret_cast<void*>(nativeWindow));
+
+ eglSurface = eglCreateWindowSurface(screen->eglDisplay(), screen->eglConfig(),
+ nativeWindow, nullptr);
+
+ DASSERT(eglSurface != EGL_NO_SURFACE);
+}
+
+void QMirClientWindowPrivate::destroyEGLSurface()
+{
+ DLOG("QMirClientWindowPrivate::destroyEGLSurface (this=%p)", this);
+ if (eglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(screen->eglDisplay(), eglSurface);
+ eglSurface = EGL_NO_SURFACE;
+ }
+}
+
+// FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
+// we need to guess the panel height (3GU + 2DP)
+int QMirClientWindowPrivate::panelHeight()
+{
+ if (qEnvironmentVariableIsSet("QT_MIRCLIENT_IGNORE_PANEL"))
+ return 0;
+ const int defaultGridUnit = 8;
+ int gridUnit = defaultGridUnit;
+ QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
+ if (!gridUnitString.isEmpty()) {
+ bool ok;
+ gridUnit = gridUnitString.toInt(&ok);
+ if (!ok) {
+ gridUnit = defaultGridUnit;
+ }
+ }
+ qreal densityPixelRatio = static_cast<qreal>(gridUnit) / defaultGridUnit;
+ return gridUnit * 3 + qFloor(densityPixelRatio) * 2;
+}
+
+namespace
+{
+static MirPixelFormat
+mir_choose_default_pixel_format(MirConnection *connection)
+{
+ MirPixelFormat format[mir_pixel_formats];
+ unsigned int nformats;
+
+ mir_connection_get_available_surface_formats(connection,
+ format, mir_pixel_formats, &nformats);
+
+ return format[0];
+}
+}
+
+void QMirClientWindow::createWindow()
+{
+ DLOG("QMirClientWindow::createWindow (this=%p)", this);
+
+ // FIXME: remove this remnant of an old platform-api enum - needs ubuntu-keyboard update
+ const int SCREEN_KEYBOARD_ROLE = 7;
+ // Get surface role and flags.
+ QVariant roleVariant = window()->property("role");
+ int role = roleVariant.isValid() ? roleVariant.toUInt() : 1; // 1 is the default role for apps.
+ QVariant opaqueVariant = window()->property("opaque");
+ uint flags = opaqueVariant.isValid() ?
+ opaqueVariant.toUInt() ? static_cast<uint>(IS_OPAQUE_FLAG) : 0 : 0;
+
+ // FIXME(loicm) Opaque flag is forced for now for non-system sessions (applications) for
+ // performance reasons.
+ flags |= static_cast<uint>(IS_OPAQUE_FLAG);
+
+ const QByteArray title = (!window()->title().isNull()) ? window()->title().toUtf8() : "Window 1"; // legacy title
+ const int panelHeight = d->panelHeight();
+
+#if !defined(QT_NO_DEBUG)
+ LOG("panelHeight: '%d'", panelHeight);
+ LOG("role: '%d'", role);
+ LOG("flags: '%s'", (flags & static_cast<uint>(1)) ? "Opaque" : "NotOpaque");
+ LOG("title: '%s'", title.constData());
+#endif
+
+ // Get surface geometry.
+ QRect geometry;
+ if (d->state == Qt::WindowFullScreen) {
+ printf("QMirClientWindow - fullscreen geometry\n");
+ geometry = screen()->geometry();
+ } else if (d->state == Qt::WindowMaximized) {
+ printf("QMirClientWindow - maximized geometry\n");
+ geometry = screen()->availableGeometry();
+ /*
+ * FIXME: Autopilot relies on being able to convert coordinates relative of the window
+ * into absolute screen coordinates. Mir does not allow this, see bug lp:1346633
+ * Until there's a correct way to perform this transformation agreed, this horrible hack
+ * guesses the transformation heuristically.
+ *
+ * Assumption: this method only used on phone devices!
+ */
+ geometry.setY(panelHeight);
+ } else {
+ printf("QMirClientWindow - regular geometry\n");
+ geometry = this->geometry();
+ geometry.setY(panelHeight);
+ }
+
+ DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with size (%d, %d) with title '%s'\n",
+ geometry.x(), geometry.y(), geometry.width(), geometry.height(), title.data());
+
+ MirSurfaceSpec *spec;
+ if (role == SCREEN_KEYBOARD_ROLE)
+ {
+ spec = mir_connection_create_spec_for_input_method(d->connection, geometry.width(),
+ geometry.height(), mir_choose_default_pixel_format(d->connection));
+ }
+ else
+ {
+ spec = mir_connection_create_spec_for_normal_surface(d->connection, geometry.width(),
+ geometry.height(), mir_choose_default_pixel_format(d->connection));
+ }
+ mir_surface_spec_set_name(spec, title.data());
+
+ // Create platform window
+ mir_wait_for(mir_surface_create(spec, surfaceCreateCallback, this));
+ mir_surface_spec_release(spec);
+
+ DASSERT(d->surface != NULL);
+ d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface)));
+
+ if (d->state == Qt::WindowFullScreen) {
+ // TODO: We could set this on creation once surface spec supports it (mps already up)
+ mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_fullscreen));
+ }
+
+ // Window manager can give us a final size different from what we asked for
+ // so let's check what we ended up getting
+ {
+ MirSurfaceParameters parameters;
+ mir_surface_get_parameters(d->surface, &parameters);
+
+ geometry.setWidth(parameters.width);
+ geometry.setHeight(parameters.height);
+ }
+
+ DLOG("[ubuntumirclient QPA] created surface has size (%d, %d)",
+ geometry.width(), geometry.height());
+
+ // Assume that the buffer size matches the surface size at creation time
+ d->bufferSize = geometry.size();
+
+ // Tell Qt about the geometry.
+ QWindowSystemInterface::handleGeometryChange(window(), geometry);
+ QPlatformWindow::setGeometry(geometry);
+}
+
+void QMirClientWindow::moveResize(const QRect& rect)
+{
+ (void) rect;
+ // TODO: Not yet supported by mir.
+}
+
+void QMirClientWindow::handleSurfaceResize(int width, int height)
+{
+ QMutexLocker(&d->mutex);
+ LOG("QMirClientWindow::handleSurfaceResize(width=%d, height=%d)", width, height);
+
+ // The current buffer size hasn't actually changed. so just render on it and swap
+ // buffers in the hope that the next buffer will match the surface size advertised
+ // in this event.
+ // But since this event is processed by a thread different from the one that swaps
+ // buffers, you can never know if this information is already outdated as there's
+ // no synchronicity whatsoever between the processing of resize events and the
+ // consumption of buffers.
+ if (d->bufferSize.width() != width || d->bufferSize.height() != height) {
+ QWindowSystemInterface::handleExposeEvent(window(), geometry());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+}
+
+void QMirClientWindow::handleSurfaceFocusChange(bool focused)
+{
+ LOG("QMirClientWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false");
+ QWindow *activatedWindow = focused ? window() : nullptr;
+
+ // System clipboard contents might have changed while this window was unfocused and wihtout
+ // this process getting notified about it because it might have been suspended (due to
+ // application lifecycle policies), thus unable to listen to any changes notified through
+ // D-Bus.
+ // Therefore let's ensure we are up to date with the system clipboard now that we are getting
+ // focused again.
+ if (focused) {
+ d->clipboard->requestDBusClipboardContents();
+ }
+
+ QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason);
+}
+
+void QMirClientWindow::setWindowState(Qt::WindowState state)
+{
+ QMutexLocker(&d->mutex);
+ DLOG("QMirClientWindow::setWindowState (this=%p, %s)", this, qtWindowStateToStr(state));
+
+ if (state == d->state)
+ return;
+
+ // TODO: Perhaps we should check if the states are applied?
+ mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(state)));
+ d->state = state;
+}
+
+void QMirClientWindow::setGeometry(const QRect& rect)
+{
+ DLOG("QMirClientWindow::setGeometry (this=%p)", this);
+
+ bool doMoveResize;
+
+ {
+ QMutexLocker(&d->mutex);
+ QPlatformWindow::setGeometry(rect);
+ doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized;
+ }
+
+ if (doMoveResize) {
+ moveResize(rect);
+ }
+}
+
+void QMirClientWindow::setVisible(bool visible)
+{
+ QMutexLocker(&d->mutex);
+ DLOG("QMirClientWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false");
+
+ if (visible) {
+ mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(d->state)));
+
+ QWindowSystemInterface::handleExposeEvent(window(), QRect());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ } else {
+ // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
+ // Will have to change qtmir and unity8 for that.
+ mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_minimized));
+ }
+}
+
+void* QMirClientWindow::eglSurface() const
+{
+ return d->eglSurface;
+}
+
+WId QMirClientWindow::winId() const
+{
+ return d->id;
+}
+
+void QMirClientWindow::onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight)
+{
+ QMutexLocker(&d->mutex);
+
+ bool sizeKnown = newBufferWidth > 0 && newBufferHeight > 0;
+
+ if (sizeKnown && (d->bufferSize.width() != newBufferWidth ||
+ d->bufferSize.height() != newBufferHeight)) {
+
+ DLOG("QMirClientWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)",
+ d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight);
+
+ d->bufferSize.rwidth() = newBufferWidth;
+ d->bufferSize.rheight() = newBufferHeight;
+
+ QRect newGeometry;
+
+ newGeometry = geometry();
+ newGeometry.setWidth(d->bufferSize.width());
+ newGeometry.setHeight(d->bufferSize.height());
+
+ QPlatformWindow::setGeometry(newGeometry);
+ QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect());
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h
new file mode 100644
index 0000000000..f342669544
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTWINDOW_H
+#define QMIRCLIENTWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+#include <QSharedPointer>
+
+#include <mir_toolkit/mir_client_library.h>
+
+class QMirClientClipboard;
+class QMirClientInput;
+class QMirClientScreen;
+class QMirClientWindowPrivate;
+
+class QMirClientWindow : public QObject, public QPlatformWindow
+{
+ Q_OBJECT
+public:
+ QMirClientWindow(QWindow *w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen *screen,
+ QMirClientInput *input, MirConnection *mir_connection);
+ virtual ~QMirClientWindow();
+
+ // QPlatformWindow methods.
+ WId winId() const override;
+ void setGeometry(const QRect&) override;
+ void setWindowState(Qt::WindowState state) override;
+ void setVisible(bool visible) override;
+
+ // New methods.
+ void* eglSurface() const;
+ void handleSurfaceResize(int width, int height);
+ void handleSurfaceFocusChange(bool focused);
+ void onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight);
+
+ QMirClientWindowPrivate* priv() { return d; }
+
+private:
+ void createWindow();
+ void moveResize(const QRect& rect);
+
+ QMirClientWindowPrivate *d;
+};
+
+#endif // QMIRCLIENTWINDOW_H
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 22d443733e..43bb04e318 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -40,3 +40,5 @@ contains(QT_CONFIG, linuxfb): SUBDIRS += linuxfb
haiku {
SUBDIRS += haiku
}
+
+contains(QT_CONFIG, mirclient): SUBDIRS += mirclient
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
index e5c853dad8..04e264860e 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
@@ -124,4 +124,25 @@ void QQnxAbstractVirtualKeyboard::setLocale(const QLocale &locale)
emit localeChanged(locale);
}
+QQnxAbstractVirtualKeyboard::EnterKeyType
+ QQnxAbstractVirtualKeyboard::qtEnterKeyTypeToQnx(Qt::EnterKeyType type)
+{
+ switch (type) {
+ case Qt::EnterKeyDone:
+ return Done;
+ case Qt::EnterKeyGo:
+ return Go;
+ case Qt::EnterKeyNext:
+ return Next;
+ case Qt::EnterKeySearch:
+ return Search;
+ case Qt::EnterKeySend:
+ return Send;
+ case Qt::EnterKeyDefault:
+ case Qt::EnterKeyReturn:
+ case Qt::EnterKeyPrevious: // unsupported
+ return DefaultReturn;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
index 8bf8313000..2fa2ed7291 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
@@ -74,6 +74,8 @@ public:
KeyboardMode keyboardMode() const { return m_keyboardMode; }
EnterKeyType enterKeyType() const { return m_enterKeyType; }
+ static EnterKeyType qtEnterKeyTypeToQnx(Qt::EnterKeyType type);
+
Q_SIGNALS:
void heightChanged(int height);
void visibilityChanged(bool visible);
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
index 3506de4bc0..ed0db82685 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
@@ -1384,13 +1384,17 @@ void QQnxInputContext::setFocusObject(QObject *object)
if (hasSession())
dispatchFocusLossEvent();
} else {
- QInputMethodQueryEvent query(Qt::ImHints);
+ QInputMethodQueryEvent query(Qt::ImHints | Qt::ImEnterKeyType);
QCoreApplication::sendEvent(object, &query);
int inputHints = query.value(Qt::ImHints).toInt();
+ Qt::EnterKeyType qtEnterKeyType = Qt::EnterKeyType(query.value(Qt::ImEnterKeyType).toInt());
dispatchFocusGainEvent(inputHints);
m_virtualKeyboard.setInputHints(inputHints);
+ m_virtualKeyboard.setEnterKeyType(
+ QQnxAbstractVirtualKeyboard::qtEnterKeyTypeToQnx(qtEnterKeyType)
+ );
if (!m_inputPanelVisible)
showInputPanel();
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
index 91ecffa2aa..3860cdf0db 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
@@ -172,11 +172,15 @@ void QQnxInputContext::setFocusObject(QObject *object)
if (m_inputPanelVisible)
hideInputPanel();
} else {
- QInputMethodQueryEvent query(Qt::ImHints);
+ QInputMethodQueryEvent query(Qt::ImHints | Qt::ImEnterKeyType);
QCoreApplication::sendEvent(object, &query);
int inputHints = query.value(Qt::ImHints).toInt();
+ Qt::EnterKeyType qtEnterKeyType = Qt::EnterKeyType(query.value(Qt::ImEnterKeyType).toInt());
m_virtualKeyboard.setInputHints(inputHints);
+ m_virtualKeyboard.setEnterKeyType(
+ QQnxAbstractVirtualKeyboard::qtEnterKeyTypeToQnx(qtEnterKeyType)
+ );
if (!m_inputPanelVisible)
showInputPanel();
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index 071bab7920..1c825dbbdd 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -95,7 +95,6 @@
#include <private/qsimpledrag_p.h>
#include <QtCore/QDebug>
-#include <QtCore/QHash>
#include <errno.h>
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
index 392d45c5b4..2c7a28e835 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
@@ -121,7 +121,7 @@ bool QQnxVirtualKeyboardPps::connect()
if (m_fd == -1)
{
qVirtualKeyboardDebug() << Q_FUNC_INFO << ": Unable to open" << ms_PPSPath
- << ":" << strerror(errno);
+ << ':' << strerror(errno);
close();
return false;
}
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index 23607523bd..1e003e2d15 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -4,7 +4,7 @@
"entries": [
{
"id": 1,
- "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263, QTBUG-42240)",
+ "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263)",
"vendor_id": "0x8086",
"device_id": [ "0x0A16" ],
"os": {
@@ -17,6 +17,55 @@
"features": [
"disable_desktopgl"
]
+ },
+ {
+ "id": 2,
+ "description": "Intel Q965/Q963 - GMA 3000 has insufficient support of opengl and directx",
+ "vendor_id": "0x8086",
+ "device_id": [ "0x2992" ],
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_desktopgl",
+ "disable_angle"
+ ]
+ },
+ {
+ "id": 3,
+ "description": "No OpenGL on Intel G33/G31 (QTBUG-47522)",
+ "vendor_id": "0x8086",
+ "device_id": [ "0x29C2" ],
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_desktopgl"
+ ]
+ },
+ {
+ "id": 4,
+ "description": "Intel HD Graphics 3000 crashes when initializing the OpenGL driver (QTBUG-42240)",
+ "vendor_id": "0x8086",
+ "device_id": [ "0x0102", "0x0106", "0x010A", "0x0112", "0x0116", "0x0122", "0x0126" ],
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_desktopgl"
+ ]
+ },
+ {
+ "id": 5,
+ "description": "Intel GMA 3150 (QTBUG-43243), Mobile Intel 945GM (QTBUG-47435) crash",
+ "vendor_id": "0x8086",
+ "device_id": [ "0xA001", "0xA011", "0x27A0" ],
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_desktopgl", "disable_angle"
+ ]
}
]
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 16c278d9df..bd5c35037d 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -35,10 +35,10 @@
#include "qwindowswindow.h"
#include "qwindowsnativeimage.h"
#include "qwindowscontext.h"
-#include "qwindowsscaling.h"
#include <QtGui/QWindow>
#include <QtGui/QPainter>
+#include <private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
@@ -68,10 +68,12 @@ QPaintDevice *QWindowsBackingStore::paintDevice()
return &m_image->image();
}
-void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoint &offset)
+void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
+ const QPoint &offset)
{
Q_ASSERT(window);
+ const QRect br = region.boundingRect();
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << offset << br;
QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window);
@@ -81,9 +83,9 @@ void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoin
const Qt::WindowFlags flags = window->flags();
if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) {
// Windows with alpha: Use blend function to update.
- const QMargins marginsDP = rw->frameMarginsDp();
- const QRect r = rw->geometryDp() + marginsDP;
- const QPoint frameOffset(marginsDP.left(), marginsDP.top());
+ QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window);
+ QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()),
+ static_cast<const QWindow *>(Q_NULLPTR)));
QRect dirtyRect = br.translated(offset + frameOffset);
SIZE size = {r.width(), r.height()};
@@ -127,15 +129,14 @@ void QWindowsBackingStore::flushDp(QWindow *window, const QRect &br, const QPoin
}
}
-void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion &regionDip)
+void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
{
- const QSize size = sizeDip * QWindowsScaling::factor();
if (m_image.isNull() || m_image->image().size() != size) {
#ifndef QT_NO_DEBUG_OUTPUT
if (QWindowsContext::verbose && lcQpaBackingStore().isDebugEnabled()) {
qCDebug(lcQpaBackingStore)
- << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << sizeDip << ' '
- << regionDip << " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
+ << __FUNCTION__ << ' ' << window() << ' ' << size << ' ' << region
+ << " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
}
#endif
const QImage::Format format = window()->format().hasAlpha() ?
@@ -144,10 +145,10 @@ void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion &regionDip
QWindowsNativeImage *oldwni = m_image.data();
QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
- if (oldwni && !regionDip.isEmpty()) {
+ if (oldwni && !region.isEmpty()) {
const QImage &oldimg(oldwni->image());
QImage &newimg(newwni->image());
- QRegion staticRegion = QWindowsScaling::mapToNative(regionDip);
+ QRegion staticRegion(region);
staticRegion &= QRect(0, 0, oldimg.width(), oldimg.height());
staticRegion &= QRect(0, 0, newimg.width(), newimg.height());
QPainter painter(&newimg);
@@ -156,38 +157,36 @@ void QWindowsBackingStore::resize(const QSize &sizeDip, const QRegion &regionDip
painter.drawImage(rect, oldimg, rect);
}
- if (QWindowsScaling::isActive())
- newwni->setDevicePixelRatio(QWindowsScaling::factor());
m_image.reset(newwni);
}
}
Q_GUI_EXPORT void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
-bool QWindowsBackingStore::scroll(const QRegion &areaDip, int dxDip, int dyDip)
+bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy)
{
if (m_image.isNull() || m_image->image().isNull())
return false;
- const QPoint dp = QPoint(dxDip, dyDip) * QWindowsScaling::factor();
- const QVector<QRect> rects = areaDip.rects();
+ const QVector<QRect> rects = area.rects();
+ const QPoint offset(dx, dy);
for (int i = 0; i < rects.size(); ++i)
- qt_scrollRectInImage(m_image->image(), QWindowsScaling::mapToNative(rects.at(i)), dp);
+ qt_scrollRectInImage(m_image->image(), rects.at(i), offset);
return true;
}
-void QWindowsBackingStore::beginPaint(const QRegion &regionDip)
+void QWindowsBackingStore::beginPaint(const QRegion &region)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaBackingStore) <<__FUNCTION__ << regionDip;
+ qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region;
if (m_image->image().hasAlphaChannel()) {
QPainter p(&m_image->image());
p.setCompositionMode(QPainter::CompositionMode_Source);
const QColor blank = Qt::transparent;
- foreach (const QRect &r, regionDip.rects())
- p.fillRect(QWindowsScaling::mapToNative(r), blank);
+ foreach (const QRect &r, region.rects())
+ p.fillRect(r, blank);
}
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 41ad29babc..4badcf1b09 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -35,7 +35,6 @@
#define QWINDOWSBACKINGSTORE_H
#include "qtwindows_additional.h"
-#include "qwindowsscaling.h"
#include <qpa/qplatformbackingstore.h>
#include <QtCore/QScopedPointer>
@@ -53,12 +52,7 @@ public:
~QWindowsBackingStore();
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE
- {
- flushDp(window, QWindowsScaling::mapToNative(region.boundingRect()),
- offset * QWindowsScaling::factor());
- }
- void flushDp(QWindow *window, const QRect &boundingRect, const QPoint &offset);
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE;
bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index 925427ac30..25cfd12b44 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -35,7 +35,6 @@
#include "qwindowscontext.h"
#include "qwindowsole.h"
#include "qwindowsmime.h"
-#include "qwindowsguieventdispatcher.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
@@ -48,6 +47,8 @@
#include <QtCore/QVariant>
#include <QtCore/QUrl>
+#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
+
QT_BEGIN_NAMESPACE
static const char formatTextPlainC[] = "text/plain";
@@ -69,6 +70,7 @@ static const char formatTextHtmlC[] = "text/html";
\ingroup qt-lighthouse-win
*/
+#ifndef QT_NO_DEBUG_STREAM
static QDebug operator<<(QDebug d, const QMimeData *mimeData)
{
QDebugStateSaver saver(d);
@@ -93,6 +95,7 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
d << ')';
return d;
}
+#endif // !QT_NO_DEBUG_STREAM
/*!
\class QWindowsClipboardRetrievalMimeData
@@ -109,8 +112,11 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const
{
IDataObject * pDataObj = 0;
- if (OleGetClipboard(&pDataObj) == S_OK)
+ if (OleGetClipboard(&pDataObj) == S_OK) {
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj;
return pDataObj;
+ }
return 0;
}
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 00049bd0d6..5cda6379de 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -36,7 +36,6 @@
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
-#include "qwindowsguieventdispatcher.h"
#include "qwindowsmousehandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmime.h"
@@ -52,7 +51,6 @@
#endif
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
-#include "qwindowsscaling.h"
#include <QtGui/QWindow>
#include <qpa/qwindowsysteminterface.h>
@@ -67,6 +65,8 @@
#include <QtCore/QScopedArrayPointer>
#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
+
#include <stdlib.h>
#include <stdio.h>
#include <windowsx.h>
@@ -893,6 +893,11 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr)
return result;
}
+static inline QWindowsInputContext *windowsInputContext()
+{
+ return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+}
+
/*!
\brief Main windows procedure registered for windows.
@@ -941,16 +946,29 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
}
+ if (et & QtWindows::InputMethodEventFlag) {
+ QWindowsInputContext *windowsInputContext = ::windowsInputContext();
+ // Disable IME assuming this is a special implementation hooking into keyboard input.
+ // "Real" IME implementations should use a native event filter intercepting IME events.
+ if (!windowsInputContext) {
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, false);
+ return false;
+ }
+ switch (et) {
+ case QtWindows::InputMethodStartCompositionEvent:
+ return windowsInputContext->startComposition(hwnd);
+ case QtWindows::InputMethodCompositionEvent:
+ return windowsInputContext->composition(hwnd, lParam);
+ case QtWindows::InputMethodEndCompositionEvent:
+ return windowsInputContext->endComposition(hwnd);
+ case QtWindows::InputMethodRequest:
+ return windowsInputContext->handleIME_Request(wParam, lParam, result);
+ default:
+ break;
+ }
+ } // InputMethodEventFlag
switch (et) {
- case QtWindows::InputMethodStartCompositionEvent:
- return QWindowsInputContext::instance()->startComposition(hwnd);
- case QtWindows::InputMethodCompositionEvent:
- return QWindowsInputContext::instance()->composition(hwnd, lParam);
- case QtWindows::InputMethodEndCompositionEvent:
- return QWindowsInputContext::instance()->endComposition(hwnd);
- case QtWindows::InputMethodRequest:
- return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result);
case QtWindows::GestureEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
@@ -1025,11 +1043,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
}
switch (et) {
+ case QtWindows::KeyboardLayoutChangeEvent:
+ if (QWindowsInputContext *wic = windowsInputContext())
+ wic->handleInputLanguageChanged(wParam, lParam); // fallthrough intended.
case QtWindows::KeyDownEvent:
case QtWindows::KeyEvent:
case QtWindows::InputMethodKeyEvent:
case QtWindows::InputMethodKeyDownEvent:
- case QtWindows::KeyboardLayoutChangeEvent:
case QtWindows::AppCommandEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
@@ -1265,9 +1285,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
}
- QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered,
- pos / QWindowsScaling::factor(),
- globalPos / QWindowsScaling::factor(),
+ QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
QWindowsKeyMapper::queryKeyboardModifiers());
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 5f443f2675..c769eb04a4 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -36,7 +36,6 @@
#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include "qwindowsscreen.h"
-#include "qwindowsscaling.h"
#include <QtGui/QBitmap>
#include <QtGui/QImage>
@@ -44,15 +43,17 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
-static void initResources()
+static bool initResources()
{
#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
Q_INIT_RESOURCE(cursors);
#endif
+ return true;
}
QT_BEGIN_NAMESPACE
@@ -68,19 +69,14 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
\ingroup qt-lighthouse-win
*/
-QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
- : shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0)
+QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
+ : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
{
- if (shape == Qt::BitmapCursor) {
- const qint64 pixmapCacheKey = c.pixmap().cacheKey();
- if (pixmapCacheKey) {
- bitmapCacheKey = pixmapCacheKey;
- } else {
- Q_ASSERT(c.bitmap());
- Q_ASSERT(c.mask());
- bitmapCacheKey = c.bitmap()->cacheKey();
- maskCacheKey = c.mask()->cacheKey();
- }
+ if (!bitmapCacheKey) {
+ Q_ASSERT(c.bitmap());
+ Q_ASSERT(c.mask());
+ bitmapCacheKey = c.bitmap()->cacheKey();
+ maskCacheKey = c.mask()->cacheKey();
}
}
@@ -98,9 +94,14 @@ QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor
*/
-HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot)
+HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
{
HCURSOR cur = 0;
+ scaleFactor /= pixmap.devicePixelRatioF();
+ if (!qFuzzyCompare(scaleFactor, 1)) {
+ pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(),
+ Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
QBitmap mask = pixmap.mask();
if (mask.isNull()) {
mask = QBitmap(pixmap.size());
@@ -207,7 +208,44 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
#endif
}
-static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
+// Create a cursor from image and mask of the format QImage::Format_Mono.
+static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1)
+{
+ Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
+ QImage bbits = cursor.bitmap()->toImage();
+ QImage mbits = cursor.mask()->toImage();
+ scaleFactor /= bbits.devicePixelRatioF();
+ if (!qFuzzyCompare(scaleFactor, 1)) {
+ const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize();
+ bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+ bbits = bbits.convertToFormat(QImage::Format_Mono);
+ mbits = mbits.convertToFormat(QImage::Format_Mono);
+ const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
+ const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
+ return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
+}
+
+static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR)
+{
+ const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR));
+ if (screen) {
+ // Correct the size if the DPI value of the screen differs from
+ // that of the primary screen.
+ if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) {
+ const QPlatformScreen *primaryScreen = primaryQScreen->handle();
+ if (screen != primaryScreen) {
+ const qreal logicalDpi = screen->logicalDpi().first;
+ const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first;
+ if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi))
+ return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize();
+ }
+ }
+ }
+ return primaryScreenCursorSize;
+}
+
static inline QSize standardCursorSize() { return QSize(32, 32); }
#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG)
@@ -216,7 +254,7 @@ static inline QSize standardCursorSize() { return QSize(32, 32); }
// createBitmapCursor() only work for standard sizes (32,48,64...), which does
// not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting
// in a non-standard 24x24 size).
-static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
+static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &systemCursorSize,
// The cursor size the bitmap is targeted for
const QSize &bitmapTargetCursorSize,
// The actual size of the bitmap data
@@ -234,10 +272,11 @@ static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
rawImage = rawImage.transformed(transform, Qt::SmoothTransformation);
}
const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2);
- return QCursor(rawImage, hotSpot.x(), hotSpot.y());
+ return QWindowsCursor::PixmapCursor(rawImage, hotSpot);
}
-QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape,
+ const QPlatformScreen *screen)
{
// Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
@@ -405,22 +444,22 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
switch (cursorShape) {
case Qt::SplitVCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
case Qt::SplitHCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
case Qt::OpenHandCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits);
case Qt::ClosedHandCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
case Qt::DragCopyCursor:
- return QCursor(QPixmap(copyDragCursorXpmC), 0, 0);
+ return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor:
- return QCursor(QPixmap(moveDragCursorXpmC), 0, 0);
+ return QWindowsCursor::PixmapCursor(QPixmap(moveDragCursorXpmC), QPoint(0, 0));
case Qt::DragLinkCursor:
- return QCursor(QPixmap(linkDragCursorXpmC), 0, 0);
+ return QWindowsCursor::PixmapCursor(QPixmap(linkDragCursorXpmC), QPoint(0, 0));
}
- return QCursor();
+ return QWindowsCursor::PixmapCursor();
}
#else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
struct QWindowsCustomPngCursor {
@@ -431,7 +470,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY;
};
-QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
@@ -457,14 +496,14 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
{ Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 }
};
- const int cursorSize = GetSystemMetrics(SM_CXCURSOR);
+ const QSize cursorSize = systemCursorSize(screen);
const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
const QWindowsCustomPngCursor *bestFit = 0;
int sizeDelta = INT_MAX;
for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
if (s->shape != cursorShape)
continue;
- const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize);
+ const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width());
if (currentSizeDelta < sizeDelta) {
bestFit = s;
if (currentSizeDelta == 0)
@@ -474,11 +513,11 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
}
if (!bestFit)
- return QCursor();
+ return PixmapCursor();
const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
QString::fromLatin1(bestFit->fileName));
- return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY);
+ return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY));
}
#endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
@@ -487,8 +526,10 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource;
};
-HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
+HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
+ Q_ASSERT(cursorShape != Qt::BitmapCursor);
+
static const QWindowsStandardCursorMapping standardCursors[] = {
{ Qt::ArrowCursor, IDC_ARROW},
{ Qt::UpArrowCursor, IDC_UPARROW },
@@ -506,20 +547,9 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
{ Qt::PointingHandCursor, IDC_HAND }
};
- const Qt::CursorShape cursorShape = c.shape();
switch (cursorShape) {
- case Qt::BitmapCursor: {
- const QPixmap pixmap = c.pixmap();
- if (!pixmap.isNull())
- return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
- const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
- const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
- const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
- const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
- return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm);
- }
case Qt::BlankCursor: {
- QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
+ QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono);
blank.fill(0); // ignore color table
return createBitmapCursor(blank, blank);
}
@@ -530,7 +560,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
case Qt::DragLinkCursor:
- return createSystemCursor(customCursor(cursorShape));
+ return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen));
default:
break;
}
@@ -555,44 +585,52 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
\brief Return cached standard cursor resources or create new ones.
*/
-QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
+CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{
- const QWindowsCursorCacheKey key(shape);
- CursorCache::iterator it = m_cursorCache.find(key);
- if (it == m_cursorCache.end())
- it = m_cursorCache.insert(key, QWindowsWindowCursor(QCursor(shape)));
- return it.value();
+ StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
+ if (it == m_standardCursorCache.end()) {
+ if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen))
+ it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
+ }
+ return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
}
/*!
\brief Return cached pixmap cursor or create new one.
*/
-QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
+CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c)
{
- const QWindowsCursorCacheKey cacheKey(c);
- CursorCache::iterator it = m_cursorCache.find(cacheKey);
- if (it == m_cursorCache.end()) {
- if (m_cursorCache.size() > 50) {
+ const QWindowsPixmapCursorCacheKey cacheKey(c);
+ PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey);
+ if (it == m_pixmapCursorCache.end()) {
+ if (m_pixmapCursorCache.size() > 50) {
// Prevent the cursor cache from growing indefinitely hitting GDI resource
// limits if new pixmap cursors are created repetitively by purging out
// all-noncurrent pixmap cursors (QTBUG-43515)
const HCURSOR currentCursor = GetCursor();
- for (it = m_cursorCache.begin(); it != m_cursorCache.end() ; ) {
- if (it.key().bitmapCacheKey && it.value().handle() != currentCursor)
- it = m_cursorCache.erase(it);
+ for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) {
+ if (it.value()->handle() != currentCursor)
+ it = m_pixmapCursorCache.erase(it);
else
++it;
}
}
- it = m_cursorCache.insert(cacheKey, QWindowsWindowCursor(c));
+ const qreal scaleFactor = QHighDpiScaling::factor(m_screen);
+ const QPixmap pixmap = c.pixmap();
+ const HCURSOR hc = pixmap.isNull()
+ ? createBitmapCursor(c, scaleFactor)
+ : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor);
+ it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
}
return it.value();
}
-QWindowsCursor::QWindowsCursor()
+QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen)
+ : m_screen(screen)
{
- initResources();
+ static const bool dummy = initResources();
+ Q_UNUSED(dummy)
}
/*!
@@ -607,13 +645,13 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
if (!window)
return;
if (!cursorIn) {
- QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor());
+ QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle));
return;
}
- const QWindowsWindowCursor wcursor =
+ const CursorHandlePtr wcursor =
cursorIn->shape() == Qt::BitmapCursor ?
pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
- if (wcursor.handle()) {
+ if (wcursor->handle()) {
QWindowsWindow::baseWindowOf(window)->setCursor(wcursor);
} else {
qWarning("%s: Unable to obtain system cursor for %d",
@@ -646,13 +684,100 @@ QWindowsCursor::CursorState QWindowsCursor::cursorState()
QPoint QWindowsCursor::pos() const
{
- return mousePosition() / QWindowsScaling::factor();
+ return mousePosition();
}
void QWindowsCursor::setPos(const QPoint &pos)
{
- const QPoint posDp = pos * QWindowsScaling::factor();
- SetCursorPos(posDp.x() , posDp.y());
+ SetCursorPos(pos.x() , pos.y());
+}
+
+QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
+{
+ switch (action) {
+ case Qt::CopyAction:
+ if (m_copyDragCursor.isNull())
+ m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap;
+ return m_copyDragCursor;
+ case Qt::TargetMoveAction:
+ case Qt::MoveAction:
+ if (m_moveDragCursor.isNull())
+ m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap;
+ return m_moveDragCursor;
+ case Qt::LinkAction:
+ if (m_linkDragCursor.isNull())
+ m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap;
+ return m_linkDragCursor;
+ default:
+ break;
+ }
+
+ static const char * const ignoreDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "aa......................",
+ "aXa.....................",
+ "aXXa....................",
+ "aXXXa...................",
+ "aXXXXa..................",
+ "aXXXXXa.................",
+ "aXXXXXXa................",
+ "aXXXXXXXa...............",
+ "aXXXXXXXXa..............",
+ "aXXXXXXXXXa.............",
+ "aXXXXXXaaaa.............",
+ "aXXXaXXa................",
+ "aXXaaXXa................",
+ "aXa..aXXa...............",
+ "aa...aXXa...............",
+ "a.....aXXa..............",
+ "......aXXa.....XXXX.....",
+ ".......aXXa..XXaaaaXX...",
+ ".......aXXa.XaaaaaaaaX..",
+ "........aa.XaaaXXXXaaaX.",
+ "...........XaaaaX..XaaX.",
+ "..........XaaXaaaX..XaaX",
+ "..........XaaXXaaaX.XaaX",
+ "..........XaaX.XaaaXXaaX",
+ "..........XaaX..XaaaXaaX",
+ "...........XaaX..XaaaaX.",
+ "...........XaaaXXXXaaaX.",
+ "............XaaaaaaaaX..",
+ ".............XXaaaaXX...",
+ "...............XXXX....."};
+
+ if (m_ignoreDragCursor.isNull()) {
+#if !defined (Q_OS_WINCE)
+ HCURSOR cursor = LoadCursor(NULL, IDC_NO);
+ ICONINFO iconInfo = {0, 0, 0, 0, 0};
+ GetIconInfo(cursor, &iconInfo);
+ BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
+
+ if (iconInfo.hbmColor
+ && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
+ && bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
+ const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
+ uchar *colorBits = new uchar[colorBitsLength];
+ GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
+ const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
+ bmColor.bmWidthBytes, QImage::Format_ARGB32);
+
+ m_ignoreDragCursor = QPixmap::fromImage(colorImage);
+ delete [] colorBits;
+ } else {
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+ }
+
+ DeleteObject(iconInfo.hbmMask);
+ DeleteObject(iconInfo.hbmColor);
+ DestroyCursor(cursor);
+#else // !Q_OS_WINCE
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+#endif // !Q_OS_WINCE
+ }
+ return m_ignoreDragCursor;
}
/*!
@@ -660,78 +785,11 @@ void QWindowsCursor::setPos(const QPoint &pos)
\brief Per-Window cursor. Contains a QCursor and manages its associated system
cursor handle resource.
- Based on QSharedDataPointer, so that it can be passed around and
- used as a property of QWindowsBaseWindow.
-
\internal
\ingroup qt-lighthouse-win
\sa QWindowsCursor
*/
-class QWindowsWindowCursorData : public QSharedData
-{
-public:
- QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {}
- explicit QWindowsWindowCursorData(const QCursor &c);
- ~QWindowsWindowCursorData();
-
- const QCursor m_cursor;
- const HCURSOR m_handle;
-};
-
-QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) :
- m_cursor(c),
- m_handle(QWindowsCursor::createSystemCursor(c))
-{
-}
-
-QWindowsWindowCursorData::~QWindowsWindowCursorData()
-{
- if (m_handle)
- DestroyCursor(m_handle);
-}
-
-QWindowsWindowCursor::QWindowsWindowCursor() :
- m_data(new QWindowsWindowCursorData)
-{
-}
-
-QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) :
- m_data(new QWindowsWindowCursorData(c))
-{
-}
-
-QWindowsWindowCursor::~QWindowsWindowCursor()
-{
-}
-
-QWindowsWindowCursor::QWindowsWindowCursor(const QWindowsWindowCursor &rhs) :
- m_data(rhs.m_data)
-{
-}
-
-QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCursor &rhs)
-{
- if (this != &rhs)
- m_data.operator =(rhs.m_data);
- return *this;
-}
-
-bool QWindowsWindowCursor::isNull() const
-{
- return m_data->m_handle == 0;
-}
-
-QCursor QWindowsWindowCursor::cursor() const
-{
- return m_data->m_cursor;
-}
-
-HCURSOR QWindowsWindowCursor::handle() const
-{
- return m_data->m_handle;
-}
-
QT_END_NAMESPACE
#endif // !QT_NO_CURSOR
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index f1763ddd7d..e93f779f94 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -37,51 +37,49 @@
#include "qtwindows_additional.h"
#include <qpa/qplatformcursor.h>
-#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedPointer>
#include <QtCore/QHash>
QT_BEGIN_NAMESPACE
-class QWindowsWindowCursorData;
-
-struct QWindowsCursorCacheKey
+struct QWindowsPixmapCursorCacheKey
{
- explicit QWindowsCursorCacheKey(const QCursor &c);
- explicit QWindowsCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {}
- QWindowsCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {}
+ explicit QWindowsPixmapCursorCacheKey(const QCursor &c);
- Qt::CursorShape shape;
qint64 bitmapCacheKey;
qint64 maskCacheKey;
};
-inline bool operator==(const QWindowsCursorCacheKey &k1, const QWindowsCursorCacheKey &k2)
+inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2)
{
- return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
+ return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
-inline uint qHash(const QWindowsCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
+inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
{
- return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
+ return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
}
-class QWindowsWindowCursor
+class CursorHandle
{
+ Q_DISABLE_COPY(CursorHandle)
public:
- QWindowsWindowCursor();
- explicit QWindowsWindowCursor(const QCursor &c);
- ~QWindowsWindowCursor();
- QWindowsWindowCursor(const QWindowsWindowCursor &c);
- QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c);
+ explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {}
+ ~CursorHandle()
+ {
+ if (m_hcursor)
+ DestroyCursor(m_hcursor);
+ }
- bool isNull() const;
- QCursor cursor() const;
- HCURSOR handle() const;
+ bool isNull() const { return !m_hcursor; }
+ HCURSOR handle() const { return m_hcursor; }
private:
- QSharedDataPointer<QWindowsWindowCursorData> m_data;
+ const HCURSOR m_hcursor;
};
+typedef QSharedPointer<CursorHandle> CursorHandlePtr;
+
class QWindowsCursor : public QPlatformCursor
{
public:
@@ -91,25 +89,44 @@ public:
CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
};
- QWindowsCursor();
+ struct PixmapCursor {
+ explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {}
+
+ QPixmap pixmap;
+ QPoint hotSpot;
+ };
+
+ explicit QWindowsCursor(const QPlatformScreen *screen);
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
QPoint pos() const Q_DECL_OVERRIDE;
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
- static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
- static HCURSOR createSystemCursor(const QCursor &c);
- static QCursor customCursor(Qt::CursorShape cursorShape);
+ 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 HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR);
static QPoint mousePosition();
static CursorState cursorState();
- QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
- QWindowsWindowCursor pixmapWindowCursor(const QCursor &c);
+ CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
+ CursorHandlePtr pixmapWindowCursor(const QCursor &c);
+
+ QPixmap dragDefaultCursor(Qt::DropAction action) const;
private:
- typedef QHash<QWindowsCursorCacheKey, QWindowsWindowCursor> CursorCache;
+ typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
+ typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
+
+ const QPlatformScreen *const m_screen;
+ StandardCursorCache m_standardCursorCache;
+ PixmapCursorCache m_pixmapCursorCache;
- CursorCache m_cursorCache;
+ mutable QPixmap m_copyDragCursor;
+ mutable QPixmap m_moveDragCursor;
+ mutable QPixmap m_linkDragCursor;
+ mutable QPixmap m_ignoreDragCursor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index da0ba27e3a..b983ba3354 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -360,6 +360,7 @@ public:
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DEBUG_STREAM
/* Output UID (IID, CLSID) as C++ constants.
* The constants are contained in the Windows SDK libs, but not for MinGW. */
static inline QString guidToString(const GUID &g)
@@ -385,6 +386,7 @@ inline QDebug operator<<(QDebug d, const GUID &g)
d << guidToString(g);
return d;
}
+#endif // !QT_NO_DEBUG_STREAM
// Return an allocated wchar_t array from a QString, reserve more memory if desired.
static wchar_t *qStringToWCharArray(const QString &s, size_t reserveSize = 0)
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 03438e3ee2..021058fa33 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -33,7 +33,7 @@
#include "qwindowsdrag.h"
#include "qwindowscontext.h"
-#include "qwindowsscaling.h"
+#include "qwindowsscreen.h"
#ifndef QT_NO_CLIPBOARD
# include "qwindowsclipboard.h"
#endif
@@ -43,7 +43,6 @@
#include "qwindowswindow.h"
#include "qwindowsmousehandler.h"
#include "qwindowscursor.h"
-#include "qwindowsscaling.h"
#include <QtGui/QMouseEvent>
#include <QtGui/QPixmap>
@@ -52,6 +51,7 @@
#include <QtGui/QGuiApplication>
#include <qpa/qwindowsysteminterface_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include <QtCore/QBuffer>
@@ -218,23 +218,14 @@ public:
STDMETHOD(GiveFeedback)(DWORD dwEffect);
private:
- class DragCursorHandle {
- Q_DISABLE_COPY(DragCursorHandle)
- public:
- DragCursorHandle(HCURSOR c) : cursor(c) {}
- ~DragCursorHandle() { DestroyCursor(cursor); }
- const HCURSOR cursor;
- };
- typedef QSharedPointer<DragCursorHandle> DragCursorHandlePtr;
-
struct CursorEntry {
CursorEntry() : cacheKey(0) {}
- CursorEntry(const QPixmap &p, qint64 cK, const DragCursorHandlePtr &c, const QPoint &h) :
+ CursorEntry(const QPixmap &p, qint64 cK, const CursorHandlePtr &c, const QPoint &h) :
pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {}
QPixmap pixmap;
qint64 cacheKey; // Cache key of cursor
- DragCursorHandlePtr cursor;
+ CursorHandlePtr cursor;
QPoint hotSpot;
};
@@ -249,7 +240,7 @@ private:
QWindowsDragCursorWindow *m_touchDragWindow;
ULONG m_refs;
-#ifndef QT_NO_DEBUG_OUTPUT
+#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug, const QWindowsOleDropSource::CursorEntry &);
#endif
};
@@ -271,14 +262,14 @@ QWindowsOleDropSource::~QWindowsOleDropSource()
qCDebug(lcQpaMime) << __FUNCTION__;
}
-#ifndef QT_NO_DEBUG_OUTPUT
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
{
d << "CursorEntry:" << e.pixmap.size() << '#' << e.cacheKey
- << "HCURSOR" << e.cursor->cursor << "hotspot:" << e.hotSpot;
+ << "HCURSOR" << e.cursor->handle() << "hotspot:" << e.hotSpot;
return d;
}
-#endif // !QT_NO_DEBUG_OUTPUT
+#endif // !QT_NO_DEBUG_STREAM
/*!
\brief Blend custom pixmap with cursors.
@@ -289,24 +280,37 @@ void QWindowsOleDropSource::createCursors()
const QDrag *drag = m_drag->currentDrag();
const QPixmap pixmap = drag->pixmap();
const bool hasPixmap = !pixmap.isNull();
- const int scaleFactor = QWindowsScaling::factor();
- const QSize pixmapSizeDp = pixmap.size() * scaleFactor;
+
+ // Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget.
+
+ qreal scaleFactor = 1;
+ QPlatformCursor *platformCursor = Q_NULLPTR;
+ if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) {
+ scaleFactor = QHighDpiScaling::factor(platformScreen);
+ platformCursor = platformScreen->cursor();
+ }
+ if (!platformCursor && QGuiApplication::primaryScreen())
+ platformCursor = QGuiApplication::primaryScreen()->handle()->cursor();
+
const bool scalePixmap = hasPixmap
&& m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled.
&& (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio()));
- const QPixmap drawPixmap = scalePixmap
- ? pixmap.scaled(pixmapSizeDp, Qt::KeepAspectRatio, Qt::SmoothTransformation) : pixmap;
-
+ const QPixmap scaledPixmap = scalePixmap
+ ? pixmap.scaled((QSizeF(pixmap.size()) * scaleFactor).toSize(),
+ Qt::KeepAspectRatio, Qt::SmoothTransformation)
+ : pixmap;
Qt::DropAction actions[] = { Qt::MoveAction, Qt::CopyAction, Qt::LinkAction, Qt::IgnoreAction };
int actionCount = int(sizeof(actions) / sizeof(actions[0]));
if (!hasPixmap)
--actionCount; // No Qt::IgnoreAction unless pixmap
- const QPoint hotSpot = drag->hotSpot() * scaleFactor;
+ const QPoint hotSpot = scalePixmap
+ ? (QPointF(drag->hotSpot()) * scaleFactor).toPoint()
+ : drag->hotSpot();
for (int cnum = 0; cnum < actionCount; ++cnum) {
const Qt::DropAction action = actions[cnum];
QPixmap cursorPixmap = drag->dragCursor(action);
- if (cursorPixmap.isNull())
- cursorPixmap = m_drag->defaultCursor(action);
+ if (cursorPixmap.isNull() && platformCursor)
+ cursorPixmap = static_cast<QWindowsCursor *>(platformCursor)->dragDefaultCursor(action);
const qint64 cacheKey = cursorPixmap.cacheKey();
const ActionCursorMapIt it = m_cursors.find(action);
if (it != m_cursors.end() && it.value().cacheKey == cacheKey)
@@ -321,21 +325,21 @@ void QWindowsOleDropSource::createCursors()
if (hasPixmap) {
const int x1 = qMin(-hotSpot.x(), 0);
- const int x2 = qMax(pixmapSizeDp.width() - hotSpot.x(), cursorPixmap.width());
+ const int x2 = qMax(scaledPixmap.width() - hotSpot.x(), cursorPixmap.width());
const int y1 = qMin(-hotSpot.y(), 0);
- const int y2 = qMax(pixmapSizeDp.height() - hotSpot.y(), cursorPixmap.height());
+ const int y2 = qMax(scaledPixmap.height() - hotSpot.y(), cursorPixmap.height());
QPixmap newCursor(x2 - x1 + 1, y2 - y1 + 1);
newCursor.fill(Qt::transparent);
QPainter p(&newCursor);
const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
- p.drawPixmap(pmDest, drawPixmap);
+ p.drawPixmap(pmDest, scaledPixmap);
p.drawPixmap(qMax(0, hotSpot.x()),qMax(0, hotSpot.y()), cursorPixmap);
newPixmap = newCursor;
newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
}
if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
- const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot);
+ const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(new CursorHandle(sysCursor)), newHotSpot);
if (it == m_cursors.end())
m_cursors.insert(action, entry);
else
@@ -448,13 +452,13 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
const CursorEntry &e = it.value();
switch (m_mode) {
case MouseDrag:
- SetCursor(e.cursor->cursor);
+ SetCursor(e.cursor->handle());
break;
case TouchDrag:
if (!m_touchDragWindow)
m_touchDragWindow = new QWindowsDragCursorWindow;
m_touchDragWindow->setPixmap(e.pixmap);
- m_touchDragWindow->setFramePosition((QWindowsCursor::mousePosition() - e.hotSpot) / QWindowsScaling::factor());
+ m_touchDragWindow->setFramePosition(QWindowsCursor::mousePosition() - e.hotSpot);
if (!m_touchDragWindow->isVisible())
m_touchDragWindow->show();
break;
@@ -530,9 +534,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
const QPlatformDragQtResponse response =
- QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
- m_lastPoint / QWindowsScaling::factor(),
- actions);
+ QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
m_answerRect = response.answerRect();
const Qt::DropAction action = response.acceptedAction();
@@ -625,9 +627,8 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
const QPlatformDropQtResponse response =
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
- m_lastPoint / QWindowsScaling::factor(),
+ m_lastPoint,
translateToQDragDropActions(*pdwEffect));
-
if (response.isAccepted()) {
const Qt::DropAction action = response.acceptedAction();
if (action == Qt::MoveAction || action == Qt::TargetMoveAction) {
@@ -706,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper;
}
-QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
-{
- switch (action) {
- case Qt::CopyAction:
- if (m_copyDragCursor.isNull())
- m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap();
- return m_copyDragCursor;
- case Qt::TargetMoveAction:
- case Qt::MoveAction:
- if (m_moveDragCursor.isNull())
- m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap();
- return m_moveDragCursor;
- case Qt::LinkAction:
- if (m_linkDragCursor.isNull())
- m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap();
- return m_linkDragCursor;
- default:
- break;
- }
-
- static const char * const ignoreDragCursorXpmC[] = {
- "24 30 3 1",
- ". c None",
- "a c #000000",
- "X c #FFFFFF",
- "aa......................",
- "aXa.....................",
- "aXXa....................",
- "aXXXa...................",
- "aXXXXa..................",
- "aXXXXXa.................",
- "aXXXXXXa................",
- "aXXXXXXXa...............",
- "aXXXXXXXXa..............",
- "aXXXXXXXXXa.............",
- "aXXXXXXaaaa.............",
- "aXXXaXXa................",
- "aXXaaXXa................",
- "aXa..aXXa...............",
- "aa...aXXa...............",
- "a.....aXXa..............",
- "......aXXa.....XXXX.....",
- ".......aXXa..XXaaaaXX...",
- ".......aXXa.XaaaaaaaaX..",
- "........aa.XaaaXXXXaaaX.",
- "...........XaaaaX..XaaX.",
- "..........XaaXaaaX..XaaX",
- "..........XaaXXaaaX.XaaX",
- "..........XaaX.XaaaXXaaX",
- "..........XaaX..XaaaXaaX",
- "...........XaaX..XaaaaX.",
- "...........XaaaXXXXaaaX.",
- "............XaaaaaaaaX..",
- ".............XXaaaaXX...",
- "...............XXXX....."};
-
- if (m_ignoreDragCursor.isNull()) {
-#if !defined (Q_OS_WINCE)
- HCURSOR cursor = LoadCursor(NULL, IDC_NO);
- ICONINFO iconInfo = {0, 0, 0, 0, 0};
- GetIconInfo(cursor, &iconInfo);
- BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
-
- if (iconInfo.hbmColor
- && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
- && bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
- const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
- uchar *colorBits = new uchar[colorBitsLength];
- GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
- const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
- bmColor.bmWidthBytes, QImage::Format_ARGB32);
-
- m_ignoreDragCursor = QPixmap::fromImage(colorImage);
- delete [] colorBits;
- } else {
- m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
- }
-
- DeleteObject(iconInfo.hbmMask);
- DeleteObject(iconInfo.hbmColor);
- DestroyCursor(cursor);
-#else // !Q_OS_WINCE
- m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
-#endif // !Q_OS_WINCE
- }
- return m_ignoreDragCursor;
-}
-
Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 9a5e0b17f2..890ad6c142 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -42,6 +42,9 @@
struct IDropTargetHelper;
QT_BEGIN_NAMESPACE
+
+class QPlatformScreen;
+
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
@@ -95,18 +98,11 @@ public:
IDropTargetHelper* dropHelper();
- QPixmap defaultCursor(Qt::DropAction action) const;
-
private:
QWindowsDropMimeData m_dropData;
IDataObject *m_dropDataObject;
IDropTargetHelper* m_cachedDropTargetHelper;
-
- mutable QPixmap m_copyDragCursor;
- mutable QPixmap m_moveDragCursor;
- mutable QPixmap m_linkDragCursor;
- mutable QPixmap m_ignoreDragCursor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index f2547d5cdd..21eba6da7e 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -39,7 +39,7 @@
#include <QtGui/QOpenGLContext>
#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
-# include <QtANGLE/EGL/eglext.h>
+# include <EGL/eglext.h>
#endif
QT_BEGIN_NAMESPACE
@@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
{
const HDC dc = QWindowsContext::instance()->displayContext();
if (!dc){
- qWarning("%s: No Display", Q_FUNC_INFO);
+ qWarning("%s: No Display", __FUNCTION__);
return 0;
}
if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
return 0;
}
if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
return 0;
}
@@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
if (display == EGL_NO_DISPLAY)
display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
- qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
+ qWarning("%s: Could not obtain EGL display", __FUNCTION__);
return 0;
}
if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
int err = libEGL.eglGetError();
- qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
if (err == 0x3001)
- qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
return 0;
}
@@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na
(EGLNativeWindowType) nativeWindow, 0);
if (surface == EGL_NO_SURFACE) {
*err = libEGL.eglGetError();
- qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
+ qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
}
return surface;
@@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
}
if (m_eglContext == EGL_NO_CONTEXT) {
- qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ int err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
+ // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
+ // A common cause for this is disabling the graphics adapter used by the app.
+ if (err == EGL_BAD_ALLOC)
+ qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
return;
}
@@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
+ } else if (err == EGL_BAD_ACCESS) {
+ // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
+ qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
+ // Simulate context loss as the context is useless.
+ QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
+ m_eglContext = EGL_NO_CONTEXT;
}
return false;
}
@@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
// Drop the surface. Will recreate on the next makeCurrent.
window->invalidateSurface();
} else {
- qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this);
+ qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
}
}
@@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent()
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
- qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
+ QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
@@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
}
bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok)
- qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ if (!ok) {
+ err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ if (err == EGL_CONTEXT_LOST) {
+ m_eglContext = EGL_NO_CONTEXT;
+ qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
+ } else {
+ qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
+ }
+ }
}
QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 3b27964b0e..c8eaccd956 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -40,6 +40,7 @@
#include <QtGui/QFont>
#include <QtGui/QGuiApplication>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
@@ -606,6 +607,7 @@ static inline bool initDirectWrite(QWindowsFontEngineData *d)
\ingroup qt-lighthouse-win
*/
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QFontDef &def)
{
QDebugStateSaver saver(d);
@@ -617,6 +619,7 @@ QDebug operator<<(QDebug d, const QFontDef &def)
<< def.hintingPreference;
return d;
}
+#endif // !QT_NO_DEBUG_STREAM
static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet)
{
@@ -1098,8 +1101,11 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal
QFontEngine *fontEngine = 0;
#if !defined(QT_NO_DIRECTWRITE)
- if (hintingPreference == QFont::PreferDefaultHinting
- || hintingPreference == QFont::PreferFullHinting)
+ bool useDirectWrite = (hintingPreference == QFont::PreferNoHinting)
+ || (hintingPreference == QFont::PreferVerticalHinting)
+ || (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting);
+
+ if (!useDirectWrite)
#endif
{
GUID guid;
@@ -1702,7 +1708,8 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
#if !defined(QT_NO_DIRECTWRITE)
bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
- || (request.hintingPreference == QFont::PreferVerticalHinting);
+ || (request.hintingPreference == QFont::PreferVerticalHinting)
+ || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting);
if (useDirectWrite && initDirectWrite(data.data())) {
const QString fam = QString::fromWCharArray(lf.lfFaceName);
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index efb5421996..10b6315aab 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -118,6 +118,10 @@ private:
QMap<QString, UniqueFontData> m_uniqueFontData;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const QFontDef &def);
+#endif
+
QT_END_NAMESPACE
#endif // QWINDOWSFONTDATABASE_H
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 795554698c..16cc2afef6 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -355,7 +355,7 @@ static bool addFontToDatabase(const QString &faceName,
const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight);
const QFont::Stretch stretch = QFont::Unstretched;
-#ifndef QT_NO_DEBUG_OUTPUT
+#ifndef QT_NO_DEBUG_STREAM
if (QWindowsContext::verbose > 2) {
QString message;
QTextStream str(&message);
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index a7c14ed2ac..a06707b84c 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -284,6 +284,7 @@ static inline void initPixelFormatDescriptor(PIXELFORMATDESCRIPTOR *d)
d->nVersion = 1;
}
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd)
{
QDebugStateSaver saver(d);
@@ -326,6 +327,32 @@ QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd)
return d;
}
+QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "OpenGL: " << s.vendor << ',' << s.renderer << " default "
+ << s.defaultFormat;
+ if (s.extensions & QOpenGLStaticContext::SampleBuffers)
+ d << ",SampleBuffers";
+ if (s.hasExtensions())
+ d << ", Extension-API present";
+ d << "\nExtensions: " << (s.extensionNames.count(' ') + 1);
+ if (QWindowsContext::verbose > 1)
+ d << s.extensionNames;
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &f)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "ContextFormat: v" << (f.version >> 8) << '.' << (f.version & 0xFF)
+ << " profile: " << f.profile << " options: " << f.options;
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
// Check whether an obtained PIXELFORMATDESCRIPTOR matches the request.
static inline bool
isAcceptableFormat(const QWindowsOpenGLAdditionalFormat &additional,
@@ -856,16 +883,11 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
{
QWindowsOpenGLContextFormat result;
const QByteArray version = QOpenGLStaticContext::getGlString(GL_VERSION);
- const int majorDot = version.indexOf('.');
- if (majorDot != -1) {
- int minorDot = version.indexOf('.', majorDot + 1);
- if (minorDot == -1)
- minorDot = version.size();
- result.version = (version.mid(0, majorDot).toInt() << 8)
- + version.mid(majorDot + 1, minorDot - majorDot - 1).toInt();
- } else {
+ int major, minor;
+ if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor))
+ result.version = (major << 8) + minor;
+ else
result.version = 0x0200;
- }
result.profile = QSurfaceFormat::NoProfile;
if (result.version < 0x0300) {
result.options |= QSurfaceFormat::DeprecatedFunctions;
@@ -905,15 +927,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const
format->setOption(QSurfaceFormat::DeprecatedFunctions);
}
-QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &f)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << "ContextFormat: v" << (f.version >> 8) << '.' << (f.version & 0xFF)
- << " profile: " << f.profile << " options: " << f.options;
- return d;
-}
-
/*!
\class QOpenGLTemporaryContext
\brief A temporary context that can be instantiated on the stack.
@@ -1018,22 +1031,6 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
return result;
}
-QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << "OpenGL: " << s.vendor << ',' << s.renderer << " default "
- << s.defaultFormat;
- if (s.extensions & QOpenGLStaticContext::SampleBuffers)
- d << ",SampleBuffers";
- if (s.hasExtensions())
- d << ", Extension-API present";
- d << "\nExtensions: " << (s.extensionNames.count(' ') + 1);
- if (QWindowsContext::verbose > 1)
- d << s.extensionNames;
- return d;
-}
-
/*!
\class QWindowsGLContext
\brief Open GL context.
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 516fa0707e..ba617f13ce 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -85,7 +85,11 @@ struct QWindowsOpenGLContextFormat
QSurfaceFormat::FormatOptions options;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &);
QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &);
+QDebug operator<<(QDebug d, const QOpenGLStaticContext &s);
+#endif
struct QWindowsOpengl32DLL
{
@@ -224,8 +228,6 @@ public:
static QWindowsOpengl32DLL opengl32;
};
-QDebug operator<<(QDebug d, const QOpenGLStaticContext &);
-
class QWindowsGLContext : public QWindowsOpenGLContext
{
public:
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
deleted file mode 100644
index 0bfa0239aa..0000000000
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwindowsguieventdispatcher.h"
-#include "qwindowscontext.h"
-
-#include <qpa/qwindowsysteminterface.h>
-
-#include <QtCore/QCoreApplication>
-#include <QtCore/QStack>
-#include <QtCore/QDebug>
-
-#include <windowsx.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QWindowsGuiEventDispatcher
- \brief Event dispatcher for Windows
-
- Maintains a global stack storing the current event dispatcher and
- its processing flags for access from the Windows procedure
- qWindowsWndProc. Handling the Lighthouse gui events should be done
- from within the qWindowsWndProc to ensure correct processing of messages.
-
- \internal
- \ingroup qt-lighthouse-win
-*/
-
-QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) :
- QEventDispatcherWin32(parent), m_flags(0)
-{
- setObjectName(QStringLiteral("QWindowsGuiEventDispatcher"));
- createInternalHwnd(); // QTBUG-40881: Do not delay registering timers, etc. for QtMfc.
-}
-
-bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
-{
- const QEventLoop::ProcessEventsFlags oldFlags = m_flags;
- m_flags = flags;
- if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
- qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags;
- const bool rc = QEventDispatcherWin32::processEvents(flags);
- if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
- qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc;
- m_flags = oldFlags;
- return rc;
-}
-
-void QWindowsGuiEventDispatcher::sendPostedEvents()
-{
- QEventDispatcherWin32::sendPostedEvents();
- QWindowSystemInterface::sendWindowSystemEvents(m_flags);
-}
-
-// Helpers for printing debug output for WM_* messages.
-struct MessageDebugEntry
-{
- UINT message;
- const char *description;
- bool interesting;
-};
-
-static const MessageDebugEntry
-messageDebugEntries[] = {
- {WM_CREATE, "WM_CREATE", true},
- {WM_PAINT, "WM_PAINT", true},
- {WM_CLOSE, "WM_CLOSE", true},
- {WM_DESTROY, "WM_DESTROY", true},
- {WM_MOVE, "WM_MOVE", true},
- {WM_SIZE, "WM_SIZE", true},
- {WM_MOUSEACTIVATE,"WM_MOUSEACTIVATE", true},
- {WM_CHILDACTIVATE, "WM_CHILDACTIVATE", true},
- {WM_PARENTNOTIFY, "WM_PARENTNOTIFY", true},
- {WM_ENTERIDLE, "WM_ENTERIDLE", false},
- {WM_GETICON, "WM_GETICON", false},
- {WM_KEYDOWN, "WM_KEYDOWN", true},
- {WM_SYSKEYDOWN, "WM_SYSKEYDOWN", true},
- {WM_SYSCOMMAND, "WM_SYSCOMMAND", true},
- {WM_KEYUP, "WM_KEYUP", true},
- {WM_SYSKEYUP, "WM_SYSKEYUP", true},
-#if defined(WM_APPCOMMAND)
- {WM_APPCOMMAND, "WM_APPCOMMAND", true},
-#endif
- {WM_IME_CHAR, "WM_IMECHAR", true},
- {WM_IME_KEYDOWN, "WM_IMECHAR", true},
- {WM_CANCELMODE, "WM_CANCELMODE", true},
- {WM_CHAR, "WM_CHAR", true},
- {WM_DEADCHAR, "WM_DEADCHAR", true},
- {WM_ACTIVATE, "WM_ACTIVATE", true},
- {WM_GETMINMAXINFO, "WM_GETMINMAXINFO", true},
- {WM_SETFOCUS, "WM_SETFOCUS", true},
- {WM_KILLFOCUS, "WM_KILLFOCUS", true},
- {WM_ENABLE, "WM_ENABLE", true},
- {WM_SHOWWINDOW, "WM_SHOWWINDOW", true},
- {WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING", true},
- {WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED", true},
- {WM_SETCURSOR, "WM_SETCURSOR", false},
- {WM_GETFONT, "WM_GETFONT", true},
- {WM_NCMOUSEMOVE, "WM_NCMOUSEMOVE", true},
- {WM_LBUTTONDOWN, "WM_LBUTTONDOWN", true},
- {WM_LBUTTONUP, "WM_LBUTTONUP", true},
- {WM_LBUTTONDBLCLK, "WM_LBUTTONDBLCLK", true},
- {WM_RBUTTONDOWN, "WM_RBUTTONDOWN", true},
- {WM_RBUTTONUP, "WM_RBUTTONUP", true},
- {WM_RBUTTONDBLCLK, "WM_RBUTTONDBLCLK", true},
- {WM_MBUTTONDOWN, "WM_MBUTTONDOWN", true},
- {WM_MBUTTONUP, "WM_MBUTTONUP", true},
- {WM_MBUTTONDBLCLK, "WM_MBUTTONDBLCLK", true},
- {WM_MOUSEWHEEL, "WM_MOUSEWHEEL", true},
- {WM_XBUTTONDOWN, "WM_XBUTTONDOWN", true},
- {WM_XBUTTONUP, "WM_XBUTTONUP", true},
- {WM_XBUTTONDBLCLK, "WM_XBUTTONDBLCLK", true},
- {WM_MOUSEHWHEEL, "WM_MOUSEHWHEEL", true},
- {WM_NCCREATE, "WM_NCCREATE", true},
- {WM_NCCALCSIZE, "WM_NCCALCSIZE", true},
- {WM_NCACTIVATE, "WM_NCACTIVATE", true},
- {WM_NCMOUSELEAVE, "WM_NCMOUSELEAVE", true},
- {WM_NCLBUTTONDOWN, "WM_NCLBUTTONDOWN", true},
- {WM_NCLBUTTONUP, "WM_NCLBUTTONUP", true},
- {WM_ACTIVATEAPP, "WM_ACTIVATEAPP", true},
- {WM_NCPAINT, "WM_NCPAINT", true},
- {WM_ERASEBKGND, "WM_ERASEBKGND", true},
- {WM_MOUSEMOVE, "WM_MOUSEMOVE", true},
- {WM_MOUSELEAVE, "WM_MOUSELEAVE", true},
- {WM_NCHITTEST, "WM_NCHITTEST", false},
- {WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true},
- {WM_INPUTLANGCHANGE, "WM_INPUTLANGCHANGE", true},
- {WM_IME_NOTIFY, "WM_IME_NOTIFY", true},
-#if defined(WM_DWMNCRENDERINGCHANGED)
- {WM_DWMNCRENDERINGCHANGED, "WM_DWMNCRENDERINGCHANGED", true},
-#endif
- {WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true},
- {WM_IME_NOTIFY, "WM_IME_NOTIFY", true},
- {WM_TOUCH, "WM_TOUCH", true},
- {WM_CHANGECBCHAIN, "WM_CHANGECBCHAIN", true},
- {WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD", true},
- {WM_RENDERFORMAT, "WM_RENDERFORMAT", true},
- {WM_RENDERALLFORMATS, "WM_RENDERALLFORMATS", true},
- {WM_DESTROYCLIPBOARD, "WM_DESTROYCLIPBOARD", true},
- {WM_CAPTURECHANGED, "WM_CAPTURECHANGED", true},
- {WM_IME_STARTCOMPOSITION, "WM_IME_STARTCOMPOSITION", true},
- {WM_IME_COMPOSITION, "WM_IME_COMPOSITION", true},
- {WM_IME_ENDCOMPOSITION, "WM_IME_ENDCOMPOSITION", true},
- {WM_IME_NOTIFY, "WM_IME_NOTIFY", true},
- {WM_IME_REQUEST, "WM_IME_REQUEST", true},
-#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
- {WM_QUERYENDSESSION, "WM_QUERYENDSESSION", true},
- {WM_ENDSESSION, "WM_ENDSESSION", true},
-#endif
- {WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE", true},
- {WM_THEMECHANGED, "WM_THEMECHANGED", true}
-};
-
-static inline const MessageDebugEntry *messageDebugEntry(UINT msg)
-{
- for (size_t i = 0; i < sizeof(messageDebugEntries)/sizeof(MessageDebugEntry); i++)
- if (messageDebugEntries[i].message == msg)
- return messageDebugEntries + i;
- return 0;
-}
-
-const char *QWindowsGuiEventDispatcher::windowsMessageName(UINT msg)
-{
- if (const MessageDebugEntry *e = messageDebugEntry(msg))
- return e->description;
- return "Unknown";
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 68e38dc4a6..7e1cc563cb 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -36,7 +36,6 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowsmousehandler.h"
-#include "qwindowsscaling.h"
#include <QtCore/QDebug>
#include <QtCore/QObject>
@@ -85,6 +84,18 @@ static inline void imeNotifyCancelComposition(HWND hwnd)
ImmReleaseContext(hwnd, himc);
}
+static inline LCID languageIdFromLocaleId(LCID localeId)
+{
+ return localeId & 0xFFFF;
+}
+
+static inline LCID currentInputLanguageId()
+{
+ return languageIdFromLocaleId(reinterpret_cast<quintptr>(GetKeyboardLayout(0)));
+}
+
+Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp
+
/*!
\class QWindowsInputContext
\brief Windows Input context implementation
@@ -154,7 +165,9 @@ QWindowsInputContext::CompositionContext::CompositionContext() :
QWindowsInputContext::QWindowsInputContext() :
m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")),
- m_endCompositionRecursionGuard(false)
+ m_endCompositionRecursionGuard(false),
+ m_languageId(currentInputLanguageId()),
+ m_locale(qt_localeFromLCID(m_languageId))
{
connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged,
this, &QWindowsInputContext::cursorRectChanged);
@@ -220,21 +233,24 @@ void QWindowsInputContext::updateEnabled()
const bool accepted = inputMethodAccepted();
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted;
- if (accepted) {
- // Re-enable IME by associating default context saved on first disabling.
- if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
- platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
- }
- } else {
- // Disable IME by associating 0 context. Store context first time.
- if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
- platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
- if (!QWindowsInputContext::m_defaultContext && oldImC)
- QWindowsInputContext::m_defaultContext = oldImC;
- }
- }
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted);
+ }
+}
+
+void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
+{
+ if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled)
+ return;
+ if (enabled) {
+ // Re-enable Windows IME by associating default context saved on first disabling.
+ ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
+ platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
+ } else {
+ // Disable Windows IME by associating 0 context. Store context first time.
+ const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
+ platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
+ if (!QWindowsInputContext::m_defaultContext && oldImC)
+ QWindowsInputContext::m_defaultContext = oldImC;
}
}
@@ -254,10 +270,9 @@ void QWindowsInputContext::cursorRectChanged()
if (!m_compositionContext.hwnd)
return;
const QInputMethod *inputMethod = QGuiApplication::inputMethod();
- const QRect cursorRectangleDip = inputMethod->cursorRectangle().toRect();
- if (!cursorRectangleDip.isValid())
+ const QRect cursorRectangle = inputMethod->cursorRectangle().toRect();
+ if (!cursorRectangle.isValid())
return;
- const QRect cursorRectangle = QWindowsScaling::mapToNative(cursorRectangleDip);
qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle;
@@ -308,11 +323,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP
ImmReleaseContext(m_compositionContext.hwnd, himc);
}
-QWindowsInputContext *QWindowsInputContext::instance()
-{
- return static_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
-}
-
static inline QString getCompositionString(HIMC himc, DWORD dwIndex)
{
enum { bufferSize = 256 };
@@ -375,7 +385,7 @@ bool QWindowsInputContext::startComposition(HWND hwnd)
QWindow *window = QGuiApplication::focusWindow();
if (!window)
return false;
- qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window;
+ qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window << "language=" << m_languageId;
if (!fo || QWindowsWindow::handleOf(window) != hwnd)
return false;
initContext(hwnd, fo);
@@ -559,6 +569,21 @@ bool QWindowsInputContext::handleIME_Request(WPARAM wParam,
return false;
}
+void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lparam)
+{
+ const LCID newLanguageId = languageIdFromLocaleId(lparam);
+ if (newLanguageId == m_languageId)
+ return;
+ const LCID oldLanguageId = m_languageId;
+ m_languageId = newLanguageId;
+ m_locale = qt_localeFromLCID(m_languageId);
+ emitLocaleChanged();
+
+ qCDebug(lcQpaInputMethods) << __FUNCTION__ << hex << showbase
+ << oldLanguageId << "->" << newLanguageId << "Character set:"
+ << DWORD(wparam) << dec << noshowbase << m_locale;
+}
+
/*!
\brief Determines the string for reconversion with selection.
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 110986c20c..636d481e70 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -36,12 +36,14 @@
#include "qtwindows_additional.h"
+#include <QtCore/QLocale>
#include <QtCore/QPointer>
#include <qpa/qplatforminputcontext.h>
QT_BEGIN_NAMESPACE
class QInputMethodEvent;
+class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
@@ -62,14 +64,16 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
+ static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
+
bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
+ QLocale locale() const Q_DECL_OVERRIDE { return m_locale; }
+
void reset() Q_DECL_OVERRIDE;
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
- static QWindowsInputContext *instance();
-
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
bool endComposition(HWND hwnd);
@@ -78,6 +82,7 @@ public:
int reconvertString(RECONVERTSTRING *reconv);
bool handleIME_Request(WPARAM wparam, LPARAM lparam, LRESULT *result);
+ void handleInputLanguageChanged(WPARAM wparam, LPARAM lparam);
private slots:
void cursorRectChanged();
@@ -93,6 +98,8 @@ private:
static HIMC m_defaultContext;
CompositionContext m_compositionContext;
bool m_endCompositionRecursionGuard;
+ LCID m_languageId;
+ QLocale m_locale;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 089c3cd0fe..797a96cda7 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -33,7 +33,6 @@
****************************************************************************/
#include "qwindowsintegration.h"
-#include "qwindowsscaling.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
#include "qwindowsopenglcontext.h"
@@ -45,7 +44,6 @@
# include "qwindowsfontdatabase_ft.h"
#endif
#include "qwindowsfontdatabase.h"
-#include "qwindowsguieventdispatcher.h"
#ifndef QT_NO_CLIPBOARD
# include "qwindowsclipboard.h"
# ifndef QT_NO_DRAGANDDROP
@@ -64,9 +62,11 @@
# include "qwindowssessionmanager.h"
#endif
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
-#include <QtCore/private/qeventdispatcher_win_p.h>
+#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
+
#include <QtCore/QDebug>
#include <QtCore/QVariant>
@@ -223,12 +223,8 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
m_context.setProcessDpiAwareness(dpiAwareness);
dpiAwarenessSet = true;
}
- // Determine suitable scale factor, don't mix Windows and Qt scaling
- if (dpiAwareness != QtWindows::ProcessDpiUnaware)
- QWindowsScaling::setFactor(QWindowsScaling::determineUiScaleFactor());
qCDebug(lcQpaWindows)
- << __FUNCTION__ << "DpiAwareness=" << dpiAwareness <<",Scaling="
- << QWindowsScaling::factor();
+ << __FUNCTION__ << "DpiAwareness=" << dpiAwareness;
m_context.initTouch(m_options);
}
@@ -258,10 +254,9 @@ QWindowsIntegration::~QWindowsIntegration()
void QWindowsIntegration::initialize()
{
- if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create())
- d->m_inputContext.reset(pluginContext);
- else
- d->m_inputContext.reset(new QWindowsInputContext);
+ QString icStr = QPlatformInputContextFactory::requested();
+ icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext)
+ : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
}
bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -293,11 +288,11 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return false;
}
-QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
+QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
{
QWindowsWindowData requested;
requested.flags = window->flags();
- requested.geometry = QWindowsScaling::mapToNative(window->geometry());
+ requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())
@@ -312,22 +307,30 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
<< "\n Obtained : " << obtained.geometry << " margins=" << obtained.frame
<< " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n';
- if (obtained.hwnd) {
- if (requested.flags != obtained.flags)
- window->setFlags(obtained.flags);
- // Trigger geometry change signals of QWindow.
- if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry)
- QWindowSystemInterface::handleGeometryChange(window, QWindowsScaling::mapFromNative(obtained.geometry));
+ if (Q_UNLIKELY(!obtained.hwnd))
+ return Q_NULLPTR;
+
+ QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
+ Q_ASSERT(result);
+
+ if (requested.flags != obtained.flags)
+ window->setFlags(obtained.flags);
+ // Trigger geometry/screen change signals of QWindow.
+ if ((obtained.flags & Qt::Desktop) != Qt::Desktop) {
+ if (requested.geometry != obtained.geometry)
+ QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
+ QPlatformScreen *screen = result->screenForGeometry(obtained.geometry);
+ if (screen && result->screen() != screen)
+ QWindowSystemInterface::handleWindowScreenChanged(window, screen->screen());
}
- return obtained;
+ return result;
}
-QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
+// Overridden to return a QWindowsDirect2DWindow in Direct2D plugin.
+QWindowsWindow *QWindowsIntegration::createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &data) const
{
- QWindowsWindowData data = createWindowData(window);
- return data.hwnd ? new QWindowsWindow(window, data)
- : Q_NULLPTR;
+ return new QWindowsWindow(window, data);
}
#ifndef QT_NO_OPENGL
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index fa5192ba03..cb10bf08f5 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -62,7 +62,6 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const;
- QWindowsWindowData createWindowData(QWindow *window) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
@@ -101,6 +100,9 @@ public:
QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE;
#endif
+protected:
+ virtual QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const;
+
private:
QScopedPointer<QWindowsIntegrationPrivate> d;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index d47c7df9e0..4c0b94e6e7 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -33,15 +33,16 @@
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
+#include "qwindowsintegration.h"
#include "qwindowswindow.h"
-#include "qwindowsguieventdispatcher.h"
-#include "qwindowsscaling.h"
#include "qwindowsinputcontext.h"
#include <QtGui/QWindow>
#include <qpa/qwindowsysteminterface.h>
#include <private/qguiapplication_p.h>
+#include <private/qhighdpiscaling_p.h>
#include <QtGui/QKeyEvent>
+#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h>
#if defined(WM_APPCOMMAND)
# ifndef FAPPCOMMAND_MOUSE
@@ -792,10 +793,12 @@ static void showSystemMenu(QWindow* w)
#undef enabled
#undef disabled
#endif // !Q_OS_WINCE
- const QPoint topLeft = topLevel->geometry().topLeft() * QWindowsScaling::factor();
+ const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel);
const int ret = TrackPopupMenuEx(menu,
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
- topLeft.x(), topLeft.y(), topLevelHwnd, 0);
+ pos.x(), pos.y(),
+ topLevelHwnd,
+ 0);
if (ret)
qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, ret, 0);
}
@@ -1072,7 +1075,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
- if (!QWindowsInputContext::instance()->isComposing())
+ const QWindowsInputContext *windowsInputContext =
+ qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+ if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey((HWND)window->winId());
BYTE keyState[256];
wchar_t newKey[3] = {0};
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 622352e987..0a2ba9b0e7 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -299,8 +299,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
return true;
}
-//#define QMIME_DEBUG
-
// helpers for using global memory
static int getCf(const FORMATETC &formatetc)
@@ -380,6 +378,73 @@ static bool canGetData(int cf, IDataObject * pDataObj)
return true;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const FORMATETC &tc)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "FORMATETC(cfFormat=" << tc.cfFormat << ' ';
+ switch (tc.cfFormat) {
+ case CF_TEXT:
+ d << "CF_TEXT";
+ break;
+ case CF_BITMAP:
+ d << "CF_BITMAP";
+ break;
+ case CF_TIFF:
+ d << "CF_TIFF";
+ break;
+ case CF_OEMTEXT:
+ d << "CF_OEMTEXT";
+ break;
+ case CF_DIB:
+ d << "CF_DIB";
+ break;
+ case CF_DIBV5:
+ d << "CF_DIBV5";
+ break;
+ case CF_UNICODETEXT:
+ d << "CF_UNICODETEXT";
+ break;
+#ifndef Q_OS_WINCE
+ case CF_ENHMETAFILE:
+ d << "CF_ENHMETAFILE";
+ break;
+#endif // !Q_OS_WINCE
+ default:
+ d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat);
+ break;
+ }
+ d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex
+ << ", tymed=" << tc.tymed << ", ptd=" << tc.ptd << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, IDataObject *dataObj)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "IDataObject(";
+ if (dataObj) { // Output formats contained in IDataObject.
+ IEnumFORMATETC *enumFormatEtc;
+ if (SUCCEEDED(dataObj->EnumFormatEtc(DATADIR_GET, &enumFormatEtc)) && enumFormatEtc) {
+ FORMATETC formatEtc[1];
+ ULONG fetched;
+ if (SUCCEEDED(enumFormatEtc->Reset())) {
+ while (SUCCEEDED(enumFormatEtc->Next(1, formatEtc, &fetched)) && fetched)
+ d << formatEtc[0] << ',';
+ enumFormatEtc->Release();
+ }
+ }
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
/*!
\class QWindowsMime
\brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
@@ -894,11 +959,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
QVariant result;
if (canConvertToMime(mime, pDataObj)) {
QByteArray html = getData(CF_HTML, pDataObj);
-#ifdef QMIME_DEBUG
- qDebug("QWindowsMimeHtml::convertToMime");
- qDebug("raw :");
- qDebug(html);
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html;
int start = html.indexOf("StartHTML:");
int end = html.indexOf("EndHTML:");
@@ -996,6 +1057,8 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
@@ -1216,9 +1279,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat
if (canConvertToMime(mimeType, pDataObj)) {
QByteArray data = getData(inFormats.key(mimeType), pDataObj);
if (!data.isEmpty()) {
-#ifdef QMIME_DEBUG
- qDebug("QBuiltInMimes::convertToMime()");
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__;
if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
// text/html is in wide chars on windows (compatible with Mozilla)
val = QString::fromWCharArray((const wchar_t *)data.data());
@@ -1326,6 +1387,8 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con
that->formats.insert(cf, mimeType);
formatetcs += setCf(cf);
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\"";
@@ -1400,11 +1463,8 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
if (!format.isEmpty())
return format;
- wchar_t buffer[256];
- int len = GetClipboardFormatName(getCf(formatetc), buffer, 256);
-
- if (len) {
- QString clipFormat = QString::fromWCharArray(buffer, len);
+ const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc));
+ if (!clipFormat.isEmpty()) {
#ifndef QT_NO_DRAGANDDROP
if (QInternalMimeData::canReadData(clipFormat))
format = clipFormat;
@@ -1470,15 +1530,12 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
if (hr == NOERROR) {
FORMATETC fmtetc;
while (S_OK == fmtenum->Next(1, &fmtetc, 0)) {
-#if defined(QMIME_DEBUG)
- wchar_t buf[256] = {0};
- GetClipboardFormatName(fmtetc.cfFormat, buf, 255);
- qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf)));
-#endif
for (int i= m_mimes.size() - 1; i >= 0; --i) {
QString format = m_mimes.at(i)->mimeForFormat(fmtetc);
if (!format.isEmpty() && !formats.contains(format)) {
formats += format;
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetc << format;
}
}
// as documented in MSDN to avoid possible memleak
@@ -1494,6 +1551,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
ensureInitialized();
+ qCDebug(lcQpaMime) << __FUNCTION__ << formatetc;
for (int i = m_mimes.size()-1; i >= 0; --i) {
if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData))
return m_mimes.at(i);
@@ -1521,13 +1579,24 @@ QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim
void QWindowsMimeConverter::ensureInitialized() const
{
if (m_mimes.isEmpty()) {
- m_mimes << new QWindowsMimeImage << new QLastResortMimes
+ m_mimes
+#ifndef QT_NO_IMAGEFORMAT_BMP
+ << new QWindowsMimeImage
+#endif //QT_NO_IMAGEFORMAT_BMP
+ << new QLastResortMimes
<< new QWindowsMimeText << new QWindowsMimeURI
<< new QWindowsMimeHtml << new QBuiltInMimes;
m_internalMimeCount = m_mimes.size();
}
}
+QString QWindowsMimeConverter::clipboardFormatName(int cf)
+{
+ wchar_t buf[256] = {0};
+ return GetClipboardFormatName(cf, buf, 255)
+ ? QString::fromWCharArray(buf) : QString();
+}
+
QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
IDataObject *pDataObj,
QVariant::Type preferredType,
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 952410e14b..1ec0dccdf8 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
+class QDebug;
class QMimeData;
class QWindowsMime
@@ -83,6 +84,8 @@ public:
void registerMime(QWindowsMime *mime);
void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
+ static QString clipboardFormatName(int cf);
+
private:
void ensureInitialized() const;
@@ -90,6 +93,11 @@ private:
mutable int m_internalMimeCount;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const FORMATETC &);
+QDebug operator<<(QDebug d, IDataObject *);
+#endif
+
QT_END_NAMESPACE
#endif // QWINDOWSMIME_H
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index e83354157b..e26010b5c4 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -218,10 +218,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const QPoint globalPosition = winEventPosition;
const QPoint clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
- QWindowSystemInterface::handleFrameStrutMouseEvent(window,
- clientPosition / QWindowsScaling::factor(),
- globalPosition / QWindowsScaling::factor(),
- buttons,
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
+ globalPosition, buttons,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
return false; // Allow further event processing (dragging of windows).
@@ -286,7 +284,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
// ChildWindowFromPointEx() may not find the Qt window (failing with ERROR_ACCESS_DENIED)
if (!currentWindowUnderMouse) {
const QRect clientRect(QPoint(0, 0), window->size());
- if (clientRect.contains(winEventPosition / QWindowsScaling::factor()))
+ if (clientRect.contains(winEventPosition))
currentWindowUnderMouse = window;
}
@@ -373,14 +371,14 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
m_windowUnderMouse = currentWindowUnderMouse;
}
- QWindowSystemInterface::handleMouseEvent(window,
- winEventPosition / QWindowsScaling::factor(),
- globalPosition / QWindowsScaling::factor(),
- buttons,
+ QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
m_previousCaptureWindow = hasCapture ? window : 0;
- return true;
+ // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
+ // is sent for unhandled WM_XBUTTONDOWN.
+ return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
+ || QWindowSystemInterface::flushWindowSystemEvents();
}
static bool isValidWheelReceiver(QWindow *candidate)
@@ -411,11 +409,9 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del
}
if (handleEvent) {
- const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor();
QWindowSystemInterface::handleWheelEvent(receiver,
- posDip, globalPos / QWindowsScaling::factor(),
- delta / QWindowsScaling::factor(),
- orientation, mods);
+ QWindowsGeometryHint::mapFromGlobal(receiver, globalPos),
+ globalPos, delta, orientation, mods);
}
}
@@ -492,7 +488,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
return true;
}
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
const int winTouchPointCount = msg.wParam;
QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]);
@@ -503,7 +504,6 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
Qt::TouchPointStates allStates = 0;
QWindowsContext::user32dll.getTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
- const qreal screenPosFactor = 0.01 / qreal(QWindowsScaling::factor());
for (int i = 0; i < winTouchPointCount; ++i) {
const TOUCHINPUT &winTouchInput = winTouchInputs[i];
int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
@@ -517,9 +517,9 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
if (m_lastTouchPositions.contains(id))
touchPoint.normalPosition = m_lastTouchPositions.value(id);
- const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) * screenPosFactor;
+ const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) / qreal(100.);
if (winTouchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA)
- touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) * screenPosFactor);
+ touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) / qreal(100.));
touchPoint.area.moveCenter(screenPos);
QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(),
screenPos.y() / screenGeometry.height());
@@ -583,7 +583,12 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd,
if (gi.dwID != GID_DIRECTMANIPULATION)
return true;
static QPoint lastTouchPos;
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
QWindowSystemInterface::TouchPoint touchPoint;
static QWindowSystemInterface::TouchPoint touchPoint2;
touchPoint.id = 0;//gi.dwInstanceID;
diff --git a/src/plugins/platforms/windows/qwindowsnativeimage.h b/src/plugins/platforms/windows/qwindowsnativeimage.h
index 6f9ce93ef0..80a1de1ea5 100644
--- a/src/plugins/platforms/windows/qwindowsnativeimage.h
+++ b/src/plugins/platforms/windows/qwindowsnativeimage.h
@@ -57,8 +57,6 @@ public:
HDC hdc() const { return m_hdc; }
- void setDevicePixelRatio(qreal scaleFactor) { m_image.setDevicePixelRatio(scaleFactor); }
-
static QImage::Format systemFormat();
private:
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 6f5a521af8..e480c1ebcf 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -132,12 +132,6 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
{
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
- if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << QString::fromWCharArray(buf);
- }
-
if (data) {
const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data))
@@ -145,11 +139,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
hr = ResultFromScode(S_OK);
}
- if (QWindowsContext::verbose > 1) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << " returns 0x" << int(hr) << dec;
- }
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr);
return hr;
}
@@ -211,7 +202,7 @@ STDMETHODIMP
QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection;
if (!data)
return ResultFromScode(DATA_E_FORMATETC);
@@ -274,7 +265,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
m_dwRefs(1), m_nIndex(0), m_isNull(false)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
m_lpfmtetcs.reserve(fmtetcs.count());
for (int idx = 0; idx < fmtetcs.count(); ++idx) {
LPFORMATETC destetc = new FORMATETC();
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 9ebd946ce4..e32a7e32af 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -98,6 +98,7 @@ GpuDescription GpuDescription::detect()
#endif
}
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const GpuDescription &gd)
{
QDebugStateSaver s(d);
@@ -109,6 +110,7 @@ QDebug operator<<(QDebug d, const GpuDescription &gd)
<< ", version=" << gd.driverVersion << ", " << gd.description << ')';
return d;
}
+#endif // !QT_NO_DEBUG_STREAM
// Return printable string formatted like the output of the dxdiag tool.
QString GpuDescription::toString() const
@@ -224,7 +226,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
#elif defined(Q_OS_WINCE)
return QWindowsOpenGLTester::Gles;
#else
- QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion);
+ QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description);
SupportedRenderersCache *srCache = supportedRenderersCache();
SupportedRenderersCache::const_iterator it = srCache->find(qgpu);
if (it != srCache->cend())
@@ -250,19 +252,19 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
qCDebug(lcQpaGl) << "GPU features:" << features;
if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific
- qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu;
+ qCDebug(lcQpaGl) << "Disabling Desktop GL: " << gpu;
result &= ~QWindowsOpenGLTester::DesktopGl;
}
if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword
- qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu;
+ qCDebug(lcQpaGl) << "Disabling ANGLE: " << gpu;
result &= ~QWindowsOpenGLTester::GlesMask;
} else {
if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword
- qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu;
+ qCDebug(lcQpaGl) << "Disabling D3D11: " << gpu;
result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
}
if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific
- qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu;
+ qCDebug(lcQpaGl) << "Disabling D3D9: " << gpu;
result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
}
}
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index 748885542d..f22031aa4e 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -36,7 +36,7 @@
#include <QtCore/QByteArray>
#include <QtCore/QFlags>
-#include <private/qversionnumber_p.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +60,9 @@ struct GpuDescription
QByteArray description;
};
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const GpuDescription &gd);
+#endif
class QWindowsOpenGLTester
{
diff --git a/src/plugins/platforms/windows/qwindowsscaling.cpp b/src/plugins/platforms/windows/qwindowsscaling.cpp
deleted file mode 100644
index 6ab7f254fd..0000000000
--- a/src/plugins/platforms/windows/qwindowsscaling.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwindowsscaling.h"
-#include "qwindowsscreen.h"
-
-#include <QtCore/QDebug>
-#include <QtCore/QCoreApplication>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QWindowsScaling
- \brief Windows scaling utilities
-
- \internal
- \ingroup qt-lighthouse-win
-*/
-
-int QWindowsScaling::m_factor = 1;
-
-static const char devicePixelRatioEnvVar[] = "QT_DEVICE_PIXEL_RATIO";
-
-// Suggest a scale factor by checking monitor sizes.
-int QWindowsScaling::determineUiScaleFactor()
-{
- if (!qEnvironmentVariableIsSet(devicePixelRatioEnvVar))
- return 1;
- const QByteArray envDevicePixelRatioEnv = qgetenv(devicePixelRatioEnvVar);
- // Auto: Suggest a scale factor by checking monitor resolution.
- if (envDevicePixelRatioEnv == "auto") {
- const int maxResolution = QWindowsScreen::maxMonitorHorizResolution();
- return maxResolution > 180 ? maxResolution / 96 : 1;
- }
- // Get factor from environment
- bool ok = false;
- const int envFactor = envDevicePixelRatioEnv.toInt(&ok);
- return ok && envFactor > 0 ? envFactor : 1;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscaling.h b/src/plugins/platforms/windows/qwindowsscaling.h
deleted file mode 100644
index 39e554bbe2..0000000000
--- a/src/plugins/platforms/windows/qwindowsscaling.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSSCALING_H
-#define QWINDOWSSCALING_H
-
-#include <QtGui/QRegion>
-#include <QtCore/QVector>
-#include <QtCore/QRect>
-
-QT_BEGIN_NAMESPACE
-
-enum
-#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
- : int
-#endif
-{ QWINDOWSIZE_MAX = 16777215 };
-
-class QWindowsScaling {
-public:
- static bool isActive() { return m_factor > 1; }
- static int factor() { return m_factor; }
- static void setFactor(int factor) { m_factor = factor; }
- static int determineUiScaleFactor();
-
- // Scaling helpers for size constraints.
- static int mapToNativeConstrained(int qt)
- { return m_factor != 1 && qt > 0 && qt < QWINDOWSIZE_MAX ? qt * m_factor : qt; }
-
- static int mapFromNativeConstrained(int dp)
- { return m_factor != 1 && dp > 0 && dp < QWINDOWSIZE_MAX ? dp / m_factor : dp; }
-
- static QSize mapToNativeConstrained(const QSize &qt)
- { return QSize(mapToNativeConstrained(qt.width()), mapToNativeConstrained(qt.height())); }
-
- static QRect mapToNative(const QRect &qRect)
- {
- return QRect(qRect.x() * m_factor, qRect.y() * m_factor, qRect.width() * m_factor, qRect.height() * m_factor);
- }
-
- static QRect mapFromNative(const QRect &dp)
- {
- return isActive() ?
- QRect(dp.x() / m_factor, dp.y() / m_factor, (dp.width() + 1) / m_factor, (dp.height() + 1) / m_factor) :
- dp;
- }
-
- static QRegion mapToNative(const QRegion &regionQt)
- {
- if (!QWindowsScaling::isActive() || regionQt.isEmpty())
- return regionQt;
-
- QRegion result;
- foreach (const QRect &rectQt, regionQt.rects())
- result += QWindowsScaling::mapToNative(rectQt);
- return result;
- }
-
- static QRegion mapFromNative(const QRegion &regionDp)
- {
- if (!QWindowsScaling::isActive() || regionDp.isEmpty())
- return regionDp;
-
- QRegion result;
- foreach (const QRect &rectDp, regionDp.rects())
- result += QWindowsScaling::mapFromNative(rectDp);
- return result;
- }
-
-private:
- static int m_factor;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSSCALING_H
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 7756c77001..e69665e4a9 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -43,6 +43,7 @@
#include <QtGui/QPixmap>
#include <QtGui/QGuiApplication>
#include <qpa/qwindowsysteminterface.h>
+#include <private/qhighdpiscaling_p.h>
#include <QtGui/QScreen>
#include <QtCore/QDebug>
@@ -171,6 +172,7 @@ static inline WindowsScreenDataList monitorData()
return result;
}
+#ifndef QT_NO_DEBUG_STREAM
static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
{
QDebugStateSaver saver(dbg);
@@ -191,16 +193,7 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
dbg << " lock screen";
return dbg;
}
-
-// Return the cursor to be shared by all screens (virtual desktop).
-static inline QSharedPointer<QPlatformCursor> sharedCursor()
-{
-#ifndef QT_NO_CURSOR
- if (const QScreen *primaryScreen = QGuiApplication::primaryScreen())
- return static_cast<const QWindowsScreen *>(primaryScreen->handle())->cursorPtr();
-#endif
- return QSharedPointer<QPlatformCursor>(new QWindowsCursor);
-}
+#endif // !QT_NO_DEBUG_STREAM
/*!
\class QWindowsScreen
@@ -213,41 +206,19 @@ static inline QSharedPointer<QPlatformCursor> sharedCursor()
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
m_data(data)
#ifndef QT_NO_CURSOR
- ,m_cursor(sharedCursor())
+ , m_cursor(new QWindowsCursor(this))
#endif
{
}
-BOOL QT_WIN_CALLBACK monitorResolutionEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM p)
-{
- QWindowsScreenData data;
- if (monitorData(hMonitor, &data)) {
- int *maxHorizResolution = reinterpret_cast<int *>(p);
- const int horizResolution = qRound(data.dpi.first);
- if (horizResolution > *maxHorizResolution)
- *maxHorizResolution = horizResolution;
- }
- return TRUE;
-}
-
-int QWindowsScreen::maxMonitorHorizResolution()
-{
- int result = 0;
- EnumDisplayMonitors(0, 0, monitorResolutionEnumCallback, (LPARAM)&result);
- return result;
-}
-
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
-QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const
+QPixmap QWindowsScreen::grabWindow(WId window, int x, int y, int width, int height) const
{
RECT r;
HWND hwnd = window ? (HWND)window : GetDesktopWindow();
GetClientRect(hwnd, &r);
- const int x = qX * QWindowsScaling::factor();
- const int y = qY * QWindowsScaling::factor();
- int width = qWidth * QWindowsScaling::factor();
- int height = qHeight * QWindowsScaling::factor();
+
if (width < 0) width = r.right - r.left;
if (height < 0) height = r.bottom - r.top;
@@ -271,10 +242,6 @@ QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int q
DeleteObject(bitmap);
ReleaseDC(0, display_dc);
- if (QWindowsScaling::isActive()) {
- const qreal factor = 1.0 / qreal(QWindowsScaling::factor());
- return pixmap.transformed(QTransform::fromScale(factor, factor));
- }
return pixmap;
}
@@ -285,7 +252,7 @@ QPixmap QWindowsScreen::grabWindow(WId window, int qX, int qY, int qWidth, int q
QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const
{
QWindow *result = 0;
- if (QWindow *child = QWindowsScreen::windowAt(point * QWindowsScaling::factor(), CWP_SKIPINVISIBLE))
+ if (QWindow *child = QWindowsScreen::windowAt(point, CWP_SKIPINVISIBLE))
result = QWindowsWindow::topLevelOf(child);
qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result;
return result;
@@ -301,16 +268,13 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
return result;
}
-QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w)
+qreal QWindowsScreen::pixelDensity() const
{
- if (w)
- if (const QScreen *s = w->screen())
- if (QPlatformScreen *pscr = s->handle())
- return static_cast<QWindowsScreen *>(pscr);
- if (const QScreen *ps = QGuiApplication::primaryScreen())
- if (QPlatformScreen *ppscr = ps->handle())
- return static_cast<QWindowsScreen *>(ppscr);
- return 0;
+ // QTBUG-49195: Use logical DPI instead of physical DPI to calculate
+ // the pixel density since it is reflects the Windows UI scaling.
+ // High DPI auto scaling should be disabled when the user chooses
+ // small fonts on a High DPI monitor, resulting in lower logical DPI.
+ return qRound(logicalDpi().first / 96);
}
/*!
@@ -542,7 +506,7 @@ void QWindowsScreenManager::clearScreens()
const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const
{
foreach (QWindowsScreen *scr, m_screens) {
- if (scr->geometryDp().contains(p))
+ if (scr->geometry().contains(p))
return scr;
}
return Q_NULLPTR;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 7352c45777..879cda047e 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -34,7 +34,6 @@
#ifndef QWINDOWSSCREEN_H
#define QWINDOWSSCREEN_H
-#include "qwindowsscaling.h"
#include "qtwindowsglobal.h"
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
@@ -43,7 +42,7 @@
#include <QtCore/QList>
#include <QtCore/QVector>
#include <QtCore/QPair>
-#include <QtCore/QSharedPointer>
+#include <QtCore/QScopedPointer>
#include <qpa/qplatformscreen.h>
QT_BEGIN_NAMESPACE
@@ -75,23 +74,19 @@ class QWindowsScreen : public QPlatformScreen
{
public:
#ifndef QT_NO_CURSOR
- typedef QSharedPointer<QPlatformCursor> CursorPtr;
+ typedef QScopedPointer<QPlatformCursor> CursorPtr;
#endif
explicit QWindowsScreen(const QWindowsScreenData &data);
- static QWindowsScreen *screenOf(const QWindow *w = 0);
-
- QRect geometryDp() const { return m_data.geometry; }
- QRect geometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(geometryDp()); }
- QRect availableGeometryDp() const { return m_data.availableGeometry; }
- QRect availableGeometry() const Q_DECL_OVERRIDE { return QWindowsScaling::mapFromNative(availableGeometryDp()); }
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
+ QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; }
QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; }
- QDpi logicalDpi() const Q_DECL_OVERRIDE
- { return QDpi(m_data.dpi.first / QWindowsScaling::factor(), m_data.dpi.second / QWindowsScaling::factor()); }
- qreal devicePixelRatio() const Q_DECL_OVERRIDE { return QWindowsScaling::factor(); }
+ QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; }
+ qreal pixelDensity() const Q_DECL_OVERRIDE;
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE { return 1.0; }
qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
QString name() const Q_DECL_OVERRIDE { return m_data.name; }
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
@@ -112,7 +107,6 @@ public:
#endif // !QT_NO_CURSOR
const QWindowsScreenData &data() const { return m_data; }
- static int maxMonitorHorizResolution();
private:
QWindowsScreenData m_data;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 7b871be015..b27811df9e 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -32,7 +32,6 @@
****************************************************************************/
#include "qwindowstabletsupport.h"
-#include "qwindowsscaling.h"
#ifndef QT_NO_TABLETEVENT
@@ -55,7 +54,7 @@
#include <QtCore/private/qsystemlibrary_p.h>
// Note: The definition of the PACKET structure in pktdef.h depends on this define.
-#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z | PK_TIME)
#include <pktdef.h>
QT_BEGIN_NAMESPACE
@@ -303,8 +302,11 @@ static inline QTabletEvent::PointerType pointerType(unsigned currentCursor)
return QTabletEvent::UnknownPointer;
}
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
{
+ QDebugStateSaver saver(d);
+ d.nospace();
d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
<< ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
<< t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ
@@ -312,6 +314,7 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
<< " pointer " << t.currentPointerType;
return d;
}
+#endif // !QT_NO_DEBUG_STREAM
QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueId, const UINT cursorType) const
{
@@ -343,17 +346,18 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueI
bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam)
{
+ PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
+ const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
+ if (!totalPacks)
+ return false;
if (!LOWORD(lParam)) {
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
- QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
}
- PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
- const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
- if (!totalPacks)
- return false;
const UINT currentCursor = proximityBuffer[0].pkCursor;
UINT physicalCursorId;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
@@ -371,7 +375,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
qCDebug(lcQpaTablet) << "enter proximity for device #"
<< m_currentDevice << m_devices.at(m_currentDevice);
- QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
@@ -399,8 +404,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
// in which case we snap the position to the mouse position.
// It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext
// area is always the virtual desktop.
- const QRect virtualDesktopArea
- = QWindowsScaling::mapToNative(QGuiApplication::primaryScreen()->virtualGeometry());
+ const QRect virtualDesktopArea = QGuiApplication::primaryScreen()->virtualGeometry();
qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount
<< "target:" << QGuiApplicationPrivate::tabletPressTarget;
@@ -420,7 +424,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
QPoint globalPos = globalPosF.toPoint();
// Get Mouse Position and compare to tablet info
- QPoint mouseLocation = QWindowsCursor::mousePosition();
+ const QPoint mouseLocation = QWindowsCursor::mousePosition();
// Positions should be almost the same if we are in absolute
// mode. If they are not, use the mouse location.
@@ -475,9 +479,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- const QPointF localPosDip = QPointF(localPos / QWindowsScaling::factor());
- const QPointF globalPosDip = globalPosF / qreal(QWindowsScaling::factor());
- QWindowSystemInterface::handleTabletEvent(target, localPosDip, globalPosDip,
+ QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index 718ae98572..a6d2771206 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -97,7 +97,9 @@ struct QWindowsTabletDeviceData
int currentPointerType;
};
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t);
+#endif
class QWindowsTabletSupport
{
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index d3f67e9eaa..877bdfec17 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -43,7 +43,6 @@
#include "qwindowsintegration.h"
#include "qt_windows.h"
#include "qwindowsfontdatabase.h"
-#include "qwindowsscaling.h"
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
# include "winuser.h"
@@ -68,6 +67,7 @@
#include <QtGui/QPainter>
#include <QtGui/QPixmapCache>
#include <qpa/qwindowsysteminterface.h>
+#include <private/qhighdpiscaling_p.h>
#include <private/qsystemlibrary_p.h>
#include <algorithm>
@@ -393,6 +393,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false));
case ContextMenuOnMouseRelease:
return QVariant(true);
+ case WheelScrollLines:
+ return dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3);
default:
break;
}
@@ -495,7 +497,8 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
{
- const int scaleFactor = QWindowsScaling::factor();
+ const QScreen *primaryScreen = QGuiApplication::primaryScreen();
+ const int scaleFactor = primaryScreen ? qRound(QHighDpiScaling::factor(primaryScreen)) : 1;
const QSizeF pixmapSize = size * scaleFactor;
int resourceId = -1;
LPCTSTR iconName = 0;
@@ -632,7 +635,7 @@ public:
static FakePointer *create(T thing)
{
- return reinterpret_cast<FakePointer *>(thing);
+ return reinterpret_cast<FakePointer *>(qintptr(thing));
}
T operator * () const
@@ -720,6 +723,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
iconSize|SHGFI_SYSICONINDEX;
#endif // Q_OS_WINCE
unsigned long val = 0;
+#if !defined(QT_NO_WINCE_SHELLSDK)
if (cacheableDirIcon && useDefaultFolderIcon) {
flags |= SHGFI_USEFILEATTRIBUTES;
val = SHGetFileInfo(L"dummy",
@@ -729,6 +733,7 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s
val = SHGetFileInfo(reinterpret_cast<const wchar_t *>(filePath.utf16()), 0,
&info, sizeof(SHFILEINFO), flags);
}
+#endif // !QT_NO_WINCE_SHELLSDK
// Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
if (val && info.hIcon) {
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 288f73cb8f..c49682cc26 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -36,7 +36,6 @@
#include "qwindowscontext.h"
#include "qwindowsdrag.h"
#include "qwindowsscreen.h"
-#include "qwindowsscaling.h"
#include "qwindowsintegration.h"
#include "qwindowsopenglcontext.h"
#ifdef QT_NO_CURSOR
@@ -49,8 +48,9 @@
#include <QtGui/QRegion>
#include <QtGui/QOpenGLContext>
#include <private/qsystemlibrary_p.h>
-#include <private/qwindow_p.h>
+#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
#include <private/qguiapplication_p.h>
+#include <private/qhighdpiscaling_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QDebug>
@@ -106,20 +106,6 @@ static QByteArray debugWinExStyle(DWORD exStyle)
return rc;
}
-#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO
-QDebug operator<<(QDebug d, const MINMAXINFO &i)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ','
- << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x
- << ',' << i.ptMaxPosition.y << " mintrack="
- << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y
- << " maxtrack=" << i.ptMaxTrackSize.x << ',' << i.ptMaxTrackSize.y;
- return d;
-}
-#endif // !Q_OS_WINCE
-
static inline QSize qSizeOfRect(const RECT &rect)
{
return QSize(rect.right -rect.left, rect.bottom - rect.top);
@@ -138,6 +124,7 @@ static inline RECT RECTfromQRect(const QRect &rect)
return result;
}
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const RECT &r)
{
QDebugStateSaver saver(d);
@@ -147,7 +134,13 @@ QDebug operator<<(QDebug d, const RECT &r)
return d;
}
-#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_NCCALCSIZE
+QDebug operator<<(QDebug d, const POINT &p)
+{
+ d << p.x << ',' << p.y;
+ return d;
+}
+
+# ifndef Q_OS_WINCE
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
{
QDebugStateSaver saver(d);
@@ -156,7 +149,30 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
<< ' ' << qrectFromRECT(p.rgrc[1]) << ' ' << qrectFromRECT(p.rgrc[2]);
return d;
}
-#endif // !Q_OS_WINCE
+
+QDebug operator<<(QDebug d, const MINMAXINFO &i)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "MINMAXINFO maxSize=" << i.ptMaxSize.x << ','
+ << i.ptMaxSize.y << " maxpos=" << i.ptMaxPosition.x
+ << ',' << i.ptMaxPosition.y << " mintrack="
+ << i.ptMinTrackSize.x << ',' << i.ptMinTrackSize.y
+ << " maxtrack=" << i.ptMaxTrackSize.x << ',' << i.ptMaxTrackSize.y;
+ return d;
+}
+
+QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd="
+ << wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition
+ << ", rcNormalPosition=" << wp.rcNormalPosition;
+ return d;
+}
+# endif // !Q_OS_WINCE
+#endif // !QT_NO_DEBUG_STREAM
// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT
// is in workspace/available area coordinates.
@@ -169,7 +185,7 @@ static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
const QWindowsScreen *screen = screenManager.screens().size() == 1
? screenManager.screens().first() : screenManager.screenAtDp(point);
if (screen)
- return screen->availableGeometryDp().topLeft() - screen->geometryDp().topLeft();
+ return screen->availableGeometry().topLeft() - screen->geometry().topLeft();
#else
Q_UNUSED(hwnd)
Q_UNUSED(point)
@@ -608,9 +624,7 @@ QWindowsWindowData
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);
- const QRect geometryDip = QWindowsScaling::mapFromNative(data.geometry);
- QRect fixedGeometryDip = QPlatformWindow::initialGeometry(w, geometryDip, defaultWindowWidth, defaultWindowHeight);
- const QRect rect = fixedGeometryDip != geometryDip ? QWindowsScaling::mapToNative(fixedGeometryDip) : data.geometry;
+ const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry, defaultWindowWidth, defaultWindowHeight);
if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
title = topLevel ? qAppName() : w->objectName();
@@ -706,6 +720,20 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang
}
}
+
+// Scaling helpers for size constraints.
+static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
+{
+ if (QHighDpiScaling::isActive()) {
+ const qreal factor = QHighDpiScaling::factor(w);
+ if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
+ dip.rwidth() *= factor;
+ if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
+ dip.rheight() *= factor;
+ }
+ return dip;
+}
+
/*!
\class QWindowsGeometryHint
\brief Stores geometry constraints and provides utility functions.
@@ -718,8 +746,8 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang
*/
QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
- minimumSize(QWindowsScaling::mapToNativeConstrained(w->minimumSize())),
- maximumSize(QWindowsScaling::mapToNativeConstrained(w->maximumSize())),
+ minimumSize(toNativeSizeConstrained(w->minimumSize(), w)),
+ maximumSize(toNativeSizeConstrained(w->maximumSize(), w)),
customMargins(cm)
{
}
@@ -900,6 +928,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_hdc(0),
m_windowState(Qt::WindowNoState),
m_opacity(1.0),
+ m_cursor(new CursorHandle),
m_dropTarget(0),
m_savedStyle(0),
m_format(aWindow->requestedFormat()),
@@ -953,8 +982,7 @@ void QWindowsWindow::fireExpose(const QRegion &region, bool force)
clearFlag(Exposed);
else
setFlag(Exposed);
- QWindowSystemInterface::handleExposeEvent(window(),
- QWindowsScaling::mapFromNative(region));
+ QWindowSystemInterface::handleExposeEvent(window(), region);
}
static inline QWindow *findTransientChild(const QWindow *parent)
@@ -1051,7 +1079,7 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w)
if (const QPlatformWindow *handle = w->handle()) {
const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(handle);
- if (ww->isEmbedded(0)) {
+ if (ww->isEmbedded()) {
HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
const HWND desktopHwnd = GetDesktopWindow();
const QWindowsContext *ctx = QWindowsContext::instance();
@@ -1129,12 +1157,12 @@ bool QWindowsWindow::isEmbedded(const QPlatformWindow *parentWindow) const
}
if (!m_data.embedded && parent())
- return parent()->isEmbedded(0);
+ return parent()->isEmbedded();
return m_data.embedded;
}
-QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const
+QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos);
@@ -1142,7 +1170,7 @@ QPoint QWindowsWindow::mapToGlobalDp(const QPoint &pos) const
return pos;
}
-QPoint QWindowsWindow::mapFromGlobalDp(const QPoint &pos) const
+QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const
{
if (m_data.hwnd)
return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos);
@@ -1323,22 +1351,22 @@ static QRect normalFrameGeometry(HWND hwnd)
return QRect();
}
-QRect QWindowsWindow::normalGeometryDp() const
+QRect QWindowsWindow::normalGeometry() const
{
// Check for fake 'fullscreen' mode.
const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen;
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
- const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMarginsDp();
+ const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
-void QWindowsWindow::setGeometryDp(const QRect &rectIn)
+void QWindowsWindow::setGeometry(const QRect &rectIn)
{
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePosition() and
// the coordinates include the frame (size is still the contents rectangle).
if (QWindowsGeometryHint::positionIncludesFrame(window())) {
- const QMargins margins = frameMarginsDp();
+ const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
if (m_windowState == Qt::WindowMinimized)
@@ -1407,9 +1435,8 @@ void QWindowsWindow::handleGeometryChange()
return;
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
- const QRect geometryDip = QWindowsScaling::mapFromNative(m_data.geometry);
- QPlatformWindow::setGeometry(geometryDip);
- QWindowSystemInterface::handleGeometryChange(window(), geometryDip);
+ QPlatformWindow::setGeometry(m_data.geometry);
+ QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
if (!testFlag(OpenGL_ES2) && isExposed()
@@ -1417,7 +1444,7 @@ void QWindowsWindow::handleGeometryChange()
fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
}
if (previousGeometry.topLeft() != m_data.geometry.topLeft()) {
- QPlatformScreen *newScreen = screenForGeometry(geometryDip);
+ QPlatformScreen *newScreen = screenForGeometry(m_data.geometry);
if (newScreen != screen())
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
@@ -1429,7 +1456,7 @@ void QWindowsWindow::handleGeometryChange()
void QWindowsWindow::setGeometry_sys(const QRect &rect) const
{
- const QMargins margins = frameMarginsDp();
+ const QMargins margins = frameMargins();
const QRect frameGeometry = rect + margins;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << window()
@@ -1468,7 +1495,7 @@ QRect QWindowsWindow::frameGeometry_sys() const
QRect QWindowsWindow::geometry_sys() const
{
- return frameGeometry_sys().marginsRemoved(frameMarginsDp());
+ return frameGeometry_sys().marginsRemoved(frameMargins());
}
/*!
@@ -1540,7 +1567,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
{
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: "
<< m_data.flags << "\n to: " << flags;
- const QRect oldGeometry = geometryDp();
+ const QRect oldGeometry = geometry();
if (m_data.flags != flags) {
m_data.flags = flags;
if (m_data.hwnd) {
@@ -1626,8 +1653,13 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
bool QWindowsWindow::isFullScreen_sys() const
{
- return window()->isTopLevel()
- && geometry_sys() == QWindowsScaling::mapToNative(window()->screen()->geometry());
+ const QWindow *w = window();
+ if (!w->isTopLevel())
+ return false;
+ const QScreen *screen = w->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ return screen && geometry_sys() == QHighDpi::toNativePixels(screen->geometry(), w);
}
/*!
@@ -1697,15 +1729,16 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
const QScreen *screen = window()->screen();
- const QRect rDip = screen->geometry();
- const QRect r = QWindowsScaling::mapToNative(rDip);
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
- QWindowSystemInterface::handleGeometryChange(window(), rDip);
+ QWindowSystemInterface::handleGeometryChange(window(), r);
QWindowSystemInterface::flushWindowSystemEvents();
} else if (newState != Qt::WindowMinimized) {
// Restore saved state.
@@ -1804,7 +1837,7 @@ void QWindowsWindow::propagateSizeHints()
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window();
}
-bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp)
+bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins)
{
#ifndef Q_OS_WINCE
if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
@@ -1812,26 +1845,19 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
if ((windowPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE)))
return false;
- const QRect suggestedFrameGeometryDp(windowPos->x, windowPos->y,
- windowPos->cx, windowPos->cy);
- const qreal factor = QWindowsScaling::factor();
- const QRect suggestedGeometryDp = suggestedFrameGeometryDp - marginsDp;
- const QRectF suggestedGeometry = QRectF(QPointF(suggestedGeometryDp.topLeft()) / factor,
- QSizeF(suggestedGeometryDp.size()) / factor);
- const QRectF correctedGeometryF =
- qt_window_private(const_cast<QWindow *>(qWindow))->closestAcceptableGeometry(suggestedGeometry);
+ const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
+ windowPos->cx, windowPos->cy);
+ const QRect suggestedGeometry = suggestedFrameGeometry - margins;
+ const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
if (!correctedGeometryF.isValid())
return false;
- const QRect correctedFrameGeometryDp
- = QRectF(correctedGeometryF.topLeft() * factor,
- correctedGeometryF.size() * factor).toRect()
- + marginsDp;
- if (correctedFrameGeometryDp == suggestedFrameGeometryDp)
+ const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;
+ if (correctedFrameGeometry == suggestedFrameGeometry)
return false;
- windowPos->x = correctedFrameGeometryDp.left();
- windowPos->y = correctedFrameGeometryDp.top();
- windowPos->cx = correctedFrameGeometryDp.width();
- windowPos->cy = correctedFrameGeometryDp.height();
+ windowPos->x = correctedFrameGeometry.left();
+ windowPos->y = correctedFrameGeometry.top();
+ windowPos->cx = correctedFrameGeometry.width();
+ windowPos->cy = correctedFrameGeometry.height();
return true;
#else // !Q_OS_WINCE
Q_UNUSED(message)
@@ -1841,11 +1867,11 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
bool QWindowsWindow::handleGeometryChanging(MSG *message) const
{
- const QMargins marginsDp = window()->isTopLevel() ? frameMarginsDp() : QMargins();
- return QWindowsWindow::handleGeometryChangingMessage(message, window(), marginsDp);
+ const QMargins margins = window()->isTopLevel() ? frameMargins() : QMargins();
+ return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins);
}
-QMargins QWindowsWindow::frameMarginsDp() const
+QMargins QWindowsWindow::frameMargins() const
{
// Frames are invalidated by style changes (window state, flags).
// As they are also required for geometry calculations in resize
@@ -1892,17 +1918,17 @@ static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion)
}
}
-static HRGN qRegionToWinRegion(const QRegion &regionDip)
+static HRGN qRegionToWinRegion(const QRegion &region)
{
- const QVector<QRect> rects = regionDip.rects();
+ const QVector<QRect> rects = region.rects();
if (rects.isEmpty())
return NULL;
const int rectCount = rects.size();
if (rectCount == 1)
- return createRectRegion(QWindowsScaling::mapToNative(regionDip.boundingRect()));
- HRGN hRegion = createRectRegion(QWindowsScaling::mapToNative(rects.front()));
+ return createRectRegion(region.boundingRect());
+ HRGN hRegion = createRectRegion(rects.front());
for (int i = 1; i < rectCount; ++i)
- addRectToWinRegion(QWindowsScaling::mapToNative(rects.at(i)), &hRegion);
+ addRectToWinRegion(rects.at(i), &hRegion);
return hRegion;
}
@@ -1916,7 +1942,7 @@ void QWindowsWindow::setMask(const QRegion &region)
// Mask is in client area coordinates, so offset it in case we have a frame
if (window()->isTopLevel()) {
- const QMargins margins = frameMarginsDp();
+ const QMargins margins = frameMargins();
OffsetRgn(winRegion, margins.left(), margins.top());
}
@@ -2053,23 +2079,23 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
|| (m_data.flags & Qt::FramelessWindowHint)) {
return false;
}
- const QSize minimumSize = QWindowsScaling::mapToNativeConstrained(w->minimumSize());
+ const QSize minimumSize = w->minimumSize();
if (minimumSize.isEmpty())
return false;
- const QSize maximumSize = QWindowsScaling::mapToNativeConstrained(w->maximumSize());
+ const QSize maximumSize = w->maximumSize();
const bool fixedWidth = minimumSize.width() == maximumSize.width();
const bool fixedHeight = minimumSize.height() == maximumSize.height();
if (!fixedWidth && !fixedHeight)
return false;
- const QPoint localPos = mapFromGlobalDp(globalPos);
- const QSize size = w->size() * QWindowsScaling::factor();
+ const QPoint localPos = w->mapFromGlobal(QHighDpi::fromNativePixels(globalPos, w));
+ const QSize size = w->size();
if (fixedHeight) {
if (localPos.y() >= size.height()) {
*result = HTBORDER; // Unspecified border, no resize cursor.
return true;
}
if (localPos.y() < 0) {
- const QMargins margins = frameMarginsDp();
+ const QMargins margins = frameMargins();
const int topResizeBarPos = margins.left() - margins.top();
if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
@@ -2088,13 +2114,13 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
#ifndef QT_NO_CURSOR
// Return the default cursor (Arrow) from QWindowsCursor's cache.
-static inline QWindowsWindowCursor defaultCursor(const QWindow *w)
+static inline CursorHandlePtr defaultCursor(const QWindow *w)
{
if (QScreen *screen = w->screen())
if (const QPlatformScreen *platformScreen = screen->handle())
if (QPlatformCursor *cursor = platformScreen->cursor())
return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
- return QWindowsWindowCursor(Qt::ArrowCursor);
+ return CursorHandlePtr(new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor)));
}
// Check whether to apply a new cursor. Either the window in question is
@@ -2108,7 +2134,7 @@ static inline bool applyNewCursor(const QWindow *w)
for (const QWindow *p = underMouse; p ; p = p->parent()) {
if (p == w)
return true;
- if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull())
+ if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull())
return false;
}
return false;
@@ -2124,25 +2150,25 @@ static inline bool applyNewCursor(const QWindow *w)
void QWindowsWindow::applyCursor()
{
#ifndef QT_NO_CURSOR
- if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
+ if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
QWindowsWindow::baseWindowOf(p)->applyCursor();
} else {
- SetCursor(defaultCursor(window()).handle());
+ SetCursor(defaultCursor(window())->handle());
}
} else {
- SetCursor(m_cursor.handle());
+ SetCursor(m_cursor->handle());
}
#endif
}
-void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
+void QWindowsWindow::setCursor(const CursorHandlePtr &c)
{
#ifndef QT_NO_CURSOR
- if (c.handle() != m_cursor.handle()) {
+ if (c->handle() != m_cursor->handle()) {
const bool apply = applyNewCursor(window());
qCDebug(lcQpaWindows) << window() << __FUNCTION__
- << c.cursor().shape() << " doApply=" << apply;
+ << c->handle() << " doApply=" << apply;
m_cursor = c;
if (apply)
applyCursor();
@@ -2245,10 +2271,6 @@ void QWindowsWindow::setWindowIcon(const QIcon &icon)
The property can be set using QPlatformNativeInterface::setWindowProperty() or,
before platform window creation, by setting a dynamic property
on the QWindow (see QWindowsIntegration::createPlatformWindow()).
-
- Note: The function uses (unscaled) device pixels since the QWizard also
- uses AdjustWindowRect() and using device independent pixels would introduce
- rounding errors.
*/
void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index fff90b4b11..4172a3d850 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -38,7 +38,6 @@
#ifdef Q_OS_WINCE
# include "qplatformfunctions_wince.h"
#endif
-#include "qwindowsscaling.h"
#include "qwindowscursor.h"
#include <qpa/qplatformwindow.h>
@@ -144,29 +143,21 @@ public:
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsWindow();
+ using QPlatformWindow::screenForGeometry;
+
QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- void setGeometryDp(const QRect &rectIn);
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE
- { setGeometryDp(QWindowsScaling::mapToNative(rect)); }
- QRect geometryDp() const { return m_data.geometry; }
- QRect geometry() const Q_DECL_OVERRIDE
- { return QWindowsScaling::mapFromNative(geometryDp()); }
- QRect normalGeometryDp() const;
- QRect normalGeometry() const Q_DECL_OVERRIDE
- { return QWindowsScaling::mapFromNative(normalGeometryDp()); }
- qreal devicePixelRatio() const Q_DECL_OVERRIDE
- { return qreal(QWindowsScaling::factor()); }
+ void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
+ QRect normalGeometry() const Q_DECL_OVERRIDE;
+
void setVisible(bool visible) Q_DECL_OVERRIDE;
bool isVisible() const;
bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
bool isActive() const Q_DECL_OVERRIDE;
- bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
- QPoint mapToGlobalDp(const QPoint &pos) const;
- QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
- { return mapToGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
- QPoint mapFromGlobalDp(const QPoint &pos) const;
- QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE
- { return mapFromGlobalDp(pos * QWindowsScaling::factor()) / QWindowsScaling::factor(); }
+ bool isEmbedded(const QPlatformWindow *parentWindow = 0) const Q_DECL_OVERRIDE;
+ QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+ QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
@@ -184,8 +175,7 @@ public:
void propagateSizeHints() Q_DECL_OVERRIDE;
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp);
bool handleGeometryChanging(MSG *message) const;
- QMargins frameMarginsDp() const;
- QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMarginsDp() / QWindowsScaling::factor(); }
+ QMargins frameMargins() const Q_DECL_OVERRIDE;
void setOpacity(qreal level) Q_DECL_OVERRIDE;
void setMask(const QRegion &region) Q_DECL_OVERRIDE;
@@ -196,7 +186,7 @@ public:
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- bool startSystemResize(const QPoint &, Qt::Corner corner) Q_DECL_OVERRIDE;
+ bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
@@ -235,9 +225,9 @@ public:
#endif // !Q_OS_WINCE
#ifndef QT_NO_CURSOR
- QWindowsWindowCursor cursor() const { return m_cursor; }
+ CursorHandlePtr cursor() const { return m_cursor; }
#endif
- void setCursor(const QWindowsWindowCursor &c);
+ void setCursor(const CursorHandlePtr &c);
void applyCursor();
inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; }
@@ -288,7 +278,7 @@ private:
Qt::WindowState m_windowState;
qreal m_opacity;
#ifndef QT_NO_CURSOR
- QWindowsWindowCursor m_cursor;
+ CursorHandlePtr m_cursor;
#endif
QWindowsOleDropTarget *m_dropTarget;
unsigned m_savedStyle;
@@ -302,12 +292,15 @@ private:
void *m_surface;
};
-// Debug
+#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const RECT &r);
-#ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO/WM_NCCALCSIZE
+QDebug operator<<(QDebug d, const POINT &);
+# ifndef Q_OS_WINCE
QDebug operator<<(QDebug d, const MINMAXINFO &i);
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p);
-#endif
+QDebug operator<<(QDebug d, const WINDOWPLACEMENT &);
+# endif // !Q_OS_WINCE
+#endif // !QT_NO_DEBUG_STREAM
// ---------- QWindowsGeometryHint inline functions.
QPoint QWindowsGeometryHint::mapToGlobal(HWND hwnd, const QPoint &qp)
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index de901aaeb1..29297116da 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -29,7 +29,6 @@ SOURCES += \
$$PWD/qwindowsfontengine.cpp \
$$PWD/qwindowsfontdatabase.cpp \
$$PWD/qwindowsmousehandler.cpp \
- $$PWD/qwindowsguieventdispatcher.cpp \
$$PWD/qwindowsole.cpp \
$$PWD/qwindowsmime.cpp \
$$PWD/qwindowsinternalmimedata.cpp \
@@ -40,7 +39,6 @@ SOURCES += \
$$PWD/qwindowsservices.cpp \
$$PWD/qwindowsnativeimage.cpp \
$$PWD/qwindowsnativeinterface.cpp \
- $$PWD/qwindowsscaling.cpp \
$$PWD/qwindowsopengltester.cpp
HEADERS += \
@@ -52,7 +50,6 @@ HEADERS += \
$$PWD/qwindowsfontengine.h \
$$PWD/qwindowsfontdatabase.h \
$$PWD/qwindowsmousehandler.h \
- $$PWD/qwindowsguieventdispatcher.h \
$$PWD/qtwindowsglobal.h \
$$PWD/qtwindows_additional.h \
$$PWD/qwindowsole.h \
@@ -67,7 +64,6 @@ HEADERS += \
$$PWD/qplatformfunctions_wince.h \
$$PWD/qwindowsnativeimage.h \
$$PWD/qwindowsnativeinterface.h \
- $$PWD/qwindowsscaling.h \
$$PWD/qwindowsopengltester.h
INCLUDEPATH += $$PWD
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
index dcf8239538..4517200a2d 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -42,8 +42,8 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFramebufferObject>
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
QT_BEGIN_NAMESPACE
@@ -66,7 +66,8 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
d->initialized = false;
d->screen = static_cast<QWinRTScreen*>(window->screen()->handle());
- window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap
+ if (window->surfaceType() == QSurface::RasterSurface)
+ window->setSurfaceType(QSurface::OpenGLSurface);
}
bool QWinRTBackingStore::initialize()
@@ -78,7 +79,6 @@ bool QWinRTBackingStore::initialize()
d->context.reset(new QOpenGLContext);
QSurfaceFormat format = window()->requestedFormat();
- format.setVersion(3, 0); // Required for ES3 framebuffer blit
d->context->setFormat(format);
d->context->setScreen(window()->screen());
if (!d->context->create())
@@ -121,13 +121,13 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPo
GL_RGBA, GL_UNSIGNED_BYTE, d->paintDevice.constScanLine(bounds.y()));
glBindTexture(GL_TEXTURE_2D, 0);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, d->fbo->handle());
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, d->fbo->handle());
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
const int y1 = bounds.y();
const int y2 = y1 + bounds.height();
const int x1 = bounds.x();
const int x2 = x1 + bounds.width();
- glBlitFramebuffer(x1, y1, x2, y2,
+ glBlitFramebufferANGLE(x1, y1, x2, y2,
x1, d->size.height() - y1, x2, d->size.height() - y2,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index 94ce23bd2c..1a511f103f 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -36,11 +36,13 @@
#include "qwinrtcursor.h"
#include "qwinrtscreen.h"
+#include <private/qeventdispatcher_winrt_p.h>
#include <QtCore/qfunctions_winrt.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <functional>
#include <wrl.h>
#include <windows.ui.core.h>
#include <windows.foundation.h>
@@ -77,12 +79,17 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
Q_D(QWinRTCursor);
+ HRESULT hr;
ICoreWindow *coreWindow = static_cast<QWinRTScreen *>(window->screen()->handle())->coreWindow();
CoreCursorType type;
switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
case Qt::BlankCursor:
- coreWindow->put_PointerCursor(Q_NULLPTR);
+ hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow]() {
+ coreWindow->put_PointerCursor(Q_NULLPTR);
+ return S_OK;
+ });
+ RETURN_VOID_IF_FAILED("Failed to set blank native cursor");
return;
default:
case Qt::OpenHandCursor:
@@ -142,21 +149,31 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
}
ComPtr<ICoreCursor> cursor;
- HRESULT hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
+ hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
RETURN_VOID_IF_FAILED("Failed to create native cursor.");
- hr = coreWindow->put_PointerCursor(cursor.Get());
- RETURN_VOID_IF_FAILED("Failed to set native cursor.");
+ hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &cursor]() {
+ return coreWindow->put_PointerCursor(cursor.Get());
+ });
+ RETURN_VOID_IF_FAILED("Failed to set native cursor");
}
#endif // QT_NO_CURSOR
QPoint QWinRTCursor::pos() const
{
- ICoreWindow *coreWindow =
- static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle())->coreWindow();
+ const QWinRTScreen *screen = static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle());
+ Q_ASSERT(screen);
+ ICoreWindow *coreWindow = screen->coreWindow();
+ Q_ASSERT(coreWindow);
Point point;
- coreWindow->get_PointerPosition(&point);
- return QPoint(point.X, point.Y);
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &point]() {
+ return coreWindow->get_PointerPosition(&point);
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+ const QPoint position = QPoint(point.X, point.Y) * screen->scaleFactor();
+ // If no cursor get_PointerPosition returns SHRT_MIN for x and y
+ return position.x() == SHRT_MIN && position.y() == SHRT_MIN || FAILED(hr) ? QPointF(Q_INFINITY, Q_INFINITY).toPoint()
+ : position;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
index 42ffe8f716..3fd0278360 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
@@ -35,40 +35,153 @@
****************************************************************************/
#include "qwinrteglcontext.h"
+#include "qwinrtwindow.h"
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
+
+#include <d3d11.h>
+
+#include <EGL/egl.h>
#define EGL_EGLEXT_PROTOTYPES
-#include "EGL/eglext.h"
+#include <EGL/eglext.h>
+
+#include <QOpenGLContext>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
QT_BEGIN_NAMESPACE
-QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config)
- : QEGLPlatformContext(format, share, display, &config), m_eglSurface(surface)
+struct WinRTEGLDisplay
+{
+ WinRTEGLDisplay() {
+ eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == EGL_NO_DISPLAY)
+ qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
+ }
+ ~WinRTEGLDisplay() {
+ eglTerminate(eglDisplay);
+ }
+
+ EGLDisplay eglDisplay;
+};
+
+Q_GLOBAL_STATIC(WinRTEGLDisplay, g)
+
+class QWinRTEGLContextPrivate
{
+public:
+ QWinRTEGLContextPrivate() : eglContext(EGL_NO_CONTEXT), eglShareContext(EGL_NO_CONTEXT) { }
+ QSurfaceFormat format;
+ EGLConfig eglConfig;
+ EGLContext eglContext;
+ EGLContext eglShareContext;
+};
+
+QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
+ : d_ptr(new QWinRTEGLContextPrivate)
+{
+ Q_D(QWinRTEGLContext);
+ d->format = context->format();
+ d->format.setRenderableType(QSurfaceFormat::OpenGLES);
+ if (QPlatformOpenGLContext *shareHandle = context->shareHandle())
+ d->eglShareContext = static_cast<QWinRTEGLContext *>(shareHandle)->d_ptr->eglContext;
}
-void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface)
+QWinRTEGLContext::~QWinRTEGLContext()
{
-#ifdef Q_OS_WINPHONE
- const QSize size = surface->surface()->size();
- eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface),
- 0, 0, size.width(), size.height());
-#else
- eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface));
-#endif
+ Q_D(QWinRTEGLContext);
+ if (d->eglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(g->eglDisplay, d->eglContext);
}
-EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+void QWinRTEGLContext::initialize()
{
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- // All windows use the same surface
- return m_eglSurface;
- } else {
- // TODO: return EGL surfaces for offscreen surfaces
- qWarning("This plugin does not support offscreen surfaces.");
- return EGL_NO_SURFACE;
+ Q_D(QWinRTEGLContext);
+
+ // Test if the hardware supports at least level 9_3
+ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_9_3 }; // minimum feature level
+ HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 1,
+ D3D11_SDK_VERSION, nullptr, nullptr, nullptr);
+ EGLint deviceType = SUCCEEDED(hr) ? EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE
+ : EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE;
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ const EGLint displayAttributes[] = {
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, true,
+ EGL_NONE,
+ };
+ g->eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes);
+ if (g->eglDisplay == EGL_NO_DISPLAY)
+ qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
+
+ if (!eglInitialize(g->eglDisplay, nullptr, nullptr))
+ qCritical("Failed to initialize EGL: 0x%x", eglGetError());
+
+ d->eglConfig = q_configFromGLFormat(g->eglDisplay, d->format);
+
+ const EGLint flags = d->format.testOption(QSurfaceFormat::DebugContext)
+ ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0;
+ const EGLint attributes[] = {
+ EGL_CONTEXT_CLIENT_VERSION, d->format.majorVersion(),
+ EGL_CONTEXT_MINOR_VERSION_KHR, d->format.minorVersion(),
+ EGL_CONTEXT_FLAGS_KHR, flags,
+ EGL_NONE
+ };
+ d->eglContext = eglCreateContext(g->eglDisplay, d->eglConfig, d->eglShareContext, attributes);
+ if (d->eglContext == EGL_NO_CONTEXT) {
+ qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError());
+ return;
}
}
+bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface)
+{
+ Q_D(QWinRTEGLContext);
+ Q_ASSERT(windowSurface->surface()->supportsOpenGL());
+
+ QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
+ if (window->eglSurface() == EGL_NO_SURFACE)
+ window->createEglSurface(g->eglDisplay, d->eglConfig);
+
+ EGLSurface surface = window->eglSurface();
+ if (surface == EGL_NO_SURFACE)
+ return false;
+
+ const bool ok = eglMakeCurrent(g->eglDisplay, surface, surface, d->eglContext);
+ if (!ok) {
+ qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+ return false;
+ }
+
+ eglSwapInterval(g->eglDisplay, d->format.swapInterval());
+ return true;
+}
+
+void QWinRTEGLContext::doneCurrent()
+{
+ const bool ok = eglMakeCurrent(g->eglDisplay, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+}
+
+void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface)
+{
+ Q_ASSERT(windowSurface->surface()->supportsOpenGL());
+
+ const QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
+ eglSwapBuffers(g->eglDisplay, window->eglSurface());
+}
+
+QSurfaceFormat QWinRTEGLContext::format() const
+{
+ Q_D(const QWinRTEGLContext);
+ return d->format;
+}
+
QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
{
static QHash<QByteArray, QFunctionPointer> standardFuncs;
@@ -221,7 +334,7 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
if (i != standardFuncs.end())
return i.value();
- return QEGLPlatformContext::getProcAddress(procName);
+ return eglGetProcAddress(procName.constData());
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h
index 958d623c4c..31a2124b03 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.h
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.h
@@ -37,23 +37,29 @@
#ifndef QWINDOWSEGLCONTEXT_H
#define QWINDOWSEGLCONTEXT_H
-#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <qpa/qplatformopenglcontext.h>
QT_BEGIN_NAMESPACE
-class QWinRTEGLContext : public QEGLPlatformContext
+class QWinRTEGLContextPrivate;
+class QWinRTEGLContext : public QPlatformOpenGLContext
{
public:
- explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config);
+ explicit QWinRTEGLContext(QOpenGLContext *context);
+ ~QWinRTEGLContext();
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
+ void initialize() Q_DECL_OVERRIDE;
+
+ bool makeCurrent(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
-protected:
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
+ QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
private:
- EGLSurface m_eglSurface;
+ QScopedPointer<QWinRTEGLContextPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTEGLContext)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index e1b2a07d5f..b0f377147e 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -37,25 +37,32 @@
#include "qwinrtfiledialoghelper.h"
#include "qwinrtfileengine.h"
+#include <QtCore/qcoreapplication.h>
#include <QtCore/QEventLoop>
#include <QtCore/QMap>
#include <QtCore/QVector>
#include <QtCore/qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.storage.pickers.h>
+#include <Windows.ApplicationModel.activation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::ApplicationModel::Activation;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::Storage;
using namespace ABI::Windows::Storage::Pickers;
+#ifndef Q_OS_WINPHONE
typedef IAsyncOperationCompletedHandler<StorageFile *> SingleFileHandler;
typedef IAsyncOperationCompletedHandler<IVectorView<StorageFile *> *> MultipleFileHandler;
typedef IAsyncOperationCompletedHandler<StorageFolder *> SingleFolderHandler;
+#endif
QT_BEGIN_NAMESPACE
@@ -142,6 +149,16 @@ private:
QVector<HSTRING> impl;
};
+#ifdef Q_OS_WINPHONE
+class QActivationEvent : public QEvent
+{
+public:
+ IInspectable *args() const {
+ return reinterpret_cast<IInspectable *>(d);
+ }
+};
+#endif
+
template<typename T>
static bool initializePicker(HSTRING runtimeId, T **picker, const QSharedPointer<QFileDialogOptions> &options)
{
@@ -200,6 +217,111 @@ static bool initializeOpenPickerOptions(T *picker, const QSharedPointer<QFileDia
return true;
}
+static bool pickFiles(IFileOpenPicker *picker, QWinRTFileDialogHelper *helper, bool singleFile)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker, singleFile]() {
+ HRESULT hr;
+ ComPtr<IFileOpenPicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast file picker");
+ if (singleFile)
+ return picker2->PickSingleFileAndContinue();
+ else
+ return picker2->PickMultipleFilesAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open file picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+ return true;
+#else
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper, singleFile]() {
+ HRESULT hr;
+ if (singleFile) {
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = picker->PickSingleFileAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to open single file picker");
+ hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
+ RETURN_HR_IF_FAILED("Failed to attach file picker callback");
+ } else {
+ ComPtr<IAsyncOperation<IVectorView<StorageFile *> *>> op;
+ hr = picker->PickMultipleFilesAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to open multi file picker");
+ hr = op->put_Completed(Callback<MultipleFileHandler>(helper, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get());
+ RETURN_HR_IF_FAILED("Failed to attach multi file callback");
+ }
+ return S_OK;
+ });
+ return SUCCEEDED(hr);
+#endif
+}
+
+static bool pickFolder(IFolderPicker *picker, QWinRTFileDialogHelper *helper)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker]() {
+ HRESULT hr;
+ ComPtr<IFolderPicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast folder picker");
+ return picker2->PickFolderAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open folder picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+#else
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<StorageFolder *>> op;
+ hr = picker->PickSingleFolderAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to open folder picker");
+ hr = op->put_Completed(Callback<SingleFolderHandler>(helper, &QWinRTFileDialogHelper::onSingleFolderPicked).Get());
+ RETURN_HR_IF_FAILED("Failed to attach folder picker callback");
+ return S_OK;
+ });
+#endif
+ return SUCCEEDED(hr);
+}
+
+static bool pickSaveFile(IFileSavePicker *picker, QWinRTFileDialogHelper *helper)
+{
+ Q_ASSERT(picker);
+ Q_ASSERT(helper);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker]() {
+ HRESULT hr;
+ ComPtr<IFileSavePicker2> picker2;
+ hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf()));
+ RETURN_HR_IF_FAILED("Failed to cast save file picker");
+ return picker2->PickSaveFileAndContinue();
+ });
+ RETURN_FALSE_IF_FAILED("Failed to open single file picker");
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->installEventFilter(helper);
+#else
+ hr = QEventDispatcherWinRT::runOnXamlThread([picker, helper]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = picker->PickSaveFileAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to open save file picker");
+ hr = op->put_Completed(Callback<SingleFileHandler>(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
+ RETURN_HR_IF_FAILED("Failed to attach save file picker callback");
+ return S_OK;
+ });
+#endif
+ return SUCCEEDED(hr);
+}
+
class QWinRTFileDialogHelperPrivate
{
public:
@@ -260,18 +382,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
return false;
- if (dialogOptions->fileMode() == QFileDialogOptions::ExistingFiles) {
- ComPtr<IAsyncOperation<IVectorView<StorageFile *> *>> op;
- hr = picker->PickMultipleFilesAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open multi file picker");
- hr = op->put_Completed(Callback<MultipleFileHandler>(this, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get());
- } else {
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSingleFileAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open single file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- }
- RETURN_FALSE_IF_FAILED("Failed to attach file picker callback");
+ if (!pickFiles(picker.Get(), this, dialogOptions->fileMode() == QFileDialogOptions::ExistingFile))
+ return false;
+
break;
}
case QFileDialogOptions::Directory:
@@ -284,11 +397,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
if (!initializeOpenPickerOptions(picker.Get(), dialogOptions))
return false;
- ComPtr<IAsyncOperation<StorageFolder *>> op;
- hr = picker->PickSingleFolderAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open folder picker");
- hr = op->put_Completed(Callback<SingleFolderHandler>(this, &QWinRTFileDialogHelper::onSingleFolderPicked).Get());
- RETURN_FALSE_IF_FAILED("Failed to attach folder picker callback");
+ if (!pickFolder(picker.Get(), this))
+ return false;
+
break;
}
}
@@ -324,7 +435,12 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
filterTitle.length());
boolean replaced;
hr = choices->Insert(namedFilterRef.Get(), entry.Get(), &replaced);
- RETURN_FALSE_IF_FAILED("Failed to insert file extension choice entry");
+ // Only print a warning as * or *.* is not a valid choice on Windows 10
+ // but used on a regular basis on all other platforms
+ if (FAILED(hr)) {
+ qWarning("Failed to insert file extension choice entry: %s: %s",
+ qPrintable(filterTitle), qPrintable(qt_error_string(hr)));
+ }
}
}
@@ -344,11 +460,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
}
- ComPtr<IAsyncOperation<StorageFile *>> op;
- hr = picker->PickSaveFileAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to open save file picker");
- hr = op->put_Completed(Callback<SingleFileHandler>(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get());
- RETURN_FALSE_IF_FAILED("Failed to attach file picker callback");
+ if (!pickSaveFile(picker.Get(), this))
+ return false;
+
break;
}
}
@@ -367,6 +481,68 @@ void QWinRTFileDialogHelper::hide()
d->shown = false;
}
+#ifdef Q_OS_WINPHONE
+bool QWinRTFileDialogHelper::eventFilter(QObject *, QEvent *e)
+{
+ if (e->type() != QEvent::WinEventAct)
+ return false;
+
+ HRESULT hr;
+ QActivationEvent *event = static_cast<QActivationEvent *>(e);
+ ComPtr<IInspectable> inspectable = event->args();
+ ComPtr<IActivatedEventArgs> arguments;
+ hr = inspectable.As(&arguments);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ActivationKind activationKind;
+ hr = arguments->get_Kind(&activationKind);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ // Handle only File, Folder and Save file pick continuation here.
+ if (activationKind != ActivationKind_PickFileContinuation
+ && activationKind != ActivationKind_PickFolderContinuation
+ && activationKind != ActivationKind_PickSaveFileContinuation) {
+ return false;
+ }
+
+ QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher();
+ Q_ASSERT(eventDispatcher);
+ eventDispatcher->removeEventFilter(this);
+ e->accept();
+
+ if (activationKind == ActivationKind_PickFileContinuation) {
+ ComPtr<IFileOpenPickerContinuationEventArgs> fileContinuationArgs;
+ hr = arguments.As(&fileContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<StorageFile *>> files;
+ hr = fileContinuationArgs->get_Files(&files);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFilesPicked(files.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ } else if (activationKind == ActivationKind_PickFolderContinuation) {
+ ComPtr<IFolderPickerContinuationEventArgs> folderContinuationArgs;
+ hr = arguments.As(&folderContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IStorageFolder> folder;
+ hr = folderContinuationArgs->get_Folder(&folder);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFolderPicked(folder.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ } else {
+ ComPtr<IFileSavePickerContinuationEventArgs> saveFileContinuationArgs;
+ hr = arguments.As(&saveFileContinuationArgs);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IStorageFile> file;
+ hr = saveFileContinuationArgs->get_File(&file);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = onFilePicked(file.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ return true;
+}
+#endif
+
void QWinRTFileDialogHelper::setDirectory(const QUrl &directory)
{
Q_D(QWinRTFileDialogHelper);
@@ -403,6 +579,7 @@ QString QWinRTFileDialogHelper::selectedNameFilter() const
return d->selectedNameFilter;
}
+#ifndef Q_OS_WINPHONE
HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation<StorageFile *> *args, AsyncStatus status)
{
Q_D(QWinRTFileDialogHelper);
@@ -419,14 +596,7 @@ HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation<StorageFile *
ComPtr<IStorageFile> file;
hr = args->GetResults(&file);
Q_ASSERT_SUCCEEDED(hr);
- if (!file) {
- emit reject();
- return S_OK;
- }
-
- appendFile(file.Get());
- emit accept();
- return S_OK;
+ return onFilePicked(file.Get());
}
HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorView<StorageFile *> *> *args, AsyncStatus status)
@@ -445,17 +615,50 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorVie
ComPtr<IVectorView<StorageFile *>> fileList;
hr = args->GetResults(&fileList);
RETURN_HR_IF_FAILED("Failed to get file list");
+ return onFilesPicked(fileList.Get());
+}
+HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation<StorageFolder *> *args, AsyncStatus status)
+{
+ Q_D(QWinRTFileDialogHelper);
+
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+ if (status == Canceled || status == Error) {
+ emit reject();
+ return S_OK;
+ }
+
+ HRESULT hr;
+ ComPtr<IStorageFolder> folder;
+ hr = args->GetResults(&folder);
+ Q_ASSERT_SUCCEEDED(hr);
+ return onFolderPicked(folder.Get());
+}
+#endif //Q_OS_WINPHONE
+
+HRESULT QWinRTFileDialogHelper::onFilesPicked(IVectorView<StorageFile *> *files)
+{
+#ifdef Q_OS_WINPHONE
+ Q_D(QWinRTFileDialogHelper);
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+#endif
+
+ HRESULT hr;
quint32 size;
- hr = fileList->get_Size(&size);
+ hr = files->get_Size(&size);
Q_ASSERT_SUCCEEDED(hr);
if (!size) {
emit reject();
return S_OK;
}
+
for (quint32 i = 0; i < size; ++i) {
ComPtr<IStorageFile> file;
- hr = fileList->GetAt(i, &file);
+ hr = files->GetAt(i, &file);
Q_ASSERT_SUCCEEDED(hr);
appendFile(file.Get());
}
@@ -464,28 +667,40 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation<IVectorVie
return S_OK;
}
-HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation<StorageFolder *> *args, AsyncStatus status)
+HRESULT QWinRTFileDialogHelper::onFolderPicked(IStorageFolder *folder)
{
+#ifdef Q_OS_WINPHONE
Q_D(QWinRTFileDialogHelper);
-
QEventLoopLocker locker(&d->loop);
d->shown = false;
d->selectedFiles.clear();
- if (status == Canceled || status == Error) {
+#endif
+
+ if (!folder) {
emit reject();
return S_OK;
}
- HRESULT hr;
- ComPtr<IStorageFolder> folder;
- hr = args->GetResults(&folder);
- Q_ASSERT_SUCCEEDED(hr);
- if (!folder) {
+ appendFile(folder);
+ emit accept();
+ return S_OK;
+}
+
+HRESULT QWinRTFileDialogHelper::onFilePicked(IStorageFile *file)
+{
+#ifdef Q_OS_WINPHONE
+ Q_D(QWinRTFileDialogHelper);
+ QEventLoopLocker locker(&d->loop);
+ d->shown = false;
+ d->selectedFiles.clear();
+#endif
+
+ if (!file) {
emit reject();
return S_OK;
}
- appendFile(folder.Get());
+ appendFile(file);
emit accept();
return S_OK;
}
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
index 51b79c84ef..d6bacd2db9 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
@@ -47,6 +47,7 @@ namespace ABI {
class StorageFile;
class StorageFolder;
struct IStorageFile;
+ struct IStorageFolder;
}
namespace Foundation {
enum class AsyncStatus;
@@ -71,6 +72,9 @@ public:
void exec() Q_DECL_OVERRIDE;
bool show(Qt::WindowFlags, Qt::WindowModality, QWindow *) Q_DECL_OVERRIDE;
void hide() Q_DECL_OVERRIDE;
+#ifdef Q_OS_WINPHONE
+ bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE;
+#endif
bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return false; }
void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
@@ -81,13 +85,19 @@ public:
void selectNameFilter(const QString &selectedNameFilter) Q_DECL_OVERRIDE;
QString selectedNameFilter() const;
-private:
+#ifndef Q_OS_WINPHONE
HRESULT onSingleFilePicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFile *> *,
ABI::Windows::Foundation::AsyncStatus);
HRESULT onMultipleFilesPicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Foundation::Collections::IVectorView<ABI::Windows::Storage::StorageFile *> *> *,
ABI::Windows::Foundation::AsyncStatus);
HRESULT onSingleFolderPicked(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFolder *> *,
ABI::Windows::Foundation::AsyncStatus);
+#endif
+
+private:
+ HRESULT onFilesPicked(ABI::Windows::Foundation::Collections::IVectorView<ABI::Windows::Storage::StorageFile *> *files);
+ HRESULT onFolderPicked(ABI::Windows::Storage::IStorageFolder *folder);
+ HRESULT onFilePicked(ABI::Windows::Storage::IStorageFile *file);
void appendFile(IInspectable *);
QScopedPointer<QWinRTFileDialogHelperPrivate> d_ptr;
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
index 09edea52e7..c348faf015 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -39,13 +39,11 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QFile>
-#ifdef QT_WINRT_USE_DWRITE
#include <QtCore/QUuid>
#include <QtGui/private/qfontengine_ft_p.h>
#include <dwrite_1.h>
#include <wrl.h>
using namespace Microsoft::WRL;
-#endif // QT_WINRT_USE_DWRITE
QT_BEGIN_NAMESPACE
@@ -122,9 +120,7 @@ QString QWinRTFontDatabase::fontDir() const
const QString applicationDirPath = QCoreApplication::applicationDirPath();
fontDirectory = applicationDirPath + QLatin1String("/fonts");
if (!QFile::exists(fontDirectory)) {
-#ifdef QT_WINRT_USE_DWRITE
if (m_fontFamilies.isEmpty())
-#endif
qWarning("No fonts directory found in application package.");
fontDirectory = applicationDirPath;
}
@@ -132,8 +128,6 @@ QString QWinRTFontDatabase::fontDir() const
return fontDirectory;
}
-#ifdef QT_WINRT_USE_DWRITE
-
QWinRTFontDatabase::~QWinRTFontDatabase()
{
foreach (IDWriteFontFile *fontFile, m_fonts.keys())
@@ -449,13 +443,4 @@ void QWinRTFontDatabase::releaseHandle(void *handle)
QBasicFontDatabase::releaseHandle(handle);
}
-#else // QT_WINRT_USE_DWRITE
-
-QFont QWinRTFontDatabase::defaultFont() const
-{
- return QFont(QFontDatabase().families().value(0));
-}
-
-#endif // !QT_WINRT_USE_DWRITE
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
index 7b3f402c13..a88092e432 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -39,26 +39,21 @@
#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
-#ifdef QT_WINRT_USE_DWRITE
struct IDWriteFontFile;
struct IDWriteFontFamily;
-#endif
QT_BEGIN_NAMESPACE
-#ifdef QT_WINRT_USE_DWRITE
struct FontDescription
{
quint32 index;
QByteArray uuid;
};
-#endif
class QWinRTFontDatabase : public QBasicFontDatabase
{
public:
QString fontDir() const;
-#ifdef QT_WINRT_USE_DWRITE
~QWinRTFontDatabase();
QFont defaultFont() const Q_DECL_OVERRIDE;
bool fontsAlwaysScalable() const Q_DECL_OVERRIDE;
@@ -69,7 +64,6 @@ public:
private:
QHash<IDWriteFontFile *, FontDescription> m_fonts;
QHash<QString, IDWriteFontFamily *> m_fontFamilies;
-#endif // QT_WINRT_USE_DWRITE
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
index c94b53ef1c..9d8792a6db 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -37,7 +37,9 @@
#include "qwinrtinputcontext.h"
#include "qwinrtscreen.h"
#include <QtGui/QWindow>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <wrl.h>
#include <roapi.h>
#include <windows.ui.viewmanagement.h>
@@ -52,6 +54,14 @@ typedef ITypedEventHandler<InputPane*, InputPaneVisibilityEventArgs*> InputPaneV
QT_BEGIN_NAMESPACE
+inline QRectF getInputPaneRect(IInputPane *pane, qreal scaleFactor)
+{
+ Rect rect;
+ pane->get_OccludedRect(&rect);
+ return QRectF(qRound(rect.X * scaleFactor), qRound(rect.Y * scaleFactor),
+ qRound(rect.Width * scaleFactor), qRound(rect.Height * scaleFactor));
+}
+
/*!
\class QWinRTInputContext
\brief Manages Input Method visibility
@@ -85,7 +95,7 @@ QWinRTInputContext::QWinRTInputContext(QWinRTScreen *screen)
inputPane->add_Hiding(Callback<InputPaneVisibilityHandler>(
this, &QWinRTInputContext::onHiding).Get(), &hideToken);
- handleVisibilityChange(inputPane);
+ m_keyboardRect = getInputPaneRect(inputPane, m_screen->scaleFactor());
m_isInputPanelVisible = !m_keyboardRect.isEmpty();
} else {
qWarning(Q_FUNC_INFO ": failed to retrieve InputPane.");
@@ -118,10 +128,7 @@ HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEvent
HRESULT QWinRTInputContext::handleVisibilityChange(IInputPane *pane)
{
- Rect rect;
- pane->get_OccludedRect(&rect);
- const QRectF keyboardRect = QRectF(qRound(rect.X * m_screen->scaleFactor()), qRound(rect.Y * m_screen->scaleFactor()),
- qRound(rect.Width * m_screen->scaleFactor()), qRound(rect.Height * m_screen->scaleFactor()));
+ const QRectF keyboardRect = getInputPaneRect(pane, m_screen->scaleFactor());
if (m_keyboardRect != keyboardRect) {
m_keyboardRect = keyboardRect;
emitKeyboardRectChanged();
@@ -129,7 +136,7 @@ HRESULT QWinRTInputContext::handleVisibilityChange(IInputPane *pane)
return S_OK;
}
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
static HRESULT getInputPane(ComPtr<IInputPane2> *inputPane2)
{
@@ -158,159 +165,34 @@ static HRESULT getInputPane(ComPtr<IInputPane2> *inputPane2)
void QWinRTInputContext::showInputPanel()
{
- ComPtr<IInputPane2> inputPane;
- HRESULT hr = getInputPane(&inputPane);
- if (FAILED(hr))
- return;
-
- boolean success;
- hr = inputPane->TryShow(&success);
- if (FAILED(hr))
- qErrnoWarning(hr, "Failed to show input panel.");
+ QEventDispatcherWinRT::runOnXamlThread([&]() {
+ ComPtr<IInputPane2> inputPane;
+ HRESULT hr = getInputPane(&inputPane);
+ if (FAILED(hr))
+ return hr;
+ boolean success;
+ hr = inputPane->TryShow(&success);
+ if (FAILED(hr) || !success)
+ qErrnoWarning(hr, "Failed to show input panel.");
+ return hr;
+ });
}
void QWinRTInputContext::hideInputPanel()
{
- ComPtr<IInputPane2> inputPane;
- HRESULT hr = getInputPane(&inputPane);
- if (FAILED(hr))
- return;
-
- boolean success;
- hr = inputPane->TryHide(&success);
- if (FAILED(hr))
- qErrnoWarning(hr, "Failed to hide input panel.");
-}
-
-#else // Q_OS_WINPHONE
-
-// IRawElementProviderSimple
-HRESULT QWinRTInputContext::get_ProviderOptions(ProviderOptions *retVal)
-{
- *retVal = ProviderOptions_ServerSideProvider|ProviderOptions_UseComThreading;
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetPatternProvider(PATTERNID id, IUnknown **retVal)
-{
- switch (id) {
- case 10002: //UIA_ValuePatternId
- return QueryInterface(__uuidof(IValueProvider), (void**)retVal);
- break;
- case 10014: //UIA_TextPatternId:
- return QueryInterface(__uuidof(ITextProvider), (void**)retVal);
- case 10029: //UIA_TextChildPatternId:
- *retVal = nullptr;
- break;
- default:
- qWarning("Unhandled pattern ID: %d", id);
- break;
- }
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal)
-{
- switch (idProp) {
- case 30003: //UIA_ControlTypePropertyId
- retVal->vt = VT_I4;
- retVal->lVal = 50025; //UIA_CustomControlTypeId
- break;
- case 30008: //UIA_IsKeyboardFocusablePropertyId
- case 30009: //UIA_HasKeyboardFocusPropertyId
- // These are probably never actually called
- case 30016: //UIA_IsControlElementPropertyId
- case 30017: //UIA_IsContentElementPropertyId
- retVal->vt = VT_BOOL;
- retVal->boolVal = VARIANT_TRUE;
- break;
- case 30019: //UIA_IsPasswordPropertyId
- retVal->vt = VT_BOOL;
- retVal->boolVal = VARIANT_FALSE;
- break;
- case 30020: //UIA_NativeWindowHandlePropertyId
- retVal->vt = VT_PTR;
- retVal->punkVal = m_screen->coreWindow();
- break;
- }
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal)
-{
- // Return the window's element provider
- IInspectable *hostProvider;
- HRESULT hr = m_screen->coreWindow()->get_AutomationHostProvider(&hostProvider);
- if (SUCCEEDED(hr)) {
- hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal));
- hostProvider->Release();
- }
- return hr;
-}
-
-// ITextProvider
-HRESULT QWinRTInputContext::GetSelection(SAFEARRAY **)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetVisibleRanges(SAFEARRAY **)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::RangeFromPoint(UiaPoint, ITextRangeProvider **)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_DocumentRange(ITextRangeProvider **)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_SupportedTextSelection(SupportedTextSelection *)
-{
- // To be useful, requires listening to the focus object for a selection change and raising an event
- return S_OK;
-}
-
-// IValueProvider
-HRESULT QWinRTInputContext::SetValue(LPCWSTR)
-{
- // To be useful, requires listening to the focus object for a value change and raising an event
- // May be useful for inputPanel autocomplete, etc.
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_Value(BSTR *)
-{
- // To be useful, requires listening to the focus object for a value change and raising an event
- // May be useful for inputPanel autocomplete, etc.
- return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_IsReadOnly(BOOL *isReadOnly)
-{
- // isReadOnly dictates keyboard opening behavior when view is tapped.
- // We need to decide if the user tapped within a control which is about to receive focus...
- // Since this isn't possible (this function gets called before we receive the touch event),
- // the most platform-aligned option is to show the keyboard if an editable item has focus,
- // and close the keyboard if it is already open.
- *isReadOnly = m_isInputPanelVisible || !inputMethodAccepted();
- return S_OK;
+ QEventDispatcherWinRT::runOnXamlThread([&]() {
+ ComPtr<IInputPane2> inputPane;
+ HRESULT hr = getInputPane(&inputPane);
+ if (FAILED(hr))
+ return hr;
+ boolean success;
+ hr = inputPane->TryHide(&success);
+ if (FAILED(hr) || !success)
+ qErrnoWarning(hr, "Failed to hide input panel.");
+ return hr;
+ });
}
-#endif // !Q_OS_WINPHONE
+#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h
index ce7fbabf49..6f88ff46e6 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.h
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h
@@ -41,9 +41,6 @@
#include <QtCore/QRectF>
#include <wrl.h>
-#ifndef Q_OS_WINPHONE
-# include <UIAutomationCore.h>
-#endif
namespace ABI {
namespace Windows {
@@ -63,11 +60,6 @@ QT_BEGIN_NAMESPACE
class QWinRTScreen;
class QWinRTInputContext : public QPlatformInputContext
-#ifndef Q_OS_WINPHONE
- , public Microsoft::WRL::RuntimeClass<
- Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
- IRawElementProviderSimple, ITextProvider, IValueProvider>
-#endif // !Q_OS_WINPHONE
{
public:
explicit QWinRTInputContext(QWinRTScreen *);
@@ -76,29 +68,10 @@ public:
bool isInputPanelVisible() const;
-#ifdef Q_OS_WINPHONE
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
void showInputPanel();
void hideInputPanel();
-#else // Q_OS_WINPHONE
- // IRawElementProviderSimple
- HRESULT __stdcall get_ProviderOptions(ProviderOptions *retVal);
- HRESULT __stdcall GetPatternProvider(PATTERNID, IUnknown **);
- HRESULT __stdcall GetPropertyValue(PROPERTYID idProp, VARIANT *retVal);
- HRESULT __stdcall get_HostRawElementProvider(IRawElementProviderSimple **retVal);
-
- // ITextProvider
- HRESULT __stdcall GetSelection(SAFEARRAY **);
- HRESULT __stdcall GetVisibleRanges(SAFEARRAY **);
- HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **);
- HRESULT __stdcall RangeFromPoint(UiaPoint, ITextRangeProvider **);
- HRESULT __stdcall get_DocumentRange(ITextRangeProvider **);
- HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *);
-
- // IValueProvider
- HRESULT __stdcall SetValue(LPCWSTR);
- HRESULT __stdcall get_Value(BSTR *);
- HRESULT __stdcall get_IsReadOnly(BOOL *);
-#endif // !Q_OS_WINPHONE
+#endif
private:
HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *,
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 70ee6dbe6a..9db5df995a 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -45,51 +45,151 @@
#include "qwinrtfontdatabase.h"
#include "qwinrttheme.h"
+#include <QtGui/QSurface>
#include <QtGui/QOpenGLContext>
+#include <qfunctions_winrt.h>
+#include <functional>
#include <wrl.h>
+#include <windows.ui.xaml.h>
+#include <windows.applicationmodel.h>
+#include <windows.applicationmodel.core.h>
#include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h>
-#include <Windows.ApplicationModel.core.h>
+#include <windows.graphics.display.h>
+#ifdef Q_OS_WINPHONE
+# include <windows.phone.ui.input.h>
+#endif
using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement;
+using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::ApplicationModel::Core;
+#ifdef Q_OS_WINPHONE
+using namespace ABI::Windows::Phone::UI::Input;
+#endif
+
+typedef IEventHandler<IInspectable *> ResumeHandler;
+typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
+#ifdef Q_OS_WINPHONE
+typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
+#endif
QT_BEGIN_NAMESPACE
-QWinRTIntegration::QWinRTIntegration()
- : m_success(false)
- , m_fontDatabase(new QWinRTFontDatabase)
- , m_services(new QWinRTServices)
+typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
+uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
+
+class QWinRTIntegrationPrivate
+{
+public:
+ QPlatformFontDatabase *fontDatabase;
+ QPlatformServices *platformServices;
+ QWinRTScreen *mainScreen;
+ QScopedPointer<QWinRTInputContext> inputContext;
+
+ ComPtr<ICoreApplication> application;
+ QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
+#ifdef Q_OS_WINPHONE
+ ComPtr<IHardwareButtonsStatics> hardwareButtons;
+ QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
+#endif
+};
+
+QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
{
- m_screen = new QWinRTScreen;
- screenAdded(m_screen);
+ Q_D(QWinRTIntegration);
+
+ d->fontDatabase = new QWinRTFontDatabase;
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&d->application));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTIntegration::onSuspended).Get(),
+ &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTIntegration::onResume).Get(),
+ &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
- m_success = true;
+#ifdef Q_OS_WINPHONE
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
+ IID_PPV_ARGS(&d->hardwareButtons));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
+ &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+#endif // Q_OS_WINPHONE
+
+ QEventDispatcherWinRT::runOnXamlThread([d]() {
+ d->mainScreen = new QWinRTScreen;
+ d->inputContext.reset(new QWinRTInputContext(d->mainScreen));
+ return S_OK;
+ });
+
+ screenAdded(d->mainScreen);
+ d->platformServices = new QWinRTServices;
}
QWinRTIntegration::~QWinRTIntegration()
{
+ Q_D(QWinRTIntegration);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
+ hr = (d->hardwareButtons.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif
+ for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i) {
+ hr = (d->application.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ destroyScreen(d->mainScreen);
Windows::Foundation::Uninitialize();
}
+bool QWinRTIntegration::succeeded() const
+{
+ Q_D(const QWinRTIntegration);
+ return d->mainScreen;
+}
+
QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const
{
return new QWinRTEventDispatcher;
}
+void QWinRTIntegration::initialize()
+{
+ Q_D(const QWinRTIntegration);
+ QEventDispatcherWinRT::runOnXamlThread([d]() {
+ d->mainScreen->initialize();
+ return S_OK;
+ });
+}
+
bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
case ThreadedPixmaps:
case OpenGL:
case ApplicationState:
- return true;
case NonFullScreenWindows:
- return false;
+ case MultipleWindows:
+ case RasterGLSurface:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -112,28 +212,31 @@ QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *wi
QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- QWinRTScreen *screen = static_cast<QWinRTScreen *>(context->screen()->handle());
- return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface(), screen->eglConfig());
+ return new QWinRTEGLContext(context);
}
QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const
{
- return m_fontDatabase;
+ Q_D(const QWinRTIntegration);
+ return d->fontDatabase;
}
QPlatformInputContext *QWinRTIntegration::inputContext() const
{
- return m_screen->inputContext();
+ Q_D(const QWinRTIntegration);
+ return d->inputContext.data();
}
QPlatformServices *QWinRTIntegration::services() const
{
- return m_services;
+ Q_D(const QWinRTIntegration);
+ return d->platformServices;
}
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
- return m_screen->keyboardModifiers();
+ Q_D(const QWinRTIntegration);
+ return d->mainScreen->keyboardModifiers();
}
QStringList QWinRTIntegration::themeNames() const
@@ -141,12 +244,45 @@ QStringList QWinRTIntegration::themeNames() const
return QStringList(QLatin1String("winrt"));
}
-QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &
-name) const
+QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &name) const
{
if (name == QLatin1String("winrt"))
return new QWinRTTheme();
return 0;
}
+
+// System-level integration points
+
+#ifdef Q_OS_WINPHONE
+HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
+{
+ Q_D(QWinRTIntegration);
+ QWindow *window = d->mainScreen->topWindow();
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
+ const bool pressed = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier,
+ 0, 0, 0, QString(), false, 1, false);
+ const bool released = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier,
+ 0, 0, 0, QString(), false, 1, false);
+ QWindowSystemInterface::setSynchronousWindowSystemEvents(false);
+ args->put_Handled(pressed || released);
+ return S_OK;
+}
+#endif // Q_OS_WINPHONE
+
+HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
+{
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ return S_OK;
+}
+
+HRESULT QWinRTIntegration::onResume(IInspectable *, IInspectable *)
+{
+ // First the system invokes onResume and then changes
+ // the visibility of the screen to be active.
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
+ return S_OK;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
index bbd6c1e41b..3a151e1ed8 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.h
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -39,11 +39,33 @@
#include <qpa/qplatformintegration.h>
+namespace ABI {
+ namespace Windows {
+ namespace ApplicationModel {
+ struct ISuspendingEventArgs;
+ }
+ namespace Foundation {
+ struct IAsyncAction;
+ }
+#ifdef Q_OS_WINPHONE
+ namespace Phone {
+ namespace UI {
+ namespace Input {
+ struct IBackPressedEventArgs;
+ }
+ }
+ }
+#endif
+ }
+}
+struct IAsyncInfo;
+struct IInspectable;
+
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
-class QWinRTScreen;
+class QWinRTIntegrationPrivate;
class QWinRTIntegration : public QPlatformIntegration
{
private:
@@ -53,29 +75,37 @@ public:
static QWinRTIntegration *create()
{
- QWinRTIntegration *integration = new QWinRTIntegration;
- return integration->m_success ? integration : 0;
+ QScopedPointer<QWinRTIntegration> integration(new QWinRTIntegration);
+ return integration->succeeded() ? integration.take() : nullptr;
}
- bool hasCapability(QPlatformIntegration::Capability cap) const;
- QVariant styleHint(StyleHint hint) const;
+ bool succeeded() const;
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
- QPlatformWindow *createPlatformWindow(QWindow *window) const;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
- QAbstractEventDispatcher *createEventDispatcher() const;
- QPlatformFontDatabase *fontDatabase() const;
- QPlatformInputContext *inputContext() const;
- QPlatformServices *services() const;
- Qt::KeyboardModifiers queryKeyboardModifiers() const;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
+ void initialize() Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
+ QPlatformServices *services() const Q_DECL_OVERRIDE;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
+
+ QStringList themeNames() const Q_DECL_OVERRIDE;
+ QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
- QStringList themeNames() const;
- QPlatformTheme *createPlatformTheme(const QString &name) const;
private:
- bool m_success;
- QWinRTScreen *m_screen;
- QPlatformFontDatabase *m_fontDatabase;
- QPlatformServices *m_services;
+#ifdef Q_OS_WINPHONE
+ HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
+#endif
+ HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
+ HRESULT onResume(IInspectable *, IInspectable *);
+
+ QScopedPointer<QWinRTIntegrationPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTIntegration)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
index 4fc1fea626..bb04144563 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -38,7 +38,9 @@
#include "qwinrttheme.h"
#include <QtCore/qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+#include <functional>
#include <windows.ui.popups.h>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
@@ -131,53 +133,58 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa
RETURN_FALSE_IF_FAILED("Failed to create dialog");
}
- // Add Buttons
- ComPtr<IVector<IUICommand *>> dialogCommands;
- hr = dialog->get_Commands(&dialogCommands);
- RETURN_FALSE_IF_FAILED("Failed to get dialog commands");
-
- // If no button is specified we need to create one to get close notification
- int buttons = options->standardButtons();
- if (buttons == 0)
- buttons = Ok;
-
- for (int i = FirstButton; i < LastButton; i<<=1) {
- if (!(buttons & i))
- continue;
- // Add native command
- const QString label = d->theme->standardButtonText(i);
- HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
- ComPtr<IUICommand> command;
- hr = commandFactory->Create(nativeLabel.Get(), &command);
- RETURN_FALSE_IF_FAILED("Failed to create message box command");
- ComPtr<IInspectable> id = Make<CommandId>(static_cast<StandardButton>(i));
- hr = command->put_Id(id.Get());
- RETURN_FALSE_IF_FAILED("Failed to set command ID");
- hr = dialogCommands->Append(command.Get());
- if (hr == E_BOUNDS) {
- qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons");
- continue;
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, d, options, commandFactory, dialog]() {
+ HRESULT hr;
+
+ // Add Buttons
+ ComPtr<IVector<IUICommand *>> dialogCommands;
+ hr = dialog->get_Commands(&dialogCommands);
+ RETURN_HR_IF_FAILED("Failed to get dialog commands");
+
+ // If no button is specified we need to create one to get close notification
+ int buttons = options->standardButtons();
+ if (buttons == 0)
+ buttons = Ok;
+
+ for (int i = FirstButton; i < LastButton; i<<=1) {
+ if (!(buttons & i))
+ continue;
+ // Add native command
+ const QString label = d->theme->standardButtonText(i);
+ HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
+ ComPtr<IUICommand> command;
+ hr = commandFactory->Create(nativeLabel.Get(), &command);
+ RETURN_HR_IF_FAILED("Failed to create message box command");
+ ComPtr<IInspectable> id = Make<CommandId>(static_cast<StandardButton>(i));
+ hr = command->put_Id(id.Get());
+ RETURN_HR_IF_FAILED("Failed to set command ID");
+ hr = dialogCommands->Append(command.Get());
+ if (hr == E_BOUNDS) {
+ qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons");
+ continue;
+ }
+ RETURN_HR_IF_FAILED("Failed to append message box command");
+ if (i == Abort || i == Cancel || i == Close) {
+ quint32 size;
+ hr = dialogCommands->get_Size(&size);
+ RETURN_HR_IF_FAILED("Failed to get command list size");
+ hr = dialog->put_CancelCommandIndex(size - 1);
+ RETURN_HR_IF_FAILED("Failed to set cancel index");
+ }
}
- RETURN_FALSE_IF_FAILED("Failed to append message box command");
- if (i == Abort || i == Cancel || i == Close) {
- quint32 size;
- hr = dialogCommands->get_Size(&size);
- RETURN_FALSE_IF_FAILED("Failed to get command list size");
- hr = dialog->put_CancelCommandIndex(size - 1);
- RETURN_FALSE_IF_FAILED("Failed to set cancel index");
- }
- }
-
- ComPtr<IAsyncOperation<IUICommand *>> op;
- hr = dialog->ShowAsync(&op);
- RETURN_FALSE_IF_FAILED("Failed to show dialog");
- hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
- RETURN_FALSE_IF_FAILED("Failed to set dialog callback");
-
- d->shown = true;
- hr = op.As(&d->info);
- RETURN_FALSE_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
+ ComPtr<IAsyncOperation<IUICommand *>> op;
+ hr = dialog->ShowAsync(&op);
+ RETURN_HR_IF_FAILED("Failed to show dialog");
+ hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
+ RETURN_HR_IF_FAILED("Failed to set dialog callback");
+ d->shown = true;
+ hr = op.As(&d->info);
+ RETURN_HR_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
+ return hr;
+ });
+
+ RETURN_FALSE_IF_FAILED("Failed to show dialog")
return true;
}
@@ -200,8 +207,7 @@ HRESULT QWinRTMessageDialogHelper::onCompleted(IAsyncOperation<IUICommand *> *as
Q_UNUSED(status);
Q_D(QWinRTMessageDialogHelper);
- if (d->loop.isRunning())
- d->loop.exit();
+ QEventLoopLocker locker(&d->loop);
d->shown = false;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 8962332208..a642443386 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -36,26 +36,18 @@
#include "qwinrtscreen.h"
-#define EGL_EGLEXT_PROTOTYPES
-#include <EGL/eglext.h>
-#include <d3d11.h>
-#include <dxgi1_2.h>
-#ifndef Q_OS_WINPHONE
-#include <dxgi1_3.h>
-#endif
-
#include "qwinrtbackingstore.h"
#include "qwinrtinputcontext.h"
#include "qwinrtcursor.h"
-#include "qwinrteglcontext.h"
+#include <private/qeventdispatcher_winrt_p.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QGuiApplication>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qt_windows.h>
#include <QtCore/qfunctions_winrt.h>
+#include <functional>
#include <wrl.h>
#include <windows.system.h>
#include <Windows.Applicationmodel.h>
@@ -64,12 +56,10 @@
#include <windows.ui.h>
#include <windows.ui.core.h>
#include <windows.ui.input.h>
+#include <windows.ui.xaml.h>
#include <windows.ui.viewmanagement.h>
#include <windows.graphics.display.h>
#include <windows.foundation.h>
-#ifdef Q_OS_WINPHONE
-#include <windows.phone.ui.input.h>
-#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@@ -77,17 +67,13 @@ using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::Input;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::Devices::Input;
using namespace ABI::Windows::Graphics::Display;
-#ifdef Q_OS_WINPHONE
-using namespace ABI::Windows::Phone::UI::Input;
-#endif
-typedef IEventHandler<IInspectable*> ResumeHandler;
-typedef IEventHandler<SuspendingEventArgs*> SuspendHandler;
typedef ITypedEventHandler<CoreWindow*, WindowActivatedEventArgs*> ActivatedHandler;
typedef ITypedEventHandler<CoreWindow*, CoreWindowEventArgs*> ClosedHandler;
typedef ITypedEventHandler<CoreWindow*, CharacterReceivedEventArgs*> CharacterReceivedHandler;
@@ -96,14 +82,34 @@ typedef ITypedEventHandler<CoreWindow*, KeyEventArgs*> KeyHandler;
typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
-typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
#ifdef Q_OS_WINPHONE
-typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
+typedef ITypedEventHandler<StatusBar*, IInspectable*> StatusBarHandler;
#endif
QT_BEGIN_NAMESPACE
+struct KeyInfo {
+ KeyInfo()
+ : virtualKey(0)
+ {
+ }
+
+ KeyInfo(const QString &text, quint32 virtualKey)
+ : text(text)
+ , virtualKey(virtualKey)
+ {
+ }
+
+ KeyInfo(quint32 virtualKey)
+ : virtualKey(virtualKey)
+ {
+ }
+
+ QString text;
+ quint32 virtualKey;
+};
+
static inline Qt::ScreenOrientations qtOrientationsFromNative(DisplayOrientations native)
{
Qt::ScreenOrientations orientations = Qt::PrimaryOrientation;
@@ -419,34 +425,29 @@ static inline Qt::Key qKeyFromCode(quint32 code, int mods)
return static_cast<Qt::Key>(code & 0xff);
}
-typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
-uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken);
uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#ifdef Q_OS_WINPHONE
-typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
-uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+typedef HRESULT (__stdcall IStatusBar::*StatusBarCallbackRemover)(EventRegistrationToken);
+uint qHash(StatusBarCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
#endif
class QWinRTScreenPrivate
{
public:
- ComPtr<ICoreApplication> application;
+ QTouchDevice *touchDevice;
ComPtr<ICoreWindow> coreWindow;
+ ComPtr<Xaml::IDependencyObject> canvas;
+ ComPtr<IApplicationView> view;
ComPtr<IDisplayInformation> displayInformation;
#ifdef Q_OS_WINPHONE
- ComPtr<IHardwareButtonsStatics> hardwareButtons;
+ ComPtr<IStatusBar> statusBar;
#endif
QScopedPointer<QWinRTCursor> cursor;
-#ifdef Q_OS_WINPHONE
- QScopedPointer<QWinRTInputContext> inputContext;
-#else
- ComPtr<QWinRTInputContext> inputContext;
-#endif
-
+ QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
QSizeF logicalSize;
QSurfaceFormat surfaceFormat;
qreal logicalDpi;
@@ -455,108 +456,43 @@ public:
Qt::ScreenOrientation nativeOrientation;
Qt::ScreenOrientation orientation;
QList<QWindow *> visibleWindows;
-#ifndef Q_OS_WINPHONE
- QHash<quint32, QPair<Qt::Key, QString>> activeKeys;
-#endif
- QTouchDevice *touchDevice;
- QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
-
- EGLDisplay eglDisplay;
- EGLSurface eglSurface;
- EGLConfig eglConfig;
-
- QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
+ QHash<Qt::Key, KeyInfo> activeKeys;
QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
#ifdef Q_OS_WINPHONE
- QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
+ QHash<StatusBarCallbackRemover, EventRegistrationToken> statusBarTokens;
#endif
};
+// To be called from the XAML thread
QWinRTScreen::QWinRTScreen()
: d_ptr(new QWinRTScreenPrivate)
{
Q_D(QWinRTScreen);
d->orientation = Qt::PrimaryOrientation;
d->touchDevice = Q_NULLPTR;
- d->eglDisplay = EGL_NO_DISPLAY;
- // Obtain the WinRT Application, view, and window
HRESULT hr;
- hr = RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
- IID_PPV_ARGS(&d->application));
+ ComPtr<Xaml::IWindowStatics> windowStatics;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Window).Get(),
+ IID_PPV_ARGS(&windowStatics));
Q_ASSERT_SUCCEEDED(hr);
- hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ ComPtr<Xaml::IWindow> window;
+ hr = windowStatics->get_Current(&window);
Q_ASSERT_SUCCEEDED(hr);
- hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ hr = window->Activate();
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<ICoreApplicationView> view;
- hr = d->application->GetCurrentView(&view);
- Q_ASSERT_SUCCEEDED(hr);
- hr = view->get_CoreWindow(&d->coreWindow);
+ hr = window->get_CoreWindow(&d->coreWindow);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->Activate();
Q_ASSERT_SUCCEEDED(hr);
-#ifdef Q_OS_WINPHONE
- d->inputContext.reset(new QWinRTInputContext(this));
-#else
- d->inputContext = Make<QWinRTInputContext>(this);
-#endif
-
Rect rect;
hr = d->coreWindow->get_Bounds(&rect);
Q_ASSERT_SUCCEEDED(hr);
d->logicalSize = QSizeF(rect.Width, rect.Height);
- d->surfaceFormat.setAlphaBufferSize(0);
- d->surfaceFormat.setRedBufferSize(8);
- d->surfaceFormat.setGreenBufferSize(8);
- d->surfaceFormat.setBlueBufferSize(8);
- d->surfaceFormat.setDepthBufferSize(24);
- d->surfaceFormat.setStencilBufferSize(8);
- d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
- d->surfaceFormat.setSamples(1);
- d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
-
- hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
- Q_ASSERT_SUCCEEDED(hr);
-#ifndef Q_OS_WINPHONE
- hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
- Q_ASSERT_SUCCEEDED(hr);
-#endif
- hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &d->windowTokens[&ICoreWindow::remove_AutomationProviderRequested]);
- Q_ASSERT_SUCCEEDED(hr);
-#ifdef Q_OS_WINPHONE
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), IID_PPV_ARGS(&d->hardwareButtons));
- Q_ASSERT_SUCCEEDED(hr);
- hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
- Q_ASSERT_SUCCEEDED(hr);
-#endif // Q_OS_WINPHONE
-
// Orientation handling
ComPtr<IDisplayInformationStatics> displayInformationStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
@@ -571,57 +507,47 @@ QWinRTScreen::QWinRTScreen()
hr = d->displayInformation->get_NativeOrientation(&displayOrientation);
Q_ASSERT_SUCCEEDED(hr);
d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
+ // Set initial pixel density
+ onDpiChanged(Q_NULLPTR, Q_NULLPTR);
+ d->orientation = d->nativeOrientation;
- hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
- Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IApplicationViewStatics2> applicationViewStatics;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
+ IID_PPV_ARGS(&applicationViewStatics));
+ RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
- hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
- Q_ASSERT_SUCCEEDED(hr);
+ hr = applicationViewStatics->GetForCurrentView(&d->view);
+ RETURN_VOID_IF_FAILED("Could not access currentView");
- // Set initial orientation & pixel density
- onDpiChanged(Q_NULLPTR, Q_NULLPTR);
- d->orientation = d->nativeOrientation;
- onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
+ // Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added
+ ComPtr<Xaml::Controls::ICanvas> canvas;
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<Xaml::IFrameworkElement> frameworkElement;
+ hr = canvas.As(&frameworkElement);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = frameworkElement->put_Width(d->logicalSize.width());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = frameworkElement->put_Height(d->logicalSize.height());
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<Xaml::IUIElement> uiElement;
+ hr = canvas.As(&uiElement);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = window->put_Content(uiElement.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = canvas.As(&d->canvas);
+ Q_ASSERT_SUCCEEDED(hr);
- d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (d->eglDisplay == EGL_NO_DISPLAY)
- qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
-
- if (!eglInitialize(d->eglDisplay, NULL, NULL))
- qCritical("Failed to initialize EGL: 0x%x", eglGetError());
-
- // Check that the device properly supports depth/stencil rendering, and disable them if not
- ComPtr<ID3D11Device> d3dDevice;
- const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
- if (ok && d3dDevice) {
- ComPtr<IDXGIDevice> dxgiDevice;
- hr = d3dDevice.As(&dxgiDevice);
- if (SUCCEEDED(hr)) {
- ComPtr<IDXGIAdapter> dxgiAdapter;
- hr = dxgiDevice->GetAdapter(&dxgiAdapter);
- if (SUCCEEDED(hr)) {
- ComPtr<IDXGIAdapter2> dxgiAdapter2;
- hr = dxgiAdapter.As(&dxgiAdapter2);
- if (SUCCEEDED(hr)) {
- DXGI_ADAPTER_DESC2 desc;
- hr = dxgiAdapter2->GetDesc2(&desc);
- if (SUCCEEDED(hr)) {
- // The following GPUs do not render properly with depth/stencil
- if ((desc.VendorId == 0x4d4f4351 && desc.DeviceId == 0x32303032)) { // Qualcomm Adreno 225
- d->surfaceFormat.setDepthBufferSize(-1);
- d->surfaceFormat.setStencilBufferSize(-1);
- }
- }
- }
- }
- }
- }
+ d->cursor.reset(new QWinRTCursor);
- d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->surfaceFormat);
- d->surfaceFormat = q_glFormatFromConfig(d->eglDisplay, d->eglConfig, d->surfaceFormat);
- d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), NULL);
- if (d->eglSurface == EGL_NO_SURFACE)
- qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
+#ifdef Q_OS_WINPHONE
+ ComPtr<IStatusBarStatics> statusBarStatics;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_StatusBar).Get(),
+ IID_PPV_ARGS(&statusBarStatics));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = statusBarStatics->GetForCurrentView(&d->statusBar);
+ Q_ASSERT_SUCCEEDED(hr);
+#endif // Q_OS_WINPHONE
}
QWinRTScreen::~QWinRTScreen()
@@ -629,16 +555,26 @@ QWinRTScreen::~QWinRTScreen()
Q_D(QWinRTScreen);
// Unregister callbacks
- for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i)
- (d->application.Get()->*i.key())(i.value());
- for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i)
- (d->coreWindow.Get()->*i.key())(i.value());
- for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i)
- (d->displayInformation.Get()->*i.key())(i.value());
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ HRESULT hr;
+ for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i) {
+ hr = (d->coreWindow.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i) {
+ hr = (d->displayInformation.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
#ifdef Q_OS_WINPHONE
- for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i)
- (d->hardwareButtons.Get()->*i.key())(i.value());
-#endif
+ for (QHash<StatusBarCallbackRemover, EventRegistrationToken>::const_iterator i = d->statusBarTokens.begin(); i != d->statusBarTokens.end(); ++i) {
+ hr = (d->statusBar.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif //Q_OS_WINPHONE
+ return hr;
+ });
+ RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks");
}
QRect QWinRTScreen::geometry() const
@@ -647,6 +583,31 @@ QRect QWinRTScreen::geometry() const
return QRect(QPoint(), (d->logicalSize * d->scaleFactor).toSize());
}
+#ifdef Q_OS_WINPHONE
+QRect QWinRTScreen::availableGeometry() const
+{
+ Q_D(const QWinRTScreen);
+ QRect statusBar;
+ QEventDispatcherWinRT::runOnXamlThread([d, &statusBar]() {
+ HRESULT hr;
+ Rect rect;
+ hr = d->statusBar->get_OccludedRect(&rect);
+ Q_ASSERT_SUCCEEDED(hr);
+ statusBar.setRect(qRound(rect.X * d->scaleFactor),
+ qRound(rect.Y * d->scaleFactor),
+ qRound(rect.Width * d->scaleFactor),
+ qRound(rect.Height * d->scaleFactor));
+ return S_OK;
+ });
+
+ return geometry().adjusted(
+ d->orientation == Qt::LandscapeOrientation ? statusBar.width() : 0,
+ d->orientation == Qt::PortraitOrientation ? statusBar.height() : 0,
+ d->orientation == Qt::InvertedLandscapeOrientation ? -statusBar.width() : 0,
+ 0);
+}
+#endif //Q_OS_WINPHONE
+
int QWinRTScreen::depth() const
{
return 32;
@@ -657,12 +618,6 @@ QImage::Format QWinRTScreen::format() const
return QImage::Format_ARGB32_Premultiplied;
}
-QSurfaceFormat QWinRTScreen::surfaceFormat() const
-{
- Q_D(const QWinRTScreen);
- return d->surfaceFormat;
-}
-
QSizeF QWinRTScreen::physicalSize() const
{
Q_D(const QWinRTScreen);
@@ -682,21 +637,9 @@ qreal QWinRTScreen::scaleFactor() const
return d->scaleFactor;
}
-QWinRTInputContext *QWinRTScreen::inputContext() const
-{
- Q_D(const QWinRTScreen);
-#ifdef Q_OS_WINPHONE
- return d->inputContext.data();
-#else
- return d->inputContext.Get();
-#endif
-}
-
QPlatformCursor *QWinRTScreen::cursor() const
{
Q_D(const QWinRTScreen);
- if (!d->cursor)
- const_cast<QWinRTScreenPrivate *>(d)->cursor.reset(new QWinRTCursor);
return d->cursor.data();
}
@@ -744,22 +687,76 @@ ICoreWindow *QWinRTScreen::coreWindow() const
return d->coreWindow.Get();
}
-EGLDisplay QWinRTScreen::eglDisplay() const
+Xaml::IDependencyObject *QWinRTScreen::canvas() const
{
Q_D(const QWinRTScreen);
- return d->eglDisplay;
+ return d->canvas.Get();
}
-EGLSurface QWinRTScreen::eglSurface() const
+#ifdef Q_OS_WINPHONE
+void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window)
{
- Q_D(const QWinRTScreen);
- return d->eglSurface;
+ Q_D(QWinRTScreen);
+ const Qt::WindowFlags windowType = window->flags() & Qt::WindowType_Mask;
+ if (!window || (windowType != Qt::Window && windowType != Qt::Dialog))
+ return;
+
+ QEventDispatcherWinRT::runOnXamlThread([d, visible]() {
+ HRESULT hr;
+ ComPtr<IAsyncAction> op;
+ if (visible)
+ hr = d->statusBar->ShowAsync(&op);
+ else
+ hr = d->statusBar->HideAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
}
+#endif //Q_OS_WINPHONE
-EGLConfig QWinRTScreen::eglConfig() const
+void QWinRTScreen::initialize()
{
- Q_D(const QWinRTScreen);
- return d->eglConfig;
+ Q_D(QWinRTScreen);
+ HRESULT hr;
+ hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+#ifndef Q_OS_WINPHONE
+ hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+#else
+ hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]);
+ Q_ASSERT_SUCCEEDED(hr);
+#endif
+ hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
+ 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);
+ onVisibilityChanged(nullptr, nullptr);
}
QWindow *QWinRTScreen::topWindow() const
@@ -773,6 +770,12 @@ void QWinRTScreen::addWindow(QWindow *window)
Q_D(QWinRTScreen);
if (window == topWindow())
return;
+
+#ifdef Q_OS_WINPHONE
+ if (window->visibility() != QWindow::Maximized && window->visibility() != QWindow::Windowed)
+ setStatusBarVisibility(false, window);
+#endif
+
d->visibleWindows.prepend(window);
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
@@ -781,6 +784,12 @@ void QWinRTScreen::addWindow(QWindow *window)
void QWinRTScreen::removeWindow(QWindow *window)
{
Q_D(QWinRTScreen);
+
+#ifdef Q_OS_WINPHONE
+ if (window->visibility() == QWindow::Minimized)
+ setStatusBarVisibility(false, window);
+#endif
+
const bool wasTopWindow = window == topWindow();
if (!d->visibleWindows.removeAll(window))
return;
@@ -809,6 +818,20 @@ void QWinRTScreen::lower(QWindow *window)
handleExpose();
}
+void QWinRTScreen::updateWindowTitle()
+{
+ Q_D(QWinRTScreen);
+
+ QWindow *window = topWindow();
+ if (!window)
+ return;
+
+ const QString title = window->title();
+ HStringReference titleRef(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
+ HRESULT hr = d->view->put_Title(titleRef.Get());
+ RETURN_VOID_IF_FAILED("Unable to set window title");
+}
+
void QWinRTScreen::handleExpose()
{
Q_D(QWinRTScreen);
@@ -822,57 +845,94 @@ void QWinRTScreen::handleExpose()
HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
+ Q_D(QWinRTScreen);
VirtualKey virtualKey;
- args->get_VirtualKey(&virtualKey);
+ HRESULT hr = args->get_VirtualKey(&virtualKey);
+ Q_ASSERT_SUCCEEDED(hr);
+ CorePhysicalKeyStatus status;
+ hr = args->get_KeyStatus(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+
Qt::Key key = qKeyFromVirtual(virtualKey);
// Defer character key presses to onCharacterReceived
- if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis))
+ if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) {
+ d->activeKeys.insert(key, KeyInfo(virtualKey));
return S_OK;
- QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, keyboardModifiers());
+ }
+
+ QWindowSystemInterface::handleExtendedKeyEvent(
+ topWindow(),
+ QEvent::KeyPress,
+ key,
+ keyboardModifiers(),
+ !status.ScanCode ? -1 : status.ScanCode,
+ virtualKey,
+ 0,
+ QString(),
+ status.RepeatCount > 1,
+ !status.RepeatCount ? 1 : status.RepeatCount,
+ false);
return S_OK;
}
HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
- Qt::KeyboardModifiers mods = keyboardModifiers();
-#ifndef Q_OS_WINPHONE
Q_D(QWinRTScreen);
- CorePhysicalKeyStatus status; // Look for a pressed character key
- if (SUCCEEDED(args->get_KeyStatus(&status)) && d->activeKeys.contains(status.ScanCode)) {
- QPair<Qt::Key, QString> keyStatus = d->activeKeys.take(status.ScanCode);
- QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
- keyStatus.first, mods, keyStatus.second);
- return S_OK;
- }
-#endif // !Q_OS_WINPHONE
VirtualKey virtualKey;
- args->get_VirtualKey(&virtualKey);
- QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
- qKeyFromVirtual(virtualKey), mods);
+ HRESULT hr = args->get_VirtualKey(&virtualKey);
+ Q_ASSERT_SUCCEEDED(hr);
+ CorePhysicalKeyStatus status;
+ hr = args->get_KeyStatus(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ Qt::Key key = qKeyFromVirtual(virtualKey);
+ const KeyInfo info = d->activeKeys.take(key);
+ QWindowSystemInterface::handleExtendedKeyEvent(
+ topWindow(),
+ QEvent::KeyRelease,
+ key,
+ keyboardModifiers(),
+ !status.ScanCode ? -1 : status.ScanCode,
+ virtualKey,
+ 0,
+ info.text,
+ status.RepeatCount > 1,
+ !status.RepeatCount ? 1 : status.RepeatCount,
+ false);
return S_OK;
}
HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEventArgs *args)
{
+ Q_D(QWinRTScreen);
quint32 keyCode;
- args->get_KeyCode(&keyCode);
+ HRESULT hr = args->get_KeyCode(&keyCode);
+ Q_ASSERT_SUCCEEDED(hr);
+ CorePhysicalKeyStatus status;
+ hr = args->get_KeyStatus(&status);
+ Q_ASSERT_SUCCEEDED(hr);
+
// Don't generate character events for non-printables; the meta key stage is enough
if (qIsNonPrintable(keyCode))
return S_OK;
- Qt::KeyboardModifiers mods = keyboardModifiers();
- Qt::Key key = qKeyFromCode(keyCode, mods);
- QString text = QChar(keyCode);
- QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text);
-#ifndef Q_OS_WINPHONE
- Q_D(QWinRTScreen);
- CorePhysicalKeyStatus status; // Defer release to onKeyUp for physical keys
- if (SUCCEEDED(args->get_KeyStatus(&status)) && !status.IsKeyReleased) {
- d->activeKeys.insert(status.ScanCode, qMakePair(key, text));
- return S_OK;
- }
-#endif // !Q_OS_WINPHONE
- QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text);
+ const Qt::KeyboardModifiers modifiers = keyboardModifiers();
+ const Qt::Key key = qKeyFromCode(keyCode, modifiers);
+ const QString text = QChar(keyCode);
+ const quint32 virtualKey = d->activeKeys.value(key).virtualKey;
+ QWindowSystemInterface::handleExtendedKeyEvent(
+ topWindow(),
+ QEvent::KeyPress,
+ key,
+ modifiers,
+ !status.ScanCode ? -1 : status.ScanCode,
+ virtualKey,
+ 0,
+ text,
+ status.RepeatCount > 1,
+ !status.RepeatCount ? 1 : status.RepeatCount,
+ false);
+ d->activeKeys.insert(key, KeyInfo(text, virtualKey));
return S_OK;
}
@@ -909,6 +969,11 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
Point point;
pointerPoint->get_Position(&point);
QPointF pos(point.X * d->scaleFactor, point.Y * d->scaleFactor);
+ QPointF localPos = pos;
+ if (topWindow()) {
+ const QPointF globalPosDelta = pos - pos.toPoint();
+ localPos = topWindow()->mapFromGlobal(pos.toPoint()) + globalPosDelta;
+ }
VirtualKeyModifiers modifiers;
args->get_KeyModifiers(&modifiers);
@@ -942,7 +1007,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
boolean isHorizontal;
properties->get_IsHorizontalMouseWheel(&isHorizontal);
QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta);
- QWindowSystemInterface::handleWheelEvent(topWindow(), pos, pos, QPoint(), angleDelta, mods);
+ QWindowSystemInterface::handleWheelEvent(topWindow(), localPos, pos, QPoint(), angleDelta, mods);
break;
}
@@ -968,7 +1033,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
if (isPressed)
buttons |= Qt::XButton2;
- QWindowSystemInterface::handleMouseEvent(topWindow(), pos, pos, buttons, mods);
+ QWindowSystemInterface::handleMouseEvent(topWindow(), localPos, pos, buttons, mods);
break;
}
@@ -1055,17 +1120,6 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
return S_OK;
}
-HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
-{
-#ifndef Q_OS_WINPHONE
- Q_D(const QWinRTScreen);
- args->put_AutomationProvider(d->inputContext.Get());
-#else
- Q_UNUSED(args)
-#endif
- return S_OK;
-}
-
HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *)
{
Q_D(QWinRTScreen);
@@ -1074,19 +1128,10 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
HRESULT hr;
hr = d->coreWindow->get_Bounds(&size);
RETURN_OK_IF_FAILED("Failed to get window bounds");
- QSizeF logicalSize = QSizeF(size.Width, size.Height);
-#ifndef Q_OS_WINPHONE // This handler is called from orientation changed, in which case we should always update the size
- if (d->logicalSize == logicalSize)
- return S_OK;
-#endif
-
- d->logicalSize = logicalSize;
- if (d->eglDisplay) {
- const QRect newGeometry = geometry();
- QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
- QPlatformScreen::resizeMaximizedWindows();
- handleExpose();
- }
+ d->logicalSize = QSizeF(size.Width, size.Height);
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
+ QPlatformScreen::resizeMaximizedWindows();
+ handleExpose();
return S_OK;
}
@@ -1110,31 +1155,6 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args
return S_OK;
}
-HRESULT QWinRTScreen::onSuspended(IInspectable *, ISuspendingEventArgs *)
-{
-#ifndef Q_OS_WINPHONE
- Q_D(QWinRTScreen);
- ComPtr<ID3D11Device> d3dDevice;
- const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, d->eglSurface, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
- if (ok && d3dDevice) {
- ComPtr<IDXGIDevice3> dxgiDevice;
- if (SUCCEEDED(d3dDevice.As(&dxgiDevice)))
- dxgiDevice->Trim();
- }
-#endif
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
- QWindowSystemInterface::flushWindowSystemEvents();
- return S_OK;
-}
-
-HRESULT QWinRTScreen::onResume(IInspectable *, IInspectable *)
-{
- // First the system invokes onResume and then changes
- // the visibility of the screen to be active.
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
- return S_OK;
-}
-
HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
{
foreach (QWindow *w, QGuiApplication::topLevelWindows())
@@ -1144,8 +1164,10 @@ HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEventArgs *args)
{
+ Q_D(QWinRTScreen);
boolean visible;
- args->get_Visible(&visible);
+ HRESULT hr = args ? args->get_Visible(&visible) : d->coreWindow->get_Visible(&visible);
+ RETURN_OK_IF_FAILED("Failed to get visbile.");
QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden);
if (visible)
handleExpose();
@@ -1163,12 +1185,12 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *
Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
if (d->orientation != newOrientation) {
d->orientation = newOrientation;
+#ifdef Q_OS_WINPHONE
+ onSizeChanged(nullptr, nullptr);
+#endif
QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
+ handleExpose(); // Clean broken frames caused by race between Qt and ANGLE
}
-
-#ifdef Q_OS_WINPHONE // The size changed handler is ignored in favor of this callback
- onSizeChanged(Q_NULLPTR, Q_NULLPTR);
-#endif
return S_OK;
}
@@ -1206,26 +1228,17 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
}
#ifdef Q_OS_WINPHONE
-HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
+HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *)
{
- Q_D(QWinRTScreen);
-
- QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
- QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
- backPress.setAccepted(false);
- backRelease.setAccepted(false);
-
- QObject *receiver = d->visibleWindows.isEmpty()
- ? static_cast<QObject *>(QGuiApplication::instance())
- : static_cast<QObject *>(d->visibleWindows.first());
-
- // If the event is ignored, the app will suspend
- QGuiApplication::sendEvent(receiver, &backPress);
- QGuiApplication::sendEvent(receiver, &backRelease);
- args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
+ onSizeChanged(nullptr, nullptr);
+ return S_OK;
+}
+HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *)
+{
+ onSizeChanged(nullptr, nullptr);
return S_OK;
}
-#endif // Q_OS_WINPHONE
+#endif //Q_OS_WINPHONE
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index d34ce75748..0043b2cfa3 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -40,8 +40,6 @@
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
-#include <EGL/egl.h>
-
namespace ABI {
namespace Windows {
namespace ApplicationModel {
@@ -59,21 +57,19 @@ namespace ABI {
struct IWindowActivatedEventArgs;
struct IWindowSizeChangedEventArgs;
}
+ namespace Xaml {
+ struct IDependencyObject;
+ struct IWindow;
+ }
+ namespace ViewManagement {
+ struct IStatusBar;
+ }
}
namespace Graphics {
namespace Display {
struct IDisplayInformation;
}
}
-#ifdef Q_OS_WINPHONE
- namespace Phone {
- namespace UI {
- namespace Input {
- struct IBackPressedEventArgs;
- }
- }
- }
-#endif
}
}
struct IInspectable;
@@ -81,7 +77,6 @@ struct IInspectable;
QT_BEGIN_NAMESPACE
class QTouchDevice;
-class QWinRTEGLContext;
class QWinRTCursor;
class QWinRTInputContext;
class QWinRTScreenPrivate;
@@ -90,19 +85,20 @@ class QWinRTScreen : public QPlatformScreen
public:
explicit QWinRTScreen();
~QWinRTScreen();
- QRect geometry() const;
- int depth() const;
- QImage::Format format() const;
- QSurfaceFormat surfaceFormat() const;
+ QRect geometry() const Q_DECL_OVERRIDE;
+#ifdef Q_OS_WINPHONE
+ QRect availableGeometry() const Q_DECL_OVERRIDE;
+#endif
+ int depth() const Q_DECL_OVERRIDE;
+ QImage::Format format() const Q_DECL_OVERRIDE;
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
qreal scaleFactor() const;
- QWinRTInputContext *inputContext() const;
- QPlatformCursor *cursor() const;
+ QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
Qt::KeyboardModifiers keyboardModifiers() const;
- Qt::ScreenOrientation nativeOrientation() const;
- Qt::ScreenOrientation orientation() const;
+ Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
+ Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
QWindow *topWindow() const;
void addWindow(QWindow *window);
@@ -110,10 +106,16 @@ public:
void raise(QWindow *window);
void lower(QWindow *window);
+ void updateWindowTitle();
+
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
- EGLDisplay eglDisplay() const; // To opengl context
- EGLSurface eglSurface() const; // To window
- EGLConfig eglConfig() const;
+ ABI::Windows::UI::Xaml::IDependencyObject *canvas() const;
+
+#ifdef Q_OS_WINPHONE
+ void setStatusBarVisibility(bool visible, QWindow *window);
+#endif
+
+ void initialize();
private:
void handleExpose();
@@ -127,18 +129,16 @@ private:
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *);
- HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
- HRESULT onResume(IInspectable *, IInspectable *);
HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *);
HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *);
- HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *);
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
#ifdef Q_OS_WINPHONE
- HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
+ HRESULT onStatusBarShowing(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *);
+ HRESULT onStatusBarHiding(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *);
#endif
QScopedPointer<QWinRTScreenPrivate> d_ptr;
diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp
index a0fa2798a8..7d09551f5b 100644
--- a/src/plugins/platforms/winrt/qwinrttheme.cpp
+++ b/src/plugins/platforms/winrt/qwinrttheme.cpp
@@ -44,7 +44,13 @@
#include <wrl.h>
#include <windows.ui.h>
#include <windows.ui.viewmanagement.h>
+#if _MSC_VER >= 1900
+#include <windows.foundation.metadata.h>
+using namespace ABI::Windows::Foundation::Metadata;
+#endif
+
using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::ViewManagement;
@@ -73,102 +79,215 @@ static inline QColor fromColor(const Color &color)
return QColor(color.R, color.G, color.B, color.A);
}
-QWinRTTheme::QWinRTTheme()
- : d_ptr(new QWinRTThemePrivate)
+#if _MSC_VER >= 1900
+static bool uiColorSettings(const wchar_t *value, UIElementType type, Color *color)
{
- Q_D(QWinRTTheme);
+ static ComPtr<IApiInformationStatics> apiInformationStatics;
+ HRESULT hr;
+ if (!apiInformationStatics) {
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(),
+ IID_PPV_ARGS(&apiInformationStatics));
+ RETURN_FALSE_IF_FAILED("Could not get ApiInformationStatics");
+ }
+
+ static const HStringReference enumRef(L"Windows.UI.ViewManagement.UIElementType");
+ HStringReference valueRef(value);
+
+ boolean exists;
+ hr = apiInformationStatics->IsEnumNamedValuePresent(enumRef.Get(), valueRef.Get(), &exists);
+
+ if (hr != S_OK || !exists)
+ return false;
+
+ return SUCCEEDED(uiSettings()->UIElementColor(type, color));
+}
+
+static void nativeColorSettings(QPalette &p)
+{
+ Color color;
+
+ if (uiColorSettings(L"ActiveCaption", UIElementType_ActiveCaption, &color))
+ p.setColor(QPalette::ToolTipBase, fromColor(color));
+
+ if (uiColorSettings(L"Background", UIElementType_Background, &color))
+ p.setColor(QPalette::AlternateBase, fromColor(color));
+
+ if (uiColorSettings(L"ButtonFace", UIElementType_ButtonFace, &color)) {
+ p.setColor(QPalette::Button, fromColor(color));
+ p.setColor(QPalette::Midlight, fromColor(color).lighter(110));
+ p.setColor(QPalette::Light, fromColor(color).lighter(150));
+ p.setColor(QPalette::Mid, fromColor(color).dark(130));
+ p.setColor(QPalette::Dark, fromColor(color).dark(150));
+ }
+
+ if (uiColorSettings(L"ButtonText", UIElementType_ButtonText, &color)) {
+ p.setColor(QPalette::ButtonText, fromColor(color));
+ p.setColor(QPalette::Text, fromColor(color));
+ }
+
+ if (uiColorSettings(L"CaptionText", UIElementType_CaptionText, &color))
+ p.setColor(QPalette::ToolTipText, fromColor(color));
+
+ if (uiColorSettings(L"Highlight", UIElementType_Highlight, &color))
+ p.setColor(QPalette::Highlight, fromColor(color));
+
+ if (uiColorSettings(L"HighlightText", UIElementType_HighlightText, &color))
+ p.setColor(QPalette::HighlightedText, fromColor(color));
+
+ if (uiColorSettings(L"Window", UIElementType_Window, &color)) {
+ p.setColor(QPalette::Window, fromColor(color));
+ p.setColor(QPalette::Base, fromColor(color));
+ }
+
+ if (uiColorSettings(L"Hotlight", UIElementType_Hotlight, &color))
+ p.setColor(QPalette::BrightText, fromColor(color));
+ //Phone related
+ if (uiColorSettings(L"PopupBackground", UIElementType_PopupBackground, &color)) {
+ p.setColor(QPalette::ToolTipBase, fromColor(color));
+ p.setColor(QPalette::AlternateBase, fromColor(color));
+ }
+
+ if (uiColorSettings(L"NonTextMedium", UIElementType_NonTextMedium, &color))
+ p.setColor(QPalette::Button, fromColor(color));
+
+ if (uiColorSettings(L"NonTextMediumHigh", UIElementType_NonTextMediumHigh, &color))
+ p.setColor(QPalette::Midlight, fromColor(color));
+
+ if (uiColorSettings(L"NonTextHigh", UIElementType_NonTextHigh, &color))
+ p.setColor(QPalette::Light, fromColor(color));
+
+ if (uiColorSettings(L"NonTextMediumLow", UIElementType_NonTextMediumLow, &color))
+ p.setColor(QPalette::Mid, fromColor(color));
+
+ if (uiColorSettings(L"NonTextLow", UIElementType_NonTextLow, &color))
+ p.setColor(QPalette::Dark, fromColor(color));
+
+ if (uiColorSettings(L"TextHigh", UIElementType_TextHigh, &color)) {
+ p.setColor(QPalette::ButtonText, fromColor(color));
+ p.setColor(QPalette::Text, fromColor(color));
+ p.setColor(QPalette::WindowText, fromColor(color));
+ }
+
+ if (uiColorSettings(L"TextMedium", UIElementType_TextMedium, &color))
+ p.setColor(QPalette::ToolTipText, fromColor(color));
+
+ if (uiColorSettings(L"AccentColor", UIElementType_AccentColor, &color))
+ p.setColor(QPalette::Highlight, fromColor(color));
+
+ if (uiColorSettings(L"PageBackground", UIElementType_PageBackground, &color)) {
+ p.setColor(QPalette::Window, fromColor(color));
+ p.setColor(QPalette::Base, fromColor(color));
+ }
+
+ if (uiColorSettings(L"TextContrastWithHigh", UIElementType_TextContrastWithHigh, &color))
+ p.setColor(QPalette::BrightText, fromColor(color));
+}
+
+#else // _MSC_VER >= 1900
+
+static void nativeColorSettings(QPalette &p)
+{
HRESULT hr;
Color color;
#ifdef Q_OS_WINPHONE
hr = uiSettings()->UIElementColor(UIElementType_PopupBackground, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ToolTipBase, fromColor(color));
- d->palette.setColor(QPalette::AlternateBase, fromColor(color));
+ p.setColor(QPalette::ToolTipBase, fromColor(color));
+ p.setColor(QPalette::AlternateBase, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_NonTextMedium, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Button, fromColor(color));
+ p.setColor(QPalette::Button, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_NonTextMediumHigh, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Midlight, fromColor(color));
+ p.setColor(QPalette::Midlight, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_NonTextHigh, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Light, fromColor(color));
+ p.setColor(QPalette::Light, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_NonTextMediumLow, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Mid, fromColor(color));
+ p.setColor(QPalette::Mid, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_NonTextLow, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Dark, fromColor(color));
+ p.setColor(QPalette::Dark, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_TextHigh, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ButtonText, fromColor(color));
- d->palette.setColor(QPalette::Text, fromColor(color));
- d->palette.setColor(QPalette::WindowText, fromColor(color));
+ p.setColor(QPalette::ButtonText, fromColor(color));
+ p.setColor(QPalette::Text, fromColor(color));
+ p.setColor(QPalette::WindowText, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_TextMedium, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ToolTipText, fromColor(color));
+ p.setColor(QPalette::ToolTipText, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_AccentColor, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Highlight, fromColor(color));
+ p.setColor(QPalette::Highlight, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_PageBackground, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Window, fromColor(color));
- d->palette.setColor(QPalette::Base, fromColor(color));
+ p.setColor(QPalette::Window, fromColor(color));
+ p.setColor(QPalette::Base, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_TextContrastWithHigh, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::BrightText, fromColor(color));
+ p.setColor(QPalette::BrightText, fromColor(color));
#else
hr = uiSettings()->UIElementColor(UIElementType_ActiveCaption, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ToolTipBase, fromColor(color));
+ p.setColor(QPalette::ToolTipBase, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_Background, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::AlternateBase, fromColor(color));
+ p.setColor(QPalette::AlternateBase, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_ButtonFace, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Button, fromColor(color));
- d->palette.setColor(QPalette::Midlight, fromColor(color).lighter(110));
- d->palette.setColor(QPalette::Light, fromColor(color).lighter(150));
- d->palette.setColor(QPalette::Mid, fromColor(color).dark(130));
- d->palette.setColor(QPalette::Dark, fromColor(color).dark(150));
+ p.setColor(QPalette::Button, fromColor(color));
+ p.setColor(QPalette::Midlight, fromColor(color).lighter(110));
+ p.setColor(QPalette::Light, fromColor(color).lighter(150));
+ p.setColor(QPalette::Mid, fromColor(color).dark(130));
+ p.setColor(QPalette::Dark, fromColor(color).dark(150));
hr = uiSettings()->UIElementColor(UIElementType_ButtonText, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ButtonText, fromColor(color));
- d->palette.setColor(QPalette::Text, fromColor(color));
+ p.setColor(QPalette::ButtonText, fromColor(color));
+ p.setColor(QPalette::Text, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_CaptionText, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::ToolTipText, fromColor(color));
+ p.setColor(QPalette::ToolTipText, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_Highlight, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Highlight, fromColor(color));
+ p.setColor(QPalette::Highlight, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_HighlightText, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::HighlightedText, fromColor(color));
+ p.setColor(QPalette::HighlightedText, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_Window, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::Window, fromColor(color));
- d->palette.setColor(QPalette::Base, fromColor(color));
+ p.setColor(QPalette::Window, fromColor(color));
+ p.setColor(QPalette::Base, fromColor(color));
hr = uiSettings()->UIElementColor(UIElementType_Hotlight, &color);
Q_ASSERT_SUCCEEDED(hr);
- d->palette.setColor(QPalette::BrightText, fromColor(color));
+ p.setColor(QPalette::BrightText, fromColor(color));
#endif
}
+#endif // _MSC_VER < 1900
+
+QWinRTTheme::QWinRTTheme()
+ : d_ptr(new QWinRTThemePrivate)
+{
+ Q_D(QWinRTTheme);
+
+ nativeColorSettings(d->palette);
+}
bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const
{
@@ -218,7 +337,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint)
case QPlatformIntegration::KeyboardAutoRepeatRate:
return defaultThemeHint(KeyboardAutoRepeatRate);
case QPlatformIntegration::ShowIsFullScreen:
- return true;
+ return false;
case QPlatformIntegration::PasswordMaskDelay:
return defaultThemeHint(PasswordMaskDelay);
case QPlatformIntegration::FontSmoothingGamma:
@@ -232,7 +351,7 @@ QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint)
case QPlatformIntegration::SetFocusOnTouchRelease:
return false;
case QPlatformIntegration::ShowIsMaximized:
- return false;
+ return true;
case QPlatformIntegration::MousePressAndHoldInterval:
return defaultThemeHint(MousePressAndHoldInterval);
default:
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index adc5dfb776..bec94c1e51 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -36,47 +36,164 @@
#include "qwinrtwindow.h"
#include "qwinrtscreen.h"
+#include <private/qeventdispatcher_winrt_p.h>
-#include <qpa/qwindowsysteminterface.h>
+#include <EGL/egl.h>
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/eglext.h>
+
+#include <qfunctions_winrt.h>
#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QWindow>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
-#include <qfunctions_winrt.h>
-#include <windows.ui.viewmanagement.h>
+#include <functional>
#include <wrl.h>
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.controls.h>
+#include <windows.ui.viewmanagement.h>
using namespace ABI::Windows::UI::ViewManagement;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Controls;
QT_BEGIN_NAMESPACE
+static void setUIElementVisibility(IUIElement *uiElement, bool visibility)
+{
+ Q_ASSERT(uiElement);
+ QEventDispatcherWinRT::runOnXamlThread([uiElement, visibility]() {
+ HRESULT hr;
+ hr = uiElement->put_Visibility(visibility ? Visibility_Visible : Visibility_Collapsed);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+
+class QWinRTWindowPrivate
+{
+public:
+ QWinRTScreen *screen;
+
+ QSurfaceFormat surfaceFormat;
+ QString windowTitle;
+ Qt::WindowState state;
+ EGLDisplay display;
+ EGLSurface surface;
+
+ ComPtr<ISwapChainPanel> swapChainPanel;
+ ComPtr<ICanvasStatics> canvas;
+ ComPtr<IUIElement> uiElement;
+};
+
QWinRTWindow::QWinRTWindow(QWindow *window)
: QPlatformWindow(window)
- , m_screen(static_cast<QWinRTScreen*>(screen()))
+ , d_ptr(new QWinRTWindowPrivate)
{
+ Q_D(QWinRTWindow);
+
+ d->surface = EGL_NO_SURFACE;
+ d->display = EGL_NO_DISPLAY;
+ d->screen = static_cast<QWinRTScreen *>(screen());
setWindowFlags(window->flags());
setWindowState(window->windowState());
setWindowTitle(window->title());
handleContentOrientationChange(window->contentOrientation());
+
+ d->surfaceFormat.setAlphaBufferSize(0);
+ d->surfaceFormat.setRedBufferSize(8);
+ d->surfaceFormat.setGreenBufferSize(8);
+ d->surfaceFormat.setBlueBufferSize(8);
+ d->surfaceFormat.setDepthBufferSize(24);
+ d->surfaceFormat.setStencilBufferSize(8);
+ d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+ d->surfaceFormat.setSamples(1);
+ d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(),
+ IID_PPV_ARGS(&d->canvas));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ // Create a new swapchain and place it inside the canvas
+ HRESULT hr;
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
+ &d->swapChainPanel);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->swapChainPanel.As(&d->uiElement);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
+ hr = canvas.As(&panel);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVector<UIElement *>> children;
+ hr = panel->get_Children(&children);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = children->Append(d->uiElement.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+
setGeometry(window->geometry());
}
QWinRTWindow::~QWinRTWindow()
{
- m_screen->removeWindow(window());
+ Q_D(QWinRTWindow);
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ HRESULT hr;
+ ComPtr<IDependencyObject> canvas = d->screen->canvas();
+ ComPtr<IPanel> panel;
+ hr = canvas.As(&panel);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVector<UIElement *>> children;
+ hr = panel->get_Children(&children);
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 index;
+ boolean found;
+ hr = children->IndexOf(d->uiElement.Get(), &index, &found);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (found) {
+ hr = children->RemoveAt(index);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ return S_OK;
+ });
+ RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
+
+ if (!d->surface)
+ return;
+
+ EGLBoolean value = eglDestroySurface(d->display, d->surface);
+ d->surface = EGL_NO_SURFACE;
+ if (value == EGL_FALSE)
+ qCritical("Failed to destroy EGL window surface: 0x%x", eglGetError());
}
QSurfaceFormat QWinRTWindow::format() const
{
- return m_screen->surfaceFormat();
+ Q_D(const QWinRTWindow);
+ return d->surfaceFormat;
}
bool QWinRTWindow::isActive() const
{
- return m_screen->topWindow() == window();
+ Q_D(const QWinRTWindow);
+ return d->screen->topWindow() == window();
}
bool QWinRTWindow::isExposed() const
@@ -87,55 +204,82 @@ bool QWinRTWindow::isExposed() const
void QWinRTWindow::setGeometry(const QRect &rect)
{
- if (window()->isTopLevel()) {
- QPlatformWindow::setGeometry(m_screen->geometry());
+ Q_D(QWinRTWindow);
+
+ const Qt::WindowFlags windowFlags = window()->flags();
+ const Qt::WindowFlags windowType = windowFlags & Qt::WindowType_Mask;
+ if (window()->isTopLevel() && (windowType == Qt::Window || windowType == Qt::Dialog)) {
+ QPlatformWindow::setGeometry(windowFlags & Qt::MaximizeUsingFullscreenGeometryHint
+ ? d->screen->geometry() : d->screen->availableGeometry());
QWindowSystemInterface::handleGeometryChange(window(), geometry());
} else {
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
}
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ HRESULT hr;
+ const QRect windowGeometry = geometry();
+ const QPointF topLeft= QPointF(windowGeometry.topLeft()) / d->screen->scaleFactor();
+ hr = d->canvas->SetTop(d->uiElement.Get(), topLeft.y());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->canvas->SetLeft(d->uiElement.Get(), topLeft.x());
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<Xaml::IFrameworkElement> frameworkElement;
+ hr = d->swapChainPanel.As(&frameworkElement);
+ Q_ASSERT_SUCCEEDED(hr);
+ const QSizeF size = QSizeF(windowGeometry.size()) / d->screen->scaleFactor();
+ hr = frameworkElement->put_Width(size.width());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = frameworkElement->put_Height(size.height());
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
}
void QWinRTWindow::setVisible(bool visible)
{
+ Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
- if (visible)
- m_screen->addWindow(window());
- else
- m_screen->removeWindow(window());
+ if (visible) {
+ d->screen->addWindow(window());
+ setUIElementVisibility(d->uiElement.Get(), d->state != Qt::WindowMinimized);
+ } else {
+ d->screen->removeWindow(window());
+ setUIElementVisibility(d->uiElement.Get(), false);
+ }
}
void QWinRTWindow::setWindowTitle(const QString &title)
{
- ComPtr<IApplicationViewStatics2> statics;
- HRESULT hr;
-
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
- IID_PPV_ARGS(&statics));
- RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
-
- ComPtr<IApplicationView> view;
- hr = statics->GetForCurrentView(&view);
- RETURN_VOID_IF_FAILED("Could not access currentView");
-
- HStringReference str(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
- hr = view->put_Title(str.Get());
- RETURN_VOID_IF_FAILED("Unable to set window title");
+ Q_D(QWinRTWindow);
+ d->windowTitle = title;
+ d->screen->updateWindowTitle();
}
void QWinRTWindow::raise()
{
+ Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
- m_screen->raise(window());
+ d->screen->raise(window());
}
void QWinRTWindow::lower()
{
+ Q_D(QWinRTWindow);
if (!window()->isTopLevel())
return;
- m_screen->lower(window());
+ d->screen->lower(window());
+}
+
+WId QWinRTWindow::winId() const
+{
+ Q_D(const QWinRTWindow);
+ return WId(d->swapChainPanel.Get());
}
qreal QWinRTWindow::devicePixelRatio() const
@@ -143,4 +287,45 @@ qreal QWinRTWindow::devicePixelRatio() const
return screen()->devicePixelRatio();
}
+void QWinRTWindow::setWindowState(Qt::WindowState state)
+{
+ Q_D(QWinRTWindow);
+ if (d->state == state)
+ return;
+
+#ifdef Q_OS_WINPHONE
+ d->screen->setStatusBarVisibility(state == Qt::WindowMaximized || state == Qt::WindowNoState, window());
+#endif
+
+ if (state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), false);
+
+ if (d->state == Qt::WindowMinimized)
+ setUIElementVisibility(d->uiElement.Get(), true);
+
+ d->state = state;
+}
+
+EGLSurface QWinRTWindow::eglSurface() const
+{
+ Q_D(const QWinRTWindow);
+ return d->surface;
+}
+
+void QWinRTWindow::createEglSurface(EGLDisplay display, EGLConfig config)
+{
+ Q_D(QWinRTWindow);
+ if (d->surface == EGL_NO_SURFACE) {
+ d->display = display;
+ QEventDispatcherWinRT::runOnXamlThread([this, d, display, config]() {
+ d->surface = eglCreateWindowSurface(display, config,
+ reinterpret_cast<EGLNativeWindowType>(winId()),
+ nullptr);
+ if (d->surface == EGL_NO_SURFACE)
+ qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
+ return S_OK;
+ });
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index 3cfe346ab2..9ac7adbf4d 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -39,11 +39,11 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
+#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
-class QWinRTScreen;
-
+class QWinRTWindowPrivate;
class QWinRTWindow : public QPlatformWindow
{
public:
@@ -59,10 +59,17 @@ public:
void raise();
void lower();
+ WId winId() const Q_DECL_OVERRIDE;
+
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+
+ EGLSurface eglSurface() const;
+ void createEglSurface(EGLDisplay display, EGLConfig config);
private:
- QWinRTScreen *m_screen;
+ QScopedPointer<QWinRTWindowPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTWindow)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 80429daeed..be6aad02d1 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -1,14 +1,6 @@
TARGET = qwinrt
CONFIG -= precompile_header
-# For Windows Phone 8 we have to deploy fonts together with the application as DirectWrite
-# is not supported here.
-winphone:equals(WINSDK_VER, 8.0): {
- fonts.path = $$[QT_INSTALL_LIBS]/fonts
- fonts.files = $$QT_SOURCE_TREE/lib/fonts/DejaVu*.ttf
- INSTALLS += fonts
-}
-
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
@@ -18,13 +10,8 @@ QT += core-private gui-private platformsupport-private
DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES
-LIBS += $$QMAKE_LIBS_CORE
-
-!if(winphone:equals(WINSDK_VER, 8.0)) {
- LIBS += -ldwrite
- INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include
- DEFINES += QT_WINRT_USE_DWRITE
-}
+LIBS += $$QMAKE_LIBS_CORE -ldwrite -ld3d11
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include
SOURCES = \
main.cpp \
@@ -60,9 +47,4 @@ HEADERS = \
qwinrttheme.h \
qwinrtwindow.h
-winphone:equals(WINSDK_VER, 8.0): {
- SOURCES -= qwinrtplatformmessagedialoghelper.cpp
- HEADERS -= qwinrtplatformmessagedialoghelper.h
-}
-
OTHER_FILES += winrt.json
diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp
index 10411e72e2..508f5e82e6 100644
--- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp
@@ -78,6 +78,7 @@ QStringList QXcbGlIntegrationFactory::keys(const QString &pluginPath)
list.append(loader()->keyMap().values());
return list;
#else
+ Q_UNUSED(pluginPath);
return QStringList();
#endif
}
@@ -93,6 +94,9 @@ QXcbGlIntegration *QXcbGlIntegrationFactory::create(const QString &platform, con
}
if (QXcbGlIntegration *ret = loadIntegration(loader(), platform))
return ret;
+#else
+ Q_UNUSED(platform);
+ Q_UNUSED(pluginPath);
#endif
return Q_NULLPTR;
}
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 8b14fc7d70..37f01d4eed 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -188,16 +188,18 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
Window window = 0; // Temporary window used to query OpenGL context
if (config) {
+ const QByteArrayList glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' ');
+
// Resolve entry point for glXCreateContextAttribsARB
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
- glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
+ if (glxExt.contains("GLX_ARB_create_context"))
+ glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
- QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' ');
- bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
+ const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
// Use glXCreateContextAttribsARB if available
// Also, GL ES context creation requires GLX_EXT_create_context_es2_profile
- if (glxExt.contains("GLX_ARB_create_context") && glXCreateContextAttribsARB != 0
+ if (glXCreateContextAttribsARB != 0
&& (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
// Try to create an OpenGL context for each known OpenGL version in descending
// order from the requested version.
@@ -561,10 +563,12 @@ void (*QGLXContext::getProcAddress(const QByteArray &procName)) ()
if (!glXGetProcAddressARB)
#endif
{
+#ifndef QT_NO_LIBRARY
extern const QString qt_gl_library_name();
// QLibrary lib(qt_gl_library_name());
QLibrary lib(QLatin1String("GL"));
glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
+#endif
}
}
resolved = true;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro
index 57cd81ec3b..1c577e5dc9 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro
@@ -17,6 +17,8 @@ contains(QT_CONFIG, xcb-glx) {
LIBS += -lxcb-glx
}
+LIBS += $$QMAKE_LIBS_DYNLOAD
+
HEADERS += \
qxcbglxintegration.h \
qxcbglxwindow.h \
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index c0f5477f82..1825a463d0 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -49,6 +49,7 @@
#include <qdebug.h>
#include <qpainter.h>
#include <qscreen.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <qpa/qplatformgraphicsbuffer.h>
#include <algorithm>
@@ -145,8 +146,8 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
if (id == -1)
- qWarning("QXcbShmImage: shmget() failed (%d) for size %d (%dx%d)",
- errno, segmentSize, size.width(), size.height());
+ qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %d (%dx%d)",
+ errno, strerror(errno), segmentSize, size.width(), size.height());
else
m_shm_info.shmid = id;
m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat (m_shm_info.shmid, 0, 0);
@@ -310,17 +311,13 @@ QPaintDevice *QXcbBackingStore::paintDevice()
void QXcbBackingStore::beginPaint(const QRegion &region)
{
+ if (!m_image && !m_size.isEmpty())
+ resize(m_size, QRegion());
+
if (!m_image)
return;
-
- int dpr = int(m_image->image()->devicePixelRatio());
- const int windowDpr = int(window()->devicePixelRatio());
- if (windowDpr != dpr) {
- resize(window()->size(), QRegion());
- dpr = int(m_image->image()->devicePixelRatio());
- }
-
- m_paintRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region);
+ m_size = QSize();
+ m_paintRegion = region;
m_image->preparePaint(m_paintRegion);
if (m_image->image()->hasAlphaChannel()) {
@@ -369,18 +366,10 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
if (!m_image || m_image->size().isEmpty())
return;
- const int dpr = int(window->devicePixelRatio());
-
-#ifndef QT_NO_DEBUG
- const int imageDpr = int(m_image->image()->devicePixelRatio());
- if (dpr != imageDpr)
- qWarning() << "QXcbBackingStore::flush() wrong devicePixelRatio for backingstore image" << dpr << imageDpr;
-#endif
-
- QSize imageSize = m_image->size() / dpr; //because we multiply with the DPR later
+ QSize imageSize = m_image->size();
QRegion clipped = region;
- clipped &= QRect(0, 0, window->width(), window->height());
+ clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window));
clipped &= QRect(0, 0, imageSize.width(), imageSize.height()).translated(-offset);
QRect bounds = clipped.boundingRect();
@@ -398,8 +387,8 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
QVector<QRect> rects = clipped.rects();
for (int i = 0; i < rects.size(); ++i) {
- QRect rect = QRect(rects.at(i).topLeft() * dpr, rects.at(i).size() * dpr);
- m_image->put(platformWindow->xcb_window(), rect.topLeft(), rect.translated(offset * dpr));
+ QRect rect = QRect(rects.at(i).topLeft(), rects.at(i).size());
+ m_image->put(platformWindow->xcb_window(), rect.topLeft(), rect.translated(offset));
}
Q_XCB_NOOP(connection());
@@ -430,13 +419,12 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion &region, c
void QXcbBackingStore::resize(const QSize &size, const QRegion &)
{
- const int dpr = int(window()->devicePixelRatio());
- const QSize xSize = size * dpr;
- if (m_image && xSize == m_image->size() && dpr == m_image->image()->devicePixelRatio())
+ if (m_image && size == m_image->size())
return;
Q_XCB_NOOP(connection());
- QXcbScreen *screen = static_cast<QXcbScreen *>(window()->screen()->handle());
+
+ QXcbScreen *screen = window()->screen() ? static_cast<QXcbScreen *>(window()->screen()->handle()) : 0;
QPlatformWindow *pw = window()->handle();
if (!pw) {
window()->create();
@@ -445,13 +433,16 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
QXcbWindow* win = static_cast<QXcbWindow *>(pw);
delete m_image;
- m_image = new QXcbShmImage(screen, xSize, win->depth(), win->imageFormat());
- m_image->image()->setDevicePixelRatio(dpr);
+ if (!screen) {
+ m_image = 0;
+ m_size = size;
+ return;
+ }
+ m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat());
// Slow path for bgr888 VNC: Create an additional image, paint into that and
// swap R and B while copying to m_image after each paint.
if (win->imageNeedsRgbSwap()) {
- m_rgbImage = QImage(xSize, win->imageFormat());
- m_rgbImage.setDevicePixelRatio(dpr);
+ m_rgbImage = QImage(size, win->imageFormat());
}
Q_XCB_NOOP(connection());
}
@@ -463,14 +454,12 @@ bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
if (!m_image || m_image->image()->isNull())
return false;
- const int dpr = int(m_image->image()->devicePixelRatio());
- QRegion xArea = dpr == 1 ? area : QTransform::fromScale(dpr,dpr).map(area);
m_image->preparePaint(area);
- QPoint delta(dx * dpr, dy * dpr);
- const QVector<QRect> xRects = xArea.rects();
- for (int i = 0; i < xRects.size(); ++i)
- qt_scrollRectInImage(*m_image->image(), xRects.at(i), delta);
+ QPoint delta(dx, dy);
+ const QVector<QRect> rects = area.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ qt_scrollRectInImage(*m_image->image(), rects.at(i), delta);
return true;
}
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index b58a32d313..1bea36d423 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -71,6 +71,7 @@ private:
QXcbShmImage *m_image;
QRegion m_paintRegion;
QImage m_rgbImage;
+ QSize m_size;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 248d1b4bbb..8b75c130fb 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -275,22 +275,8 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
m_clientClipboard[QClipboard::Selection] = 0;
m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME;
m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME;
+ m_owner = connection()->getQtSelectionOwner();
- QXcbScreen *platformScreen = screen();
-
- int x = 0, y = 0, w = 3, h = 3;
-
- m_owner = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- m_owner, // window id
- platformScreen->screen()->root, // parent window id
- x, y, w, h,
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- platformScreen->screen()->root_visual, // visual
- 0, // value mask
- 0)); // value list
#ifndef QT_NO_DEBUG
QByteArray ba("Qt clipboard window");
Q_XCB_CALL(xcb_change_property(xcb_connection(),
@@ -353,13 +339,7 @@ void QXcbClipboard::incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepte
xcb_window_t QXcbClipboard::getSelectionOwner(xcb_atom_t atom) const
{
- xcb_connection_t *c = xcb_connection();
- xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom);
- xcb_get_selection_owner_reply_t *reply;
- reply = xcb_get_selection_owner_reply(c, cookie, 0);
- xcb_window_t win = reply->owner;
- free(reply);
- return win;
+ return connection()->getSelectionOwner(atom);
}
xcb_atom_t QXcbClipboard::atomForMode(QClipboard::Mode mode) const
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index d2e08aecee..50d49ca798 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -107,6 +107,24 @@ Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
#define XCB_GE_GENERIC 35
#endif
+// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
+// - "pad0" became "extension"
+// - "pad1" and "pad" became "pad0"
+// New and old version of this struct share the following fields:
+typedef struct qt_xcb_ge_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+} qt_xcb_ge_event_t;
+
+static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
+{
+ qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event;
+ return e->extension == opCode;
+}
+
#ifdef XCB_USE_XLIB
static const char * const xcbConnectionErrors[] = {
"No error", /* Error 0 */
@@ -245,8 +263,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Known screen removed -> delete it
m_screens.removeOne(screen);
- foreach (QXcbScreen *otherScreen, m_screens)
- otherScreen->removeVirtualSibling((QPlatformScreen *) screen);
+ virtualDesktop->removeScreen(screen);
QXcbIntegration::instance()->destroyScreen(screen);
@@ -265,9 +282,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
- foreach (QXcbScreen *otherScreen, m_screens)
- if (otherScreen->root() == output.window)
- otherScreen->addVirtualSibling(screen);
+ virtualDesktop->addScreen(screen);
m_screens << screen;
QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
@@ -290,8 +305,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
m_screens.removeOne(screen);
- foreach (QXcbScreen *otherScreen, m_screens)
- otherScreen->removeVirtualSibling((QPlatformScreen *) screen);
+ virtualDesktop->removeScreen(screen);
QXcbIntegration::instance()->destroyScreen(screen);
} else {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
@@ -305,13 +319,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
screen->updateRefreshRate(output.mode);
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
- // TODO: add a proper mechanism for updating primary screen
if (!wasPrimary && screen->isPrimary()) {
- QScreen *realScreen = static_cast<QPlatformScreen*>(screen)->screen();
- QGuiApplicationPrivate::screen_list.removeOne(realScreen);
- QGuiApplicationPrivate::screen_list.prepend(realScreen);
- m_screens.removeOne(screen);
- m_screens.prepend(screen);
+ const int idx = m_screens.indexOf(screen);
+ m_screens.swap(0, idx);
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
}
qCDebug(lcQpaScreen) << "output has changed" << screen;
}
@@ -428,12 +439,14 @@ void QXcbConnection::initializeScreens()
}
}
}
- foreach (QPlatformScreen* s, siblings)
- ((QXcbScreen*)s)->setVirtualSiblings(siblings);
+ virtualDesktop->setScreens(siblings);
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
+ foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
+ virtualDesktop->subscribeToXFixesSelectionNotify();
+
// If there's no randr extension, or there was some error above, or we found a
// screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X),
// but the dimensions are known anyway, and we don't already have any lingering
@@ -442,7 +455,7 @@ void QXcbConnection::initializeScreens()
QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
- screen->setVirtualSiblings(QList<QPlatformScreen *>() << screen);
+ virtualDesktop->setScreens(QList<QPlatformScreen *>() << screen);
m_screens << screen;
primaryScreen = screen;
primaryScreen->setPrimary(true);
@@ -461,7 +474,7 @@ void QXcbConnection::initializeScreens()
// Push the screens to QApplication
QXcbIntegration *integration = QXcbIntegration::instance();
foreach (QXcbScreen* screen, m_screens) {
- qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')';
integration->screenAdded(screen, screen->isPrimary());
}
@@ -492,6 +505,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
, m_systemTrayTracker(0)
, m_glIntegration(Q_NULLPTR)
, m_xiGrab(false)
+ , m_qtSelectionOwner(0)
{
#ifdef XCB_USE_XLIB
Display *dpy = XOpenDisplay(m_displayName.constData());
@@ -536,12 +550,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_netWmUserTime = XCB_CURRENT_TIME;
initializeXRandr();
+ initializeXFixes();
initializeScreens();
if (m_screens.isEmpty())
qFatal("QXcbConnection: no screens available");
- initializeXFixes();
initializeXRender();
m_xi2Enabled = false;
#if defined(XCB_USE_XINPUT2)
@@ -590,9 +604,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration";
sync();
-
- if (qEnvironmentVariableIsEmpty("QT_IM_MODULE"))
- qputenv("QT_IM_MODULE", QByteArray("compose"));
}
QXcbConnection::~QXcbConnection()
@@ -1075,8 +1086,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_FOCUS_OUT:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
case XCB_KEY_PRESS:
- m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state);
+ {
+ xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
+ m_keyboard->updateXKBStateFromCore(kp->state);
+ setTime(kp->time);
HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
+ }
case XCB_KEY_RELEASE:
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
@@ -1110,12 +1125,21 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
handled = false;
break;
case XCB_PROPERTY_NOTIFY:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
+ {
+ xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) {
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window);
+ if (virtualDesktop)
+ virtualDesktop->updateWorkArea();
+ } else {
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
+ }
break;
+ }
#if defined(XCB_USE_XINPUT2)
case XCB_GE_GENERIC:
// Here the windowEventListener is invoked from xi2HandleEvent()
- if (m_xi2Enabled)
+ if (m_xi2Enabled && isXIEvent(event, m_xiOpCode))
xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
break;
#endif
@@ -1127,10 +1151,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (!handled) {
if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
- setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
+ xcb_xfixes_selection_notify_event_t *notify_event = (xcb_xfixes_selection_notify_event_t *)event;
+ setTime(notify_event->timestamp);
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
+ m_clipboard->handleXFixesSelectionRequest(notify_event);
#endif
+ foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
+ virtualDesktop->handleXFixesSelectionNotify(notify_event);
+
handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
updateScreens((xcb_randr_notify_event_t *)event);
@@ -1288,10 +1316,12 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
memset(&event, 0, sizeof(event));
const xcb_window_t eventListener = xcb_generate_id(m_connection);
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
+ xcb_screen_t *screen = it.data;
Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
- eventListener, m_screens.at(0)->root(),
+ eventListener, screen->root,
0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
- m_screens.at(0)->screen()->root_visual, 0, 0));
+ screen->root_visual, 0, 0));
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
@@ -1357,6 +1387,37 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
return timestamp;
}
+xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const
+{
+ xcb_connection_t *c = xcb_connection();
+ xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom);
+ xcb_get_selection_owner_reply_t *reply;
+ reply = xcb_get_selection_owner_reply(c, cookie, 0);
+ xcb_window_t win = reply->owner;
+ free(reply);
+ return win;
+}
+
+xcb_window_t QXcbConnection::getQtSelectionOwner()
+{
+ if (!m_qtSelectionOwner) {
+ xcb_screen_t *xcbScreen = primaryVirtualDesktop()->screen();
+ int x = 0, y = 0, w = 3, h = 3;
+ m_qtSelectionOwner = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL(xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_qtSelectionOwner, // window id
+ xcbScreen->root, // parent window id
+ x, y, w, h,
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ xcbScreen->root_visual, // visual
+ 0, // value mask
+ 0)); // value list
+ }
+ return m_qtSelectionOwner;
+}
+
xcb_window_t QXcbConnection::rootWindow()
{
QXcbScreen *s = primaryScreen();
@@ -1437,6 +1498,105 @@ void *QXcbConnection::createVisualInfoForDefaultVisualId() const
#endif
+#if defined(XCB_USE_XINPUT2)
+// it is safe to cast XI_* events here as long as we are only touching the first 32 bytes,
+// after that position event needs memmove, see xi2PrepareXIGenericDeviceEvent
+static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type)
+{
+ if (!isXIEvent(event, opCode))
+ return false;
+
+ xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ return xiEvent->evtype == type;
+}
+#endif
+static inline bool isValid(xcb_generic_event_t *event)
+{
+ return event && (event->response_type & ~0x80);
+}
+
+/*! \internal
+
+ Compresses events of the same type to avoid swamping the event queue.
+ If event compression is not desired there are several options what developers can do:
+
+ 1) Write responsive applications. We drop events that have been buffered in the event
+ queue while waiting on unresponsive GUI thread.
+ 2) Use QAbstractNativeEventFilter to get all events from X connection. This is not optimal
+ because it requires working with native event types.
+ 3) Or add public API to Qt for disabling event compression QTBUG-44964
+
+*/
+bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const
+{
+ uint responseType = event->response_type & ~0x80;
+ int nextIndex = currentIndex + 1;
+
+ if (responseType == XCB_MOTION_NOTIFY) {
+ // compress XCB_MOTION_NOTIFY notify events
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (next->response_type == XCB_MOTION_NOTIFY)
+ return true;
+ }
+ return false;
+ }
+#if defined(XCB_USE_XINPUT2)
+ // compress XI_* events
+ if (responseType == XCB_GE_GENERIC) {
+ if (!m_xi2Enabled)
+ return false;
+
+ // compress XI_Motion
+ if (isXIType(event, m_xiOpCode, XI_Motion)) {
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (isXIType(next, m_xiOpCode, XI_Motion))
+ return true;
+ }
+ return false;
+ }
+#ifdef XCB_USE_XINPUT22
+ // compress XI_TouchUpdate for the same touch point id
+ if (isXIType(event, m_xiOpCode, XI_TouchUpdate)) {
+ xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ uint32_t id = xiDeviceEvent->detail % INT_MAX;
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (!isValid(next))
+ continue;
+ if (isXIType(next, m_xiOpCode, XI_TouchUpdate)) {
+ xXIDeviceEvent *xiDeviceNextEvent = reinterpret_cast<xXIDeviceEvent *>(next);
+ if (id == xiDeviceNextEvent->detail % INT_MAX)
+ return true;
+ }
+ }
+ return false;
+ }
+#endif
+ return false;
+ }
+#endif
+ if (responseType == XCB_CONFIGURE_NOTIFY) {
+ // compress multiple configure notify events for the same window
+ for (int j = nextIndex; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *next = eventqueue->at(j);
+ if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY
+ && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+}
+
void QXcbConnection::processXcbEvents()
{
int connection_error = xcb_connection_has_error(xcb_connection());
@@ -1447,61 +1607,39 @@ void QXcbConnection::processXcbEvents()
QXcbEventArray *eventqueue = m_reader->lock();
- for(int i = 0; i < eventqueue->size(); ++i) {
+ for (int i = 0; i < eventqueue->size(); ++i) {
xcb_generic_event_t *event = eventqueue->at(i);
if (!event)
continue;
QScopedPointer<xcb_generic_event_t, QScopedPointerPodDeleter> eventGuard(event);
(*eventqueue)[i] = 0;
- uint response_type = event->response_type & ~0x80;
-
- if (!response_type) {
+ if (!(event->response_type & ~0x80)) {
handleXcbError((xcb_generic_error_t *)event);
- } else {
- if (response_type == XCB_MOTION_NOTIFY) {
- // compress multiple motion notify events in a row
- // to avoid swamping the event queue
- xcb_generic_event_t *next = eventqueue->value(i+1, 0);
- if (next && (next->response_type & ~0x80) == XCB_MOTION_NOTIFY)
- continue;
- }
+ continue;
+ }
- if (response_type == XCB_CONFIGURE_NOTIFY) {
- // compress multiple configure notify events for the same window
- bool found = false;
- for (int j = i; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *other = eventqueue->at(j);
- if (other && (other->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY
- && ((xcb_configure_notify_event_t *)other)->event == ((xcb_configure_notify_event_t *)event)->event)
- {
- found = true;
- break;
- }
- }
- if (found)
- continue;
- }
+ if (compressEvent(event, i, eventqueue))
+ continue;
- bool accepted = false;
- if (clipboard()->processIncr())
- clipboard()->incrTransactionPeeker(event, accepted);
- if (accepted)
- continue;
+ bool accepted = false;
+ if (clipboard()->processIncr())
+ clipboard()->incrTransactionPeeker(event, accepted);
+ if (accepted)
+ continue;
- QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
- while (it != m_peekFuncs.end()) {
- // These callbacks return true if the event is what they were
- // waiting for, remove them from the list in that case.
- if ((*it)(this, event))
- it = m_peekFuncs.erase(it);
- else
- ++it;
- }
- m_reader->unlock();
- handleXcbEvent(event);
- m_reader->lock();
+ QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
+ while (it != m_peekFuncs.end()) {
+ // These callbacks return true if the event is what they were
+ // waiting for, remove them from the list in that case.
+ if ((*it)(this, event))
+ it = m_peekFuncs.erase(it);
+ else
+ ++it;
}
+ m_reader->unlock();
+ handleXcbEvent(event);
+ m_reader->lock();
}
eventqueue->clear();
@@ -1746,7 +1884,8 @@ static const char * xcb_atomnames = {
"_XSETTINGS_SETTINGS\0"
"_COMPIZ_DECOR_PENDING\0"
"_COMPIZ_DECOR_REQUEST\0"
- "_COMPIZ_DECOR_DELETE_PIXMAP\0" // \0\0 terminates loop.
+ "_COMPIZ_DECOR_DELETE_PIXMAP\0"
+ "_COMPIZ_TOOLKIT_ACTION\0" // \0\0 terminates loop.
};
QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
@@ -2043,41 +2182,21 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub
return true;
}
-// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
-// - "pad0" became "extension"
-// - "pad1" and "pad" became "pad0"
-// New and old version of this struct share the following fields:
-// NOTE: API might change again in the next release of xcb in which case this comment will
-// need to be updated to reflect the reality.
-typedef struct qt_xcb_ge_event_t {
- uint8_t response_type;
- uint8_t extension;
- uint16_t sequence;
- uint32_t length;
- uint16_t event_type;
-} qt_xcb_ge_event_t;
-
-bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode)
-{
- qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev;
- // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from
- // the xcb version 1.9.3, prior to that it was called "pad0".
- if (event->extension == opCode) {
- // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
- // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
- // Move this data back to have the same layout in memory as it was on the wire
- // and allow casting, overwriting the full_sequence field.
- memmove((char*) event + 32, (char*) event + 36, event->length * 4);
- return true;
- }
- return false;
+void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
+{
+ // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
+ // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
+ // Move this data back to have the same layout in memory as it was on the wire
+ // and allow casting, overwriting the full_sequence field.
+ memmove((char*) event + 32, (char*) event + 36, event->length * 4);
}
#endif // defined(XCB_USE_XINPUT2)
-QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker()
+QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
{
if (!m_systemTrayTracker) {
- if ( (m_systemTrayTracker = QXcbSystemTrayTracker::create(this)) ) {
+ QXcbConnection *self = const_cast<QXcbConnection *>(this);
+ if ((self->m_systemTrayTracker = QXcbSystemTrayTracker::create(self))) {
connect(m_systemTrayTracker, SIGNAL(systemTrayWindowChanged(QScreen*)),
QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)));
}
@@ -2085,6 +2204,22 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker()
return m_systemTrayTracker;
}
+bool QXcbConnection::xEmbedSystemTrayAvailable()
+{
+ if (!QGuiApplicationPrivate::platformIntegration())
+ return false;
+ QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
+ return connection->systemTrayTracker();
+}
+
+bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel()
+{
+ if (!QGuiApplicationPrivate::platformIntegration())
+ return false;
+ QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
+ return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel();
+}
+
bool QXcbConnection::event(QEvent *e)
{
if (e->type() == QEvent::User + 1) {
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index a183a72353..3c82170679 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -286,6 +286,7 @@ namespace QXcbAtom {
_COMPIZ_DECOR_PENDING,
_COMPIZ_DECOR_REQUEST,
_COMPIZ_DECOR_DELETE_PIXMAP,
+ _COMPIZ_TOOLKIT_ACTION,
NPredefinedAtoms,
@@ -375,8 +376,10 @@ public:
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
+ const QList<QXcbVirtualDesktop *> &virtualDesktops() const { return m_virtualDesktops; }
const QList<QXcbScreen *> &screens() const { return m_screens; }
int primaryScreenNumber() const { return m_primaryScreenNumber; }
+ QXcbVirtualDesktop *primaryVirtualDesktop() const { return m_virtualDesktops.value(m_primaryScreenNumber); }
QXcbScreen *primaryScreen() const;
inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
@@ -457,6 +460,8 @@ public:
bool threadedEventHandling() const { return m_reader->isRunning(); }
xcb_timestamp_t getTimestamp();
+ xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
+ xcb_window_t getQtSelectionOwner();
void setButton(Qt::MouseButton button, bool down) { if (down) m_buttons |= button; else m_buttons &= ~button; }
Qt::MouseButtons buttons() const { return m_buttons; }
@@ -474,7 +479,9 @@ public:
QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; }
- QXcbSystemTrayTracker *systemTrayTracker();
+ QXcbSystemTrayTracker *systemTrayTracker() const;
+ static bool xEmbedSystemTrayAvailable();
+ static bool xEmbedSystemTrayVisualHasAlphaChannel();
#ifdef XCB_USE_XINPUT2
void handleEnterEvent(const xcb_enter_notify_event_t *);
@@ -520,6 +527,7 @@ private:
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void initializeScreens();
void updateScreens(const xcb_randr_notify_event_t *event);
+ bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled;
int m_xi2Minor;
@@ -572,7 +580,7 @@ private:
QHash<int, ScrollingDevice> m_scrollingDevices;
static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value);
- static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode);
+ static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event);
#endif
xcb_connection_t *m_connection;
@@ -644,6 +652,8 @@ private:
QXcbGlIntegration *m_glIntegration;
bool m_xiGrab;
+ xcb_window_t m_qtSelectionOwner;
+
friend class QXcbEventReader;
};
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index d7688be0ff..8097cce709 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -216,6 +216,12 @@ void QXcbConnection::xi2SetupDevices()
isTablet = true;
tabletData.pointerType = QTabletEvent::Pen;
dbgType = QLatin1String("pen");
+ } else if (name.contains("waltop") && name.contains("tablet")) {
+ // other "Genius" tablets
+ // WALTOP International Corp. Slim Tablet
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
} else {
isTablet = false;
}
@@ -413,8 +419,10 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
hasRelativeCoords = true;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
} else if (vci->label == atom(QXcbAtom::AbsX)) {
+ caps |= QTouchDevice::Position;
dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
} else if (vci->label == atom(QXcbAtom::AbsY)) {
+ caps |= QTouchDevice::Position;
dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
}
break;
@@ -459,82 +467,81 @@ static inline qreal fixed1616ToReal(FP1616 val)
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
- if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
- xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
- int sourceDeviceId = xiEvent->deviceid; // may be the master id
- xXIDeviceEvent *xiDeviceEvent = 0;
- QXcbWindowEventListener *eventListener = 0;
+ xi2PrepareXIGenericDeviceEvent(event);
+ xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ int sourceDeviceId = xiEvent->deviceid; // may be the master id
+ xXIDeviceEvent *xiDeviceEvent = 0;
+ QXcbWindowEventListener *eventListener = 0;
- switch (xiEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
+ switch (xiEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
#ifdef XCB_USE_XINPUT22
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
#endif
- {
- xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
- eventListener = windowEventListenerFromId(xiDeviceEvent->event);
- if (eventListener) {
- long result = 0;
- if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
- return;
- }
- sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
- break;
- }
- case XI_HierarchyChanged:
- xi2HandleHierachyEvent(xiEvent);
- return;
- case XI_DeviceChanged:
- xi2HandleDeviceChangedEvent(xiEvent);
- return;
- default:
- break;
+ {
+ xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ eventListener = windowEventListenerFromId(xiDeviceEvent->event);
+ if (eventListener) {
+ long result = 0;
+ if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
+ return;
}
+ sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
+ break;
+ }
+ case XI_HierarchyChanged:
+ xi2HandleHierachyEvent(xiEvent);
+ return;
+ case XI_DeviceChanged:
+ xi2HandleDeviceChangedEvent(xiEvent);
+ return;
+ default:
+ break;
+ }
#ifndef QT_NO_TABLETEVENT
- for (int i = 0; i < m_tabletData.count(); ++i) {
- if (m_tabletData.at(i).deviceId == sourceDeviceId) {
- if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
- return;
- }
+ for (int i = 0; i < m_tabletData.count(); ++i) {
+ if (m_tabletData.at(i).deviceId == sourceDeviceId) {
+ if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
+ return;
}
+ }
#endif // QT_NO_TABLETEVENT
#ifdef XCB_USE_XINPUT21
- QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
- if (device != m_scrollingDevices.end())
- xi2HandleScrollEvent(xiEvent, device.value());
+ QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
+ if (device != m_scrollingDevices.end())
+ xi2HandleScrollEvent(xiEvent, device.value());
#endif // XCB_USE_XINPUT21
#ifdef XCB_USE_XINPUT22
- if (xiDeviceEvent) {
- switch (xiDeviceEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
- if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
- eventListener->handleXIMouseEvent(event);
- break;
+ if (xiDeviceEvent) {
+ switch (xiDeviceEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
+ eventListener->handleXIMouseEvent(event);
+ break;
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
- if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
- event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
- fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
- fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
- if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
- xi2ProcessTouch(xiDeviceEvent, platformWindow);
- break;
- }
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
+ if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+ qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
+ event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
+ fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
+ fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
+ if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
+ xi2ProcessTouch(xiDeviceEvent, platformWindow);
+ break;
}
-#endif // XCB_USE_XINPUT22
}
+#endif // XCB_USE_XINPUT22
}
#ifdef XCB_USE_XINPUT22
@@ -562,10 +569,8 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
}
QWindowSystemInterface::TouchPoint &touchPoint = dev->touchPoints[xiDeviceEvent->detail];
QXcbScreen* screen = platformWindow->xcbScreen();
- QPointF pos = screen->mapFromNative(QPointF(fixed1616ToReal(xiDeviceEvent->root_x),
- fixed1616ToReal(xiDeviceEvent->root_y)));
- qreal x = pos.x();
- qreal y = pos.y();
+ qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
+ qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
qreal nx = -1.0, ny = -1.0, d = 0.0;
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
@@ -872,9 +877,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
}
}
if (!angleDelta.isNull()) {
- const int dpr = int(platformWindow->devicePixelRatio());
- QPoint local(fixed1616ToReal(xiDeviceEvent->event_x)/dpr, fixed1616ToReal(xiDeviceEvent->event_y)/dpr);
- QPoint global(fixed1616ToReal(xiDeviceEvent->root_x)/dpr, fixed1616ToReal(xiDeviceEvent->root_y)/dpr);
+ QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y));
+ QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y));
Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
if (modifiers & Qt::AltModifier) {
std::swap(angleDelta.rx(), angleDelta.ry());
@@ -900,9 +904,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
angleDelta.setX(-120);
}
if (!angleDelta.isNull()) {
- const int dpr = int(platformWindow->devicePixelRatio());
- QPoint local(fixed1616ToReal(xiDeviceEvent->event_x)/dpr, fixed1616ToReal(xiDeviceEvent->event_y)/dpr);
- QPoint global(fixed1616ToReal(xiDeviceEvent->root_x)/dpr, fixed1616ToReal(xiDeviceEvent->root_y)/dpr);
+ QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y));
+ QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y));
Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
if (modifiers & Qt::AltModifier)
std::swap(angleDelta.rx(), angleDelta.ry());
@@ -1024,9 +1027,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
tabletData->inProximity = true;
tabletData->tool = toolIdToTabletDevice(tool);
tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_TOOL_SERIAL]);
- QWindowSystemInterface::handleTabletEnterProximityEvent(tabletData->tool,
- tabletData->pointerType,
- tabletData->serialId);
+ QWindowSystemInterface::handleTabletEnterProximityEvent(ev->time,
+ tabletData->tool, tabletData->pointerType, tabletData->serialId);
} else {
tabletData->inProximity = false;
tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_ID]);
@@ -1035,9 +1037,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q
if (!tabletData->tool)
tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]);
tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_LAST_TOOL_SERIAL]);
- QWindowSystemInterface::handleTabletLeaveProximityEvent(tabletData->tool,
- tabletData->pointerType,
- tabletData->serialId);
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(ev->time,
+ tabletData->tool, tabletData->pointerType, tabletData->serialId);
}
// TODO maybe have a hash of tabletData->deviceId to device data so we can
// look up the tablet name here, and distinguish multiple tablets
@@ -1115,13 +1116,14 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
}
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
- tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
+ qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d "
+ "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time,
fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
(int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
- QWindowSystemInterface::handleTabletEvent(window, local, global,
+ QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global,
tabletData.tool, tabletData.pointerType,
tabletData.buttons, pressure,
xTilt, yTilt, tangentialPressure,
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index bd880698e6..b321ed95dc 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -52,7 +52,7 @@ typedef char *(*PtrXcursorLibraryGetTheme)(void *);
typedef int (*PtrXcursorLibrarySetTheme)(void *, const char *);
typedef int (*PtrXcursorLibraryGetDefaultSize)(void *);
-#ifdef XCB_USE_XLIB
+#if defined(XCB_USE_XLIB) && !defined(QT_NO_LIBRARY)
#include <X11/Xlib.h>
enum {
XCursorShape = CursorShape
@@ -300,7 +300,7 @@ QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
const char *cursorStr = "cursor";
xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
-#ifdef XCB_USE_XLIB
+#if defined(XCB_USE_XLIB) && !defined(QT_NO_LIBRARY)
static bool function_ptrs_not_initialized = true;
if (function_ptrs_not_initialized) {
QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
@@ -491,7 +491,7 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
return cursor;
}
-#ifdef XCB_USE_XLIB
+#if defined(XCB_USE_XLIB) && !defined(QT_NO_LIBRARY)
bool updateCursorTheme(void *dpy, const QByteArray &theme) {
if (!ptrXcursorLibraryGetTheme
|| !ptrXcursorLibrarySetTheme)
@@ -535,7 +535,7 @@ static xcb_cursor_t loadCursor(void *dpy, int cshape)
}
return cursor;
}
-#endif //XCB_USE_XLIB
+#endif //XCB_USE_XLIB / QT_NO_LIBRARY
xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
{
@@ -544,7 +544,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
xcb_cursor_t cursor = XCB_NONE;
// Try Xcursor first
-#ifdef XCB_USE_XLIB
+#if defined(XCB_USE_XLIB) && !defined(QT_NO_LIBRARY)
if (cshape >= 0 && cshape <= Qt::LastCursor) {
void *dpy = connection()->xlib_display();
// special case for non-standard dnd-* cursors
@@ -607,45 +607,47 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
}
#endif
-void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask)
+void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask)
{
if (pos)
*pos = QPoint();
- xcb_screen_iterator_t it = xcb_setup_roots_iterator(c->setup());
- while (it.rem) {
- xcb_window_t root = it.data->root;
- xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root);
- xcb_generic_error_t *err = 0;
- xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err);
- if (!err && reply) {
- if (pos)
- *pos = QPoint(reply->root_x, reply->root_y);
- if (rootWin)
- *rootWin = root;
- if (keybMask)
- *keybMask = reply->mask;
- free(reply);
- return;
+
+ xcb_window_t root = c->primaryVirtualDesktop()->root();
+ xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root);
+ xcb_generic_error_t *err = 0;
+ xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err);
+ if (!err && reply) {
+ if (virtualDesktop) {
+ foreach (QXcbVirtualDesktop *vd, c->virtualDesktops()) {
+ if (vd->root() == reply->root) {
+ *virtualDesktop = vd;
+ break;
+ }
+ }
}
- free(err);
+ if (pos)
+ *pos = QPoint(reply->root_x, reply->root_y);
+ if (keybMask)
+ *keybMask = reply->mask;
free(reply);
- xcb_screen_next(&it);
+ return;
}
+ free(err);
+ free(reply);
}
QPoint QXcbCursor::pos() const
{
QPoint p;
queryPointer(connection(), 0, &p);
- return m_screen->mapFromNative(p);
+ return p;
}
void QXcbCursor::setPos(const QPoint &pos)
{
- const QPoint xPos = m_screen->mapToNative(pos);
- xcb_window_t root = 0;
- queryPointer(connection(), &root, 0);
- xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, xPos.x(), xPos.y());
+ QXcbVirtualDesktop *virtualDesktop = Q_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/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index 7e5cdc6870..3c6dece1f2 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -75,7 +75,7 @@ public:
QPoint pos() const Q_DECL_OVERRIDE;
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
- static void queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask = 0);
+ static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask = 0);
private:
#ifndef QT_NO_CURSOR
@@ -90,7 +90,7 @@ private:
#ifndef QT_NO_CURSOR
CursorHash m_cursorHash;
#endif
-#ifdef XCB_USE_XLIB
+#if defined(XCB_USE_XLIB) && !defined(QT_NO_LIBRARY)
static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
const QByteArray &name,
const QVariant &property,
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 1d13adf851..d19ea241f1 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -39,6 +39,7 @@
#include "qxcbwindow.h"
#include "qxcbscreen.h"
#include "qwindow.h"
+#include "qxcbcursor.h"
#include <private/qdnd_p.h>
#include <qdebug.h>
#include <qevent.h>
@@ -51,6 +52,7 @@
#include <private/qshapedpixmapdndwindow_p.h>
#include <private/qsimpledrag_p.h>
+#include <private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE
@@ -71,12 +73,16 @@ QT_BEGIN_NAMESPACE
const int xdnd_version = 5;
+static inline xcb_window_t xcb_window(QPlatformWindow *w)
+{
+ return static_cast<QXcbWindow *>(w)->xcb_window();
+}
+
static inline xcb_window_t xcb_window(QWindow *w)
{
return static_cast<QXcbWindow *>(w->handle())->xcb_window();
}
-
static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
{
xcb_window_t proxy = XCB_NONE;
@@ -155,7 +161,7 @@ void QXcbDrag::init()
source_time = XCB_CURRENT_TIME;
target_time = XCB_CURRENT_TIME;
- current_screen = 0;
+ QXcbCursor::queryPointer(connection(), &current_virtual_desktop, 0);
drag_types.clear();
}
@@ -185,6 +191,8 @@ void QXcbDrag::startDrag()
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),
atom(QXcbAtom::XdndTypelist),
XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
+
+ setUseCompositing(current_virtual_desktop->compositingActive());
QBasicDrag::startDrag();
}
@@ -297,50 +305,29 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
return 0;
}
-void QXcbDrag::move(const QMouseEvent *me)
+void QXcbDrag::move(const QPoint &globalPos)
{
- // The mouse event is in the coordinate system of the window that started the drag.
- // We do not know which window that was at this point, so we just use the device pixel ratio
- // of the QGuiApplication. This will break once we support screens with different DPR. Fixing
- // this properly requires some redesign of the drag and drop architecture.
- static const int dpr = int(qApp->devicePixelRatio());
- QBasicDrag::move(me);
- QPoint globalPos = me->globalPos();
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
return;
- const QList<QXcbScreen *> &screens = connection()->screens();
- QXcbScreen *screen = connection()->primaryScreen();
- for (int i = 0; i < screens.size(); ++i) {
- if (screens.at(i)->geometry().contains(globalPos)) {
- screen = screens.at(i);
- break;
- }
- }
- if (screen != current_screen) {
- // ### need to recreate the shaped pixmap window?
-// int screen = QCursor::x11Screen();
-// if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) {
-// // recreate the pixmap on the new screen...
-// delete xdnd_data.deco;
-// QWidget* parent = object->source()->window()->x11Info().screen() == screen
-// ? object->source()->window() : QApplication::desktop()->screen(screen);
-// xdnd_data.deco = new QShapedPixmapWidget(parent);
-// if (!QWidget::mouseGrabber()) {
-// updatePixmap();
-// xdnd_data.deco->grabMouse();
-// }
-// }
-// xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot);
- current_screen = screen;
- }
+ QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR;
+ QPoint cursorPos;
+ QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);
+ QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);
+ QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen);
+ if (virtualDesktop != current_virtual_desktop) {
+ setUseCompositing(virtualDesktop->compositingActive());
+ recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);
+ current_virtual_desktop = virtualDesktop;
+ } else {
+ QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);
+ }
-// qt_xdnd_current_screen = screen;
- xcb_window_t rootwin = current_screen->root();
+ xcb_window_t rootwin = current_virtual_desktop->root();
xcb_translate_coordinates_reply_t *translate =
- ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x() * dpr, globalPos.y() * dpr);
+ ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y());
if (!translate)
return;
@@ -443,7 +430,7 @@ void QXcbDrag::move(const QMouseEvent *me)
DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
if (w)
- handleEnter(w->window(), &enter);
+ handleEnter(w, &enter, current_proxy_target);
else if (target)
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);
waiting_for_status = false;
@@ -463,7 +450,7 @@ void QXcbDrag::move(const QMouseEvent *me)
move.type = atom(QXcbAtom::XdndPosition);
move.data.data32[0] = connection()->clipboard()->owner();
move.data.data32[1] = 0; // flags
- move.data.data32[2] = (globalPos.x() * dpr << 16) + globalPos.y() * dpr;
+ move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
move.data.data32[3] = connection()->time();
move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));
DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
@@ -471,15 +458,15 @@ void QXcbDrag::move(const QMouseEvent *me)
source_time = connection()->time();
if (w)
- handle_xdnd_position(w->window(), &move);
+ handle_xdnd_position(w, &move);
else
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
}
}
-void QXcbDrag::drop(const QMouseEvent *event)
+void QXcbDrag::drop(const QPoint &globalPos)
{
- QBasicDrag::drop(event);
+ QBasicDrag::drop(globalPos);
if (!current_target)
return;
@@ -505,7 +492,7 @@ void QXcbDrag::drop(const QMouseEvent *event)
connection()->time(),
current_target,
current_proxy_target,
- (w ? w->window() : 0),
+ w,
// current_embeddig_widget,
currentDrag(),
QTime::currentTime()
@@ -518,7 +505,7 @@ void QXcbDrag::drop(const QMouseEvent *event)
}
if (w) {
- handleDrop(w->window(), &drop);
+ handleDrop(w, &drop);
} else {
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
}
@@ -664,7 +651,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe)
#endif
-void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *event)
+void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy)
{
Q_UNUSED(window);
DEBUG() << "handleEnter" << window;
@@ -676,6 +663,9 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev
return;
xdnd_dragsource = event->data.data32[0];
+ if (!proxy)
+ proxy = xdndProxy(connection(), xdnd_dragsource);
+ current_proxy_target = proxy ? proxy : xdnd_dragsource;
if (event->data.data32[1] & 1) {
// get the types from XdndTypeList
@@ -689,6 +679,7 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev
length = xdnd_max_type;
xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);
+ xdnd_types.reserve(length);
for (int i = 0; i < length; ++i)
xdnd_types.append(atoms[i]);
}
@@ -704,17 +695,14 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev
DEBUG() << " " << connection()->atomName(xdnd_types.at(i));
}
-void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e)
+void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e)
{
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
Q_ASSERT(w);
QRect geometry = w->geometry();
- const int dpr = int(w->handle()->devicePixelRatio());
-
- p /= dpr;
p -= geometry.topLeft();
- if (!w || (w->type() == Qt::Desktop))
+ if (!w || !w->window() || (w->window()->type() == Qt::Desktop))
return;
if (e->data.data32[0] != xdnd_dragsource) {
@@ -723,7 +711,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
}
currentPosition = p;
- currentWindow = w;
+ currentWindow = w->window();
// timestamp from the source
if (e->data.data32[3] != XCB_NONE) {
@@ -740,7 +728,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
}
- QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions);
+ QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions);
QRect answerRect(p + geometry.topLeft(), QSize(1,1));
answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
@@ -776,7 +764,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
if (xdnd_dragsource == connection()->clipboard()->owner())
handle_xdnd_status(&response);
else
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
}
@@ -796,7 +784,7 @@ namespace
};
}
-void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event)
+void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event)
{
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
xcb_generic_event_t *nextEvent;
@@ -830,12 +818,10 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)
updateCursor(Qt::IgnoreAction);
}
- static const int dpr = int(qApp->devicePixelRatio());
-
if ((event->data.data32[1] & 2) == 0) {
QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff);
QSize s((event->data.data32[3] & 0xffff0000) >> 16, event->data.data32[3] & 0x0000ffff);
- source_sameanswer = QRect(p / dpr, s / dpr);
+ source_sameanswer = QRect(p, s);
} else {
source_sameanswer = QRect();
}
@@ -861,10 +847,10 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
DEBUG("xdndHandleStatus end");
}
-void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
+void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event)
{
DEBUG("xdnd leave");
- if (!currentWindow || w != currentWindow.data())
+ if (!currentWindow || w != currentWindow.data()->handle())
return; // sanity
// ###
@@ -879,7 +865,7 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
}
- QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction);
+ QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction);
xdnd_dragsource = 0;
xdnd_types.clear();
@@ -909,7 +895,7 @@ void QXcbDrag::send_leave()
w = 0;
if (w)
- handleLeave(w->window(), (const xcb_client_message_event_t *)&leave);
+ handleLeave(w, (const xcb_client_message_event_t *)&leave);
else
xcb_send_event(xcb_connection(), false,current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);
@@ -920,7 +906,7 @@ void QXcbDrag::send_leave()
waiting_for_status = false;
}
-void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event)
+void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleDrop");
if (!currentWindow) {
@@ -970,7 +956,7 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event)
finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
finished.data.data32[1] = response.isAccepted(); // flags
finished.data.data32[2] = toXdndAction(response.acceptedAction());
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
xdnd_dragsource = 0;
@@ -1135,7 +1121,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
}
}
- xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
+ xcb_window_t proxy_target = xdndProxy(connection(), event->requestor);
+ if (!proxy_target)
+ proxy_target = event->requestor;
+
+ xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
}
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 95da76b732..c9d257906f 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -53,8 +53,8 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DRAGANDDROP
-class QMouseEvent;
class QWindow;
+class QPlatformWindow;
class QXcbConnection;
class QXcbWindow;
class QXcbDropData;
@@ -72,14 +72,14 @@ public:
void startDrag() Q_DECL_OVERRIDE;
void cancel() Q_DECL_OVERRIDE;
- void move(const QMouseEvent *me) Q_DECL_OVERRIDE;
- void drop(const QMouseEvent *me) Q_DECL_OVERRIDE;
+ void move(const QPoint &globalPos) Q_DECL_OVERRIDE;
+ void drop(const QPoint &globalPos) Q_DECL_OVERRIDE;
void endDrag() Q_DECL_OVERRIDE;
- void handleEnter(QWindow *window, const xcb_client_message_event_t *event);
- void handlePosition(QWindow *w, const xcb_client_message_event_t *event);
- void handleLeave(QWindow *w, const xcb_client_message_event_t *event);
- void handleDrop(QWindow *, const xcb_client_message_event_t *event);
+ void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0);
+ void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
+ void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
+ void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event);
void handleStatus(const xcb_client_message_event_t *event);
void handleSelectionRequest(const xcb_selection_request_event_t *event);
@@ -99,7 +99,7 @@ private:
void init();
- void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event);
+ void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handle_xdnd_status(const xcb_client_message_event_t *event);
void send_leave();
@@ -133,7 +133,7 @@ private:
// window to send events to (always valid if current_target)
xcb_window_t current_proxy_target;
- QXcbScreen *current_screen;
+ QXcbVirtualDesktop *current_virtual_desktop;
// 10 minute timer used to discard old XdndDrop transactions
enum { XdndDropTransactionTimeout = 600000 };
@@ -146,7 +146,7 @@ private:
xcb_timestamp_t timestamp;
xcb_window_t target;
xcb_window_t proxy_target;
- QWindow *targetWindow;
+ QPlatformWindow *targetWindow;
// QWidget *embedding_widget;
QPointer<QDrag> drag;
QTime time;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index fc06f1a7b0..9cedfa77ad 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -268,7 +268,10 @@ void QXcbIntegration::initialize()
{
// Perform everything that may potentially need the event dispatcher (timers, socket
// notifiers) here instead of the constructor.
- m_inputContext.reset(QPlatformInputContextFactory::create());
+ QString icStr = QPlatformInputContextFactory::requested();
+ if (icStr.isNull())
+ icStr = QLatin1String("compose");
+ m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
}
void QXcbIntegration::moveToScreen(QWindow *window, int screen)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index ea541e4556..2e088d3ca5 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -1545,11 +1545,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
{
- QByteArray chars;
- chars.resize(1 + xkb_state_key_get_utf8(state, code, 0, 0));
- // equivalent of XLookupString
- xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
- return QString::fromUtf8(chars);
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
+ chars.resize(size + 1);
+ xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ }
+ return QString::fromUtf8(chars.constData(), size);
}
void QXcbKeyboard::handleKeyPressEvent(const xcb_key_press_event_t *event)
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 8bf9003af7..dfb0a125e2 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -47,6 +47,7 @@
#include <QtGui/qscreen.h>
#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+#include <QtPlatformHeaders/qxcbintegrationfunctions.h>
#ifndef QT_NO_DBUS
#include "QtPlatformSupport/private/qdbusmenuconnection_p.h"
@@ -76,7 +77,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("gettimestamp"), QByteArrayLiteral("x11screen"),
QByteArrayLiteral("rootwindow"),
QByteArrayLiteral("subpixeltype"), QByteArrayLiteral("antialiasingEnabled"),
- QByteArrayLiteral("nofonthinting")
+ QByteArrayLiteral("nofonthinting"),
+ QByteArrayLiteral("atspibus")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@@ -85,8 +87,7 @@ static int resourceType(const QByteArray &key)
QXcbNativeInterface::QXcbNativeInterface() :
m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")),
- m_sysTraySelectionAtom(XCB_ATOM_NONE),
- m_systrayVisualId(XCB_NONE)
+ m_sysTraySelectionAtom(XCB_ATOM_NONE)
{
}
@@ -117,22 +118,12 @@ bool QXcbNativeInterface::systemTrayAvailable(const QScreen *screen) const
bool QXcbNativeInterface::requestSystemTrayWindowDock(const QWindow *window)
{
- const QPlatformWindow *platformWindow = window->handle();
- if (!platformWindow)
- return false;
- QXcbSystemTrayTracker *trayTracker = systemTrayTracker(window->screen());
- if (!trayTracker)
- return false;
- trayTracker->requestSystemTrayWindowDock(static_cast<const QXcbWindow *>(platformWindow)->xcb_window());
- return true;
+ return QXcbWindow::requestSystemTrayWindowDockStatic(window);
}
QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
{
- if (const QPlatformWindow *platformWindow = window->handle())
- if (const QXcbSystemTrayTracker *trayTracker = systemTrayTracker(window->screen()))
- return trayTracker->systemTrayWindowGlobalGeometry(static_cast<const QXcbWindow *>(platformWindow)->xcb_window());
- return QRect();
+ return QXcbWindow::systemTrayWindowGlobalGeometryStatic(window);
}
xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
@@ -163,54 +154,14 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const
return selection_window;
}
-bool QXcbNativeInterface::systrayVisualHasAlphaChannel() {
- const QXcbScreen *screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle());
-
- if (m_systrayVisualId == XCB_NONE) {
- xcb_connection_t *xcb_conn = screen->xcb_connection();
- xcb_atom_t tray_atom = screen->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
-
- xcb_window_t systray_window = locateSystemTray(xcb_conn, screen);
- if (systray_window == XCB_WINDOW_NONE)
- return false;
-
- // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom
- xcb_get_property_cookie_t systray_atom_cookie;
- xcb_get_property_reply_t *systray_atom_reply;
-
- systray_atom_cookie = xcb_get_property_unchecked(xcb_conn, false, systray_window,
- tray_atom, XCB_ATOM_VISUALID, 0, 1);
- systray_atom_reply = xcb_get_property_reply(xcb_conn, systray_atom_cookie, 0);
-
- if (!systray_atom_reply)
- return false;
-
- if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) {
- xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply);
- m_systrayVisualId = vids[0];
- }
-
- free(systray_atom_reply);
- }
-
- if (m_systrayVisualId != XCB_NONE) {
- quint8 depth = screen->depthOfVisual(m_systrayVisualId);
- return depth == 32;
- } else {
- return false;
- }
+bool QXcbNativeInterface::systrayVisualHasAlphaChannel()
+{
+ return QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel();
}
-void QXcbNativeInterface::setParentRelativeBackPixmap(const QWindow *qwindow)
+void QXcbNativeInterface::setParentRelativeBackPixmap(QWindow *window)
{
- if (const QPlatformWindow *platformWindow = qwindow->handle()) {
- const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow);
- xcb_connection_t *xcb_conn = qxwindow->xcb_connection();
-
- const quint32 mask = XCB_CW_BACK_PIXMAP;
- const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE };
- Q_XCB_CALL(xcb_change_window_attributes(xcb_conn, qxwindow->xcb_window(), mask, values));
- }
+ QXcbWindow::setParentRelativeBackPixmapStatic(window);
}
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
@@ -233,6 +184,9 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour
case Display:
result = display();
break;
+ case AtspiBus:
+ result = atspiBus();
+ break;
case Connection:
result = connection();
break;
@@ -294,6 +248,9 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceStr
case NoFontHinting:
result = xcbScreen->noFontHinting() ? this : 0; //qboolptr...
break;
+ case RootWindow:
+ result = reinterpret_cast<void *>(xcbScreen->root());
+ break;
default:
break;
}
@@ -389,9 +346,24 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
return func;
//case sensitive
- if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) {
- return QFunctionPointer(QXcbWindow::setWmWindowTypeStatic);
- }
+ if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier())
+ return QFunctionPointer(QXcbWindowFunctions::SetWmWindowType(QXcbWindow::setWmWindowTypeStatic));
+
+ if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier())
+ return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic));
+
+ if (function == QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier())
+ return QFunctionPointer(QXcbWindowFunctions::SetParentRelativeBackPixmap(QXcbWindow::setParentRelativeBackPixmapStatic));
+
+ if (function == QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier())
+ return QFunctionPointer(QXcbWindowFunctions::RequestSystemTrayWindowDock(QXcbWindow::requestSystemTrayWindowDockStatic));
+
+ if (function == QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier())
+ return QFunctionPointer(QXcbWindowFunctions::SystemTrayWindowGlobalGeometry(QXcbWindow::systemTrayWindowGlobalGeometryStatic));
+
+ if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier())
+ return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel));
+
if (function == QXcbWindowFunctions::visualIdIdentifier()) {
return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
}
@@ -466,6 +438,27 @@ void *QXcbNativeInterface::connection()
return integration->defaultConnection()->xcb_connection();
}
+void *QXcbNativeInterface::atspiBus()
+{
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QXcbConnection *defaultConnection = integration->defaultConnection();
+ if (defaultConnection) {
+ xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS");
+ xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(defaultConnection->xcb_connection(), false,
+ defaultConnection->rootWindow(),
+ atspiBusAtom,
+ XCB_ATOM_STRING, 0, 128));
+ xcb_get_property_reply_t *reply = Q_XCB_CALL(xcb_get_property_reply(defaultConnection->xcb_connection(), cookie, 0));
+ Q_ASSERT(!reply->bytes_after);
+ char *data = (char *)xcb_get_property_value(reply);
+ int length = xcb_get_property_value_length(reply);
+ QByteArray *busAddress = new QByteArray(data, length);
+ free(reply);
+ return busAddress;
+ }
+ return 0;
+}
+
void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
{
if (screen) {
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index 721c6f4b1d..f88b710864 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -67,7 +67,8 @@ public:
RootWindow,
ScreenSubpixelType,
ScreenAntialiasingEnabled,
- NoFontHinting
+ NoFontHinting,
+ AtspiBus
};
QXcbNativeInterface();
@@ -98,6 +99,7 @@ public:
void *x11Screen();
void *rootWindow();
void *display();
+ void *atspiBus();
void *connection();
static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
@@ -105,7 +107,7 @@ public:
Q_INVOKABLE void beep();
Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const;
- Q_INVOKABLE void setParentRelativeBackPixmap(const QWindow *window);
+ Q_INVOKABLE void setParentRelativeBackPixmap(QWindow *window);
Q_INVOKABLE bool systrayVisualHasAlphaChannel();
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
@@ -121,7 +123,6 @@ private:
const QByteArray m_genericEventFilterType;
xcb_atom_t m_sysTraySelectionAtom;
- xcb_visualid_t m_systrayVisualId;
static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 3dcd6a713a..0e99d58679 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -44,6 +44,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <private/qmath_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
QT_BEGIN_NAMESPACE
@@ -53,6 +54,12 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
, m_number(number)
, m_xSettings(Q_NULLPTR)
{
+ QByteArray cmAtomName("_NET_WM_CM_S");
+ cmAtomName += QByteArray::number(m_number);
+ m_net_wm_cm_atom = connection->internAtom(cmAtomName.constData());
+ m_compositingActive = connection->getSelectionOwner(m_net_wm_cm_atom);
+
+ m_workArea = getWorkArea();
}
QXcbVirtualDesktop::~QXcbVirtualDesktop()
@@ -60,6 +67,20 @@ QXcbVirtualDesktop::~QXcbVirtualDesktop()
delete m_xSettings;
}
+QXcbScreen *QXcbVirtualDesktop::screenAt(const QPoint &pos) const
+{
+ foreach (QXcbScreen *screen, connection()->screens()) {
+ if (screen->virtualDesktop() == this && screen->nativeGeometry().contains(pos))
+ return screen;
+ }
+ return Q_NULLPTR;
+}
+
+void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
+{
+ ((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
+}
+
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{
if (!m_xSettings) {
@@ -69,6 +90,64 @@ QXcbXSettings *QXcbVirtualDesktop::xSettings() const
return m_xSettings;
}
+bool QXcbVirtualDesktop::compositingActive() const
+{
+ if (connection()->hasXFixes())
+ return m_compositingActive;
+ else
+ return connection()->getSelectionOwner(m_net_wm_cm_atom);
+}
+
+void QXcbVirtualDesktop::handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event)
+{
+ if (notify_event->selection == m_net_wm_cm_atom)
+ m_compositingActive = notify_event->owner;
+}
+
+void QXcbVirtualDesktop::subscribeToXFixesSelectionNotify()
+{
+ if (connection()->hasXFixes()) {
+ const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
+ Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask));
+ }
+}
+
+QRect QXcbVirtualDesktop::getWorkArea() const
+{
+ QRect r;
+ xcb_get_property_reply_t * workArea =
+ xcb_get_property_reply(xcb_connection(),
+ xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
+ atom(QXcbAtom::_NET_WORKAREA),
+ XCB_ATOM_CARDINAL, 0, 1024), NULL);
+ if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) {
+ // If workArea->value_len > 4, the remaining ones seem to be for WM's virtual desktops
+ // (don't mess with QXcbVirtualDesktop which represents an X screen).
+ // But QScreen doesn't know about that concept. In reality there could be a
+ // "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop.
+ // But for now just assume the first 4 values give us the geometry of the
+ // "work area", AKA "available geometry"
+ uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea);
+ r = QRect(geom[0], geom[1], geom[2], geom[3]);
+ } else {
+ r = QRect(QPoint(), size());
+ }
+ free(workArea);
+ return r;
+}
+
+void QXcbVirtualDesktop::updateWorkArea()
+{
+ QRect workArea = getWorkArea();
+ if (m_workArea != workArea) {
+ m_workArea = workArea;
+ foreach (QPlatformScreen *screen, m_screens)
+ ((QXcbScreen *)screen)->updateAvailableGeometry();
+ }
+}
+
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
QString outputName)
@@ -86,7 +165,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
, m_orientation(Qt::PrimaryOrientation)
, m_refreshRate(60)
, m_forcedDpi(-1)
- , m_devicePixelRatio(1)
+ , m_pixelDensity(1)
, m_hintStyle(QFontEngine::HintStyle(-1))
, m_noFontHinting(false)
, m_subpixelType(QFontEngine::SubpixelAntialiasingType(-1))
@@ -107,9 +186,8 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
updateGeometry(output ? output->timestamp : 0);
}
- const int dpr = int(devicePixelRatio());
if (m_geometry.isEmpty()) {
- m_geometry = QRect(QPoint(), m_virtualSize/dpr);
+ m_geometry = QRect(QPoint(), m_virtualSize);
m_nativeGeometry = QRect(QPoint(), m_virtualSize);
}
if (m_availableGeometry.isEmpty())
@@ -117,12 +195,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
readXResources();
- // disable font hinting when we do UI scaling
- static bool dpr_scaling_enabled = (qgetenv("QT_DEVICE_PIXEL_RATIO").toInt() > 1
- || qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto");
- if (dpr_scaling_enabled)
- m_noFontHinting = true;
-
QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs(
xcb_get_window_attributes_reply(xcb_connection(),
xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL));
@@ -201,9 +273,8 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
xcb_window_t root = screen()->root;
- int dpr = int(devicePixelRatio());
- int x = p.x() / dpr;
- int y = p.y() / dpr;
+ int x = p.x();
+ int y = p.y();
xcb_window_t parent = root;
xcb_window_t child = root;
@@ -237,43 +308,6 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
return 0;
}
-
-QPoint QXcbScreen::mapToNative(const QPoint &pos) const
-{
- const int dpr = int(devicePixelRatio());
- return (pos - m_geometry.topLeft()) * dpr + m_nativeGeometry.topLeft();
-}
-
-QPoint QXcbScreen::mapFromNative(const QPoint &pos) const
-{
- const int dpr = int(devicePixelRatio());
- return (pos - m_nativeGeometry.topLeft()) / dpr + m_geometry.topLeft();
-}
-
-QPointF QXcbScreen::mapToNative(const QPointF &pos) const
-{
- const int dpr = int(devicePixelRatio());
- return (pos - m_geometry.topLeft()) * dpr + m_nativeGeometry.topLeft();
-}
-
-QPointF QXcbScreen::mapFromNative(const QPointF &pos) const
-{
- const int dpr = int(devicePixelRatio());
- return (pos - m_nativeGeometry.topLeft()) / dpr + m_geometry.topLeft();
-}
-
-QRect QXcbScreen::mapToNative(const QRect &rect) const
-{
- const int dpr = int(devicePixelRatio());
- return QRect(mapToNative(rect.topLeft()), rect.size() * dpr);
-}
-
-QRect QXcbScreen::mapFromNative(const QRect &rect) const
-{
- const int dpr = int(devicePixelRatio());
- return QRect(mapFromNative(rect.topLeft()), rect.size() / dpr);
-}
-
void QXcbScreen::windowShown(QXcbWindow *window)
{
// Freedesktop.org Startup Notification
@@ -335,29 +369,22 @@ QDpi QXcbScreen::virtualDpi() const
Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height());
}
+
QDpi QXcbScreen::logicalDpi() const
{
static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
if (overrideDpi)
return QDpi(overrideDpi, overrideDpi);
- int primaryDpr = int(connection()->screens().at(0)->devicePixelRatio());
- if (m_forcedDpi > 0)
- return QDpi(m_forcedDpi/primaryDpr, m_forcedDpi/primaryDpr);
- QDpi vDpi = virtualDpi();
- return QDpi(vDpi.first/primaryDpr, vDpi.second/primaryDpr);
+ if (m_forcedDpi > 0) {
+ return QDpi(m_forcedDpi, m_forcedDpi);
+ }
+ return virtualDpi();
}
-
-qreal QXcbScreen::devicePixelRatio() const
+qreal QXcbScreen::pixelDensity() const
{
- static int override_dpr = qEnvironmentVariableIntValue("QT_DEVICE_PIXEL_RATIO");
- static bool auto_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto";
- if (override_dpr > 0)
- return override_dpr;
- if (auto_dpr)
- return m_devicePixelRatio;
- return 1.0;
+ return m_pixelDensity;
}
QPlatformCursor *QXcbScreen::cursor() const
@@ -466,7 +493,6 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
{
QRect xGeometry = geom;
- QRect xAvailableGeometry = xGeometry;
switch (rotation) {
case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal
m_orientation = Qt::LandscapeOrientation;
@@ -495,35 +521,23 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
Q_MM_PER_INCH * xGeometry.width() / dpi.second);
}
- xcb_get_property_reply_t * workArea =
- xcb_get_property_reply(xcb_connection(),
- xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
- atom(QXcbAtom::_NET_WORKAREA),
- XCB_ATOM_CARDINAL, 0, 1024), NULL);
-
- if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) {
- // If workArea->value_len > 4, the remaining ones seem to be for virtual desktops.
- // But QScreen doesn't know about that concept. In reality there could be a
- // "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop.
- // But for now just assume the first 4 values give us the geometry of the
- // "work area", AKA "available geometry"
- uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea);
- QRect virtualAvailableGeometry(geom[0], geom[1], geom[2], geom[3]);
- // Take the intersection of the desktop's available geometry with this screen's geometry
- // to get the part of the available geometry which belongs to this screen.
- xAvailableGeometry = xGeometry & virtualAvailableGeometry;
- }
- free(workArea);
-
qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
- m_devicePixelRatio = qRound(dpi/96);
- const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio
- m_geometry = QRect(xGeometry.topLeft(), xGeometry.size()/dpr);
+ m_pixelDensity = qRound(dpi/96);
+ m_geometry = QRect(xGeometry.topLeft(), xGeometry.size());
m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
- m_availableGeometry = QRect(mapFromNative(xAvailableGeometry.topLeft()), xAvailableGeometry.size()/dpr);
+ m_availableGeometry = xGeometry & m_virtualDesktop->workArea();
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
}
+void QXcbScreen::updateAvailableGeometry()
+{
+ QRect availableGeometry = m_geometry & m_virtualDesktop->workArea();
+ if (m_availableGeometry != availableGeometry) {
+ m_availableGeometry = availableGeometry;
+ QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
+ }
+}
+
void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
{
if (!connection()->hasXRandr())
@@ -544,7 +558,8 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) {
xcb_randr_mode_info_t *modeInfo = modesIter.data;
if (modeInfo->id == mode) {
- m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal);
+ const uint32_t dotCount = modeInfo->htotal * modeInfo->vtotal;
+ m_refreshRate = (dotCount != 0) ? modeInfo->dot_clock / dotCount : 0;
m_mode = mode;
break;
}
@@ -778,7 +793,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen)
formatSizeF(debug, screen->physicalSize());
// TODO 5.6 if (debug.verbosity() > 2) {
debug << ", screenNumber=" << screen->screenNumber();
- debug << ", virtualSize=" << screen->virtualSize().width() << "x" << screen->virtualSize().height() << " (";
+ debug << ", virtualSize=" << screen->virtualSize().width() << 'x' << screen->virtualSize().height() << " (";
formatSizeF(debug, screen->virtualSize());
debug << "), nativeGeometry=";
formatRect(debug, screen->nativeGeometry());
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index ccc30c0b84..c68c290791 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -39,6 +39,7 @@
#include <xcb/xcb.h>
#include <xcb/randr.h>
+#include <xcb/xfixes.h>
#include "qxcbobject.h"
#include "qxcbscreen.h"
@@ -64,14 +65,36 @@ public:
int number() const { return m_number; }
QSize size() const { return QSize(m_screen->width_in_pixels, m_screen->height_in_pixels); }
QSize physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); }
+ xcb_window_t root() const { return m_screen->root; }
+ QXcbScreen *screenAt(const QPoint &pos) const;
+
+ QList<QPlatformScreen *> screens() const { return m_screens; }
+ void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
+ void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
+ void addScreen(QPlatformScreen *s);
QXcbXSettings *xSettings() const;
+ bool compositingActive() const;
+
+ QRect workArea() const { return m_workArea; }
+ void updateWorkArea();
+
+ void handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event);
+ void subscribeToXFixesSelectionNotify();
+
private:
+ QRect getWorkArea() const;
+
xcb_screen_t *m_screen;
int m_number;
+ QList<QPlatformScreen *> m_screens;
QXcbXSettings *m_xSettings;
+ xcb_atom_t m_net_wm_cm_atom;
+ bool m_compositingActive;
+
+ QRect m_workArea;
};
class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
@@ -96,14 +119,12 @@ public:
QSizeF physicalVirtualSize() const { return m_virtualSizeMillimeters; }
QDpi virtualDpi() const;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ qreal pixelDensity() const Q_DECL_OVERRIDE;
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; }
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_orientation; }
- QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
- void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
- void removeVirtualSibling(QPlatformScreen *s) { m_siblings.removeOne(s); }
- void addVirtualSibling(QPlatformScreen *s) { ((QXcbScreen *) s)->isPrimary() ? m_siblings.prepend(s) : m_siblings.append(s); }
+ QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_virtualDesktop->screens(); }
+ QXcbVirtualDesktop *virtualDesktop() const { return m_virtualDesktop; }
void setPrimary(bool primary) { m_primary = primary; }
bool isPrimary() const { return m_primary; }
@@ -128,6 +149,7 @@ public:
void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event);
void updateGeometry(const QRect &geom, uint8_t rotation);
void updateGeometry(xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME);
+ void updateAvailableGeometry();
void updateRefreshRate(xcb_randr_mode_t mode);
void readXResources();
@@ -139,13 +161,6 @@ public:
QXcbXSettings *xSettings() const;
- QPoint mapToNative(const QPoint &pos) const;
- QPoint mapFromNative(const QPoint &pos) const;
- QPointF mapToNative(const QPointF &pos) const;
- QPointF mapFromNative(const QPointF &pos) const;
- QRect mapToNative(const QRect &rect) const;
- QRect mapFromNative(const QRect &rect) const;
-
private:
static bool xResource(const QByteArray &identifier,
const QByteArray &expectedIdentifier,
@@ -167,7 +182,6 @@ private:
QRect m_availableGeometry;
QSize m_virtualSize;
QSizeF m_virtualSizeMillimeters;
- QList<QPlatformScreen *> m_siblings;
Qt::ScreenOrientation m_orientation;
QString m_windowManagerName;
bool m_syncRequestSupported;
@@ -176,7 +190,7 @@ private:
QXcbCursor *m_cursor;
int m_refreshRate;
int m_forcedDpi;
- int m_devicePixelRatio;
+ int m_pixelDensity;
QFontEngine::HintStyle m_hintStyle;
bool m_noFontHinting;
QFontEngine::SubpixelAntialiasingType m_subpixelType;
diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
index 328b72234a..c2101a71c1 100644
--- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
@@ -134,6 +134,7 @@ static void sm_setProperty(const QString &name, const QStringList &value)
SmPropValue *prop = new SmPropValue[value.count()];
int count = 0;
QList<QByteArray> vl;
+ vl.reserve(value.size());
for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
prop[count].length = (*it).length();
vl.append((*it).toUtf8());
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index a4fdd70b79..1f217e8de7 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -63,14 +63,14 @@ QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection)
const xcb_atom_t selection = connection->internAtom(netSysTray.constData());
if (!selection)
return 0;
- return new QXcbSystemTrayTracker(connection, trayAtom, selection, connection);
+
+ return new QXcbSystemTrayTracker(connection, trayAtom, selection);
}
QXcbSystemTrayTracker::QXcbSystemTrayTracker(QXcbConnection *connection,
xcb_atom_t trayAtom,
- xcb_atom_t selection,
- QObject *parent)
- : QObject(parent)
+ xcb_atom_t selection)
+ : QObject(connection)
, m_selection(selection)
, m_trayAtom(trayAtom)
, m_connection(connection)
@@ -125,6 +125,7 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow()
// does not work for the QWindow parented on the tray.
QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const
{
+
xcb_connection_t *conn = m_connection->xcb_connection();
xcb_get_geometry_reply_t *geomReply =
xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), 0);
@@ -161,9 +162,43 @@ void QXcbSystemTrayTracker::handleDestroyNotifyEvent(const xcb_destroy_notify_ev
{
if (event->window == m_trayWindow) {
m_connection->removeWindowEventListener(m_trayWindow);
- m_trayWindow = 0;
+ m_trayWindow = XCB_WINDOW_NONE;
emitSystemTrayWindowChanged();
}
}
+bool QXcbSystemTrayTracker::visualHasAlphaChannel()
+{
+ if (m_trayWindow == XCB_WINDOW_NONE)
+ return false;
+
+ xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
+
+ // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom
+ xcb_get_property_cookie_t systray_atom_cookie;
+ xcb_get_property_reply_t *systray_atom_reply;
+
+ systray_atom_cookie = xcb_get_property_unchecked(m_connection->xcb_connection(), false, m_trayWindow,
+ tray_atom, XCB_ATOM_VISUALID, 0, 1);
+ systray_atom_reply = xcb_get_property_reply(m_connection->xcb_connection(), systray_atom_cookie, 0);
+
+ if (!systray_atom_reply)
+ return false;
+
+ xcb_visualid_t systrayVisualId = XCB_NONE;
+ if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) {
+ xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply);
+ systrayVisualId = vids[0];
+ }
+
+ free(systray_atom_reply);
+
+ if (systrayVisualId != XCB_NONE) {
+ quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId);
+ return depth == 32;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
index 9c20f1729a..b619afb9c4 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
@@ -57,14 +57,14 @@ public:
void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) Q_DECL_OVERRIDE;
+ bool visualHasAlphaChannel();
signals:
void systemTrayWindowChanged(QScreen *screen);
private:
explicit QXcbSystemTrayTracker(QXcbConnection *connection,
xcb_atom_t trayAtom,
- xcb_atom_t selection,
- QObject *parent = 0);
+ xcb_atom_t selection);
static xcb_window_t locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection);
void emitSystemTrayWindowChanged();
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 4fdebe1ebb..6023ee6b29 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -37,6 +37,7 @@
#include <QScreen>
#include <QtGui/QIcon>
#include <QtGui/QRegion>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include "qxcbintegration.h"
#include "qxcbconnection.h"
@@ -46,6 +47,7 @@
#include "qxcbwmsupport.h"
#include "qxcbimage.h"
#include "qxcbnativeinterface.h"
+#include "qxcbsystemtraytracker.h"
#include <qpa/qplatformintegration.h>
@@ -139,73 +141,11 @@ enum QX11EmbedMessageType {
const quint32 XEMBED_VERSION = 0;
-static inline QRect mapLocalGeometryToNative(const QRect &qtRect, int dpr)
-{
- return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr);
-}
-
-// When mapping expose events to Qt rects: round top/left towards the origin and
-// bottom/right away from the origin, making sure that we cover the whole widget
-
-static inline QPoint dpr_floor(const QPoint &p, int dpr)
-{
- return QPoint(p.x()/dpr, p.y()/dpr);
-}
-
-static inline QPoint dpr_ceil(const QPoint &p, int dpr)
-{
- return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr);
-}
-
-static inline QSize dpr_ceil(const QSize &s, int dpr)
-{
- return QSize((s.width() + dpr - 1) / dpr, (s.height() + dpr - 1) / dpr);
-}
-
-static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
-{
- return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr));
-}
-
-static inline QRect mapLocalGeometryFromNative(const QRect &xRect, int dpr)
-{
- return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr));
-}
-
QXcbScreen *QXcbWindow::parentScreen()
{
return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
}
-QPoint QXcbWindow::mapToNative(const QPoint &pos, const QXcbScreen *screen) const
-{
- if (parent())
- return pos * int(screen->devicePixelRatio());
- else
- return screen->mapToNative(pos);
-}
-QPoint QXcbWindow::mapFromNative(const QPoint &pos, const QXcbScreen *screen) const
-{
- if (parent())
- return pos / int(screen->devicePixelRatio());
- else
- return screen->mapFromNative(pos);
-}
-QRect QXcbWindow::mapToNative(const QRect &rect, const QXcbScreen *screen) const
-{
- if (parent())
- return mapLocalGeometryToNative(rect, int(screen->devicePixelRatio()));
- else
- return screen->mapToNative(rect);
-}
-QRect QXcbWindow::mapFromNative(const QRect &rect, const QXcbScreen *screen) const
-{
- if (parent())
- return mapLocalGeometryFromNative(rect, int(screen->devicePixelRatio()));
- else
- return screen->mapFromNative(rect);
-}
-
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
static inline bool isTransient(const QWindow *w)
{
@@ -374,14 +314,12 @@ void QXcbWindow::create()
destroy();
- m_deferredExpose = false;
- m_configureNotifyPending = true;
m_windowState = Qt::WindowNoState;
Qt::WindowType type = window()->type();
QXcbScreen *currentScreen = xcbScreen();
- QRect rect = window()->geometry();
+ QRect rect = windowGeometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
m_xcbScreen = platformScreen;
@@ -424,17 +362,15 @@ void QXcbWindow::create()
if (platformScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
- const int dpr = int(devicePixelRatio());
-
- QSize minimumSize = window()->minimumSize();
+ const QSize minimumSize = windowMinimumSize();
if (rect.width() > 0 || rect.height() > 0) {
- rect.setWidth(qBound(1, rect.width(), XCOORD_MAX/dpr));
- rect.setHeight(qBound(1, rect.height(), XCOORD_MAX/dpr));
+ rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
+ rect.setHeight(qBound(1, rect.height(), XCOORD_MAX));
} else if (minimumSize.width() > 0 || minimumSize.height() > 0) {
rect.setSize(minimumSize);
} else {
- rect.setWidth(defaultWindowWidth);
- rect.setHeight(defaultWindowHeight);
+ rect.setWidth(QHighDpi::toNativePixels(int(defaultWindowWidth), platformScreen->QPlatformScreen::screen()));
+ rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen()));
}
xcb_window_t xcb_parent_id = platformScreen->root();
@@ -451,7 +387,8 @@ void QXcbWindow::create()
resolveFormat();
#ifdef XCB_USE_XLIB
- if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
+ if (window()->surfaceType() != QSurface::RasterSurface
+ && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
XVisualInfo *visualInfo = Q_NULLPTR;
if (connection()->hasDefaultVisualId())
visualInfo = CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(this);
@@ -478,9 +415,7 @@ void QXcbWindow::create()
m_visualId = visualInfo->visualid;
- const QRect xRect = mapToNative(rect, platformScreen);
-
- m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(),
+ m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, rect.x(), rect.y(), rect.width(), rect.height(),
0, visualInfo->depth, InputOutput, visualInfo->visual,
CWBackPixel|CWBorderPixel|CWColormap, &a);
@@ -536,16 +471,14 @@ void QXcbWindow::create()
}
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
- const QRect xRect = mapToNative(rect, platformScreen);
-
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
m_window, // window id
xcb_parent_id, // parent window id
- xRect.x(),
- xRect.y(),
- xRect.width(),
- xRect.height(),
+ rect.x(),
+ rect.y(),
+ rect.width(),
+ rect.height(),
0, // border width
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
m_visualId, // visual
@@ -565,10 +498,7 @@ void QXcbWindow::create()
properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
- if (platformScreen->syncRequestSupported())
- m_usingSyncProtocol = supportsSyncProtocol();
- else
- m_usingSyncProtocol = false;
+ m_usingSyncProtocol = platformScreen->syncRequestSupported();
if (m_usingSyncProtocol)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
@@ -708,17 +638,16 @@ void QXcbWindow::setGeometry(const QRect &rect)
propagateSizeHints();
- QXcbScreen *currentScreen = xcbScreen();
+ QXcbScreen *currentScreen = m_xcbScreen;
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen)
- newScreen = currentScreen;
+ newScreen = xcbScreen();
m_xcbScreen = newScreen;
- const QRect xRect = mapToNative(rect, newScreen);
- const QRect wmGeometry = windowToWmGeometry(xRect);
+ const QRect wmGeometry = windowToWmGeometry(rect);
- if (newScreen != currentScreen)
+ if (newScreen && newScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (qt_window_private(window())->positionAutomatic) {
@@ -842,6 +771,13 @@ void QXcbWindow::setVisible(bool visible)
hide();
}
+static inline bool testShowWithoutActivating(const QWindow *window)
+{
+ // QWidget-attribute Qt::WA_ShowWithoutActivating.
+ const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
+ return showWithoutActivating.isValid() && showWithoutActivating.toBool();
+}
+
void QXcbWindow::show()
{
if (window()->isTopLevel()) {
@@ -889,7 +825,9 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
- if (connection()->time() != XCB_TIME_CURRENT_TIME)
+ if (testShowWithoutActivating(window()))
+ updateNetWmUserTime(0);
+ else if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow"))
@@ -1179,6 +1117,9 @@ void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
mwmhints.flags |= MWM_HINTS_DECORATIONS;
bool customize = flags & Qt::CustomizeWindowHint;
+ if (type == Qt::Window && !customize)
+ flags |= Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
+
if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
mwmhints.decorations |= MWM_DECOR_BORDER;
mwmhints.decorations |= MWM_DECOR_RESIZEH;
@@ -1328,7 +1269,7 @@ void QXcbWindow::updateMotifWmHintsBeforeMap()
mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
}
- if (window()->minimumSize() == window()->maximumSize()) {
+ if (windowMinimumSize() == windowMaximumSize()) {
// fixed size, remove the resize handle (since mwm/dtwm
// isn't smart enough to do it itself)
mwmhints.flags |= MWM_HINTS_FUNCTIONS;
@@ -1393,7 +1334,11 @@ void QXcbWindow::updateNetWmStateBeforeMap()
void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
{
xcb_window_t wid = m_window;
- connection()->setNetWmUserTime(timestamp);
+ // If timestamp == 0, then it means that the window should not be
+ // initially activated. Don't update global user time for this
+ // special case.
+ if (timestamp != 0)
+ connection()->setNetWmUserTime(timestamp);
const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
if (m_netWmUserTimeWindow || isSupportedByWM) {
@@ -1522,10 +1467,22 @@ void QXcbWindow::setWindowTitle(const QString &title)
xcb_flush(xcb_connection());
}
+void QXcbWindow::setWindowIconText(const QString &title)
+{
+ const QByteArray ba = title.toUtf8();
+ Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_ICON_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData()));
+}
+
void QXcbWindow::setWindowIcon(const QIcon &icon)
{
QVector<quint32> icon_data;
-
if (!icon.isNull()) {
QList<QSize> availableSizes = icon.availableSizes();
if (availableSizes.isEmpty()) {
@@ -1602,8 +1559,7 @@ void QXcbWindow::propagateSizeHints()
xcb_size_hints_t hints;
memset(&hints, 0, sizeof(hints));
- const int dpr = int(devicePixelRatio());
- const QRect xRect = windowToWmGeometry(mapToNative(geometry(), xcbScreen()));
+ const QRect xRect = windowToWmGeometry(geometry());
QWindow *win = window();
@@ -1613,10 +1569,10 @@ void QXcbWindow::propagateSizeHints()
xcb_size_hints_set_size(&hints, true, xRect.width(), xRect.height());
xcb_size_hints_set_win_gravity(&hints, m_gravity);
- QSize minimumSize = win->minimumSize() * dpr;
- QSize maximumSize = win->maximumSize() * dpr;
- QSize baseSize = win->baseSize() * dpr;
- QSize sizeIncrement = win->sizeIncrement() * dpr;
+ QSize minimumSize = windowMinimumSize();
+ QSize maximumSize = windowMaximumSize();
+ QSize baseSize = windowBaseSize();
+ QSize sizeIncrement = windowSizeIncrement();
if (minimumSize.width() > 0 || minimumSize.height() > 0)
xcb_size_hints_set_min_size(&hints,
@@ -1645,7 +1601,7 @@ void QXcbWindow::requestActivateWindow()
return;
}
- if (!m_mapped) {
+ if (!m_mapped || !xcbScreen()) {
m_deferredActivation = true;
return;
}
@@ -1690,6 +1646,12 @@ void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmW
static_cast<QXcbWindow *>(window->handle())->setWmWindowType(windowTypes, window->flags());
}
+void QXcbWindow::setWindowIconTextStatic(QWindow *window, const QString &text)
+{
+ if (window->handle())
+ static_cast<QXcbWindow *>(window->handle())->setWindowIconText(text);
+}
+
uint QXcbWindow::visualIdStatic(QWindow *window)
{
if (window && window->handle())
@@ -1855,13 +1817,54 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W
xcb_flush(xcb_connection());
}
+void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window)
+{
+ if (window->handle())
+ static_cast<QXcbWindow *>(window->handle())->setParentRelativeBackPixmap();
+}
+
+void QXcbWindow::setParentRelativeBackPixmap()
+{
+ const quint32 mask = XCB_CW_BACK_PIXMAP;
+ const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE };
+ Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
+}
+
+bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window)
+{
+ if (window->handle())
+ return static_cast<QXcbWindow *>(window->handle())->requestSystemTrayWindowDock();
+ return false;
+}
+
+bool QXcbWindow::requestSystemTrayWindowDock() const
+{
+ if (!connection()->systemTrayTracker())
+ return false;
+ connection()->systemTrayTracker()->requestSystemTrayWindowDock(m_window);
+ return true;
+}
+
+QRect QXcbWindow::systemTrayWindowGlobalGeometryStatic(const QWindow *window)
+{
+ if (window->handle())
+ return static_cast<QXcbWindow *>(window->handle())->systemTrayWindowGlobalGeometry();
+ return QRect();
+}
+
+QRect QXcbWindow::systemTrayWindowGlobalGeometry() const
+{
+ if (!connection()->systemTrayTracker())
+ return QRect();
+ return connection()->systemTrayTracker()->systemTrayWindowGlobalGeometry(m_window);
+}
+
class ExposeCompressor
{
public:
- ExposeCompressor(xcb_window_t window, QRegion *region, int devicePixelRatio)
+ ExposeCompressor(xcb_window_t window, QRegion *region)
: m_window(window)
, m_region(region)
- , m_dpr(devicePixelRatio)
, m_pending(true)
{
}
@@ -1877,7 +1880,7 @@ public:
return false;
if (expose->count == 0)
m_pending = false;
- *m_region |= mapExposeFromNative(QRect(expose->x, expose->y, expose->width, expose->height), m_dpr);
+ *m_region |= QRect(expose->x, expose->y, expose->width, expose->height);
return true;
}
@@ -1889,7 +1892,6 @@ public:
private:
xcb_window_t m_window;
QRegion *m_region;
- int m_dpr;
bool m_pending;
};
@@ -1903,16 +1905,14 @@ bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result)
void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
- const int dpr = int(devicePixelRatio());
- QRect x_rect(event->x, event->y, event->width, event->height);
- QRect rect = mapExposeFromNative(x_rect, dpr);
+ QRect rect(event->x, event->y, event->width, event->height);
if (m_exposeRegion.isEmpty())
m_exposeRegion = rect;
else
m_exposeRegion |= rect;
- ExposeCompressor compressor(m_window, &m_exposeRegion, dpr);
+ ExposeCompressor compressor(m_window, &m_exposeRegion);
xcb_generic_event_t *filter = 0;
do {
filter = connection()->checkEvent(compressor);
@@ -1964,13 +1964,13 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
}
#ifndef QT_NO_DRAGANDDROP
} else if (event->type == atom(QXcbAtom::XdndEnter)) {
- connection()->drag()->handleEnter(window(), event);
+ connection()->drag()->handleEnter(this, event);
} else if (event->type == atom(QXcbAtom::XdndPosition)) {
- connection()->drag()->handlePosition(window(), event);
+ connection()->drag()->handlePosition(this, event);
} else if (event->type == atom(QXcbAtom::XdndLeave)) {
- connection()->drag()->handleLeave(window(), event);
+ connection()->drag()->handleLeave(this, event);
} else if (event->type == atom(QXcbAtom::XdndDrop)) {
- connection()->drag()->handleDrop(window(), event);
+ connection()->drag()->handleDrop(this, event);
#endif
} else if (event->type == atom(QXcbAtom::_XEMBED)) {
handleXEmbedMessage(event);
@@ -1983,33 +1983,14 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
// and other messages.
} else if (event->type == atom(QXcbAtom::_COMPIZ_DECOR_PENDING)
|| event->type == atom(QXcbAtom::_COMPIZ_DECOR_REQUEST)
- || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)) {
+ || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)
+ || event->type == atom(QXcbAtom::_COMPIZ_TOOLKIT_ACTION)) {
//silence the _COMPIZ messages for now
} else {
qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type);
}
}
-// Temporary workaround for bug in QPlatformScreen::screenForGeometry
-// we need the native geometries to detect our screen, but that's not
-// available in cross-platform code. Will be fixed properly when highDPI
-// support is refactored to expose the native coordinate system.
-
-QXcbScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const
-{
- QXcbScreen *currentScreen = xcbScreen();
- if (!currentScreen && QGuiApplication::primaryScreen())
- currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle());
- if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) {
- Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
- QXcbScreen *xcbScreen = static_cast<QXcbScreen*>(screen);
- if (xcbScreen->nativeGeometry().intersects(newGeometry))
- return xcbScreen;
- }
- }
- return currentScreen;
-}
-
void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event)
{
bool fromSendEvent = (event->response_type & 0x80);
@@ -2026,26 +2007,21 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
- const QRect nativeRect = QRect(pos, QSize(event->width, event->height));
- QXcbScreen *newScreen = parent() ? parentScreen() : screenForNativeGeometry(nativeRect);
+ const QRect rect = QRect(pos, QSize(event->width, event->height));
+ QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
QXcbScreen *currentScreen = m_xcbScreen;
- m_xcbScreen = newScreen;
+ m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
if (!newScreen)
return;
- const QRect rect = mapFromNative(nativeRect, newScreen);
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
if (newScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
- m_configureNotifyPending = false;
-
- if (m_deferredExpose) {
- m_deferredExpose = false;
+ if (m_mapped)
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
- }
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@@ -2071,11 +2047,10 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const
if (!m_embedded)
return pos;
- const int dpr = int(devicePixelRatio());
QPoint ret;
xcb_translate_coordinates_cookie_t cookie =
xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(),
- pos.x() * dpr, pos.y() * dpr);
+ pos.x(), pos.y());
xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) {
@@ -2084,7 +2059,7 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const
free(reply);
}
- return mapFromNative(ret, xcbScreen());
+ return ret;
}
QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
@@ -2092,17 +2067,15 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
if (!m_embedded)
return pos;
- const int dpr = int(devicePixelRatio());
QPoint ret;
- QPoint xPos = mapToNative(pos, xcbScreen());
xcb_translate_coordinates_cookie_t cookie =
xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(),
- xPos.x(), xPos.y());
+ pos.x(), pos.y());
xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) {
- ret.setX(reply->dst_x / dpr);
- ret.setY(reply->dst_y / dpr);
+ ret.setX(reply->dst_x);
+ ret.setY(reply->dst_y);
free(reply);
}
@@ -2115,10 +2088,8 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
m_mapped = true;
if (m_deferredActivation)
requestActivateWindow();
- if (m_configureNotifyPending)
- m_deferredExpose = true;
- else
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size() * int(devicePixelRatio())));
+
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
}
}
@@ -2150,9 +2121,8 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
sendXEmbedMessage(container->xcb_window(), XEMBED_REQUEST_FOCUS);
}
}
- const int dpr = int(devicePixelRatio());
- QPoint local(event_x / dpr, event_y / dpr);
- QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
+ QPoint local(event_x, event_y);
+ QPoint global(root_x, root_y);
if (isWheel) {
if (!connection()->isAtLeastXI21()) {
@@ -2174,9 +2144,8 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
{
- const int dpr = int(devicePixelRatio());
- QPoint local(event_x / dpr, event_y / dpr);
- QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
+ QPoint local(event_x, event_y);
+ QPoint global(root_x, root_y);
if (detail >= 4 && detail <= 7) {
// mouse wheel, handled in handleButtonPressEvent()
@@ -2189,11 +2158,8 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
{
- if (!xcbScreen())
- return;
- const int dpr = int(devicePixelRatio());
- QPoint local(event_x / dpr, event_y / dpr);
- QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
+ QPoint local(event_x, event_y);
+ QPoint global(root_x, root_y);
handleMouseEvent(timestamp, local, global, modifiers);
}
@@ -2321,11 +2287,10 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
if (ignoreEnterEvent(event))
return;
- const int dpr = int(devicePixelRatio());
- const QPoint local(event->event_x/dpr, event->event_y/dpr);
+ const QPoint local(event->event_x, event->event_y);
if (!xcbScreen())
return;
- QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
+ QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -2341,11 +2306,10 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0;
if (enterWindow) {
- const int dpr = int(devicePixelRatio());
- QPoint local(enter->event_x/dpr, enter->event_y/dpr);
+ QPoint local(enter->event_x, enter->event_y);
if (!xcbScreen())
return;
- QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
+ QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
} else {
@@ -2403,8 +2367,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
return;
} else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) {
m_dirtyFrameMargins = true;
- } else if (event->atom == atom(QXcbAtom::_NET_WORKAREA) && xcbScreen() && event->window == xcbScreen()->root()) {
- xcbScreen()->updateGeometry(event->time);
}
}
@@ -2524,7 +2486,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
xev.type = moveResize;
xev.window = xcb_window();
xev.format = 32;
- const QPoint globalPos = mapToNative(window()->mapToGlobal(pos), xcbScreen());
+ const QPoint globalPos = window()->mapToGlobal(pos);
xev.data.data32[0] = globalPos.x();
xev.data.data32[1] = globalPos.y();
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
@@ -2650,10 +2612,11 @@ 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 {
- const int dpr = devicePixelRatio();
QVector<xcb_rectangle_t> rects;
- foreach (const QRect &r, region.rects())
- rects.push_back(qRectToXCBRectangle(mapLocalGeometryToNative(r, dpr)));
+ const QVector<QRect> regionRects = region.rects();
+ rects.reserve(regionRects.count());
+ foreach (const QRect &r, regionRects)
+ rects.push_back(qRectToXCBRectangle(r));
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]);
@@ -2691,11 +2654,6 @@ void QXcbWindow::postSyncWindowRequest()
}
}
-qreal QXcbWindow::devicePixelRatio() const
-{
- return xcbScreen() ? xcbScreen()->devicePixelRatio() : 1.0;
-}
-
QXcbScreen *QXcbWindow::xcbScreen() const
{
return static_cast<QXcbScreen *>(screen());
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index a379a6f9db..43e66a774d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -81,11 +81,12 @@ public:
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
bool isExposed() const Q_DECL_OVERRIDE;
- bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
+ bool isEmbedded(const QPlatformWindow *parentWindow = 0) const Q_DECL_OVERRIDE;
QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
+ void setWindowIconText(const QString &title);
void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void raise() Q_DECL_OVERRIDE;
void lower() Q_DECL_OVERRIDE;
@@ -145,6 +146,16 @@ public:
QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const;
void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::WindowFlags flags);
+ static void setWindowIconTextStatic(QWindow *window, const QString &text);
+
+ static void setParentRelativeBackPixmapStatic(QWindow *window);
+ void setParentRelativeBackPixmap();
+
+ static bool requestSystemTrayWindowDockStatic(const QWindow *window);
+ bool requestSystemTrayWindowDock() const;
+
+ static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window);
+ QRect systemTrayWindowGlobalGeometry() const;
uint visualId() const;
bool needsSync() const;
@@ -152,8 +163,6 @@ public:
void postSyncWindowRequest();
void clearSyncWindowRequest() { m_pendingSyncRequest = 0; }
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
-
QXcbScreen *xcbScreen() const;
virtual void create();
@@ -167,12 +176,7 @@ public Q_SLOTS:
protected:
virtual void resolveFormat() { m_format = window()->requestedFormat(); }
virtual void *createVisual() { return Q_NULLPTR; }
- virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); }
- QPoint mapToNative(const QPoint &pos, const QXcbScreen *screen) const;
- QPoint mapFromNative(const QPoint &pos, const QXcbScreen *screen) const;
- QRect mapToNative(const QRect &rect, const QXcbScreen *screen) const;
- QRect mapFromNative(const QRect &rect, const QXcbScreen *screen) const;
QXcbScreen *parentScreen();
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
@@ -227,8 +231,6 @@ protected:
bool m_transparent;
bool m_usingSyncProtocol;
bool m_deferredActivation;
- bool m_deferredExpose;
- bool m_configureNotifyPending;
bool m_embedded;
bool m_alertState;
xcb_window_t m_netWmUserTimeWindow;
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 7d31ac7118..82c1c1de77 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -94,14 +94,14 @@ void QXcbWMSupport::updateVirtualRoots()
int offset = 0;
int remaining = 0;
do {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_ATOM, offset, 1024);
+ xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL);
if (!reply)
break;
remaining = 0;
- if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
+ if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) {
int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t);
xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply);
int s = net_virtual_roots.size();
diff --git a/src/plugins/platforms/xcb/qxlibconvenience.cpp b/src/plugins/platforms/xcb/qxlibconvenience.cpp
deleted file mode 100644
index f3c7d2b24e..0000000000
--- a/src/plugins/platforms/xcb/qxlibconvenience.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifdef XCB_USE_XLIB
-
-#include "qxlibconvenience.h"
-
-// Some Xlib headers are heavy macro namespace polluters and conflict with Qt types.
-// This unit makes it easier to deal with them by encapsulating these includes in this .cpp.
-#include <X11/Xutil.h>
-
-QT_BEGIN_NAMESPACE
-
-xcb_keysym_t q_XLookupString(void *display, xcb_window_t window, xcb_window_t root, uint state, xcb_keycode_t code, int type, QByteArray *chars)
-{
- KeySym sym = 0;
- chars->resize(512);
- XKeyEvent event;
- memset(&event, 0, sizeof(event));
- event.type = type;
- event.display = static_cast<Display*>(display);
- event.window = window;
- event.root = root;
- event.state = state;
- event.keycode = code;
- int count = XLookupString(&event, chars->data(), chars->size(), &sym, 0);
- chars->resize(count);
- return sym;
-}
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/xcb/qxlibconvenience.h b/src/plugins/platforms/xcb/qxlibconvenience.h
deleted file mode 100644
index 0e6e1c37ec..0000000000
--- a/src/plugins/platforms/xcb/qxlibconvenience.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef XLIBUTILS_H
-#define XLIBUTILS_H
-
-#ifdef XCB_USE_XLIB
-
-#include <xcb/xcb_keysyms.h>
-#include <QByteArray>
-
-QT_BEGIN_NAMESPACE
-
-xcb_keysym_t q_XLookupString(void *display, xcb_window_t window, xcb_window_t root, uint state, xcb_keycode_t code, int type, QByteArray *chars);
-
-QT_END_NAMESPACE
-
-#endif // XCB_USE_XLIB
-#endif
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 12987567ff..60eb8a02e3 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -1,13 +1,6 @@
TARGET = QtXcbQpa
CONFIG += no_module_headers internal_module
-MODULE_INCLUDES = \
- \$\$QT_MODULE_INCLUDE_BASE \
- \$\$QT_MODULE_INCLUDE_BASE/QtQGui
-MODULE_PRIVATE_INCLUDES = \
- \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION \
- \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION/QtGui
-
load(qt_module)
QT += core-private gui-private platformsupport-private
@@ -47,8 +40,6 @@ HEADERS = \
qxcbxsettings.h \
qxcbsystemtraytracker.h
-LIBS += $$QMAKE_LIBS_DYNLOAD
-
DEFINES += QT_BUILD_XCB_PLUGIN
# needed by Xcursor ...
contains(QT_CONFIG, xcb-xlib) {
diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
index 2ac31bf715..141056637e 100644
--- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
+++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.h
@@ -34,7 +34,11 @@
#ifndef QGTK2DIALOGHELPERS_P_H
#define QGTK2DIALOGHELPERS_P_H
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qurl.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
#include <qpa/qplatformdialoghelper.h>
typedef struct _GtkDialog GtkDialog;
@@ -43,6 +47,7 @@ typedef struct _GtkFileFilter GtkFileFilter;
QT_BEGIN_NAMESPACE
class QGtk2Dialog;
+class QColor;
class QGtk2ColorDialogHelper : public QPlatformColorDialogHelper
{
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index af4f6fc8fe..03b7dc266b 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,8 +1,15 @@
TEMPLATE = subdirs
+load(qfeatures)
SUBDIRS *= sqldrivers
-!winrt:qtHaveModule(network): SUBDIRS += bearer
-qtHaveModule(gui): SUBDIRS *= imageformats platforms platforminputcontexts platformthemes generic
+qtHaveModule(network):!contains(QT_DISABLED_FEATURES, bearermanagement): SUBDIRS += bearer
+qtHaveModule(gui) {
+ SUBDIRS *= platforms platforminputcontexts platformthemes
+ !contains(QT_DISABLED_FEATURES, imageformatplugin): SUBDIRS *= imageformats
+ !contains(QT_DISABLED_FEATURES, library): SUBDIRS *= generic
+}
qtHaveModule(widgets): SUBDIRS *= styles
-!winrt:!wince:qtHaveModule(widgets): SUBDIRS += printsupport
+!winrt:!wince*:qtHaveModule(widgets):!contains(QT_DISABLED_FEATURES, printer) {
+ SUBDIRS += printsupport
+}
diff --git a/src/plugins/printsupport/cocoa/main.cpp b/src/plugins/printsupport/cocoa/main.cpp
index 2037724719..3db7b49ba4 100644
--- a/src/plugins/printsupport/cocoa/main.cpp
+++ b/src/plugins/printsupport/cocoa/main.cpp
@@ -38,8 +38,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_PRINTER
-
class QCocoaPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
{
Q_OBJECT
@@ -67,8 +65,6 @@ QPlatformPrinterSupport *QCocoaPrinterSupportPlugin::create(const QString &key)
return platformPrinterSupport;
}
-#endif
-
QT_END_NAMESPACE
#include "main.moc"
diff --git a/src/plugins/printsupport/cups/main.cpp b/src/plugins/printsupport/cups/main.cpp
index 82485114ab..abd24d411a 100644
--- a/src/plugins/printsupport/cups/main.cpp
+++ b/src/plugins/printsupport/cups/main.cpp
@@ -37,8 +37,6 @@
#include <qpa/qplatformprintplugin.h>
#include <QtCore/QStringList>
-#ifndef QT_NO_PRINTER
-
QT_BEGIN_NAMESPACE
class QCupsPrinterSupportPlugin : public QPlatformPrinterSupportPlugin
@@ -65,6 +63,4 @@ QPlatformPrinterSupport *QCupsPrinterSupportPlugin::create(const QString &key)
QT_END_NAMESPACE
-#endif // QT_NO_PRINTER
-
#include "main.moc"
diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp
index c00d7f302c..7ca81986b4 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp
@@ -33,8 +33,6 @@
#include "qcupsprintengine_p.h"
-#ifndef QT_NO_PRINTER
-
#include <qpa/qplatformprintplugin.h>
#include <qpa/qplatformprintersupport.h>
@@ -226,7 +224,9 @@ void QCupsPrintEnginePrivate::closePrintDevice()
it += 2;
}
- for (int c = 0; c < options.size(); ++c) {
+ const int numOptions = options.size();
+ cupsOptStruct.reserve(numOptions);
+ for (int c = 0; c < numOptions; ++c) {
cups_option_t opt;
opt.name = options[c].first.data();
opt.value = options[c].second.data();
@@ -315,5 +315,3 @@ void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
}
QT_END_NAMESPACE
-
-#endif // QT_NO_PRINTER
diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h
index b589d40b6c..a611740e09 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -47,8 +47,6 @@
#include "QtPrintSupport/qprintengine.h"
-#ifndef QT_NO_PRINTER
-
#include <QtCore/qstring.h>
#include <QtGui/qpaintengine.h>
@@ -100,6 +98,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_PRINTER
-
#endif // QCUPSPRINTENGINE_P_H
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index ea7c116e3c..b257918acf 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -34,8 +34,6 @@
#include "qcupsprintersupport_p.h"
-#ifndef QT_NO_PRINTER
-
#include "qcupsprintengine_p.h"
#include "qppdprintdevice.h"
#include <private/qprinterinfo_p.h>
@@ -80,6 +78,7 @@ QStringList QCupsPrinterSupport::availablePrintDeviceIds() const
QStringList list;
cups_dest_t *dests;
int count = cupsGetDests(&dests);
+ list.reserve(count);
for (int i = 0; i < count; ++i) {
QString printerId = QString::fromLocal8Bit(dests[i].name);
if (dests[i].instance)
@@ -109,5 +108,3 @@ QString QCupsPrinterSupport::defaultPrintDeviceId() const
}
QT_END_NAMESPACE
-
-#endif // QT_NO_PRINTER
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
index ea913deeaa..6dcaa4e893 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h
@@ -48,8 +48,6 @@
#include <qpa/qplatformprintersupport.h>
-#ifndef QT_NO_PRINTER
-
#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
@@ -73,5 +71,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_PRINTER
#endif // QCUPSPRINTERSUPPORT_H
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index 808424b1ed..1b9ff98fca 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -42,8 +42,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_PRINTER
-
QPpdPrintDevice::QPpdPrintDevice()
: QPlatformPrintDevice(),
m_cupsDest(0),
@@ -269,6 +267,7 @@ void QPpdPrintDevice::loadInputSlots() const
if (m_ppd) {
ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot");
if (inputSlots) {
+ m_inputSlots.reserve(inputSlots->num_choices);
for (int i = 0; i < inputSlots->num_choices; ++i)
m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i]));
}
@@ -309,6 +308,7 @@ void QPpdPrintDevice::loadOutputBins() const
if (m_ppd) {
ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin");
if (outputBins) {
+ m_outputBins.reserve(outputBins->num_choices);
for (int i = 0; i < outputBins->num_choices; ++i)
m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i]));
}
@@ -350,6 +350,7 @@ void QPpdPrintDevice::loadDuplexModes() const
if (m_ppd) {
ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex");
if (duplexModes) {
+ m_duplexModes.reserve(duplexModes->num_choices);
for (int i = 0; i < duplexModes->num_choices; ++i)
m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice));
}
@@ -472,6 +473,4 @@ cups_ptype_e QPpdPrintDevice::printerTypeFlags() const
return static_cast<cups_ptype_e>(printerOption("printer-type").toUInt());
}
-#endif // QT_NO_PRINTER
-
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h
index 5ebcf39566..a28348eb60 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.h
+++ b/src/plugins/printsupport/cups/qppdprintdevice.h
@@ -47,7 +47,9 @@
#include <qpa/qplatformprintdevice.h>
-#ifndef QT_NO_PRINTER
+#include <QtCore/qbytearray.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmargins.h>
#include <cups/cups.h>
#include <cups/ppd.h>
@@ -107,5 +109,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_PRINTER
#endif // QPPDPRINTDEVICE_H
diff --git a/src/plugins/printsupport/printsupport.pro b/src/plugins/printsupport/printsupport.pro
index ed201f0744..bd6681f53c 100644
--- a/src/plugins/printsupport/printsupport.pro
+++ b/src/plugins/printsupport/printsupport.pro
@@ -2,4 +2,7 @@ TEMPLATE = subdirs
osx: SUBDIRS += cocoa
win32: SUBDIRS += windows
-unix:!mac:contains(QT_CONFIG, cups): SUBDIRS += cups
+unix:!mac:contains(QT_CONFIG, cups) {
+ load(qfeatures)
+ !contains(QT_DISABLED_FEATURES, cups): SUBDIRS += cups
+}
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index 505f3138ca..d378ff3130 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -41,8 +41,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_PRINTER
-
QT_WARNING_DISABLE_GCC("-Wsign-compare")
extern qreal qt_pointMultiplier(QPageLayout::Unit unit);
@@ -471,6 +469,4 @@ QString QWindowsPrintDevice::defaultPrintDeviceId()
return QString::fromWCharArray(name.data());
}
-#endif // QT_NO_PRINTER
-
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h
index 8ab487a59c..2c232d22c5 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.h
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h
@@ -47,8 +47,6 @@
#include <qpa/qplatformprintdevice.h>
-#ifndef QT_NO_PRINTER
-
#include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE
@@ -95,5 +93,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_PRINTER
#endif // QWINDOWSPRINTDEVICE_H
diff --git a/src/plugins/styles/bb10style/bright/button/core_button_inactive.png b/src/plugins/styles/bb10style/bright/button/core_button_inactive.png
index 7769f15e44..7769f15e44 100755..100644
--- a/src/plugins/styles/bb10style/bright/button/core_button_inactive.png
+++ b/src/plugins/styles/bb10style/bright/button/core_button_inactive.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/button/core_button_pressed.png b/src/plugins/styles/bb10style/bright/button/core_button_pressed.png
index 59b5bfa7c2..59b5bfa7c2 100755..100644
--- a/src/plugins/styles/bb10style/bright/button/core_button_pressed.png
+++ b/src/plugins/styles/bb10style/bright/button/core_button_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png b/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png
index f1c2ee3bed..f1c2ee3bed 100755..100644
--- a/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png
+++ b/src/plugins/styles/bb10style/bright/checkbox/core_checkbox_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png
index 07b8ea21bf..07b8ea21bf 100755..100644
--- a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png
+++ b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png
index 55f8aee066..55f8aee066 100755..100644
--- a/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png
+++ b/src/plugins/styles/bb10style/bright/lineedit/core_textinput_bg_highlight.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png b/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png
index 34daccc27e..34daccc27e 100755..100644
--- a/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png
+++ b/src/plugins/styles/bb10style/bright/listitem/core_listitem_active.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png b/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png
index 7a1e22321d..7a1e22321d 100755..100644
--- a/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png
+++ b/src/plugins/styles/bb10style/bright/listitem/core_listitem_divider.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png b/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png
index 3ff930dea7..3ff930dea7 100755..100644
--- a/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png
+++ b/src/plugins/styles/bb10style/bright/progressbar/core_progressindicator_bg.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png
index cb4c6a8136..cb4c6a8136 100755..100644
--- a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png
+++ b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_inactive.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png
index 88fd1344d2..88fd1344d2 100755..100644
--- a/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png
+++ b/src/plugins/styles/bb10style/bright/radiobutton/core_radiobutton_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png b/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png
index 79154e0568..79154e0568 100755..100644
--- a/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png
+++ b/src/plugins/styles/bb10style/bright/scrollbar/core_scrollbar.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png b/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png
index 8cb79118b9..8cb79118b9 100755..100644
--- a/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png
+++ b/src/plugins/styles/bb10style/bright/slider/core_slider_handle_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/button/core_button_inactive.png b/src/plugins/styles/bb10style/dark/button/core_button_inactive.png
index 97842e1ac4..97842e1ac4 100755..100644
--- a/src/plugins/styles/bb10style/dark/button/core_button_inactive.png
+++ b/src/plugins/styles/bb10style/dark/button/core_button_inactive.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/button/core_button_pressed.png b/src/plugins/styles/bb10style/dark/button/core_button_pressed.png
index c149b64a26..c149b64a26 100755..100644
--- a/src/plugins/styles/bb10style/dark/button/core_button_pressed.png
+++ b/src/plugins/styles/bb10style/dark/button/core_button_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png b/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png
index 507a77b3ea..507a77b3ea 100755..100644
--- a/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png
+++ b/src/plugins/styles/bb10style/dark/checkbox/core_checkbox_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png
index 07b8ea21bf..07b8ea21bf 100755..100644
--- a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png
+++ b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png
index 9b115897e8..9b115897e8 100755..100644
--- a/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png
+++ b/src/plugins/styles/bb10style/dark/lineedit/core_textinput_bg_highlight.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png b/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png
index 52aa4e4aa2..52aa4e4aa2 100755..100644
--- a/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png
+++ b/src/plugins/styles/bb10style/dark/listitem/core_listitem_active.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png b/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png
index 39e3a8a4f5..39e3a8a4f5 100755..100644
--- a/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png
+++ b/src/plugins/styles/bb10style/dark/listitem/core_listitem_divider.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png b/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png
index 95fcafb437..95fcafb437 100755..100644
--- a/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png
+++ b/src/plugins/styles/bb10style/dark/progressbar/core_progressindicator_bg.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png
index fd61937d65..fd61937d65 100755..100644
--- a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png
+++ b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_inactive.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png
index 58a1a57b4c..58a1a57b4c 100755..100644
--- a/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png
+++ b/src/plugins/styles/bb10style/dark/radiobutton/core_radiobutton_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png b/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png
index 384f60758a..384f60758a 100755..100644
--- a/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png
+++ b/src/plugins/styles/bb10style/dark/scrollbar/core_scrollbar.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png b/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png
index 803c374015..803c374015 100755..100644
--- a/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png
+++ b/src/plugins/styles/bb10style/dark/slider/core_slider_handle_pressed.png
Binary files differ
diff --git a/src/plugins/styles/bb10style/qpixmapstyle.cpp b/src/plugins/styles/bb10style/qpixmapstyle.cpp
index 759f57eb1c..3090c42959 100644
--- a/src/plugins/styles/bb10style/qpixmapstyle.cpp
+++ b/src/plugins/styles/bb10style/qpixmapstyle.cpp
@@ -616,9 +616,9 @@ void QPixmapStyle::drawProgressBarBackground(const QStyleOption *option,
QPainter *painter, const QWidget *) const
{
bool vertical = false;
- if (const QStyleOptionProgressBarV2 *pb2 =
- qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
- vertical = (pb2->orientation == Qt::Vertical);
+ if (const QStyleOptionProgressBar *pb =
+ qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
+ vertical = pb->orientation == Qt::Vertical;
}
drawCachedPixmap(vertical ? PB_VBackground : PB_HBackground, option->rect, painter);
}
@@ -628,11 +628,7 @@ void QPixmapStyle::drawProgressBarLabel(const QStyleOption *option,
{
if (const QStyleOptionProgressBar *pb =
qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
- bool vertical = false;
- if (const QStyleOptionProgressBarV2 *pb2 =
- qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
- vertical = (pb2->orientation == Qt::Vertical);
- }
+ const bool vertical = pb->orientation == Qt::Vertical;
if (!vertical) {
QPalette::ColorRole textRole = QPalette::ButtonText;
proxy()->drawItemText(painter, pb->rect,
@@ -647,13 +643,8 @@ void QPixmapStyle::drawProgressBarFill(const QStyleOption *option,
{
const QStyleOptionProgressBar *pbar =
qstyleoption_cast<const QStyleOptionProgressBar*>(option);
- bool vertical = false;
- bool flip = pbar->direction == Qt::RightToLeft;
- if (const QStyleOptionProgressBarV2 *pb2 =
- qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
- vertical = (pb2->orientation == Qt::Vertical);
- flip = flip ^ pb2->invertedAppearance;
- }
+ const bool vertical = pbar->orientation == Qt::Vertical;
+ const bool flip = (pbar->direction == Qt::RightToLeft) ^ pbar->invertedAppearance;
if (pbar->progress == pbar->maximum) {
drawCachedPixmap(vertical ? PB_VComplete : PB_HComplete, option->rect, painter);
@@ -801,9 +792,9 @@ QSize QPixmapStyle::progressBarSizeFromContents(const QStyleOption *option,
const QWidget *widget) const
{
bool vertical = false;
- if (const QStyleOptionProgressBarV2 *pb2 =
- qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
- vertical = (pb2->orientation == Qt::Vertical);
+ if (const QStyleOptionProgressBar *pb =
+ qstyleoption_cast<const QStyleOptionProgressBar *>(option)) {
+ vertical = pb->orientation == Qt::Vertical;
}
QSize result = QCommonStyle::sizeFromContents(CT_Slider, option, contentsSize, widget);
if (vertical) {