summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/accessible/accessible.pri2
-rw-r--r--src/gui/accessible/qaccessible.cpp17
-rw-r--r--src/gui/accessible/qaccessible_mac.mm2
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp2
-rw-r--r--src/gui/accessible/qaccessiblewidget.cpp2
-rw-r--r--src/gui/dialogs/dialogs.pri4
-rw-r--r--src/gui/dialogs/qcolordialog_mac.mm4
-rw-r--r--src/gui/dialogs/qdialog.cpp6
-rw-r--r--src/gui/dialogs/qfiledialog.cpp7
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm9
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp3
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h3
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp12
-rw-r--r--src/gui/dialogs/qfilesystemmodel.h4
-rw-r--r--src/gui/dialogs/qfontdialog_mac.mm7
-rw-r--r--src/gui/dialogs/qinputdialog.cpp32
-rw-r--r--src/gui/dialogs/qinputdialog.h25
-rw-r--r--src/gui/dialogs/qmessagebox.cpp8
-rw-r--r--src/gui/dialogs/qnspanelproxy_mac.mm87
-rw-r--r--src/gui/dialogs/qpagesetupdialog_mac.mm4
-rw-r--r--src/gui/egl/egl.pri28
-rw-r--r--src/gui/egl/qegl.cpp2
-rw-r--r--src/gui/egl/qegl_qpa.cpp111
-rw-r--r--src/gui/embedded/qkbd_defaultmap_qws_p.h7
-rw-r--r--src/gui/embedded/qkbd_qws.cpp22
-rw-r--r--src/gui/graphicsview/qgraphicsgridlayout.cpp12
-rw-r--r--src/gui/graphicsview/qgraphicsgridlayout.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp48
-rw-r--r--src/gui/graphicsview/qgraphicsitemanimation.cpp22
-rw-r--r--src/gui/graphicsview/qgraphicslayout.cpp8
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.cpp12
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.h8
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.cpp7
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp41
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp12
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h34
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp38
-rw-r--r--src/gui/graphicsview/qgridlayoutengine.cpp9
-rw-r--r--src/gui/graphicsview/qgridlayoutengine_p.h1
-rw-r--r--src/gui/gui.pro4
-rw-r--r--src/gui/image/image.pri5
-rw-r--r--src/gui/image/qbitmap.cpp8
-rw-r--r--src/gui/image/qbitmap.h1
-rw-r--r--src/gui/image/qicon.cpp8
-rw-r--r--src/gui/image/qicon.h6
-rw-r--r--src/gui/image/qimage.cpp152
-rw-r--r--src/gui/image/qimage.h10
-rw-r--r--src/gui/image/qimage_p.h37
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qmnghandler.cpp2
-rw-r--r--src/gui/image/qmovie.cpp6
-rw-r--r--src/gui/image/qnativeimage.cpp22
-rw-r--r--src/gui/image/qpicture.cpp8
-rw-r--r--src/gui/image/qpicture.h5
-rw-r--r--src/gui/image/qpixmap.cpp17
-rw-r--r--src/gui/image/qpixmap.h6
-rw-r--r--src/gui/image/qpixmap_blitter.cpp311
-rw-r--r--src/gui/image/qpixmap_blitter_p.h166
-rw-r--r--src/gui/image/qpixmap_mac.cpp6
-rw-r--r--src/gui/image/qpixmap_qpa.cpp49
-rw-r--r--src/gui/image/qpixmap_raster.cpp8
-rw-r--r--src/gui/image/qpixmap_x11.cpp12
-rw-r--r--src/gui/image/qpixmapdata_p.h3
-rw-r--r--src/gui/image/qpixmapdatafactory.cpp7
-rw-r--r--src/gui/image/qpnghandler.cpp83
-rw-r--r--src/gui/image/qtiffhandler.cpp7
-rw-r--r--src/gui/image/qxpmhandler.cpp32
-rw-r--r--src/gui/inputmethod/inputmethod.pri2
-rw-r--r--src/gui/itemviews/qabstractitemdelegate.cpp4
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp188
-rw-r--r--src/gui/itemviews/qabstractitemview.h1
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h42
-rw-r--r--src/gui/itemviews/qabstractproxymodel.cpp120
-rw-r--r--src/gui/itemviews/qabstractproxymodel.h15
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp2
-rw-r--r--src/gui/itemviews/qheaderview.cpp8
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp10
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp21
-rw-r--r--src/gui/itemviews/qitemselectionmodel.h24
-rw-r--r--src/gui/itemviews/qlistview.cpp126
-rw-r--r--src/gui/itemviews/qlistview_p.h9
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp2
-rw-r--r--src/gui/itemviews/qstringlistmodel.cpp3
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp9
-rw-r--r--src/gui/itemviews/qtableview.cpp13
-rw-r--r--src/gui/itemviews/qtreeview.cpp37
-rw-r--r--src/gui/kernel/kernel.pri72
-rw-r--r--src/gui/kernel/mac.pri2
-rw-r--r--src/gui/kernel/qapplication.cpp83
-rw-r--r--src/gui/kernel/qapplication.h12
-rw-r--r--src/gui/kernel/qapplication_mac.mm33
-rw-r--r--src/gui/kernel/qapplication_p.h58
-rw-r--r--src/gui/kernel/qapplication_qpa.cpp928
-rw-r--r--src/gui/kernel/qapplication_s60.cpp7
-rw-r--r--src/gui/kernel/qapplication_win.cpp78
-rw-r--r--src/gui/kernel/qapplication_x11.cpp34
-rw-r--r--src/gui/kernel/qclipboard.cpp2
-rw-r--r--src/gui/kernel/qclipboard_qpa.cpp163
-rw-r--r--src/gui/kernel/qcocoaapplication_mac.mm87
-rw-r--r--src/gui/kernel/qcocoaapplication_mac_p.h8
-rw-r--r--src/gui/kernel/qcocoaapplicationdelegate_mac.mm5
-rw-r--r--src/gui/kernel/qcocoaintrospection_mac.mm125
-rw-r--r--src/gui/kernel/qcocoaintrospection_p.h84
-rw-r--r--src/gui/kernel/qcocoamenuloader_mac.mm12
-rw-r--r--src/gui/kernel/qcocoasharedwindowmethods_mac_p.h21
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm80
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h1
-rw-r--r--src/gui/kernel/qcocoawindow_mac.mm2
-rw-r--r--src/gui/kernel/qcocoawindowdelegate_mac.mm2
-rw-r--r--src/gui/kernel/qcursor.h6
-rw-r--r--src/gui/kernel/qcursor_p.h2
-rw-r--r--src/gui/kernel/qcursor_qpa.cpp127
-rw-r--r--src/gui/kernel/qdesktopwidget_qpa.cpp180
-rw-r--r--src/gui/kernel/qdesktopwidget_qpa_p.h76
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp14
-rw-r--r--src/gui/kernel/qdnd_p.h4
-rw-r--r--src/gui/kernel/qevent.cpp221
-rw-r--r--src/gui/kernel/qevent.h46
-rw-r--r--src/gui/kernel/qevent_p.h28
-rw-r--r--src/gui/kernel/qeventdispatcher_glib_qpa.cpp147
-rw-r--r--src/gui/kernel/qeventdispatcher_glib_qpa_p.h88
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm5
-rw-r--r--src/gui/kernel/qeventdispatcher_qpa.cpp335
-rw-r--r--src/gui/kernel/qeventdispatcher_qpa_p.h86
-rw-r--r--src/gui/kernel/qgenericplugin_qpa.cpp112
-rw-r--r--src/gui/kernel/qgenericplugin_qpa.h84
-rw-r--r--src/gui/kernel/qgenericpluginfactory_qpa.cpp115
-rw-r--r--src/gui/kernel/qgenericpluginfactory_qpa.h67
-rw-r--r--src/gui/kernel/qgesturemanager.cpp41
-rw-r--r--src/gui/kernel/qguifunctions_wince.cpp5
-rw-r--r--src/gui/kernel/qguiplatformplugin.cpp2
-rw-r--r--src/gui/kernel/qkeysequence.cpp15
-rw-r--r--src/gui/kernel/qkeysequence.h5
-rw-r--r--src/gui/kernel/qlayoutitem.cpp4
-rw-r--r--src/gui/kernel/qmacdefines_mac.h12
-rw-r--r--src/gui/kernel/qpalette.h8
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.cpp660
-rw-r--r--src/gui/kernel/qplatformcursor_qpa.h103
-rw-r--r--src/gui/kernel/qplatformeventloopintegration_qpa.cpp86
-rw-r--r--src/gui/kernel/qplatformeventloopintegration_qpa.h82
-rw-r--r--src/gui/kernel/qplatformglcontext_qpa.cpp227
-rw-r--r--src/gui/kernel/qplatformglcontext_qpa.h94
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.cpp196
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.h97
-rw-r--r--src/gui/kernel/qplatformintegrationfactory_qpa.cpp88
-rw-r--r--src/gui/kernel/qplatformintegrationfactory_qpa_p.h78
-rw-r--r--src/gui/kernel/qplatformintegrationplugin_qpa.cpp55
-rw-r--r--src/gui/kernel/qplatformintegrationplugin_qpa.h92
-rw-r--r--src/gui/kernel/qplatformscreen_qpa.cpp114
-rw-r--r--src/gui/kernel/qplatformscreen_qpa.h82
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp210
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.h94
-rw-r--r--src/gui/kernel/qplatformwindowformat_qpa.cpp1019
-rw-r--r--src/gui/kernel/qplatformwindowformat_qpa.h243
-rw-r--r--src/gui/kernel/qsizepolicy.h21
-rw-r--r--src/gui/kernel/qsizepolicy.qdoc24
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm238
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac_p.h14
-rw-r--r--src/gui/kernel/qt_x11_p.h2
-rw-r--r--src/gui/kernel/qtooltip.cpp2
-rw-r--r--src/gui/kernel/qwidget.cpp92
-rw-r--r--src/gui/kernel/qwidget.h27
-rw-r--r--src/gui/kernel/qwidget_mac.mm45
-rw-r--r--src/gui/kernel/qwidget_p.h22
-rw-r--r--src/gui/kernel/qwidget_qpa.cpp909
-rw-r--r--src/gui/kernel/qwidget_s60.cpp8
-rw-r--r--src/gui/kernel/qwidget_win.cpp28
-rw-r--r--src/gui/kernel/qwidget_x11.cpp11
-rw-r--r--src/gui/kernel/qwindowdefs.h6
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa.cpp255
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa.h95
-rw-r--r--src/gui/kernel/qwindowsysteminterface_qpa_p.h189
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp12
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp14
-rw-r--r--src/gui/math3d/qmatrix4x4.h16
-rw-r--r--src/gui/painting/painting.pri38
-rw-r--r--src/gui/painting/qbackingstore.cpp51
-rw-r--r--src/gui/painting/qblendfunctions.cpp4
-rw-r--r--src/gui/painting/qblittable.cpp105
-rw-r--r--src/gui/painting/qblittable_p.h91
-rw-r--r--src/gui/painting/qbrush.cpp9
-rw-r--r--src/gui/painting/qbrush.h6
-rw-r--r--src/gui/painting/qcolor_p.cpp36
-rw-r--r--src/gui/painting/qcolormap_qpa.cpp231
-rw-r--r--src/gui/painting/qgraphicssystem.cpp7
-rw-r--r--src/gui/painting/qgraphicssystem_p.h6
-rw-r--r--src/gui/painting/qgraphicssystemfactory.cpp2
-rw-r--r--src/gui/painting/qgrayraster.c35
-rw-r--r--src/gui/painting/qgrayraster_p.h2
-rw-r--r--src/gui/painting/qoutlinemapper.cpp9
-rw-r--r--src/gui/painting/qoutlinemapper_p.h8
-rw-r--r--src/gui/painting/qpaintbuffer.cpp44
-rw-r--r--src/gui/painting/qpaintdevice.cpp2
-rw-r--r--src/gui/painting/qpaintdevice_qpa.cpp68
-rw-r--r--src/gui/painting/qpaintengine.h4
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp663
-rw-r--r--src/gui/painting/qpaintengine_blitter_p.h113
-rw-r--r--src/gui/painting/qpaintengine_mac.cpp5
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp203
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h3
-rw-r--r--src/gui/painting/qpainter.cpp187
-rw-r--r--src/gui/painting/qpainter.h5
-rw-r--r--src/gui/painting/qpainter_p.h3
-rw-r--r--src/gui/painting/qpainterpath.cpp8
-rw-r--r--src/gui/painting/qpainterpath.h5
-rw-r--r--src/gui/painting/qpdf.cpp3
-rw-r--r--src/gui/painting/qpen.cpp8
-rw-r--r--src/gui/painting/qpen.h5
-rw-r--r--src/gui/painting/qpolygon.cpp16
-rw-r--r--src/gui/painting/qpolygon.h3
-rw-r--r--src/gui/painting/qprinterinfo.cpp (renamed from src/gui/painting/qprinterinfo.qdoc)82
-rw-r--r--src/gui/painting/qprinterinfo.h15
-rw-r--r--src/gui/painting/qprinterinfo_mac.cpp185
-rw-r--r--src/gui/painting/qprinterinfo_p.h107
-rw-r--r--src/gui/painting/qprinterinfo_unix.cpp411
-rw-r--r--src/gui/painting/qprinterinfo_win.cpp193
-rw-r--r--src/gui/painting/qrasterizer.cpp4
-rw-r--r--src/gui/painting/qregion.cpp12
-rw-r--r--src/gui/painting/qregion.h12
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp185
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h49
-rw-r--r--src/gui/painting/qunifiedtoolbarsurface_mac.cpp259
-rw-r--r--src/gui/painting/qunifiedtoolbarsurface_mac_p.h100
-rw-r--r--src/gui/painting/qwindowsurface.cpp39
-rw-r--r--src/gui/painting/qwindowsurface_mac.cpp2
-rw-r--r--src/gui/painting/qwindowsurface_p.h9
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp68
-rw-r--r--src/gui/painting/qwindowsurface_raster_p.h2
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp3
-rw-r--r--src/gui/painting/qwindowsurface_x11.cpp2
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp1
-rw-r--r--src/gui/styles/qcommonstyle.cpp2
-rw-r--r--src/gui/styles/qgtkstyle.cpp48
-rw-r--r--src/gui/styles/qgtkstyle_p.cpp8
-rw-r--r--src/gui/styles/qgtkstyle_p.h8
-rw-r--r--src/gui/styles/qmacstyle_mac.mm68
-rw-r--r--src/gui/styles/qplastiquestyle.cpp7
-rw-r--r--src/gui/styles/qs60style.cpp2
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp162
-rw-r--r--src/gui/styles/qstylesheetstyle_p.h20
-rw-r--r--src/gui/styles/qwindowscestyle.cpp1
-rw-r--r--src/gui/styles/qwindowsstyle.cpp6
-rw-r--r--src/gui/styles/qwindowsvistastyle.cpp16
-rw-r--r--src/gui/styles/qwindowsxpstyle.cpp2
-rw-r--r--src/gui/styles/styles.pri2
-rw-r--r--src/gui/symbian/qsymbianevent.cpp33
-rw-r--r--src/gui/symbian/qsymbianevent.h4
-rw-r--r--src/gui/text/qcssparser.cpp47
-rw-r--r--src/gui/text/qcssparser_p.h3
-rw-r--r--src/gui/text/qfont.cpp26
-rw-r--r--src/gui/text/qfont.h6
-rw-r--r--src/gui/text/qfont_mac.cpp1
-rw-r--r--src/gui/text/qfont_p.h5
-rw-r--r--src/gui/text/qfont_qpa.cpp114
-rw-r--r--src/gui/text/qfontdatabase.cpp76
-rw-r--r--src/gui/text/qfontdatabase.h3
-rw-r--r--src/gui/text/qfontdatabase_mac.cpp120
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp390
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp10
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp30
-rw-r--r--src/gui/text/qfontengine.cpp57
-rw-r--r--src/gui/text/qfontengine_coretext.mm733
-rw-r--r--src/gui/text/qfontengine_coretext_p.h136
-rw-r--r--src/gui/text/qfontengine_ft.cpp47
-rw-r--r--src/gui/text/qfontengine_ft_p.h27
-rw-r--r--src/gui/text/qfontengine_mac.mm702
-rw-r--r--src/gui/text/qfontengine_mac_p.h167
-rw-r--r--src/gui/text/qfontengine_p.h237
-rw-r--r--src/gui/text/qfontengine_qpa.cpp691
-rw-r--r--src/gui/text/qfontengine_qpa_p.h262
-rw-r--r--src/gui/text/qfontengine_s60.cpp7
-rw-r--r--src/gui/text/qfontengine_win.cpp2
-rw-r--r--src/gui/text/qfontengine_win_p.h2
-rw-r--r--src/gui/text/qfontengine_x11.cpp2
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h2
-rw-r--r--src/gui/text/qfontmetrics.cpp32
-rw-r--r--src/gui/text/qfontmetrics.h11
-rw-r--r--src/gui/text/qglyphs.cpp240
-rw-r--r--src/gui/text/qglyphs.h96
-rw-r--r--src/gui/text/qglyphs_p.h84
-rw-r--r--src/gui/text/qpfutil.cpp2
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp290
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.h108
-rw-r--r--src/gui/text/qtextcontrol.cpp5
-rw-r--r--src/gui/text/qtextcursor.h1
-rw-r--r--src/gui/text/qtextdocument.cpp36
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp4
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp38
-rw-r--r--src/gui/text/qtextengine.cpp89
-rw-r--r--src/gui/text/qtextengine_mac.cpp3
-rw-r--r--src/gui/text/qtextengine_p.h23
-rw-r--r--src/gui/text/qtextformat.cpp111
-rw-r--r--src/gui/text/qtextformat.h51
-rw-r--r--src/gui/text/qtexthtmlparser.cpp20
-rw-r--r--src/gui/text/qtexthtmlparser_p.h2
-rw-r--r--src/gui/text/qtextlayout.cpp464
-rw-r--r--src/gui/text/qtextlayout.h6
-rw-r--r--src/gui/text/qtextlist.cpp14
-rw-r--r--src/gui/text/qtextobject.cpp29
-rw-r--r--src/gui/text/qtextobject.h3
-rw-r--r--src/gui/text/qtextodfwriter.cpp10
-rw-r--r--src/gui/text/text.pri36
-rw-r--r--src/gui/util/qcompleter.cpp2
-rw-r--r--src/gui/util/qdesktopservices.cpp2
-rw-r--r--src/gui/util/qdesktopservices_mac.cpp2
-rw-r--r--src/gui/util/qflickgesture.cpp677
-rw-r--r--src/gui/util/qflickgesture_p.h113
-rw-r--r--src/gui/util/qscroller.cpp1999
-rw-r--r--src/gui/util/qscroller.h149
-rw-r--r--src/gui/util/qscroller_mac.mm69
-rw-r--r--src/gui/util/qscroller_p.h205
-rw-r--r--src/gui/util/qscrollerproperties.cpp397
-rw-r--r--src/gui/util/qscrollerproperties.h140
-rw-r--r--src/gui/util/qscrollerproperties_p.h94
-rw-r--r--src/gui/util/util.pri18
-rw-r--r--src/gui/widgets/qabstractbutton.cpp2
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp105
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h2
-rw-r--r--src/gui/widgets/qabstractslider_p.h2
-rw-r--r--src/gui/widgets/qcheckbox.cpp9
-rw-r--r--src/gui/widgets/qcheckbox.h1
-rw-r--r--src/gui/widgets/qcocoamenu_mac.mm29
-rw-r--r--src/gui/widgets/qcombobox.cpp22
-rw-r--r--src/gui/widgets/qcombobox.h2
-rw-r--r--src/gui/widgets/qcombobox_p.h2
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp15
-rw-r--r--src/gui/widgets/qdial.cpp15
-rw-r--r--src/gui/widgets/qdialogbuttonbox.cpp2
-rw-r--r--src/gui/widgets/qlabel.cpp2
-rw-r--r--src/gui/widgets/qlinecontrol.cpp4
-rw-r--r--src/gui/widgets/qlineedit.h1
-rw-r--r--src/gui/widgets/qlineedit_p.cpp23
-rw-r--r--src/gui/widgets/qlineedit_p.h3
-rw-r--r--src/gui/widgets/qmainwindow.cpp17
-rw-r--r--src/gui/widgets/qmainwindowlayout_mac.mm31
-rw-r--r--src/gui/widgets/qmainwindowlayout_p.h14
-rw-r--r--src/gui/widgets/qmdisubwindow.cpp4
-rw-r--r--src/gui/widgets/qmenu.cpp2
-rw-r--r--src/gui/widgets/qmenu.h4
-rw-r--r--src/gui/widgets/qmenu_mac.mm17
-rw-r--r--src/gui/widgets/qmenu_symbian.cpp3
-rw-r--r--src/gui/widgets/qmenu_wince.cpp2
-rw-r--r--src/gui/widgets/qradiobutton.cpp8
-rw-r--r--src/gui/widgets/qradiobutton.h1
-rw-r--r--src/gui/widgets/qsizegrip.cpp17
-rw-r--r--src/gui/widgets/qspinbox.cpp3
-rw-r--r--src/gui/widgets/qsplashscreen.cpp54
-rw-r--r--src/gui/widgets/qstackedwidget.cpp46
-rw-r--r--src/gui/widgets/qtabbar.cpp13
-rw-r--r--src/gui/widgets/qtabwidget.cpp62
-rw-r--r--src/gui/widgets/qtabwidget.h1
-rw-r--r--src/gui/widgets/qtoolbutton.cpp3
-rw-r--r--src/gui/widgets/qvalidator.h6
-rw-r--r--src/gui/widgets/qworkspace.cpp2
-rw-r--r--src/gui/widgets/widgets.pri2
358 files changed, 22467 insertions, 3459 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri
index ad2fb4c828..31362ffded 100644
--- a/src/gui/accessible/accessible.pri
+++ b/src/gui/accessible/accessible.pri
@@ -12,7 +12,7 @@ contains(QT_CONFIG, accessibility) {
accessible/qaccessiblewidget.cpp \
accessible/qaccessibleplugin.cpp
- mac:!embedded {
+ mac:!embedded:!qpa {
HEADERS += accessible/qaccessible_mac_p.h
OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \
accessible/qaccessible_mac_cocoa.mm
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 4f0053ff6b..abe68f8108 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -409,13 +409,18 @@ static void qAccessibleCleanup()
/*!
\typedef QAccessible::InterfaceFactory
- A function pointer type. Use a function with this prototype to install
- interface factories with installFactory().
+ This is a typedef for a pointer to a function with the following
+ signature:
- The function receives a QObject pointer. If the QObject
- provides a QAccessibleInterface, it sets the second parameter to
- point to the corresponding QAccessibleInterface, and returns true;
- otherwise returns false.
+ \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 1
+
+ The function receives a QString and a QObject pointer, where the
+ QString is the key identifying the interface. The QObject is used
+ to pass on to the QAccessibleInterface so that it can hold a reference
+ to it.
+
+ If the key and the QObject does not have a corresponding
+ QAccessibleInterface, a null-pointer will be returned.
Installed factories are called by queryAccessibilityInterface() until
one provides an interface.
diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm
index cc6ce4b389..d01c1c9733 100644
--- a/src/gui/accessible/qaccessible_mac.mm
+++ b/src/gui/accessible/qaccessible_mac.mm
@@ -774,7 +774,7 @@ QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
return factory->interface(id);
#else
return QAInterface();
-#endif;
+#endif
}
QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index d6ceabc556..1d2d1da806 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -276,7 +276,7 @@ QAccessible::Relation QAccessibleApplication::relationTo(int child, const
for (int i = 0; i < tlw.count(); ++i) {
QWidget *w = tlw.at(i);
- QObjectList cl = qFindChildren<QObject *>(w, QString());
+ QObjectList cl = w->findChildren<QObject *>(QString());
if (cl.contains(o))
return Ancestor;
}
diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp
index c31ce44493..2b2cec0f02 100644
--- a/src/gui/accessible/qaccessiblewidget.cpp
+++ b/src/gui/accessible/qaccessiblewidget.cpp
@@ -1015,7 +1015,7 @@ QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVa
case ListSupportedMethods: {
QSet<QAccessible::Method> set;
set << ListSupportedMethods << ForegroundColor << BackgroundColor;
- return qVariantFromValue(set);
+ return QVariant::fromValue(set);
}
case ForegroundColor:
return widget()->palette().color(widget()->foregroundRole());
diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri
index 12e3a711c8..6ba707c9d3 100644
--- a/src/gui/dialogs/dialogs.pri
+++ b/src/gui/dialogs/dialogs.pri
@@ -27,7 +27,7 @@ HEADERS += \
dialogs/qwizard.h \
dialogs/qprintpreviewdialog.h
-!embedded:mac {
+!embedded:!qpa:mac {
OBJECTIVE_SOURCES += dialogs/qfiledialog_mac.mm \
dialogs/qfontdialog_mac.mm \
dialogs/qnspanelproxy_mac.mm \
@@ -61,7 +61,7 @@ win32 {
!win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library
}
-!mac:!embedded:!symbian:unix {
+!mac:!embedded:!symbian:unix|qpa {
HEADERS += dialogs/qpagesetupdialog_unix_p.h
SOURCES += dialogs/qprintdialog_unix.cpp \
dialogs/qpagesetupdialog_unix.cpp
diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm
index a9c70d3c21..ee9b19ad99 100644
--- a/src/gui/dialogs/qcolordialog_mac.mm
+++ b/src/gui/dialogs/qcolordialog_mac.mm
@@ -185,7 +185,7 @@ QT_USE_NAMESPACE
[self relayout];
}
-- (void)colorChanged:(NSNotification *)notification;
+- (void)colorChanged:(NSNotification *)notification
{
Q_UNUSED(notification);
[self updateQtColor];
@@ -439,7 +439,7 @@ void QColorDialogPrivate::openCocoaColorPanel(const QColor &initial,
priv:this];
[colorPanel setDelegate:static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate)];
}
- [delegate setResultSet:false];
+ [static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) setResultSet:NO];
setCocoaPanelColor(initial);
[static_cast<QT_MANGLE_NAMESPACE(QCocoaColorPanelDelegate) *>(delegate) showColorPanel];
}
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index e44c38c0f6..6838d927a8 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -337,7 +337,7 @@ void QDialogPrivate::setDefault(QPushButton *pushButton)
{
Q_Q(QDialog);
bool hasMain = false;
- QList<QPushButton*> list = qFindChildren<QPushButton*>(q);
+ QList<QPushButton*> list = q->findChildren<QPushButton*>();
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
if (pb->window() == q) {
@@ -372,7 +372,7 @@ void QDialogPrivate::setMainDefault(QPushButton *pushButton)
void QDialogPrivate::hideDefault()
{
Q_Q(QDialog);
- QList<QPushButton*> list = qFindChildren<QPushButton*>(q);
+ QList<QPushButton*> list = q->findChildren<QPushButton*>();
for (int i=0; i<list.size(); ++i) {
list.at(i)->setDefault(false);
}
@@ -675,7 +675,7 @@ void QDialog::keyPressEvent(QKeyEvent *e)
switch (e->key()) {
case Qt::Key_Enter:
case Qt::Key_Return: {
- QList<QPushButton*> list = qFindChildren<QPushButton*>(this);
+ QList<QPushButton*> list = findChildren<QPushButton*>();
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
if (pb->isDefault() && pb->isVisible()) {
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 5ff8d1ee5e..e81773b177 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -2258,9 +2258,9 @@ void QFileDialogPrivate::createWidgets()
#ifndef QT_NO_FSCOMPLETER
completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
+#endif // QT_NO_FSCOMPLETER
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
-#endif // QT_NO_FSCOMPLETER
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_updateOkButton()));
@@ -3311,7 +3311,10 @@ QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
if (currentLocation == QDir::separator())
return path.mid(currentLocation.length());
#endif
- return path.mid(currentLocation.length() + 1);
+ if (currentLocation.endsWith(QLatin1Char('/')))
+ return path.mid(currentLocation.length());
+ else
+ return path.mid(currentLocation.length()+1);
}
return index.data(QFileSystemModel::FilePathRole).toString();
}
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index cc53858fa1..832f9bfaf8 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -63,6 +63,7 @@
#include <qdesktopwidget.h>
#include <stdlib.h>
#include <qabstracteventdispatcher.h>
+#import <AppKit/NSSavePanel.h>
#include "ui_qfiledialog.h"
QT_BEGIN_NAMESPACE
@@ -84,7 +85,13 @@ QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate);
-@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) : NSObject {
+@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ : NSObject<NSOpenSavePanelDelegate>
+#else
+ : NSObject
+#endif
+{
@public
NSOpenPanel *mOpenPanel;
NSSavePanel *mSavePanel;
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index 9b68adb595..114f4bedbc 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -60,7 +60,6 @@
#endif
#ifdef Q_WS_WINCE
-#include <shlobj.h>
#include <commdlg.h>
bool qt_priv_ptr_valid = false;
#else
@@ -603,7 +602,7 @@ QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args)
// Set the FOS_PICKFOLDERS flag
DWORD newOptions;
hr = pfd->GetOptions(&newOptions);
- newOptions |= FOS_PICKFOLDERS;
+ newOptions |= (FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) {
QWidget *parentWindow = args.parent;
if (parentWindow)
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index 3fb4d90599..db308ef57e 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -84,10 +84,13 @@ public:
&& permissions() == fileInfo.permissions();
}
+#ifndef QT_NO_FSFILEENGINE
bool isCaseSensitive() const {
QFSFileEngine fe(mFileInfo.absoluteFilePath());
return fe.caseSensitive();
}
+#endif
+
QFile::Permissions permissions() const {
return mFileInfo.permissions();
}
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 8bd7fe3a9b..dd27aff409 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -1313,6 +1313,10 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const
if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/'))
fullPath = fullPath.mid(1);
#endif
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':')))
+ fullPath.append(QLatin1Char('/'));
+#endif
return fullPath;
}
@@ -1631,6 +1635,14 @@ bool QFileSystemModel::event(QEvent *event)
return QAbstractItemModel::event(event);
}
+bool QFileSystemModel::rmdir(const QModelIndex &aindex) const
+{
+ QString path = filePath(aindex);
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ return QDir().rmdir(path);
+}
+
/*!
\internal
diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h
index fe8cf4d1c0..8aa9875d13 100644
--- a/src/gui/dialogs/qfilesystemmodel.h
+++ b/src/gui/dialogs/qfilesystemmodel.h
@@ -139,7 +139,7 @@ public:
QDateTime lastModified(const QModelIndex &index) const;
QModelIndex mkdir(const QModelIndex &parent, const QString &name);
- inline bool rmdir(const QModelIndex &index) const;
+ bool rmdir(const QModelIndex &index) const; // ### Qt5: should not be const
inline QString fileName(const QModelIndex &index) const;
inline QIcon fileIcon(const QModelIndex &index) const;
QFile::Permissions permissions(const QModelIndex &index) const;
@@ -163,8 +163,6 @@ private:
friend class QFileDialogPrivate;
};
-inline bool QFileSystemModel::rmdir(const QModelIndex &aindex) const
-{ QDir dir; return dir.rmdir(filePath(aindex)); }
inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const
{ return aindex.data(Qt::DisplayRole).toString(); }
inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const
diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm
index 87187fc8ae..1552ad675f 100644
--- a/src/gui/dialogs/qfontdialog_mac.mm
+++ b/src/gui/dialogs/qfontdialog_mac.mm
@@ -51,6 +51,7 @@
#include <private/qt_mac_p.h>
#include <qabstracteventdispatcher.h>
#include <qdebug.h>
+#include <private/qfontengine_coretext_p.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@@ -346,7 +347,7 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
[self relayoutToContentSize:[[mStolenContentView superview] frame].size];
}
-- (void)relayoutToContentSize:(NSSize)frameSize;
+- (void)relayoutToContentSize:(NSSize)frameSize
{
Q_ASSERT(mPanelHackedWithButtons);
@@ -505,7 +506,7 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
QMacCocoaAutoReleasePool pool;
QFontEngine *fe = font.d->engineForScript(QUnicodeTables::Common);
NSFontManager *mgr = [NSFontManager sharedFontManager];
- NSFont *nsFont = 0;
+ const NSFont *nsFont = 0;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
if (qstrcmp(fe->name(), "CoreText") == 0) {
@@ -531,7 +532,7 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font)
size:fontInfo.pointSize()];
}
- [mgr setSelectedFont:nsFont isMultiple:NO];
+ [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO];
[static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate) setQtFont:font];
}
diff --git a/src/gui/dialogs/qinputdialog.cpp b/src/gui/dialogs/qinputdialog.cpp
index 1947a08463..f13b8f55c3 100644
--- a/src/gui/dialogs/qinputdialog.cpp
+++ b/src/gui/dialogs/qinputdialog.cpp
@@ -1136,6 +1136,8 @@ void QInputDialog::done(int result)
be entered).
\a text is the default text which is placed in the line edit.
\a mode is the echo mode the line edit will use.
+ \a inputMethodHints is the input method hints that will be used in the
+ edit widget if an input method is active.
If \a ok is nonnull \e *\a ok will be set to true if the user pressed
\gui OK and to false if the user pressed \gui Cancel. The dialog's parent
@@ -1158,13 +1160,14 @@ void QInputDialog::done(int result)
QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
QLineEdit::EchoMode mode, const QString &text, bool *ok,
- Qt::WindowFlags flags)
+ Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
{
QInputDialog dialog(parent, flags);
dialog.setWindowTitle(title);
dialog.setLabelText(label);
dialog.setTextValue(text);
dialog.setTextEchoMode(mode);
+ dialog.setInputMethodHints(inputMethodHints);
int ret = dialog.exec();
if (ok)
@@ -1177,6 +1180,17 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri
}
/*!
+ \internal
+*/
+// ### Qt 5: Use only the version above.
+QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label,
+ QLineEdit::EchoMode mode, const QString &text, bool *ok,
+ Qt::WindowFlags flags)
+{
+ return getText(parent, title, label, mode, text, ok, flags, Qt::ImhNone);
+}
+
+/*!
\since 4.5
Static convenience function to get an integer input from the user.
@@ -1286,6 +1300,8 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
be entered).
\a items is the string list which is inserted into the combobox.
\a current is the number of the item which should be the current item.
+ \a inputMethodHints is the input method hints that will be used if the
+ combobox is editable and an input method is active.
If \a editable is true the user can enter their own text; otherwise the
user may only select one of the existing items.
@@ -1310,7 +1326,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
const QStringList &items, int current, bool editable, bool *ok,
- Qt::WindowFlags flags)
+ Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
{
QString text(items.value(current));
@@ -1320,6 +1336,7 @@ QString QInputDialog::getItem(QWidget *parent, const QString &title, const QStri
dialog.setComboBoxItems(items);
dialog.setTextValue(text);
dialog.setComboBoxEditable(editable);
+ dialog.setInputMethodHints(inputMethodHints);
int ret = dialog.exec();
if (ok)
@@ -1332,6 +1349,17 @@ QString QInputDialog::getItem(QWidget *parent, const QString &title, const QStri
}
/*!
+ \internal
+*/
+// ### Qt 5: Use only the version above.
+QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label,
+ const QStringList &items, int current, bool editable, bool *ok,
+ Qt::WindowFlags flags)
+{
+ return getItem(parent, title, label, items, current, editable, ok, flags, Qt::ImhNone);
+}
+
+/*!
\obsolete
Use getInt() instead.
diff --git a/src/gui/dialogs/qinputdialog.h b/src/gui/dialogs/qinputdialog.h
index f3fbda6b06..b0e6fbb216 100644
--- a/src/gui/dialogs/qinputdialog.h
+++ b/src/gui/dialogs/qinputdialog.h
@@ -167,18 +167,37 @@ public:
void setVisible(bool visible);
+#ifdef Q_QDOC
+ static QString getText(QWidget *parent, const QString &title, const QString &label,
+ QLineEdit::EchoMode echo = QLineEdit::Normal,
+ const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0,
+ Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
+ static QString getItem(QWidget *parent, const QString &title, const QString &label,
+ const QStringList &items, int current = 0, bool editable = true,
+ bool *ok = 0, Qt::WindowFlags flags = 0,
+ Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
+#else
static QString getText(QWidget *parent, const QString &title, const QString &label,
QLineEdit::EchoMode echo = QLineEdit::Normal,
const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0);
+ static QString getItem(QWidget *parent, const QString &title, const QString &label,
+ const QStringList &items, int current = 0, bool editable = true,
+ bool *ok = 0, Qt::WindowFlags flags = 0);
+ static QString getText(QWidget *parent, const QString &title, const QString &label,
+ QLineEdit::EchoMode echo,
+ const QString &text, bool *ok, Qt::WindowFlags flags,
+ Qt::InputMethodHints inputMethodHints);
+ static QString getItem(QWidget *parent, const QString &title, const QString &label,
+ const QStringList &items, int current, bool editable,
+ bool *ok, Qt::WindowFlags flags,
+ Qt::InputMethodHints inputMethodHints);
+#endif
static int getInt(QWidget *parent, const QString &title, const QString &label, int value = 0,
int minValue = -2147483647, int maxValue = 2147483647,
int step = 1, bool *ok = 0, Qt::WindowFlags flags = 0);
static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0,
double minValue = -2147483647, double maxValue = 2147483647,
int decimals = 1, bool *ok = 0, Qt::WindowFlags flags = 0);
- static QString getItem(QWidget *parent, const QString &title, const QString &label,
- const QStringList &items, int current = 0, bool editable = true,
- bool *ok = 0, Qt::WindowFlags flags = 0);
// obsolete
static int getInteger(QWidget *parent, const QString &title, const QString &label, int value = 0,
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index dd06445ff6..09bb56cd4b 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -412,7 +412,7 @@ void QMessageBoxPrivate::updateSize()
void QMessageBoxPrivate::hideSpecial()
{
Q_Q(QMessageBox);
- QList<QPushButton*> list = qFindChildren<QPushButton*>(q);
+ QList<QPushButton*> list = q->findChildren<QPushButton*>();
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
QString text = pb->text();
@@ -1264,7 +1264,7 @@ bool QMessageBox::event(QEvent *e)
(e->type() == QEvent::OkRequest)
? QApplication::translate("QMessageBox", "OK")
: QApplication::translate("QMessageBox", "Help");
- QList<QPushButton*> list = qFindChildren<QPushButton*>(this);
+ QList<QPushButton*> list = findChildren<QPushButton*>();
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
if (pb->text() == bName) {
@@ -1511,7 +1511,7 @@ static QMessageBox::StandardButton showNewMessageBox(QWidget *parent,
int(defaultButton), 0);
QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent);
- QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&msgBox);
+ QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>();
Q_ASSERT(buttonBox != 0);
uint mask = QMessageBox::FirstButton;
@@ -1925,7 +1925,7 @@ void QMessageBoxPrivate::retranslateStrings()
{
#ifndef QT_NO_TEXTEDIT
if (detailsButton)
- detailsButton->setLabel(detailsText->isHidden() ? HideLabel : ShowLabel);
+ detailsButton->setLabel(detailsText->isHidden() ? ShowLabel : HideLabel);
#endif
}
diff --git a/src/gui/dialogs/qnspanelproxy_mac.mm b/src/gui/dialogs/qnspanelproxy_mac.mm
index 3078888ba2..5c8ef24688 100644
--- a/src/gui/dialogs/qnspanelproxy_mac.mm
+++ b/src/gui/dialogs/qnspanelproxy_mac.mm
@@ -42,6 +42,7 @@
#include <qdialogbuttonbox.h>
#if defined(Q_WS_MAC)
#include <private/qt_mac_p.h>
+#include <private/qcocoaintrospection_p.h>
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <objc/objc-class.h>
@@ -137,46 +138,6 @@ QT_USE_NAMESPACE
QT_BEGIN_NAMESPACE
-void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class proxyClass)
-{
-#ifndef QT_MAC_USE_COCOA
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
-#endif
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- // The following code replaces the _implementation_ for the selector we want to hack
- // (originalSel) with the implementation found in proxyClass. Then it creates
- // a new 'backup' method inside baseClass containing the old, original,
- // implementation (fakeSel). You can let the proxy implementation of originalSel
- // call fakeSel if needed (similar approach to calling a super class implementation).
- // fakeSel must also be implemented in proxyClass, as the signature is used
- // as template for the method one we add into baseClass.
- // NB: You will typically never create any instances of proxyClass; we use it
- // only for stealing its contents and put it into baseClass.
- Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
- Method newMethod = class_getInstanceMethod(proxyClass, originalSel);
- Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel);
-
- IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod));
- class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod));
-#endif
- }
-}
-
-void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* proxyClass */)
-{
-#ifndef QT_MAC_USE_COCOA
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
-#endif
- {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
- Method fakeMethodInBaseClass = class_getInstanceMethod(baseClass, fakeSel);
- method_setImplementation(originalMethod, method_getImplementation(fakeMethodInBaseClass));
-#endif
- }
-}
-
/*
Intercept the NSColorPanel constructor if the shared
color panel doesn't exist yet. What's going on here is
@@ -188,12 +149,18 @@ void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* pr
*/
void macStartInterceptNSPanelCtor()
{
- macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:),
- @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:),
- [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
- macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:),
- @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:),
- [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
+ qt_cocoa_change_implementation(
+ [NSPanel class],
+ @selector(initWithContentRect:styleMask:backing:defer:),
+ [QT_MANGLE_NAMESPACE(QNSPanelProxy) class],
+ @selector(initWithContentRect:styleMask:backing:defer:),
+ @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:));
+ qt_cocoa_change_implementation(
+ [NSPanel class],
+ @selector(initWithContentRect:styleMask:backing:defer:screen:),
+ [QT_MANGLE_NAMESPACE(QNSPanelProxy) class],
+ @selector(initWithContentRect:styleMask:backing:defer:screen:),
+ @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:));
}
/*
@@ -201,12 +168,14 @@ void macStartInterceptNSPanelCtor()
*/
void macStopInterceptNSPanelCtor()
{
- macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:),
- @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:),
- [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
- macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:),
- @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:),
- [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]);
+ qt_cocoa_change_back_implementation(
+ [NSPanel class],
+ @selector(initWithContentRect:styleMask:backing:defer:screen:),
+ @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:));
+ qt_cocoa_change_back_implementation(
+ [NSPanel class],
+ @selector(initWithContentRect:styleMask:backing:defer:),
+ @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:));
}
/*
@@ -216,8 +185,12 @@ void macStopInterceptNSPanelCtor()
void macStartInterceptWindowTitle(QWidget *window)
{
currentWindow = window;
- macStartIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:),
- [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]);
+ qt_cocoa_change_implementation(
+ [NSWindow class],
+ @selector(setTitle:),
+ [QT_MANGLE_NAMESPACE(QNSWindowProxy) class],
+ @selector(setTitle:),
+ @selector(qt_fakeSetTitle:));
}
/*
@@ -226,8 +199,10 @@ void macStartInterceptWindowTitle(QWidget *window)
void macStopInterceptWindowTitle()
{
currentWindow = 0;
- macStopIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:),
- [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]);
+ qt_cocoa_change_back_implementation(
+ [NSWindow class],
+ @selector(setTitle:),
+ @selector(qt_fakeSetTitle:));
}
/*
diff --git a/src/gui/dialogs/qpagesetupdialog_mac.mm b/src/gui/dialogs/qpagesetupdialog_mac.mm
index 48a44a0348..fa3f47378f 100644
--- a/src/gui/dialogs/qpagesetupdialog_mac.mm
+++ b/src/gui/dialogs/qpagesetupdialog_mac.mm
@@ -61,7 +61,7 @@ QT_USE_NAMESPACE
@end
@implementation QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate)
-- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine;
+- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine
{
self = [super init];
if (self) {
@@ -312,4 +312,4 @@ int QPageSetupDialog::exec()
QT_END_NAMESPACE
-#endif QT_NO_PRINTDIALOG
+#endif /* QT_NO_PRINTDIALOG */
diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri
index c6c020d307..8e8664c679 100644
--- a/src/gui/egl/egl.pri
+++ b/src/gui/egl/egl.pri
@@ -6,9 +6,21 @@ contains(QT_CONFIG, egl): {
egl/qeglcontext_p.h \
egl/qeglproperties_p.h
- SOURCES += \
- egl/qegl.cpp \
- egl/qeglproperties.cpp
+ SOURCES += \
+ egl/qegl.cpp \
+ egl/qeglproperties.cpp
+ unix {
+ !isEmpty(QMAKE_INCDIR_EGL){
+ INCLUDEPATH += $$QMAKE_INCDIR_EGL
+ }
+ !isEmpty(QMAKE_LIBDIR_EGL){
+ for(p, QMAKE_LIBDIR_EGL) {
+ exists($$p):LIBS += -L$$p
+ }
+ }
+
+ !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL
+ }
wince*: SOURCES += egl/qegl_wince.cpp
@@ -16,10 +28,14 @@ contains(QT_CONFIG, egl): {
embedded {
SOURCES += egl/qegl_qws.cpp
} else {
- symbian {
- SOURCES += egl/qegl_symbian.cpp
+ qpa {
+ SOURCES += egl/qegl_qpa.cpp
} else {
- SOURCES += egl/qegl_x11.cpp
+ symbian {
+ SOURCES += egl/qegl_symbian.cpp
+ } else {
+ SOURCES += egl/qegl_x11.cpp
+ }
}
}
}
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index f21765eb2e..fdb6a1e029 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -394,7 +394,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties
}
}
if (ctx == EGL_NO_CONTEXT) {
- ctx = eglCreateContext(display(), cfg, 0, contextProps.properties());
+ ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
return false;
diff --git a/src/gui/egl/qegl_qpa.cpp b/src/gui/egl/qegl_qpa.cpp
new file mode 100644
index 0000000000..10caf46d56
--- /dev/null
+++ b/src/gui/egl/qegl_qpa.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qwidget.h>
+#include "qeglcontext_p.h"
+
+#if !defined(QT_NO_EGL)
+
+#include <QtGui/private/qgraphicssystem_p.h>
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/qdesktopwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+EGLNativeDisplayType QEgl::nativeDisplay()
+{
+ return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY);
+}
+
+EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
+{
+ return (EGLNativeWindowType)(widget->winId());
+}
+
+EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap)
+{
+ Q_UNUSED(pixmap);
+ return 0;
+}
+
+//EGLDisplay QEglContext::display()
+//{
+// return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
+//}
+
+static QPlatformScreen *screenForDevice(QPaintDevice *device)
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+
+ QList<QPlatformScreen *> screens = pi->screens();
+
+ int screenNumber;
+ if (device && device->devType() == QInternal::Widget)
+ screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device));
+ else
+ screenNumber = 0;
+ if (screenNumber < 0 || screenNumber >= screens.size())
+ return 0;
+ return screens[screenNumber];
+}
+
+// Set pixel format and other properties based on a paint device.
+void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
+{
+ if (!dev)
+ return;
+
+ // Find the QGLScreen for this paint device.
+ QPlatformScreen *screen = screenForDevice(dev);
+ if (!screen)
+ return;
+ int devType = dev->devType();
+ if (devType == QInternal::Image)
+ setPixelFormat(static_cast<QImage *>(dev)->format());
+ else
+ setPixelFormat(screen->format());
+}
+
+QT_END_NAMESPACE
+
+#endif // !QT_NO_EGL
diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h
index e70cf02e57..0444093957 100644
--- a/src/gui/embedded/qkbd_defaultmap_qws_p.h
+++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h
@@ -642,7 +642,14 @@ const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = {
{ 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 },
{ 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
{ 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+ { 113, 0xffff, 0x01000071, 0x00, 0x00, 0x0000 },
+ { 114, 0xffff, 0x01000070, 0x00, 0x00, 0x0000 },
+ { 115, 0xffff, 0x01000072, 0x00, 0x00, 0x0000 },
+ { 116, 0xffff, 0x0100010b, 0x00, 0x00, 0x0000 },
{ 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 },
+ { 138, 0xffff, 0x01000058, 0x00, 0x00, 0x0000 },
+ { 139, 0xffff, 0x01000055, 0x00, 0x00, 0x0000 },
+
};
const QWSKeyboard::Composing QWSKbPrivate::s_keycompose_default[] = {
diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp
index 8fc7bb86e0..9d2c6e86d8 100644
--- a/src/gui/embedded/qkbd_qws.cpp
+++ b/src/gui/embedded/qkbd_qws.cpp
@@ -48,8 +48,16 @@
#include <QDataStream>
#include <QStringList>
+#ifdef Q_WS_QWS
#include "qwindowsystem_qws.h"
#include "qscreen_qws.h"
+#endif
+
+#ifdef Q_WS_QPA
+#include <QWindowSystemInterface>
+#include <QKeyEvent>
+#endif
+
#include "qtimer.h"
#include <stdlib.h>
@@ -352,7 +360,15 @@ QWSKeyboardHandler::~QWSKeyboardHandler()
void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
bool isPress, bool autoRepeat)
{
+#if defined(Q_WS_QWS)
qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat);
+#elif defined(Q_WS_QPA)
+ QEvent::Type type = isPress ? QEvent::KeyPress : QEvent::KeyRelease;
+ QString str;
+ if (unicode != 0xffff)
+ str = QString(unicode);
+ QWindowSystemInterface::handleKeyEvent(0, type, keycode, modifiers, str);
+#endif
}
/*!
@@ -375,6 +391,7 @@ void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardM
*/
int QWSKeyboardHandler::transformDirKey(int key)
{
+#ifdef Q_WS_QWS
static int dir_keyrot = -1;
if (dir_keyrot < 0) {
// get the rotation
@@ -387,6 +404,9 @@ int QWSKeyboardHandler::transformDirKey(int key)
}
int xf = qt_screen->transformOrientation() + dir_keyrot;
return (key-Qt::Key_Left+xf)%4+Qt::Key_Left;
+#else
+ return 0;
+#endif
}
/*!
@@ -454,7 +474,7 @@ void QWSKeyboardHandler::endAutoRepeat()
Maps \a keycode according to a keymap and sends that key event to the
\l{Qt for Embedded Linux} server application.
-
+
Please see the \l{Qt for Embedded Linux Character Input} and the \l
{kmap2qmap} documentations for a description on how to create and use
keymap files.
diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp
index cb14fe865d..f6eec1d405 100644
--- a/src/gui/graphicsview/qgraphicsgridlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp
@@ -600,6 +600,18 @@ void QGraphicsGridLayout::removeAt(int index)
}
/*!
+ Removes the layout item \a item without destroying it.
+ Ownership of the item is transferred to the caller.
+
+ \sa addItem()
+*/
+void QGraphicsGridLayout::removeItem(QGraphicsLayoutItem *item)
+{
+ Q_D(QGraphicsGridLayout);
+ int index = d->engine.indexOf(item);
+ removeAt(index);
+}
+/*!
\reimp
*/
void QGraphicsGridLayout::invalidate()
diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h
index 94f90f4f91..f493eb6153 100644
--- a/src/gui/graphicsview/qgraphicsgridlayout.h
+++ b/src/gui/graphicsview/qgraphicsgridlayout.h
@@ -109,11 +109,12 @@ public:
int columnCount() const;
QGraphicsLayoutItem *itemAt(int row, int column) const;
-
+
// inherited from QGraphicsLayout
int count() const;
QGraphicsLayoutItem *itemAt(int index) const;
void removeAt(int index);
+ void removeItem(QGraphicsLayoutItem *item);
void invalidate();
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 52e4d794ee..01fed8ceed 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1703,12 +1703,12 @@ void QGraphicsItem::setParentItem(QGraphicsItem *newParent)
return;
const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange,
- qVariantFromValue<QGraphicsItem *>(newParent)));
- newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
+ QVariant::fromValue<QGraphicsItem *>(newParent)));
+ newParent = qvariant_cast<QGraphicsItem *>(newParentVariant);
if (newParent == d_ptr->parent)
return;
- const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this));
+ const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this));
d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant);
}
@@ -2132,7 +2132,7 @@ void QGraphicsItem::setToolTip(const QString &toolTip)
*/
QCursor QGraphicsItem::cursor() const
{
- return qVariantValue<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
+ return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor));
}
/*!
@@ -2152,8 +2152,8 @@ QCursor QGraphicsItem::cursor() const
*/
void QGraphicsItem::setCursor(const QCursor &cursor)
{
- const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue<QCursor>(cursor)));
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant));
+ const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor)));
+ d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant));
d_ptr->hasCursor = 1;
if (d_ptr->scene) {
d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
@@ -2279,7 +2279,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
// Schedule redrawing
if (update) {
- QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
+ QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
if (c)
c->purge();
if (scene) {
@@ -3721,7 +3721,7 @@ void QGraphicsItem::setPos(const QPointF &pos)
}
// Notify the item that the position is changing.
- const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
+ const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos)));
QPointF newPos = newPosVariant.toPointF();
if (newPos == d_ptr->pos)
return;
@@ -4075,7 +4075,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
if (d_ptr->flags & ItemSendsGeometryChanges) {
// Notify the item that the origin point is changing.
const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
- qVariantFromValue<QPointF>(origin)));
+ QVariant::fromValue<QPointF>(origin)));
newOrigin = newOriginVariant.toPointF();
}
@@ -4094,7 +4094,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
// Send post-notification.
if (d_ptr->flags & ItemSendsGeometryChanges)
- itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin));
+ itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin));
}
/*!
@@ -4356,8 +4356,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
}
// Notify the item that the transformation matrix is changing.
- const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine());
- newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
+ const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine());
+ newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
if (d_ptr->transformData->transform == newTransform)
return;
@@ -4365,7 +4365,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
d_ptr->setTransformHelper(newTransform);
// Send post-notification.
- itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
+ itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform));
}
/*!
@@ -4408,8 +4408,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
// Notify the item that the transformation matrix is changing.
const QVariant newTransformVariant(itemChange(ItemTransformChange,
- qVariantFromValue<QTransform>(newTransform)));
- newTransform = qVariantValue<QTransform>(newTransformVariant);
+ QVariant::fromValue<QTransform>(newTransform)));
+ newTransform = qvariant_cast<QTransform>(newTransformVariant);
if (d_ptr->transformData->transform == newTransform)
return;
@@ -5262,7 +5262,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c
qreal QGraphicsItem::boundingRegionGranularity() const
{
return d_ptr->hasBoundingRegionGranularity
- ? qVariantValue<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity))
+ ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity))
: 0;
}
@@ -5298,7 +5298,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity)
}
d_ptr->hasBoundingRegionGranularity = 1;
d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity,
- qVariantFromValue<qreal>(granularity));
+ QVariant::fromValue<qreal>(granularity));
}
/*!
@@ -5473,7 +5473,7 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
*/
QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
{
- return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
+ return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
}
/*!
@@ -5481,11 +5481,11 @@ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
*/
QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
{
- QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
+ QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
if (!c) {
QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this);
c = new QGraphicsItemCache;
- that->setExtra(ExtraCacheData, qVariantFromValue<void *>(c));
+ that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c));
}
return c;
}
@@ -5495,7 +5495,7 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
*/
void QGraphicsItemPrivate::removeExtraItemCache()
{
- QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
+ QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData));
if (c) {
c->purge();
delete c;
@@ -8115,6 +8115,8 @@ QPen QAbstractGraphicsShapeItem::pen() const
void QAbstractGraphicsShapeItem::setPen(const QPen &pen)
{
Q_D(QAbstractGraphicsShapeItem);
+ if (d->pen == pen)
+ return;
prepareGeometryChange();
d->pen = pen;
d->boundingRect = QRectF();
@@ -8145,6 +8147,8 @@ QBrush QAbstractGraphicsShapeItem::brush() const
void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush)
{
Q_D(QAbstractGraphicsShapeItem);
+ if (d->brush == brush)
+ return;
d->brush = brush;
update();
}
@@ -9275,6 +9279,8 @@ QPen QGraphicsLineItem::pen() const
void QGraphicsLineItem::setPen(const QPen &pen)
{
Q_D(QGraphicsLineItem);
+ if (d->pen == pen)
+ return;
prepareGeometryChange();
d->pen = pen;
update();
diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp
index ec45d82376..7eedc8dd3d 100644
--- a/src/gui/graphicsview/qgraphicsitemanimation.cpp
+++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp
@@ -49,20 +49,20 @@
The QGraphicsItemAnimation class animates a QGraphicsItem. You can
schedule changes to the item's transformation matrix at
- specified steps. The QGraphicsItemAnimation class has a
- current step value. When this value changes the transformations
- scheduled at that step are performed. The current step of the
+ specified steps. The QGraphicsItemAnimation class has a
+ current step value. When this value changes the transformations
+ scheduled at that step are performed. The current step of the
animation is set with the \c setStep() function.
QGraphicsItemAnimation will do a simple linear interpolation
- between the nearest adjacent scheduled changes to calculate the
+ between the nearest adjacent scheduled changes to calculate the
matrix. For instance, if you set the position of an item at values
0.0 and 1.0, the animation will show the item moving in a straight
- line between these positions. The same is true for scaling and
+ line between these positions. The same is true for scaling and
rotation.
It is usual to use the class with a QTimeLine. The timeline's
- \l{QTimeLine::}{valueChanged()} signal is then connected to the
+ \l{QTimeLine::}{valueChanged()} signal is then connected to the
\c setStep() slot. For example, you can set up an item for rotation
by calling \c setRotationAt() for different step values.
The animations timeline is set with the setTimeLine() function.
@@ -286,7 +286,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const
QList<QPair<qreal, QPointF> > list;
for (int i = 0; i < d->xPosition.size(); ++i)
list << QPair<qreal, QPointF>(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value));
-
+
return list;
}
@@ -343,7 +343,7 @@ QList<QPair<qreal, qreal> > QGraphicsItemAnimation::rotationList() const
QList<QPair<qreal, qreal> > list;
for (int i = 0; i < d->rotation.size(); ++i)
list << QPair<qreal, qreal>(d->rotation.at(i).step, d->rotation.at(i).value);
-
+
return list;
}
@@ -395,7 +395,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::translationList() const
QList<QPair<qreal, QPointF> > list;
for (int i = 0; i < d->xTranslation.size(); ++i)
list << QPair<qreal, QPointF>(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value));
-
+
return list;
}
@@ -447,7 +447,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::scaleList() const
QList<QPair<qreal, QPointF> > list;
for (int i = 0; i < d->horizontalScale.size(); ++i)
list << QPair<qreal, QPointF>(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value));
-
+
return list;
}
@@ -499,7 +499,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::shearList() const
QList<QPair<qreal, QPointF> > list;
for (int i = 0; i < d->horizontalShear.size(); ++i)
list << QPair<qreal, QPointF>(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value));
-
+
return list;
}
diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp
index ed213f1627..904a3deda2 100644
--- a/src/gui/graphicsview/qgraphicslayout.cpp
+++ b/src/gui/graphicsview/qgraphicslayout.cpp
@@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE
/*!
Contructs a QGraphicsLayout object.
-
+
\a parent is passed to QGraphicsLayoutItem's constructor and the
QGraphicsLayoutItem's isLayout argument is set to \e true.
@@ -259,7 +259,7 @@ void QGraphicsLayout::activate()
return;
d->activateRecursive(this);
-
+
// we don't call activate on a sublayout, but somebody might.
// Therefore, we walk to the parentitem of the toplevel layout.
QGraphicsLayoutItem *parentItem = this;
@@ -270,7 +270,7 @@ void QGraphicsLayout::activate()
Q_ASSERT(!parentItem->isLayout());
setGeometry(parentItem->contentsRect()); // relayout children
-
+
// ### bug, should be parentItem ?
parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false
// ### too many resizes? maybe we should walk up the chain to the
@@ -350,7 +350,7 @@ void QGraphicsLayout::updateGeometry()
widget. QGraphicsLayout uses this event handler to listen for layout
related events such as geometry changes, layout changes or layout
direction changes.
-
+
\a e is a pointer to the event.
You can reimplement this event handler to track similar events for your
diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp
index c2d4a08dda..c325602cc6 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicslayout_p.cpp
@@ -136,13 +136,13 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem
/*!
\internal
- This function is called from subclasses to add a layout item \a layoutItem
+ This function is called from subclasses to add a layout item \a layoutItem
to a layout.
It takes care of automatically reparenting graphics items, if needed.
If \a layoutItem is a is already in a layout, it will remove it from that layout.
-
+
*/
void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
{
@@ -150,14 +150,14 @@ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) {
if (maybeLayout->isLayout())
removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(maybeLayout), layoutItem);
- }
+ }
layoutItem->setParentLayoutItem(q);
if (layoutItem->isLayout()) {
if (QGraphicsItem *parItem = parentItem()) {
static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(parItem);
}
} else {
- if (QGraphicsItem *item = layoutItem->graphicsItem()) {
+ if (QGraphicsItem *item = layoutItem->graphicsItem()) {
QGraphicsItem *newParent = parentItem();
QGraphicsItem *oldParent = item->parentItem();
if (oldParent == newParent || !newParent)
@@ -182,7 +182,7 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item)
QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item);
if (layout->d_func()->activated)
layout->invalidate();
-
+
for (int i = layout->count() - 1; i >= 0; --i) {
QGraphicsLayoutItem *childItem = layout->itemAt(i);
if (childItem)
@@ -194,5 +194,5 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item)
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h
index 6e6f385eb8..5358ec3cf4 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.h
+++ b/src/gui/graphicsview/qgraphicslayout_p.h
@@ -84,7 +84,7 @@ class QLayoutStyleInfo
public:
inline QLayoutStyleInfo() { invalidate(); }
inline QLayoutStyleInfo(QStyle *style, QWidget *widget)
- : m_valid(true), m_style(style), m_widget(widget)
+ : m_valid(true), m_style(style), m_widget(widget)
{
Q_ASSERT(style);
if (widget) //###
@@ -112,7 +112,7 @@ public:
return m_defaultSpacing[o - 1];
}
- inline qreal perItemSpacing(QSizePolicy::ControlType control1,
+ inline qreal perItemSpacing(QSizePolicy::ControlType control1,
QSizePolicy::ControlType control2,
Qt::Orientation orientation) const
{
@@ -132,7 +132,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva
Q_DECLARE_PUBLIC(QGraphicsLayout)
public:
- QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0),
+ QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0),
activated(true) { }
void reparentChildItems(QGraphicsItem *newParent);
@@ -148,7 +148,7 @@ public:
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
#endif
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp
index fb08b9e984..c064e01502 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp
@@ -296,10 +296,6 @@ bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const
bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
{
- // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8)
-#if 1
- return false;
-#else
Q_Q(const QGraphicsLayoutItem);
if (isLayout) {
const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
@@ -316,7 +312,6 @@ bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
}
}
return q->sizePolicy().hasWidthForHeight();
-#endif
}
/*!
@@ -710,7 +705,7 @@ void QGraphicsLayoutItem::setMaximumHeight(qreal height)
is equivalent to the item's position in parent coordinates).
You must reimplement this function in a subclass of QGraphicsLayoutItem to
- receive geometry updates. The layout will call this function when it does a
+ receive geometry updates. The layout will call this function when it does a
rearrangement.
If \a rect is outside of the bounds of minimumSize and maximumSize, it
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index d82b1952b9..7112dd06fc 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -118,7 +118,7 @@ protected:
private:
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
Q_DECLARE_PRIVATE(QGraphicsLayoutItem)
-
+
friend class QGraphicsLayout;
};
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index 8bbaff9695..e6142e66ac 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -266,8 +266,8 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent
}
if (!lastWidgetUnderMouse) {
- QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : widget, 0);
- lastWidgetUnderMouse = widget;
+ QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0);
+ lastWidgetUnderMouse = receiver;
}
// Map event position from us to the receiver
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 5e5077bce3..7b87239a68 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -2544,8 +2544,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Notify the item that its scene is changing, and allow the item to
// react.
const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
- qVariantFromValue<QGraphicsScene *>(this)));
- QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
+ QVariant::fromValue<QGraphicsScene *>(this)));
+ QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
if (targetScene != this) {
if (targetScene && item->d_ptr->scene != targetScene)
targetScene->addItem(item);
@@ -2956,8 +2956,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
// Notify the item that it's scene is changing to 0, allowing the item to
// react.
const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
- qVariantFromValue<QGraphicsScene *>(0)));
- QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
+ QVariant::fromValue<QGraphicsScene *>(0)));
+ QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
if (targetScene != 0 && targetScene != this) {
targetScene->addItem(item);
return;
@@ -3461,7 +3461,8 @@ bool QGraphicsScene::event(QEvent *event)
break;
}
case QEvent::Leave:
- d->leaveScene();
+ // hackieshly unpacking the viewport pointer from the leave event.
+ d->leaveScene(reinterpret_cast<QWidget *>(event->d));
break;
case QEvent::GraphicsSceneHelp:
helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
@@ -3933,20 +3934,19 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv
Handles all actions necessary to clean up the scene when the mouse leaves
the view.
*/
-void QGraphicsScenePrivate::leaveScene()
+void QGraphicsScenePrivate::leaveScene(QWidget *viewport)
{
- Q_Q(QGraphicsScene);
#ifndef QT_NO_TOOLTIP
QToolTip::hideText();
#endif
+ QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent());
// Send HoverLeave events to all existing hover items, topmost first.
- QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender());
QGraphicsSceneHoverEvent hoverEvent;
- hoverEvent.setWidget(senderWidget);
+ hoverEvent.setWidget(viewport);
- if (senderWidget) {
+ if (view) {
QPoint cursorPos = QCursor::pos();
- hoverEvent.setScenePos(senderWidget->mapToScene(senderWidget->mapFromGlobal(cursorPos)));
+ hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos)));
hoverEvent.setLastScenePos(hoverEvent.scenePos());
hoverEvent.setScreenPos(cursorPos);
hoverEvent.setLastScreenPos(hoverEvent.screenPos());
@@ -4367,25 +4367,8 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &
static inline bool transformIsSimple(const QTransform& transform)
{
QTransform::TransformationType type = transform.type();
- if (type == QTransform::TxNone || type == QTransform::TxTranslate) {
+ if (type <= QTransform::TxScale) {
return true;
- } else if (type == QTransform::TxScale) {
- // Check for 0 and 180 degree rotations.
- // (0 might happen after 4 rotations of 90 degrees).
- qreal m11 = transform.m11();
- qreal m12 = transform.m12();
- qreal m21 = transform.m21();
- qreal m22 = transform.m22();
- if (m12 == 0.0f && m21 == 0.0f) {
- if (m11 == 1.0f && m22 == 1.0f)
- return true; // 0 degrees
- else if (m11 == -1.0f && m22 == -1.0f)
- return true; // 180 degrees.
- if(m11 == 1.0f && m22 == -1.0f)
- return true; // 0 degrees inverted y.
- else if(m11 == -1.0f && m22 == 1.0f)
- return true; // 180 degrees inverted y.
- }
} else if (type == QTransform::TxRotate) {
// Check for 90, and 270 degree rotations.
qreal m11 = transform.m11();
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 815c70b614..2314e37a20 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -201,7 +201,7 @@ public:
bool dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent);
bool itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const;
- void leaveScene();
+ void leaveScene(QWidget *viewport);
void cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
QGraphicsSceneDragDropEvent *source);
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 2b129d7a84..0e2750d546 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -80,9 +80,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
yourself, you can call setSceneRect(). This will adjust the scroll bars'
ranges appropriately. Note that although the scene supports a virtually
unlimited size, the range of the scroll bars will never exceed the range of
- an integer (INT_MIN, INT_MAX). When the scene is larger than the scroll
- bars' values, you can choose to use translate() to navigate the scene
- instead.
+ an integer (INT_MIN, INT_MAX).
QGraphicsView visualizes the scene by calling render(). By default, the
items are drawn onto the viewport by using a regular QPainter, and using
@@ -101,7 +99,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
convenience functions rotate(), scale(), translate() or shear(). The most
two common transformations are scaling, which is used to implement
zooming, and rotation. QGraphicsView keeps the center of the view fixed
- during a transformation.
+ during a transformation. Because of the scene alignment (setAligment()),
+ translating the view will have no visual impact.
You can interact with the items on the scene by using the mouse and
keyboard. QGraphicsView translates the mouse and key events into \e scene
@@ -2790,6 +2789,9 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
}
d->useLastMouseEvent = false;
+ // a hack to pass a viewport pointer to the scene inside the leave event
+ Q_ASSERT(event->d == 0);
+ event->d = reinterpret_cast<QEventPrivate *>(viewport());
QApplication::sendEvent(d->scene, event);
break;
#ifndef QT_NO_TOOLTIP
@@ -3710,7 +3712,7 @@ void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
}
/*!
- \obsolete
+ \obsolete
Draws the items \a items in the scene using \a painter, after the
background and before the foreground are drawn. \a numItems is the number
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index 61b843b76c..5572b7e770 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -62,6 +62,7 @@
#include "qgraphicssceneevent.h"
#include <QtGui/qstyleoption.h>
#include <private/qabstractscrollarea_p.h>
+#include <private/qapplication_p.h>
QT_BEGIN_NAMESPACE
@@ -180,21 +181,24 @@ public:
inline void dispatchPendingUpdateRequests()
{
-#ifndef Q_WS_MAC
- // QWidget::update() works slightly different on the Mac; it's not part of
- // our backing store so it needs special threatment.
- if (qt_widget_private(viewport)->paintOnScreen())
- QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
- else
- QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
-#else
- // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa)
- // is called, which means there's a pending update request. We want to dispatch it
- // now because otherwise graphics view updates would require two
- // round-trips in the event loop before the item is painted.
- extern void qt_mac_dispatchPendingUpdateRequests(QWidget *);
- qt_mac_dispatchPendingUpdateRequests(viewport->window());
-#endif
+#ifdef Q_WS_MAC
+ // QWidget::update() works slightly different on the Mac without the raster engine;
+ // it's not part of our backing store so it needs special threatment.
+ if (QApplicationPrivate::graphics_system_name != QLatin1String("raster")) {
+ // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa)
+ // is called, which means there's a pending update request. We want to dispatch it
+ // now because otherwise graphics view updates would require two
+ // round-trips in the event loop before the item is painted.
+ extern void qt_mac_dispatchPendingUpdateRequests(QWidget *);
+ qt_mac_dispatchPendingUpdateRequests(viewport->window());
+ } else
+#endif // !Q_WS_MAC
+ {
+ if (qt_widget_private(viewport)->paintOnScreen())
+ QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
+ else
+ QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
+ }
}
void setUpdateClip(QGraphicsItem *);
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index a756fb53a5..45800551cb 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -46,6 +46,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
+#include "qgraphicslayoutitem_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
#include <QtGui/qapplication.h>
@@ -415,8 +416,7 @@ static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
bool heightForWidth = true)
{
qreal minimumHeightForWidth = -1;
- const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy();
- const bool hasHFW = sp.hasHeightForWidth();
+ const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
if (hasHFW == heightForWidth) {
minimumHeightForWidth = hasHFW
? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
@@ -505,21 +505,31 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
qreal width = qBound(min.width(), proposedRect.width(), max.width());
qreal height = qBound(min.height(), proposedRect.height(), max.height());
- QSizePolicy sp = widget->sizePolicy();
- if (const QGraphicsLayout *l = widget->layout()) {
- sp = l->sizePolicy();
- }
- const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight();
+ const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
+ const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight();
- const bool widthChanged = proposedRect.width() < widget->size().width();
- const bool heightChanged = proposedRect.height() < widget->size().height();
+ const bool widthChanged = proposedRect.width() != widget->size().width();
+ const bool heightChanged = proposedRect.height() != widget->size().height();
- if (hasHFW) {
+ if (hasHFW || hasWFH) {
if (widthChanged || heightChanged) {
- const qreal minh = min.height();
- const qreal maxh = max.height();
- const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget);
- if (proposedHFW > proposedRect.height()) {
+ qreal minExtent;
+ qreal maxExtent;
+ qreal constraint;
+ qreal proposed;
+ if (hasHFW) {
+ minExtent = min.height();
+ maxExtent = max.height();
+ constraint = width;
+ proposed = proposedRect.height();
+ } else {
+ // width for height
+ minExtent = min.width();
+ maxExtent = max.width();
+ constraint = height;
+ proposed = proposedRect.width();
+ }
+ if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) {
QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
width = effectiveSize.width();
height = effectiveSize.height();
diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp
index 8f833f805f..41ede20276 100644
--- a/src/gui/graphicsview/qgridlayoutengine.cpp
+++ b/src/gui/graphicsview/qgridlayoutengine.cpp
@@ -824,6 +824,15 @@ QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const
return q_items.at(index);
}
+int QGridLayoutEngine::indexOf(QGraphicsLayoutItem *item) const
+{
+ for (int i = 0; i < q_items.size(); ++i) {
+ if (item == q_items.at(i)->layoutItem())
+ return i;
+ }
+ return -1;
+}
+
int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const
{
ensureEffectiveFirstAndLastRows();
diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h
index 17071b0b23..c5b35f59e8 100644
--- a/src/gui/graphicsview/qgridlayoutengine_p.h
+++ b/src/gui/graphicsview/qgridlayoutengine_p.h
@@ -341,6 +341,7 @@ public:
// returns the number of items inserted, which may be less than (rowCount * columnCount)
int itemCount() const;
QGridLayoutItem *itemAt(int index) const;
+ int indexOf(QGraphicsLayoutItem *item) const;
int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const;
int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const;
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 4d51fa8ce3..fe1a595af3 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -5,9 +5,9 @@ DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
-!win32:!embedded:!mac:!symbian:CONFIG += x11
+!win32:!embedded:!qpa:!mac:!symbian:CONFIG += x11
-unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
+unix|win32-g++*:QMAKE_PKGCONFIG_REQUIRES = QtCore
include(../qbase.pri)
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index f89706cc7c..92ea397a57 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -23,6 +23,7 @@ HEADERS += \
image/qpictureformatplugin.h \
image/qpixmap.h \
image/qpixmap_raster_p.h \
+ image/qpixmap_blitter_p.h \
image/qpixmapcache.h \
image/qpixmapcache_p.h \
image/qpixmapdata_p.h \
@@ -50,6 +51,7 @@ SOURCES += \
image/qiconengineplugin.cpp \
image/qmovie.cpp \
image/qpixmap_raster.cpp \
+ image/qpixmap_blitter.cpp \
image/qnativeimage.cpp \
image/qimagepixmapcleanuphooks.cpp
@@ -59,6 +61,9 @@ win32 {
else:embedded {
SOURCES += image/qpixmap_qws.cpp
}
+else:qpa {
+ SOURCES += image/qpixmap_qpa.cpp
+}
else:x11 {
HEADERS += image/qpixmap_x11_p.h
SOURCES += image/qpixmap_x11.cpp
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index ae9911575e..260b397140 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -227,6 +227,14 @@ QBitmap::~QBitmap()
}
/*!
+ \fn void QBitmap::swap(QBitmap &other)
+ \since 4.8
+
+ Swaps bitmap \a other with this bitmap. This operation is very
+ fast and never fails.
+*/
+
+/*!
Returns the bitmap as a QVariant.
*/
QBitmap::operator QVariant() const
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index 525a694fd7..f1771e3e43 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -63,6 +63,7 @@ public:
~QBitmap();
QBitmap &operator=(const QPixmap &);
+ inline void swap(QBitmap &other) { QPixmap::swap(other); } // prevent QBitmap<->QPixmap swaps
operator QVariant() const;
inline void clear() { fill(Qt::color0); }
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index d0cc937ce6..158f9ab8b1 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -613,6 +613,14 @@ QIcon &QIcon::operator=(const QIcon &other)
}
/*!
+ \fn void QIcon::swap(QIcon &other)
+ \since 4.8
+
+ Swaps icon \a other with this icon. This operation is very
+ fast and never fails.
+*/
+
+/*!
Returns the icon as a QVariant.
*/
QIcon::operator QVariant() const
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index aadcb48cd5..170559182b 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -71,6 +71,12 @@ public:
explicit QIcon(QIconEngineV2 *engine);
~QIcon();
QIcon &operator=(const QIcon &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QIcon &operator=(QIcon &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QIcon &other) { qSwap(d, other.d); }
+
operator QVariant() const;
QPixmap pixmap(const QSize &size, Mode mode = Normal, State state = Off) const;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 9028de4961..91ee697d94 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -139,42 +139,6 @@ QImageData::QImageData()
{
}
-static int depthForFormat(QImage::Format format)
-{
- int depth = 0;
- switch(format) {
- case QImage::Format_Invalid:
- case QImage::NImageFormats:
- Q_ASSERT(false);
- case QImage::Format_Mono:
- case QImage::Format_MonoLSB:
- depth = 1;
- break;
- case QImage::Format_Indexed8:
- depth = 8;
- break;
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32:
- case QImage::Format_ARGB32_Premultiplied:
- depth = 32;
- break;
- case QImage::Format_RGB555:
- case QImage::Format_RGB16:
- case QImage::Format_RGB444:
- case QImage::Format_ARGB4444_Premultiplied:
- depth = 16;
- break;
- case QImage::Format_RGB666:
- case QImage::Format_ARGB6666_Premultiplied:
- case QImage::Format_ARGB8565_Premultiplied:
- case QImage::Format_ARGB8555_Premultiplied:
- case QImage::Format_RGB888:
- depth = 24;
- break;
- }
- return depth;
-}
-
/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
\internal
@@ -195,7 +159,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
uint width = size.width();
uint height = size.height();
- uint depth = depthForFormat(format);
+ uint depth = qt_depthForFormat(format);
switch (format) {
case QImage::Format_Mono:
@@ -871,7 +835,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
return 0;
}
- const int depth = depthForFormat(format);
+ const int depth = qt_depthForFormat(format);
const int calc_bytes_per_line = ((width * depth + 31)/32) * 4;
const int min_bytes_per_line = (width * depth + 7)/8;
@@ -1338,6 +1302,14 @@ QImage &QImage::operator=(const QImage &image)
}
/*!
+ \fn void QImage::swap(QImage &other)
+ \since 4.8
+
+ Swaps image \a other with this image. This operation is very
+ fast and never fails.
+*/
+
+/*!
\internal
*/
int QImage::devType() const
@@ -2031,6 +2003,88 @@ void QImage::fill(uint pixel)
0, 0, d->width, d->height, d->bytes_per_line);
}
+
+/*!
+ \fn void QImage::fill(Qt::GlobalColor color)
+
+ \overload
+
+ \since 4.8
+ */
+
+void QImage::fill(Qt::GlobalColor color)
+{
+ fill(QColor(color));
+}
+
+
+
+/*!
+ \fn void QImage::fill(Qt::GlobalColor color)
+
+ \overload
+
+ Fills the entire image with the given \a color.
+
+ If the depth of the image is 1, the image will be filled with 1 if
+ \a color equals Qt::color1; it will otherwise be filled with 0.
+
+ If the depth of the image is 8, the image will be filled with the
+ index corresponding the \a color in the color table if present; it
+ will otherwise be filled with 0.
+
+ \since 4.8
+*/
+
+void QImage::fill(const QColor &color)
+{
+ if (!d)
+ return;
+ detach();
+
+ // In case we run out of memory
+ if (!d)
+ return;
+
+ if (d->depth == 32) {
+ uint pixel = color.rgba();
+ if (d->format == QImage::Format_ARGB32_Premultiplied)
+ pixel = PREMUL(pixel);
+ fill((uint) pixel);
+
+ } else if (d->depth == 16 && d->format == QImage::Format_RGB16) {
+ qrgb565 p(color.rgba());
+ fill((uint) p.rawValue());
+
+ } else if (d->depth == 1) {
+ if (color == Qt::color1)
+ fill((uint) 1);
+ else
+ fill((uint) 0);
+
+ } else if (d->depth == 8) {
+ uint pixel = 0;
+ for (int i=0; i<d->colortable.size(); ++i) {
+ if (color.rgba() == d->colortable.at(i)) {
+ pixel = i;
+ break;
+ }
+ }
+ fill(pixel);
+
+ } else {
+ QPainter p(this);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(rect(), color);
+ }
+
+}
+
+
+
+
+
+
/*!
Inverts all pixel values in the image.
@@ -3788,6 +3842,26 @@ void qInitImageConversions()
#endif
}
+void qGamma_correct_back_to_linear_cs(QImage *image)
+{
+ extern uchar qt_pow_rgb_gamma[256];
+
+ // gamma correct the pixels back to linear color space...
+ int h = image->height();
+ int w = image->width();
+
+ for (int y=0; y<h; ++y) {
+ uint *pixels = (uint *) image->scanLine(y);
+ for (int x=0; x<w; ++x) {
+ uint p = pixels[x];
+ uint r = qt_pow_rgb_gamma[qRed(p)];
+ uint g = qt_pow_rgb_gamma[qGreen(p)];
+ uint b = qt_pow_rgb_gamma[qBlue(p)];
+ pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
+ }
+ }
+}
+
/*!
Returns a copy of the image in the given \a format.
@@ -6240,7 +6314,7 @@ int QImage::bitPlaneCount() const
bpc = 12;
break;
default:
- bpc = depthForFormat(d->format);
+ bpc = qt_depthForFormat(d->format);
break;
}
return bpc;
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index a83d70f77f..496fe93c54 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -140,6 +140,12 @@ public:
~QImage();
QImage &operator=(const QImage &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QImage &operator=(QImage &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QImage &other) { qSwap(d, other.d); }
+
bool isNull() const;
int devType() const;
@@ -210,6 +216,9 @@ public:
void setColorTable(const QVector<QRgb> colors);
void fill(uint pixel);
+ void fill(const QColor &color);
+ void fill(Qt::GlobalColor color);
+
bool hasAlphaChannel() const;
void setAlphaChannel(const QImage &alphaChannel);
@@ -326,6 +335,7 @@ private:
QImageData *d;
friend class QRasterPixmapData;
+ friend class QBlittablePixmapData;
friend class QPixmapCacheEntry;
friend Q_GUI_EXPORT qint64 qt_image_id(const QImage &image);
friend const QVector<QRgb> *qt_image_colortable(const QImage &image);
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index e8e36d0e04..db6620b39c 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -111,6 +111,43 @@ struct Q_GUI_EXPORT QImageData { // internal image data
};
void qInitImageConversions();
+Q_GUI_EXPORT void qGamma_correct_back_to_linear_cs(QImage *image);
+
+inline int qt_depthForFormat(QImage::Format format)
+{
+ int depth = 0;
+ switch(format) {
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ Q_ASSERT(false);
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ depth = 1;
+ break;
+ case QImage::Format_Indexed8:
+ depth = 8;
+ break;
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ depth = 32;
+ break;
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB444:
+ case QImage::Format_ARGB4444_Premultiplied:
+ depth = 16;
+ break;
+ case QImage::Format_RGB666:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_RGB888:
+ depth = 24;
+ break;
+ }
+ return depth;
+}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 1fa1058cb6..ab05bf19c1 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1092,7 +1092,7 @@ QColor QImageReader::backgroundColor() const
if (!d->initHandler())
return QColor();
if (d->handler->supportsOption(QImageIOHandler::BackgroundColor))
- return qVariantValue<QColor>(d->handler->option(QImageIOHandler::BackgroundColor));
+ return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor));
return QColor();
}
diff --git a/src/gui/image/qmnghandler.cpp b/src/gui/image/qmnghandler.cpp
index e4c3b4ff48..6b918af0c3 100644
--- a/src/gui/image/qmnghandler.cpp
+++ b/src/gui/image/qmnghandler.cpp
@@ -481,7 +481,7 @@ void QMngHandler::setOption(ImageOption option, const QVariant & value)
{
Q_D(QMngHandler);
if (option == QImageIOHandler::BackgroundColor)
- d->setBackgroundColor(qVariantValue<QColor>(value));
+ d->setBackgroundColor(qvariant_cast<QColor>(value));
}
/*! \reimp */
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 5fb97e01af..8b6e360096 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -381,10 +381,14 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
QPixmap aPixmap = QPixmap::fromImage(anImage);
int aDelay = reader->nextImageDelay();
return QFrameInfo(aPixmap, aDelay);
- } else {
+ } else if (frameNumber != 0) {
// We've read all frames now. Return an end marker
haveReadAll = true;
return QFrameInfo::endMarker();
+ } else {
+ // No readable frames
+ haveReadAll = true;
+ return QFrameInfo();
}
}
diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp
index b560af3598..01baa36016 100644
--- a/src/gui/image/qnativeimage.cpp
+++ b/src/gui/image/qnativeimage.cpp
@@ -45,6 +45,9 @@
#include "private/qpaintengine_raster_p.h"
+#include "private/qapplication_p.h"
+#include "private/qgraphicssystem_p.h"
+
#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM)
#include <qx11info_x11.h>
#include <sys/ipc.h>
@@ -241,8 +244,21 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /*
: image(width, height, format)
{
-
uint cgflags = kCGImageAlphaNoneSkipFirst;
+ switch (format) {
+ case QImage::Format_ARGB32:
+ cgflags = kCGImageAlphaFirst;
+ break;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ cgflags = kCGImageAlphaPremultipliedFirst;
+ break;
+ default:
+ break;
+ }
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
cgflags |= kCGBitmapByteOrder32Host;
@@ -284,7 +300,11 @@ QNativeImage::~QNativeImage()
QImage::Format QNativeImage::systemFormat()
{
+#ifdef Q_WS_QPA
+ return QApplicationPrivate::platformIntegration()->screens().at(0)->format();
+#else
return QImage::Format_RGB32;
+#endif
}
#endif // platforms
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index a06c2bc443..053d1fc15e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1030,6 +1030,14 @@ QPicture& QPicture::operator=(const QPicture &p)
}
/*!
+ \fn void QPicture::swap(QPicture &other)
+ \since 4.8
+
+ Swaps picture \a other with this picture. This operation is very
+ fast and never fails.
+*/
+
+/*!
\internal
Constructs a QPicturePrivate
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 8d8c2ce40d..c478ed962e 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -81,6 +81,11 @@ public:
void setBoundingRect(const QRect &r);
QPicture& operator=(const QPicture &p);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPicture &operator=(QPicture &&other)
+ { qSwap(d_ptr, other.d_ptr); return *this; }
+#endif
+ inline void swap(QPicture &other) { d_ptr.swap(other.d_ptr); }
void detach();
bool isDetached() const;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 0aefafb1cd..f89657254d 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -99,7 +99,7 @@ static bool qt_pixmap_thread_test()
return false;
}
#ifndef Q_WS_WIN
- if (qApp->thread() != QThread::currentThread()) {
+ if (!QApplication::testAttribute(Qt::AA_X11InitThreads) && qApp->thread() != QThread::currentThread()) {
qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
return false;
}
@@ -440,6 +440,14 @@ QPixmap &QPixmap::operator=(const QPixmap &pixmap)
}
/*!
+ \fn void QPixmap::swap(QPixmap &other)
+ \since 4.8
+
+ Swaps pixmap \a other with this pixmap. This operation is very
+ fast and never fails.
+*/
+
+/*!
Returns the pixmap as a QVariant.
*/
QPixmap::operator QVariant() const
@@ -1178,7 +1186,12 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
\warning This function is X11 specific; using it is non-portable.
+ \warning Since 4.8, pixmaps do not have an X11 handle unless
+ created with \l {QPixmap::}{fromX11Pixmap()}, or if the native
+ graphics system is explicitly enabled.
+
\sa detach()
+ \sa QApplication::setGraphicsSystem()
*/
Qt::HANDLE QPixmap::handle() const
@@ -1962,6 +1975,8 @@ int QPixmap::defaultDepth()
return 32;
#elif defined(Q_OS_SYMBIAN)
return S60->screenDepth;
+#elif defined(Q_WS_QPA)
+ return 32; //LITE: use graphicssystem (we should do that in general)
#endif
}
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index ace0d86c42..f2e79c14f4 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -83,6 +83,12 @@ public:
~QPixmap();
QPixmap &operator=(const QPixmap &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPixmap &operator=(QPixmap &&other)
+ { qSwap(data, other.data); return *this; }
+#endif
+ inline void swap(QPixmap &other) { qSwap(data, other.data); }
+
operator QVariant() const;
bool isNull() const; // ### Qt 5: make inline
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
new file mode 100644
index 0000000000..e8a7b8915c
--- /dev/null
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixmap_blitter_p.h"
+
+#include <qpainter.h>
+#include <qimage.h>
+
+#include <private/qapplication_p.h>
+#include <private/qgraphicssystem_p.h>
+#include <private/qblittable_p.h>
+
+#include <private/qdrawhelper_p.h>
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+static int global_ser_no = 0;
+
+QBlittablePixmapData::QBlittablePixmapData()
+ : QPixmapData(QPixmapData::PixmapType,BlitterClass), m_engine(0), m_blittable(0)
+#ifdef QT_BLITTER_RASTEROVERLAY
+ ,m_rasterOverlay(0), m_unmergedCopy(0)
+#endif //QT_BLITTER_RASTEROVERLAY
+{
+ setSerialNumber(++global_ser_no);
+}
+
+QBlittablePixmapData::~QBlittablePixmapData()
+{
+ delete m_blittable;
+ delete m_engine;
+#ifdef QT_BLITTER_RASTEROVERLAY
+ delete m_rasterOverlay;
+ delete m_unmergedCopy;
+#endif //QT_BLITTER_RASTEROVERLAY
+}
+
+QBlittable *QBlittablePixmapData::blittable() const
+{
+ if (!m_blittable) {
+ QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this);
+ that->m_blittable = this->createBlittable(QSize(w,h));
+ }
+
+ return m_blittable;
+}
+
+void QBlittablePixmapData::setBlittable(QBlittable *blittable)
+{
+ resize(blittable->size().width(),blittable->size().height());
+ m_blittable = blittable;
+}
+
+void QBlittablePixmapData::resize(int width, int height)
+{
+
+ delete m_blittable;
+ m_blittable = 0;
+ delete m_engine;
+ m_engine = 0;
+#ifdef Q_WS_QPA
+ d = QApplicationPrivate::platformIntegration()->screens().at(0)->depth();
+#endif
+ w = width;
+ h = height;
+ is_null = (w <= 0 || h <= 0);
+}
+Q_GUI_EXPORT extern int qt_defaultDpiX();
+Q_GUI_EXPORT extern int qt_defaultDpiY();
+
+int QBlittablePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return w;
+ case QPaintDevice::PdmHeight:
+ return h;
+ case QPaintDevice::PdmWidthMM:
+ return qRound(w * 25.4 / qt_defaultDpiX());
+ case QPaintDevice::PdmHeightMM:
+ return qRound(h * 25.4 / qt_defaultDpiY());
+ case QPaintDevice::PdmDepth:
+ return 32;
+ case QPaintDevice::PdmDpiX: // fall-through
+ case QPaintDevice::PdmPhysicalDpiX:
+ return qt_defaultDpiX();
+ case QPaintDevice::PdmDpiY: // fall-through
+ case QPaintDevice::PdmPhysicalDpiY:
+ return qt_defaultDpiY();
+ default:
+ qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric);
+ break;
+ }
+
+ return 0;
+}
+
+void QBlittablePixmapData::fill(const QColor &color)
+{
+ //jlind: todo: change when blittables can support non opaque fillRects
+ if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) {
+ blittable()->unlock();
+ blittable()->fillRect(QRectF(0,0,w,h),color);
+ }else {
+ uint pixel;
+ switch (blittable()->lock()->format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ pixel = PREMUL(color.rgba());
+ break;
+ case QImage::Format_ARGB8565_Premultiplied:
+ pixel = qargb8565(color.rgba()).rawValue();
+ break;
+ case QImage::Format_ARGB8555_Premultiplied:
+ pixel = qargb8555(color.rgba()).rawValue();
+ break;
+ case QImage::Format_ARGB6666_Premultiplied:
+ pixel = qargb6666(color.rgba()).rawValue();
+ break;
+ case QImage::Format_ARGB4444_Premultiplied:
+ pixel = qargb4444(color.rgba()).rawValue();
+ break;
+ default:
+ pixel = color.rgba();
+ break;
+ }
+ //so premultiplied formats are supported and ARGB32 and RGB32
+ blittable()->lock()->fill(pixel);
+ }
+
+}
+
+QImage *QBlittablePixmapData::buffer()
+{
+ return blittable()->lock();
+}
+
+QImage QBlittablePixmapData::toImage() const
+{
+ return blittable()->lock()->copy();
+}
+
+bool QBlittablePixmapData::hasAlphaChannel() const
+{
+ return blittable()->lock()->hasAlphaChannel();
+}
+
+void QBlittablePixmapData::fromImage(const QImage &image,
+ Qt::ImageConversionFlags flags)
+{
+ resize(image.width(),image.height());
+ markRasterOverlay(QRect(0,0,w,h));
+ QImage *thisImg = buffer();
+
+ QImage correctFormatPic = image;
+ if (correctFormatPic.format() != thisImg->format())
+ correctFormatPic = correctFormatPic.convertToFormat(thisImg->format(), flags);
+
+ uchar *mem = thisImg->bits();
+ const uchar *bits = correctFormatPic.bits();
+ int bytesCopied = 0;
+ while (bytesCopied < correctFormatPic.byteCount()) {
+ memcpy(mem,bits,correctFormatPic.bytesPerLine());
+ mem += thisImg->bytesPerLine();
+ bits += correctFormatPic.bytesPerLine();
+ bytesCopied+=correctFormatPic.bytesPerLine();
+ }
+}
+
+QPaintEngine *QBlittablePixmapData::paintEngine() const
+{
+ if (!m_engine) {
+ QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this);
+ that->m_engine = new QBlitterPaintEngine(that);
+ }
+ return m_engine;
+}
+
+#ifdef QT_BLITTER_RASTEROVERLAY
+
+static bool showRasterOverlay = !qgetenv("QT_BLITTER_RASTEROVERLAY").isEmpty();
+
+void QBlittablePixmapData::mergeOverlay()
+{
+ if (m_unmergedCopy || !showRasterOverlay)
+ return;
+ m_unmergedCopy = new QImage(buffer()->copy());
+ QPainter p(buffer());
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ p.drawImage(0,0,*overlay());
+ p.end();
+}
+
+void QBlittablePixmapData::unmergeOverlay()
+{
+ if (!m_unmergedCopy || !showRasterOverlay)
+ return;
+ QPainter p(buffer());
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.drawImage(0,0,*m_unmergedCopy);
+ p.end();
+
+ delete m_unmergedCopy;
+ m_unmergedCopy = 0;
+}
+
+QImage *QBlittablePixmapData::overlay()
+{
+ if (!m_rasterOverlay||
+ m_rasterOverlay->size() != QSize(w,h)){
+ m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied);
+ m_rasterOverlay->fill(0x00000000);
+ uint color = (qrand() % 11)+7;
+ m_overlayColor = QColor(Qt::GlobalColor(color));
+ m_overlayColor.setAlpha(0x88);
+
+ }
+ return m_rasterOverlay;
+}
+
+void QBlittablePixmapData::markRasterOverlayImpl(const QRectF &rect)
+{
+ if (!showRasterOverlay)
+ return;
+ QRectF transformationRect = clipAndTransformRect(rect);
+ if(!transformationRect.isEmpty()) {
+ QPainter p(overlay());
+ p.setBrush(m_overlayColor);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(transformationRect,QBrush(m_overlayColor));
+ }
+}
+
+void QBlittablePixmapData::unmarkRasterOverlayImpl(const QRectF &rect)
+{
+ if (!showRasterOverlay)
+ return;
+ QRectF transformationRect = clipAndTransformRect(rect);
+ if (!transformationRect.isEmpty()) {
+ QPainter p(overlay());
+ QColor color(0x00,0x00,0x00,0x00);
+ p.setBrush(color);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(transformationRect,QBrush(color));
+ }
+}
+
+QRectF QBlittablePixmapData::clipAndTransformRect(const QRectF &rect) const
+{
+ QRectF transformationRect = rect;
+ paintEngine();
+ if (m_engine->state()) {
+ transformationRect = m_engine->state()->matrix.mapRect(rect);
+ const QClipData *clipData = m_engine->clip();
+ if (clipData) {
+ if (clipData->hasRectClip) {
+ transformationRect &= clipData->clipRect;
+ } else if (clipData->hasRegionClip) {
+ const QVector<QRect> rects = clipData->clipRegion.rects();
+ for (int i = 0; i < rects.size(); i++) {
+ transformationRect &= rects.at(i);
+ }
+ }
+ }
+ }
+ return transformationRect;
+}
+
+#endif //QT_BLITTER_RASTEROVERLAY
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_BLITTABLE
diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h
new file mode 100644
index 0000000000..55b5618d65
--- /dev/null
+++ b/src/gui/image/qpixmap_blitter_p.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAP_BLITTER_P_H
+#define QPIXMAP_BLITTER_P_H
+
+#include <private/qpixmapdata_p.h>
+#include <private/qpaintengine_blitter_p.h>
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QBlittablePixmapData : public QPixmapData
+{
+// Q_DECLARE_PRIVATE(QBlittablePixmapData);
+public:
+ QBlittablePixmapData();
+ ~QBlittablePixmapData();
+
+ virtual QBlittable *createBlittable(const QSize &size) const = 0;
+ QBlittable *blittable() const;
+ void setBlittable(QBlittable *blittable);
+
+ void resize(int width, int height);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+ void fill(const QColor &color);
+ QImage *buffer();
+ QImage toImage() const;
+ bool hasAlphaChannel() const;
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+
+ QPaintEngine *paintEngine() const;
+
+ void markRasterOverlay(const QRectF &);
+ void markRasterOverlay(const QPointF &, const QTextItem &);
+ void markRasterOverlay(const QVectorPath &);
+ void markRasterOverlay(const QRect *rects, int rectCount);
+ void markRasterOverlay(const QRectF *rects, int rectCount);
+ void unmarkRasterOverlay(const QRectF &);
+
+#ifdef QT_BLITTER_RASTEROVERLAY
+ void mergeOverlay();
+ void unmergeOverlay();
+ QImage *overlay();
+
+#endif //QT_BLITTER_RASTEROVERLAY
+protected:
+ QBlitterPaintEngine *m_engine;
+ QBlittable *m_blittable;
+
+#ifdef QT_BLITTER_RASTEROVERLAY
+ QImage *m_rasterOverlay;
+ QImage *m_unmergedCopy;
+ QColor m_overlayColor;
+
+ void markRasterOverlayImpl(const QRectF &);
+ void unmarkRasterOverlayImpl(const QRectF &);
+ QRectF clipAndTransformRect(const QRectF &) const;
+#endif //QT_BLITTER_RASTEROVERLAY
+
+};
+
+inline void QBlittablePixmapData::markRasterOverlay(const QRectF &rect)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ markRasterOverlayImpl(rect);
+#else
+ Q_UNUSED(rect)
+#endif
+}
+
+inline void QBlittablePixmapData::markRasterOverlay(const QVectorPath &path)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ markRasterOverlayImpl(path.convertToPainterPath().boundingRect());
+#else
+ Q_UNUSED(path)
+#endif
+}
+
+inline void QBlittablePixmapData::markRasterOverlay(const QPointF &pos, const QTextItem &ti)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ QFontMetricsF fm(ti.font());
+ QRectF rect = fm.tightBoundingRect(ti.text());
+ rect.moveBottomLeft(pos);
+ markRasterOverlay(rect);
+#else
+ Q_UNUSED(pos)
+ Q_UNUSED(ti)
+#endif
+}
+
+inline void QBlittablePixmapData::markRasterOverlay(const QRect *rects, int rectCount)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ for (int i = 0; i < rectCount; i++) {
+ markRasterOverlay(rects[i]);
+ }
+#else
+ Q_UNUSED(rects)
+ Q_UNUSED(rectCount)
+#endif
+}
+inline void QBlittablePixmapData::markRasterOverlay(const QRectF *rects, int rectCount)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ for (int i = 0; i < rectCount; i++) {
+ markRasterOverlay(rects[i]);
+ }
+#else
+ Q_UNUSED(rects)
+ Q_UNUSED(rectCount)
+#endif
+}
+
+inline void QBlittablePixmapData::unmarkRasterOverlay(const QRectF &rect)
+{
+#ifdef QT_BLITTER_RASTEROVERLAY
+ unmarkRasterOverlayImpl(rect);
+#else
+ Q_UNUSED(rect)
+#endif
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_BLITTABLE
+#endif // QPIXMAP_BLITTER_P_H
diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp
index bbddd60156..72e2aa6e04 100644
--- a/src/gui/image/qpixmap_mac.cpp
+++ b/src/gui/image/qpixmap_mac.cpp
@@ -413,7 +413,11 @@ void QMacPixmapData::fill(const QColor &fillColor)
*(dptr + i) = colr;
}
}
- macSetHasAlpha(fillColor.alpha() != 255);
+
+ // If we had an alpha channel from before, don't
+ // switch it off. Only go from no alpha to alpha:
+ if (fillColor.alpha() != 255)
+ macSetHasAlpha(true);
}
QPixmap QMacPixmapData::alphaChannel() const
diff --git a/src/gui/image/qpixmap_qpa.cpp b/src/gui/image/qpixmap_qpa.cpp
new file mode 100644
index 0000000000..61be2169d0
--- /dev/null
+++ b/src/gui/image/qpixmap_qpa.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpixmap.h>
+#include <private/qgraphicssystem_p.h>
+#include <private/qapplication_p.h>
+
+QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
+{
+ return QApplicationPrivate::platformIntegration()->grabWindow(window, x, y, w, h);
+}
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 368600f4f5..1e7ff04504 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -208,7 +208,13 @@ void QRasterPixmapData::fill(const QColor &color)
else
#endif
toFormat = QImage::Format_ARGB32_Premultiplied;
- image = QImage(image.width(), image.height(), toFormat);
+
+ if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
+ image.detach();
+ image.d->format = toFormat;
+ } else {
+ image = QImage(image.width(), image.height(), toFormat);
+ }
}
switch (image.format()) {
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 674c09f309..bc468cb7ec 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -310,7 +310,7 @@ static int defaultScreen = -1;
QPixmap member functions
*****************************************************************************/
-static int qt_pixmap_serial = 0;
+QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0);
int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
QX11PixmapData::QX11PixmapData(PixelType type)
@@ -327,7 +327,7 @@ QPixmapData *QX11PixmapData::createCompatiblePixmapData() const
void QX11PixmapData::resize(int width, int height)
{
- setSerialNumber(++qt_pixmap_serial);
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
w = width;
h = height;
@@ -410,7 +410,7 @@ struct QX11AlphaDetector
void QX11PixmapData::fromImage(const QImage &img,
Qt::ImageConversionFlags flags)
{
- setSerialNumber(++qt_pixmap_serial);
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
w = img.width();
h = img.height();
@@ -2013,7 +2013,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform,
x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(X11->display, xinfo.screen()),
w, h, d);
- x11Data->setSerialNumber(++qt_pixmap_serial);
+ x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
#ifndef QT_NO_XRENDER
if (X11->use_xrender) {
@@ -2264,7 +2264,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data);
- setSerialNumber(++qt_pixmap_serial);
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
flags &= ~Uninitialized;
xinfo = x11Data->xinfo;
@@ -2384,7 +2384,7 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode)
}
QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType);
- data->setSerialNumber(++qt_pixmap_serial);
+ data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
data->flags = QX11PixmapData::Readonly;
data->share_mode = mode;
data->w = width;
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 7699344bd4..5c05c28cab 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -75,7 +75,8 @@ public:
};
#endif
enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass,
- OpenGLClass, OpenVGClass, RuntimeClass, CustomClass = 1024 };
+ OpenGLClass, OpenVGClass, RuntimeClass, BlitterClass,
+ CustomClass = 1024 };
QPixmapData(PixelType pixelType, int classId);
virtual ~QPixmapData();
diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp
index e94c6ab8d6..ec53dcb9c1 100644
--- a/src/gui/image/qpixmapdatafactory.cpp
+++ b/src/gui/image/qpixmapdatafactory.cpp
@@ -53,6 +53,9 @@
#ifdef Q_WS_MAC
# include <private/qpixmap_mac_p.h>
#endif
+#ifdef Q_WS_QPA
+# include <private/qpixmap_raster_p.h>
+#endif
#ifdef Q_OS_SYMBIAN
# include <private/qpixmap_s60_p.h>
#endif
@@ -82,8 +85,10 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type)
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
+#elif defined(Q_WS_QPA)
+ return new QRasterPixmapData(type);
#elif defined(Q_OS_SYMBIAN)
- return new QS60PixmapData(type);
+ return new QS60PixmapData(type);
#else
#error QSimplePixmapDataFactory::create() not implemented
#endif
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 31d12fe378..a9aad51859 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -100,6 +100,7 @@ public:
float gamma;
int quality;
QString description;
+ QStringList readTexts;
png_struct *png_ptr;
png_info *info_ptr;
@@ -358,7 +359,6 @@ static void CALLBACK_CALL_TYPE qt_png_warning(png_structp /*png_ptr*/, png_const
}
#endif
-
/*!
\internal
*/
@@ -401,25 +401,20 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader()
while (num_text--) {
QString key, value;
-#if defined(PNG_iTXt_SUPPORTED) && !defined(QT_NO_TEXTCODEC)
- if (text_ptr->lang) {
- QTextCodec *codec = QTextCodec::codecForName(text_ptr->lang);
- if (codec) {
- key = codec->toUnicode(text_ptr->lang_key);
- value = codec->toUnicode(QByteArray(text_ptr->text, text_ptr->itxt_length));
- } else {
- key = QString::fromLatin1(text_ptr->key);
- value = QString::fromLatin1(QByteArray(text_ptr->text, int(text_ptr->text_length)));
- }
+ key = QString::fromLatin1(text_ptr->key);
+#if defined(PNG_iTXt_SUPPORTED)
+ if (text_ptr->itxt_length) {
+ value = QString::fromUtf8(text_ptr->text, int(text_ptr->itxt_length));
} else
#endif
{
- key = QString::fromLatin1(text_ptr->key);
value = QString::fromLatin1(QByteArray(text_ptr->text, int(text_ptr->text_length)));
}
if (!description.isEmpty())
description += QLatin1String("\n\n");
description += key + QLatin1String(": ") + value.simplified();
+ readTexts.append(key);
+ readTexts.append(value);
text_ptr++;
}
#endif
@@ -497,25 +492,8 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)
outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr));
outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr));
-#ifndef QT_NO_IMAGE_TEXT
- png_textp text_ptr;
- int num_text=0;
- png_get_text(png_ptr,info_ptr,&text_ptr,&num_text);
- while (num_text--) {
- outImage->setText(text_ptr->key,0,QString::fromAscii(text_ptr->text));
- text_ptr++;
- }
-
- foreach (const QString &pair, description.split(QLatin1String("\n\n"))) {
- int index = pair.indexOf(QLatin1Char(':'));
- if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
- outImage->setText(QLatin1String("Description"), pair.simplified());
- } else {
- QString key = pair.left(index);
- outImage->setText(key, pair.mid(index + 2).simplified());
- }
- }
-#endif
+ for (int i = 0; i < readTexts.size()-1; i+=2)
+ outImage->setText(readTexts.at(i), readTexts.at(i+1));
state = ReadingEnd;
png_read_end(png_ptr, end_info);
@@ -647,29 +625,40 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
return;
png_textp text_ptr = new png_text[text.size()];
+ qMemSet(text_ptr, 0, text.size() * sizeof(png_text));
QMap<QString, QString>::ConstIterator it = text.constBegin();
int i = 0;
while (it != text.constEnd()) {
- QString t = it.value();
- if (t.length() < 40)
- text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE;
- else
- text_ptr[i].compression = PNG_TEXT_COMPRESSION_zTXt;
text_ptr[i].key = qstrdup(it.key().left(79).toLatin1().constData());
+ bool noCompress = (it.value().length() < 40);
-#ifndef PNG_iTXt_SUPPORTED
- QByteArray value = it.value().toLatin1();
- text_ptr[i].text = qstrdup(value.constData());
- text_ptr[i].text_length = value.size();
-#else
- QByteArray value = it.value().toUtf8();
- text_ptr[i].text = qstrdup(value.constData());
- text_ptr[i].text_length = 0;
- text_ptr[i].itxt_length = value.size();
- text_ptr[i].lang = const_cast<char*>("UTF-8");
- text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
+#ifdef PNG_iTXt_SUPPORTED
+ bool needsItxt = false;
+ foreach(const QChar c, it.value()) {
+ uchar ch = c.cell();
+ if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) {
+ needsItxt = true;
+ break;
+ }
+ }
+
+ if (needsItxt) {
+ text_ptr[i].compression = noCompress ? PNG_ITXT_COMPRESSION_NONE : PNG_ITXT_COMPRESSION_zTXt;
+ QByteArray value = it.value().toUtf8();
+ text_ptr[i].text = qstrdup(value.constData());
+ text_ptr[i].itxt_length = value.size();
+ text_ptr[i].lang = const_cast<char*>("UTF-8");
+ text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
+ }
+ else
#endif
+ {
+ text_ptr[i].compression = noCompress ? PNG_TEXT_COMPRESSION_NONE : PNG_TEXT_COMPRESSION_zTXt;
+ QByteArray value = it.value().toLatin1();
+ text_ptr[i].text = qstrdup(value.constData());
+ text_ptr[i].text_length = value.size();
+ }
++i;
++it;
}
diff --git a/src/gui/image/qtiffhandler.cpp b/src/gui/image/qtiffhandler.cpp
index c93009f128..5939ad5830 100644
--- a/src/gui/image/qtiffhandler.cpp
+++ b/src/gui/image/qtiffhandler.cpp
@@ -196,9 +196,12 @@ bool QTiffHandler::read(QImage *image)
uint16 bitPerSample;
if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample))
bitPerSample = 1;
+ uint16 samplesPerPixel; // they may be e.g. grayscale with 2 samples per pixel
+ if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel))
+ samplesPerPixel = 1;
bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE;
- if (grayscale && bitPerSample == 1) {
+ if (grayscale && bitPerSample == 1 && samplesPerPixel == 1) {
if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono)
*image = QImage(width, height, QImage::Format_Mono);
QVector<QRgb> colortable(2);
@@ -220,7 +223,7 @@ bool QTiffHandler::read(QImage *image)
}
}
} else {
- if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) {
+ if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) {
if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8)
*image = QImage(width, height, QImage::Format_Indexed8);
if (!image->isNull()) {
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index a02b3ff787..ffad75bb6d 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -54,12 +54,6 @@
#include "qplatformdefs.h"
#endif
-#include <stdlib.h>
-
-#if defined(Q_OS_WINCE)
-#include "qguifunctions_wince.h"
-#endif
-
QT_BEGIN_NAMESPACE
static quint64 xpmHash(const QString &str)
@@ -751,27 +745,15 @@ static const struct XPMRGBData {
{ QRGB(139,139, 0), "yellow4" },
{ QRGB(154,205, 50), "yellowgreen" } };
-#if defined(Q_C_CALLBACKS)
-extern "C" {
-#endif
-static int rgb_cmp(const void *d1, const void *d2)
-{
- return qstricmp(((XPMRGBData *)d1)->name, ((XPMRGBData *)d2)->name);
-}
-#if defined(Q_C_CALLBACKS)
-}
-#endif
+inline bool operator<(const char *name, const XPMRGBData &data)
+{ return qstrcmp(name, data.name) < 0; }
+inline bool operator<(const XPMRGBData &data, const char *name)
+{ return qstrcmp(data.name, name) < 0; }
-static bool qt_get_named_xpm_rgb(const char *name_no_space, QRgb *rgb)
+static inline bool qt_get_named_xpm_rgb(const char *name_no_space, QRgb *rgb)
{
- XPMRGBData x;
- x.name = name_no_space;
- // Function bsearch() is supposed to be
- // void *bsearch(const void *key, const void *base, ...
- // So why (char*)? Are there broken bsearch() declarations out there?
- XPMRGBData *r = (XPMRGBData *)bsearch((char *)&x, (char *)xpmRgbTbl, xpmRgbTblSize,
- sizeof(XPMRGBData), rgb_cmp);
- if (r) {
+ const XPMRGBData *r = qBinaryFind(xpmRgbTbl, xpmRgbTbl + xpmRgbTblSize, name_no_space);
+ if (r != xpmRgbTbl + xpmRgbTblSize) {
*rgb = r->value;
return true;
} else {
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
index 02e3e57024..d4394380dc 100644
--- a/src/gui/inputmethod/inputmethod.pri
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -19,7 +19,7 @@ embedded {
HEADERS += inputmethod/qwsinputcontext_p.h
SOURCES += inputmethod/qwsinputcontext_qws.cpp
}
-mac:!embedded {
+mac:!embedded:!qpa {
HEADERS += inputmethod/qmacinputcontext_p.h
SOURCES += inputmethod/qmacinputcontext_mac.cpp
}
diff --git a/src/gui/itemviews/qabstractitemdelegate.cpp b/src/gui/itemviews/qabstractitemdelegate.cpp
index f929e2eefe..478c4747ef 100644
--- a/src/gui/itemviews/qabstractitemdelegate.cpp
+++ b/src/gui/itemviews/qabstractitemdelegate.cpp
@@ -362,7 +362,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
case QEvent::ToolTip: {
QHelpEvent *he = static_cast<QHelpEvent*>(event);
QVariant tooltip = index.data(Qt::ToolTipRole);
- if (qVariantCanConvert<QString>(tooltip)) {
+ if (tooltip.canConvert<QString>()) {
QToolTip::showText(he->globalPos(), tooltip.toString(), view);
return true;
}
@@ -376,7 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
case QEvent::WhatsThis: {
QHelpEvent *he = static_cast<QHelpEvent*>(event);
QVariant whatsthis = index.data(Qt::WhatsThisRole);
- if (qVariantCanConvert<QString>(whatsthis)) {
+ if (whatsthis.canConvert<QString>()) {
QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view);
return true;
}
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index 37507ddf78..4dd0aa31d8 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -62,6 +62,9 @@
#include <qaccessible.h>
#endif
#include <private/qsoftkeymanager_p.h>
+#ifndef QT_NO_GESTURE
+# include <qscroller.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -79,6 +82,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate()
pressedAlreadySelected(false),
viewportEnteredNeeded(false),
state(QAbstractItemView::NoState),
+ stateBeforeAnimation(QAbstractItemView::NoState),
editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed),
lastTrigger(QAbstractItemView::NoEditTriggers),
tabKeyNavigation(false),
@@ -190,6 +194,37 @@ void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index
}
}
+// stores and restores the selection and current item when flicking
+void QAbstractItemViewPrivate::_q_scrollerStateChanged()
+{
+ Q_Q(QAbstractItemView);
+
+ if (QScroller *scroller = QScroller::scroller(viewport)) {
+ switch (scroller->state()) {
+ case QScroller::Pressed:
+ // store the current selection in case we start scrolling
+ if (q->selectionModel()) {
+ oldSelection = q->selectionModel()->selection();
+ oldCurrent = q->selectionModel()->currentIndex();
+ }
+ break;
+
+ case QScroller::Dragging:
+ // restore the old selection if we really start scrolling
+ if (q->selectionModel()) {
+ q->selectionModel()->select(oldSelection, QItemSelectionModel::ClearAndSelect);
+ q->selectionModel()->setCurrentIndex(oldCurrent, QItemSelectionModel::NoUpdate);
+ }
+ // fall through
+
+ default:
+ oldSelection = QItemSelection();
+ oldCurrent = QModelIndex();
+ break;
+ }
+ }
+}
+
/*!
\class QAbstractItemView
@@ -661,7 +696,7 @@ void QAbstractItemView::setModel(QAbstractItemModel *model)
"QAbstractItemView::setModel",
"A model should return the exact same index "
"(including its internal id/pointer) when asked for it twice in a row.");
- Q_ASSERT_X(d->model->index(0,0).parent() == QModelIndex(),
+ Q_ASSERT_X(!d->model->index(0,0).parent().isValid(),
"QAbstractItemView::setModel",
"The parent of a top level index should be invalid");
@@ -1045,10 +1080,12 @@ void QAbstractItemView::reset()
{
Q_D(QAbstractItemView);
d->delayedReset.stop(); //make sure we stop the timer
- QList<QEditorInfo>::const_iterator it = d->editors.constBegin();
- for (; it != d->editors.constEnd(); ++it)
- d->releaseEditor(it->editor);
- d->editors.clear();
+ foreach (const QEditorInfo &info, d->indexEditorHash) {
+ if (info.widget)
+ d->releaseEditor(info.widget.data());
+ }
+ d->editorIndexHash.clear();
+ d->indexEditorHash.clear();
d->persistent.clear();
d->currentIndexSet = false;
setState(NoState);
@@ -1622,6 +1659,11 @@ bool QAbstractItemView::viewportEvent(QEvent *event)
case QEvent::WindowDeactivate:
d->viewport->update();
break;
+ case QEvent::ScrollPrepare:
+ executeDelayedItemsLayout();
+ connect(QScroller::scroller(d->viewport), SIGNAL(stateChanged(QScroller::State)), this, SLOT(_q_scrollerStateChanged()), Qt::UniqueConnection);
+ break;
+
default:
break;
}
@@ -2342,7 +2384,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
case Qt::Key_Return:
// Propagate the enter if you couldn't edit the item and there are no
// current editors (if there are editors, the event was most likely propagated from it).
- if (!edit(currentIndex(), EditKeyPressed, event) && d->editors.isEmpty())
+ if (!edit(currentIndex(), EditKeyPressed, event) && d->editorIndexHash.isEmpty())
event->ignore();
break;
#else
@@ -2527,7 +2569,7 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve
if (!d->isIndexValid(index))
return false;
- if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).editor.data())) {
+ if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).widget.data())) {
if (w->focusPolicy() == Qt::NoFocus)
return false;
w->setFocus();
@@ -2587,15 +2629,15 @@ void QAbstractItemView::updateEditorData()
void QAbstractItemView::updateEditorGeometries()
{
Q_D(QAbstractItemView);
- if(d->editors.isEmpty())
+ if(d->editorIndexHash.isEmpty())
return;
QStyleOptionViewItemV4 option = d->viewOptionsV4();
- QList<QEditorInfo>::iterator it = d->editors.begin();
+ QEditorIndexHash::iterator it = d->editorIndexHash.begin();
QWidgetList editorsToRelease;
QWidgetList editorsToHide;
- while (it != d->editors.end()) {
- QModelIndex index = it->index;
- QWidget *editor = it->editor;
+ while (it != d->editorIndexHash.end()) {
+ QModelIndex index = it.value();
+ QWidget *editor = it.key();
if (index.isValid() && editor) {
option.rect = visualRect(index);
if (option.rect.isValid()) {
@@ -2608,13 +2650,14 @@ void QAbstractItemView::updateEditorGeometries()
}
++it;
} else {
- it = d->editors.erase(it);
+ d->indexEditorHash.remove(it.value());
+ it = d->editorIndexHash.erase(it);
editorsToRelease << editor;
}
}
//we hide and release the editor outside of the loop because it might change the focus and try
- //to change the d->editors list.
+ //to change the editors hashes.
for (int i = 0; i < editorsToHide.count(); ++i) {
editorsToHide.at(i)->hide();
}
@@ -2954,7 +2997,7 @@ int QAbstractItemView::sizeHintForRow(int row) const
{
Q_D(const QAbstractItemView);
- if (row < 0 || row >= d->model->rowCount() || !model())
+ if (row < 0 || row >= d->model->rowCount(d->root))
return -1;
ensurePolished();
@@ -2965,8 +3008,8 @@ int QAbstractItemView::sizeHintForRow(int row) const
QModelIndex index;
for (int c = 0; c < colCount; ++c) {
index = d->model->index(row, c, d->root);
- if (QWidget *editor = d->editorForIndex(index).editor)
- height = qMax(height, editor->size().height());
+ if (QWidget *editor = d->editorForIndex(index).widget.data())
+ height = qMax(height, editor->height());
int hint = d->delegateForIndex(index)->sizeHint(option, index).height();
height = qMax(height, hint);
}
@@ -2985,7 +3028,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const
{
Q_D(const QAbstractItemView);
- if (column < 0 || column >= d->model->columnCount() || !model())
+ if (column < 0 || column >= d->model->columnCount(d->root))
return -1;
ensurePolished();
@@ -2996,7 +3039,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const
QModelIndex index;
for (int r = 0; r < rows; ++r) {
index = d->model->index(r, column, d->root);
- if (QWidget *editor = d->editorForIndex(index).editor)
+ if (QWidget *editor = d->editorForIndex(index).widget.data())
width = qMax(width, editor->sizeHint().width());
int hint = d->delegateForIndex(index)->sizeHint(option, index).width();
width = qMax(width, hint);
@@ -3032,8 +3075,7 @@ void QAbstractItemView::openPersistentEditor(const QModelIndex &index)
void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
{
Q_D(QAbstractItemView);
- QWidget *editor = d->editorForIndex(index).editor;
- if (editor) {
+ if (QWidget *editor = d->editorForIndex(index).widget.data()) {
if (index == selectionModel()->currentIndex())
closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
d->persistent.remove(editor);
@@ -3097,9 +3139,11 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
QWidget* QAbstractItemView::indexWidget(const QModelIndex &index) const
{
Q_D(const QAbstractItemView);
- if (!d->isIndexValid(index))
- return 0;
- return d->editorForIndex(index).editor;
+ if (d->isIndexValid(index))
+ if (QWidget *editor = d->editorForIndex(index).widget.data())
+ return editor;
+
+ return 0;
}
/*!
@@ -3161,12 +3205,12 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
// Single item changed
Q_D(QAbstractItemView);
if (topLeft == bottomRight && topLeft.isValid()) {
- const QEditorInfo editorInfo = d->editorForIndex(topLeft);
+ const QEditorInfo &editorInfo = d->editorForIndex(topLeft);
//we don't update the edit data if it is static
- if (!editorInfo.isStatic && editorInfo.editor) {
+ if (!editorInfo.isStatic && editorInfo.widget) {
QAbstractItemDelegate *delegate = d->delegateForIndex(topLeft);
if (delegate) {
- delegate->setEditorData(editorInfo.editor, topLeft);
+ delegate->setEditorData(editorInfo.widget.data(), topLeft);
}
}
if (isVisible() && !d->delayedPendingLayout) {
@@ -3240,12 +3284,17 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star
}
// Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes
- for (int i = d->editors.size() - 1; i >= 0; --i) {
- const QModelIndex index = d->editors.at(i).index;
- QWidget *editor = d->editors.at(i).editor;
+ QEditorIndexHash::iterator i = d->editorIndexHash.begin();
+ while (i != d->editorIndexHash.end()) {
+ const QModelIndex index = i.value();
if (index.row() >= start && index.row() <= end && d->model->parent(index) == parent) {
- d->editors.removeAt(i);
- d->releaseEditor(editor);
+ QWidget *editor = i.key();
+ QEditorInfo info = d->indexEditorHash.take(index);
+ i = d->editorIndexHash.erase(i);
+ if (info.widget)
+ d->releaseEditor(editor);
+ } else {
+ ++i;
}
}
}
@@ -3302,17 +3351,20 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par
}
// Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes
- QList<QEditorInfo>::iterator it = editors.begin();
- while (it != editors.end()) {
- QModelIndex index = it->index;
+ QEditorIndexHash::iterator it = editorIndexHash.begin();
+ while (it != editorIndexHash.end()) {
+ QModelIndex index = it.value();
if (index.column() <= start && index.column() >= end && model->parent(index) == parent) {
- QWidget *editor = it->editor;
- it = editors.erase(it);
- releaseEditor(editor);
+ QWidget *editor = it.key();
+ QEditorInfo info = indexEditorHash.take(it.value());
+ it = editorIndexHash.erase(it);
+ if (info.widget)
+ releaseEditor(editor);
} else {
++it;
}
}
+
}
/*!
@@ -3394,7 +3446,7 @@ void QAbstractItemView::currentChanged(const QModelIndex &current, const QModelI
if (previous.isValid()) {
QModelIndex buddy = d->model->buddy(previous);
- QWidget *editor = d->editorForIndex(buddy).editor;
+ QWidget *editor = d->editorForIndex(buddy).widget.data();
if (editor && !d->persistent.contains(editor)) {
commitData(editor);
if (current.row() != previous.row())
@@ -3920,7 +3972,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
const QStyleOptionViewItem &options)
{
Q_Q(QAbstractItemView);
- QWidget *w = editorForIndex(index).editor;
+ QWidget *w = editorForIndex(index).widget.data();
if (!w) {
QAbstractItemDelegate *delegate = delegateForIndex(index);
if (!delegate)
@@ -3951,6 +4003,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
#endif
}
}
+
return w;
}
@@ -3959,11 +4012,11 @@ void QAbstractItemViewPrivate::updateEditorData(const QModelIndex &tl, const QMo
// we are counting on having relatively few editors
const bool checkIndexes = tl.isValid() && br.isValid();
const QModelIndex parent = tl.parent();
- QList<QEditorInfo>::const_iterator it = editors.constBegin();
- for (; it != editors.constEnd(); ++it) {
- QWidget *editor = it->editor;
- const QModelIndex index = it->index;
- if (it->isStatic || editor == 0 || !index.isValid() ||
+ QIndexEditorHash::const_iterator it = indexEditorHash.constBegin();
+ for (; it != indexEditorHash.constEnd(); ++it) {
+ QWidget *editor = it.value().widget.data();
+ const QModelIndex index = it.key();
+ if (it.value().isStatic || !editor || !index.isValid() ||
(checkIndexes
&& (index.row() < tl.row() || index.row() > br.row()
|| index.column() < tl.column() || index.column() > br.column()
@@ -4036,41 +4089,40 @@ void QAbstractItemViewPrivate::checkPersistentEditorFocus()
}
-QEditorInfo QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const
+const QEditorInfo & QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const
{
- QList<QEditorInfo>::const_iterator it = editors.constBegin();
- for (; it != editors.constEnd(); ++it) {
- if (it->index == index)
- return *it;
- }
+ static QEditorInfo nullInfo;
- return QEditorInfo();
+ QIndexEditorHash::const_iterator it = indexEditorHash.find(index);
+ if (it == indexEditorHash.end())
+ return nullInfo;
+
+ return it.value();
}
QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const
{
- QList<QEditorInfo>::const_iterator it = editors.constBegin();
- for (; it != editors.constEnd(); ++it) {
- if (it->editor == editor)
- return it->index;
- }
- return QModelIndex();
+ QEditorIndexHash::const_iterator it = editorIndexHash.find(editor);
+ if (it == editorIndexHash.end())
+ return QModelIndex();
+
+ return it.value();
}
void QAbstractItemViewPrivate::removeEditor(QWidget *editor)
{
- QList<QEditorInfo>::iterator it = editors.begin();
- for (; it != editors.end(); ) {
- if (it->editor == editor)
- it = editors.erase(it);
- else
- ++it;
+ QEditorIndexHash::iterator it = editorIndexHash.find(editor);
+ if (it != editorIndexHash.end())
+ {
+ indexEditorHash.remove(it.value());
+ editorIndexHash.erase(it);
}
}
void QAbstractItemViewPrivate::addEditor(const QModelIndex &index, QWidget *editor, bool isStatic)
{
- editors.append(QEditorInfo(index, editor, isStatic));
+ editorIndexHash.insert(editor, index);
+ indexEditorHash.insert(index, QEditorInfo(editor, isStatic));
}
bool QAbstractItemViewPrivate::sendDelegateEvent(const QModelIndex &index, QEvent *event) const
@@ -4097,13 +4149,13 @@ bool QAbstractItemViewPrivate::openEditor(const QModelIndex &index, QEvent *even
if (!w)
return false;
- if (event)
- QApplication::sendEvent(w->focusProxy() ? w->focusProxy() : w, event);
-
q->setState(QAbstractItemView::EditingState);
w->show();
w->setFocus();
+ if (event)
+ QApplication::sendEvent(w->focusProxy() ? w->focusProxy() : w, event);
+
return true;
}
diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h
index 7043a5f0e6..20cfb87be6 100644
--- a/src/gui/itemviews/qabstractitemview.h
+++ b/src/gui/itemviews/qabstractitemview.h
@@ -359,6 +359,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed())
Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged())
Q_PRIVATE_SLOT(d_func(), void _q_headerDataChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_scrollerStateChanged())
friend class QTreeViewPrivate; // needed to compile with MSVC
friend class QAccessibleItemRow;
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index da9537de15..6041e5e177 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -70,22 +70,18 @@
QT_BEGIN_NAMESPACE
-struct QEditorInfo
-{
- QEditorInfo() : isStatic(false)
- {
- }
-
- QEditorInfo(const QPersistentModelIndex &i, QWidget *e, bool b) : index(i), editor(e), isStatic(b)
- {
- }
-
- QPersistentModelIndex index;
- QPointer<QWidget> editor;
- bool isStatic; //true when called from setIndexWidget
+struct QEditorInfo {
+ QEditorInfo(QWidget *e, bool s): widget(QWeakPointer<QWidget>(e)), isStatic(s) {}
+ QEditorInfo(): isStatic(false) {}
+ QWeakPointer<QWidget> widget;
+ bool isStatic;
};
+// Fast associativity between Persistent editors and indices.
+typedef QHash<QWidget *, QPersistentModelIndex> QEditorIndexHash;
+typedef QHash<QPersistentModelIndex, QEditorInfo> QIndexEditorHash;
+
typedef QPair<QRect, QModelIndex> QItemViewPaintPair;
typedef QList<QItemViewPaintPair> QItemViewPaintPairs;
@@ -118,6 +114,7 @@ public:
virtual void _q_modelDestroyed();
virtual void _q_layoutChanged();
void _q_headerDataChanged() { doDelayedItemsLayout(); }
+ void _q_scrollerStateChanged();
void fetchMore();
@@ -135,8 +132,9 @@ public:
}
void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;}
-
- bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
+#ifndef QT_NO_DRAGANDDROP
+ virtual bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
+#endif
bool droppingOnItself(QDropEvent *event, const QModelIndex &index);
QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options);
@@ -247,9 +245,9 @@ public:
: q->horizontalOffset(), q->verticalOffset());
}
- QEditorInfo editorForIndex(const QModelIndex &index) const;
+ const QEditorInfo &editorForIndex(const QModelIndex &index) const;
inline bool hasEditor(const QModelIndex &index) const {
- return editorForIndex(index).editor != 0;
+ return indexEditorHash.find(index) != indexEditorHash.constEnd();
}
QModelIndex indexForEditor(QWidget *editor) const;
@@ -352,7 +350,8 @@ public:
QAbstractItemView::SelectionMode selectionMode;
QAbstractItemView::SelectionBehavior selectionBehavior;
- QList<QEditorInfo> editors;
+ QEditorIndexHash editorIndexHash;
+ QIndexEditorHash indexEditorHash;
QSet<QWidget*> persistent;
QWidget *currentlyCommittingEditor;
@@ -367,6 +366,7 @@ public:
bool viewportEnteredNeeded;
QAbstractItemView::State state;
+ QAbstractItemView::State stateBeforeAnimation;
QAbstractItemView::EditTriggers editTriggers;
QAbstractItemView::EditTrigger lastTrigger;
@@ -415,6 +415,12 @@ public:
QAbstractItemView::ScrollMode verticalScrollMode;
QAbstractItemView::ScrollMode horizontalScrollMode;
+#ifndef QT_NO_GESTURES
+ // the selection before the last mouse down. In case we have to restore it for scrolling
+ QItemSelection oldSelection;
+ QModelIndex oldCurrent;
+#endif
+
bool currentIndexSet;
bool wrapItemText;
diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp
index 368b351709..34ca7dff50 100644
--- a/src/gui/itemviews/qabstractproxymodel.cpp
+++ b/src/gui/itemviews/qabstractproxymodel.cpp
@@ -45,6 +45,9 @@
#include "qitemselectionmodel.h"
#include <private/qabstractproxymodel_p.h>
+#include <QtCore/QSize>
+#include <QtCore/QStringList>
+
QT_BEGIN_NAMESPACE
@@ -118,12 +121,15 @@ QAbstractProxyModel::~QAbstractProxyModel()
void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
Q_D(QAbstractProxyModel);
- if (d->model)
+ if (d->model) {
disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
+ }
if (sourceModel) {
d->model = sourceModel;
connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed()));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData()));
} else {
d->model = QAbstractItemModelPrivate::staticEmptyModel();
}
@@ -270,6 +276,15 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu
/*!
\reimp
*/
+bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles)
+{
+ Q_D(QAbstractProxyModel);
+ return d->model->setItemData(mapToSource(index), roles);
+}
+
+/*!
+ \reimp
+ */
bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
Q_D(QAbstractProxyModel);
@@ -284,6 +299,109 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation
return d->model->setHeaderData(sourceSection, orientation, value, role);
}
+/*!
+ \reimp
+ */
+QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const
+{
+ Q_D(const QAbstractProxyModel);
+ return mapFromSource(d->model->buddy(mapToSource(index)));
+}
+
+/*!
+ \reimp
+ */
+bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const
+{
+ Q_D(const QAbstractProxyModel);
+ return d->model->canFetchMore(mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+void QAbstractProxyModel::fetchMore(const QModelIndex &parent)
+{
+ Q_D(QAbstractProxyModel);
+ d->model->fetchMore(mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+void QAbstractProxyModel::sort(int column, Qt::SortOrder order)
+{
+ Q_D(QAbstractProxyModel);
+ d->model->sort(column, order);
+}
+
+/*!
+ \reimp
+ */
+QSize QAbstractProxyModel::span(const QModelIndex &index) const
+{
+ Q_D(const QAbstractProxyModel);
+ return d->model->span(mapToSource(index));
+}
+
+/*!
+ \reimp
+ */
+bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const
+{
+ Q_D(const QAbstractProxyModel);
+ return d->model->hasChildren(mapToSource(parent));
+}
+
+/*!
+ \reimp
+ */
+QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const
+{
+ Q_D(const QAbstractProxyModel);
+ QModelIndexList list;
+ foreach(const QModelIndex &index, indexes)
+ list << mapToSource(index);
+ return d->model->mimeData(list);
+}
+
+/*!
+ \reimp
+ */
+QStringList QAbstractProxyModel::mimeTypes() const
+{
+ Q_D(const QAbstractProxyModel);
+ return d->model->mimeTypes();
+}
+
+/*!
+ \reimp
+ */
+Qt::DropActions QAbstractProxyModel::supportedDropActions() const
+{
+ Q_D(const QAbstractProxyModel);
+ return d->model->supportedDropActions();
+}
+
+/*
+ \since 4.8
+
+ This slot is called just after the internal data of a model is cleared
+ while it is being reset.
+
+ This slot is provided the convenience of subclasses of concrete proxy
+ models, such as subclasses of QSortFilterProxyModel which maintain extra
+ data.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 10
+
+ \sa modelAboutToBeReset(), modelReset()
+*/
+void QAbstractProxyModel::resetInternalData()
+{
+
+}
+
QT_END_NAMESPACE
#include "moc_qabstractproxymodel.cpp"
diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h
index 256433ae24..6e485aec12 100644
--- a/src/gui/itemviews/qabstractproxymodel.h
+++ b/src/gui/itemviews/qabstractproxymodel.h
@@ -81,8 +81,23 @@ public:
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+ bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles);
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole);
+ QModelIndex buddy(const QModelIndex &index) const;
+ bool canFetchMore(const QModelIndex &parent) const;
+ void fetchMore(const QModelIndex &parent);
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+ QSize span(const QModelIndex &index) const;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
+
+ QMimeData* mimeData(const QModelIndexList &indexes) const;
+ QStringList mimeTypes() const;
+ Qt::DropActions supportedDropActions() const;
+
+protected Q_SLOTS:
+ void resetInternalData();
+
protected:
QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent);
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index 7901dcab4b..ae93054cf3 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -234,7 +234,7 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper();
QString key;
- if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink())
+ if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink() && fileExtension != QLatin1String(".ICO"))
key = QLatin1String("qt_") + fileExtension;
QPixmap pixmap;
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index c8576709b9..6359f0b438 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -2105,7 +2105,7 @@ void QHeaderView::paintEvent(QPaintEvent *e)
QVariant variant = d->model->headerData(logical, d->orientation,
Qt::FontRole);
- if (variant.isValid() && qVariantCanConvert<QFont>(variant)) {
+ if (variant.isValid() && variant.canConvert<QFont>()) {
QFont sectionFont = qvariant_cast<QFont>(variant);
painter.setFont(sectionFont);
}
@@ -2485,13 +2485,13 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical
opt.icon = qvariant_cast<QPixmap>(variant);
QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
Qt::ForegroundRole);
- if (qVariantCanConvert<QBrush>(foregroundBrush))
+ if (foregroundBrush.canConvert<QBrush>())
opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));
QPointF oldBO = painter->brushOrigin();
QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation,
Qt::BackgroundRole);
- if (qVariantCanConvert<QBrush>(backgroundBrush)) {
+ if (backgroundBrush.canConvert<QBrush>()) {
opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
painter->setBrushOrigin(opt.rect.topLeft());
@@ -2552,7 +2552,7 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const
QVariant var = d->model->headerData(logicalIndex, d->orientation,
Qt::FontRole);
QFont fnt;
- if (var.isValid() && qVariantCanConvert<QFont>(var))
+ if (var.isValid() && var.canConvert<QFont>())
fnt = qvariant_cast<QFont>(var);
else
fnt = font();
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index e0612738ae..f211438dcd 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -850,7 +850,7 @@ void QItemDelegate::drawBackground(QPainter *painter,
painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
} else {
QVariant value = index.data(Qt::BackgroundRole);
- if (qVariantCanConvert<QBrush>(value)) {
+ if (value.canConvert<QBrush>()) {
QPointF oldBO = painter->brushOrigin();
painter->setBrushOrigin(option.rect.topLeft());
painter->fillRect(option.rect, qvariant_cast<QBrush>(value));
@@ -1278,7 +1278,8 @@ bool QItemDelegate::editorEvent(QEvent *event,
// make sure that we have the right event type
if ((event->type() == QEvent::MouseButtonRelease)
- || (event->type() == QEvent::MouseButtonDblClick)) {
+ || (event->type() == QEvent::MouseButtonDblClick)
+ || (event->type() == QEvent::MouseButtonPress)) {
QRect checkRect = check(option, option.rect, Qt::Checked);
QRect emptyRect;
doLayout(option, &checkRect, &emptyRect, &emptyRect, false);
@@ -1287,7 +1288,8 @@ bool QItemDelegate::editorEvent(QEvent *event,
return false;
// eat the double click events inside the check rect
- if (event->type() == QEvent::MouseButtonDblClick)
+ if ((event->type() == QEvent::MouseButtonPress)
+ || (event->type() == QEvent::MouseButtonDblClick))
return true;
} else if (event->type() == QEvent::KeyPress) {
@@ -1326,7 +1328,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
// set foreground brush
value = index.data(Qt::ForegroundRole);
- if (qVariantCanConvert<QBrush>(value))
+ if (value.canConvert<QBrush>())
opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
return opt;
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index 73c562e882..27a4a402e2 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -212,6 +212,7 @@ bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const
{
return (isValid() && other.isValid()
&& parent() == other.parent()
+ && model() == other.model()
&& ((top() <= other.top() && bottom() >= other.top())
|| (top() >= other.top() && top() <= other.bottom()))
&& ((left() <= other.left() && right() >= other.left())
@@ -508,7 +509,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel
void QItemSelection::split(const QItemSelectionRange &range,
const QItemSelectionRange &other, QItemSelection *result)
{
- if (range.parent() != other.parent())
+ if (range.parent() != other.parent() || range.model() != other.model())
return;
QModelIndex parent = other.parent();
@@ -634,6 +635,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
}
QItemSelection deselected;
+ QItemSelection newParts;
QItemSelection::iterator it = ranges.begin();
while (it != ranges.end()) {
if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range
@@ -659,13 +661,20 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare
deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight()));
*it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent()));
++it;
- } else {
- if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing)
- deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()),
- model->index(end, it->left(), it->parent())));
+ } else if (it->top() < start && end < it->bottom()) { // Middle intersection
+ // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected,
+ // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6].
+ // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection
+ // in ranges.
+ const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()),
+ model->index(end, it->left(), it->parent()));
+ deselected.append(removedRange);
+ QItemSelection::split(*it, removedRange, &newParts);
+ it = ranges.erase(it);
+ } else
++it;
- }
}
+ ranges.append(newParts);
if (!deselected.isEmpty())
emit q->selectionChanged(QItemSelection(), deselected);
diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h
index 11aa0d5600..12b875b8ab 100644
--- a/src/gui/itemviews/qitemselectionmodel.h
+++ b/src/gui/itemviews/qitemselectionmodel.h
@@ -101,6 +101,30 @@ public:
{ return (tl == other.tl && br == other.br); }
inline bool operator!=(const QItemSelectionRange &other) const
{ return !operator==(other); }
+ inline bool operator<(const QItemSelectionRange &other) const
+ {
+ // Comparing parents will compare the models, but if two equivalent ranges
+ // in two different models have invalid parents, they would appear the same
+ if (other.tl.model() == tl.model()) {
+ // parent has to be calculated, so we only do so once.
+ const QModelIndex topLeftParent = tl.parent();
+ const QModelIndex otherTopLeftParent = other.tl.parent();
+ if (topLeftParent == otherTopLeftParent) {
+ if (other.tl.row() == tl.row()) {
+ if (other.tl.column() == tl.column()) {
+ if (other.br.row() == br.row()) {
+ return br.column() < other.br.column();
+ }
+ return br.row() < other.br.row();
+ }
+ return tl.column() < other.tl.column();
+ }
+ return tl.row() < other.tl.row();
+ }
+ return topLeftParent < otherTopLeftParent;
+ }
+ return tl.model() < other.tl.model();
+ }
inline bool isValid() const
{
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 18fa3b98bf..44b45d835d 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -756,10 +756,13 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e
// if the parent is above d->root in the tree, nothing will happen
QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
if (parent == d->root) {
- for (int i = d->hiddenRows.count() - 1; i >= 0; --i) {
- int hiddenRow = d->hiddenRows.at(i).row();
+ QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin();
+ while (it != d->hiddenRows.end()) {
+ int hiddenRow = it->row();
if (hiddenRow >= start && hiddenRow <= end) {
- d->hiddenRows.remove(i);
+ it = d->hiddenRows.erase(it);
+ } else {
+ ++it;
}
}
}
@@ -1033,16 +1036,7 @@ void QListView::paintEvent(QPaintEvent *e)
previousRow = row;
}
- if (const QWidget *widget = d->editorForIndex(*it).editor) {
- QRegion itemGeometry(option.rect);
- QRegion widgetGeometry(widget->geometry());
- painter.save();
- painter.setClipRegion(itemGeometry.subtracted(widgetGeometry));
- d->delegateForIndex(*it)->paint(&painter, option, *it);
- painter.restore();
- } else {
- d->delegateForIndex(*it)->paint(&painter, option, *it);
- }
+ d->delegateForIndex(*it)->paint(&painter, option, *it);
}
#ifndef QT_NO_DRAGANDDROP
@@ -1496,19 +1490,20 @@ void QListView::updateGeometries()
// if the scroll bars are turned off, we resize the contents to the viewport
if (d->movement == Static && !d->isWrapping()) {
- d->layoutChildren(); // we need the viewport size to be updated
+ const QSize maxSize = maximumViewportSize();
if (d->flow == TopToBottom) {
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
- d->setContentsSize(viewport()->width(), contentsSize().height());
+ d->setContentsSize(maxSize.width(), contentsSize().height());
horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway
}
} else { // LeftToRight
if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
- d->setContentsSize(contentsSize().width(), viewport()->height());
+ d->setContentsSize(contentsSize().width(), maxSize.height());
verticalScrollBar()->setRange(0, 0); // we see all the contents anyway
}
}
}
+
}
/*!
@@ -1833,6 +1828,14 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint
else
return QAbstractItemViewPrivate::position(pos, rect, idx);
}
+
+bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
+{
+ if (viewMode == QListView::ListMode && flow == QListView::LeftToRight)
+ return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex);
+ else
+ return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex);
+}
#endif
/*
@@ -1841,12 +1844,12 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint
void QCommonListViewBase::appendHiddenRow(int row)
{
- dd->hiddenRows.append(dd->model->index(row, 0, qq->rootIndex()));
+ dd->hiddenRows.insert(dd->model->index(row, 0, qq->rootIndex()));
}
void QCommonListViewBase::removeHiddenRow(int row)
{
- dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0, qq->rootIndex())));
+ dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex()));
}
void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
@@ -1960,7 +1963,13 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
// ignore by default
event->ignore();
- QModelIndex index = qq->indexAt(event->pos());
+ // can't use indexAt, doesn't account for spacing.
+ QPoint p = event->pos();
+ QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
+ rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
+ const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect);
+ QModelIndex index = intersectVector.count() > 0
+ ? intersectVector.last() : QModelIndex();
dd->hover = index;
if (!dd->droppingOnItself(event, index)
&& dd->canDecode(event)) {
@@ -1968,10 +1977,11 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
if (index.isValid() && dd->showDropIndicator) {
QRect rect = qq->visualRect(index);
dd->dropIndicatorPosition = position(event->pos(), rect, index);
+ // if spacing, should try to draw between items, not just next to item.
switch (dd->dropIndicatorPosition) {
case QAbstractItemView::AboveItem:
if (dd->isIndexDropEnabled(index.parent())) {
- dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height());
+ dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height());
event->accept();
} else {
dd->dropIndicatorRect = QRect();
@@ -1979,7 +1989,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
break;
case QAbstractItemView::BelowItem:
if (dd->isIndexDropEnabled(index.parent())) {
- dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height());
+ dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height());
event->accept();
} else {
dd->dropIndicatorRect = QRect();
@@ -2014,6 +2024,68 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
qq->startAutoScroll();
}
+/*!
+ If the event hasn't already been accepted, determines the index to drop on.
+
+ if (row == -1 && col == -1)
+ // append to this drop index
+ else
+ // place at row, col in drop index
+
+ If it returns true a drop can be done, and dropRow, dropCol and dropIndex reflects the position of the drop.
+ \internal
+ */
+bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
+{
+ if (event->isAccepted())
+ return false;
+
+ QModelIndex index;
+ if (dd->viewport->rect().contains(event->pos())) {
+ // can't use indexAt, doesn't account for spacing.
+ QPoint p = event->pos();
+ QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
+ rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
+ const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect);
+ index = intersectVector.count() > 0
+ ? intersectVector.last() : QModelIndex();
+ if (!index.isValid())
+ index = dd->root;
+ }
+
+ // If we are allowed to do the drop
+ if (dd->model->supportedDropActions() & event->dropAction()) {
+ int row = -1;
+ int col = -1;
+ if (index != dd->root) {
+ dd->dropIndicatorPosition = position(event->pos(), qq->visualRect(index), index);
+ switch (dd->dropIndicatorPosition) {
+ case QAbstractItemView::AboveItem:
+ row = index.row();
+ col = index.column();
+ index = index.parent();
+ break;
+ case QAbstractItemView::BelowItem:
+ row = index.row() + 1;
+ col = index.column();
+ index = index.parent();
+ break;
+ case QAbstractItemView::OnItem:
+ case QAbstractItemView::OnViewport:
+ break;
+ }
+ } else {
+ dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
+ }
+ *dropIndex = index;
+ *dropRow = row;
+ *dropCol = col;
+ if (!dd->droppingOnItself(event, index))
+ return true;
+ }
+ return false;
+}
+
#endif //QT_NO_DRAGANDDROP
void QListModeViewBase::updateVerticalScrollBar(const QSize &step)
@@ -2107,7 +2179,7 @@ int QListModeViewBase::verticalOffset() const
int value = verticalScrollBar()->value();
if (value >= segmentPositions.count())
return 0;
- return segmentPositions.at(value);
+ return segmentPositions.at(value) - spacing();
}
} else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
int value = verticalScrollBar()->value();
@@ -2155,14 +2227,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
if (horizontal && flow() == QListView::TopToBottom && dx != 0) {
int currentValue = qBound(0, horizontalValue, max);
int previousValue = qBound(0, currentValue + dx, max);
- int currentCoordinate = segmentPositions.at(currentValue);
- int previousCoordinate = segmentPositions.at(previousValue);
+ int currentCoordinate = segmentPositions.at(currentValue) - spacing();
+ int previousCoordinate = segmentPositions.at(previousValue) - spacing();
dx = previousCoordinate - currentCoordinate;
} else if (vertical && flow() == QListView::LeftToRight && dy != 0) {
int currentValue = qBound(0, verticalValue, max);
int previousValue = qBound(0, currentValue + dy, max);
- int currentCoordinate = segmentPositions.at(currentValue);
- int previousCoordinate = segmentPositions.at(previousValue);
+ int currentCoordinate = segmentPositions.at(currentValue) - spacing();
+ int previousCoordinate = segmentPositions.at(previousValue) - spacing();
dy = previousCoordinate - currentCoordinate;
}
} else {
@@ -2330,6 +2402,8 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
segmentExtents.append(flowPosition);
flowPosition = info.spacing + segStartPosition;
segPosition += deltaSegPosition;
+ if (info.wrap)
+ segPosition += info.spacing;
segmentPositions.append(segPosition);
segmentStartRows.append(row);
deltaSegPosition = 0;
diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h
index 5e50a67337..84aaaca2de 100644
--- a/src/gui/itemviews/qlistview_p.h
+++ b/src/gui/itemviews/qlistview_p.h
@@ -237,6 +237,7 @@ public:
// WARNING: Plenty of duplicated code from QAbstractItemView{,Private}.
QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
void dragMoveEvent(QDragMoveEvent *e);
+ bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
#endif
private:
@@ -364,6 +365,7 @@ public:
#ifndef QT_NO_DRAGANDDROP
virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
+ bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
#endif
inline void setGridSize(const QSize &size) { grid = size; }
@@ -376,7 +378,10 @@ public:
inline bool isSelectionRectVisible() const { return showElasticBand; }
inline QModelIndex modelIndex(int row) const { return model->index(row, column, root); }
- inline bool isHidden(int row) const { return hiddenRows.contains(model->index(row, 0, root)); }
+ inline bool isHidden(int row) const {
+ QModelIndex idx = model->index(row, 0, root);
+ return isPersistent(idx) && hiddenRows.contains(idx);
+ }
inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); }
inline void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex &current) const {
@@ -430,7 +435,7 @@ public:
QBasicTimer batchLayoutTimer;
// used for hidden items
- QVector<QPersistentModelIndex> hiddenRows;
+ QSet<QPersistentModelIndex> hiddenRows;
int column;
bool uniformItemSizes;
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index e54cbd24d5..3196ba57d7 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -362,6 +362,7 @@ QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &pro
return QModelIndex(); // for now; we may want to be able to set a root index later
if (proxy_index.model() != q_func()) {
qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapToSource";
+ Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapToSource");
return QModelIndex();
}
IndexMap::const_iterator it = index_to_iterator(proxy_index);
@@ -379,6 +380,7 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou
return QModelIndex(); // for now; we may want to be able to set a root index later
if (source_index.model() != model) {
qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapFromSource";
+ Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapFromSource");
return QModelIndex();
}
QModelIndex source_parent = source_index.parent();
diff --git a/src/gui/itemviews/qstringlistmodel.cpp b/src/gui/itemviews/qstringlistmodel.cpp
index cadb73143f..d2e4c2204e 100644
--- a/src/gui/itemviews/qstringlistmodel.cpp
+++ b/src/gui/itemviews/qstringlistmodel.cpp
@@ -290,8 +290,9 @@ QStringList QStringListModel::stringList() const
*/
void QStringListModel::setStringList(const QStringList &strings)
{
+ emit beginResetModel();
lst = strings;
- reset();
+ emit endResetModel();
}
/*!
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index 0d1473da4d..33293f73bc 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -326,7 +326,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
option->displayAlignment = Qt::Alignment(value.toInt());
value = index.data(Qt::ForegroundRole);
- if (qVariantCanConvert<QBrush>(value))
+ if (value.canConvert<QBrush>())
option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) {
@@ -727,7 +727,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event,
// make sure that we have the right event type
if ((event->type() == QEvent::MouseButtonRelease)
- || (event->type() == QEvent::MouseButtonDblClick)) {
+ || (event->type() == QEvent::MouseButtonDblClick)
+ || (event->type() == QEvent::MouseButtonPress)) {
QStyleOptionViewItemV4 viewOpt(option);
initStyleOption(&viewOpt, index);
QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget);
@@ -735,8 +736,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event,
if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos()))
return false;
- // eat the double click events inside the check rect
- if (event->type() == QEvent::MouseButtonDblClick)
+ if ((event->type() == QEvent::MouseButtonPress)
+ || (event->type() == QEvent::MouseButtonDblClick))
return true;
} else if (event->type() == QEvent::KeyPress) {
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 49053c1379..e494ee5564 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -926,14 +926,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4
q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q);
- if (const QWidget *widget = editorForIndex(index).editor) {
- painter->save();
- painter->setClipRect(widget->geometry());
- q->itemDelegate(index)->paint(painter, opt, index);
- painter->restore();
- } else {
- q->itemDelegate(index)->paint(painter, opt, index);
- }
+ q->itemDelegate(index)->paint(painter, opt, index);
}
/*!
@@ -2166,7 +2159,7 @@ int QTableView::sizeHintForRow(int row) const
option.rect.setWidth(columnWidth(index.column()));
}
- QWidget *editor = d->editorForIndex(index).editor;
+ QWidget *editor = d->editorForIndex(index).widget.data();
if (editor && d->persistent.contains(editor)) {
hint = qMax(hint, editor->sizeHint().height());
int min = editor->minimumSize().height();
@@ -2219,7 +2212,7 @@ int QTableView::sizeHintForColumn(int column) const
continue;
index = d->model->index(logicalRow, column, d->root);
- QWidget *editor = d->editorForIndex(index).editor;
+ QWidget *editor = d->editorForIndex(index).widget.data();
if (editor && d->persistent.contains(editor)) {
hint = qMax(hint, editor->sizeHint().width());
int min = editor->minimumSize().width();
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index f1f32360bb..d03babb529 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -1493,7 +1493,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
// when the row contains an index widget which has focus,
// we want to paint the entire row as active
bool indexWidgetHasFocus = false;
- if ((current.row() == index.row()) && !d->editors.isEmpty()) {
+ if ((current.row() == index.row()) && !d->editorIndexHash.isEmpty()) {
const int r = index.row();
QWidget *fw = QApplication::focusWidget();
for (int c = 0; c < header->count(); ++c) {
@@ -1669,14 +1669,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
opt.state = oldState;
}
- if (const QWidget *widget = d->editorForIndex(modelIndex).editor) {
- painter->save();
- painter->setClipRect(widget->geometry());
- d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
- painter->restore();
- } else {
- d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
- }
+ d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
}
if (currentRowHasFocus) {
@@ -2395,7 +2388,7 @@ void QTreeView::scrollContentsBy(int dx, int dy)
int viewCount = d->viewport->height() / itemHeight;
int maxDeltaY = qMin(d->viewItems.count(), viewCount);
// no need to do a lot of work if we are going to redraw the whole thing anyway
- if (qAbs(dy) > qAbs(maxDeltaY) && d->editors.isEmpty()) {
+ if (qAbs(dy) > qAbs(maxDeltaY) && d->editorIndexHash.isEmpty()) {
verticalScrollBar()->update();
d->viewport->update();
return;
@@ -2469,11 +2462,9 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
}
const int parentItem = d->viewIndex(parent);
- if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled())
+ if (((parentItem != -1) && d->viewItems.at(parentItem).expanded)
|| (parent == d->root)) {
d->doDelayedItemsLayout();
- } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) {
- d->doDelayedItemsLayout();
} else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
// the parent just went from 0 children to more. update to re-paint the decoration
d->viewItems[parentItem].hasChildren = true;
@@ -2727,7 +2718,7 @@ int QTreeView::sizeHintForColumn(int column) const
continue; // we have no good size hint
QModelIndex index = viewItems.at(i).index;
index = index.sibling(index.row(), column);
- QWidget *editor = d->editorForIndex(index).editor;
+ QWidget *editor = d->editorForIndex(index).widget.data();
if (editor && d->persistent.contains(editor)) {
w = qMax(w, editor->sizeHint().width());
int min = editor->minimumSize().width();
@@ -2791,7 +2782,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const
continue;
QModelIndex idx = d->model->index(index.row(), logicalColumn, parent);
if (idx.isValid()) {
- QWidget *editor = d->editorForIndex(idx).editor;
+ QWidget *editor = d->editorForIndex(idx).widget.data();
if (editor && d->persistent.contains(editor)) {
height = qMax(height, editor->sizeHint().height());
int min = editor->minimumSize().height();
@@ -2870,13 +2861,13 @@ void QTreeViewPrivate::expand(int item, bool emitSignal)
if (emitSignal && animationsEnabled)
prepareAnimatedOperation(item, QVariantAnimation::Forward);
#endif //QT_NO_ANIMATION
- QAbstractItemView::State oldState = state;
+ stateBeforeAnimation = state;
q->setState(QAbstractItemView::ExpandingState);
const QModelIndex index = viewItems.at(item).index;
storeExpanded(index);
viewItems[item].expanded = true;
layout(item);
- q->setState(oldState);
+ q->setState(stateBeforeAnimation);
if (model->canFetchMore(index))
model->fetchMore(index);
@@ -2945,7 +2936,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
prepareAnimatedOperation(item, QVariantAnimation::Backward);
#endif //QT_NO_ANIMATION
- QAbstractItemView::State oldState = state;
+ stateBeforeAnimation = state;
q->setState(QAbstractItemView::CollapsingState);
expandedIndexes.erase(it);
viewItems[item].expanded = false;
@@ -2955,7 +2946,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal)
index = viewItems[index].parentItem;
}
removeViewItems(item + 1, total); // collapse
- q->setState(oldState);
+ q->setState(stateBeforeAnimation);
if (emitSignal) {
emit q->collapsed(modelIndex);
@@ -3040,9 +3031,9 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons
//and now let's render the editors the editors
QStyleOptionViewItemV4 option = viewOptionsV4();
- for (QList<QEditorInfo>::const_iterator it = editors.constBegin(); it != editors.constEnd(); ++it) {
- QWidget *editor = it->editor;
- QModelIndex index = it->index;
+ for (QEditorIndexHash::const_iterator it = editorIndexHash.constBegin(); it != editorIndexHash.constEnd(); ++it) {
+ QWidget *editor = it.key();
+ const QModelIndex &index = it.value();
option.rect = q->visualRect(index);
if (option.rect.isValid()) {
@@ -3066,7 +3057,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons
void QTreeViewPrivate::_q_endAnimatedOperation()
{
Q_Q(QTreeView);
- q->setState(QAbstractItemView::NoState);
+ q->setState(stateBeforeAnimation);
q->updateGeometries();
viewport->update();
}
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index f9c84c1ebe..4261e93438 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -32,8 +32,6 @@ HEADERS += \
kernel/qshortcutmap_p.h \
kernel/qsizepolicy.h \
kernel/qpalette.h \
- kernel/qsound.h \
- kernel/qsound_p.h \
kernel/qstackedlayout.h \
kernel/qtooltip.h \
kernel/qwhatsthis.h \
@@ -50,7 +48,7 @@ HEADERS += \
kernel/qgesturemanager_p.h \
kernel/qsoftkeymanager_p.h \
kernel/qsoftkeymanager_common_p.h \
- kernel/qguiplatformplugin_p.h
+ kernel/qguiplatformplugin_p.h \
SOURCES += \
kernel/qaction.cpp \
@@ -72,7 +70,6 @@ SOURCES += \
kernel/qpalette.cpp \
kernel/qshortcut.cpp \
kernel/qshortcutmap.cpp \
- kernel/qsound.cpp \
kernel/qstackedlayout.cpp \
kernel/qtooltip.cpp \
kernel/qguivariant.cpp \
@@ -200,7 +197,66 @@ embedded {
}
}
-!embedded:!x11:mac {
+!qpa {
+ HEADERS += \
+ kernel/qsound.h \
+ kernel/qsound_p.h
+
+ SOURCES += \
+ kernel/qsound.cpp
+}
+
+qpa {
+ HEADERS += \
+ kernel/qgenericpluginfactory_qpa.h \
+ kernel/qgenericplugin_qpa.h \
+ kernel/qeventdispatcher_qpa_p.h \
+ kernel/qwindowsysteminterface_qpa.h \
+ kernel/qwindowsysteminterface_qpa_p.h \
+ kernel/qplatformintegration_qpa.h \
+ kernel/qplatformscreen_qpa.h \
+ kernel/qplatformintegrationfactory_qpa_p.h \
+ kernel/qplatformintegrationplugin_qpa.h \
+ kernel/qplatformwindow_qpa.h \
+ kernel/qplatformwindowformat_qpa.h \
+ kernel/qplatformglcontext_qpa.h \
+ kernel/qdesktopwidget_qpa_p.h \
+ kernel/qplatformeventloopintegration_qpa.h \
+ kernel/qplatformcursor_qpa.h
+
+ SOURCES += \
+ kernel/qapplication_qpa.cpp \
+ kernel/qclipboard_qpa.cpp \
+ kernel/qcursor_qpa.cpp \
+ kernel/qdnd_qws.cpp \
+ kernel/qdesktopwidget_qpa.cpp \
+ kernel/qgenericpluginfactory_qpa.cpp \
+ kernel/qgenericplugin_qpa.cpp \
+ kernel/qkeymapper_qws.cpp \
+ kernel/qwidget_qpa.cpp \
+ kernel/qeventdispatcher_qpa.cpp \
+ kernel/qwindowsysteminterface_qpa.cpp \
+ kernel/qplatformintegration_qpa.cpp \
+ kernel/qplatformscreen_qpa.cpp \
+ kernel/qplatformintegrationfactory_qpa.cpp \
+ kernel/qplatformintegrationplugin_qpa.cpp \
+ kernel/qplatformwindow_qpa.cpp \
+ kernel/qplatformwindowformat_qpa.cpp \
+ kernel/qplatformeventloopintegration_qpa.cpp \
+ kernel/qplatformglcontext_qpa.cpp \
+ kernel/qplatformcursor_qpa.cpp
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qeventdispatcher_glib_qpa.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_glib_qpa_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
+ }
+}
+
+!embedded:!qpa:!x11:mac {
SOURCES += \
kernel/qclipboard_mac.cpp \
kernel/qmime_mac.cpp \
@@ -216,7 +272,8 @@ embedded {
qcocoaapplicationdelegate_mac_p.h \
qmacgesturerecognizer_mac_p.h \
qmultitouch_mac_p.h \
- qcocoasharedwindowmethods_mac_p.h
+ qcocoasharedwindowmethods_mac_p.h \
+ qcocoaintrospection_p.h
OBJECTIVE_SOURCES += \
kernel/qcursor_mac.mm \
@@ -236,7 +293,8 @@ embedded {
kernel/qeventdispatcher_mac.mm \
kernel/qcocoawindowcustomthemeframe_mac.mm \
kernel/qmacgesturerecognizer_mac.mm \
- kernel/qmultitouch_mac.mm
+ kernel/qmultitouch_mac.mm \
+ kernel/qcocoaintrospection_mac.mm
HEADERS += \
kernel/qt_cocoa_helpers_mac_p.h \
diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri
index 153851069e..21acd06e65 100644
--- a/src/gui/kernel/mac.pri
+++ b/src/gui/kernel/mac.pri
@@ -1,4 +1,4 @@
-!x11:!embedded:mac {
+!x11:!embedded:!qpa:mac {
LIBS_PRIVATE += -framework Carbon -lz
*-mwerks:INCLUDEPATH += compat
}
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 59aec91af4..5c4a314770 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -153,8 +153,6 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT void qt_call_post_routines();
-int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0
-
QApplication::Type qt_appType=QApplication::Tty;
QApplicationPrivate *QApplicationPrivate::self = 0;
@@ -169,8 +167,8 @@ bool QApplicationPrivate::autoSipEnabled = false;
bool QApplicationPrivate::autoSipEnabled = true;
#endif
-QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
- : QCoreApplicationPrivate(argc, argv)
+QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags)
+ : QCoreApplicationPrivate(argc, argv, flags)
{
application_type = type;
qt_appType = type;
@@ -452,6 +450,9 @@ QPalette *QApplicationPrivate::sys_pal = 0; // default system palette
QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer
QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system
+#if defined(Q_WS_QPA)
+QPlatformIntegration *QApplicationPrivate::platform_integration = 0;
+#endif
QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization
bool QApplicationPrivate::runtime_graphics_system = false;
@@ -514,7 +515,7 @@ inline bool QApplicationPrivate::isAlien(QWidget *widget)
{
if (!widget)
return false;
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
return !widget->isWindow()
# ifdef Q_BACKINGSTORE_SUBSURFACES
&& !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface)
@@ -724,12 +725,12 @@ void QApplicationPrivate::process_cmdline()
*/
QApplication::QApplication(int &argc, char **argv)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000))
{ Q_D(QApplication); d->construct(); }
QApplication::QApplication(int &argc, char **argv, int _internal)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
-{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal))
+{ Q_D(QApplication); d->construct(); }
/*!
@@ -758,12 +759,12 @@ QApplication::QApplication(int &argc, char **argv, int _internal)
*/
QApplication::QApplication(int &argc, char **argv, bool GUIenabled )
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, 0x040000))
{ Q_D(QApplication); d->construct(); }
QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty))
-{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, _internal))
+{ Q_D(QApplication); d->construct();}
@@ -781,12 +782,12 @@ QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _intern
\c -qws option).
*/
QApplication::QApplication(int &argc, char **argv, Type type)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, type))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, type, 0x040000))
{ Q_D(QApplication); d->construct(); }
QApplication::QApplication(int &argc, char **argv, Type type , int _internal)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, type))
-{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, type, _internal))
+{ Q_D(QApplication); d->construct(); }
#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
static int qt_matchLibraryName(dl_phdr_info *info, size_t, void *data)
@@ -892,7 +893,7 @@ static char *aargv[] = { (char*)"unknown", 0 };
This function is only available on X11.
*/
QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
- : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, 0x040000))
{
if (! dpy)
qWarning("QApplication: Invalid Display* argument");
@@ -901,7 +902,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap)
}
QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
- : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, _internal))
{
if (! dpy)
qWarning("QApplication: Invalid Display* argument");
@@ -926,7 +927,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap,
*/
QApplication::QApplication(Display *dpy, int &argc, char **argv,
Qt::HANDLE visual, Qt::HANDLE colormap)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000))
{
if (! dpy)
qWarning("QApplication: Invalid Display* argument");
@@ -936,7 +937,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv,
QApplication::QApplication(Display *dpy, int &argc, char **argv,
Qt::HANDLE visual, Qt::HANDLE colormap, int _internal)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal))
{
if (! dpy)
qWarning("QApplication: Invalid Display* argument");
@@ -966,10 +967,11 @@ void QApplicationPrivate::initialize()
QWidgetPrivate::mapper = new QWidgetMapper;
QWidgetPrivate::allWidgets = new QWidgetSet;
-#if !defined(Q_WS_X11) && !defined(Q_WS_QWS)
+#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
// initialize the graphics system - on X11 this is initialized inside
// qt_init() in qapplication_x11.cpp because of several reasons.
// On QWS, the graphics system is set by the QScreen plugin.
+ // We don't use graphics systems in Qt QPA
graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
#endif
@@ -1643,14 +1645,18 @@ QStyle* QApplication::setStyle(const QString& style)
void QApplication::setGraphicsSystem(const QString &system)
{
-#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+#ifdef Q_WS_QPA
+ Q_UNUSED(system);
+#else
+# ifdef QT_GRAPHICSSYSTEM_RUNTIME
if (QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
QRuntimeGraphicsSystem *r =
static_cast<QRuntimeGraphicsSystem *>(QApplicationPrivate::graphics_system);
r->setGraphicsSystem(system);
} else
-#endif
+# endif
QApplicationPrivate::graphics_system_name = system;
+#endif
}
/*!
@@ -2796,7 +2802,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
// Update cursor for alien/graphics widgets.
const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen)));
-#if defined(Q_WS_X11)
+#if defined(Q_WS_X11) || defined(Q_WS_QPA)
//Whenever we leave an alien widget on X11, we need to reset its nativeParentWidget()'s cursor.
// This is not required on Windows as the cursor is reset on every single mouse move.
QWidget *parentOfLeavingCursor = 0;
@@ -2820,7 +2826,15 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
if (!parentOfLeavingCursor->window()->graphicsProxyWidget())
#endif
{
+#if defined(Q_WS_X11)
qt_x11_enforce_cursor(parentOfLeavingCursor,true);
+#elif defined(Q_WS_QPA)
+ if (enter == QApplication::desktop()) {
+ qt_qpa_set_cursor(enter, true);
+ } else {
+ qt_qpa_set_cursor(parentOfLeavingCursor, true);
+ }
+#endif
}
}
#endif
@@ -2844,6 +2858,8 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
qt_x11_enforce_cursor(cursorWidget, true);
#elif defined(Q_OS_SYMBIAN)
qt_symbian_set_cursor(cursorWidget, true);
+#elif defined(Q_WS_QPA)
+ qt_qpa_set_cursor(cursorWidget, true);
#endif
}
}
@@ -3148,7 +3164,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
return result;
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
/*
This function should only be called when the widget changes visibility, i.e.
when the \a widget is shown, hidden or deleted. This function does nothing
@@ -3160,7 +3176,7 @@ extern QWidget *qt_button_down;
void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
{
#ifndef QT_NO_CURSOR
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
if (!widget || widget->isWindow())
return;
#else
@@ -3754,11 +3770,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
d->checkReceiverThread(receiver);
#endif
-#ifdef QT3_SUPPORT
- if (e->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty())
- receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(e)->child());
-#endif // QT3_SUPPORT
-
// capture the current mouse/keyboard state
if(e->spontaneous()) {
if (e->type() == QEvent::KeyPress
@@ -5861,12 +5872,12 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
#ifndef QT_NO_GESTURES
QGestureManager* QGestureManager::instance()
{
- if (QApplicationPrivate *qAppPriv = QApplicationPrivate::instance()) {
- if (!qAppPriv->gestureManager)
- qAppPriv->gestureManager = new QGestureManager(qApp);
- return qAppPriv->gestureManager;
- }
- return 0;
+ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
+ if (!qAppPriv)
+ return 0;
+ if (!qAppPriv->gestureManager)
+ qAppPriv->gestureManager = new QGestureManager(qApp);
+ return qAppPriv->gestureManager;
}
#endif // QT_NO_GESTURES
@@ -6090,6 +6101,8 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
default:
break;
}
+#else
+ Q_UNUSED(cshape);
#endif
return QPixmap();
}
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index b65cf9150f..aa62518df8 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -123,15 +123,15 @@ public:
#endif
#ifndef qdoc
- QApplication(int &argc, char **argv, int = QT_VERSION);
- QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION);
- QApplication(int &argc, char **argv, Type, int = QT_VERSION);
+ QApplication(int &argc, char **argv, int = ApplicationFlags);
+ QApplication(int &argc, char **argv, bool GUIenabled, int = ApplicationFlags);
+ QApplication(int &argc, char **argv, Type, int = ApplicationFlags);
#if defined(Q_WS_X11)
- QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION);
- QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION);
+ QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = ApplicationFlags);
+ QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = ApplicationFlags);
#endif
#if defined(Q_OS_SYMBIAN)
- QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = QT_VERSION);
+ QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = ApplicationFlags);
#endif
#endif
virtual ~QApplication();
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index bcf8cf221f..b22a6b3c2d 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -549,7 +549,7 @@ void qt_mac_update_os_settings()
FontMap("QTipLabel", kThemeSmallSystemFont),
FontMap("QLabel", kThemeSystemFont),
FontMap("QToolButton", kThemeSmallSystemFont),
- FontMap("QMenuItem", kThemeMenuItemCmdKeyFont), // It doesn't exist, but its unique.
+ FontMap("QMenuItem", kThemeMenuItemFont), // It doesn't exist, but its unique.
FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique.
FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique.
FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique.
@@ -1243,8 +1243,10 @@ void qt_init(QApplicationPrivate *priv, int)
// Cocoa application delegate
#ifdef QT_MAC_USE_COCOA
NSApplication *cocoaApp = [QNSApplication sharedApplication];
+ qt_redirectNSApplicationSendEvent();
+
QMacCocoaAutoReleasePool pool;
- NSObject *oldDelegate = [cocoaApp delegate];
+ id oldDelegate = [cocoaApp delegate];
QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
Q_ASSERT(newDelegate);
[newDelegate setQtPrivate:priv];
@@ -2608,25 +2610,26 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap
/*!
\fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event)
- \warning This virtual function is only implemented under Mac OS X when against Carbon.
+ \warning This virtual function is only used under Mac OS X, and behaves different
+ depending on if Qt is based on Carbon or Cocoa.
- If you create an application that inherits QApplication and reimplement
+ For the Carbon port, If you create an application that inherits QApplication and reimplement
this function, you get direct access to all Carbon Events that Qt registers
for from Mac OS X with this function being called with the \a caller and
the \a event.
+ For the Cocoa port, If you create an application that inherits QApplication and reimplement
+ this function, you get direct access to all Cocoa Events that Qt receives
+ from Mac OS X with this function being called with the \a caller being 0 and
+ the \a event being an NSEvent pointer:
+
+ NSEvent *e = reinterpret_cast<NSEvent *>(event);
+
Return true if you want to stop the event from being processed.
Return false for normal event dispatching. The default
implementation returns false.
- Cocoa uses a different event system which means this function is NOT CALLED
- when building Qt against Cocoa. If you want similar functionality subclass
- NSApplication and reimplement the sendEvent: message to handle all the
- NSEvents. You also will need to to instantiate your custom NSApplication
- before creating a QApplication. See \l
- {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's
- NSApplication Reference} for more information.
-
+ \sa macEventFilter(void *nsevent)
*/
bool QApplication::macEventFilter(EventHandlerCallRef, EventRef)
{
@@ -3107,11 +3110,7 @@ void onApplicationChangedActivation( bool activated )
}
if (!app->activeWindow()) {
-#if QT_MAC_USE_COCOA
- OSWindowRef wp = [NSApp keyWindow];
-#else
- OSWindowRef wp = ActiveNonFloatingWindow();
-#endif
+ OSWindowRef wp = [NSApp keyWindow];
if (QWidget *tmp_w = qt_mac_find_window(wp))
app->setActiveWindow(tmp_w);
}
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 43634efabc..f9508a7bb4 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -65,8 +65,10 @@
#include "QtCore/qhash.h"
#include "QtCore/qpointer.h"
#include "private/qcoreapplication_p.h"
-#include "private/qshortcutmap_p.h"
+#include "QtGui/private/qshortcutmap_p.h"
#include <private/qthread_p.h>
+#include "QtCore/qpoint.h"
+#include <QTime>
#ifdef Q_WS_QWS
#include "QtGui/qscreen_qws.h"
#include <private/qgraphicssystem_qws_p.h>
@@ -74,6 +76,11 @@
#ifdef Q_OS_SYMBIAN
#include <w32std.h>
#endif
+#ifdef Q_WS_QPA
+#include <QWindowSystemInterface>
+#include "qwindowsysteminterface_qpa_p.h"
+#include "QtGui/qplatformintegration_qpa.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -291,7 +298,7 @@ class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate
{
Q_DECLARE_PUBLIC(QApplication)
public:
- QApplicationPrivate(int &argc, char **argv, QApplication::Type type);
+ QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags);
~QApplicationPrivate();
#if defined(Q_WS_X11)
@@ -312,10 +319,18 @@ public:
static QString desktopStyleKey();
static QGraphicsSystem *graphicsSystem()
-#if !defined(Q_WS_QWS)
- { return graphics_system; }
-#else
+#if defined(Q_WS_QWS)
{ return QScreen::instance()->graphicsSystem(); }
+#else
+ { return graphics_system; }
+#endif
+
+#if defined(Q_WS_QPA)
+ static QPlatformIntegration *platformIntegration()
+ { return platform_integration; }
+
+ static QAbstractEventDispatcher *qt_qpa_core_dispatcher()
+ { return QCoreApplication::instance()->d_func()->threadData->eventDispatcher; }
#endif
void createEventDispatcher();
@@ -418,6 +433,9 @@ public:
static QGraphicsSystem *graphics_system;
static QString graphics_system_name;
static bool runtime_graphics_system;
+#ifdef Q_WS_QPA
+ static QPlatformIntegration *platform_integration;
+#endif
private:
static QFont *app_font; // private for a reason! Always use QApplication::font() instead!
@@ -477,6 +495,30 @@ public:
static bool qt_mac_apply_settings();
#endif
+#ifdef Q_WS_QPA
+ static void processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e);
+ static void processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e);
+ static void processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e);
+ static void processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e);
+
+ static void processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e);
+
+ static void processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e);
+
+ static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e);
+ static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e);
+
+ static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e);
+
+// static void reportScreenCount(int count);
+ static void reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e);
+// static void reportGeometryChange(int screenIndex);
+ static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e);
+// static void reportAvailableGeometryChange(int screenIndex);
+ static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e);
+
+#endif
+
#ifdef Q_WS_QWS
QPointer<QWSManager> last_manager;
QWSServerCleaner qwsServerCleaner;
@@ -492,8 +534,6 @@ public:
static QString styleOverride;
- static int app_compile_version;
-
#ifdef QT_KEYPAD_NAVIGATION
static QWidget *oldEditFocus;
static Qt::NavigationMode navigationMode;
@@ -524,7 +564,7 @@ public:
void _q_aboutToQuit();
#endif
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
@@ -632,6 +672,8 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
extern void qt_x11_enforce_cursor(QWidget *);
#elif defined(Q_OS_SYMBIAN)
extern void qt_symbian_set_cursor(QWidget *, bool);
+#elif defined (Q_WS_QPA)
+ extern void qt_qpa_set_cursor(QWidget *, bool);
#endif
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp
new file mode 100644
index 0000000000..ece035c9c6
--- /dev/null
+++ b/src/gui/kernel/qapplication_qpa.cpp
@@ -0,0 +1,928 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication_p.h"
+#include "qcolormap.h"
+#include "qpixmapcache.h"
+#if !defined(QT_NO_GLIB)
+#include "qeventdispatcher_glib_qpa_p.h"
+#endif
+#include "qeventdispatcher_qpa_p.h"
+#ifndef QT_NO_CURSOR
+#include "private/qcursor_p.h"
+#endif
+
+#include "private/qwidget_p.h"
+
+#include "qgenericpluginfactory_qpa.h"
+#include "qplatformintegrationfactory_qpa_p.h"
+#include <qdesktopwidget.h>
+
+#include <qinputcontext.h>
+#include <QPlatformCursor>
+#include <qdebug.h>
+#include <QWindowSystemInterface>
+#include "qwindowsysteminterface_qpa_p.h"
+#include <QPlatformIntegration>
+
+#include "qdesktopwidget_qpa_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QString appName;
+static QString appFont;
+
+QWidget *qt_button_down = 0; // widget got last button-down
+
+static bool app_do_modal = false;
+extern QWidgetList *qt_modal_stack; // stack of modal widgets
+
+int qt_last_x = 0;
+int qt_last_y = 0;
+QPointer<QWidget> qt_last_mouse_receiver = 0;
+
+static Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+static Qt::MouseButtons buttons = Qt::NoButton;
+static ulong mousePressTime;
+static Qt::MouseButton mousePressButton = Qt::NoButton;
+static int mousePressX;
+static int mousePressY;
+static int mouse_double_click_distance = 5;
+
+void QApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
+{
+ switch(e->type) {
+ case QWindowSystemInterfacePrivate::Mouse:
+ QApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Wheel:
+ QApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Key:
+ QApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Touch:
+ QApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::GeometryChange:
+ QApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Enter:
+ QApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Leave:
+ QApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::Close:
+ QApplicationPrivate::processCloseEvent(
+ static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::ScreenCountChange:
+ QApplicationPrivate::reportScreenCount(
+ static_cast<QWindowSystemInterfacePrivate::ScreenCountEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::ScreenGeometry:
+ QApplicationPrivate::reportGeometryChange(
+ static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e));
+ break;
+ case QWindowSystemInterfacePrivate::ScreenAvailableGeometry:
+ QApplicationPrivate::reportAvailableGeometryChange(
+ static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e));
+ break;
+ default:
+ qWarning() << "Unknown user input event type:" << e->type;
+ break;
+ }
+}
+
+QString QApplicationPrivate::appName() const
+{
+ return QT_PREPEND_NAMESPACE(appName);
+}
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+#if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
+ eventDispatcher = new QPAEventDispatcherGlib(q);
+ else
+#endif
+ eventDispatcher = new QEventDispatcherQPA(q);
+}
+
+static bool qt_try_modal(QWidget *widget, QEvent::Type type)
+{
+ QWidget * top = 0;
+
+ if (QApplicationPrivate::tryModalHelper(widget, &top))
+ return true;
+
+ bool block_event = false;
+ bool paint_event = false;
+
+ switch (type) {
+#if 0
+ case QEvent::Focus:
+ if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
+ break;
+ // drop through
+#endif
+ case QEvent::MouseButtonPress: // disallow mouse/key events
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ block_event = true;
+ break;
+ default:
+ break;
+ }
+
+ if ((block_event || paint_event) && top->parentWidget() == 0)
+ top->raise();
+
+ return !block_event;
+}
+
+
+
+void QApplicationPrivate::enterModal_sys(QWidget *widget)
+{
+ if (!qt_modal_stack)
+ qt_modal_stack = new QWidgetList;
+ qt_modal_stack->insert(0, widget);
+ app_do_modal = true;
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget *widget )
+{
+ if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
+ if (qt_modal_stack->isEmpty()) {
+ delete qt_modal_stack;
+ qt_modal_stack = 0;
+ }
+ }
+ app_do_modal = qt_modal_stack != 0;
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return app_do_modal;
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ Q_Q(QApplication);
+ if (!popupWidgets)
+ return;
+ popupWidgets->removeAll(popup);
+
+//###
+// if (popup == qt_popup_down) {
+// qt_button_down = 0;
+// qt_popup_down = 0;
+// }
+
+ if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+
+ //### replay mouse event?
+
+ //### transfer/release mouse grab
+
+ //### transfer/release keyboard grab
+
+ //give back focus
+
+ if (active_window) {
+ if (QWidget *fw = active_window->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q->sendEvent(fw, &e);
+ }
+ }
+ }
+
+ } else {
+ // A popup was closed, so the previous popup gets the focus.
+
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = aw->focusWidget())
+ fw->setFocus(Qt::PopupFocusReason);
+
+ //### regrab the keyboard and mouse in case 'popup' lost the grab
+
+
+ }
+
+}
+
+static int openPopupCount = 0;
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ openPopupCount++;
+ if (!popupWidgets) { // create list
+ popupWidgets = new QWidgetList;
+
+ /* only grab if you are the first/parent popup */
+ //#### ->grabMouse(popup,true);
+ //#### ->grabKeyboard(popup,true);
+ //### popupGrabOk = true;
+ }
+ popupWidgets->append(popup); // add to end of list
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (popup->focusWidget()) {
+ popup->focusWidget()->setFocus(Qt::PopupFocusReason);
+ } else if (popupWidgets->count() == 1) { // this was the first popup
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ QApplication::sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+}
+
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ QApplicationPrivate::mouse_double_click_time = ms;
+}
+
+int QApplication::doubleClickInterval()
+{
+ return QApplicationPrivate::mouse_double_click_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QApplication::setWheelScrollLines(int lines)
+{
+ QApplicationPrivate::wheel_scroll_lines = lines;
+}
+
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+#endif
+
+void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+{
+ switch (effect) {
+ case Qt::UI_AnimateMenu:
+ QApplicationPrivate::animate_menu = enable;
+ break;
+ case Qt::UI_FadeMenu:
+ if (enable)
+ QApplicationPrivate::animate_menu = true;
+ QApplicationPrivate::fade_menu = enable;
+ break;
+ case Qt::UI_AnimateCombo:
+ QApplicationPrivate::animate_combo = enable;
+ break;
+ case Qt::UI_AnimateTooltip:
+ QApplicationPrivate::animate_tooltip = enable;
+ break;
+ case Qt::UI_FadeTooltip:
+ if (enable)
+ QApplicationPrivate::animate_tooltip = true;
+ QApplicationPrivate::fade_tooltip = enable;
+ break;
+ case Qt::UI_AnimateToolBox:
+ QApplicationPrivate::animate_toolbox = enable;
+ break;
+ default:
+ QApplicationPrivate::animate_ui = enable;
+ break;
+ }
+}
+
+bool QApplication::isEffectEnabled(Qt::UIEffect effect)
+{
+ if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
+ return false;
+
+ switch(effect) {
+ case Qt::UI_AnimateMenu:
+ return QApplicationPrivate::animate_menu;
+ case Qt::UI_FadeMenu:
+ return QApplicationPrivate::fade_menu;
+ case Qt::UI_AnimateCombo:
+ return QApplicationPrivate::animate_combo;
+ case Qt::UI_AnimateTooltip:
+ return QApplicationPrivate::animate_tooltip;
+ case Qt::UI_FadeTooltip:
+ return QApplicationPrivate::fade_tooltip;
+ case Qt::UI_AnimateToolBox:
+ return QApplicationPrivate::animate_toolbox;
+ default:
+ return QApplicationPrivate::animate_ui;
+ }
+}
+
+#ifndef QT_NO_CURSOR
+void QApplication::setOverrideCursor(const QCursor &cursor)
+{
+ qApp->d_func()->cursor_list.prepend(cursor);
+ qt_qpa_set_cursor(0, false);
+}
+
+void QApplication::restoreOverrideCursor()
+{
+ if (qApp->d_func()->cursor_list.isEmpty())
+ return;
+ qApp->d_func()->cursor_list.removeFirst();
+ qt_qpa_set_cursor(0, false);
+}
+
+#endif// QT_NO_CURSOR
+
+QWidget *QApplication::topLevelAt(const QPoint &pos)
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+
+ QList<QPlatformScreen *> screens = pi->screens();
+ QList<QPlatformScreen *>::const_iterator screen = screens.constBegin();
+ QList<QPlatformScreen *>::const_iterator end = screens.constEnd();
+
+ // The first screen in a virtual environment should know about all top levels
+ if (pi->isVirtualDesktop()) {
+ QWidget *w = (*screen)->topLevelAt(pos);
+ return w;
+ }
+
+ while (screen != end) {
+ if ((*screen)->geometry().contains(pos))
+ return (*screen)->topLevelAt(pos);
+ ++screen;
+ }
+ return 0;
+}
+
+void QApplication::beep()
+{
+}
+
+void QApplication::alert(QWidget *, int)
+{
+}
+
+static void init_platform(const QString &name)
+{
+ QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name);
+ if (!QApplicationPrivate::platform_integration) {
+ QStringList keys = QPlatformIntegrationFactory::keys();
+ QString fatalMessage =
+ QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name);
+ foreach(QString key, keys) {
+ fatalMessage.append(key + QString::fromLatin1("\n"));
+ }
+ qFatal("%s", fatalMessage.toLocal8Bit().constData());
+
+ }
+
+}
+
+
+static void cleanup_platform()
+{
+ delete QApplicationPrivate::platform_integration;
+ QApplicationPrivate::platform_integration = 0;
+}
+
+static void init_plugins(const QList<QByteArray> pluginList)
+{
+ for (int i = 0; i < pluginList.count(); ++i) {
+ QByteArray pluginSpec = pluginList.at(i);
+ qDebug() << "init_plugins" << i << pluginSpec;
+ int colonPos = pluginSpec.indexOf(':');
+ QObject *plugin;
+ if (colonPos < 0)
+ plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString());
+ else
+ plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)),
+ QLatin1String(pluginSpec.mid(colonPos+1)));
+ qDebug() << " created" << plugin;
+ }
+}
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+class QDummyInputContext : public QInputContext
+{
+public:
+ explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {}
+ ~QDummyInputContext() {}
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+ bool isComposing() const { return false; }
+
+};
+#endif // QT_NO_QWS_INPUTMETHODS
+
+void qt_init(QApplicationPrivate *priv, int type)
+{
+ Q_UNUSED(type);
+
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ char *p;
+ char **argv = priv->argv;
+ int argc = priv->argc;
+
+ if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms
+ p = strrchr(argv[0], '/');
+ appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
+ }
+
+ QList<QByteArray> pluginList;
+ QString platformName = QLatin1String(qgetenv("QT_QPA_PLATFORM"));
+
+ // Get command line params
+
+ int j = argc ? 1 : 0;
+ for (int i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QByteArray arg = argv[i];
+ if (arg == "-fn" || arg == "-font") {
+ if (++i < argc)
+ appFont = QString::fromLocal8Bit(argv[i]);
+ } else if (arg == "-platform") {
+ if (++i < argc)
+ platformName = QLatin1String(argv[i]);
+ } else if (arg == "-plugin") {
+ if (++i < argc)
+ pluginList << argv[i];
+ } else {
+ argv[j++] = argv[i];
+ }
+ }
+
+ if (j < priv->argc) {
+ priv->argv[j] = 0;
+ priv->argc = j;
+ }
+
+#if 0
+ QByteArray pluginEnv = qgetenv("QT_QPA_PLUGINS");
+ if (!pluginEnv.isEmpty()) {
+ pluginList.append(pluginEnv.split(';'));
+ }
+#endif
+
+ init_platform(platformName);
+ init_plugins(pluginList);
+
+ QColormap::initialize();
+ QFont::initialize();
+#ifndef QT_NO_CURSOR
+// QCursorData::initialize();
+#endif
+
+ qApp->setObjectName(appName);
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ qApp->setInputContext(new QDummyInputContext(qApp));
+#endif
+}
+
+void qt_cleanup()
+{
+ cleanup_platform();
+
+ QPixmapCache::clear();
+#ifndef QT_NO_CURSOR
+ QCursorData::cleanup();
+#endif
+ QFont::cleanup();
+ QColormap::cleanup();
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+
+ QApplicationPrivate::active_window = 0; //### this should not be necessary
+}
+
+
+#ifdef QT3_SUPPORT
+void QApplication::setMainWidget(QWidget *mainWidget)
+{
+ QApplicationPrivate::main_widget = mainWidget;
+ if (QApplicationPrivate::main_widget && windowIcon().isNull()
+ && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
+ setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
+}
+#endif
+
+void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
+{
+ // qDebug() << "handleMouseEvent" << tlw << ev.pos() << ev.globalPos() << hex << ev.buttons();
+ static QWeakPointer<QWidget> implicit_mouse_grabber;
+
+ QEvent::Type type;
+ // move first
+ Qt::MouseButtons stateChange = e->buttons ^ buttons;
+ if (e->globalPos != QPoint(qt_last_x, qt_last_y) && (stateChange != Qt::NoButton)) {
+ QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent =
+ new QWindowSystemInterfacePrivate::MouseEvent(e->widget.data(), e->timestamp, e->localPos, e->globalPos, e->buttons);
+ QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop
+ stateChange = Qt::NoButton;
+ }
+
+ QWidget * tlw = e->widget.data();
+
+ QPoint localPoint = e->localPos;
+ QPoint globalPoint = e->globalPos;
+ QWidget *mouseWindow = tlw;
+
+ Qt::MouseButton button = Qt::NoButton;
+
+
+ if (qt_last_x != globalPoint.x() || qt_last_y != globalPoint.y()) {
+ type = QEvent::MouseMove;
+ qt_last_x = globalPoint.x();
+ qt_last_y = globalPoint.y();
+ if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance||
+ qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance)
+ mousePressButton = Qt::NoButton;
+ }
+ else { // check to see if a new button has been pressed/released
+ for (int check = Qt::LeftButton;
+ check <= Qt::XButton2;
+ check = check << 1) {
+ if (check & stateChange) {
+ button = Qt::MouseButton(check);
+ break;
+ }
+ }
+ if (button == Qt::NoButton) {
+ // Ignore mouse events that don't change the current state
+ return;
+ }
+ buttons = e->buttons;
+ if (button & e->buttons) {
+ if ((e->timestamp - mousePressTime) < static_cast<ulong>(QApplication::doubleClickInterval()) && button == mousePressButton) {
+ type = QEvent::MouseButtonDblClick;
+ mousePressButton = Qt::NoButton;
+ }
+ else {
+ type = QEvent::MouseButtonPress;
+ mousePressTime = e->timestamp;
+ mousePressButton = button;
+ mousePressX = qt_last_x;
+ mousePressY = qt_last_y;
+ }
+ }
+ else
+ type = QEvent::MouseButtonRelease;
+ }
+
+ if (self->inPopupMode()) {
+ //popup mouse handling is magical...
+ mouseWindow = qApp->activePopupWidget();
+
+ implicit_mouse_grabber.clear();
+ //### how should popup mode and implicit mouse grab interact?
+
+ } else if (tlw && app_do_modal && !qt_try_modal(tlw, QEvent::MouseButtonRelease) ) {
+ //even if we're blocked by modality, we should deliver the mouse release event..
+ //### this code is not completely correct: multiple buttons can be pressed simultaneously
+ if (!(implicit_mouse_grabber && buttons == Qt::NoButton)) {
+ //qDebug() << "modal blocked mouse event to" << tlw;
+ return;
+ }
+ }
+
+ // find the tlw if we didn't get it from the plugin
+ if (!mouseWindow) {
+ mouseWindow = QApplication::topLevelAt(globalPoint);
+ }
+
+ if (!mouseWindow && !implicit_mouse_grabber)
+ mouseWindow = QApplication::desktop();
+
+ if (mouseWindow && mouseWindow != tlw) {
+ //we did not get a sensible localPoint from the window system, so let's calculate it
+ localPoint = mouseWindow->mapFromGlobal(globalPoint);
+ }
+
+ // which child should have it?
+ QWidget *mouseWidget = mouseWindow;
+ if (mouseWindow) {
+ QWidget *w = mouseWindow->childAt(localPoint);
+ if (w) {
+ mouseWidget = w;
+ }
+ }
+
+ //handle implicit mouse grab
+ if (type == QEvent::MouseButtonPress && !implicit_mouse_grabber) {
+ implicit_mouse_grabber = mouseWidget;
+
+ Q_ASSERT(mouseWindow);
+ mouseWindow->activateWindow(); //focus
+ } else if (implicit_mouse_grabber) {
+ mouseWidget = implicit_mouse_grabber.data();
+ mouseWindow = mouseWidget->window();
+ if (mouseWindow != tlw)
+ localPoint = mouseWindow->mapFromGlobal(globalPoint);
+ }
+
+ Q_ASSERT(mouseWidget);
+
+ //localPoint is local to mouseWindow, but it needs to be local to mouseWidget
+ localPoint = mouseWidget->mapFrom(mouseWindow, localPoint);
+
+ if (buttons == Qt::NoButton) {
+ //qDebug() << "resetting mouse grabber";
+ implicit_mouse_grabber.clear();
+ }
+
+ if (mouseWidget != qt_last_mouse_receiver) {
+ dispatchEnterLeave(mouseWidget, qt_last_mouse_receiver);
+ qt_last_mouse_receiver = mouseWidget;
+ }
+
+ // Remember, we might enter a modal event loop when sending the event,
+ // so think carefully before adding code below this point.
+
+ // qDebug() << "sending mouse ev." << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber;
+
+ QMouseEvent ev(type, localPoint, globalPoint, button, buttons, modifiers);
+
+ QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
+ foreach (QWeakPointer<QPlatformCursor> cursor, cursors) {
+ if (cursor)
+ cursor.data()->pointerEvent(ev);
+ }
+
+ QApplication::sendSpontaneousEvent(mouseWidget, &ev);
+}
+
+
+//### there's a lot of duplicated logic here -- refactoring required!
+
+void QApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e)
+{
+// QPoint localPoint = ev.pos();
+ QPoint globalPoint = e->globalPos;
+// bool trustLocalPoint = !!tlw; //is there something the local point can be local to?
+ QWidget *mouseWidget;
+
+ qt_last_x = globalPoint.x();
+ qt_last_y = globalPoint.y();
+
+ QWidget *mouseWindow = e->widget.data();
+
+ // find the tlw if we didn't get it from the plugin
+ if (!mouseWindow) {
+ mouseWindow = QApplication::topLevelAt(globalPoint);
+ }
+
+ if (!mouseWindow)
+ return;
+
+ mouseWidget = mouseWindow;
+
+ if (app_do_modal && !qt_try_modal(mouseWindow, QEvent::Wheel) ) {
+ qDebug() << "modal blocked wheel event" << mouseWindow;
+ return;
+ }
+ QPoint p = mouseWindow->mapFromGlobal(globalPoint);
+ QWidget *w = mouseWindow->childAt(p);
+ if (w) {
+ mouseWidget = w;
+ p = mouseWidget->mapFromGlobal(globalPoint);
+ }
+
+ QWheelEvent ev(p, globalPoint, e->delta, buttons, modifiers,
+ e->orient);
+ QApplication::sendSpontaneousEvent(mouseWidget, &ev);
+}
+
+
+
+// Remember, Qt convention is: keyboard state is state *before*
+
+void QApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e)
+{
+ QWidget *focusW = 0;
+ if (self->inPopupMode()) {
+ QWidget *popupW = qApp->activePopupWidget();
+ focusW = popupW->focusWidget() ? popupW->focusWidget() : popupW;
+ }
+ if (!focusW)
+ focusW = QApplication::focusWidget();
+ if (!focusW) {
+ focusW = e->widget.data();
+ }
+ if (!focusW)
+ focusW = QApplication::activeWindow();
+
+ //qDebug() << "handleKeyEvent" << hex << e->key() << e->modifiers() << e->text() << "widget" << focusW;
+
+ if (!focusW)
+ return;
+ if (app_do_modal && !qt_try_modal(focusW, e->keyType))
+ return;
+
+ modifiers = e->modifiers;
+ QKeyEvent ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount);
+ QApplication::sendSpontaneousEvent(focusW, &ev);
+}
+
+void QApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e)
+{
+ QApplicationPrivate::dispatchEnterLeave(e->enter.data(),0);
+ qt_last_mouse_receiver = e->enter.data();
+}
+
+void QApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e)
+{
+ QApplicationPrivate::dispatchEnterLeave(0,qt_last_mouse_receiver);
+
+ if (e->leave.data() && !e->leave.data()->isAncestorOf(qt_last_mouse_receiver)) //(???) this should not happen
+ QApplicationPrivate::dispatchEnterLeave(0, e->leave.data());
+ qt_last_mouse_receiver = 0;
+
+}
+
+
+void QApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
+{
+ if (e->tlw.isNull())
+ return;
+ QWidget *tlw = e->tlw.data();
+ if (!tlw->isWindow())
+ return; //geo of native child widgets is controlled by lighthouse
+ //so we already have sent the events; besides this new rect
+ //is not mapped to parent
+
+ QRect newRect = e->newGeometry;
+ QRect cr(tlw->geometry());
+ bool isResize = cr.size() != newRect.size();
+ bool isMove = cr.topLeft() != newRect.topLeft();
+ tlw->data->crect = newRect;
+ if (isResize) {
+ QResizeEvent e(tlw->data->crect.size(), cr.size());
+ QApplication::sendSpontaneousEvent(tlw, &e);
+ tlw->update();
+ }
+
+ if (isMove) {
+ //### frame geometry
+ QMoveEvent e(tlw->data->crect.topLeft(), cr.topLeft());
+ QApplication::sendSpontaneousEvent(tlw, &e);
+ }
+}
+
+void QApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e)
+{
+ if (e->topLevel.isNull()) {
+ //qDebug() << "QApplicationPrivate::processCloseEvent NULL";
+ return;
+ }
+ e->topLevel.data()->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
+}
+
+void QApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e)
+{
+ translateRawTouchEvent(e->widget.data(), e->devType, e->points);
+}
+
+void QApplicationPrivate::reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e)
+{
+ // This operation only makes sense after the QApplication constructor runs
+ if (QCoreApplication::startingUp())
+ return;
+
+ QApplication::desktop()->d_func()->updateScreenList();
+ // signal anything listening for creation or deletion of screens
+ QDesktopWidget *desktop = QApplication::desktop();
+ emit desktop->screenCountChanged(e->count);
+}
+
+void QApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e)
+{
+ // This operation only makes sense after the QApplication constructor runs
+ if (QCoreApplication::startingUp())
+ return;
+
+ QApplication::desktop()->d_func()->updateScreenList();
+
+ // signal anything listening for screen geometry changes
+ QDesktopWidget *desktop = QApplication::desktop();
+ emit desktop->resized(e->index);
+
+ // make sure maximized and fullscreen windows are updated
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ QWidget *w = list.at(i);
+ if (w->isFullScreen())
+ w->d_func()->setFullScreenSize_helper();
+ else if (w->isMaximized())
+ w->d_func()->setMaxWindowState_helper();
+ }
+}
+
+void QApplicationPrivate::reportAvailableGeometryChange(
+ QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e)
+{
+ // This operation only makes sense after the QApplication constructor runs
+ if (QCoreApplication::startingUp())
+ return;
+
+ QApplication::desktop()->d_func()->updateScreenList();
+
+ // signal anything listening for screen geometry changes
+ QDesktopWidget *desktop = QApplication::desktop();
+ emit desktop->workAreaResized(e->index);
+
+ // make sure maximized and fullscreen windows are updated
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ QWidget *w = list.at(i);
+ if (w->isFullScreen())
+ w->d_func()->setFullScreenSize_helper();
+ else if (w->isMaximized())
+ w->d_func()->setMaxWindowState_helper();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 789f198242..3a70dd5ade 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1401,7 +1401,7 @@ bool QSymbianControl::isControlActive()
This function is only available on S60.
*/
QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000))
{
Q_D(QApplication);
S60->s60ApplicationFactory = factory;
@@ -1409,7 +1409,7 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int
}
QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal)
- : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
+ : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal))
{
Q_D(QApplication);
S60->s60ApplicationFactory = factory;
@@ -1623,6 +1623,9 @@ extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp
*****************************************************************************/
void qt_cleanup()
{
+#ifdef Q_WS_S60
+ S60->setButtonGroupContainer(0);
+#endif
if(qt_S60Beep) {
delete qt_S60Beep;
qt_S60Beep = 0;
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 6e89ceb173..5f5da592a1 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -115,12 +115,25 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
# if defined(Q_WS_WINCE)
# include <bldver.h>
# endif
-# include <winable.h>
+# if !defined(Q_WS_WINCE)
+# include <winable.h>
+# endif
+#endif
+
+#ifndef QT_NO_GESTURES
+# ifndef GID_ZOOM
+# define GID_ZOOM 3
+# define GID_TWOFINGERTAP 6
+# define GID_PRESSANDTAP 7
+# define GID_ROLLOVER GID_PRESSANDTAP
+# endif
#endif
#ifndef WM_TOUCH
# define WM_TOUCH 0x0240
+#endif
+#ifndef TOUCHEVENTF_MOVE
# define TOUCHEVENTF_MOVE 0x0001
# define TOUCHEVENTF_DOWN 0x0002
# define TOUCHEVENTF_UP 0x0004
@@ -207,8 +220,6 @@ static void resolveAygLibs()
if (!aygResolved) {
aygResolved = true;
QSystemLibrary ayglib(QLatin1String("aygshell"));
- if (!ayglib.load())
- return;
ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture");
}
}
@@ -944,29 +955,36 @@ bool qt_nograb() // application no-grab option
typedef QHash<QString, int> WinClassNameHash;
Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
+//
+// If 0 is passed as the widget pointer, register a window class
+// for QWidget as default. This is used in QGLTemporaryContext
+// during GL initialization, where we don't want to use temporary
+// QWidgets or QGLWidgets, neither do we want to have separate code
+// to register window classes.
+//
const QString qt_reg_winclass(QWidget *w) // register window class
{
- int flags = w->windowFlags();
- int type = flags & Qt::WindowType_Mask;
+ Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0;
+ Qt::WindowFlags type = flags & Qt::WindowType_Mask;
uint style;
bool icon;
QString cname;
- if (qt_widget_private(w)->isGLWidget) {
+ if (w && qt_widget_private(w)->isGLWidget) {
cname = QLatin1String("QGLWidget");
style = CS_DBLCLKS;
#ifndef Q_WS_WINCE
style |= CS_OWNDC;
#endif
icon = true;
- } else if (flags & Qt::MSWindowsOwnDC) {
+ } else if (w && (flags & Qt::MSWindowsOwnDC)) {
cname = QLatin1String("QWidgetOwnDC");
style = CS_DBLCLKS;
#ifndef Q_WS_WINCE
style |= CS_OWNDC;
#endif
icon = true;
- } else if (type == Qt::Tool || type == Qt::ToolTip){
+ } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) {
style = CS_DBLCLKS;
if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) {
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
@@ -981,7 +999,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
style |= CS_SAVEBITS;
#endif
icon = false;
- } else if (type == Qt::Popup) {
+ } else if (w && (type == Qt::Popup)) {
cname = QLatin1String("QPopup");
style = CS_DBLCLKS;
#ifndef Q_WS_WINCE
@@ -1035,7 +1053,12 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (winclassNames()->contains(cname)) // already registered in our list
return cname;
+#ifndef Q_WS_WINCE
+ WNDCLASSEX wc;
+ wc.cbSize = sizeof(WNDCLASSEX);
+#else
WNDCLASS wc;
+#endif
wc.style = style;
wc.lpfnWndProc = (WNDPROC)QtWndProc;
wc.cbClsExtra = 0;
@@ -1044,22 +1067,38 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (icon) {
wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
#ifndef Q_WS_WINCE
- if (!wc.hIcon)
+ if (wc.hIcon) {
+ int sw = GetSystemMetrics(SM_CXSMICON);
+ int sh = GetSystemMetrics(SM_CYSMICON);
+ wc.hIconSm = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, sw, sh, 0);
+ } else {
wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ wc.hIconSm = 0;
+ }
#endif
} else {
wc.hIcon = 0;
+#ifndef Q_WS_WINCE
+ wc.hIconSm = 0;
+#endif
}
wc.hCursor = 0;
#ifndef Q_WS_WINCE
- wc.hbrBackground = qt_widget_private(w)->isGLWidget ? 0 : (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
+ HBRUSH brush = 0;
+ if (w && !qt_widget_private(w)->isGLWidget)
+ brush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
+ wc.hbrBackground = brush;
#else
wc.hbrBackground = 0;
#endif
wc.lpszMenuName = 0;
wc.lpszClassName = (wchar_t*)cname.utf16();
+#ifndef Q_WS_WINCE
+ ATOM atom = RegisterClassEx(&wc);
+#else
ATOM atom = RegisterClass(&wc);
+#endif
#ifndef QT_NO_DEBUG
if (!atom)
@@ -1074,8 +1113,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
Q_GUI_EXPORT const QString qt_getRegisteredWndClass()
{
- QWidget w;
- return qt_reg_winclass(&w);
+ return qt_reg_winclass(0);
}
static void unregWinClasses()
@@ -2324,7 +2362,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa
case WM_GETOBJECT:
{
// Ignoring all requests while starting up
- if (QApplication::startingUp() || QApplication::closingDown() || (LONG)lParam != OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || lParam != (LPARAM)OBJID_CLIENT) {
result = false;
break;
}
@@ -3676,13 +3714,11 @@ static void initWinTabFunctions()
return;
QSystemLibrary library(QLatin1String("wintab32"));
- if (library.load()) {
- ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
- ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
- ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable");
- ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
- ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
- }
+ ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW");
+ ptrWTGet = (PtrWTGet)library.resolve("WTGetW");
+ ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable");
+ ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap");
+ ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet");
#endif // Q_OS_WINCE
}
#endif // QT_NO_TABLETEVENT
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index f28868cdf7..2c5172231b 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -483,11 +483,9 @@ static void* qt_load_library_runtime(const char *library, int vernum,
Q_FOREACH(int version, versions) {
QLatin1String libName(library);
QLibrary xfixesLib(libName, version);
- if (xfixesLib.load()) {
- void *ptr = xfixesLib.resolve(symbol);
- if (ptr)
- return ptr;
- }
+ void *ptr = xfixesLib.resolve(symbol);
+ if (ptr)
+ return ptr;
}
return 0;
}
@@ -1739,6 +1737,9 @@ void qt_init(QApplicationPrivate *priv, int,
} else {
// Qt controls everything (default)
+ if (QApplication::testAttribute(Qt::AA_X11InitThreads))
+ XInitThreads();
+
// Set application name and class
char *app_class = 0;
if (argv && argv[0]) {
@@ -2014,12 +2015,15 @@ void qt_init(QApplicationPrivate *priv, int,
(PtrXRRRootToScreen) xrandrLib.resolve("XRRRootToScreen");
X11->ptrXRRQueryExtension =
(PtrXRRQueryExtension) xrandrLib.resolve("XRRQueryExtension");
+ X11->ptrXRRSizes =
+ (PtrXRRSizes) xrandrLib.resolve("XRRSizes");
}
# else
X11->ptrXRRSelectInput = XRRSelectInput;
X11->ptrXRRUpdateConfiguration = XRRUpdateConfiguration;
X11->ptrXRRRootToScreen = XRRRootToScreen;
X11->ptrXRRQueryExtension = XRRQueryExtension;
+ X11->ptrXRRSizes = XRRSizes;
# endif
if (X11->ptrXRRQueryExtension
@@ -2608,22 +2612,20 @@ void qt_init(QApplicationPrivate *priv, int,
#if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET)
QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this.
- if (wacom.load()) {
- // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x
- ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit");
- ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice");
- ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam");
- ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice");
- ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm");
-
- if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0
- || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none.
+ // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x
+ ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit");
+ ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice");
+ ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam");
+ ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice");
+ ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm");
+
+ if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0
+ || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none.
ptrWacomConfigInit = 0;
ptrWacomConfigOpenDevice = 0;
ptrWacomConfigGetRawParam = 0;
ptrWacomConfigCloseDevice = 0;
ptrWacomConfigTerm = 0;
- }
}
#endif
}
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index bae43fa5e4..ba7ad0caac 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -631,7 +631,7 @@ QByteArray QMimeDataWrapper::encodedData(const char *format) const
return data->data(QLatin1String(format));
} else{
QVariant variant = data->imageData();
- QImage img = qVariantValue<QImage>(variant);
+ QImage img = qvariant_cast<QImage>(variant);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qclipboard_qpa.cpp
new file mode 100644
index 0000000000..92b9e83255
--- /dev/null
+++ b/src/gui/kernel/qclipboard_qpa.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qmimedata.h"
+#include "qapplication.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+
+class QClipboardData
+{
+public:
+ QClipboardData();
+ ~QClipboardData();
+
+ void setSource(QMimeData* s)
+ {
+ if (s == src)
+ return;
+ delete src;
+ src = s;
+ }
+ QMimeData* source()
+ { return src; }
+
+ void clear();
+
+private:
+ QMimeData* src;
+};
+
+QClipboardData::QClipboardData()
+{
+ src = 0;
+}
+
+QClipboardData::~QClipboardData()
+{
+ delete src;
+}
+
+void QClipboardData::clear()
+{
+ delete src;
+ src = 0;
+}
+
+
+static QClipboardData *internalCbData = 0;
+
+static void cleanupClipboardData()
+{
+ delete internalCbData;
+ internalCbData = 0;
+}
+
+static QClipboardData *clipboardData()
+{
+ if (internalCbData == 0) {
+ internalCbData = new QClipboardData;
+ qAddPostRoutine(cleanupClipboardData);
+ }
+ return internalCbData;
+}
+
+
+void QClipboard::clear(Mode mode)
+{
+ setText(QString(), mode);
+}
+
+
+bool QClipboard::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ if (mode != Clipboard) return 0;
+
+ QClipboardData *d = clipboardData();
+ return d->source();
+}
+
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ if (mode != Clipboard) return;
+
+ QClipboardData *d = clipboardData();
+
+ d->setSource(src);
+
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard)
+ qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!");
+ return false;
+}
+
+void QClipboard::connectNotify( const char * )
+{
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+#endif // QT_NO_CLIPBOARD
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm
index 478bc960d6..872f31dec7 100644
--- a/src/gui/kernel/qcocoaapplication_mac.mm
+++ b/src/gui/kernel/qcocoaapplication_mac.mm
@@ -78,6 +78,7 @@
#include <private/qcocoaapplication_mac_p.h>
#include <private/qcocoaapplicationdelegate_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qcocoaintrospection_p.h>
QT_USE_NAMESPACE
@@ -116,12 +117,30 @@ QT_USE_NAMESPACE
quint64 lower = [event data1];
quint64 upper = [event data2];
QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32));
- [args->target performSelector:args->selector];
+ // Special case for convenience: if the argument is an NSNumber, we unbox it directly.
+ // Use NSValue instead if this behaviour is unwanted.
+ id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 intValue] : args->arg1;
+ id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 intValue] : args->arg2;
+ switch (args->argCount) {
+ case 0:
+ [args->target performSelector:args->selector];
+ break;
+ case 1:
+ [args->target performSelector:args->selector withObject:a1];
+ break;
+ case 3:
+ [args->target performSelector:args->selector withObject:a1 withObject:a2];
+ break;
+ }
+
delete args;
}
-- (BOOL)qt_sendEvent:(NSEvent *)event
+- (BOOL)qt_filterEvent:(NSEvent *)event
{
+ if (qApp->macEventFilter(0, reinterpret_cast<EventRef>(event)))
+ return true;
+
if ([event type] == NSApplicationDefined) {
switch ([event subtype]) {
case QtCocoaEventSubTypePostMessage:
@@ -138,20 +157,66 @@ QT_USE_NAMESPACE
@implementation QNSApplication
-// WARNING: If Qt did not create NSApplication (this can e.g.
-// happend if Qt is used as a plugin from a 3rd-party cocoa
-// application), QNSApplication::sendEvent will never be called.
-// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE.
-// Plugin developers that _do_ control the NSApplication sub-class
-// implementation of the 3rd-party application can call qt_sendEvent
-// from the sub-class event handler (like we do here) to work around
-// any issues.
+- (void)qt_sendEvent_original:(NSEvent *)event
+{
+ Q_UNUSED(event);
+ // This method will only be used as a signature
+ // template for the method we add into NSApplication
+ // containing the original [NSApplication sendEvent:] implementation
+}
+
+- (void)qt_sendEvent_replacement:(NSEvent *)event
+{
+ // This method (or its implementation to be precise) will
+ // be called instead of sendEvent if redirection occurs.
+ // 'self' will then be an instance of NSApplication
+ // (and not QNSApplication)
+ if (![NSApp qt_filterEvent:event])
+ [self qt_sendEvent_original:event];
+}
+
- (void)sendEvent:(NSEvent *)event
{
- if (![self qt_sendEvent:event])
+ // This method will be called if
+ // no redirection occurs
+ if (![NSApp qt_filterEvent:event])
[super sendEvent:event];
}
+- (void)qtDispatcherToQAction:(id)sender
+{
+ // Forward actions sendt from the menu bar (e.g. quit) to the menu loader.
+ // Having this method here means that we are the last stop in the responder
+ // chain, and that we are able to handle menu actions even when no window is
+ // visible on screen. Note: If Qt is used as a plugin, Qt will not use a
+ // native menu bar. Hence, we will also not need to do any redirection etc. as
+ // we do with sendEvent.
+ [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender];
+}
+
@end
+QT_BEGIN_NAMESPACE
+
+void qt_redirectNSApplicationSendEvent()
+{
+ if ([NSApp isMemberOfClass:[QNSApplication class]]) {
+ // No need to change implementation since Qt
+ // already controls a subclass of NSApplication
+ return;
+ }
+
+ // Change the implementation of [NSApplication sendEvent] to the
+ // implementation of qt_sendEvent_replacement found in QNSApplication.
+ // And keep the old implementation that gets overwritten inside a new
+ // method 'qt_sendEvent_original' that we add to NSApplication
+ qt_cocoa_change_implementation(
+ [NSApplication class],
+ @selector(sendEvent:),
+ [QNSApplication class],
+ @selector(qt_sendEvent_replacement:),
+ @selector(qt_sendEvent_original:));
+ }
+
+QT_END_NAMESPACE
#endif
diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h
index 230e780c42..0c3f5e442d 100644
--- a/src/gui/kernel/qcocoaapplication_mac_p.h
+++ b/src/gui/kernel/qcocoaapplication_mac_p.h
@@ -101,11 +101,17 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate)
- (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel;
- (void)qt_sendPostedMessage:(NSEvent *)event;
-- (BOOL)qt_sendEvent:(NSEvent *)event;
+- (BOOL)qt_filterEvent:(NSEvent *)event;
@end
@interface QNSApplication : NSApplication {
}
@end
+QT_BEGIN_NAMESPACE
+
+void qt_redirectNSApplicationSendEvent();
+
+QT_END_NAMESPACE
+
#endif
diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
index a520e273f8..bf4d9e5d49 100644
--- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
+++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm
@@ -78,6 +78,7 @@
#import <private/qcocoaapplicationdelegate_mac_p.h>
#import <private/qcocoamenuloader_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <private/qapplication_p.h>
#include <private/qt_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
@@ -173,7 +174,7 @@ static void cleanupCocoaApplicationDelegate()
qtMenuLoader = menuLoader;
}
-- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
+- (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader
{
return [[qtMenuLoader retain] autorelease];
}
@@ -256,7 +257,7 @@ static void cleanupCocoaApplicationDelegate()
onApplicationChangedActivation(true);
}
-- (void)applicationDidResignActive:(NSNotification *)notification;
+- (void)applicationDidResignActive:(NSNotification *)notification
{
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
diff --git a/src/gui/kernel/qcocoaintrospection_mac.mm b/src/gui/kernel/qcocoaintrospection_mac.mm
new file mode 100644
index 0000000000..9b536b7a1e
--- /dev/null
+++ b/src/gui/kernel/qcocoaintrospection_mac.mm
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Copyright (c) 2007-2008, Apple, Inc.
+**
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** * Neither the name of Apple, Inc. nor the names of its contributors
+** may be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#include <private/qcocoaintrospection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
+#endif
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ // The following code replaces the _implementation_ for the selector we want to hack
+ // (originalSel) with the implementation found in proxyClass. Then it creates
+ // a new 'backup' method inside baseClass containing the old, original,
+ // implementation (fakeSel). You can let the proxy implementation of originalSel
+ // call fakeSel if needed (similar approach to calling a super class implementation).
+ // fakeSel must also be implemented in proxyClass, as the signature is used
+ // as template for the method one we add into baseClass.
+ // NB: You will typically never create any instances of proxyClass; we use it
+ // only for stealing its contents and put it into baseClass.
+ if (!replacementSel)
+ replacementSel = originalSel;
+
+ Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
+ Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel);
+ IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod));
+
+ if (backupSel) {
+ Method backupMethod = class_getInstanceMethod(proxyClass, backupSel);
+ class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod));
+ }
+#endif
+ }
+}
+
+void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
+#endif
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ Method originalMethod = class_getInstanceMethod(baseClass, originalSel);
+ Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel);
+ method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass));
+#endif
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcocoaintrospection_p.h b/src/gui/kernel/qcocoaintrospection_p.h
new file mode 100644
index 0000000000..b9422e826e
--- /dev/null
+++ b/src/gui/kernel/qcocoaintrospection_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Copyright (c) 2007-2008, Apple, Inc.
+**
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+**
+** * Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** * Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** * Neither the name of Apple, Inc. nor the names of its contributors
+** may be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#import <objc/objc-class.h>
+
+QT_BEGIN_NAMESPACE
+
+void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0);
+void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel);
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm
index 0b00211c7d..71ff011069 100644
--- a/src/gui/kernel/qcocoamenuloader_mac.mm
+++ b/src/gui/kernel/qcocoamenuloader_mac.mm
@@ -70,13 +70,13 @@ QT_USE_NAMESPACE
showAllItem = [[appMenu itemWithTitle:@"Show All"] retain];
// Get the names in the nib to match the app name set by Qt.
- NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName()));
+ const NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName()));
[quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
- withString:appName]];
+ withString:const_cast<NSString *>(appName)]];
[hideItem setTitle:[[hideItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
- withString:appName]];
+ withString:const_cast<NSString *>(appName)]];
[aboutItem setTitle:[[aboutItem title] stringByReplacingOccurrencesOfString:@"NewApplication"
- withString:appName]];
+ withString:const_cast<NSString *>(appName)]];
[appName release];
// Disable the items that don't do anything. If someone associates a QAction with them
// They should get synced back in.
@@ -170,12 +170,12 @@ QT_USE_NAMESPACE
return [[aboutQtItem retain] autorelease];
}
-- (NSMenuItem *)hideMenuItem;
+- (NSMenuItem *)hideMenuItem
{
return [[hideItem retain] autorelease];
}
-- (NSMenuItem *)appSpecificMenuItem;
+- (NSMenuItem *)appSpecificMenuItem
{
// Create an App-Specific menu item, insert it into the menu and return
// it as an autorelease item.
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index 9c110fdf83..df0f24e96f 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -136,16 +136,6 @@ QT_END_NAMESPACE
qt_dispatchTabletProximityEvent(tabletEvent);
}
-- (void)qtDispatcherToQAction:(id)sender
-{
- // If this window is modal, the menu bar will be modally shaddowed.
- // In that case, since the window will be in the first responder chain,
- // we can still catch the trigger here and forward it to the menu bar.
- // This is needed as a single modal dialog on Qt should be able to access
- // the application menu (e.g. quit).
- [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender];
-}
-
- (void)terminate:(id)sender
{
// This function is called from the quit item in the menubar when this window
@@ -155,17 +145,6 @@ QT_END_NAMESPACE
- (void)sendEvent:(NSEvent *)event
{
- if ([event type] == NSApplicationDefined) {
- switch ([event subtype]) {
- case QtCocoaEventSubTypePostMessage:
- [NSApp qt_sendPostedMessage:event];
- return;
- default:
- break;
- }
- return;
- }
-
QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
// Cocoa can hold onto the window after we've disavowed its knowledge. So,
// if we get sent an event afterwards just have it go through the super's
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 749472a55f..5ea893c626 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -207,6 +207,7 @@ static int qCocoaViewCount = 0;
composing = false;
sendKeyEvents = true;
+ fromKeyDownEvent = false;
[self setHidden:YES];
return self;
}
@@ -301,7 +302,6 @@ static int qCocoaViewCount = 0;
QMimeData *mimeData = dropData;
if (QDragManager::self()->source())
mimeData = QDragManager::self()->dragPrivate()->data;
- NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
QPoint posDrag(localPoint.x, localPoint.y);
NSDragOperation nsActions = [sender draggingSourceOperationMask];
@@ -364,7 +364,6 @@ static int qCocoaViewCount = 0;
return NSDragOperationNone;
}
// return last value, if we are still in the answerRect.
- NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
NSDragOperation nsActions = [sender draggingSourceOperationMask];
QPoint posDrag(localPoint.x, localPoint.y);
@@ -433,7 +432,6 @@ static int qCocoaViewCount = 0;
dragEnterSequence = -1;
[self addDropData:sender];
- NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint];
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
QPoint posDrop(localPoint.x, localPoint.y);
@@ -469,14 +467,14 @@ static int qCocoaViewCount = 0;
[super dealloc];
}
-- (BOOL)isOpaque;
+- (BOOL)isOpaque
{
if (!qwidgetprivate)
return [super isOpaque];
return qwidgetprivate->isOpaque;
}
-- (BOOL)isFlipped;
+- (BOOL)isFlipped
{
return YES;
}
@@ -508,7 +506,7 @@ static int qCocoaViewCount = 0;
}
// Make sure the opengl context is updated on resize.
- if (qwidgetprivate && qwidgetprivate->isGLWidget) {
+ if (qwidgetprivate && qwidgetprivate->isGLWidget && [self window]) {
qwidgetprivate->needWindowChange = true;
QEvent event(QEvent::MacGLWindowChange);
qApp->sendEvent(qwidget, &event);
@@ -532,16 +530,41 @@ static int qCocoaViewCount = 0;
if (!qwidget)
return;
- if (QApplicationPrivate::graphicsSystem() != 0) {
- if (qwidgetprivate->maybeBackingStore()) {
- // Drawing is handled on the window level
- // See qcocoasharedwindowmethods_mac_p.h
- if (!qwidget->testAttribute(Qt::WA_PaintOnScreen))
- return;
+ // We use a different graphics system.
+ if (QApplicationPrivate::graphicsSystem() != 0 && !qwidgetprivate->isInUnifiedToolbar) {
+
+ // Qt handles the painting occuring inside the window.
+ // Cocoa also keeps track of all widgets as NSView and therefore might
+ // ask for a repainting of a widget even if Qt is already taking care of it.
+ //
+ // The only valid reason for Cocoa to call drawRect: is for window manipulation
+ // (ie. resize, ...).
+ //
+ // Qt will then forward the update to the children.
+ if (qwidget->isWindow()) {
+ qwidget->update(qwidget->rect());
+ qwidgetprivate->syncBackingStore(qwidget->rect());
}
+
+ // Since we don't want to use the native engine, we must exit, however
+ // widgets that are set to paint on screen, spesifically QGLWidget,
+ // requires the following code to execute in order to be drawn.
+ if (!qwidget->testAttribute(Qt::WA_PaintOnScreen))
+ return;
}
+
CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ CGContextRetain(cg);
qwidgetprivate->hd = cg;
+
+ // We steal the CGContext for flushing in the unified toolbar with the raster engine.
+ if (QApplicationPrivate::graphicsSystem() != 0 && qwidgetprivate->isInUnifiedToolbar) {
+ qwidgetprivate->cgContext = cg;
+ qwidgetprivate->hasOwnContext = true;
+ qwidgetprivate->unifiedSurface->flush(qwidget, qwidgetprivate->ut_rg, qwidgetprivate->ut_pt);
+ return;
+ }
+
CGContextSaveGState(cg);
if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event.
@@ -595,8 +618,8 @@ static int qCocoaViewCount = 0;
// is the case. This makes sure child widgets are drawn as well, Cocoa does not know about
// those and wont send them drawRect calls.
if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false) {
- if (engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
- && (qwidget->isWindow() || qwidget->autoFillBackground())
+ if ((engine && !qwidget->testAttribute(Qt::WA_NoSystemBackground)
+ && (qwidget->isWindow() || qwidget->autoFillBackground()))
|| qwidget->testAttribute(Qt::WA_TintedBackground)
|| qwidget->testAttribute(Qt::WA_StyledBackground)) {
#ifdef DEBUG_WIDGET_PAINT
@@ -631,6 +654,7 @@ static int qCocoaViewCount = 0;
}
qwidgetprivate->hd = 0;
CGContextRestoreGState(cg);
+ CGContextRelease(cg);
}
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
@@ -953,32 +977,32 @@ static int qCocoaViewCount = 0;
}
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-- (void)touchesBeganWithEvent:(NSEvent *)event;
+- (void)touchesBeganWithEvent:(NSEvent *)event
{
bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
}
-- (void)touchesMovedWithEvent:(NSEvent *)event;
+- (void)touchesMovedWithEvent:(NSEvent *)event
{
bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
}
-- (void)touchesEndedWithEvent:(NSEvent *)event;
+- (void)touchesEndedWithEvent:(NSEvent *)event
{
bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
}
-- (void)touchesCancelledWithEvent:(NSEvent *)event;
+- (void)touchesCancelledWithEvent:(NSEvent *)event
{
bool all = qwidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
qt_translateRawTouchEvent(qwidget, QTouchEvent::TouchPad, QCocoaTouch::getCurrentTouchPointList(event, all));
}
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-- (void)magnifyWithEvent:(NSEvent *)event;
+- (void)magnifyWithEvent:(NSEvent *)event
{
if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
return;
@@ -993,7 +1017,7 @@ static int qCocoaViewCount = 0;
#endif // QT_NO_GESTURES
}
-- (void)rotateWithEvent:(NSEvent *)event;
+- (void)rotateWithEvent:(NSEvent *)event
{
if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
return;
@@ -1008,7 +1032,7 @@ static int qCocoaViewCount = 0;
#endif // QT_NO_GESTURES
}
-- (void)swipeWithEvent:(NSEvent *)event;
+- (void)swipeWithEvent:(NSEvent *)event
{
if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
return;
@@ -1030,7 +1054,7 @@ static int qCocoaViewCount = 0;
#endif // QT_NO_GESTURES
}
-- (void)beginGestureWithEvent:(NSEvent *)event;
+- (void)beginGestureWithEvent:(NSEvent *)event
{
if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
return;
@@ -1044,7 +1068,7 @@ static int qCocoaViewCount = 0;
#endif // QT_NO_GESTURES
}
-- (void)endGestureWithEvent:(NSEvent *)event;
+- (void)endGestureWithEvent:(NSEvent *)event
{
if (!QApplicationPrivate::tryModalHelper(qwidget, 0))
return;
@@ -1199,7 +1223,9 @@ static int qCocoaViewCount = 0;
&& !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly
|| widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly
|| widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) {
+ fromKeyDownEvent = true;
[qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]];
+ fromKeyDownEvent = false;
}
if (sendKeyEvents && !composing) {
bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey);
@@ -1269,7 +1295,10 @@ static int qCocoaViewCount = 0;
};
}
- if ([aString length] && composing) {
+ // When entering characters through Character Viewer or Keyboard Viewer, the text is passed
+ // through this insertText method. Since we dont receive a keyDown Event in such cases, the
+ // composing flag will be false.
+ if (([aString length] && composing) || !fromKeyDownEvent) {
// Send the commit string to the widget.
composing = false;
sendKeyEvents = false;
@@ -1383,7 +1412,7 @@ static int qCocoaViewCount = 0;
if (!selectedText.isEmpty()) {
QCFString string(selectedText.mid(theRange.location, theRange.length));
const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
- return [[[NSAttributedString alloc] initWithString:tmpString] autorelease];
+ return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease];
} else {
return nil;
}
@@ -1579,7 +1608,6 @@ Qt::DropAction QDragManager::drag(QDrag *o)
dndParams.localPoint.y + pix.height() - hotspot.y()};
NSSize mouseOffset = {0.0, 0.0};
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- NSPoint windowPoint = [dndParams.theEvent locationInWindow];
dragPrivate()->executed_action = Qt::ActionMask;
// do the drag
[dndParams.view retain];
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 45eafdd3df..8d57f951ef 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -86,6 +86,7 @@ Q_GUI_EXPORT
bool composing;
int composingLength;
bool sendKeyEvents;
+ bool fromKeyDownEvent;
QString *composingText;
NSInteger dragEnterSequence;
}
diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm
index f1a2f6723a..28f09add74 100644
--- a/src/gui/kernel/qcocoawindow_mac.mm
+++ b/src/gui/kernel/qcocoawindow_mac.mm
@@ -55,7 +55,7 @@ QT_USE_NAMESPACE
@implementation NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration))
-- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask;
+- (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask
{
self = [self initWithContentRect:rect styleMask:mask backing:NSBackingStoreBuffered defer:YES];
if (self) {
diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm
index ebce6acab2..b8be6277f2 100644
--- a/src/gui/kernel/qcocoawindowdelegate_mac.mm
+++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm
@@ -138,7 +138,7 @@ static void cleanupCocoaWindowDelegate()
}
}
-- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window;
+- (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window
{
if (!window)
return; // Nothing to do.
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index 610469f8a3..d90375da36 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -96,6 +96,10 @@ public:
QCursor(const QCursor &cursor);
~QCursor();
QCursor &operator=(const QCursor &cursor);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QCursor &operator=(QCursor &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
operator QVariant() const;
Qt::CursorShape shape() const;
@@ -126,7 +130,7 @@ public:
static int x11Screen();
#elif defined(Q_WS_MAC)
Qt::HANDLE handle() const;
-#elif defined(Q_WS_QWS)
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
int handle() const;
#elif defined(Q_OS_SYMBIAN)
Qt::HANDLE handle() const;
diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h
index 885c345cb5..660a2a5e8b 100644
--- a/src/gui/kernel/qcursor_p.h
+++ b/src/gui/kernel/qcursor_p.h
@@ -91,7 +91,7 @@ public:
short hx, hy;
#if defined (Q_WS_MAC)
int mId;
-#elif defined(Q_WS_QWS)
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
int id;
#endif
#if defined (Q_WS_WIN)
diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp
new file mode 100644
index 0000000000..a6ae7d30f5
--- /dev/null
+++ b/src/gui/kernel/qcursor_qpa.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qcursor.h>
+#include <private/qcursor_p.h>
+#include <qbitmap.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+#ifndef QT_NO_CURSOR
+
+static int nextCursorId = Qt::BitmapCursor;
+
+/*****************************************************************************
+ Internal QCursorData class
+ *****************************************************************************/
+
+QCursorData::QCursorData(Qt::CursorShape s)
+ : cshape(s), bm(0), bmm(0), hx(0), hy(0), id(s)
+{
+ ref = 1;
+}
+
+QCursorData::~QCursorData()
+{
+ delete bm;
+ delete bmm;
+}
+
+
+/*****************************************************************************
+ Global cursors
+ *****************************************************************************/
+
+extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
+
+int QCursor::handle() const
+{
+ return d->id;
+}
+
+
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+{
+ if (!QCursorData::initialized)
+ QCursorData::initialize();
+ if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
+ qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
+ QCursorData *c = qt_cursorTable[0];
+ c->ref.ref();
+ return c;
+ }
+ QCursorData *d = new QCursorData;
+ d->bm = new QBitmap(bitmap);
+ d->bmm = new QBitmap(mask);
+ d->cshape = Qt::BitmapCursor;
+ d->id = ++nextCursorId;
+ d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
+ d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+
+ return d;
+}
+
+void QCursorData::update()
+{
+}
+
+#endif //QT_NO_CURSOR
+
+extern int qt_last_x,qt_last_y;
+
+QPoint QCursor::pos()
+{
+ return QPoint(qt_last_x, qt_last_y);
+}
+
+void QCursor::setPos(int x, int y)
+{
+ // Need to check, since some X servers generate null mouse move
+ // events, causing looping in applications which call setPos() on
+ // every mouse move event.
+ //
+ if (pos() == QPoint(x, y))
+ return;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_qpa.cpp b/src/gui/kernel/qdesktopwidget_qpa.cpp
new file mode 100644
index 0000000000..cff05f5836
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_qpa.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "private/qapplication_p.h"
+#include "private/qgraphicssystem_p.h"
+#include <QWidget>
+#include "private/qwidget_p.h"
+#include "private/qdesktopwidget_qpa_p.h"
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+void QDesktopWidgetPrivate::updateScreenList()
+{
+ QList<QPlatformScreen *> screenList = QApplicationPrivate::platformIntegration()->screens();
+ int targetLength = screenList.length();
+ int currentLength = screens.length();
+
+ // Add or remove screen widgets as necessary
+ if(currentLength > targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength-- > targetLength) {
+ screen = screens.takeLast();
+ delete screen;
+ }
+ }
+ else if (currentLength < targetLength) {
+ QDesktopScreenWidget *screen;
+ while (currentLength < targetLength) {
+ screen = new QDesktopScreenWidget(currentLength++);
+ screens.append(screen);
+ }
+ }
+
+ QRegion virtualGeometry;
+ bool doVirtualGeometry = QApplicationPrivate::platformIntegration()->isVirtualDesktop();
+
+ // update the geometry of each screen widget
+ for (int i = 0; i < screens.length(); i++) {
+ QRect screenGeometry = screenList.at(i)->geometry();
+ screens.at(i)->setGeometry(screenGeometry);
+ if (doVirtualGeometry)
+ virtualGeometry += screenGeometry;
+ }
+
+ virtualScreen.setGeometry(virtualGeometry.boundingRect());
+ Q_Q(QDesktopWidget);
+ q->setGeometry(virtualScreen.geometry());
+}
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ Q_D(QDesktopWidget);
+ setObjectName(QLatin1String("desktop"));
+ d->updateScreenList();
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return QApplicationPrivate::platformIntegration()->isVirtualDesktop();
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return 0;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ return qMax(pi->screens().size(), 1);
+}
+
+QWidget *QDesktopWidget::screen(int screen)
+{
+ Q_D(QDesktopWidget);
+ if (QApplicationPrivate::platformIntegration()->isVirtualDesktop())
+ return &d->virtualScreen;
+ if (screen < 0 || screen >= d->screens.length())
+ return d->screens.at(0);
+ return d->screens.at(screen);
+}
+
+const QRect QDesktopWidget::availableGeometry(int screenNo) const
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens[screenNo]->availableGeometry();
+}
+
+const QRect QDesktopWidget::screenGeometry(int screenNo) const
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+ if (screenNo == -1)
+ screenNo = 0;
+ if (screenNo < 0 || screenNo >= screens.size())
+ return QRect();
+ else
+ return screens[screenNo]->geometry();
+}
+
+int QDesktopWidget::screenNumber(const QWidget *w) const
+{
+ if (!w)
+ return 0;
+
+ QRect frame = w->frameGeometry();
+ if (!w->isWindow())
+ frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
+ const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2;
+ return screenNumber(midpoint);
+}
+
+int QDesktopWidget::screenNumber(const QPoint &p) const
+{
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+
+ for (int i = 0; i < screens.size(); ++i)
+ if (screens[i]->geometry().contains(p))
+ return i;
+
+ return primaryScreen(); //even better would be closest screen
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdesktopwidget_qpa_p.h b/src/gui/kernel/qdesktopwidget_qpa_p.h
new file mode 100644
index 0000000000..8bed09d5fd
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_qpa_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESKTOPWIDGET_QPA_P_H
+#define QDESKTOPWIDGET_QPA_P_H
+
+#include "QDesktopWidget"
+#include "private/qwidget_p.h"
+
+class QDesktopScreenWidget : public QWidget {
+ Q_OBJECT
+public:
+ QDesktopScreenWidget(int screenNumber = -1) { setWindowFlags(Qt::Desktop); setVisible(false); d_func()->screenNumber = screenNumber; }
+};
+
+class QDesktopWidgetPrivate : public QWidgetPrivate {
+ Q_DECLARE_PUBLIC(QDesktopWidget)
+
+public:
+ ~QDesktopWidgetPrivate() {foreach(QDesktopScreenWidget *s, screens) delete s; }
+ void updateScreenList();
+
+ QList<QDesktopScreenWidget *> screens;
+ QDesktopScreenWidget virtualScreen;
+};
+
+#endif // QDESKTOPWIDGET_QPA_P_H
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
index b82264487d..d57b355ef4 100644
--- a/src/gui/kernel/qdesktopwidget_win.cpp
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -156,10 +156,8 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
#ifndef Q_OS_WINCE
QSystemLibrary user32Lib(QLatin1String("user32"));
- if (user32Lib.load()) {
- enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
- getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
- }
+ enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
+ getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
if (!enumDisplayMonitors || !getMonitorInfo) {
screenCount = GetSystemMetrics(80); // SM_CMONITORS
@@ -174,11 +172,9 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
getMonitorInfo = 0;
#else
QSystemLibrary coreLib(QLatin1String("coredll"));
- if (coreLib.load()) {
- // CE >= 4.0 case
- enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
- getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
- }
+ // CE >= 4.0 case
+ enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
+ getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
if ((!enumDisplayMonitors || !getMonitorInfo)) {
screenCount = GetSystemMetrics(SM_CMONITORS);
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 2ebe78c349..9a55b18ad8 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -261,11 +261,11 @@ public:
#endif
private:
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
Qt::DropAction currentActionForOverrideCursor;
#endif
#ifdef Q_OS_SYMBIAN
-#ifndef QT_NO_CURSOR
+#ifndef QT_NO_CURSOR
QCursor overrideCursor;
#endif
#endif
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index f0ddd83100..e7abb473c8 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -4392,7 +4392,7 @@ void QGestureEvent::accept(QGesture *gesture)
of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}.
Clearing the accept flag indicates that the event receiver does not
- want the gesture. Unwanted gestures may be propgated to the parent widget.
+ want the gesture. Unwanted gestures may be propagated to the parent widget.
\sa QGestureEvent::accept()
*/
@@ -4568,4 +4568,223 @@ const QGestureEventPrivate *QGestureEvent::d_func() const
#endif // QT_NO_GESTURES
+/*!
+ \class QScrollPrepareEvent
+ \since 4.8
+ \ingroup events
+
+ \brief The QScrollPrepareEvent class is send in preparation of a scrolling.
+
+ The scroll prepare event is send before scrolling (usually by QScroller) is started.
+ The object receiving this event should set viewportSize, maxContentPos and contentPos.
+ It also should accept this event to indicate that scrolling should be started.
+
+ It is not guaranteed that a QScrollEvent will be send after an acceepted
+ QScrollPrepareEvent, e.g. in a case where the maximum content position is (0,0).
+
+ \sa QScrollEvent, QScroller
+*/
+
+/*!
+ Creates new QScrollPrepareEvent
+ The \a startPos is the position of a touch or mouse event that started the scrolling.
+*/
+QScrollPrepareEvent::QScrollPrepareEvent(const QPointF &startPos)
+ : QEvent(QEvent::ScrollPrepare)
+{
+ d = reinterpret_cast<QEventPrivate *>(new QScrollPrepareEventPrivate());
+ d_func()->startPos = startPos;
+}
+
+/*!
+ Destroys QScrollEvent.
+*/
+QScrollPrepareEvent::~QScrollPrepareEvent()
+{
+ delete reinterpret_cast<QScrollPrepareEventPrivate *>(d);
+}
+
+/*!
+ Returns the position of the touch or mouse event that started the scrolling.
+*/
+QPointF QScrollPrepareEvent::startPos() const
+{
+ return d_func()->startPos;
+}
+
+/*!
+ Returns size of the area that is to be scrolled as set by setViewportSize
+
+ \sa setViewportSize()
+*/
+QSizeF QScrollPrepareEvent::viewportSize() const
+{
+ return d_func()->viewportSize;
+}
+
+/*!
+ Returns the range of coordinates for the content as set by setContentPosRange().
+*/
+QRectF QScrollPrepareEvent::contentPosRange() const
+{
+ return d_func()->contentPosRange;
+}
+
+/*!
+ Returns the current position of the content as set by setContentPos.
+*/
+QPointF QScrollPrepareEvent::contentPos() const
+{
+ return d_func()->contentPos;
+}
+
+
+/*!
+ Sets the size of the area that is to be scrolled to \a size.
+
+ \sa viewportSize()
+*/
+void QScrollPrepareEvent::setViewportSize(const QSizeF &size)
+{
+ d_func()->viewportSize = size;
+}
+
+/*!
+ Sets the range of content coordinates to \a rect.
+
+ \sa contentPosRange()
+*/
+void QScrollPrepareEvent::setContentPosRange(const QRectF &rect)
+{
+ d_func()->contentPosRange = rect;
+}
+
+/*!
+ Sets the current content position to \a pos.
+
+ \sa contentPos()
+*/
+void QScrollPrepareEvent::setContentPos(const QPointF &pos)
+{
+ d_func()->contentPos = pos;
+}
+
+
+/*!
+ \internal
+*/
+QScrollPrepareEventPrivate *QScrollPrepareEvent::d_func()
+{
+ return reinterpret_cast<QScrollPrepareEventPrivate *>(d);
+}
+
+/*!
+ \internal
+*/
+const QScrollPrepareEventPrivate *QScrollPrepareEvent::d_func() const
+{
+ return reinterpret_cast<const QScrollPrepareEventPrivate *>(d);
+}
+
+/*!
+ \class QScrollEvent
+ \since 4.8
+ \ingroup events
+
+ \brief The QScrollEvent class is send when scrolling.
+
+ The scroll event is send to indicate that the receiver should be scrolled.
+ Usually the receiver should be something visual like QWidget or QGraphicsObject.
+
+ Some care should be taken that no conflicting QScrollEvents are sent from two
+ sources. Using QScroller::scrollTo is save however.
+
+ \sa QScrollPrepareEvent, QScroller
+*/
+
+/*!
+ \enum QScrollEvent::ScrollState
+
+ This enum describes the states a scroll event can have.
+
+ \value ScrollStarted Set for the first scroll event of a scroll activity.
+
+ \value ScrollUpdated Set for all but the first and the last scroll event of a scroll activity.
+
+ \value ScrollFinished Set for the last scroll event of a scroll activity.
+
+ \sa QScrollEvent::scrollState()
+*/
+
+/*!
+ Creates a new QScrollEvent
+ \a contentPos is the new content position, \a overshootDistance is the
+ new overshoot distance while \a scrollState indicates if this scroll
+ event is the first one, the last one or some event in between.
+*/
+QScrollEvent::QScrollEvent(const QPointF &contentPos, const QPointF &overshootDistance, ScrollState scrollState)
+ : QEvent(QEvent::Scroll)
+{
+ d = reinterpret_cast<QEventPrivate *>(new QScrollEventPrivate());
+ d_func()->contentPos = contentPos;
+ d_func()->overshoot= overshootDistance;
+ d_func()->state = scrollState;
+}
+
+/*!
+ Destroys QScrollEvent.
+*/
+QScrollEvent::~QScrollEvent()
+{
+ delete reinterpret_cast<QScrollEventPrivate *>(d);
+}
+
+/*!
+ Returns the new scroll position.
+*/
+QPointF QScrollEvent::contentPos() const
+{
+ return d_func()->contentPos;
+}
+
+/*!
+ Returns the new overshoot distance.
+ See QScroller for an explanation of the term overshoot.
+
+ \sa QScroller
+*/
+QPointF QScrollEvent::overshootDistance() const
+{
+ return d_func()->overshoot;
+}
+
+/*!
+ Returns the current scroll state as a combination of ScrollStateFlag values.
+ ScrollStarted (or ScrollFinished) will be set, if this scroll event is the first (or last) event in a scrolling activity.
+ Please note that both values can be set at the same time, if the activity consists of a single QScrollEvent.
+ All other scroll events in between will have their state set to ScrollUpdated.
+
+ A widget could for example revert selections when scrolling is started and stopped.
+*/
+QScrollEvent::ScrollState QScrollEvent::scrollState() const
+{
+ return d_func()->state;
+}
+
+/*!
+ \internal
+*/
+QScrollEventPrivate *QScrollEvent::d_func()
+{
+ return reinterpret_cast<QScrollEventPrivate *>(d);
+}
+
+/*!
+ \internal
+*/
+const QScrollEventPrivate *QScrollEvent::d_func() const
+{
+ return reinterpret_cast<const QScrollEventPrivate *>(d);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 879ac2df41..a7b06f4cd0 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -880,6 +880,52 @@ private:
};
#endif // QT_NO_GESTURES
+class QScrollPrepareEventPrivate;
+class Q_GUI_EXPORT QScrollPrepareEvent : public QEvent
+{
+public:
+ QScrollPrepareEvent(const QPointF &startPos);
+ ~QScrollPrepareEvent();
+
+ QPointF startPos() const;
+
+ QSizeF viewportSize() const;
+ QRectF contentPosRange() const;
+ QPointF contentPos() const;
+
+ void setViewportSize(const QSizeF &size);
+ void setContentPosRange(const QRectF &rect);
+ void setContentPos(const QPointF &pos);
+
+private:
+ QScrollPrepareEventPrivate *d_func();
+ const QScrollPrepareEventPrivate *d_func() const;
+};
+
+
+class QScrollEventPrivate;
+class Q_GUI_EXPORT QScrollEvent : public QEvent
+{
+public:
+ enum ScrollState
+ {
+ ScrollStarted,
+ ScrollUpdated,
+ ScrollFinished
+ };
+
+ QScrollEvent(const QPointF &contentPos, const QPointF &overshoot, ScrollState scrollState);
+ ~QScrollEvent();
+
+ QPointF contentPos() const;
+ QPointF overshootDistance() const;
+ ScrollState scrollState() const;
+
+private:
+ QScrollEventPrivate *d_func();
+ const QScrollEventPrivate *d_func() const;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 784062edf1..3a270233fa 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -178,6 +178,34 @@ public:
QUrl url;
};
+
+class QScrollPrepareEventPrivate
+{
+public:
+ inline QScrollPrepareEventPrivate()
+ : target(0)
+ {
+ }
+
+ QObject* target;
+ QPointF startPos;
+ QSizeF viewportSize;
+ QRectF contentPosRange;
+ QPointF contentPos;
+};
+
+class QScrollEventPrivate
+{
+public:
+ inline QScrollEventPrivate()
+ {
+ }
+
+ QPointF contentPos;
+ QPointF overshoot;
+ QScrollEvent::ScrollState state;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa.cpp b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp
new file mode 100644
index 0000000000..01d40ca998
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_glib_qpa_p.h"
+
+#include "qapplication.h"
+
+#include "qplatformdefs.h"
+#include "qapplication.h"
+
+#include <glib.h>
+#include "qapplication_p.h"
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+struct GUserEventSource
+{
+ GSource source;
+ QPAEventDispatcherGlib *q;
+};
+
+static gboolean userEventSourcePrepare(GSource *s, gint *timeout)
+{
+ Q_UNUSED(s)
+ Q_UNUSED(timeout)
+
+ return QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0;
+}
+
+static gboolean userEventSourceCheck(GSource *source)
+{
+ return userEventSourcePrepare(source, 0);
+}
+
+static gboolean userEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
+{
+ GUserEventSource * source = reinterpret_cast<GUserEventSource *>(s);
+
+ QWindowSystemInterfacePrivate::WindowSystemEvent * event;
+ while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
+ event = QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ if (!event)
+ break;
+
+ // send through event filter
+ if (source->q->filterEvent(event)) {
+ delete event;
+ continue;
+ }
+ QApplicationPrivate::processWindowSystemEvent(event);
+ delete event;
+ }
+
+ return true;
+}
+
+
+static GSourceFuncs userEventSourceFuncs = {
+ userEventSourcePrepare,
+ userEventSourceCheck,
+ userEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context)
+ : QEventDispatcherGlibPrivate(context)
+{
+ userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs,
+ sizeof(GUserEventSource)));
+ userEventSource->q = 0;
+ g_source_set_can_recurse(&userEventSource->source, true);
+ g_source_attach(&userEventSource->source, mainContext);
+}
+
+
+QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent)
+ : QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent)
+{
+ Q_D(QPAEventDispatcherGlib);
+ d->userEventSource->q = this;
+}
+
+QPAEventDispatcherGlib::~QPAEventDispatcherGlib()
+{
+ Q_D(QPAEventDispatcherGlib);
+
+ g_source_destroy(&d->userEventSource->source);
+ g_source_unref(&d->userEventSource->source);
+ d->userEventSource = 0;
+}
+
+bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ static bool init = false;
+ if (!init) {
+ if (QApplicationPrivate::platformIntegration()->createEventLoopIntegration()) {
+ qWarning("Eventloop integration is not supported by the glib event dispatcher");
+ qWarning("Use the UNIX event dispatcher by defining environment variable QT_NO_GLIB=1");
+ }
+ init = true;
+ }
+ return QEventDispatcherGlib::processEvents(flags);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa_p.h b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h
new file mode 100644
index 0000000000..1c32ab2961
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_GLIB_QPA_P_H
+#define QEVENTDISPATCHER_GLIB_QPA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qeventdispatcher_glib_p.h>
+
+typedef struct _GMainContext GMainContext;
+
+QT_BEGIN_NAMESPACE
+class QPAEventDispatcherGlibPrivate;
+
+class QPAEventDispatcherGlib : public QEventDispatcherGlib
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPAEventDispatcherGlib)
+
+public:
+ explicit QPAEventDispatcherGlib(QObject *parent = 0);
+ ~QPAEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+};
+
+struct GUserEventSource;
+
+class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
+{
+ Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
+public:
+ QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GUserEventSource *userEventSource;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_GLIB_QPA_P_H
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index 8f024f5d04..15410ada4c 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -588,7 +588,10 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
// manually (rather than from a QEventLoop), we cannot enter a tight
// loop and block this call, but instead we need to return after one flush:
const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
- const bool canExec_Qt = flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec;
+ const bool canExec_Qt =
+ (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec)
+ && !(flags & QEventLoop::ExcludeUserInputEvents);
+
if (canExec_Qt && canExec_3rdParty) {
// We can use exec-mode, meaning that we can stay in a tight loop until
diff --git a/src/gui/kernel/qeventdispatcher_qpa.cpp b/src/gui/kernel/qeventdispatcher_qpa.cpp
new file mode 100644
index 0000000000..519d2a61ed
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_qpa.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qapplication.h"
+#include "qeventdispatcher_qpa_p.h"
+#include "private/qeventdispatcher_unix_p.h"
+#include "qapplication_p.h"
+#include "qplatformeventloopintegration_qpa.h"
+
+#include <QWindowSystemInterface>
+#include <QtCore/QElapsedTimer>
+#include <QtCore/QAtomicInt>
+#include <QtCore/QSemaphore>
+
+#include <QtCore/QDebug>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class Rendezvous
+{
+public:
+ void checkpoint()
+ {
+ if (state.testAndSetOrdered(0,1)) {
+ semaphore.acquire();
+ } else if (state.testAndSetAcquire(1,0)) {
+ semaphore.release();
+ } else {
+ qWarning("Barrier internal error");
+ }
+ }
+private:
+ QSemaphore semaphore;
+ QAtomicInt state;
+};
+
+class SelectWorker : public QThread
+{
+public:
+ SelectWorker(QEventDispatcherQPAPrivate *eventDispatcherPrivate)
+ : QThread(),
+ m_edPrivate(eventDispatcherPrivate),
+ m_retVal(0)
+ {
+ }
+
+ void setSelectValues(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+ {
+ m_nfds = nfds;
+ m_readfds = readfds;
+ m_writefds = writefds;
+ m_exceptfds = exceptfds;
+
+
+ }
+
+ int retVal() const {
+ return m_retVal;
+ }
+
+protected:
+ void run();
+
+private:
+ QEventDispatcherQPAPrivate *m_edPrivate;
+ int m_retVal;
+
+ int m_nfds;
+ fd_set *m_readfds, *m_writefds, *m_exceptfds;
+};
+
+class QEventDispatcherQPAPrivate : public QEventDispatcherUNIXPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherQPA)
+public:
+ QEventDispatcherQPAPrivate()
+ : eventLoopIntegration(0),
+ barrierBeforeBlocking(0),
+ barrierReturnValue(0),
+ selectReturnMutex(0),
+ selectWorkerNeedsSync(true),
+ selectWorkerHasResult(false),
+ m_integrationInitialised(false),
+ m_hasIntegration(false),
+ m_isEventLoopIntegrationRunning(false)
+ {
+
+ }
+
+ ~QEventDispatcherQPAPrivate()
+ {
+ delete selectWorker;
+ delete eventLoopIntegration;
+ delete barrierBeforeBlocking;
+ delete barrierReturnValue;
+ delete selectReturnMutex;
+ }
+
+ bool hasIntegration() const
+ {
+ if (!m_integrationInitialised) {
+ QEventDispatcherQPAPrivate *that = const_cast<QEventDispatcherQPAPrivate *>(this);
+ if (qApp && (qApp->thread() == QThread::currentThread())) { // guiThread
+ if (QApplicationPrivate::platformIntegration()) {
+ that->eventLoopIntegration = QApplicationPrivate::platformIntegration()->createEventLoopIntegration();
+ if (that->eventLoopIntegration) {
+ that->selectWorker = new SelectWorker(that);
+ that->barrierBeforeBlocking = new Rendezvous;
+ that->barrierReturnValue = new Rendezvous;
+ that->selectReturnMutex = new QMutex;
+ that->selectWorker->start();
+ that->m_hasIntegration = true;
+ if (!QElapsedTimer::isMonotonic())
+ qWarning("Having eventloop integration without monotonic timers can lead to undefined behaviour");
+ }
+ }
+ }
+ that->m_integrationInitialised = true;
+ }
+ return m_hasIntegration;
+ }
+
+ bool isEventLoopIntegrationRunning() const
+ {
+ return m_isEventLoopIntegrationRunning;
+ }
+
+ void runEventLoopIntegration()
+ {
+ if (qApp && (qApp->thread() == QThread::currentThread())) {
+ m_isEventLoopIntegrationRunning = true;
+ QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
+ eventLoopIntegration->startEventLoop();
+ }
+ }
+
+ QPlatformEventLoopIntegration *eventLoopIntegration;
+ Rendezvous *barrierBeforeBlocking;
+ Rendezvous *barrierReturnValue;
+
+ QMutex *selectReturnMutex;
+ bool selectWorkerNeedsSync;
+ bool selectWorkerHasResult;
+
+ SelectWorker *selectWorker;
+private:
+ bool m_integrationInitialised;
+ bool m_hasIntegration;
+ bool m_isEventLoopIntegrationRunning;
+};
+
+QEventDispatcherQPA::QEventDispatcherQPA(QObject *parent)
+ : QEventDispatcherUNIX(*new QEventDispatcherQPAPrivate, parent)
+{ }
+
+QEventDispatcherQPA::~QEventDispatcherQPA()
+{ }
+
+bool QEventDispatcherQPA::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherQPA);
+
+ if (d->hasIntegration()) {
+ if (!d->isEventLoopIntegrationRunning()) {
+ d->runEventLoopIntegration();
+ }
+ if (d->threadData->quitNow) {
+ d->eventLoopIntegration->quitEventLoop();
+ return false;
+ }
+ }
+
+ int nevents = 0;
+
+ // handle gui and posted events
+ d->interrupt = false;
+ QApplication::sendPostedEvents();
+
+ while (!d->interrupt) { // also flushes output buffer ###can be optimized
+ QWindowSystemInterfacePrivate::WindowSystemEvent *event;
+ if (!(flags & QEventLoop::ExcludeUserInputEvents)
+ && QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0) {
+ // process a pending user input event
+ event = QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ if (!event)
+ break;
+ } else {
+ break;
+ }
+
+ if (filterEvent(event)) {
+ delete event;
+ continue;
+ }
+ nevents++;
+
+ QApplicationPrivate::processWindowSystemEvent(event);
+ delete event;
+ }
+
+ if (!d->interrupt) {
+ if (QEventDispatcherUNIX::processEvents(flags)) {
+ QEventDispatcherUNIX::processEvents(flags);
+ return true;
+ }
+ }
+ return (nevents > 0);
+}
+
+bool QEventDispatcherQPA::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return qGlobalPostedEventsCount() || QWindowSystemInterfacePrivate::windowSystemEventsQueued();
+}
+
+void QEventDispatcherQPA::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_D(QEventDispatcherQPA);
+ QEventDispatcherUNIX::registerSocketNotifier(notifier);
+ if (d->hasIntegration())
+ wakeUp();
+
+}
+
+void QEventDispatcherQPA::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_D(QEventDispatcherQPA);
+ QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
+ if (d->hasIntegration())
+ wakeUp();
+}
+
+void QEventDispatcherQPA::flush()
+{
+ if(qApp)
+ qApp->sendPostedEvents();
+}
+
+int QEventDispatcherQPA::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ Q_D(QEventDispatcherQPA);
+ int retVal = 0;
+ if (d->hasIntegration()) {
+ qint64 timeoutmsec = 0;
+ if (timeout)
+ timeoutmsec = timeout->tv_sec * 1000 + (timeout->tv_usec/1000);
+ d->selectReturnMutex->lock();
+ if (d->selectWorkerNeedsSync) {
+ if (d->selectWorkerHasResult) {
+ retVal = d->selectWorker->retVal();
+ d->selectWorkerHasResult = false;
+
+ d->selectReturnMutex->unlock();
+ d->barrierReturnValue->checkpoint();
+ d->eventLoopIntegration->setNextTimerEvent(0);
+ return retVal;
+ } else {
+ d->selectWorkerNeedsSync = false;
+ d->selectWorker->setSelectValues(nfds,readfds, writefds, exceptfds);
+ d->barrierBeforeBlocking->checkpoint();
+ }
+ }
+ d->selectReturnMutex->unlock();
+ d->eventLoopIntegration->setNextTimerEvent(timeoutmsec);
+ retVal = 0; //is 0 if select has not returned
+ } else {
+ retVal = QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout);
+ }
+ return retVal;
+}
+
+
+void SelectWorker::run()
+{
+
+ while(true) {
+ m_retVal = 0;
+ m_edPrivate->barrierBeforeBlocking->checkpoint(); // wait for mainthread
+ int tmpRet = qt_safe_select(m_nfds,m_readfds,m_writefds,m_exceptfds,0);
+ m_edPrivate->selectReturnMutex->lock();
+ m_edPrivate->eventLoopIntegration->qtNeedsToProcessEvents();
+
+ m_edPrivate->selectWorkerNeedsSync = true;
+ m_edPrivate->selectWorkerHasResult = true;
+ m_retVal = tmpRet;
+
+ m_edPrivate->selectReturnMutex->unlock();
+ m_edPrivate->barrierReturnValue->checkpoint();
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_qpa_p.h b/src/gui/kernel/qeventdispatcher_qpa_p.h
new file mode 100644
index 0000000000..8065c3e60c
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_qpa_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_QPA_P_H
+#define QEVENTDISPATCHER_QPA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qeventdispatcher_unix_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherQPAPrivate;
+
+class QEventDispatcherQPA : public QEventDispatcherUNIX
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherQPA)
+
+public:
+ explicit QEventDispatcherQPA(QObject *parent = 0);
+ ~QEventDispatcherQPA();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void flush();
+
+protected:
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_QPA_P_H
diff --git a/src/gui/kernel/qgenericplugin_qpa.cpp b/src/gui/kernel/qgenericplugin_qpa.cpp
new file mode 100644
index 0000000000..43d6525bb6
--- /dev/null
+++ b/src/gui/kernel/qgenericplugin_qpa.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericplugin_qpa.h"
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGenericPlugin
+ \ingroup plugins
+ \ingroup qpa
+
+ \brief The QGenericPlugin class is an abstract base class for
+ window-system related plugins in Qt QPA.
+
+ Note that this class is only available in \l{Qt QPA}.
+
+ A mouse plugin can be created by subclassing
+ QGenericPlugin and reimplementing the pure virtual keys() and
+ create() functions. By exporting the derived class using the
+ Q_EXPORT_PLUGIN2() macro, The default implementation of the
+ QGenericPluginFactory class will automatically detect the plugin and
+ load the driver into the server application at run-time. See \l
+ {How to Create Qt Plugins} for details.
+
+ \sa QGenericPluginFactory
+*/
+
+/*!
+ \fn QStringList QGenericPlugin::keys() const
+
+ Implement this function to return the list of valid keys, i.e. the
+ drivers supported by this plugin.
+
+ \sa create()
+*/
+
+/*!
+ Constructs a plugin with the given \a parent.
+
+ Note that this constructor is invoked automatically by the
+ Q_EXPORT_PLUGIN2() macro, so there is no need for calling it
+ explicitly.
+*/
+QGenericPlugin::QGenericPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QGenericPlugin::~QGenericPlugin()
+{
+}
+
+/*!
+ \fn QObject* QGenericPlugin::create(const QString &key, const QString& specification)
+
+ Implement this function to create a driver matching the type
+ specified by the given \a key and \a specification parameters. Note that
+ keys are case-insensitive.
+
+ \sa keys()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/gui/kernel/qgenericplugin_qpa.h b/src/gui/kernel/qgenericplugin_qpa.h
new file mode 100644
index 0000000000..e1792cd417
--- /dev/null
+++ b/src/gui/kernel/qgenericplugin_qpa.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICPLUGIN_QPA_H
+#define QGENERICPLUGIN_QPA_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_LIBRARY
+
+//class QGenericObject; ?????
+
+ struct Q_GUI_EXPORT QGenericPluginFactoryInterface : public QFactoryInterface
+{
+ virtual QObject* create(const QString &name, const QString &spec) = 0;
+};
+
+#define QGenericPluginFactoryInterface_iid "com.trolltech.Qt.QGenericPluginFactoryInterface"
+Q_DECLARE_INTERFACE(QGenericPluginFactoryInterface, QGenericPluginFactoryInterface_iid)
+
+class Q_GUI_EXPORT QGenericPlugin : public QObject, public QGenericPluginFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QGenericPluginFactoryInterface:QFactoryInterface)
+public:
+ explicit QGenericPlugin(QObject *parent = 0);
+ ~QGenericPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QObject* create(const QString& name, const QString &spec) = 0;
+};
+
+#endif // QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGENERICPLUGIN_QPA_H
diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.cpp b/src/gui/kernel/qgenericpluginfactory_qpa.cpp
new file mode 100644
index 0000000000..abc575ae86
--- /dev/null
+++ b/src/gui/kernel/qgenericpluginfactory_qpa.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericpluginfactory_qpa.h"
+
+#include "qapplication.h"
+#include "private/qfactoryloader_p.h"
+#include "qgenericplugin_qpa.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QGenericPluginFactoryInterface_iid,
+ QLatin1String("/generic"), Qt::CaseInsensitive))
+
+#endif //QT_NO_LIBRARY
+#endif //QT_MAKEDLL
+
+/*!
+ \class QGenericPluginFactory
+ \ingroup qpa
+
+ \brief The QGenericPluginFactory class creates window-system
+ related plugin drivers in Qt QPA.
+
+ Note that this class is only available in \l{Qt QPA}.
+
+
+ \sa QGenericPlugin
+*/
+
+/*!
+ Creates the driver specified by \a key, using the given \a specification.
+
+ Note that the keys are case-insensitive.
+
+ \sa keys()
+*/
+QObject *QGenericPluginFactory::create(const QString& key, const QString &specification)
+{
+ QString driver = key.toLower();
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+ if (QGenericPluginFactoryInterface *factory = qobject_cast<QGenericPluginFactoryInterface*>(loader()->instance(driver)))
+ return factory->create(driver, specification);
+#endif
+#endif
+ return 0;
+}
+
+/*!
+ Returns the list of valid keys, i.e. the available mouse drivers.
+
+ \sa create()
+*/
+QStringList QGenericPluginFactory::keys()
+{
+ QStringList list;
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+ QStringList plugins = loader()->keys();
+ for (int i = 0; i < plugins.size(); ++i) {
+ if (!list.contains(plugins.at(i)))
+ list += plugins.at(i);
+ }
+#endif //QT_NO_LIBRARY
+#endif //QT_MAKEDLL
+ return list;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.h b/src/gui/kernel/qgenericpluginfactory_qpa.h
new file mode 100644
index 0000000000..59eac386ed
--- /dev/null
+++ b/src/gui/kernel/qgenericpluginfactory_qpa.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICPLUGINFACTORY_QPA_H
+#define QGENERICPLUGINFACTORY_QPA_H
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QString;
+class QObject;
+
+class Q_GUI_EXPORT QGenericPluginFactory
+{
+public:
+ static QStringList keys();
+ static QObject *create(const QString&, const QString &);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGENERICPLUGINFACTORY_QPA_H
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
index 22bfb26591..5359fb37e8 100644
--- a/src/gui/kernel/qgesturemanager.cpp
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -243,52 +243,53 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
// TODO: sort contexts by the gesture type and check if one of the contexts
// is already active.
- bool ret = false;
+ bool consumeEventHint = false;
// filter the event through recognizers
typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
- for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
- Qt::GestureType gestureType = cit.value();
+ ContextIterator contextEnd = contexts.end();
+ for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) {
+ Qt::GestureType gestureType = context.value();
QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
- rit = m_recognizers.lowerBound(gestureType),
- re = m_recognizers.upperBound(gestureType);
- for (; rit != re; ++rit) {
- QGestureRecognizer *recognizer = rit.value();
- QObject *target = cit.key();
+ typeToRecognizerIterator = m_recognizers.lowerBound(gestureType),
+ typeToRecognizerEnd = m_recognizers.upperBound(gestureType);
+ for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) {
+ QGestureRecognizer *recognizer = typeToRecognizerIterator.value();
+ QObject *target = context.key();
QGesture *state = getState(target, recognizer, gestureType);
if (!state)
continue;
- QGestureRecognizer::Result result = recognizer->recognize(state, target, event);
- QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
- result &= QGestureRecognizer::ResultHint_Mask;
- if (type == QGestureRecognizer::TriggerGesture) {
+ QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event);
+ QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask;
+ QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask;
+ if (recognizerState == QGestureRecognizer::TriggerGesture) {
DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state;
triggeredGestures << state;
- } else if (type == QGestureRecognizer::FinishGesture) {
+ } else if (recognizerState == QGestureRecognizer::FinishGesture) {
DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state;
finishedGestures << state;
- } else if (type == QGestureRecognizer::MayBeGesture) {
+ } else if (recognizerState == QGestureRecognizer::MayBeGesture) {
DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state;
newMaybeGestures << state;
- } else if (type == QGestureRecognizer::CancelGesture) {
+ } else if (recognizerState == QGestureRecognizer::CancelGesture) {
DEBUG() << "QGestureManager:Recognizer: not gesture: " << state;
notGestures << state;
- } else if (type == QGestureRecognizer::Ignore) {
+ } else if (recognizerState == QGestureRecognizer::Ignore) {
DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state;
} else {
DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer"
<< "ignored the event: " << state;
}
- if (result & QGestureRecognizer::ConsumeEventHint) {
+ if (resultHint & QGestureRecognizer::ConsumeEventHint) {
DEBUG() << "QGestureManager: we were asked to consume the event: "
<< state;
- ret = true;
+ consumeEventHint = true;
}
}
}
if (triggeredGestures.isEmpty() && finishedGestures.isEmpty()
&& newMaybeGestures.isEmpty() && notGestures.isEmpty())
- return ret;
+ return consumeEventHint;
QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
triggeredGestures &= m_activeGestures;
@@ -390,7 +391,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
qDeleteAll(m_gesturesToDelete);
m_gesturesToDelete.clear();
- return ret;
+ return consumeEventHint;
}
// Cancel all gestures of children of the widget that original is associated with
diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp
index 9098a05340..bb4ed11589 100644
--- a/src/gui/kernel/qguifunctions_wince.cpp
+++ b/src/gui/kernel/qguifunctions_wince.cpp
@@ -112,6 +112,9 @@ struct AygSIPINFO
#ifndef SPI_GETSIPINFO
#define SPI_GETSIPINFO 225
#endif
+#ifndef SPI_GETPLATFORMTYPE
+#define SPI_GETPLATFORMTYPE 257
+#endif
typedef BOOL (*AygInitDialog)(AygSHINITDLGINFO*);
typedef BOOL (*AygFullScreen)(HWND, DWORD);
@@ -129,8 +132,6 @@ static void resolveAygLibs()
if (!aygResolved) {
aygResolved = true;
QLibrary ayglib(QLatin1String("aygshell"));
- if (!ayglib.load())
- return;
ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog");
ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen");
ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo");
diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp
index 636e35136f..011b816e77 100644
--- a/src/gui/kernel/qguiplatformplugin.cpp
+++ b/src/gui/kernel/qguiplatformplugin.cpp
@@ -152,7 +152,7 @@ QString QGuiPlatformPlugin::styleName()
return QLatin1String("Windows"); // default style for Symbian without S60
#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
return QLatin1String("SGI"); // default style for X11 on IRIX
-#elif defined(Q_WS_QWS)
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
return QLatin1String("Plastique"); // default style for X11 and small devices
#elif defined(Q_WS_MAC)
return QLatin1String("Macintosh"); // default style for all Mac's
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index b5473d3592..3cf5dc5275 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -76,7 +76,7 @@ static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Backtab, 0x21E4 },
{ Qt::Key_Backspace, 0x232B },
{ Qt::Key_Return, 0x21B5 },
- { Qt::Key_Enter, 0x21B5 },
+ { Qt::Key_Enter, 0x2324 },
{ Qt::Key_Delete, 0x2326 },
{ Qt::Key_Home, 0x2196 },
{ Qt::Key_End, 0x2198 },
@@ -240,7 +240,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
\row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V
\row \i Preferences \i \i Ctrl+, \i \i \i (none)
\row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z
- \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none)
+ \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none)
\row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none)
\row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none)
\row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none)
@@ -718,7 +718,6 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac},
{QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All},
{QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_S60},
- {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above
{QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All},
{QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac},
{QKeySequence::Forward, 1, Qt::CTRL | Qt::Key_BracketRight, QApplicationPrivate::KB_Mac},
@@ -747,7 +746,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE},
{QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
{QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
- {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above
+ {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac},
{QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above
{QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11},
@@ -1522,6 +1521,14 @@ QKeySequence &QKeySequence::operator=(const QKeySequence &other)
}
/*!
+ \fn void QKeySequence::swap(QKeySequence &other)
+ \since 4.8
+
+ Swaps key sequence \a other with this key sequence. This operation is very
+ fast and never fails.
+*/
+
+/*!
\fn bool QKeySequence::operator!=(const QKeySequence &other) const
Returns true if this key sequence is not equal to the \a other
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index f3ab19bb90..9eabb89d29 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -179,6 +179,11 @@ public:
operator int() const;
int operator[](uint i) const;
QKeySequence &operator=(const QKeySequence &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QKeySequence &operator=(QKeySequence &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QKeySequence &other) { qSwap(d, other.d); }
bool operator==(const QKeySequence &other) const;
inline bool operator!= (const QKeySequence &other) const
{ return !(*this == other); }
diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp
index 929e115b41..aeb96e9ef5 100644
--- a/src/gui/kernel/qlayoutitem.cpp
+++ b/src/gui/kernel/qlayoutitem.cpp
@@ -516,9 +516,7 @@ bool QWidgetItem::hasHeightForWidth() const
{
if (isEmpty())
return false;
- if (wid->layout())
- return wid->layout()->hasHeightForWidth();
- return wid->sizePolicy().hasHeightForWidth();
+ return wid->d_func()->hasHeightForWidth();
}
/*!
diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h
index 1d2d284309..d6ccb93593 100644
--- a/src/gui/kernel/qmacdefines_mac.h
+++ b/src/gui/kernel/qmacdefines_mac.h
@@ -94,12 +94,6 @@ Yes, it is an informative comment ;-)
#include <QtCore/qglobal.h>
-#undef OLD_DEBUG
-#ifdef DEBUG
-# define OLD_DEBUG DEBUG
-# undef DEBUG
-#endif
-#define DEBUG 0
#ifdef qDebug
# define old_qDebug qDebug
# undef qDebug
@@ -179,12 +173,6 @@ typedef AERecord AppleEvent;
#undef check
#endif
-#undef DEBUG
-#ifdef OLD_DEBUG
-# define DEBUG OLD_DEBUG
-# undef OLD_DEBUG
-#endif
-
#ifdef old_qDebug
# undef qDebug
# define qDebug QT_NO_QDEBUG_MACRO
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
index b48ad1295c..dffd2cbec8 100644
--- a/src/gui/kernel/qpalette.h
+++ b/src/gui/kernel/qpalette.h
@@ -78,6 +78,14 @@ public:
QPalette(const QPalette &palette);
~QPalette();
QPalette &operator=(const QPalette &palette);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPalette &operator=(QPalette &&other)
+ {
+ resolve_mask = other.resolve_mask;
+ current_group = other.current_group;
+ qSwap(d, other.d); return *this;
+ }
+#endif
operator QVariant() const;
// Do not change the order, the serialization format depends on it
diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp
new file mode 100644
index 0000000000..ac557b9ff9
--- /dev/null
+++ b/src/gui/kernel/qplatformcursor_qpa.cpp
@@ -0,0 +1,660 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenVG module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qplatformcursor_qpa.h"
+
+#include <QWidget>
+#include <QPainter>
+#include <QBitmap>
+#include <QApplication>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QList <QWeakPointer<QPlatformCursor> > QPlatformCursorPrivate::instances;
+
+/*!
+ \class QGraphicsSystemCursor
+
+ \brief The QGraphicsSystemCursor class provides information about
+ pointer device events (movement, buttons), and requests to change
+ the currently displayed cursor.
+
+ Note that QGraphicsSystemCursor does not include any graphics for
+ display. An application that sets a QCursor may provide its own
+ graphics.
+
+ \sa QGraphicsSystemCursorImage
+*/
+
+/*!
+ \fn virtual void QGraphicsSystemCursor::pointerEvent(const QMouseEvent & event)
+
+ This method is called by Qt whenever a QMouseEvent is generated by the
+ underlying pointer input. \a event is a reference to the QMouseEvent in
+ question. A default do-nothing implementation is provided.
+
+ \sa QApplicationPrivate::handleMouseEvent()
+*/
+
+/*!
+ \fn virtual void QGraphicsSystemCursor::changeCursor(QCursor * widgetCursor, QWidget * widget)
+
+ \brief This method is called by Qt whenever the cursor graphic should be changed.
+
+ Implementation of this method is mandatory for a subclass of QGraphicsSystemCursor.
+
+ \a widgetCursor is a pointer to the QCursor that should be displayed.
+
+ \a widget is a pointer to the widget currently displayed at QCursor::pos(). Note
+ that this may be 0 if the current position is not occupied by a displayed widget.
+
+ \sa QApplicationPrivate::handleMouseEvent(), QCursor::pos()
+*/
+
+/*!
+ \fn QGraphicsSystemCursor::QGraphicsSystemCursor()
+
+ \brief Constructs a QGraphicsSystemCursor
+*/
+QPlatformCursor::QPlatformCursor(QPlatformScreen *scr )
+ : screen(scr)
+{
+ QPlatformCursorPrivate::instances.append(this);
+}
+
+// End of display and pointer event handling code
+// Beginning of built-in cursor graphics
+// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp
+
+/*!
+ \class QGraphicsSystemCursorImage
+
+ \brief The QGraphicsSystemCursorImage class provides a set of graphics
+ intended to be used as cursors.
+
+ \sa QGraphicsSystemCursor
+*/
+
+static QPlatformCursorImage *systemCursorTable[Qt::LastCursor+1];
+static bool systemCursorTableInit = false;
+
+// 16 x 16
+static const uchar cur_arrow_bits[] = {
+ 0x07, 0x00, 0x39, 0x00, 0xc1, 0x01, 0x02, 0x0e, 0x02, 0x10, 0x02, 0x08,
+ 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x88, 0x08, 0x48, 0x11, 0x28, 0x22,
+ 0x10, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00 };
+static const uchar mcur_arrow_bits[] = {
+ 0x07, 0x00, 0x3f, 0x00, 0xff, 0x01, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x0f,
+ 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x0f, 0x78, 0x1f, 0x38, 0x3e,
+ 0x10, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00 };
+
+static const unsigned char cur_up_arrow_bits[] = {
+ 0x80, 0x00, 0x40, 0x01, 0x40, 0x01, 0x20, 0x02, 0x20, 0x02, 0x10, 0x04,
+ 0x10, 0x04, 0x08, 0x08, 0x78, 0x0f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01,
+ 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01};
+static const unsigned char mcur_up_arrow_bits[] = {
+ 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xe0, 0x03, 0xf0, 0x07,
+ 0xf0, 0x07, 0xf8, 0x0f, 0xf8, 0x0f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};
+
+static const unsigned char cur_cross_bits[] = {
+ 0xc0, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01,
+ 0x7f, 0x7f, 0x01, 0x40, 0x7f, 0x7f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01,
+ 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01, 0x00, 0x00};
+static const unsigned char mcur_cross_bits[] = {
+ 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00};
+
+static const uchar cur_ibeam_bits[] = {
+ 0x00, 0x00, 0xe0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
+ 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
+ 0x80, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 };
+static const uchar mcur_ibeam_bits[] = {
+ 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
+ 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0x00, 0x00 };
+
+static const uchar cur_ver_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
+ 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f,
+ 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 };
+static const uchar mcur_ver_bits[] = {
+ 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f,
+ 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f,
+ 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 };
+
+static const uchar cur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18,
+ 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar mcur_hor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c,
+ 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c,
+ 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 };
+static const uchar cur_bdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e,
+ 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00,
+ 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar mcur_bdiag_bits[] = {
+ 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f,
+ 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01,
+ 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 };
+static const uchar cur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00,
+ 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c,
+ 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+static const uchar mcur_fdiag_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00,
+ 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e,
+ 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 };
+
+// 20 x 20
+static const uchar forbidden_bits[] = {
+ 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01,
+ 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06,
+ 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03,
+ 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 };
+
+static const uchar forbiddenm_bits[] = {
+ 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03,
+ 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f,
+ 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07,
+ 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00};
+
+// 32 x 32
+static const uchar wait_data_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00,
+ 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x08, 0x20, 0x00,
+ 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00,
+ 0x00, 0x50, 0x15, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x40, 0x05, 0x00,
+ 0x00, 0x80, 0x02, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x20, 0x08, 0x00,
+ 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x88, 0x22, 0x00,
+ 0x00, 0x48, 0x25, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0xfc, 0x7f, 0x00,
+ 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar wait_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00,
+ 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00,
+ 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x07, 0x00,
+ 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00,
+ 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00,
+ 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00,
+ 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const uchar hsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03,
+ 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00,
+ 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar hsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00,
+ 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07,
+ 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00,
+ 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+ 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar vsplit_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar vsplitm_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar phand_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+ 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00,
+ 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00,
+ 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00,
+ 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar phandm_bits[] = {
+ 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00,
+ 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00,
+ 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00,
+ 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00,
+ 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const uchar size_all_data_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x80, 0x81, 0xc0, 0x00,
+ 0xc0, 0xff, 0xff, 0x01, 0x80, 0x81, 0xc0, 0x00, 0x00, 0x81, 0x40, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const uchar size_all_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc2, 0x21, 0x00,
+ 0x00, 0xc3, 0x61, 0x00, 0x80, 0xc3, 0xe1, 0x00, 0xc0, 0xff, 0xff, 0x01,
+ 0xe0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01, 0x80, 0xc3, 0xe1, 0x00,
+ 0x00, 0xc3, 0x61, 0x00, 0x00, 0xc2, 0x21, 0x00, 0x00, 0xc0, 0x01, 0x00,
+ 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00,
+ 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static const uchar whatsthis_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00,
+ 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00,
+ 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00,
+ 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00,
+ 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00,
+ 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+static const uchar whatsthism_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00,
+ 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00,
+ 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00,
+ 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00,
+ 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00,
+ 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00,
+ 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+
+static const uchar busy_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+ 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00,
+ 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00,
+ 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00,
+ 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00,
+ 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static const uchar busym_bits[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+ 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00,
+ 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00,
+ 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00,
+ 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00,
+ 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00,
+ 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// 16 x 16
+static const uchar openhand_bits[] = {
+ 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92,
+ 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20,
+ 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00};
+static const uchar openhandm_bits[] = {
+ 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff,
+ 0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f,
+ 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00};
+static const uchar closedhand_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50,
+ 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10,
+ 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00};
+static const uchar closedhandm_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f,
+ 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
+ 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
+
+void QPlatformCursorImage::createSystemCursor(int id)
+{
+ if (!systemCursorTableInit) {
+ for (int i = 0; i <= Qt::LastCursor; i++)
+ systemCursorTable[i] = 0;
+ systemCursorTableInit = true;
+ }
+ switch (id) {
+ // 16x16 cursors
+ case Qt::ArrowCursor:
+ systemCursorTable[Qt::ArrowCursor] =
+ new QPlatformCursorImage(cur_arrow_bits, mcur_arrow_bits, 16, 16, 0, 0);
+ break;
+
+ case Qt::UpArrowCursor:
+ systemCursorTable[Qt::UpArrowCursor] =
+ new QPlatformCursorImage(cur_up_arrow_bits, mcur_up_arrow_bits, 16, 16, 7, 0);
+ break;
+
+ case Qt::CrossCursor:
+ systemCursorTable[Qt::CrossCursor] =
+ new QPlatformCursorImage(cur_cross_bits, mcur_cross_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::IBeamCursor:
+ systemCursorTable[Qt::IBeamCursor] =
+ new QPlatformCursorImage(cur_ibeam_bits, mcur_ibeam_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeVerCursor:
+ systemCursorTable[Qt::SizeVerCursor] =
+ new QPlatformCursorImage(cur_ver_bits, mcur_ver_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeHorCursor:
+ systemCursorTable[Qt::SizeHorCursor] =
+ new QPlatformCursorImage(cur_hor_bits, mcur_hor_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeBDiagCursor:
+ systemCursorTable[Qt::SizeBDiagCursor] =
+ new QPlatformCursorImage(cur_bdiag_bits, mcur_bdiag_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeFDiagCursor:
+ systemCursorTable[Qt::SizeFDiagCursor] =
+ new QPlatformCursorImage(cur_fdiag_bits, mcur_fdiag_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::BlankCursor:
+ systemCursorTable[Qt::BlankCursor] =
+ new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
+ break;
+
+ // 20x20 cursors
+ case Qt::ForbiddenCursor:
+ systemCursorTable[Qt::ForbiddenCursor] =
+ new QPlatformCursorImage(forbidden_bits, forbiddenm_bits, 20, 20, 10, 10);
+ break;
+
+ // 32x32 cursors
+ case Qt::WaitCursor:
+ systemCursorTable[Qt::WaitCursor] =
+ new QPlatformCursorImage(wait_data_bits, wait_mask_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SplitVCursor:
+ systemCursorTable[Qt::SplitVCursor] =
+ new QPlatformCursorImage(vsplit_bits, vsplitm_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SplitHCursor:
+ systemCursorTable[Qt::SplitHCursor] =
+ new QPlatformCursorImage(hsplit_bits, hsplitm_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SizeAllCursor:
+ systemCursorTable[Qt::SizeAllCursor] =
+ new QPlatformCursorImage(size_all_data_bits, size_all_mask_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::PointingHandCursor:
+ systemCursorTable[Qt::PointingHandCursor] =
+ new QPlatformCursorImage(phand_bits, phandm_bits, 32, 32, 0, 0);
+ break;
+
+ case Qt::WhatsThisCursor:
+ systemCursorTable[Qt::WhatsThisCursor] =
+ new QPlatformCursorImage(whatsthis_bits, whatsthism_bits, 32, 32, 0, 0);
+ break;
+ case Qt::BusyCursor:
+ systemCursorTable[Qt::BusyCursor] =
+ new QPlatformCursorImage(busy_bits, busym_bits, 32, 32, 0, 0);
+ break;
+
+ case Qt::OpenHandCursor:
+ systemCursorTable[Qt::OpenHandCursor] =
+ new QPlatformCursorImage(openhand_bits, openhandm_bits, 16, 16, 8, 8);
+ break;
+ case Qt::ClosedHandCursor:
+ systemCursorTable[Qt::ClosedHandCursor] =
+ new QPlatformCursorImage(closedhand_bits, closedhandm_bits, 16, 16, 8, 8);
+ break;
+ default:
+ qWarning("Unknown system cursor %d", id);
+ }
+}
+
+/*!
+ \fn void QGraphicsSystemCursorImage::set(Qt::CursorShape id)
+
+ \brief Calling this method sets the cursor image to the specified shape
+
+ \a id is one of the defined Qt::CursorShape values.
+
+ If id is invalid, Qt::BitmapCursor, or unknown by the implementation,
+ Qt::ArrowCursor is used instead.
+*/
+
+void QPlatformCursorImage::set(Qt::CursorShape id)
+{
+ QPlatformCursorImage *cursor = 0;
+ if (id >= 0 && id <= Qt::LastCursor) {
+ if (!systemCursorTable[id])
+ createSystemCursor(id);
+ cursor = systemCursorTable[id];
+ }
+
+ if (cursor == 0) {
+ if (!systemCursorTable[Qt::ArrowCursor])
+ createSystemCursor(Qt::ArrowCursor);
+ cursor = systemCursorTable[Qt::ArrowCursor];
+ }
+ cursorImage = cursor->cursorImage;
+ hot = cursor->hot;
+}
+
+/*!
+ \fn void QGraphicsSystemCursorImage::set(const QImage * image, int hx, int hy)
+
+ \brief Set the cursor image to the specified QImage, with the hotsport at (hx, hy)
+
+ \a image A pointer to a QImage
+
+ \a hx The x coordinate of the cursor's hotspot
+
+ \a hy the y coordinate of the cursor's hotspot
+*/
+
+void QPlatformCursorImage::set(const QImage &image, int hx, int hy)
+{
+ hot.setX(hx);
+ hot.setY(hy);
+ cursorImage = image;
+}
+
+/*!
+ \fn void QGraphicsSystemCursorImage::set(const uchar *data, const uchar *mask, int width, int height, int hx, int hy)
+
+ \brief set the cursor image to the graphic represented by the combination of data, mask,
+ width, and height
+
+ \a data The pixel data of the graphic
+
+ \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn
+
+ \a width The width of the graphic in pixels
+
+ \a height The height of the graphic in pixels
+
+ \a hx The X hotspot of the cursor graphic
+
+ \a hy The Y hotspot of the cursor graphic
+*/
+void QPlatformCursorImage::set(const uchar *data, const uchar *mask,
+ int width, int height, int hx, int hy)
+{
+ hot.setX(hx);
+ hot.setY(hy);
+
+ cursorImage = QImage(width,height, QImage::Format_Indexed8);
+
+ if (!width || !height || !data || !mask || cursorImage.isNull())
+ return;
+
+ cursorImage.setNumColors(3);
+ cursorImage.setColor(0, 0xff000000);
+ cursorImage.setColor(1, 0xffffffff);
+ cursorImage.setColor(2, 0x00000000);
+
+ int bytesPerLine = (width + 7) / 8;
+ int p = 0;
+ int d, m;
+
+ int x = -1, w = 0;
+
+ uchar *cursor_data = cursorImage.bits();
+ int bpl = cursorImage.bytesPerLine();
+ for (int i = 0; i < height; i++)
+ {
+ for (int j = 0; j < bytesPerLine; j++, data++, mask++)
+ {
+ for (int b = 0; b < 8 && j*8+b < width; b++)
+ {
+ d = *data & (1 << b);
+ m = *mask & (1 << b);
+ if (d && m) p = 0;
+ else if (!d && m) p = 1;
+ else p = 2;
+ cursor_data[j*8+b] = p;
+
+ // calc region
+ if (x < 0 && m)
+ x = j*8+b;
+ else if (x >= 0 && !m) {
+ x = -1;
+ w = 0;
+ }
+ if (m)
+ w++;
+ }
+ }
+ if (x >= 0) {
+ x = -1;
+ w = 0;
+ }
+ cursor_data += bpl;
+ }
+
+}
+
+/*!
+ \fn QGraphicsSystemCursorImage::QGraphicsSystemCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY)
+
+ \brief set the cursor image to the graphic represented by the combination of data, mask,
+ width, and height
+
+ \a data The pixel data of the graphic
+
+ \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn
+
+ \a width The width of the graphic in pixels
+
+ \a height The height of the graphic in pixels
+
+ \a hotX The X hotspot of the cursor graphic
+
+ \a hotY The Y hotspot of the cursor graphic
+
+ \sa set
+*/
+
+/*!
+ \fn QImage *QGraphicsSystemCursorImage::image()
+
+ \brief Return the cursor graphic as a pointer to a QImage
+*/
+
+/*!
+ \fn QPoint QGraphicsSystemCursorImage::hotspot()
+
+ \brief Return the cursor's hotspot
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h
new file mode 100644
index 0000000000..71d0e87444
--- /dev/null
+++ b/src/gui/kernel/qplatformcursor_qpa.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenVG module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QGRAPHICSSYSTEMCURSOR_H
+#define QGRAPHICSSYSTEMCURSOR_H
+
+#include <QtCore/QList>
+#include <QtGui/QImage>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QWeakPointer>
+#include <QtCore/QObject>
+#include <QtGui/QPlatformScreen>
+#include <QtGui/QCursor>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+// Cursor graphics management
+class Q_GUI_EXPORT QPlatformCursorImage {
+public:
+ QPlatformCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY)
+ { set(data, mask, width, height, hotX, hotY); }
+ QImage * image() { return &cursorImage; }
+ QPoint hotspot() { return hot; }
+ void set(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY);
+ void set(const QImage &image, int hx, int hy);
+ void set(Qt::CursorShape);
+private:
+ static void createSystemCursor(int id);
+ QImage cursorImage;
+ QPoint hot;
+};
+
+class QPlatformCursor;
+
+class QPlatformCursorPrivate {
+public:
+ static QList<QWeakPointer<QPlatformCursor> > getInstances() { return instances; }
+ static QList<QWeakPointer<QPlatformCursor> > instances;
+};
+
+class Q_GUI_EXPORT QPlatformCursor : public QObject {
+public:
+ QPlatformCursor(QPlatformScreen *);
+
+ // input methods
+ virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); }
+ virtual void changeCursor(QCursor * widgetCursor, QWidget * widget) = 0;
+
+protected:
+ QPlatformScreen* screen; // Where to request an update
+
+private:
+ Q_DECLARE_PRIVATE(QPlatformCursor);
+ friend void qt_qpa_set_cursor(QWidget * w, bool force);
+ friend class QApplicationPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSSYSTEMCURSOR_H
diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.cpp b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp
new file mode 100644
index 0000000000..fdb3852748
--- /dev/null
+++ b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformeventloopintegration_qpa.h"
+
+#include <QtCore/QCoreApplication>
+
+#include <QtCore/QDebug>
+
+class QPlatformEventLoopIntegrationPrivate
+{
+public:
+ QPlatformEventLoopIntegrationPrivate();
+ qint64 nextTimerEvent;
+};
+
+QPlatformEventLoopIntegrationPrivate::QPlatformEventLoopIntegrationPrivate()
+ : nextTimerEvent(0)
+{
+}
+
+QPlatformEventLoopIntegration::QPlatformEventLoopIntegration()
+ : d_ptr(new QPlatformEventLoopIntegrationPrivate)
+
+{
+}
+
+QPlatformEventLoopIntegration::~QPlatformEventLoopIntegration()
+{
+}
+
+qint64 QPlatformEventLoopIntegration::nextTimerEvent() const
+{
+ Q_D(const QPlatformEventLoopIntegration);
+ return d->nextTimerEvent;
+}
+
+
+void QPlatformEventLoopIntegration::setNextTimerEvent(qint64 nextTimerEvent)
+{
+ Q_D(QPlatformEventLoopIntegration);
+ d->nextTimerEvent = nextTimerEvent;
+}
+
+void QPlatformEventLoopIntegration::processEvents()
+{
+ QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
+}
diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.h b/src/gui/kernel/qplatformeventloopintegration_qpa.h
new file mode 100644
index 0000000000..6e0f9847cf
--- /dev/null
+++ b/src/gui/kernel/qplatformeventloopintegration_qpa.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMEVENTLOOPINTEGRATION_QPA_H
+#define QPLATFORMEVENTLOOPINTEGRATION_QPA_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformEventLoopIntegrationPrivate;
+
+class Q_GUI_EXPORT QPlatformEventLoopIntegration
+{
+ Q_DECLARE_PRIVATE(QPlatformEventLoopIntegration);
+public:
+ QPlatformEventLoopIntegration();
+ virtual ~QPlatformEventLoopIntegration();
+
+ virtual void startEventLoop() = 0;
+ virtual void quitEventLoop() = 0;
+ virtual void qtNeedsToProcessEvents() = 0;
+
+ qint64 nextTimerEvent() const;
+ void setNextTimerEvent(qint64 nextTimerEvent);
+
+ static void processEvents();
+protected:
+ QScopedPointer<QPlatformEventLoopIntegrationPrivate> d_ptr;
+private:
+ Q_DISABLE_COPY(QPlatformEventLoopIntegration);
+ friend class QEventDispatcherQPA;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMEVENTLOOPINTEGRATION_QPA_H
diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp
new file mode 100644
index 0000000000..14bd71815a
--- /dev/null
+++ b/src/gui/kernel/qplatformglcontext_qpa.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformglcontext_qpa.h"
+
+#include <QtCore/QThreadStorage>
+#include <QtCore/QThread>
+
+#include <QDebug>
+
+class QPlatformGLThreadContext
+{
+public:
+ ~QPlatformGLThreadContext() {
+ if (context)
+ context->doneCurrent();
+ }
+ QPlatformGLContext *context;
+};
+
+static QThreadStorage<QPlatformGLThreadContext *> qplatformgl_context_storage;
+
+class QPlatformGLContextPrivate
+{
+public:
+ QPlatformGLContextPrivate()
+ :qGLContextHandle(0)
+ {
+ }
+
+ virtual ~QPlatformGLContextPrivate()
+ {
+ //do not delete the QGLContext handle here as it is deleted in
+ //QWidgetPrivate::deleteTLSysExtra()
+ }
+ void *qGLContextHandle;
+ void (*qGLContextDeleteFunction)(void *handle);
+ static QPlatformGLContext *staticSharedContext;
+
+ static void setCurrentContext(QPlatformGLContext *context);
+};
+
+QPlatformGLContext *QPlatformGLContextPrivate::staticSharedContext = 0;
+
+void QPlatformGLContextPrivate::setCurrentContext(QPlatformGLContext *context)
+{
+ QPlatformGLThreadContext *threadContext = qplatformgl_context_storage.localData();
+ if (!threadContext) {
+ if (!QThread::currentThread()) {
+ qWarning("No QTLS available. currentContext wont work");
+ return;
+ }
+ threadContext = new QPlatformGLThreadContext;
+ qplatformgl_context_storage.setLocalData(threadContext);
+ }
+ threadContext->context = context;
+}
+
+/*!
+ Returns the last context which called makeCurrent. This function is thread aware.
+*/
+const QPlatformGLContext* QPlatformGLContext::currentContext()
+{
+ QPlatformGLThreadContext *threadContext = qplatformgl_context_storage.localData();
+ if(threadContext) {
+ return threadContext->context;
+ }
+ return 0;
+}
+
+/*!
+ All subclasses needs to specify the platformWindow. It can be a null window.
+*/
+QPlatformGLContext::QPlatformGLContext()
+ :d_ptr(new QPlatformGLContextPrivate())
+{
+}
+
+/*!
+ If this is the current context for the thread, doneCurrent is called
+*/
+QPlatformGLContext::~QPlatformGLContext()
+{
+ if (QPlatformGLContext::currentContext() == this) {
+ doneCurrent();
+ }
+
+}
+
+
+/*!
+ Makes it possible to set the context which can be the default for making new contexts.
+*/
+void QPlatformGLContext::setDefaultSharedContext(QPlatformGLContext *sharedContext)
+{
+ QPlatformGLContextPrivate::staticSharedContext = sharedContext;
+}
+
+/*!
+ Default shared context is intended to be a globally awailable pointer to a context which can
+ be used for sharing resources when creating new contexts. Its default value is 0;
+*/
+const QPlatformGLContext *QPlatformGLContext::defaultSharedContext()
+{
+ return QPlatformGLContextPrivate::staticSharedContext;
+}
+
+/*!
+ Reimplement in subclass to do makeCurrent on native GL context
+*/
+void QPlatformGLContext::makeCurrent()
+{
+ QPlatformGLContextPrivate::setCurrentContext(this);
+}
+
+/*!
+ Reimplement in subclass to release current context.
+ Typically this is calling makeCurrent with 0 "surface"
+*/
+void QPlatformGLContext::doneCurrent()
+{
+ QPlatformGLContextPrivate::setCurrentContext(0);
+}
+
+/*
+ internal: Needs to have a pointer to qGLContext. But since this is in QtGui we cant
+ have any type information.
+*/
+void *QPlatformGLContext::qGLContextHandle() const
+{
+ Q_D(const QPlatformGLContext);
+ return d->qGLContextHandle;
+}
+
+void QPlatformGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))
+{
+ Q_D(QPlatformGLContext);
+ d->qGLContextHandle = handle;
+ d->qGLContextDeleteFunction = qGLContextDeleteFunction;
+}
+
+void QPlatformGLContext::deleteQGLContext()
+{
+ Q_D(QPlatformGLContext);
+ if (d->qGLContextDeleteFunction && d->qGLContextHandle) {
+ d->qGLContextDeleteFunction(d->qGLContextHandle);
+ d->qGLContextDeleteFunction = 0;
+ d->qGLContextHandle = 0;
+ }
+}
+
+/*!
+ \class QPlatformGLContext
+ \since 4.8
+ \internal
+ \preliminary
+ \ingroup qpa
+
+ \brief The QPlatformGLContext class provides an abstraction for native GL contexts.
+
+ In QPA the way to support OpenGL or OpenVG or other technologies that requires a native GL
+ context is through the QPlatformGLContext wrapper.
+
+ There is no factory function for QPlatformGLContexts, but rather only one accessor function.
+ The only place to retrieve a QPlatformGLContext from is through a QPlatformWindow.
+
+ The context which is current for a specific thread can be collected by the currentContext()
+ function. This is how QPlatformGLContext also makes it possible to use the QtOpenGL module
+ withhout using QGLWidget. When using QGLContext::currentContext(), it will ask
+ QPlatformGLContext for the currentContext. Then a corresponding QGLContext will be returned,
+ which maps to the QPlatformGLContext.
+*/
+
+/*! \fn void swapBuffers()
+ Reimplement in subclass to native swap buffers calls
+*/
+
+/*! getProcAddress(const QString& procName)
+ Reimplement in subclass to native getProcAddr calls.
+
+ Note: its convenient to use qPrintable(const QString &str) to get the const char * pointer
+*/
+
+/*! platformWindowFormat() const
+ QWidget has the function qplatformWindowFormat(). That function is for the application
+ programmer to request the format of the window and the context that he wants.
+
+ Reimplement this function in a subclass to indicate what format the glContext actually has.
+*/
diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformglcontext_qpa.h
new file mode 100644
index 0000000000..a70e04620a
--- /dev/null
+++ b/src/gui/kernel/qplatformglcontext_qpa.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORM_GL_CONTEXT_H
+#define QPLATFORM_GL_CONTEXT_H
+
+#include <QtCore/qnamespace.h>
+#include <QtGui/QPlatformWindowFormat>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformGLContextPrivate;
+
+class Q_OPENGL_EXPORT QPlatformGLContext
+{
+Q_DECLARE_PRIVATE(QPlatformGLContext);
+
+public:
+ explicit QPlatformGLContext();
+ virtual ~QPlatformGLContext();
+
+ virtual void makeCurrent();
+ virtual void doneCurrent();
+ virtual void swapBuffers() = 0;
+ virtual void* getProcAddress(const QString& procName) = 0;
+
+ virtual QPlatformWindowFormat platformWindowFormat() const = 0;
+
+ const static QPlatformGLContext *currentContext();
+ const static QPlatformGLContext *defaultSharedContext();
+
+protected:
+
+ static void setDefaultSharedContext(QPlatformGLContext *sharedContext);
+
+ QScopedPointer<QPlatformGLContextPrivate> d_ptr;
+private:
+ //hack to make it work with QGLContext::CurrentContext
+ friend class QGLContext;
+ friend class QWidgetPrivate;
+ void *qGLContextHandle() const;
+ void setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *));
+ void deleteQGLContext();
+ Q_DISABLE_COPY(QPlatformGLContext);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QPLATFORM_GL_INTEGRATION_P_H
diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp
new file mode 100644
index 0000000000..9b6e59085d
--- /dev/null
+++ b/src/gui/kernel/qplatformintegration_qpa.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformintegration_qpa.h"
+
+#include <QtGui/QPlatformFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+QPixmap QPlatformIntegration::grabWindow(WId window, int x, int y, int width, int height) const
+{
+ Q_UNUSED(window);
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+ return QPixmap();
+}
+
+/*!
+ Factory function for the eventloop integration interface.
+
+ Default implementation returns 0, which causes the eventloop to run in a single thread mode.
+
+ \sa QPlatformEventLoopIntegration
+*/
+QPlatformEventLoopIntegration *QPlatformIntegration::createEventLoopIntegration() const
+{
+ return 0;
+}
+
+/*!
+ Returns whether the given platform integration supports OpenGL.
+
+ Default implementation returns false,
+*/
+bool QPlatformIntegration::hasOpenGL() const
+{
+ return false;
+}
+
+/*!
+ Accessor for the platform integrations fontdatabase.
+
+ Default implementation returns a default QPlatformFontDatabase.
+
+ \sa QPlatformFontDatabase
+*/
+QPlatformFontDatabase *QPlatformIntegration::fontDatabase() const
+{
+ static QPlatformFontDatabase *db = 0;
+ if (!db) {
+ db = new QPlatformFontDatabase;
+ }
+ return db;
+}
+
+/*!
+ \class QPlatformIntegration
+ \since 4.8
+ \internal
+ \preliminary
+ \ingroup qpa
+ \brief The QPlatformIntegration class is the entry for WindowSystem specific functionality.
+
+ QPlatformIntegration is the single entry point for windowsystem specific functionality when
+ using the QPA platform. It has factory functions for creating platform specific pixmaps and
+ windows. The class also controls the font subsystem.
+
+ QPlatformIntegration is a singelton class which gets instansiated in the QApplication
+ constructor. The QPlatformIntegration instance do not have ownership of objects it creates in
+ functions where the name starts with create. However, functions which don't have a name
+ starting with create acts as assessors to member variables.
+
+ It is not trivial to create or build a platform plugin outside of the Qt source tree. Therefor
+ the recommended approach for making new platform plugin is to copy an existing plugin inside
+ the QTSRCTREE/src/plugins/platform and develop the plugin inside the source tree.
+
+ The minimal platformintegration is the smallest platform integration it is possible to make,
+ which makes it an ideal starting point for new plugins. For a slightly more advanced plugin,
+ consider reviewing the directfb plugin, or the testlite plugin.
+*/
+
+/*!
+ \fn QPixmapData *createPixmapData(QPixmapData::PixelType type) const
+
+ Factory function for QPixmapData. PixelType can be either PixmapType or BitmapType.
+ \sa QPixmapData
+*/
+
+/*!
+ \fn QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const
+
+ Factory function for QPlatformWindow. The widget parameter is a pointer to the top level
+ widget(tlw) which the QPlatformWindow is suppose to be created for. The WId handle is actually
+ never used, but there for future reference. Its purpose is if it is going to be possible to
+ create QPlatformWindows on existing WId.
+
+ All tlw has to have a QPlatformWindow, and it will be created when the QPlatformWindow is set
+ to be visible for the first time. If the tlw's window flags are changed, or if the tlw's
+ QPlatformWindowFormat is changed, then the tlw's QPlatformWindow is deleted and a new one is
+ created.
+
+ \sa QPlatformWindow, QPlatformWindowFormat
+ \sa createWindowSurface(QWidget *widget, WId winId) const
+*/
+
+/*!
+ \fn QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const
+
+ Factory function for QWindowSurface. The QWidget parameter is a pointer to the
+ top level widget(tlw) the window surface is created for. A QPlatformWindow is always created
+ before the QWindowSurface for tlw where the widget also requires a WindowSurface. It is
+ possible to create top level QWidgets without a QWindowSurface by specifying
+ QPlatformWindowFormat::setWindowSurface(false) for the tlw QPlatformWindowFormat.
+
+ \sa QWindowSurface
+ \sa createPlatformWindow(QWidget *widget, WId winId = 0) const
+*/
+
+/*!
+ \fn void moveToScreen(QWidget *window, int screen)
+
+ This function is called when a QWidget is displayed on screen, or the QWidget is to be
+ displayed on a new screen. The QWidget parameter is a pointer to the top level widget and
+ the int parameter is the index to the screen in QList<QPlatformScreen *> screens() const.
+
+ Default implementation does nothing.
+
+ \sa screens() const
+*/
+
+/*!
+ \fn QList<QPlatformScreen *> screens() const
+
+ Accessor function to a list of all the screens on the current system. The screen with the
+ index == 0 is the default/main screen.
+*/
+
+/*!
+ \fn bool isVirtualDesktop()
+
+ Returns if the current windowing system configuration defines all the screens to be one
+ desktop(virtual desktop), or if each screen is a desktop of its own.
+
+ Default implementation returns false.
+*/
+
+/*!
+ \fn QPixmap grabWindow(WId window, int x, int y, int width, int height) const
+
+ This function is called when Qt needs to be able to grab the content of a window.
+
+ Returnes the content of the window specified with the WId handle within the boundaries of
+ QRect(x,y,width,height).
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h
new file mode 100644
index 0000000000..f01b4f4c79
--- /dev/null
+++ b/src/gui/kernel/qplatformintegration_qpa.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMINTEGRATION_H
+#define QPLATFORMINTEGRATION_H
+
+#include <QtGui/qwindowdefs.h>
+#include <QtGui/private/qwindowsurface_p.h>
+#include <QtGui/private/qpixmapdata_p.h>
+#include <QtGui/qplatformscreen_qpa.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformWindow;
+class QWindowSurface;
+class QBlittable;
+class QWidget;
+class QPlatformEventLoopIntegration;
+class QPlatformFontDatabase;
+
+class Q_GUI_EXPORT QPlatformIntegration
+{
+public:
+ virtual ~QPlatformIntegration() { }
+
+// GraphicsSystem functions
+ virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0;
+ virtual QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const = 0;
+ virtual QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const = 0;
+
+// Window System functions
+ virtual QList<QPlatformScreen *> screens() const = 0;
+ virtual void moveToScreen(QWidget *window, int screen) {Q_UNUSED(window); Q_UNUSED(screen);}
+ virtual bool isVirtualDesktop() { return false; }
+ virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+
+//Fontdatabase integration.
+ virtual QPlatformFontDatabase *fontDatabase() const;
+
+// Experimental in mainthread eventloop integration
+// This should only be used if it is only possible to do window system event processing in
+// the gui thread. All of the functions in QWindowSystemInterface are thread safe.
+ virtual QPlatformEventLoopIntegration *createEventLoopIntegration() const;
+
+//jl:XXX should it be hasGLContext and do we need it at all?
+ virtual bool hasOpenGL() const;
+
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMINTEGRATION_H
diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp
new file mode 100644
index 0000000000..9122e1a300
--- /dev/null
+++ b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformintegrationfactory_qpa_p.h"
+#include <QPlatformIntegrationPlugin>
+#include "private/qfactoryloader_p.h"
+#include "qmutex.h"
+
+#include "qapplication.h"
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive))
+#endif
+
+QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key)
+{
+ QPlatformIntegration *ret = 0;
+ QStringList paramList = key.split(QLatin1Char(':'));
+ QString platform = paramList.takeFirst().toLower();
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ if (QPlatformIntegrationFactoryInterface *factory = qobject_cast<QPlatformIntegrationFactoryInterface*>(loader()->instance(platform)))
+ ret = factory->create(platform, paramList);
+#endif
+
+ return ret;
+}
+
+/*!
+ Returns the list of valid keys, i.e. the keys this factory can
+ create styles for.
+
+ \sa create()
+*/
+QStringList QPlatformIntegrationFactory::keys()
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QStringList list = loader()->keys();
+#else
+ QStringList list;
+#endif
+ return list;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa_p.h b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h
new file mode 100644
index 0000000000..ba02d2c6b6
--- /dev/null
+++ b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMINTEGRATIONFACTORY_H
+#define QPLATFORMINTEGRATIONFACTORY_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 <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformIntegration;
+
+class QPlatformIntegrationFactory
+{
+public:
+ static QStringList keys();
+ static QPlatformIntegration *create(const QString&);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMINTEGRATIONFACTORY_H
+
diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.cpp b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp
new file mode 100644
index 0000000000..3bf2474f52
--- /dev/null
+++ b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformintegrationplugin_qpa.h"
+
+QT_BEGIN_NAMESPACE
+
+QPlatformIntegrationPlugin::QPlatformIntegrationPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QPlatformIntegrationPlugin::~QPlatformIntegrationPlugin()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.h b/src/gui/kernel/qplatformintegrationplugin_qpa.h
new file mode 100644
index 0000000000..9c37cf72e5
--- /dev/null
+++ b/src/gui/kernel/qplatformintegrationplugin_qpa.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMINTEGRATIONPLUGIN_H
+#define QPLATFORMINTEGRATIONPLUGIN_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 <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformIntegration;
+
+struct QPlatformIntegrationFactoryInterface : public QFactoryInterface
+{
+ virtual QPlatformIntegration *create(const QString &key, const QStringList &paramList) = 0;
+};
+
+#define QPlatformIntegrationFactoryInterface_iid "com.nokia.Qt.QPlatformIntegrationFactoryInterface"
+
+Q_DECLARE_INTERFACE(QPlatformIntegrationFactoryInterface, QPlatformIntegrationFactoryInterface_iid)
+
+class Q_GUI_EXPORT QPlatformIntegrationPlugin : public QObject, public QPlatformIntegrationFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QPlatformIntegrationFactoryInterface:QFactoryInterface)
+public:
+ explicit QPlatformIntegrationPlugin(QObject *parent = 0);
+ ~QPlatformIntegrationPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QPlatformIntegration *create(const QString &key, const QStringList &paramList) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMINTEGRATIONPLUGIN_H
diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp
new file mode 100644
index 0000000000..5e80ba8d06
--- /dev/null
+++ b/src/gui/kernel/qplatformscreen_qpa.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformscreen_qpa.h"
+#include <QtGui/qapplication.h>
+#include <QtGui/qdesktopwidget.h>
+
+/*!
+ Return the given top level widget for a given position.
+
+ Default implementation retrieves a list of all top level widgets and finds the first widget
+ which contains point \a pos
+*/
+QWidget *QPlatformScreen::topLevelAt(const QPoint & pos) const
+{
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = list.size()-1; i >= 0; --i) {
+ QWidget *w = list[i];
+ //### mask is ignored
+ if (w != QApplication::desktop() && w->isVisible() && w->geometry().contains(pos))
+ return w;
+ }
+
+ return 0;
+}
+
+/*! \fn physicalSize() const
+ Reimplement in subclass to return the physical size of the screen. This function is used by
+ QFont to convert point sizes to pixel sizes.
+
+ Default implementation takes the pixel size of the screen, considers a dpi of 100 and returns
+ the calculated (and probably wrong) physical size
+*/
+QSize QPlatformScreen::physicalSize() const
+{
+ static const int dpi = 100;
+ int width = geometry().width() / dpi * qreal(25.4) ;
+ int height = geometry().height() / dpi * qreal(25.4) ;
+ return QSize(width,height);
+}
+
+/*!
+ \class QPlatformScreen
+ \since 4.8
+ \internal
+ \preliminary
+ \ingroup qpa
+
+ \brief The QPlatformScreen class provides an abstraction for visual displays.
+
+ Many window systems has support for retrieving information on the attached displays. To be able
+ to query the display QPA uses QPlatformScreen. Qt its self is most dependent on the
+ physicalSize() function, since this is the function it uses to calculate the dpi to use when
+ converting point sizes to pixels sizes. However, this is unfortunate on some systems, as the
+ native system fakes its dpi size.
+
+ QPlatformScreen is also used by the public api QDesktopWidget for information about the desktop.
+ */
+
+/*! \fn geometry() const
+ Reimplement in subclass to return the pixel geometry of the screen
+*/
+
+/*! \fn availableGeometry() const
+ Reimplement in subclass to return the pixel geometry of the available space
+ This normally is the desktop screen minus the task manager, global menubar etc.
+*/
+
+/*! \fn depth() const
+ Reimplement in subclass to return current depth of the screen
+*/
+
+/*! \fn format() const
+ Reimplement in subclass to return the image format which corresponds to the screen format
+*/
+
diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h
new file mode 100644
index 0000000000..908048950e
--- /dev/null
+++ b/src/gui/kernel/qplatformscreen_qpa.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMSCREEN_H
+#define QPLATFORMSCREEN_H
+
+#include <QtCore/qmetatype.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qobject.h>
+
+#include <QtGui/qcursor.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qwidget.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QPlatformScreen : public QObject
+{
+ Q_OBJECT
+public:
+ virtual ~QPlatformScreen() { }
+
+ virtual QRect geometry() const = 0;
+ virtual QRect availableGeometry() const {return geometry();}
+ virtual int depth() const = 0;
+ virtual QImage::Format format() const = 0;
+ virtual QSize physicalSize() const;
+ //jl: should setDirty be removed.
+ virtual void setDirty(const QRect &) {}
+ virtual QWidget *topLevelAt(const QPoint &point) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMSCREEN_H
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
new file mode 100644
index 0000000000..29eaa8277c
--- /dev/null
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformwindow_qpa.h"
+
+#include <QtGui/qwidget.h>
+
+class QPlatformWindowPrivate
+{
+ QWidget *tlw;
+ QRect rect;
+ Qt::WindowFlags flags;
+ friend class QPlatformWindow;
+};
+
+/*!
+ Constructs a platform window with the given top level widget.
+*/
+
+QPlatformWindow::QPlatformWindow(QWidget *tlw)
+ : d_ptr(new QPlatformWindowPrivate)
+{
+ Q_D(QPlatformWindow);
+ d->tlw = tlw;
+ tlw->setPlatformWindow(this);
+}
+
+/*!
+ Virtual destructor does not delete its top level widget.
+*/
+QPlatformWindow::~QPlatformWindow()
+{
+}
+
+/*!
+ Returnes the widget which belongs to the QPlatformWindow
+*/
+QWidget *QPlatformWindow::widget() const
+{
+ Q_D(const QPlatformWindow);
+ return d->tlw;
+}
+
+/*!
+ This function is called by Qt whenever a window is moved or the window is resized. The resize
+ can happen programatically(from ie. user application) or by the window manager. This means that
+ there is no need to call this function specifically from the window manager callback, instead
+ call QWindowSystemInterface::handleGeometryChange(QWidget *w, const QRect &newRect);
+*/
+void QPlatformWindow::setGeometry(const QRect &rect)
+{
+ Q_D(QPlatformWindow);
+ d->rect = rect;
+}
+
+/*!
+ Returnes the current geometry of a window
+*/
+QRect QPlatformWindow::geometry() const
+{
+ Q_D(const QPlatformWindow);
+ return d->rect;
+}
+
+/*!
+ Reimplemented in subclasses to show the surface
+ if \a visible is \c true, and hide it if \a visible is \c false.
+*/
+void QPlatformWindow::setVisible(bool visible)
+{
+ Q_UNUSED(visible);
+}
+/*!
+ Requests setting the window flags of this surface
+ to \a type. Returns the actual flags set.
+*/
+Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
+{
+ Q_D(QPlatformWindow);
+ d->flags = flags;
+ return flags;
+}
+
+/*!
+ Returns the effective window flags for this surface.
+*/
+Qt::WindowFlags QPlatformWindow::windowFlags() const
+{
+ Q_D(const QPlatformWindow);
+ return d->flags;
+}
+
+/*!
+ Reimplement in subclasses to return a handle to the native window
+*/
+WId QPlatformWindow::winId() const { return WId(0); }
+
+/*!
+ This function is called to enable native child widgets in QPA. It is common not to support this
+ feature in Window systems, but can be faked. When this function is called all geometry of this
+ platform window will be relative to the parent.
+*/
+//jl: It would be useful to have a property on the platform window which indicated if the sub-class
+// supported the setParent. If not, then geometry would be in screen coordinates.
+void QPlatformWindow::setParent(const QPlatformWindow *parent)
+{
+ Q_UNUSED(parent);
+ qWarning("This plugin does not support setParent!");
+}
+
+/*!
+ Reimplement to set the window title to \a title
+*/
+void QPlatformWindow::setWindowTitle(const QString &title) {}
+
+/*!
+ Reimplement to be able to let Qt rais windows to the top of the desktop
+*/
+void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); }
+
+/*!
+ Reimplement to be able to let Qt lower windows to the bottom of the desktop
+*/
+void QPlatformWindow::lower() { qWarning("This plugin does not support lower()"); }
+
+/*!
+ Reimplement to be able to let Qt set the opacity level of a window
+*/
+void QPlatformWindow::setOpacity(qreal level)
+{
+ Q_UNUSED(level);
+ qWarning("This plugin does not support setting window opacity");
+}
+
+/*!
+ Reimplement to return the glContext associated with the window.
+*/
+QPlatformGLContext *QPlatformWindow::glContext() const
+{
+ return 0;
+}
+
+/*!
+ \class QPlatformWindow
+ \since 4.8
+ \internal
+ \preliminary
+ \ingroup qpa
+
+ \brief The QPlatformWindow class provides an abstraction for top-level windows.
+
+ The QPlatformWindow abstraction is used by QWidget for all its top level widgets. It is being
+ created by calling the createPlatformWindow function in the loaded QPlatformIntegration
+ instance.
+
+ QPlatformWindow is used to signal to the windowing system, how Qt persieves its frame.
+ However, it is not concerned with how Qt renders into the window it represents.
+
+ Top level QWidgets(tlw) will always have a QPlatformWindow. However, it is not necessary for
+ all tlw to have a QWindowSurface. This is the case for QGLWidget. And could be the case for
+ widgets where some 3.party renders into it.
+
+ The platform specific window handle can be retrieved by the winId function.
+
+ QPlatformWindow is also the way QPA defines how native child windows should be supported
+ through the setParent function.
+
+ The only way to retrieve a QPlatformGLContext in QPA is by calling the glContext() function
+ on QPlatformWindow.
+
+ \sa QWindowSurface, QWidget
+*/
diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h
new file mode 100644
index 0000000000..4f6fedc80e
--- /dev/null
+++ b/src/gui/kernel/qplatformwindow_qpa.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QPLATFORMWINDOW_H
+#define QPLATFORMWINDOW_H
+
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qstring.h>
+#include <QtGui/qwindowdefs.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformWindowPrivate;
+class QWidget;
+class QPlatformGLContext;
+
+class Q_GUI_EXPORT QPlatformWindow
+{
+ Q_DECLARE_PRIVATE(QPlatformWindow)
+public:
+ QPlatformWindow(QWidget *tlw);
+ virtual ~QPlatformWindow();
+
+ QWidget *widget() const;
+ virtual void setGeometry(const QRect &rect);
+ virtual QRect geometry() const;
+
+ virtual void setVisible(bool visible);
+ virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
+ virtual Qt::WindowFlags windowFlags() const;
+ virtual WId winId() const;
+ virtual void setParent(const QPlatformWindow *window);
+
+ virtual void setWindowTitle(const QString &title);
+ virtual void raise();
+ virtual void lower();
+
+ virtual void setOpacity(qreal level);
+
+ virtual QPlatformGLContext *glContext() const;
+protected:
+ QScopedPointer<QPlatformWindowPrivate> d_ptr;
+private:
+ Q_DISABLE_COPY(QPlatformWindow)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif //QPLATFORMWINDOW_H
diff --git a/src/gui/kernel/qplatformwindowformat_qpa.cpp b/src/gui/kernel/qplatformwindowformat_qpa.cpp
new file mode 100644
index 0000000000..44b0698fda
--- /dev/null
+++ b/src/gui/kernel/qplatformwindowformat_qpa.cpp
@@ -0,0 +1,1019 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformwindowformat_qpa.h"
+
+#include <QtCore/QDebug>
+
+Q_GLOBAL_STATIC(QPlatformWindowFormat, q_platformwindow_default_format);
+
+class QPlatformWindowFormatPrivate
+{
+public:
+ QPlatformWindowFormatPrivate()
+ : ref(1)
+ , opts(QPlatformWindowFormat::DoubleBuffer | QPlatformWindowFormat::DepthBuffer
+ | QPlatformWindowFormat::Rgba | QPlatformWindowFormat::DirectRendering
+ | QPlatformWindowFormat::StencilBuffer | QPlatformWindowFormat::DeprecatedFunctions
+ | QPlatformWindowFormat::UseDefaultSharedContext | QPlatformWindowFormat::HasWindowSurface)
+ , depthSize(-1)
+ , accumSize(-1)
+ , stencilSize(-1)
+ , redSize(-1)
+ , greenSize(-1)
+ , blueSize(-1)
+ , alphaSize(-1)
+ , numSamples(-1)
+ , swapInterval(-1)
+ , windowApi(QPlatformWindowFormat::Raster)
+ , sharedContext(0)
+ {
+ }
+
+ QPlatformWindowFormatPrivate(const QPlatformWindowFormatPrivate *other)
+ : ref(1),
+ opts(other->opts),
+ depthSize(other->depthSize),
+ accumSize(other->accumSize),
+ stencilSize(other->stencilSize),
+ redSize(other->redSize),
+ greenSize(other->greenSize),
+ blueSize(other->blueSize),
+ alphaSize(other->alphaSize),
+ numSamples(other->numSamples),
+ swapInterval(other->swapInterval),
+ windowApi(other->windowApi),
+ sharedContext(other->sharedContext)
+ {
+ }
+ QAtomicInt ref;
+ QPlatformWindowFormat::FormatOptions opts;
+ int depthSize;
+ int accumSize;
+ int stencilSize;
+ int redSize;
+ int greenSize;
+ int blueSize;
+ int alphaSize;
+ int numSamples;
+ int swapInterval;
+ QPlatformWindowFormat::WindowApi windowApi;
+ QPlatformGLContext *sharedContext;
+};
+
+/*!
+ \class QPlatformWindowFormat
+ \brief The QPlatformWindowFormat class specifies the display format of an OpenGL
+ rendering context and if possible attributes of the corresponding QPlatformWindow.
+
+ \ingroup painting
+
+ QWidget has a setter and getter function for QPlatformWindowFormat. These functions can be used
+ by the application programmer to signal what kind of format he wants to the window and glcontext
+ should have. However, it is not always possible to fulfill these requirements. The application
+ programmer should therefore check the resulting QPlatformWindowFormat from QPlatformGLContext
+ to see the format that was actually created.
+
+ A display format has several characteristics:
+ \list
+ \i \link setDoubleBuffer() Double or single buffering.\endlink
+ \i \link setDepth() Depth buffer.\endlink
+ \i \link setRgba() RGBA or color index mode.\endlink
+ \i \link setAlpha() Alpha channel.\endlink
+ \i \link setAccum() Accumulation buffer.\endlink
+ \i \link setStencil() Stencil buffer.\endlink
+ \i \link setStereo() Stereo buffers.\endlink
+ \i \link setDirectRendering() Direct rendering.\endlink
+ \i \link setOverlay() Presence of an overlay.\endlink
+ \i \link setPlane() Plane of an overlay.\endlink
+ \i \link setSampleBuffers() Multisample buffers.\endlink
+ \endlist
+
+ You can also specify preferred bit depths for the color buffer,
+ depth buffer, alpha buffer, accumulation buffer and the stencil
+ buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
+ setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
+ setAccumBufferSize() and setStencilBufferSize().
+
+ Note that even if you specify that you prefer a 32 bit depth
+ buffer (e.g. with setDepthBufferSize(32)), the format that is
+ chosen may not have a 32 bit depth buffer, even if there is a
+ format available with a 32 bit depth buffer. The main reason for
+ this is how the system dependant picking algorithms work on the
+ different platforms, and some format options may have higher
+ precedence than others.
+
+ You create and tell a QPlatformWindowFormat object what rendering options you
+ want from an OpenGL rendering context.
+
+ OpenGL drivers or accelerated hardware may or may not support
+ advanced features such as alpha channel or stereographic viewing.
+ If you request some features that the driver/hardware does not
+ provide when you create a QGLWidget, you will get a rendering
+ context with the nearest subset of features.
+
+ There are different ways to define the display characteristics of
+ a rendering context. One is to create a QPlatformWindowFormat and make it the
+ default for the entire application:
+ \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0
+
+ Or you can specify the desired format when creating an object of
+ your QGLWidget subclass:
+ \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1
+
+ After the widget has been created, you can find out which of the
+ requested features the system was able to provide:
+ \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2
+
+ \legalese
+ OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+ \endlegalese
+
+ \sa QPlatformContext, QWidget
+*/
+
+/*!
+ Constructs a QPlatformWindowFormat object with the following default settings:
+ \list
+ \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
+ \i \link setDepth() Depth buffer:\endlink Enabled.
+ \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
+ \i \link setAlpha() Alpha channel:\endlink Disabled.
+ \i \link setAccum() Accumulator buffer:\endlink Disabled.
+ \i \link setStencil() Stencil buffer:\endlink Enabled.
+ \i \link setStereo() Stereo:\endlink Disabled.
+ \i \link setDirectRendering() Direct rendering:\endlink Enabled.
+ \i \link setOverlay() Overlay:\endlink Disabled.
+ \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
+ \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
+ \endlist
+*/
+
+QPlatformWindowFormat::QPlatformWindowFormat()
+{
+ d = new QPlatformWindowFormatPrivate;
+}
+
+
+/*!
+ Creates a QPlatformWindowFormat object that is a copy of the current
+ defaultFormat().
+
+ If \a options is not 0, the default format is modified by the
+ specified format options. The \a options parameter should be
+ QGL::FormatOption values OR'ed together.
+
+ This constructor makes it easy to specify a certain desired format
+ in classes derived from QGLWidget, for example:
+ \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
+
+ Note that there are QGL::FormatOption values to turn format settings
+ both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
+ QGL::DirectRendering and QGL::IndirectRendering, etc.
+
+ The \a plane parameter defaults to 0 and is the plane which this
+ format should be associated with. Not all OpenGL implementations
+ supports overlay/underlay rendering planes.
+
+ \sa defaultFormat(), setOption(), setPlane()
+*/
+
+QPlatformWindowFormat::QPlatformWindowFormat(QPlatformWindowFormat::FormatOptions options)
+{
+ d = new QPlatformWindowFormatPrivate;
+ QPlatformWindowFormat::FormatOptions newOpts = options;
+ d->opts = defaultFormat().d->opts;
+ d->opts |= (newOpts & 0xffff);
+ d->opts &= ~(newOpts >> 16);
+}
+
+/*!
+ \internal
+*/
+void QPlatformWindowFormat::detach()
+{
+ if (d->ref != 1) {
+ QPlatformWindowFormatPrivate *newd = new QPlatformWindowFormatPrivate(d);
+ if (!d->ref.deref())
+ delete d;
+ d = newd;
+ }
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+
+QPlatformWindowFormat::QPlatformWindowFormat(const QPlatformWindowFormat &other)
+{
+ d = other.d;
+ d->ref.ref();
+}
+
+/*!
+ Assigns \a other to this object.
+*/
+
+QPlatformWindowFormat &QPlatformWindowFormat::operator=(const QPlatformWindowFormat &other)
+{
+ if (d != other.d) {
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = other.d;
+ }
+ return *this;
+}
+
+/*!
+ Destroys the QPlatformWindowFormat.
+*/
+QPlatformWindowFormat::~QPlatformWindowFormat()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ \fn bool QPlatformWindowFormat::doubleBuffer() const
+
+ Returns true if double buffering is enabled; otherwise returns
+ false. Double buffering is enabled by default.
+
+ \sa setDoubleBuffer()
+*/
+
+/*!
+ If \a enable is true sets double buffering; otherwise sets single
+ buffering.
+
+ Double buffering is enabled by default.
+
+ Double buffering is a technique where graphics are rendered on an
+ off-screen buffer and not directly to the screen. When the drawing
+ has been completed, the program calls a swapBuffers() function to
+ exchange the screen contents with the buffer. The result is
+ flicker-free drawing and often better performance.
+
+ \sa doubleBuffer(), QGLContext::swapBuffers(),
+ QGLWidget::swapBuffers()
+*/
+
+void QPlatformWindowFormat::setDoubleBuffer(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::DoubleBuffer : QPlatformWindowFormat::SingleBuffer);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::depth() const
+
+ Returns true if the depth buffer is enabled; otherwise returns
+ false. The depth buffer is enabled by default.
+
+ \sa setDepth(), setDepthBufferSize()
+*/
+
+/*!
+ If \a enable is true enables the depth buffer; otherwise disables
+ the depth buffer.
+
+ The depth buffer is enabled by default.
+
+ The purpose of a depth buffer (or Z-buffering) is to remove hidden
+ surfaces. Pixels are assigned Z values based on the distance to
+ the viewer. A pixel with a high Z value is closer to the viewer
+ than a pixel with a low Z value. This information is used to
+ decide whether to draw a pixel or not.
+
+ \sa depth(), setDepthBufferSize()
+*/
+
+void QPlatformWindowFormat::setDepth(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::DepthBuffer : QPlatformWindowFormat::NoDepthBuffer);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::rgba() const
+
+ Returns true if RGBA color mode is set. Returns false if color
+ index mode is set. The default color mode is RGBA.
+
+ \sa setRgba()
+*/
+
+/*!
+ If \a enable is true sets RGBA mode. If \a enable is false sets
+ color index mode.
+
+ The default color mode is RGBA.
+
+ RGBA is the preferred mode for most OpenGL applications. In RGBA
+ color mode you specify colors as red + green + blue + alpha
+ quadruplets.
+
+ In color index mode you specify an index into a color lookup
+ table.
+
+ \sa rgba()
+*/
+
+void QPlatformWindowFormat::setRgba(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::Rgba : QPlatformWindowFormat::ColorIndex);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::alpha() const
+
+ Returns true if the alpha buffer in the framebuffer is enabled;
+ otherwise returns false. The alpha buffer is disabled by default.
+
+ \sa setAlpha(), setAlphaBufferSize()
+*/
+
+/*!
+ If \a enable is true enables the alpha buffer; otherwise disables
+ the alpha buffer.
+
+ The alpha buffer is disabled by default.
+
+ The alpha buffer is typically used for implementing transparency
+ or translucency. The A in RGBA specifies the transparency of a
+ pixel.
+
+ \sa alpha(), setAlphaBufferSize()
+*/
+
+void QPlatformWindowFormat::setAlpha(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::AlphaChannel : QPlatformWindowFormat::NoAlphaChannel);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::accum() const
+
+ Returns true if the accumulation buffer is enabled; otherwise
+ returns false. The accumulation buffer is disabled by default.
+
+ \sa setAccum(), setAccumBufferSize()
+*/
+
+/*!
+ If \a enable is true enables the accumulation buffer; otherwise
+ disables the accumulation buffer.
+
+ The accumulation buffer is disabled by default.
+
+ The accumulation buffer is used to create blur effects and
+ multiple exposures.
+
+ \sa accum(), setAccumBufferSize()
+*/
+
+void QPlatformWindowFormat::setAccum(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::AccumBuffer : QPlatformWindowFormat::NoAccumBuffer);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::stencil() const
+
+ Returns true if the stencil buffer is enabled; otherwise returns
+ false. The stencil buffer is enabled by default.
+
+ \sa setStencil(), setStencilBufferSize()
+*/
+
+/*!
+ If \a enable is true enables the stencil buffer; otherwise
+ disables the stencil buffer.
+
+ The stencil buffer is enabled by default.
+
+ The stencil buffer masks certain parts of the drawing area so that
+ masked parts are not drawn on.
+
+ \sa stencil(), setStencilBufferSize()
+*/
+
+void QPlatformWindowFormat::setStencil(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::StencilBuffer: QPlatformWindowFormat::NoStencilBuffer);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::stereo() const
+
+ Returns true if stereo buffering is enabled; otherwise returns
+ false. Stereo buffering is disabled by default.
+
+ \sa setStereo()
+*/
+
+/*!
+ If \a enable is true enables stereo buffering; otherwise disables
+ stereo buffering.
+
+ Stereo buffering is disabled by default.
+
+ Stereo buffering provides extra color buffers to generate left-eye
+ and right-eye images.
+
+ \sa stereo()
+*/
+
+void QPlatformWindowFormat::setStereo(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::StereoBuffers : QPlatformWindowFormat::NoStereoBuffers);
+}
+
+
+/*!
+ \fn bool QPlatformWindowFormat::directRendering() const
+
+ Returns true if direct rendering is enabled; otherwise returns
+ false.
+
+ Direct rendering is enabled by default.
+
+ \sa setDirectRendering()
+*/
+
+/*!
+ If \a enable is true enables direct rendering; otherwise disables
+ direct rendering.
+
+ Direct rendering is enabled by default.
+
+ Enabling this option will make OpenGL bypass the underlying window
+ system and render directly from hardware to the screen, if this is
+ supported by the system.
+
+ \sa directRendering()
+*/
+
+void QPlatformWindowFormat::setDirectRendering(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::DirectRendering : QPlatformWindowFormat::IndirectRendering);
+}
+
+/*!
+ \fn bool QPlatformWindowFormat::sampleBuffers() const
+
+ Returns true if multisample buffer support is enabled; otherwise
+ returns false.
+
+ The multisample buffer is disabled by default.
+
+ \sa setSampleBuffers()
+*/
+
+/*!
+ If \a enable is true, a GL context with multisample buffer support
+ is picked; otherwise ignored.
+
+ \sa sampleBuffers(), setSamples(), samples()
+*/
+void QPlatformWindowFormat::setSampleBuffers(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::SampleBuffers : QPlatformWindowFormat::NoSampleBuffers);
+}
+
+void QPlatformWindowFormat::setUseDefaultSharedContext(bool enable)
+{
+ if (enable) {
+ setOption(QPlatformWindowFormat::UseDefaultSharedContext);
+ d->sharedContext = 0;
+ } else {
+ setOption(QPlatformWindowFormat::NoDefaultSharedContext);
+ }
+}
+
+/*!
+ Returns the number of samples per pixel when multisampling is
+ enabled. By default, the highest number of samples that is
+ available is used.
+
+ \sa setSampleBuffers(), sampleBuffers(), setSamples()
+*/
+int QPlatformWindowFormat::samples() const
+{
+ return d->numSamples;
+}
+
+/*!
+ Set the preferred number of samples per pixel when multisampling
+ is enabled to \a numSamples. By default, the highest number of
+ samples available is used.
+
+ \sa setSampleBuffers(), sampleBuffers(), samples()
+*/
+void QPlatformWindowFormat::setSamples(int numSamples)
+{
+ detach();
+ if (numSamples < 0) {
+ qWarning("QPlatformWindowFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
+ return;
+ }
+ d->numSamples = numSamples;
+ setSampleBuffers(numSamples > 0);
+}
+
+/*!
+ \since 4.2
+
+ Set the preferred swap interval. This can be used to sync the GL
+ drawing into a system window to the vertical refresh of the screen.
+ Setting an \a interval value of 0 will turn the vertical refresh syncing
+ off, any value higher than 0 will turn the vertical syncing on.
+
+ Under Windows and under X11, where the \c{WGL_EXT_swap_control}
+ and \c{GLX_SGI_video_sync} extensions are used, the \a interval
+ parameter can be used to set the minimum number of video frames
+ that are displayed before a buffer swap will occur. In effect,
+ setting the \a interval to 10, means there will be 10 vertical
+ retraces between every buffer swap.
+
+ Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
+ and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
+*/
+void QPlatformWindowFormat::setSwapInterval(int interval)
+{
+ detach();
+ d->swapInterval = interval;
+}
+
+/*!
+ \since 4.2
+
+ Returns the currently set swap interval. -1 is returned if setting
+ the swap interval isn't supported in the system GL implementation.
+*/
+int QPlatformWindowFormat::swapInterval() const
+{
+ return d->swapInterval;
+}
+
+void QPlatformWindowFormat::setWindowApi(QPlatformWindowFormat::WindowApi api)
+{
+ detach();
+ d->windowApi = api;
+}
+
+QPlatformWindowFormat::WindowApi QPlatformWindowFormat::windowApi() const
+{
+ return d->windowApi;
+}
+
+void QPlatformWindowFormat::setSharedContext(QPlatformGLContext *context)
+{
+ setUseDefaultSharedContext(false);
+ d->sharedContext = context;
+}
+
+QPlatformGLContext *QPlatformWindowFormat::sharedGLContext() const
+{
+ return d->sharedContext;
+}
+
+/*!
+ \fn bool QPlatformWindowFormat::hasWindowSurface() const
+
+ Returns true if the corresponding widget has an instance of QWindowSurface.
+
+ Otherwise returns false.
+
+ WindowSurface is enabled by default.
+
+ \sa setOverlay()
+*/
+
+/*!
+ If \a enable is true a top level QWidget will create a QWindowSurface at creation;
+
+ otherwise the QWidget will only have a QPlatformWindow.
+
+ This is useful for ie. QGLWidget where the QPlatformGLContext controls the surface.
+
+ \sa hasOverlay()
+*/
+
+void QPlatformWindowFormat::setWindowSurface(bool enable)
+{
+ setOption(enable ? QPlatformWindowFormat::HasWindowSurface : QPlatformWindowFormat::NoWindowSurface);
+}
+
+/*!
+ Sets the format option to \a opt.
+
+ \sa testOption()
+*/
+
+void QPlatformWindowFormat::setOption(QPlatformWindowFormat::FormatOptions opt)
+{
+ detach();
+ if (opt & 0xffff)
+ d->opts |= opt;
+ else
+ d->opts &= ~(opt >> 16);
+}
+
+
+
+/*!
+ Returns true if format option \a opt is set; otherwise returns false.
+
+ \sa setOption()
+*/
+
+bool QPlatformWindowFormat::testOption(QPlatformWindowFormat::FormatOptions opt) const
+{
+ if (opt & 0xffff)
+ return (d->opts & opt) != 0;
+ else
+ return (d->opts & (opt >> 16)) == 0;
+}
+
+/*!
+ Set the minimum depth buffer size to \a size.
+
+ \sa depthBufferSize(), setDepth(), depth()
+*/
+void QPlatformWindowFormat::setDepthBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
+ return;
+ }
+ d->depthSize = size;
+ setDepth(size > 0);
+}
+
+/*!
+ Returns the depth buffer size.
+
+ \sa depth(), setDepth(), setDepthBufferSize()
+*/
+int QPlatformWindowFormat::depthBufferSize() const
+{
+ return d->depthSize;
+}
+
+/*!
+ \since 4.2
+
+ Set the preferred red buffer size to \a size.
+
+ \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
+*/
+void QPlatformWindowFormat::setRedBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
+ return;
+ }
+ d->redSize = size;
+}
+
+/*!
+ \since 4.2
+
+ Returns the red buffer size.
+
+ \sa setRedBufferSize()
+*/
+int QPlatformWindowFormat::redBufferSize() const
+{
+ return d->redSize;
+}
+
+/*!
+ \since 4.2
+
+ Set the preferred green buffer size to \a size.
+
+ \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
+*/
+void QPlatformWindowFormat::setGreenBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
+ return;
+ }
+ d->greenSize = size;
+}
+
+/*!
+ \since 4.2
+
+ Returns the green buffer size.
+
+ \sa setGreenBufferSize()
+*/
+int QPlatformWindowFormat::greenBufferSize() const
+{
+ return d->greenSize;
+}
+
+/*!
+ \since 4.2
+
+ Set the preferred blue buffer size to \a size.
+
+ \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
+*/
+void QPlatformWindowFormat::setBlueBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
+ return;
+ }
+ d->blueSize = size;
+}
+
+/*!
+ \since 4.2
+
+ Returns the blue buffer size.
+
+ \sa setBlueBufferSize()
+*/
+int QPlatformWindowFormat::blueBufferSize() const
+{
+ return d->blueSize;
+}
+
+/*!
+ Set the preferred alpha buffer size to \a size.
+ This function implicitly enables the alpha channel.
+
+ \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
+*/
+void QPlatformWindowFormat::setAlphaBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
+ return;
+ }
+ d->alphaSize = size;
+ setAlpha(size > 0);
+}
+
+/*!
+ Returns the alpha buffer size.
+
+ \sa alpha(), setAlpha(), setAlphaBufferSize()
+*/
+int QPlatformWindowFormat::alphaBufferSize() const
+{
+ return d->alphaSize;
+}
+
+/*!
+ Set the preferred accumulation buffer size, where \a size is the
+ bit depth for each RGBA component.
+
+ \sa accum(), setAccum(), accumBufferSize()
+*/
+void QPlatformWindowFormat::setAccumBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
+ return;
+ }
+ d->accumSize = size;
+ setAccum(size > 0);
+}
+
+/*!
+ Returns the accumulation buffer size.
+
+ \sa setAccumBufferSize(), accum(), setAccum()
+*/
+int QPlatformWindowFormat::accumBufferSize() const
+{
+ return d->accumSize;
+}
+
+/*!
+ Set the preferred stencil buffer size to \a size.
+
+ \sa stencilBufferSize(), setStencil(), stencil()
+*/
+void QPlatformWindowFormat::setStencilBufferSize(int size)
+{
+ detach();
+ if (size < 0) {
+ qWarning("QPlatformWindowFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
+ return;
+ }
+ d->stencilSize = size;
+ setStencil(size > 0);
+}
+
+/*!
+ Returns the stencil buffer size.
+
+ \sa stencil(), setStencil(), setStencilBufferSize()
+*/
+int QPlatformWindowFormat::stencilBufferSize() const
+{
+ return d->stencilSize;
+}
+
+/*!
+ Returns the default QPlatformWindowFormat for the application. All QGLWidget
+ objects that are created use this format unless another format is
+ specified, e.g. when they are constructed.
+
+ If no special default format has been set using
+ setDefaultFormat(), the default format is the same as that created
+ with QPlatformWindowFormat().
+
+ \sa setDefaultFormat()
+*/
+
+QPlatformWindowFormat QPlatformWindowFormat::defaultFormat()
+{
+ return *q_platformwindow_default_format();
+}
+
+/*!
+ Sets a new default QPlatformWindowFormat for the application to \a f. For
+ example, to set single buffering as the default instead of double
+ buffering, your main() might contain code like this:
+ \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4
+
+ \sa defaultFormat()
+*/
+
+void QPlatformWindowFormat::setDefaultFormat(const QPlatformWindowFormat &f)
+{
+ *q_platformwindow_default_format() = f;
+}
+
+
+/*!
+ Returns the default QPlatformWindowFormat for overlay contexts.
+
+ The default overlay format is:
+ \list
+ \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
+ \i \link setDepth() Depth buffer:\endlink Disabled.
+ \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
+ \i \link setAlpha() Alpha channel:\endlink Disabled.
+ \i \link setAccum() Accumulator buffer:\endlink Disabled.
+ \i \link setStencil() Stencil buffer:\endlink Disabled.
+ \i \link setStereo() Stereo:\endlink Disabled.
+ \i \link setDirectRendering() Direct rendering:\endlink Enabled.
+ \i \link setOverlay() Overlay:\endlink Disabled.
+ \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
+ \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
+ \endlist
+
+ \sa setDefaultFormat()
+*/
+
+//QPlatformWindowFormat QPlatformWindowFormat::defaultOverlayFormat()
+//{
+// return *defaultOverlayFormatInstance();
+//}
+
+///*!
+// Sets a new default QPlatformWindowFormat for overlay contexts to \a f. This
+// format is used whenever a QGLWidget is created with a format that
+// hasOverlay() enabled.
+
+// For example, to get a double buffered overlay context (if
+// available), use code like this:
+
+// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5
+
+// As usual, you can find out after widget creation whether the
+// underlying OpenGL system was able to provide the requested
+// specification:
+
+// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6
+
+// \sa defaultOverlayFormat()
+//*/
+
+//void QPlatformWindowFormat::setDefaultOverlayFormat(const QPlatformWindowFormat &f)
+//{
+// QPlatformWindowFormat *defaultFormat = defaultOverlayFormatInstance();
+// *defaultFormat = f;
+// // Make sure the user doesn't request that the overlays themselves
+// // have overlays, since it is unlikely that the system supports
+// // infinitely many planes...
+// defaultFormat->setOverlay(false);
+//}
+
+
+/*!
+ Returns true if all the options of the two QPlatformWindowFormat objects
+ \a a and \a b are equal; otherwise returns false.
+
+ \relates QPlatformWindowFormat
+*/
+
+bool operator==(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b)
+{
+ return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
+ && a.d->alphaSize == b.d->alphaSize
+ && a.d->accumSize == b.d->accumSize
+ && a.d->stencilSize == b.d->stencilSize
+ && a.d->depthSize == b.d->depthSize
+ && a.d->redSize == b.d->redSize
+ && a.d->greenSize == b.d->greenSize
+ && a.d->blueSize == b.d->blueSize
+ && a.d->numSamples == b.d->numSamples
+ && a.d->swapInterval == b.d->swapInterval
+ && a.d->windowApi == b.d->windowApi);
+}
+
+
+/*!
+ Returns false if all the options of the two QPlatformWindowFormat objects
+ \a a and \a b are equal; otherwise returns true.
+
+ \relates QPlatformWindowFormat
+*/
+
+bool operator!=(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b)
+{
+ return !(a == b);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QPlatformWindowFormat &f)
+{
+ const QPlatformWindowFormatPrivate * const d = f.d;
+
+ dbg.nospace() << "QGLFormat("
+ << "options " << d->opts
+ << ", depthBufferSize " << d->depthSize
+ << ", accumBufferSize " << d->accumSize
+ << ", stencilBufferSize " << d->stencilSize
+ << ", redBufferSize " << d->redSize
+ << ", greenBufferSize " << d->greenSize
+ << ", blueBufferSize " << d->blueSize
+ << ", alphaBufferSize " << d->alphaSize
+ << ", samples " << d->numSamples
+ << ", swapInterval " << d->swapInterval
+ << ')';
+
+ return dbg.space();
+}
+#endif
diff --git a/src/gui/kernel/qplatformwindowformat_qpa.h b/src/gui/kernel/qplatformwindowformat_qpa.h
new file mode 100644
index 0000000000..790385b983
--- /dev/null
+++ b/src/gui/kernel/qplatformwindowformat_qpa.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QPLATFORMWINDOWFORMAT_QPA_H
+#define QPLATFORMWINDOWFORMAT_QPA_H
+
+#include <QtGui/QPlatformWindow>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPlatformWindowFormatPrivate;
+
+class Q_GUI_EXPORT QPlatformWindowFormat
+{
+public:
+ enum FormatOption {
+ DoubleBuffer = 0x0001,
+ DepthBuffer = 0x0002,
+ Rgba = 0x0004,
+ AlphaChannel = 0x0008,
+ AccumBuffer = 0x0010,
+ StencilBuffer = 0x0020,
+ StereoBuffers = 0x0040,
+ DirectRendering = 0x0080,
+ HasOverlay = 0x0100,
+ SampleBuffers = 0x0200,
+ DeprecatedFunctions = 0x0400,
+ UseDefaultSharedContext = 0x0800,
+ HasWindowSurface = 0x1000,
+ SingleBuffer = DoubleBuffer << 16,
+ NoDepthBuffer = DepthBuffer << 16,
+ ColorIndex = Rgba << 16,
+ NoAlphaChannel = AlphaChannel << 16,
+ NoAccumBuffer = AccumBuffer << 16,
+ NoStencilBuffer = StencilBuffer << 16,
+ NoStereoBuffers = StereoBuffers << 16,
+ IndirectRendering = DirectRendering << 16,
+ NoOverlay = HasOverlay << 16,
+ NoSampleBuffers = SampleBuffers << 16,
+ NoDeprecatedFunctions = DeprecatedFunctions << 16,
+ NoDefaultSharedContext = UseDefaultSharedContext << 16,
+ NoWindowSurface = HasWindowSurface << 16
+
+ };
+ Q_DECLARE_FLAGS(FormatOptions, FormatOption)
+
+ enum WindowApi {
+ Raster,
+ OpenGL,
+ OpenVG
+ };
+
+ QPlatformWindowFormat();
+ QPlatformWindowFormat(FormatOptions options);
+ QPlatformWindowFormat(const QPlatformWindowFormat &other);
+ QPlatformWindowFormat &operator=(const QPlatformWindowFormat &other);
+ ~QPlatformWindowFormat();
+
+ void setDepthBufferSize(int size);
+ int depthBufferSize() const;
+
+ void setAccumBufferSize(int size);
+ int accumBufferSize() const;
+
+ void setRedBufferSize(int size);
+ int redBufferSize() const;
+
+ void setGreenBufferSize(int size);
+ int greenBufferSize() const;
+
+ void setBlueBufferSize(int size);
+ int blueBufferSize() const;
+
+ void setAlphaBufferSize(int size);
+ int alphaBufferSize() const;
+
+ void setStencilBufferSize(int size);
+ int stencilBufferSize() const;
+
+ void setSampleBuffers(bool enable);
+ bool sampleBuffers() const;
+
+ void setSamples(int numSamples);
+ int samples() const;
+
+ void setSwapInterval(int interval);
+ int swapInterval() const;
+
+ void setWindowApi(QPlatformWindowFormat::WindowApi api);
+ WindowApi windowApi() const;
+
+ void setSharedContext(QPlatformGLContext *context);
+ QPlatformGLContext *sharedGLContext() const;
+
+ bool doubleBuffer() const;
+ void setDoubleBuffer(bool enable);
+ bool depth() const;
+ void setDepth(bool enable);
+ bool rgba() const;
+ void setRgba(bool enable);
+ bool alpha() const;
+ void setAlpha(bool enable);
+ bool accum() const;
+ void setAccum(bool enable);
+ bool stencil() const;
+ void setStencil(bool enable);
+ bool stereo() const;
+ void setStereo(bool enable);
+ bool directRendering() const;
+ void setDirectRendering(bool enable);
+ bool useDefaultSharedContext() const;
+ void setUseDefaultSharedContext(bool enable);
+ bool hasWindowSurface() const;
+ void setWindowSurface(bool enable);
+
+ void setOption(QPlatformWindowFormat::FormatOptions opt);
+ bool testOption(QPlatformWindowFormat::FormatOptions opt) const;
+
+ static QPlatformWindowFormat defaultFormat();
+ static void setDefaultFormat(const QPlatformWindowFormat& f);
+
+private:
+ QPlatformWindowFormatPrivate *d;
+
+ void detach();
+
+ friend Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&);
+ friend Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&);
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &);
+#endif
+};
+
+Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&);
+Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &);
+#endif
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformWindowFormat::FormatOptions)
+
+inline bool QPlatformWindowFormat::doubleBuffer() const
+{
+ return testOption(QPlatformWindowFormat::DoubleBuffer);
+}
+
+inline bool QPlatformWindowFormat::depth() const
+{
+ return testOption(QPlatformWindowFormat::DepthBuffer);
+}
+
+inline bool QPlatformWindowFormat::rgba() const
+{
+ return testOption(QPlatformWindowFormat::Rgba);
+}
+
+inline bool QPlatformWindowFormat::alpha() const
+{
+ return testOption(QPlatformWindowFormat::AlphaChannel);
+}
+
+inline bool QPlatformWindowFormat::accum() const
+{
+ return testOption(QPlatformWindowFormat::AccumBuffer);
+}
+
+inline bool QPlatformWindowFormat::stencil() const
+{
+ return testOption(QPlatformWindowFormat::StencilBuffer);
+}
+
+inline bool QPlatformWindowFormat::stereo() const
+{
+ return testOption(QPlatformWindowFormat::StereoBuffers);
+}
+
+inline bool QPlatformWindowFormat::directRendering() const
+{
+ return testOption(QPlatformWindowFormat::DirectRendering);
+}
+
+inline bool QPlatformWindowFormat::hasWindowSurface() const
+{
+ return testOption(QPlatformWindowFormat::HasWindowSurface);
+}
+
+inline bool QPlatformWindowFormat::sampleBuffers() const
+{
+ return testOption(QPlatformWindowFormat::SampleBuffers);
+}
+
+inline bool QPlatformWindowFormat::useDefaultSharedContext() const
+{
+ return testOption(QPlatformWindowFormat::UseDefaultSharedContext);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QPLATFORMWINDOWFORMAT_QPA_H
diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h
index 4b5fbdc8d4..c0a8cc1f18 100644
--- a/src/gui/kernel/qsizepolicy.h
+++ b/src/gui/kernel/qsizepolicy.h
@@ -62,12 +62,12 @@ private:
HSize = 4,
HMask = 0x0f,
VMask = HMask << HSize,
- CTShift = 9,
- CTSize = 5,
- WFHShift = CTShift + CTSize,
- CTMask = ((0x1 << CTSize) - 1) << CTShift,
- UnusedShift = CTShift + CTSize,
- UnusedSize = 2
+ CTShift = 9,
+ CTSize = 5,
+ CTMask = ((0x1 << CTSize) - 1) << CTShift,
+ WFHShift = CTShift + CTSize,
+ UnusedShift = WFHShift + 1,
+ UnusedSize = 1
};
public:
@@ -134,6 +134,8 @@ public:
void setHeightForWidth(bool b) { data = b ? (data | (1 << 2*HSize)) : (data & ~(1 << 2*HSize)); }
bool hasHeightForWidth() const { return data & (1 << 2*HSize); }
+ void setWidthForHeight(bool b) { data = b ? (data | (1 << (WFHShift))) : (data & ~(1 << (WFHShift))); }
+ bool hasWidthForHeight() const { return data & (1 << (WFHShift)); }
bool operator==(const QSizePolicy& s) const { return data == s.data; }
bool operator!=(const QSizePolicy& s) const { return data != s.data; }
@@ -200,15 +202,18 @@ private:
QSizePolicy(int i) : data(i) { }
quint32 data;
-/* use bit flags instead, keep it here for improved readability for now
+/* Qt5: Use bit flags instead, keep it here for improved readability for now.
+ We can maybe change it for Qt4, but we'd have to be careful, since the behaviour
+ is implementation defined. It usually varies between little- and big-endian compilers, but
+ it might also not vary.
quint32 horzPolicy : 4;
quint32 vertPolicy : 4;
quint32 hfw : 1;
quint32 ctype : 5;
quint32 wfh : 1;
quint32 padding : 1; // we cannot use the highest bit
- quint32 horStretch : 8;
quint32 verStretch : 8;
+ quint32 horStretch : 8;
*/
};
diff --git a/src/gui/kernel/qsizepolicy.qdoc b/src/gui/kernel/qsizepolicy.qdoc
index 66ae43803e..80e9f20f74 100644
--- a/src/gui/kernel/qsizepolicy.qdoc
+++ b/src/gui/kernel/qsizepolicy.qdoc
@@ -249,7 +249,7 @@
Sets the flag determining whether the widget's preferred height
depends on its width, to \a dependent.
- \sa hasHeightForWidth()
+ \sa hasHeightForWidth(), setWidthForHeight()
*/
/*!
@@ -262,6 +262,28 @@
*/
/*!
+ \fn void QSizePolicy::setWidthForHeight(bool dependent)
+
+ Sets the flag determining whether the widget's width
+ depends on its height, to \a dependent.
+
+ This is only supported for QGraphicsLayout's subclasses.
+ It is not possible to have a layout with both height-for-width
+ and width-for-height constraints at the same time.
+
+ \sa hasWidthForHeight(), setHeightForWidth()
+*/
+
+/*!
+ \fn bool QSizePolicy::hasWidthForHeight() const
+
+ Returns true if the widget's width depends on its
+ height; otherwise returns false.
+
+ \sa setWidthForHeight()
+*/
+
+/*!
\fn bool QSizePolicy::operator==(const QSizePolicy &other) const
Returns true if this policy is equal to \a other; otherwise
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 462b30bc91..3a0cafd90d 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -79,6 +79,7 @@
#include <qdesktopwidget.h>
#include <qevent.h>
#include <qpixmapcache.h>
+#include <qvarlengtharray.h>
#include <private/qevent_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qt_mac_p.h>
@@ -470,7 +471,6 @@ void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec)
qt_sendSpontaneousEvent(qApp, &qtabletProximity);
}
-#ifdef QT_MAC_USE_COCOA
// Use this method to keep all the information in the TextSegment. As long as it is ordered
// we are in OK shape, and we can influence that ourselves.
struct KeyPair
@@ -494,69 +494,107 @@ bool operator<(QChar qchar, const KeyPair &entry)
return qchar < entry.cocoaKey;
}
+bool operator<(const Qt::Key &key, const KeyPair &entry)
+{
+ return key < entry.qtKey;
+}
+
+bool operator<(const KeyPair &entry, const Qt::Key &key)
+{
+ return entry.qtKey < key;
+}
+
+static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2)
+{
+ return entry1.qtKey < entry2.qtKey;
+}
+
+static const int NumEntries = 59;
+static const KeyPair entries[NumEntries] = {
+ { NSEnterCharacter, Qt::Key_Enter },
+ { NSBackspaceCharacter, Qt::Key_Backspace },
+ { NSTabCharacter, Qt::Key_Tab },
+ { NSNewlineCharacter, Qt::Key_Return },
+ { NSCarriageReturnCharacter, Qt::Key_Return },
+ { NSBackTabCharacter, Qt::Key_Backtab },
+ { NSDeleteCharacter, Qt::Key_Delete },
+ { kEscapeCharCode, Qt::Key_Escape },
+ { NSUpArrowFunctionKey, Qt::Key_Up },
+ { NSDownArrowFunctionKey, Qt::Key_Down },
+ { NSLeftArrowFunctionKey, Qt::Key_Left },
+ { NSRightArrowFunctionKey, Qt::Key_Right },
+ { NSF1FunctionKey, Qt::Key_F1 },
+ { NSF2FunctionKey, Qt::Key_F2 },
+ { NSF3FunctionKey, Qt::Key_F3 },
+ { NSF4FunctionKey, Qt::Key_F4 },
+ { NSF5FunctionKey, Qt::Key_F5 },
+ { NSF6FunctionKey, Qt::Key_F6 },
+ { NSF7FunctionKey, Qt::Key_F7 },
+ { NSF8FunctionKey, Qt::Key_F8 },
+ { NSF9FunctionKey, Qt::Key_F8 },
+ { NSF10FunctionKey, Qt::Key_F10 },
+ { NSF11FunctionKey, Qt::Key_F11 },
+ { NSF12FunctionKey, Qt::Key_F12 },
+ { NSF13FunctionKey, Qt::Key_F13 },
+ { NSF14FunctionKey, Qt::Key_F14 },
+ { NSF15FunctionKey, Qt::Key_F15 },
+ { NSF16FunctionKey, Qt::Key_F16 },
+ { NSF17FunctionKey, Qt::Key_F17 },
+ { NSF18FunctionKey, Qt::Key_F18 },
+ { NSF19FunctionKey, Qt::Key_F19 },
+ { NSF20FunctionKey, Qt::Key_F20 },
+ { NSF21FunctionKey, Qt::Key_F21 },
+ { NSF22FunctionKey, Qt::Key_F22 },
+ { NSF23FunctionKey, Qt::Key_F23 },
+ { NSF24FunctionKey, Qt::Key_F24 },
+ { NSF25FunctionKey, Qt::Key_F25 },
+ { NSF26FunctionKey, Qt::Key_F26 },
+ { NSF27FunctionKey, Qt::Key_F27 },
+ { NSF28FunctionKey, Qt::Key_F28 },
+ { NSF29FunctionKey, Qt::Key_F29 },
+ { NSF30FunctionKey, Qt::Key_F30 },
+ { NSF31FunctionKey, Qt::Key_F31 },
+ { NSF32FunctionKey, Qt::Key_F32 },
+ { NSF33FunctionKey, Qt::Key_F33 },
+ { NSF34FunctionKey, Qt::Key_F34 },
+ { NSF35FunctionKey, Qt::Key_F35 },
+ { NSInsertFunctionKey, Qt::Key_Insert },
+ { NSDeleteFunctionKey, Qt::Key_Delete },
+ { NSHomeFunctionKey, Qt::Key_Home },
+ { NSEndFunctionKey, Qt::Key_End },
+ { NSPageUpFunctionKey, Qt::Key_PageUp },
+ { NSPageDownFunctionKey, Qt::Key_PageDown },
+ { NSPrintScreenFunctionKey, Qt::Key_Print },
+ { NSScrollLockFunctionKey, Qt::Key_ScrollLock },
+ { NSPauseFunctionKey, Qt::Key_Pause },
+ { NSSysReqFunctionKey, Qt::Key_SysReq },
+ { NSMenuFunctionKey, Qt::Key_Menu },
+ { NSHelpFunctionKey, Qt::Key_Help },
+};
+static const KeyPair * const end = entries + NumEntries;
+
+QChar qtKey2CocoaKey(Qt::Key key)
+{
+ // The first time this function is called, create a reverse
+ // looup table sorted on Qt Key rather than Cocoa key:
+ static QVector<KeyPair> rev_entries(NumEntries);
+ static bool mustInit = true;
+ if (mustInit){
+ mustInit = false;
+ for (int i=0; i<NumEntries; ++i)
+ rev_entries[i] = entries[i];
+ qSort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan);
+ }
+ const QVector<KeyPair>::iterator i
+ = qBinaryFind(rev_entries.begin(), rev_entries.end(), key);
+ if (i == rev_entries.end())
+ return QChar();
+ return i->cocoaKey;
+}
+
+#ifdef QT_MAC_USE_COCOA
static Qt::Key cocoaKey2QtKey(QChar keyCode)
{
- static const int NumEntries = 57;
- static const KeyPair entries[NumEntries] = {
- { NSEnterCharacter, Qt::Key_Enter },
- { NSTabCharacter, Qt::Key_Tab },
- { NSCarriageReturnCharacter, Qt::Key_Return },
- { NSBackTabCharacter, Qt::Key_Backtab },
- { kEscapeCharCode, Qt::Key_Escape },
- { NSDeleteCharacter, Qt::Key_Backspace },
- { NSUpArrowFunctionKey, Qt::Key_Up },
- { NSDownArrowFunctionKey, Qt::Key_Down },
- { NSLeftArrowFunctionKey, Qt::Key_Left },
- { NSRightArrowFunctionKey, Qt::Key_Right },
- { NSF1FunctionKey, Qt::Key_F1 },
- { NSF2FunctionKey, Qt::Key_F2 },
- { NSF3FunctionKey, Qt::Key_F3 },
- { NSF4FunctionKey, Qt::Key_F4 },
- { NSF5FunctionKey, Qt::Key_F5 },
- { NSF6FunctionKey, Qt::Key_F6 },
- { NSF7FunctionKey, Qt::Key_F7 },
- { NSF8FunctionKey, Qt::Key_F8 },
- { NSF9FunctionKey, Qt::Key_F8 },
- { NSF10FunctionKey, Qt::Key_F10 },
- { NSF11FunctionKey, Qt::Key_F11 },
- { NSF12FunctionKey, Qt::Key_F12 },
- { NSF13FunctionKey, Qt::Key_F13 },
- { NSF14FunctionKey, Qt::Key_F14 },
- { NSF15FunctionKey, Qt::Key_F15 },
- { NSF16FunctionKey, Qt::Key_F16 },
- { NSF17FunctionKey, Qt::Key_F17 },
- { NSF18FunctionKey, Qt::Key_F18 },
- { NSF19FunctionKey, Qt::Key_F19 },
- { NSF20FunctionKey, Qt::Key_F20 },
- { NSF21FunctionKey, Qt::Key_F21 },
- { NSF22FunctionKey, Qt::Key_F22 },
- { NSF23FunctionKey, Qt::Key_F23 },
- { NSF24FunctionKey, Qt::Key_F24 },
- { NSF25FunctionKey, Qt::Key_F25 },
- { NSF26FunctionKey, Qt::Key_F26 },
- { NSF27FunctionKey, Qt::Key_F27 },
- { NSF28FunctionKey, Qt::Key_F28 },
- { NSF29FunctionKey, Qt::Key_F29 },
- { NSF30FunctionKey, Qt::Key_F30 },
- { NSF31FunctionKey, Qt::Key_F31 },
- { NSF32FunctionKey, Qt::Key_F32 },
- { NSF33FunctionKey, Qt::Key_F33 },
- { NSF34FunctionKey, Qt::Key_F34 },
- { NSF35FunctionKey, Qt::Key_F35 },
- { NSInsertFunctionKey, Qt::Key_Insert },
- { NSDeleteFunctionKey, Qt::Key_Delete },
- { NSHomeFunctionKey, Qt::Key_Home },
- { NSEndFunctionKey, Qt::Key_End },
- { NSPageUpFunctionKey, Qt::Key_PageUp },
- { NSPageDownFunctionKey, Qt::Key_PageDown },
- { NSPrintScreenFunctionKey, Qt::Key_Print },
- { NSScrollLockFunctionKey, Qt::Key_ScrollLock },
- { NSPauseFunctionKey, Qt::Key_Pause },
- { NSSysReqFunctionKey, Qt::Key_SysReq },
- { NSMenuFunctionKey, Qt::Key_Menu },
- { NSHelpFunctionKey, Qt::Key_Help },
- };
- static const KeyPair * const end = entries + NumEntries;
const KeyPair *i = qBinaryFind(entries, end, keyCode);
if (i == end)
return Qt::Key(keyCode.unicode());
@@ -579,6 +617,27 @@ Qt::KeyboardModifiers qt_cocoaModifiers2QtModifiers(ulong modifierFlags)
return qtMods;
}
+NSString *qt_mac_removePrivateUnicode(NSString* string)
+{
+ int len = [string length];
+ if (len) {
+ QVarLengthArray <unichar, 10> characters(len);
+ bool changed = false;
+ for (int i = 0; i<len; i++) {
+ characters[i] = [string characterAtIndex:i];
+ // check if they belong to key codes in private unicode range
+ // currently we need to handle only the NSDeleteFunctionKey
+ if (characters[i] == NSDeleteFunctionKey) {
+ characters[i] = NSDeleteCharacter;
+ changed = true;
+ }
+ }
+ if (changed)
+ return [NSString stringWithCharacters:characters.data() length:len];
+ }
+ return string;
+}
+
Qt::KeyboardModifiers qt_cocoaDragOperation2QtModifiers(uint dragOperations)
{
Qt::KeyboardModifiers qtMods =Qt::NoModifier;
@@ -1205,7 +1264,7 @@ void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widge
// We have the original method here. Proceed and swap the methods.
method_exchangeImplementations(m1, m0);
widget->originalDrawMethod = false;
- [window display];
+ [theWindow display];
}
}
@@ -1228,7 +1287,7 @@ void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivat
}
method_exchangeImplementations(m1, m0);
widget->originalDrawMethod = true;
- [window display];
+ [theWindow display];
}
#endif // QT_MAC_USE_COCOA
@@ -1298,7 +1357,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
CGrafPtr port = GetWindowPort(qt_mac_window_for(widget));
QDBeginCGContext(port, &context);
#else
- CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]);
+ CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort];
#endif
return context;
}
@@ -1328,11 +1387,11 @@ QString qt_mac_get_pasteboardString(OSPasteboardRef paste)
QMacCocoaAutoReleasePool pool;
NSPasteboard *pb = nil;
CFStringRef pbname;
- if (PasteboardCopyName (paste, &pbname)) {
- pb = [NSPasteboard generalPasteboard];
+ if (PasteboardCopyName(paste, &pbname) == noErr) {
+ pb = [NSPasteboard pasteboardWithName:const_cast<NSString *>(reinterpret_cast<const NSString *>(pbname))];
+ CFRelease(pbname);
} else {
- pb = [NSPasteboard pasteboardWithName:reinterpret_cast<const NSString *>(pbname)];
- CFRelease (pbname);
+ pb = [NSPasteboard generalPasteboard];
}
if (pb) {
NSString *text = [pb stringForType:NSStringPboardType];
@@ -1427,39 +1486,17 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor)
[static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set];
}
-// WARNING: If Qt did not create NSApplication (e.g. in case it is
-// used as a plugin), and at the same time, there is no window on
-// screen (or the window that the event is sendt to becomes hidden etc
-// before the event gets delivered), the message will not be performed.
-bool qt_cocoaPostMessage(id target, SEL selector)
+void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2)
{
- if (!target)
- return false;
-
- NSInteger windowNumber = 0;
- if (![NSApp isMemberOfClass:[QNSApplication class]]) {
- // INVARIANT: Cocoa is not using our NSApplication subclass. That means
- // we don't control the main event handler either. So target the event
- // for one of the windows on screen:
- NSWindow *nswin = [NSApp mainWindow];
- if (!nswin) {
- nswin = [NSApp keyWindow];
- if (!nswin)
- return false;
- }
- windowNumber = [nswin windowNumber];
- }
-
- // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5!
+ // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5!
// That is why we need to split the address in two parts:
- QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector);
+ QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector, argCount, arg1, arg2);
quint32 lower = quintptr(args);
quint32 upper = quintptr(args) >> 32;
NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined
- location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber
+ location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0
context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper];
[NSApp postEvent:e atStart:NO];
- return true;
}
#endif
@@ -1498,7 +1535,7 @@ void macDrawRectOnTop(void * /*OSWindowRef */window)
NSRect contentRect = [contentView frame];
// Draw a line on top of the already drawn line.
// We need to check if we are active or not to use the proper color.
- if([window isKeyWindow] || [window isMainWindow]) {
+ if([theWindow isKeyWindow] || [theWindow isMainWindow]) {
[[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set];
} else {
[[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set];
@@ -1518,7 +1555,7 @@ void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window)
{
OSWindowRef theWindow = static_cast<OSWindowRef>(window);
NSApplication *application = [NSApplication sharedApplication];
- NSToolbar *toolbar = [window toolbar];
+ NSToolbar *toolbar = [theWindow toolbar];
if([application isActive]) {
// Launched from finder
[toolbar setShowsBaselineSeparator:NO];
@@ -1546,6 +1583,13 @@ void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *childWidget)
}
}
+void qt_mac_display(QWidget *widget)
+{
+ NSView *theNSView = qt_mac_nativeview_for(widget);
+ [theNSView display];
+ return;
+}
+
#endif // QT_MAC_USE_COCOA
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
index d5f4b2be3a..d61c00f70f 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h
+++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h
@@ -202,23 +202,33 @@ class QCocoaPostMessageArgs {
public:
id target;
SEL selector;
- QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector)
+ int argCount;
+ id arg1;
+ id arg2;
+ QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0)
+ : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2)
{
[target retain];
+ [arg1 retain];
+ [arg2 retain];
}
~QCocoaPostMessageArgs()
{
+ [arg2 release];
+ [arg1 release];
[target release];
}
};
-bool qt_cocoaPostMessage(id target, SEL selector);
+void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0);
#endif
#endif
void qt_mac_post_retranslateAppMenu();
+void qt_mac_display(QWidget *widget);
+
QT_END_NAMESPACE
#endif // QT_COCOA_HELPERS_MAC_P_H
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 8ab129c173..69079cfaad 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -226,6 +226,7 @@ typedef void (*PtrXRRSelectInput)(Display *, Window, int);
typedef int (*PtrXRRUpdateConfiguration)(XEvent *);
typedef int (*PtrXRRRootToScreen)(Display *, Window);
typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *);
+typedef XRRScreenSize *(*PtrXRRSizes)(Display *, int, int *);
#endif // QT_NO_XRANDR
#ifndef QT_NO_XINPUT
@@ -710,6 +711,7 @@ struct QX11Data
PtrXRRUpdateConfiguration ptrXRRUpdateConfiguration;
PtrXRRRootToScreen ptrXRRRootToScreen;
PtrXRRQueryExtension ptrXRRQueryExtension;
+ PtrXRRSizes ptrXRRSizes;
#endif // QT_NO_XRANDR
};
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
index dff5e5cd95..4311df58a6 100644
--- a/src/gui/kernel/qtooltip.cpp
+++ b/src/gui/kernel/qtooltip.cpp
@@ -353,7 +353,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
#ifndef QT_NO_STYLE_STYLESHEET
if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) {
//the stylesheet need to know the real parent
- QTipLabel::instance->setProperty("_q_stylesheet_parent", qVariantFromValue(w));
+ QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w));
//we force the style to be the QStyleSheetStyle, and force to clear the cache as well.
QTipLabel::instance->setStyleSheet(QLatin1String("/* */"));
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 9a76b0a0e5..f35afb0ef1 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -76,6 +76,9 @@
# include "qpaintengine.h" // for PorterDuff
# include "private/qwindowsurface_qws_p.h"
#endif
+#if defined(Q_WS_QPA)
+#include "qplatformwindow_qpa.h"
+#endif
#include "qpainter.h"
#include "qtooltip.h"
#include "qwhatsthis.h"
@@ -300,6 +303,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
, hasAlienChildren(0)
, window_event(0)
, qd_hd(0)
+#elif defined (Q_WS_QPA)
+ , screenNumber(0)
#endif
{
if (!qApp) {
@@ -316,6 +321,9 @@ QWidgetPrivate::QWidgetPrivate(int version)
drawRectOriginalAdded = false;
originalDrawMethod = true;
changeMethods = false;
+ hasOwnContext = false;
+ isInUnifiedToolbar = false;
+ unifiedSurface = 0;
#endif // QT_MAC_USE_COCOA
#ifdef QWIDGET_EXTRA_DEBUG
static int count = 0;
@@ -1267,6 +1275,12 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
// programmer specified desktop widget
xinfo = desktopWidget->d_func()->xinfo;
}
+#elif defined(Q_WS_QPA)
+ if (desktopWidget) {
+ int screen = desktopWidget->d_func()->screenNumber;
+ QPlatformIntegration *platform = QApplicationPrivate::platformIntegration();
+ platform->moveToScreen(q, screen);
+ }
#else
Q_UNUSED(desktopWidget);
#endif
@@ -1398,6 +1412,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
flags |= Qt::Window;
}
+#ifndef Q_WS_QPA
if (QWidget *parent = parentWidget()) {
#ifdef Q_WS_MAC
if (testAttribute(Qt::WA_NativeWindow) == false)
@@ -1418,6 +1433,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
return;
}
}
+#endif //Q_WS_QPA
#ifdef QT3_SUPPORT
if (flags & Qt::WStaticContents)
@@ -1576,13 +1592,13 @@ QWidget::~QWidget()
}
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)|| defined(Q_WS_MAC)
else if (!internalWinId() && isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
-#ifdef Q_WS_QWS
- } else if (isVisible()) {
+ }
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ else if (isVisible()) {
qApp->d_func()->sendSyntheticEnterLeave(this);
-#endif
}
#endif
@@ -1607,7 +1623,8 @@ QWidget::~QWidget()
d->needsFlush = 0;
// set all QPointers for this object to zero
- QObjectPrivate::clearGuards(this);
+ if (d->hasGuards)
+ QObjectPrivate::clearGuards(this);
if (d->declarativeData) {
QAbstractDeclarativeData::destroyed(d->declarativeData, this);
@@ -1709,6 +1726,10 @@ void QWidgetPrivate::createTLExtra()
static int count = 0;
qDebug() << "tlextra" << ++count;
#endif
+#if defined(Q_WS_QPA)
+ x->platformWindow = 0;
+ x->platformWindowFormat = QPlatformWindowFormat::defaultFormat();
+#endif
}
}
@@ -1830,13 +1851,7 @@ void QWidgetPrivate::syncBackingStore()
repaint_sys(dirty);
dirty = QRegion();
} else if (QWidgetBackingStore *bs = maybeBackingStore()) {
-#ifdef QT_MAC_USE_COCOA
- Q_UNUSED(bs);
- void qt_mac_set_needs_display(QWidget *, QRegion);
- qt_mac_set_needs_display(q_func(), QRegion());
-#else
bs->sync();
-#endif
}
}
@@ -1845,13 +1860,7 @@ void QWidgetPrivate::syncBackingStore(const QRegion &region)
if (paintOnScreen())
repaint_sys(region);
else if (QWidgetBackingStore *bs = maybeBackingStore()) {
-#ifdef QT_MAC_USE_COCOA
- Q_UNUSED(bs);
- void qt_mac_set_needs_display(QWidget *, QRegion);
- qt_mac_set_needs_display(q_func(), region);
-#else
bs->sync(q_func(), region);
-#endif
}
}
@@ -2455,7 +2464,9 @@ WId QWidget::winId() const
qDebug() << "QWidget::winId: creating native window for" << this;
#endif
QWidget *that = const_cast<QWidget*>(this);
+#ifndef Q_WS_QPA
that->setAttribute(Qt::WA_NativeWindow);
+#endif
that->d_func()->createWinId();
return that->data->winid;
}
@@ -2472,6 +2483,7 @@ void QWidgetPrivate::createWinId(WId winid)
#endif
const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
+#ifndef Q_WS_QPA
if (!q->isWindow()) {
QWidget *parent = q->parentWidget();
QWidgetPrivate *pd = parent->d_func();
@@ -2499,6 +2511,11 @@ void QWidgetPrivate::createWinId(WId winid)
} else {
q->create();
}
+#else
+ Q_UNUSED(winid);
+ q->create();
+#endif //Q_WS_QPA
+
}
}
@@ -5382,6 +5399,14 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (rgn.isEmpty())
return;
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // We disable the rendering of QToolBar in the backingStore if
+ // it's supposed to be in the unified toolbar on Mac OS X.
+ if (backingStore && isInUnifiedToolbar)
+ return;
+#endif // Q_WS_MAC && QT_MAC_USE_COCOA
+
+
Q_Q(QWidget);
#ifndef QT_NO_GRAPHICSEFFECT
if (graphicsEffect && graphicsEffect->isEnabled()) {
@@ -5444,6 +5469,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QPaintEngine *paintEngine = pdev->paintEngine();
if (paintEngine) {
setRedirected(pdev, -offset);
+
#ifdef Q_WS_MAC
// (Alien support) Special case for Mac when redirecting: If the paint device
// is of the Widget type we need to set WA_WState_InPaintEvent since painting
@@ -5486,7 +5512,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//actually send the paint event
QPaintEvent e(toBePainted);
QCoreApplication::sendSpontaneousEvent(q, &e);
-#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS)
+#if !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
backingStore->markDirtyOnScreen(toBePainted, q, offset);
#endif
@@ -6633,7 +6659,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
// that can take keyboard focus so that second is inserted after
// that last child, and the focus order within first is (more
// likely to be) preserved.
- QList<QWidget *> l = qFindChildren<QWidget *>(first);
+ QList<QWidget *> l = first->findChildren<QWidget *>();
for (int i = l.size()-1; i >= 0; --i) {
QWidget * next = l.at(i);
if (next->window() == fp->window()) {
@@ -7022,7 +7048,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
if (maximized || fullScreen) {
// set geomerty before setting the window state to make
// sure the window is maximized to the right screen.
+ // Skip on windows: the window is restored into a broken
+ // half-maximized state.
+#ifndef Q_WS_WIN
setGeometry(restoredNormalGeometry);
+#endif
Qt::WindowStates ws = windowState();
if (maximized)
ws |= Qt::WindowMaximized;
@@ -7524,7 +7554,7 @@ void QWidgetPrivate::hide_helper()
// next bit tries to move the focus if the focus widget is now
// hidden.
if (wasVisible) {
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(q);
#endif
@@ -7656,7 +7686,7 @@ void QWidget::setVisible(bool visible)
d->show_helper();
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(this);
#endif
}
@@ -7788,7 +7818,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
widget->d_func()->hide_sys();
}
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA)
qApp->d_func()->sendSyntheticEnterLeave(widget);
#endif
#ifndef QT_NO_ACCESSIBILITY
@@ -9797,6 +9827,23 @@ int QWidget::heightForWidth(int w) const
return -1;
}
+
+/*!
+ \internal
+
+ *virtual private*
+
+ This is a bit hackish, but ideally we would have created a virtual function
+ in the public API (however, too late...) so that subclasses could reimplement
+ their own function.
+ Instead we add a virtual function to QWidgetPrivate.
+ ### Qt5: move to public class and make virtual
+*/
+bool QWidgetPrivate::hasHeightForWidth() const
+{
+ return layout ? layout->hasHeightForWidth() : size_policy.hasHeightForWidth();
+}
+
/*!
\fn QWidget *QWidget::childAt(int x, int y) const
@@ -10549,7 +10596,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
Q_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8),
"QWidget::setAttribute(WidgetAttribute, bool)",
"QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
-
#ifdef Q_WS_WIN
// ### Don't use PaintOnScreen+paintEngine() to do native painting in 5.0
if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) {
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index d08c58c86c..7d4726ed6d 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -56,6 +56,10 @@
#include <QtGui/qcursor.h>
#include <QtGui/qkeysequence.h>
+#ifdef Q_WS_QPA //should this go somewhere else?
+#include <QtGui/qplatformwindowformat_qpa.h>
+#endif
+
#ifdef QT_INCLUDE_COMPAT
#include <QtGui/qevent.h>
#endif
@@ -94,9 +98,12 @@ class QHideEvent;
class QInputContext;
class QIcon;
class QWindowSurface;
+class QPlatformWindow;
class QLocale;
class QGraphicsProxyWidget;
class QGraphicsEffect;
+class QRasterWindowSurface;
+class QUnifiedToolbarSurface;
#if defined(Q_WS_X11)
class QX11Info;
#endif
@@ -627,6 +634,16 @@ public:
void setWindowSurface(QWindowSurface *surface);
QWindowSurface *windowSurface() const;
+#if defined(Q_WS_QPA)
+ void setPlatformWindow(QPlatformWindow *window);
+ QPlatformWindow *platformWindow() const;
+
+ void setPlatformWindowFormat(const QPlatformWindowFormat &format);
+ QPlatformWindowFormat platformWindowFormat() const;
+
+ friend class QDesktopScreenWidget;
+#endif
+
Q_SIGNALS:
void customContextMenuRequested(const QPoint &pos);
@@ -758,6 +775,8 @@ private:
friend OSViewRef qt_mac_nativeview_for(const QWidget *w);
friend void qt_event_request_window_change(QWidget *widget);
friend bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref);
+ friend class QRasterWindowSurface;
+ friend class QUnifiedToolbarSurface;
#endif
#ifdef Q_WS_QWS
friend class QWSBackingStore;
@@ -898,13 +917,6 @@ protected:
Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags)
-#if defined Q_CC_MSVC && _MSC_VER < 1300
-template <> inline QWidget *qobject_cast_helper<QWidget*>(QObject *o, QWidget *)
-{
- if (!o || !o->isWidgetType()) return 0;
- return (QWidget*)(o);
-}
-#else
template <> inline QWidget *qobject_cast<QWidget*>(QObject *o)
{
if (!o || !o->isWidgetType()) return 0;
@@ -915,7 +927,6 @@ template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o)
if (!o || !o->isWidgetType()) return 0;
return static_cast<const QWidget*>(o);
}
-#endif
inline QWidget *QWidget::childAt(int ax, int ay) const
{ return childAt(QPoint(ax, ay)); }
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 7e5173ffb4..376999e41b 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -226,6 +226,8 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget)
for (NSWindow *window in windows) {
NSArray *drawers = [window drawers];
for (NSDrawer *drawer in drawers) {
+ if ([drawer contentView] == widgetView)
+ return drawer;
NSArray *views = [[drawer contentView] subviews];
for (NSView *view in views) {
if (view == widgetView)
@@ -240,6 +242,9 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget)
static void qt_mac_destructView(OSViewRef view)
{
#ifdef QT_MAC_USE_COCOA
+ NSWindow *window = [view window];
+ if ([window contentView] == view)
+ [window setContentView:[[NSView alloc] initWithFrame:[view bounds]]];
[view removeFromSuperview];
[view release];
#else
@@ -2289,33 +2294,31 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin
} else {
[windowRef setHidesOnDeactivate:NO];
}
- [windowRef setHasShadow:YES];
+ if (q->testAttribute(Qt::WA_MacNoShadow))
+ [windowRef setHasShadow:NO];
+ else
+ [windowRef setHasShadow:YES];
Q_UNUSED(parentWidget);
Q_UNUSED(dialog);
data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty
+
OSViewRef nsview = (OSViewRef)data.winid;
- OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef);
if (!nsview) {
- nsview = qt_mac_create_widget(q, this, window_contentview);
+ nsview = qt_mac_create_widget(q, this, 0);
setWinId(WId(nsview));
- } else {
- [window_contentview addSubview:nsview];
}
- if (nsview) {
- NSRect bounds = [window_contentview bounds];
- [nsview setFrame:bounds];
- [nsview setHidden:NO];
- if (q->testAttribute(Qt::WA_DropSiteRegistered))
- registerDropSite(true);
- transferChildren();
+ [windowRef setContentView:nsview];
+ [nsview setHidden:NO];
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ registerDropSite(true);
+ transferChildren();
- // Tell Cocoa explicit that we wan't the view to receive key events
- // (regardless of focus policy) because this is how it works on other
- // platforms (and in the carbon port):
- if (!qApp->focusWidget())
- [windowRef makeFirstResponder:nsview];
- }
+ // Tell Cocoa explicit that we wan't the view to receive key events
+ // (regardless of focus policy) because this is how it works on other
+ // platforms (and in the carbon port):
+ if (!qApp->focusWidget())
+ [windowRef makeFirstResponder:nsview];
if (topExtra->posFromMove) {
updateFrameStrut();
@@ -2939,7 +2942,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
// unless this is an alien widget. )
const bool nonWindowWithCreatedParent = !q->isWindow() && parent->testAttribute(Qt::WA_WState_Created);
const bool nativeWidget = q->internalWinId() != 0;
- if (wasCreated || nativeWidget && nonWindowWithCreatedParent) {
+ if (wasCreated || (nativeWidget && nonWindowWithCreatedParent)) {
createWinId();
if (q->isWindow()) {
#ifndef QT_MAC_USE_COCOA
@@ -3206,7 +3209,7 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
if (iconButton == nil) {
QCFString string(q->windowTitle());
const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
- [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:tmpString]];
+ [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:const_cast<NSString *>(tmpString)]];
iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton];
}
if (icon.isNull()) {
@@ -4221,6 +4224,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
}
}
+#ifndef QT_MAC_USE_COCOA
const QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
if (!validRange.contains(xrect)) {
// we are too big, and must clip
@@ -4239,6 +4243,7 @@ void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
wrect = xrect;
wrect.translate(-data.crect.topLeft()); // translate wrect in my Qt coordinates
}
+#endif //QT_MAC_USE_COCOA
}
// unmap if we are outside the valid window system coord system
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 693984a52d..e37e06db89 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -102,6 +102,9 @@ class QWSManager;
#if defined(Q_WS_MAC)
class QCoreGraphicsPaintEnginePrivate;
#endif
+#if defined(Q_WS_QPA)
+class QPlatformWindow;
+#endif
class QPaintEngine;
class QPixmap;
class QWidgetBackingStore;
@@ -227,6 +230,9 @@ struct QTLWExtra {
#elif defined(Q_OS_SYMBIAN)
uint inExpose : 1; // Prevents drawing recursion
uint nativeWindowTransparencyEnabled : 1; // Tracks native window transparency
+#elif defined(Q_WS_QPA)
+ QPlatformWindow *platformWindow;
+ QPlatformWindowFormat platformWindowFormat;
#endif
};
@@ -544,6 +550,7 @@ public:
bool setMinimumSize_helper(int &minw, int &minh);
bool setMaximumSize_helper(int &maxw, int &maxh);
+ virtual bool hasHeightForWidth() const;
void setConstraints_sys();
bool pointInsideRectAndMask(const QPoint &) const;
QWidget *childAt_helper(const QPoint &, bool) const;
@@ -844,6 +851,13 @@ public:
bool originalDrawMethod;
// Do we need to change the methods?
bool changeMethods;
+ bool hasOwnContext;
+ CGContextRef cgContext;
+ QRegion ut_rg;
+ QPoint ut_pt;
+ bool isInUnifiedToolbar;
+ QWindowSurface *unifiedSurface;
+ QPoint toolbar_offset;
#endif
void determineWindowClass();
void transferChildren();
@@ -871,6 +885,14 @@ public:
void updateCursor() const;
#endif
QScreen* getScreen() const;
+#elif defined(Q_WS_QPA)
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+
+ int screenNumber; // screen the widget should be displayed on
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
+#endif
#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
static QWidget *mouseGrabber;
static QWidget *keyboardGrabber;
diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp
new file mode 100644
index 0000000000..617d984bbd
--- /dev/null
+++ b/src/gui/kernel/qwidget_qpa.cpp
@@ -0,0 +1,909 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "QtGui/qwidget.h"
+#include "QtGui/qevent.h"
+#include "QtGui/qapplication.h"
+#include "QtGui/private/qbackingstore_p.h"
+#include "QtGui/private/qwidget_p.h"
+#include "QtGui/private/qgraphicssystem_p.h"
+#include "QtGui/private/qapplication_p.h"
+#include "QtGui/qdesktopwidget.h"
+#include "QtGui/qplatformwindow_qpa.h"
+#include "QtGui/qplatformglcontext_qpa.h"
+
+#include <QtGui/QPlatformCursor>
+
+QT_BEGIN_NAMESPACE
+static QPlatformScreen *qt_screenForWidget(const QWidget *w);
+
+void q_createNativeChildrenAndSetParent(QPlatformWindow *parentWindow, const QWidget *parentWidget)
+{
+ QObjectList children = parentWidget->children();
+ for (int i = 0; i < children.size(); i++) {
+ if (children.at(i)->isWidgetType()) {
+ const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
+ if (childWidget) { // should not be necessary
+ if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
+ if (!childWidget->platformWindow())
+ childWidget->winId();
+ }
+ if (childWidget->platformWindow()) {
+ childWidget->platformWindow()->setParent(parentWindow);
+ } else {
+ q_createNativeChildrenAndSetParent(parentWindow,childWidget);
+ }
+ }
+ }
+ }
+
+}
+
+void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+
+ Q_UNUSED(window);
+ Q_UNUSED(initializeWindow);
+ Q_UNUSED(destroyOldWindow);
+
+ Qt::WindowFlags flags = data.window_flags;
+
+ if ((!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) || q->windowType() == Qt::Desktop )
+ return; // we only care about real toplevels
+
+ QWindowSurface *surface = q->windowSurface();
+ QPlatformWindow *platformWindow = q->platformWindow();
+
+ if (!platformWindow) {
+ platformWindow = QApplicationPrivate::platformIntegration()->createPlatformWindow(q);
+ }
+ Q_ASSERT(platformWindow);
+
+ if (!surface ) {
+ if (platformWindow && q->platformWindowFormat().hasWindowSurface()) {
+ surface = QApplicationPrivate::platformIntegration()->createWindowSurface(q,platformWindow->winId());
+ } else {
+ q->setAttribute(Qt::WA_PaintOnScreen,true);
+ }
+ }
+
+ data.window_flags = q->platformWindow()->setWindowFlags(data.window_flags);
+
+ setWinId(q->platformWindow()->winId());
+
+ //first check children. and create them if necessary
+ q_createNativeChildrenAndSetParent(q->platformWindow(),q);
+
+ //if we we have a parent, then set correct parent;
+ if (!q->isWindow()) {
+ if (QWidget *nativeParent = q->nativeParentWidget()) {
+ if (nativeParent->platformWindow()) {
+ platformWindow->setParent(nativeParent->platformWindow());
+ }
+ }
+ }
+
+ QApplicationPrivate::platformIntegration()->moveToScreen(q, screenNumber);
+// qDebug() << "create_sys" << q << q->internalWinId();
+}
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+
+ if ((windowType() == Qt::Popup))
+ qApp->d_func()->closePopup(this);
+
+ //### we don't have proper focus event handling yet
+ if (this == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+
+ if (windowType() != Qt::Desktop) {
+ if (destroySubWindows) {
+ QObjectList childList(children());
+ for (int i = 0; i < childList.size(); i++) {
+ QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
+ if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
+ if (widget->platformWindow()) {
+ widget->destroy();
+ }
+ }
+ }
+ }
+ if (destroyWindow) {
+ d->deleteTLSysExtra();
+ } else {
+ if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
+ d->hide_sys();
+ }
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+
+ // QWidget *oldParent = q->parentWidget();
+ Qt::WindowFlags oldFlags = data.window_flags;
+
+ int targetScreen = -1;
+ // Handle a request to move the widget to a particular screen
+ if (newparent && newparent->windowType() == Qt::Desktop) {
+ // make sure the widget is created on the same screen as the
+ // programmer specified desktop widget
+
+ // get the desktop's screen number
+ targetScreen = newparent->d_func()->screenNumber;
+ newparent = 0;
+ }
+
+ if (parent != newparent) {
+ QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
+ if (q->platformWindow() && newparent) {
+ QWidget * parentWithWindow = newparent->platformWindow()? newparent : newparent->nativeParentWidget();
+ if (parentWithWindow && parentWithWindow->platformWindow()) {
+ q->platformWindow()->setParent(parentWithWindow->platformWindow());
+ }
+ }
+
+ }
+
+ if (!newparent) {
+ f |= Qt::Window;
+ if (targetScreen == -1) {
+ if (parent)
+ targetScreen = qobject_cast<QWidget *>(parent)->d_func()->screenNumber;
+ }
+ }
+
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ // Reparenting toplevel to child
+ if (!(f&Qt::Window) && (oldFlags&Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
+ //qDebug() << "setParent_sys() change from toplevel";
+ q->destroy();
+ }
+
+ data.window_flags = f;
+ q->setAttribute(Qt::WA_WState_Created, false);
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ q->setAttribute(Qt::WA_WState_Hidden, false);
+
+ if (f & Qt::Window) {
+ //qDebug() << "setParent_sys" << q << newparent << hex << f;
+ if (QPlatformWindow *window = q->platformWindow())
+ data.window_flags = window->setWindowFlags(data.window_flags);
+ }
+
+ // Reparenting child to toplevel
+ if ((f&Qt::Window) && !(oldFlags&Qt::Window)) {
+ //qDebug() << "setParent_sys() change to toplevel";
+ q->create(); //### too early: this ought to happen at show() time
+ }
+
+
+ if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ // move the window to the selected screen
+ if (!newparent && targetScreen != -1) {
+ screenNumber = targetScreen;
+ // only if it is already created
+ if (q->testAttribute(Qt::WA_WState_Created)) {
+ QPlatformIntegration *platform = QApplicationPrivate::platformIntegration();
+ platform->moveToScreen(q, targetScreen);
+ }
+ }
+}
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x += w->data->crect.x();
+ y += w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ int x=pos.x(), y=pos.y();
+ const QWidget* w = this;
+ while (w) {
+ x -= w->data->crect.x();
+ y -= w->data->crect.y();
+ w = w->isWindow() ? 0 : w->parentWidget();
+ }
+ return QPoint(x, y);
+}
+
+void QWidgetPrivate::updateSystemBackground() {}
+
+#ifndef QT_NO_CURSOR
+void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+ Q_Q(QWidget);
+ if (q->isVisible())
+ qt_qpa_set_cursor(q, false);
+}
+
+void QWidgetPrivate::unsetCursor_sys()
+{
+ Q_Q(QWidget);
+ if (q->isVisible())
+ qt_qpa_set_cursor(q, false);
+}
+
+void QWidgetPrivate::updateCursor() const
+{
+ // XXX
+}
+
+#endif //QT_NO_CURSOR
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+ Q_Q(QWidget);
+ if (!q->isWindow())
+ return;
+
+ if (QPlatformWindow *window = q->platformWindow())
+ window->setWindowTitle(caption);
+
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/)
+{
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
+{
+ Q_UNUSED(iconText);
+}
+
+QWidget *qt_pressGrab = 0;
+QWidget *qt_mouseGrb = 0;
+static QWidget *keyboardGrb = 0;
+
+void QWidget::grabMouse()
+{
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ // XXX
+ //qwsDisplay()->grabMouse(this,true);
+
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+
+#ifndef QT_NO_CURSOR
+void QWidget::grabMouse(const QCursor &cursor)
+{
+ Q_UNUSED(cursor);
+
+ if (qt_mouseGrb)
+ qt_mouseGrb->releaseMouse();
+
+ // XXX
+ //qwsDisplay()->grabMouse(this,true);
+ //qwsDisplay()->selectCursor(this, cursor.handle());
+ qt_mouseGrb = this;
+ qt_pressGrab = 0;
+}
+#endif
+
+void QWidget::releaseMouse()
+{
+ if (qt_mouseGrb == this) {
+ // XXX
+ //qwsDisplay()->grabMouse(this,false);
+ qt_mouseGrb = 0;
+ }
+}
+
+void QWidget::grabKeyboard()
+{
+ if (keyboardGrb)
+ keyboardGrb->releaseKeyboard();
+ // XXX
+ //qwsDisplay()->grabKeyboard(this, true);
+ keyboardGrb = this;
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (keyboardGrb == this) {
+ // XXX
+ //qwsDisplay()->grabKeyboard(this, false);
+ keyboardGrb = 0;
+ }
+}
+
+QWidget *QWidget::mouseGrabber()
+{
+ if (qt_mouseGrb)
+ return qt_mouseGrb;
+ return qt_pressGrab;
+}
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return keyboardGrb;
+}
+
+void QWidget::activateWindow()
+{
+ // XXX
+// qDebug() << "QWidget::activateWindow" << this;
+ QApplication::setActiveWindow(this); //#####
+}
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
+
+ QPlatformWindow *window = q->platformWindow();
+ if (window) {
+ const QRect geomRect = q->geometry();
+ const QRect windowRect = window->geometry();
+ if (windowRect != geomRect) {
+ window->setGeometry(geomRect);
+ }
+ if (QWindowSurface *surface = q->windowSurface()) {
+ if (windowRect.size() != geomRect.size()) {
+ surface->resize(geomRect.size());
+ }
+ }
+ if (window)
+ window->setVisible(true);
+
+ if (q->isWindow() && q->windowType() != Qt::Popup && q->windowType() != Qt::ToolTip && !(q->windowFlags() & Qt::X11BypassWindowManagerHint))
+ q->activateWindow(); //### QWindowSystemInterface should have callback function for when WS actually activates window.
+ }
+}
+
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ q->setAttribute(Qt::WA_Mapped, false);
+ if (!q->isWindow()) {
+ QWidget *p = q->parentWidget();
+ if (p &&p->isVisible()) {
+ invalidateBuffer(q->rect());
+ }
+ return;
+ }
+ if (QPlatformWindow *window = q->platformWindow()) {
+ window->setVisible(false);
+ }
+
+ //### we don't yet have proper focus event handling
+ if (q == QApplicationPrivate::active_window)
+ QApplication::setActiveWindow(0);
+
+}
+
+void QWidgetPrivate::setMaxWindowState_helper()
+{
+ setFullScreenSize_helper(); //### decoration size
+}
+
+void QWidgetPrivate::setFullScreenSize_helper()
+{
+ Q_Q(QWidget);
+
+ const uint old_state = data.in_set_window_state;
+ data.in_set_window_state = 1;
+
+ const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q));
+ q->move(screen.topLeft());
+ q->resize(screen.size());
+
+ data.in_set_window_state = old_state;
+}
+
+static Qt::WindowStates effectiveState(Qt::WindowStates state)
+ {
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+ }
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+ if (isWindow() && !testAttribute(Qt::WA_WState_Created))
+ create();
+
+ data->window_state = newstate;
+ data->in_set_window_state = 1;
+ bool needShow = false;
+ Qt::WindowStates newEffectiveState = effectiveState(newstate);
+ Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
+ if (isWindow() && newEffectiveState != oldEffectiveState) {
+ d->createTLExtra();
+ if (oldEffectiveState == Qt::WindowNoState) { //normal
+ d->topData()->normalGeometry = geometry();
+ } else if (oldEffectiveState == Qt::WindowFullScreen) {
+ setParent(0, d->topData()->savedFlags);
+ needShow = true;
+ } else if (oldEffectiveState == Qt::WindowMinimized) {
+ needShow = true;
+ }
+
+ if (newEffectiveState == Qt::WindowMinimized) {
+ //### not ideal...
+ hide();
+ needShow = false;
+ } else if (newEffectiveState == Qt::WindowFullScreen) {
+ d->topData()->savedFlags = windowFlags();
+ setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
+ d->setFullScreenSize_helper();
+ raise();
+ needShow = true;
+ } else if (newEffectiveState == Qt::WindowMaximized) {
+ createWinId();
+ d->setMaxWindowState_helper();
+ } else { //normal
+ QRect r = d->topData()->normalGeometry;
+ if (r.width() >= 0) {
+ d->topData()->normalGeometry = QRect(0,0,-1,-1);
+ setGeometry(r);
+ }
+ }
+ }
+ data->in_set_window_state = 0;
+
+ if (needShow)
+ show();
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ q->platformWindow()->raise();
+ }
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ q->platformWindow()->lower();
+ } else if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget*)
+{
+ Q_Q(QWidget);
+ if (QWidget *p = q->parentWidget()) {
+ setDirtyOpaqueRegion();
+ p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
+ }
+}
+
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ QPoint oldp = q->geometry().topLeft();
+ QSize olds = q->size();
+ QRect r(x, y, w, h);
+
+ bool isResize = olds != r.size();
+ isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
+
+
+ // We only care about stuff that changes the geometry, or may
+ // cause the window manager to change its state
+ if (r.size() == olds && oldp == r.topLeft())
+ return;
+
+ if (!data.in_set_window_state) {
+ q->data->window_state &= ~Qt::WindowMaximized;
+ q->data->window_state &= ~Qt::WindowFullScreen;
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ }
+
+ QPoint oldPos = q->pos();
+ data.crect = r;
+
+ if (q->isVisible()) {
+ if (q->platformWindow()) {
+ if (q->isWindow()) {
+ q->platformWindow()->setGeometry(q->frameGeometry());
+ } else {
+ QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint());
+ q->platformWindow()->setGeometry(QRect(posInNativeParent,r.size()));
+ }
+ const QWidgetBackingStore *bs = maybeBackingStore();
+ if (bs->windowSurface) {
+ if (isResize)
+ bs->windowSurface->resize(r.size());
+ }
+ } else {
+ if (isMove && !isResize)
+ moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, olds);
+ }
+
+ if (isMove) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ QResizeEvent e(r.size(), olds);
+ QApplication::sendEvent(q, &e);
+ if (q->platformWindow())
+ q->update();
+ }
+ } else { // not visible
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+ scrollChildren(dx, dy);
+ scrollRect(q->rect(), dx, dy);
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ scrollRect(r, dx, dy);
+}
+
+static QPlatformScreen *qt_screenForWidget(const QWidget *w)
+{
+ if (!w)
+ return 0;
+ QRect frame = w->frameGeometry();
+ if (!w->isWindow())
+ frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0)));
+ const QPoint p = (frame.topLeft() + frame.bottomRight()) / 2;
+
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen *> screens = pi->screens();
+
+ for (int i = 0; i < screens.size(); ++i) {
+ if (screens[i]->geometry().contains(p))
+ return screens[i];
+ }
+
+ // Assume screen zero if we have it.
+ if (!screens.isEmpty())
+ return screens[0];
+ else
+ qWarning("qt_screenForWidget: no screens");
+
+ return 0;
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+
+ QPlatformScreen *screen = qt_screenForWidget(this);
+ if (!screen) {
+ if (m == PdmDpiX || m == PdmDpiY)
+ return 72;
+ return QPaintDevice::metric(m);
+ }
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmWidthMM) {
+ val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else if (m == PdmHeightMM) {
+ val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
+ } else if (m == PdmDepth) {
+ return screen->depth();
+ } else if (m == PdmDpiX || m == PdmPhysicalDpiX) {
+ if (d->extra && d->extra->customDpiX)
+ return d->extra->customDpiX;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4));
+ } else if (m == PdmDpiY || m == PdmPhysicalDpiY) {
+ if (d->extra && d->extra->customDpiY)
+ return d->extra->customDpiY;
+ else if (d->parent)
+ return static_cast<QWidget *>(d->parent)->metric(m);
+ return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4));
+ } else {
+ val = QPaintDevice::metric(m);// XXX
+ }
+ return val;
+}
+
+/*!
+ \preliminary
+
+ Sets the window to be the \a window specified.
+ The QWidget takes ownership of the \a surface.
+*/
+void QWidget::setPlatformWindow(QPlatformWindow *window)
+{
+ Q_D(QWidget);
+
+ QTLWExtra *topData = d->topData();
+ if (topData->platformWindow == window)
+ return;
+
+ delete topData->platformWindow;
+ topData->platformWindow = window;
+}
+
+/*!
+ \preliminary
+
+ Returns the QPlatformWindow this widget will be drawn into.
+*/
+QPlatformWindow *QWidget::platformWindow() const
+{
+ Q_D(const QWidget);
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra && extra->platformWindow)
+ return extra->platformWindow;
+
+ return 0;
+}
+
+void QWidget::setPlatformWindowFormat(const QPlatformWindowFormat &format)
+{
+ if (isWindow() || testAttribute(Qt::WA_NativeWindow)) {
+ Q_D(QWidget);
+ QTLWExtra *topData = d->topData();
+ topData->platformWindowFormat = format;
+ if (testAttribute(Qt::WA_WState_Created)) {
+ bool wasVisible = testAttribute(Qt::WA_WState_Visible);
+ destroy();
+ d->create_sys(0,true,true);
+ if (wasVisible)
+ topData->platformWindow->setVisible(true);
+ }
+ }
+}
+
+QPlatformWindowFormat QWidget::platformWindowFormat() const
+{
+ Q_D(const QWidget);
+
+ QTLWExtra *extra = d->maybeTopData();
+ if (extra){
+ return extra->platformWindowFormat;
+ } else {
+ return QPlatformWindowFormat::defaultFormat();
+ }
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ if (extra && extra->topextra) {
+ //the toplevel might have a context with a "qglcontext associated with it. We need to
+ //delete the qglcontext before we delete the qplatformglcontext.
+ //One unfortunate thing about this is that we potentially create a glContext just to
+ //delete it straight afterwards.
+ if (extra->topextra->platformWindow) {
+ if (QPlatformGLContext *context = extra->topextra->platformWindow->glContext()) {
+ context->deleteQGLContext();
+ }
+ }
+ delete extra->topextra->platformWindow;
+ extra->topextra->platformWindow = 0;
+ extra->topextra->backingStore.destroy();
+ }
+}
+
+void QWidgetPrivate::registerDropSite(bool on)
+{
+ Q_UNUSED(on);
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion &region)
+{
+ Q_UNUSED(region);
+ // XXX
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+ // XXX
+}
+
+void QWidgetPrivate::setWindowOpacity_sys(qreal level)
+{
+ Q_Q(QWidget);
+ q->platformWindow()->setOpacity(level);
+}
+
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
+{
+ Q_UNUSED(dontShow);
+ Q_UNUSED(oldRect);
+ // XXX
+}
+
+QPaintEngine *QWidget::paintEngine() const
+{
+ qWarning("QWidget::paintEngine: Should no longer be called");
+ return 0; //##### @@@
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ Q_Q(QWidget);
+ if (q->platformWindowFormat().hasWindowSurface())
+ return QApplicationPrivate::platformIntegration()->createWindowSurface(q,0);
+ else
+ return 0;
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+}
+
+#ifndef QT_NO_CURSOR
+void qt_qpa_set_cursor(QWidget * w, bool force)
+{
+ static QCursor arrowCursor(Qt::ArrowCursor);
+ static QPointer<QWidget> lastUnderMouse = 0;
+
+ QCursor * override = QApplication::overrideCursor();
+
+ if (override && w != 0)
+ return;
+
+ QWidget *cursorWidget;
+ QCursor cursorCursor;
+
+ do {
+ if (w == 0) {
+ if (override) {
+ cursorCursor = *override;
+ cursorWidget = QApplication::topLevelAt(QCursor::pos());
+ break;
+ }
+ w = QApplication::widgetAt(QCursor::pos());
+ if (w == 0) // clear the override cursor while over empty space
+ w = QApplication::desktop();
+ } else if (force) {
+ lastUnderMouse = w;
+ } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse
+ && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
+ w = lastUnderMouse;
+ }
+ if (w == QApplication::desktop() && !override) {
+ cursorCursor = arrowCursor;
+ cursorWidget = w;
+ break;
+ }
+
+ QWidget * curWin = QApplication::activeWindow();
+ if (!curWin && w && w->internalWinId())
+ return;
+ QWidget* cW = w && !w->internalWinId() ? w : curWin;
+
+ if (!cW || cW->window() != w->window() ||
+ !cW->isVisible() || !cW->underMouse() || override)
+ return;
+
+ cursorCursor = w->cursor();
+ cursorWidget = w;
+ } while (0);
+ foreach (QWeakPointer<QPlatformCursor> cursor, QPlatformCursorPrivate::getInstances())
+ if (cursor)
+ cursor.data()->changeCursor(&cursorCursor, cursorWidget);
+}
+#endif //QT_NO_CURSOR
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 8e4e99a887..cb7280065a 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -361,7 +361,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
- QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
+ QScopedPointer<QSymbianControl> control( new QSymbianControl(q) );
+ Q_CHECK_PTR(control);
+
QT_TRAP_THROWING(control->ConstructL(true, desktop));
control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi()));
@@ -406,7 +408,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
- QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
+ QScopedPointer<QSymbianControl> control( new QSymbianControl(q) );
+ Q_CHECK_PTR(control);
+
QT_TRAP_THROWING(control->ConstructL(!parentWidget));
// Symbian windows are always created in an inactive state
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 4d28e99b50..a02c5ba008 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -329,18 +329,11 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (topLevel) {
if ((type == Qt::Window || dialog || tool)) {
if (!(flags & Qt::FramelessWindowHint)) {
- if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) {
+ style |= WS_POPUP;
+ if (!(flags & Qt::MSWindowsFixedSizeDialogHint))
style |= WS_THICKFRAME;
- if(!(flags &
- ( Qt::WindowSystemMenuHint
- | Qt::WindowTitleHint
- | Qt::WindowMinMaxButtonsHint
- | Qt::WindowCloseButtonHint
- | Qt::WindowContextHelpButtonHint)))
- style |= WS_POPUP;
- } else {
- style |= WS_POPUP | WS_DLGFRAME;
- }
+ else
+ style |= WS_DLGFRAME;
}
if (flags & Qt::WindowTitleHint)
style |= WS_CAPTION;
@@ -424,6 +417,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (!q->testAttribute(Qt::WA_Resized)) {
w = sw/2;
h = 4*sh/10;
+ if (extra) {
+ int dx = rect.right - rect.left;
+ int dy = rect.bottom - rect.top;
+ w = qMin(w, extra->maxw + dx);
+ h = qMin(h, extra->maxh + dy);
+ w = qMax(w, extra->minw + dx);
+ h = qMax(h, extra->minh + dy);
+ }
}
if (!wasMoved) {
x = sw/2 - w/2;
@@ -1635,8 +1636,6 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
}
}
-extern Q_GUI_EXPORT HDC qt_win_display_dc();
-
int QWidget::metric(PaintDeviceMetric m) const
{
Q_D(const QWidget);
@@ -1646,7 +1645,7 @@ int QWidget::metric(PaintDeviceMetric m) const
} else if (m == PdmHeight) {
val = data->crect.height();
} else {
- HDC gdc = qt_win_display_dc();
+ HDC gdc = GetDC(0);
switch (m) {
case PdmDpiX:
case PdmPhysicalDpiX:
@@ -1697,6 +1696,7 @@ int QWidget::metric(PaintDeviceMetric m) const
val = 0;
qWarning("QWidget::metric: Invalid metric command");
}
+ ReleaseDC(0, gdc);
}
return val;
}
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index a93c5455b2..cf23981272 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -905,8 +905,17 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
inputContext->setFocusWidget(q);
}
- if (destroyw)
+ if (destroyw) {
qt_XDestroyWindow(q, dpy, destroyw);
+ if (QTLWExtra *topData = maybeTopData()) {
+#ifndef QT_NO_XSYNC
+ if (topData->syncUpdateCounter)
+ XSyncDestroyCounter(dpy, topData->syncUpdateCounter);
+#endif
+ // we destroyed our old window - reset the top-level state
+ createTLSysExtra();
+ }
+ }
// newly created windows are positioned at the window system's
// (0,0) position. If the parent uses wrect mapping to expand the
diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h
index 2a731e587e..ab8af5fbb2 100644
--- a/src/gui/kernel/qwindowdefs.h
+++ b/src/gui/kernel/qwindowdefs.h
@@ -131,6 +131,12 @@ QT_END_HEADER
#endif // Q_WS_QWS
+#if defined(Q_WS_QPA)
+
+typedef unsigned long WId;
+
+#endif // Q_WS_QPA
+
#if defined(Q_OS_SYMBIAN)
class CCoeControl;
typedef CCoeControl * WId;
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp
new file mode 100644
index 0000000000..bb29cbf228
--- /dev/null
+++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qwindowsysteminterface_qpa.h"
+#include "qwindowsysteminterface_qpa_p.h"
+#include "qapplication_p.h"
+#include <QAbstractEventDispatcher>
+
+QT_BEGIN_NAMESPACE
+
+
+QTime QWindowSystemInterfacePrivate::eventTime;
+
+//------------------------------------------------------------
+//
+// Callback functions for plugins:
+//
+
+QList<QWindowSystemInterfacePrivate::WindowSystemEvent *> QWindowSystemInterfacePrivate::windowSystemEventQueue;
+QMutex QWindowSystemInterfacePrivate::queueMutex;
+
+extern QPointer<QWidget> qt_last_mouse_receiver;
+
+
+void QWindowSystemInterface::handleEnterEvent(QWidget *tlw)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ return;
+
+ QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+ }
+}
+
+void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ return;
+ }
+ QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ return;
+ }
+ QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+
+void QWindowSystemInterface::handleCloseEvent(QWidget *tlw)
+{
+ if (tlw) {
+ QWindowSystemInterfacePrivate::CloseEvent *e =
+ new QWindowSystemInterfacePrivate::CloseEvent(tlw);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+ }
+}
+
+/*!
+
+\a tlw == 0 means that \a ev is in global coords only
+
+
+*/
+void QWindowSystemInterface::handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b) {
+ unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleMouseEvent(w, time, local, global, b);
+}
+
+void QWindowSystemInterface::handleMouseEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ tlw = 0;
+ }
+ QWindowSystemInterfacePrivate::MouseEvent * e =
+ new QWindowSystemInterfacePrivate::MouseEvent(tlw, timestamp, local, global, b);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
+ unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleKeyEvent(w, time, t, k, mods, text, autorep, count);
+}
+
+void QWindowSystemInterface::handleKeyEvent(QWidget *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ tlw = 0;
+ }
+
+ QWindowSystemInterfacePrivate::KeyEvent * e =
+ new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) {
+ unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleWheelEvent(w, time, local, global, d, o);
+}
+
+void QWindowSystemInterface::handleWheelEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o)
+{
+ if (tlw) {
+ QWidgetData *data = qt_qwidget_data(tlw);
+ if (data->in_destructor)
+ tlw = 0;
+ }
+
+ QWindowSystemInterfacePrivate::WheelEvent *e =
+ new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, d, o);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
+{
+ queueMutex.lock();
+ int ret = windowSystemEventQueue.count();
+ queueMutex.unlock();
+ return ret;
+}
+
+QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent()
+{
+ queueMutex.lock();
+ QWindowSystemInterfacePrivate::WindowSystemEvent *ret;
+ if (windowSystemEventQueue.isEmpty())
+ ret = 0;
+ else
+ ret = windowSystemEventQueue.takeFirst();
+ queueMutex.unlock();
+ return ret;
+}
+
+void QWindowSystemInterfacePrivate::queueWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
+{
+ queueMutex.lock();
+ windowSystemEventQueue.append(ev);
+ queueMutex.unlock();
+
+ QAbstractEventDispatcher *dispatcher = QApplicationPrivate::qt_qpa_core_dispatcher();
+ if (dispatcher)
+ dispatcher->wakeUp();
+}
+
+void QWindowSystemInterface::handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points) {
+ unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleTouchEvent(w, time, type, devType, points);
+}
+
+void QWindowSystemInterface::handleTouchEvent(QWidget *tlw, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points)
+{
+ if (!points.size()) // Touch events must have at least one point
+ return;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ Qt::TouchPointStates states;
+ QTouchEvent::TouchPoint p;
+
+ QList<struct TouchPoint>::const_iterator point = points.constBegin();
+ QList<struct TouchPoint>::const_iterator end = points.constEnd();
+ while (point != end) {
+ p.setId(point->id);
+ p.setPressure(point->pressure);
+ states |= point->state;
+ Qt::TouchPointStates state = point->state;
+ if (point->isPrimary) {
+ state |= Qt::TouchPointPrimary;
+ }
+ p.setState(state);
+ p.setRect(point->area);
+ p.setScreenPos(point->area.center());
+ p.setNormalizedPos(point->normalPosition);
+
+ touchPoints.append(p);
+ ++point;
+ }
+
+ QWindowSystemInterfacePrivate::TouchEvent *e =
+ new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, devType, touchPoints);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleScreenGeometryChange(int screenIndex)
+{
+ QWindowSystemInterfacePrivate::ScreenGeometryEvent *e =
+ new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screenIndex);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleScreenAvailableGeometryChange(int screenIndex)
+{
+ QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e =
+ new QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent(screenIndex);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+void QWindowSystemInterface::handleScreenCountChange(int count)
+{
+ QWindowSystemInterfacePrivate::ScreenCountEvent *e =
+ new QWindowSystemInterfacePrivate::ScreenCountEvent(count);
+ QWindowSystemInterfacePrivate::queueWindowSystemEvent(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h
new file mode 100644
index 0000000000..1c79f2a257
--- /dev/null
+++ b/src/gui/kernel/qwindowsysteminterface_qpa.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QWINDOWSYSTEMINTERFACE_H
+#define QWINDOWSYSTEMINTERFACE_H
+
+#include <QtCore/QTime>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/QEvent>
+#include <QtGui/QWidget>
+#include <QtCore/QWeakPointer>
+#include <QtCore/QMutex>
+#include <QtGui/QTouchEvent>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QWindowSystemInterface
+{
+public:
+ static void handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b);
+ static void handleMouseEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b);
+
+ static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
+ static void handleKeyEvent(QWidget *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
+
+ static void handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o);
+ static void handleWheelEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o);
+
+ struct TouchPoint {
+ int id; // for application use
+ bool isPrimary; // for application use
+ QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1)
+ QRectF area; // the touched area, centered at position in screen coordinates
+ qreal pressure; // 0 to 1
+ Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released}
+ };
+
+ static void handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points);
+ static void handleTouchEvent(QWidget *w, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points);
+
+ static void handleGeometryChange(QWidget *w, const QRect &newRect);
+ static void handleCloseEvent(QWidget *w);
+ static void handleEnterEvent(QWidget *w);
+ static void handleLeaveEvent(QWidget *w);
+
+ // Changes to the screen
+ static void handleScreenGeometryChange(int screenIndex);
+ static void handleScreenAvailableGeometryChange(int screenIndex);
+ static void handleScreenCountChange(int count);
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif // QWINDOWSYSTEMINTERFACE_H
diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h
new file mode 100644
index 0000000000..78e1f33339
--- /dev/null
+++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QWINDOWSYSTEMINTERFACE_QPA_P_H
+#define QWINDOWSYSTEMINTERFACE_QPA_P_H
+
+#include "qwindowsysteminterface_qpa.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWindowSystemInterfacePrivate {
+public:
+ enum EventType {
+ Close,
+ GeometryChange,
+ Enter,
+ Leave,
+ Mouse,
+ Wheel,
+ Key,
+ Touch,
+ ScreenGeometry,
+ ScreenAvailableGeometry,
+ ScreenCountChange
+ };
+
+ class WindowSystemEvent {
+ public:
+ WindowSystemEvent(EventType t)
+ : type(t) { }
+ EventType type;
+ };
+
+ class CloseEvent : public WindowSystemEvent {
+ public:
+ CloseEvent(QWidget *tlw)
+ : WindowSystemEvent(Close), topLevel(tlw) { }
+ QWeakPointer<QWidget> topLevel;
+ };
+
+ class GeometryChangeEvent : public WindowSystemEvent {
+ public:
+ GeometryChangeEvent(QWidget *tlw, const QRect &newGeometry)
+ : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry)
+ { }
+ QWeakPointer<QWidget> tlw;
+ QRect newGeometry;
+ };
+
+ class EnterEvent : public WindowSystemEvent {
+ public:
+ EnterEvent(QWidget *enter)
+ : WindowSystemEvent(Enter), enter(enter)
+ { }
+ QWeakPointer<QWidget> enter;
+ };
+
+ class LeaveEvent : public WindowSystemEvent {
+ public:
+ LeaveEvent(QWidget *leave)
+ : WindowSystemEvent(Leave), leave(leave)
+ { }
+ QWeakPointer<QWidget> leave;
+ };
+
+ class UserEvent : public WindowSystemEvent {
+ public:
+ UserEvent(QWidget * w, ulong time, EventType t)
+ : WindowSystemEvent(t), widget(w), timestamp(time) { }
+ QWeakPointer<QWidget> widget;
+ unsigned long timestamp;
+ };
+
+ class MouseEvent : public UserEvent {
+ public:
+ MouseEvent(QWidget * w, ulong time, const QPoint & local, const QPoint & global, Qt::MouseButtons b)
+ : UserEvent(w, time, Mouse), localPos(local), globalPos(global), buttons(b) { }
+ QPoint localPos;
+ QPoint globalPos;
+ Qt::MouseButtons buttons;
+ };
+
+ class WheelEvent : public UserEvent {
+ public:
+ WheelEvent(QWidget *w, ulong time, const QPoint & local, const QPoint & global, int d, Qt::Orientation o)
+ : UserEvent(w, time, Wheel), delta(d), localPos(local), globalPos(global), orient(o) { }
+ int delta;
+ QPoint localPos;
+ QPoint globalPos;
+ Qt::Orientation orient;
+ };
+
+ class KeyEvent : public UserEvent {
+ public:
+ KeyEvent(QWidget *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
+ :UserEvent(w, time, Key), key(k), unicode(text), repeat(autorep),
+ repeatCount(count), modifiers(mods), keyType(t) { }
+ int key;
+ QString unicode;
+ bool repeat;
+ ushort repeatCount;
+ Qt::KeyboardModifiers modifiers;
+ QEvent::Type keyType;
+ };
+
+ class TouchEvent : public UserEvent {
+ public:
+ TouchEvent(QWidget *w, ulong time, QEvent::Type t, QTouchEvent::DeviceType d, const QList<QTouchEvent::TouchPoint> &p)
+ :UserEvent(w, time, Touch), devType(d), points(p), touchType(t) { }
+ QTouchEvent::DeviceType devType;
+ QList<QTouchEvent::TouchPoint> points;
+ QEvent::Type touchType;
+
+ };
+
+ class ScreenCountEvent : public WindowSystemEvent {
+ public:
+ ScreenCountEvent (int count)
+ : WindowSystemEvent(ScreenCountChange) , count(count) { }
+ int count;
+ };
+
+ class ScreenGeometryEvent : public WindowSystemEvent {
+ public:
+ ScreenGeometryEvent(int index)
+ : WindowSystemEvent(ScreenGeometry), index(index) { }
+ int index;
+ };
+
+ class ScreenAvailableGeometryEvent : public WindowSystemEvent {
+ public:
+ ScreenAvailableGeometryEvent(int index)
+ : WindowSystemEvent(ScreenAvailableGeometry), index(index) { }
+ int index;
+ };
+
+ static QList<WindowSystemEvent *> windowSystemEventQueue;
+ static QMutex queueMutex;
+
+ static int windowSystemEventsQueued();
+ static WindowSystemEvent * getWindowSystemEvent();
+ static void queueWindowSystemEvent(WindowSystemEvent *ev);
+
+ static QTime eventTime;
+};
+
+QT_END_HEADER
+QT_END_NAMESPACE
+
+#endif // QWINDOWSYSTEMINTERFACE_QPA_P_H
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index aba42f2660..47cefe4f59 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -512,7 +512,7 @@ QX11EmbedWidget::~QX11EmbedWidget()
<< "from container with winId" << d->container;
#endif
XUnmapWindow(x11Info().display(), internalWinId());
- XReparentWindow(x11Info().display(), internalWinId(), x11Info().appRootWindow(), 0, 0);
+ XReparentWindow(x11Info().display(), internalWinId(), x11Info().appRootWindow(x11Info().screen()), 0, 0);
}
#ifdef QX11EMBED_DEBUG
@@ -791,13 +791,13 @@ bool QX11EmbedWidget::x11Event(XEvent *event)
qDebug() << "QX11EmbedWidget::x11Event: client"
<< (void *)this << "with winId" << winId()
<< "received a ReparentNotify to"
- << ((event->xreparent.parent == x11Info().appRootWindow())
+ << ((event->xreparent.parent == x11Info().appRootWindow(x11Info().screen()))
? QString::fromLatin1("root") : QString::number(event->xreparent.parent));
#endif
// If the container shuts down, we will be reparented to the
// root window. We must also consider the case that we may be
// reparented from one container to another.
- if (event->xreparent.parent == x11Info().appRootWindow()) {
+ if (event->xreparent.parent == x11Info().appRootWindow(x11Info().screen())) {
if (((QHackWidget *)this)->topData()->embedded) {
d->container = 0;
emit containerClosed();
@@ -1115,7 +1115,7 @@ QX11EmbedContainer::~QX11EmbedContainer()
Q_D(QX11EmbedContainer);
if (d->client) {
XUnmapWindow(x11Info().display(), d->client);
- XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+ XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(x11Info().screen()), 0, 0);
}
if (d->xgrab)
@@ -1379,7 +1379,7 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
// Wait until the messages have been processed. Then ask
// the window manager to delete the window.
XUnmapWindow(x11Info().display(), d->client);
- XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(), 0, 0);
+ XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(x11Info().screen()), 0, 0);
XSync(x11Info().display(), false);
XEvent ev;
@@ -1627,7 +1627,7 @@ void QX11EmbedContainerPrivate::rejectClient(WId window)
Q_Q(QX11EmbedContainer);
q->setEnabled(false);
XRemoveFromSaveSet(q->x11Info().display(), client);
- XReparentWindow(q->x11Info().display(), window, q->x11Info().appRootWindow(), 0, 0);
+ XReparentWindow(q->x11Info().display(), window, q->x11Info().appRootWindow(q->x11Info().screen()), 0, 0);
}
/*! \internal
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index e839b2518c..c18dd3c29d 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -102,8 +102,6 @@ QMatrix4x4::QMatrix4x4(const qreal *values)
\sa optimize()
*/
-#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
-
/*!
\fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
@@ -112,7 +110,7 @@ QMatrix4x4::QMatrix4x4(const qreal *values)
the remaining elements are filled with elements from the identity
matrix.
- \sa toGenericMatrix(), qGenericMatrixToMatrix4x4()
+ \sa toGenericMatrix()
*/
/*!
@@ -122,34 +120,32 @@ QMatrix4x4::QMatrix4x4(const qreal *values)
top-most M rows of this 4x4 matrix. If N or M is greater than 4,
then the remaining elements are filled with elements from the
identity matrix.
-
- \sa qGenericMatrixFromMatrix4x4()
*/
-#endif
-
/*!
\fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
\relates QMatrix4x4
+ \obsolete
Returns a 4x4 matrix constructed from the left-most 4 columns and
top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
or rows, the remaining elements are filled with elements from the
identity matrix.
- \sa qGenericMatrixFromMatrix4x4()
+ \sa QMatrix4x4(const QGenericMatrix &)
*/
/*!
\fn QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
\relates QMatrix4x4
+ \obsolete
Returns a NxM generic matrix constructed from the left-most N columns
and top-most M rows of \a matrix. If N or M is greater than 4,
then the remaining elements are filled with elements from the
identity matrix.
- \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix()
+ \sa QMatrix4x4::toGenericMatrix()
*/
/*!
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index 6d8a68b317..706450a9c1 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -69,10 +69,10 @@ public:
qreal m21, qreal m22, qreal m23, qreal m24,
qreal m31, qreal m32, qreal m33, qreal m34,
qreal m41, qreal m42, qreal m43, qreal m44);
-#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+
template <int N, int M>
explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix);
-#endif
+
QMatrix4x4(const qreal *values, int cols, int rows);
QMatrix4x4(const QTransform& transform);
QMatrix4x4(const QMatrix& matrix);
@@ -169,10 +169,8 @@ public:
QRect mapRect(const QRect& rect) const;
QRectF mapRect(const QRectF& rect) const;
-#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
template <int N, int M>
QGenericMatrix<N, M, qreal> toGenericMatrix() const;
-#endif
inline qreal *data();
inline const qreal *data() const { return m[0]; }
@@ -223,8 +221,6 @@ inline QMatrix4x4::QMatrix4x4
flagBits = General;
}
-#if !defined(QT_NO_MEMBER_TEMPLATES)
-
template <int N, int M>
Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
(const QGenericMatrix<N, M, qreal>& matrix)
@@ -261,8 +257,6 @@ QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const
return result;
}
-#endif
-
inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const
{
Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
@@ -992,14 +986,15 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
#endif
+#ifdef QT_DEPRECATED
template <int N, int M>
-QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
+QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
{
return QMatrix4x4(matrix.constData(), N, M);
}
template <int N, int M>
-QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+QT_DEPRECATED QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
{
QGenericMatrix<N, M, qreal> result;
const qreal *m = matrix.constData();
@@ -1016,6 +1011,7 @@ QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix
}
return result;
}
+#endif
#endif
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index bd37d9f56e..51f2538a83 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -34,6 +34,7 @@ HEADERS += \
painting/qprinter.h \
painting/qprinter_p.h \
painting/qprinterinfo.h \
+ painting/qprinterinfo_p.h \
painting/qrasterizer_p.h \
painting/qregion.h \
painting/qstroker_p.h \
@@ -73,6 +74,7 @@ SOURCES += \
painting/qprintengine_pdf.cpp \
painting/qprintengine_ps.cpp \
painting/qprinter.cpp \
+ painting/qprinterinfo.cpp \
painting/qrasterizer.cpp \
painting/qregion.cpp \
painting/qstroker.cpp \
@@ -87,14 +89,18 @@ SOURCES += \
painting/qpaintengine_raster.cpp \
painting/qdrawhelper.cpp \
painting/qimagescale.cpp \
- painting/qgrayraster.c
+ painting/qgrayraster.c \
+ painting/qpaintengine_blitter.cpp \
+ painting/qblittable.cpp \
HEADERS += \
painting/qpaintengine_raster_p.h \
painting/qdrawhelper_p.h \
painting/qblendfunctions_p.h \
painting/qrasterdefs_p.h \
- painting/qgrayraster_p.h
+ painting/qgrayraster_p.h \
+ painting/qpaintengine_blitter_p.h \
+ painting/qblittable_p.h \
win32 {
HEADERS += painting/qprintengine_win_p.h
@@ -115,20 +121,20 @@ embedded {
SOURCES += \
painting/qgraphicssystem_qws.cpp \
-} else {
+} else: if(!qpa) {
HEADERS += \
painting/qgraphicssystem_raster_p.h \
painting/qgraphicssystem_runtime_p.h \
painting/qgraphicssystemfactory_p.h \
painting/qgraphicssystemplugin_p.h \
- painting/qwindowsurface_raster_p.h \
+ painting/qwindowsurface_raster_p.h
SOURCES += \
painting/qgraphicssystem_raster.cpp \
painting/qgraphicssystem_runtime.cpp \
painting/qgraphicssystemfactory.cpp \
painting/qgraphicssystemplugin.cpp \
- painting/qwindowsurface_raster.cpp \
+ painting/qwindowsurface_raster.cpp
}
unix:x11 {
@@ -141,7 +147,7 @@ unix:x11 {
painting/qpaintengine_x11.cpp
}
-!embedded:!x11:mac {
+!embedded:!qpa:!x11:mac {
HEADERS += \
painting/qpaintengine_mac_p.h \
painting/qgraphicssystem_mac_p.h \
@@ -157,14 +163,14 @@ unix:x11 {
painting/qprintengine_mac.mm \
}
-unix:!mac:!symbian {
+unix:!mac:!symbian|qpa {
HEADERS += \
painting/qprinterinfo_unix_p.h
SOURCES += \
painting/qprinterinfo_unix.cpp
}
-win32|x11|mac|embedded|symbian {
+win32|x11|mac|embedded|qpa|symbian {
SOURCES += painting/qbackingstore.cpp
HEADERS += painting/qbackingstore_p.h
}
@@ -181,6 +187,12 @@ embedded {
painting/qpaintdevice_qws.cpp
}
+qpa {
+ SOURCES += \
+ painting/qcolormap_qpa.cpp \
+ painting/qpaintdevice_qpa.cpp
+}
+
symbian {
SOURCES += \
painting/qpaintengine_s60.cpp \
@@ -191,7 +203,7 @@ symbian {
painting/qpaintengine_s60_p.h
}
-x11|embedded {
+x11|embedded|qpa {
contains(QT_CONFIG,qtopia) {
DEFINES += QT_NO_CUPS QT_NO_LPR
} else {
@@ -221,7 +233,7 @@ x11 {
SOURCES += painting/qwindowsurface_x11.cpp
}
-mac {
+!embedded:!qpa:mac {
HEADERS += painting/qwindowsurface_mac_p.h
SOURCES += painting/qwindowsurface_mac.cpp
}
@@ -248,6 +260,12 @@ symbian {
QMAKE_CXXFLAGS.ARMCC *= -O3
}
+mac {
+ HEADERS += painting/qunifiedtoolbarsurface_mac_p.h
+ SOURCES += painting/qunifiedtoolbarsurface_mac.cpp
+}
+
+
NEON_SOURCES += painting/qdrawhelper_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 83c58c405e..129bba5600 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -98,6 +98,21 @@ static inline void qt_flush(QWidget *widget, const QRegion &region, QWindowSurfa
QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false);
#endif
+ //The performance hit by doing this should be negligible. However, be aware that
+ //using this FPS when you have > 1 windowsurface can give you inaccurate FPS
+ static bool fpsDebug = qgetenv("QT_DEBUG_FPS").toInt();
+ if (fpsDebug) {
+ static QTime time = QTime::currentTime();
+ static int frames = 0;
+
+ frames++;
+
+ if(time.elapsed() > 5000) {
+ double fps = double(frames * 1000) /time.restart();
+ fprintf(stderr,"FPS: %.1f\n",fps);
+ frames = 0;
+ }
+ }
if (widget != tlw)
windowSurface->flush(widget, region, tlwOffset + widget->mapTo(tlw, QPoint()));
else
@@ -271,7 +286,11 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi
void QWidgetBackingStore::releaseBuffer()
{
if (windowSurface)
+#if defined(Q_WS_QPA)
+ windowSurface->resize(QSize());
+#else
windowSurface->setGeometry(QRect());
+#endif
#ifdef Q_BACKINGSTORE_SUBSURFACES
for (int i = 0; i < subSurfaces.size(); ++i)
subSurfaces.at(i)->setGeometry(QRect());
@@ -401,7 +420,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
{
const bool widgetDirty = widget && widget != tlw;
const QRect tlwRect(topLevelRect());
+#if defined(Q_WS_QPA)
+ const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
+#else
const QRect surfaceGeometry(windowSurface->geometry());
+#endif
if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {
if (widgetDirty) {
const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());
@@ -452,7 +475,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const
QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const
{
if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) {
+#if defined(Q_WS_QPA)
+ const QSize surfaceGeometry(windowSurface->size());
+#else
const QRect surfaceGeometry(windowSurface->geometry());
+#endif
QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
if (!withinClipRect.isEmpty())
surfaceRect &= withinClipRect;
@@ -720,9 +747,8 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
}
// Alien widgets.
- if (!widget->internalWinId()) {
- QWidget *nativeParent = widget->nativeParentWidget();
- // Alien widgets with the top-level as the native parent (common case).
+ if (!widget->internalWinId() && !widget->isWindow()) {
+ QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
if (nativeParent == tlw) {
if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))
dirtyOnScreen += region.translated(topLevelOffset);
@@ -1152,12 +1178,16 @@ void QWidgetBackingStore::sync()
return;
}
- const bool inTopLevelResize = tlwExtra->inTopLevelResize;
const bool updatesDisabled = !tlw->updatesEnabled();
- const QRect tlwRect(topLevelRect());
- const QRect surfaceGeometry(windowSurface->geometry());
bool repaintAllWidgets = false;
+ const bool inTopLevelResize = tlwExtra->inTopLevelResize;
+ const QRect tlwRect(topLevelRect());
+#ifdef Q_WS_QPA
+ const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size());
+#else
+ const QRect surfaceGeometry(windowSurface->geometry());
+#endif
if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
if (hasStaticContents()) {
// Repaint existing dirty area and newly visible area.
@@ -1177,8 +1207,13 @@ void QWidgetBackingStore::sync()
}
}
+#ifdef Q_WS_QPA
+ if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size())
+ windowSurface->resize(tlwRect.size());
+#else
if (inTopLevelResize || surfaceGeometry != tlwRect)
windowSurface->setGeometry(tlwRect);
+#endif
if (updatesDisabled)
return;
@@ -1585,7 +1620,11 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn)
extra->staticContentsSize = data.crect.size();
}
+#ifdef Q_WS_QPA //Dont even call q->p
+ QPaintEngine *engine = 0;
+#else
QPaintEngine *engine = q->paintEngine();
+#endif
// QGLWidget does not support partial updates if:
// 1) The context is double buffered
// 2) The context is single buffered and auto-fill background is enabled.
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 517959e531..dc90003b85 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -309,9 +309,9 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl,
const uchar *src = srcPixels + y * sbpl;
const uchar *srcEnd = src + srcOffset;
while (src < srcEnd) {
-#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU))
+#if defined(QT_ARCH_ARMV5) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU))
// non-16-bit aligned memory access is not possible on PowerPC,
- // ARM <v6 (QT_ARCH_ARMV6) & SH & AVR32 & SPARC w/GCC
+ // ARM <v6 (QT_ARCH_ARMV5) & SH & AVR32 & SPARC w/GCC
quint16 spix = (quint16(src[2])<<8) + src[1];
#else
quint16 spix = *(quint16 *) (src + 1);
diff --git a/src/gui/painting/qblittable.cpp b/src/gui/painting/qblittable.cpp
new file mode 100644
index 0000000000..f4b84a9142
--- /dev/null
+++ b/src/gui/painting/qblittable.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qblittable_p.h"
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+class QBlittablePrivate
+{
+public:
+ QBlittablePrivate(const QSize &size, QBlittable::Capabilities caps)
+ : caps(caps), m_size(size), locked(false), cachedImg(0)
+ {}
+ QBlittable::Capabilities caps;
+ QSize m_size;
+ bool locked;
+ QImage *cachedImg;
+};
+
+
+QBlittable::QBlittable(const QSize &size, Capabilities caps)
+ : d_ptr(new QBlittablePrivate(size,caps))
+{
+}
+
+QBlittable::~QBlittable()
+{
+ delete d_ptr;
+}
+
+
+QBlittable::Capabilities QBlittable::capabilities() const
+{
+ Q_D(const QBlittable);
+ return d->caps;
+}
+
+QSize QBlittable::size() const
+{
+ Q_D(const QBlittable);
+ return d->m_size;
+}
+
+QImage *QBlittable::lock()
+{
+ Q_D(QBlittable);
+ if (!d->locked) {
+ d->cachedImg = doLock();
+ d->locked = true;
+ }
+
+ return d->cachedImg;
+}
+
+void QBlittable::unlock()
+{
+ Q_D(QBlittable);
+ if (d->locked) {
+ doUnlock();
+ d->locked = false;
+ }
+}
+
+QT_END_NAMESPACE
+#endif //QT_NO_BLITTABLE
+
diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h
new file mode 100644
index 0000000000..cb56cb2528
--- /dev/null
+++ b/src/gui/painting/qblittable_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBLITTABLE_P_H
+#define QBLITTABLE_P_H
+
+#include <QtCore/qsize.h>
+#include <QtGui/private/qpixmap_blitter_p.h>
+
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+class QImage;
+class QBlittablePrivate;
+
+class Q_GUI_EXPORT QBlittable
+{
+ Q_DECLARE_PRIVATE(QBlittable);
+public:
+ enum Capability {
+
+ SolidRectCapability = 0x0001,
+ SourcePixmapCapability = 0x0002,
+ SourceOverPixmapCapability = 0x0004,
+ SourceOverScaledPixmapCapability = 0x0008,
+
+ // Internal ones
+ OutlineCapability = 0x0001000,
+ };
+ Q_DECLARE_FLAGS (Capabilities, Capability);
+
+ QBlittable(const QSize &size, Capabilities caps);
+ virtual ~QBlittable();
+
+ Capabilities capabilities() const;
+ QSize size() const;
+
+ virtual void fillRect(const QRectF &rect, const QColor &color) = 0;
+ virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect) = 0;
+
+ QImage *lock();
+ void unlock();
+
+protected:
+ virtual QImage *doLock() = 0;
+ virtual void doUnlock() = 0;
+ QBlittablePrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+#endif //QT_NO_BLITTABLE
+#endif //QBLITTABLE_P_H
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 81a62b09ff..5741667ae9 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -635,6 +635,15 @@ QBrush &QBrush::operator=(const QBrush &b)
return *this;
}
+
+/*!
+ \fn void QBrush::swap(QBrush &other)
+ \since 4.8
+
+ Swaps brush \a other with this brush. This operation is very
+ fast and never fails.
+*/
+
/*!
Returns the brush as a QVariant
*/
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index ac247a68df..8b313196db 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -92,6 +92,12 @@ public:
~QBrush();
QBrush &operator=(const QBrush &brush);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QBrush &operator=(QBrush &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QBrush &other) { qSwap(d, other.d); }
+
operator QVariant() const;
inline Qt::BrushStyle style() const;
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index b9ec0d4d73..38fed7146d 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -49,9 +49,6 @@
#include "qrgb.h"
#include "qstringlist.h"
-#if defined(Q_WS_WINCE)
-#include "qguifunctions_wince.h"
-#endif
QT_BEGIN_NAMESPACE
static inline int h2i(char hex)
@@ -290,33 +287,16 @@ static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
#undef rgb
-QT_BEGIN_INCLUDE_NAMESPACE
-#include <stdlib.h>
-QT_END_INCLUDE_NAMESPACE
-
-#if defined(Q_C_CALLBACKS)
-extern "C" {
-#endif
-
-#ifdef Q_OS_WINCE
-static int __cdecl rgb_cmp(const void *d1, const void *d2)
-#else
-static int rgb_cmp(const void *d1, const void *d2)
-#endif
-{
- return qstricmp(((RGBData *)d1)->name, ((RGBData *)d2)->name);
-}
-
-#if defined(Q_C_CALLBACKS)
-}
-#endif
+inline bool operator<(const char *name, const RGBData &data)
+{ return qstrcmp(name, data.name) < 0; }
+inline bool operator<(const RGBData &data, const char *name)
+{ return qstrcmp(data.name, name) < 0; }
-static bool get_named_rgb(const char *name, QRgb *rgb)
+static bool get_named_rgb(const char *name_no_space, QRgb *rgb)
{
- RGBData x;
- x.name = name;
- RGBData *r = (RGBData*)bsearch(&x, rgbTbl, rgbTblSize, sizeof(RGBData), rgb_cmp);
- if (r) {
+ QByteArray name = QByteArray(name_no_space).toLower();
+ const RGBData *r = qBinaryFind(rgbTbl, rgbTbl + rgbTblSize, name.constData());
+ if (r != rgbTbl + rgbTblSize) {
*rgb = r->value;
return true;
}
diff --git a/src/gui/painting/qcolormap_qpa.cpp b/src/gui/painting/qcolormap_qpa.cpp
new file mode 100644
index 0000000000..1f4fea8e41
--- /dev/null
+++ b/src/gui/painting/qcolormap_qpa.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcolormap.h"
+#include "qcolor.h"
+#include "qpaintdevice.h"
+#include "private/qapplication_p.h"
+#include "private/qgraphicssystem_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QColormapPrivate
+{
+public:
+ inline QColormapPrivate()
+ : ref(1), mode(QColormap::Direct), depth(0), numcolors(0)
+ { }
+
+ QAtomicInt ref;
+
+ QColormap::Mode mode;
+ int depth;
+ int numcolors;
+};
+
+static QColormapPrivate *screenMap = 0;
+
+void QColormap::initialize()
+{
+ screenMap = new QColormapPrivate;
+
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ QList<QPlatformScreen*> screens = pi->screens();
+
+ screenMap->depth = screens[0]->depth();
+ if (screenMap->depth < 8) {
+ screenMap->mode = QColormap::Indexed;
+ screenMap->numcolors = 256;
+ } else {
+ screenMap->mode = QColormap::Direct;
+ screenMap->numcolors = -1;
+ }
+}
+
+void QColormap::cleanup()
+{
+ delete screenMap;
+ screenMap = 0;
+}
+
+QColormap QColormap::instance(int /*screen*/)
+{
+ return QColormap();
+}
+
+QColormap::QColormap()
+ : d(screenMap)
+{ d->ref.ref(); }
+
+QColormap::QColormap(const QColormap &colormap)
+ :d (colormap.d)
+{ d->ref.ref(); }
+
+QColormap::~QColormap()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+QColormap::Mode QColormap::mode() const
+{ return d->mode; }
+
+
+int QColormap::depth() const
+{ return d->depth; }
+
+
+int QColormap::size() const
+{
+ return d->numcolors;
+}
+
+#ifndef QT_QWS_DEPTH16_RGB
+#define QT_QWS_DEPTH16_RGB 565
+#endif
+static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100);
+static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10);
+static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10);
+static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits);
+static const int qt_green_shift = qt_bbits-(8-qt_gbits);
+static const int qt_neg_blue_shift = 8-qt_bbits;
+static const int qt_blue_mask = (1<<qt_bbits)-1;
+static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits);
+static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits));
+
+static const int qt_red_rounding_shift = qt_red_shift + qt_rbits;
+static const int qt_green_rounding_shift = qt_green_shift + qt_gbits;
+static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift;
+
+inline ushort qt_convRgbTo16(QRgb c)
+{
+ const int tr = qRed(c) << qt_red_shift;
+ const int tg = qGreen(c) << qt_green_shift;
+ const int tb = qBlue(c) >> qt_neg_blue_shift;
+
+ return (tb & qt_blue_mask) | (tg & qt_green_mask) | (tr & qt_red_mask);
+}
+
+inline QRgb qt_conv16ToRgb(ushort c)
+{
+ const int r=(c & qt_red_mask);
+ const int g=(c & qt_green_mask);
+ const int b=(c & qt_blue_mask);
+ const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift;
+ const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift;
+ const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift;
+
+ return qRgb(tr,tg,tb);
+}
+
+uint QColormap::pixel(const QColor &color) const
+{
+ QRgb rgb = color.rgba();
+ if (d->mode == QColormap::Direct) {
+ switch(d->depth) {
+ case 16:
+ return qt_convRgbTo16(rgb);
+ case 24:
+ case 32:
+ {
+ const int r = qRed(rgb);
+ const int g = qGreen(rgb);
+ const int b = qBlue(rgb);
+ const int red_shift = 16;
+ const int green_shift = 8;
+ const int red_mask = 0xff0000;
+ const int green_mask = 0x00ff00;
+ const int blue_mask = 0x0000ff;
+ const int tg = g << green_shift;
+#ifdef QT_QWS_DEPTH_32_BGR
+ if (qt_screen->pixelType() == QScreen::BGRPixel) {
+ const int tb = b << red_shift;
+ return 0xff000000 | (r & blue_mask) | (tg & green_mask) | (tb & red_mask);
+ }
+#endif
+ const int tr = r << red_shift;
+ return 0xff000000 | (b & blue_mask) | (tg & green_mask) | (tr & red_mask);
+ }
+ }
+ }
+ //XXX
+ //return qt_screen->alloc(qRed(rgb), qGreen(rgb), qBlue(rgb));
+ return 0;
+}
+
+const QColor QColormap::colorAt(uint pixel) const
+{
+ if (d->mode == Direct) {
+ if (d->depth == 16) {
+ pixel = qt_conv16ToRgb(pixel);
+ }
+ const int red_shift = 16;
+ const int green_shift = 8;
+ const int red_mask = 0xff0000;
+ const int green_mask = 0x00ff00;
+ const int blue_mask = 0x0000ff;
+#ifdef QT_QWS_DEPTH_32_BGR
+ if (qt_screen->pixelType() == QScreen::BGRPixel) {
+ return QColor((pixel & blue_mask),
+ (pixel & green_mask) >> green_shift,
+ (pixel & red_mask) >> red_shift);
+ }
+#endif
+ return QColor((pixel & red_mask) >> red_shift,
+ (pixel & green_mask) >> green_shift,
+ (pixel & blue_mask));
+ }
+#if 0 // XXX
+ Q_ASSERT_X(int(pixel) < qt_screen->numCols(), "QColormap::colorAt", "pixel out of bounds of palette");
+ return QColor(qt_screen->clut()[pixel]);
+#endif
+ return QColor();
+}
+
+const QVector<QColor> QColormap::colormap() const
+{
+ return QVector<QColor>();
+}
+
+QColormap &QColormap::operator=(const QColormap &colormap)
+{ qAtomicAssign(d, colormap.d); return *this; }
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp
index 770d947469..8d39b59e4d 100644
--- a/src/gui/painting/qgraphicssystem.cpp
+++ b/src/gui/painting/qgraphicssystem.cpp
@@ -50,6 +50,9 @@
#ifdef Q_WS_MAC
# include <private/qpixmap_mac_p.h>
#endif
+#ifdef Q_WS_QPA
+# include <QtGui/private/qapplication_p.h>
+#endif
#ifdef Q_OS_SYMBIAN
# include <private/qpixmap_s60_p.h>
#endif
@@ -71,8 +74,10 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
+#elif defined(Q_WS_QPA)
+ return QApplicationPrivate::platformIntegration()->createPixmapData(type);
#elif defined(Q_OS_SYMBIAN)
- return new QS60PixmapData(type);
+ return new QS60PixmapData(type);
#elif !defined(Q_WS_QWS)
#error QGraphicsSystem::createDefaultPixmapData() not implemented
#endif
diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h
index 76e9a8e3c3..1aa3aa08b2 100644
--- a/src/gui/painting/qgraphicssystem_p.h
+++ b/src/gui/painting/qgraphicssystem_p.h
@@ -55,10 +55,14 @@
#include "private/qpixmapdata_p.h"
#include "private/qwindowsurface_p.h"
+#include "private/qpaintengine_blitter_p.h"
+
+#include <qdebug.h>
QT_BEGIN_NAMESPACE
class QPixmapFilter;
+class QBlittable;
class Q_GUI_EXPORT QGraphicsSystem
{
@@ -67,7 +71,7 @@ public:
virtual QPixmapData *createPixmapData(QPixmapData *origin);
virtual QWindowSurface *createWindowSurface(QWidget *widget) const = 0;
- virtual ~QGraphicsSystem() = 0;
+ virtual ~QGraphicsSystem();
//### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed
// to have a graphics system.
diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp
index 22e947c73e..5605fc14cf 100644
--- a/src/gui/painting/qgraphicssystemfactory.cpp
+++ b/src/gui/painting/qgraphicssystemfactory.cpp
@@ -73,7 +73,7 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
if (system.isEmpty()) {
system = QLatin1String("runtime");
}
-#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN)
+#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) || defined(Q_WS_X11)
if (system.isEmpty()) {
system = QLatin1String("raster");
}
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index 08a6ef8726..e5e8ba4fa1 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -408,25 +408,31 @@
/* */
/* Record the current cell in the table. */
/* */
- static PCell
- gray_find_cell( RAS_ARG )
+ static void
+ gray_record_cell( RAS_ARG )
{
PCell *pcell, cell;
int x = ras.ex;
+ if ( ras.invalid || !( ras.area | ras.cover ) )
+ return;
if ( x > ras.max_ex )
x = ras.max_ex;
pcell = &ras.ycells[ras.ey];
+
for (;;)
{
cell = *pcell;
if ( cell == NULL || cell->x > x )
break;
- if ( cell->x == x )
- goto Exit;
+ if ( cell->x == x ) {
+ cell->area += ras.area;
+ cell->cover += ras.cover;
+ return;
+ }
pcell = &cell->next;
}
@@ -436,28 +442,11 @@
cell = ras.cells + ras.num_cells++;
cell->x = x;
- cell->area = 0;
- cell->cover = 0;
+ cell->area = ras.area;
+ cell->cover = ras.cover;
cell->next = *pcell;
*pcell = cell;
-
- Exit:
- return cell;
- }
-
-
- static void
- gray_record_cell( RAS_ARG )
- {
- if ( !ras.invalid && ( ras.area | ras.cover ) )
- {
- PCell cell = gray_find_cell( RAS_VAR );
-
-
- cell->area += ras.area;
- cell->cover += ras.cover;
- }
}
diff --git a/src/gui/painting/qgrayraster_p.h b/src/gui/painting/qgrayraster_p.h
index f2dd9d271e..b9a4aed66d 100644
--- a/src/gui/painting/qgrayraster_p.h
+++ b/src/gui/painting/qgrayraster_p.h
@@ -91,7 +91,7 @@
/* Minimum buffer size for raster object, that accounts
for TWorker and TCell sizes.*/
-#define MINIMUM_POOL_SIZE 4096
+#define MINIMUM_POOL_SIZE 8192
QT_FT_EXPORT_VAR( const QT_FT_Raster_Funcs ) qt_ft_grays_raster;
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 6e53c353cb..aac50838d7 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -47,8 +47,6 @@
QT_BEGIN_NAMESPACE
-static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-
#define qreal_to_fixed_26_6(f) (int(f * 64))
@@ -216,13 +214,6 @@ void QOutlineMapper::endOutline()
elements = m_elements_dev.data();
}
- if (m_round_coords) {
- // round coordinates to match outlines drawn with drawLine_midpoint_i
- for (int i = 0; i < m_elements.size(); ++i)
- elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta),
- qFloor(elements[i].y() + aliasedCoordinateDelta));
- }
-
controlPointRect = boundingRect(elements, element_count);
#ifdef QT_DEBUG_CONVERT
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index 0f2303ccbe..4dd28ac172 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -95,8 +95,7 @@ public:
m_tags(0),
m_contours(0),
m_polygon_dev(0),
- m_in_clip_elements(false),
- m_round_coords(false)
+ m_in_clip_elements(false)
{
}
@@ -202,8 +201,6 @@ public:
QT_FT_Outline *convertPath(const QPainterPath &path);
QT_FT_Outline *convertPath(const QVectorPath &path);
- void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; }
-
inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); }
public:
@@ -237,9 +234,6 @@ public:
bool m_valid;
bool m_in_clip_elements;
-
-private:
- bool m_round_coords;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 6ce21dce8f..fac356c1b7 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -130,7 +130,7 @@ QPaintBufferPrivate::~QPaintBufferPrivate()
for (int i = 0; i < commands.size(); ++i) {
const QPaintBufferCommand &cmd = commands.at(i);
if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem)
- delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset)));
+ delete reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(variants.at(cmd.offset)));
}
}
@@ -330,7 +330,7 @@ QString QPaintBuffer::commandDescription(int command) const
break; }
case QPaintBufferPrivate::Cmd_SetBrush: {
- QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset));
+ QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.offset));
debug << "Cmd_SetBrush: " << brush;
break; }
@@ -354,27 +354,27 @@ QString QPaintBuffer::commandDescription(int command) const
break; }
case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
- QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra));
+ QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.extra));
debug << "ExCmd_StrokeVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
<< "pts/elms:" << cmd.offset << cmd.offset2 << pen;
break; }
case QPaintBufferPrivate::Cmd_FillVectorPath: {
- QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra));
debug << "ExCmd_FillVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
<< "pts/elms:" << cmd.offset << cmd.offset2 << brush;
break; }
case QPaintBufferPrivate::Cmd_FillRectBrush: {
- QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
break; }
case QPaintBufferPrivate::Cmd_FillRectColor: {
- QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra));
+ QColor color = qvariant_cast<QColor>(d_ptr->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset);
debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
break; }
@@ -451,12 +451,12 @@ QString QPaintBuffer::commandDescription(int command) const
break; }
case QPaintBufferPrivate::Cmd_SetPen: {
- QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset));
+ QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.offset));
debug << "Cmd_SetPen: " << pen;
break; }
case QPaintBufferPrivate::Cmd_SetTransform: {
- QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset));
+ QTransform xform = qvariant_cast<QTransform>(d_ptr->variants.at(cmd.offset));
debug << "Cmd_SetTransform, offset: " << cmd.offset << xform;
break; }
@@ -532,7 +532,7 @@ QString QPaintBuffer::commandDescription(int command) const
case QPaintBufferPrivate::Cmd_DrawTextItem: {
QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
- QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset)));
+ QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d_ptr->variants.at(cmd.offset)));
QTextItemInt &ti = (*tiCopy)();
QString text(ti.text());
@@ -1287,7 +1287,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text();
#endif
if (m_stream_raw_text_items) {
- QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti)));
+ QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, QVariant::fromValue<void *>(new QTextItemIntCopy(ti)));
QFont font(ti.font());
font.setUnderline(false);
@@ -1429,7 +1429,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_SetPen: {
- QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset));
+ QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.offset));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_SetPen: " << pen;
#endif
@@ -1437,7 +1437,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_SetBrush: {
- QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset));
+ QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.offset));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_SetBrush: " << brush;
#endif
@@ -1452,7 +1452,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_SetTransform: {
- QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset));
+ QTransform xform = qvariant_cast<QTransform>(d->variants.at(cmd.offset));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform;
#endif
@@ -1520,7 +1520,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
- QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
+ QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
@@ -1531,7 +1531,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillVectorPath: {
- QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
@@ -1705,7 +1705,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillRectBrush: {
- QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
@@ -1714,7 +1714,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillRectColor: {
- QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
+ QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
@@ -1790,7 +1790,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
case QPaintBufferPrivate::Cmd_DrawTextItem: {
QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1));
- QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset)));
+ QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d->variants.at(cmd.offset)));
QTextItemInt &ti = (*tiCopy)();
QString text(ti.text());
@@ -1885,7 +1885,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_StrokeVectorPath: {
- QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra));
+ QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
@@ -1896,7 +1896,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillVectorPath: {
- QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size
// << ", hints:" << d->ints[cmd.offset2+cmd.size]
@@ -1907,7 +1907,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillRectBrush: {
- QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra));
+ QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush;
@@ -1916,7 +1916,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd)
break; }
case QPaintBufferPrivate::Cmd_FillRectColor: {
- QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra));
+ QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra));
QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset);
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color;
diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp
index 10463e0de1..f2ba7f0744 100644
--- a/src/gui/painting/qpaintdevice.cpp
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -59,11 +59,13 @@ QPaintDevice::~QPaintDevice()
}
+#ifndef Q_WS_QPA
int QPaintDevice::metric(PaintDeviceMetric) const
{
qWarning("QPaintDevice::metrics: Device has no metric information");
return 0;
}
+#endif
Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric)
{
diff --git a/src/gui/painting/qpaintdevice_qpa.cpp b/src/gui/painting/qpaintdevice_qpa.cpp
new file mode 100644
index 0000000000..0d1ca92d45
--- /dev/null
+++ b/src/gui/painting/qpaintdevice_qpa.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpaintdevice.h"
+#include "qpainter.h"
+#include "qwidget.h"
+#include "qbitmap.h"
+#include "qapplication.h"
+
+QT_BEGIN_NAMESPACE
+
+extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp
+
+int QPaintDevice::metric(PaintDeviceMetric m) const
+{
+ qWarning("QPaintDevice::metrics: Device has no metric information");
+ if (m == PdmDpiX) {
+ return 72;
+ } else if (m == PdmDpiY) {
+ return 72;
+ } else if (m == PdmNumColors) {
+ // FIXME: does this need to be a real value?
+ return 256;
+ } else {
+ qDebug("Unrecognised metric %d!",m);
+ return 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index f89a04672f..93aa63bea9 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -213,6 +213,7 @@ public:
OpenVG,
OpenGL2,
PaintBuffer,
+ Blitter,
User = 50, // first user type id
MaxUser = 100 // last user type id
@@ -270,6 +271,9 @@ private:
friend class QtopiaPrintEnginePrivate;
friend class QProxyFontEngine;
#endif
+#ifdef Q_WS_QPA
+ friend class QFontEngineQPA;
+#endif
friend class QPainter;
friend class QPainterPrivate;
friend class QWidget;
diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp
new file mode 100644
index 0000000000..2e8d9dd65e
--- /dev/null
+++ b/src/gui/painting/qpaintengine_blitter.cpp
@@ -0,0 +1,663 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qpaintengine_blitter_p.h"
+
+#include "private/qblittable_p.h"
+#include "private/qpaintengine_raster_p.h"
+#include "private/qpainter_p.h"
+#include "private/qapplication_p.h"
+#include "private/qpixmap_blitter_p.h"
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+#define STATE_XFORM_SCALE 0x00000001
+#define STATE_XFORM_COMPLEX 0x00000002
+
+#define STATE_BRUSH_PATTERN 0x00000010
+#define STATE_BRUSH_ALPHA 0x00000020
+
+#define STATE_PEN_ENABLED 0x00000100
+
+#define STATE_ANTIALIASING 0x00001000
+#define STATE_ALPHA 0x00002000
+#define STATE_BLENDING_COMPLEX 0x00004000
+
+#define STATE_CLIPSYS_COMPLEX 0x00010000
+#define STATE_CLIP_COMPLEX 0x00020000
+
+
+static inline void updateStateBits(uint *state, uint mask, bool on)
+{
+ *state = on ? (*state | mask) : (*state & ~mask);
+}
+
+static inline bool checkStateAgainstMask(uint state, uint mask)
+{
+ return !state || (state & mask && !(state & ~mask));
+}
+
+class CapabilitiesToStateMask
+{
+public:
+ CapabilitiesToStateMask(QBlittable::Capabilities capabilities)
+ : m_capabilities(capabilities),
+ fillRectMask(0),
+ drawRectMask(0),
+ drawPixmapMask(0),
+ capabillitiesState(0)
+ {
+ if (capabilities & QBlittable::SolidRectCapability) {
+ setFillRectMask();
+ }
+ if (capabilities & QBlittable::SourcePixmapCapability) {
+ setSourcePixmapMask();
+ }
+ if (capabilities & QBlittable::SourceOverPixmapCapability) {
+ setSourceOverPixmapMask();
+ }
+ if (capabilities & QBlittable::SourceOverScaledPixmapCapability) {
+ setSourceOverScaledPixmapMask();
+ }
+ }
+
+ inline bool canBlitterFillRect() const
+ {
+ return checkStateAgainstMask(capabillitiesState,fillRectMask);
+ }
+
+ inline bool canBlitterDrawRectMask() const
+ {
+ return checkStateAgainstMask(capabillitiesState,drawRectMask);
+ }
+
+ bool canBlitterDrawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) const
+ {
+ if (pm.pixmapData()->classId() != QPixmapData::BlitterClass)
+ return false;
+ if (checkStateAgainstMask(capabillitiesState,drawPixmapMask)) {
+ if (m_capabilities & (QBlittable::SourceOverPixmapCapability
+ | QBlittable::SourceOverScaledPixmapCapability)) {
+ if (r.size() != sr.size()) {
+ return m_capabilities & QBlittable::SourceOverScaledPixmapCapability;
+ } else {
+ return m_capabilities & QBlittable::SourceOverPixmapCapability;
+ }
+ }
+ if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel()) {
+ return m_capabilities & QBlittable::SourcePixmapCapability;
+ }
+ }
+ return false;
+ }
+
+ inline void updateState(uint mask, bool on) {
+ updateStateBits(&capabillitiesState,mask,on);
+ }
+
+public:
+
+ void setFillRectMask() {
+ updateStateBits(&fillRectMask, STATE_XFORM_SCALE, false);
+ updateStateBits(&fillRectMask, STATE_XFORM_COMPLEX, false);
+
+ updateStateBits(&fillRectMask, STATE_BRUSH_PATTERN, false);
+ updateStateBits(&fillRectMask, STATE_BRUSH_ALPHA, false);
+
+ updateStateBits(&fillRectMask, STATE_PEN_ENABLED, true);
+
+ //Sub-pixel aliasing should not be sent to the blitter
+ updateStateBits(&fillRectMask, STATE_ANTIALIASING, true);
+ updateStateBits(&fillRectMask, STATE_ALPHA, false);
+ updateStateBits(&fillRectMask, STATE_BLENDING_COMPLEX, false);
+
+ updateStateBits(&fillRectMask, STATE_CLIPSYS_COMPLEX, false);
+ updateStateBits(&fillRectMask, STATE_CLIP_COMPLEX, false);
+ }
+
+ void setSourcePixmapMask() {
+ updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true);
+ updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false);
+
+ updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true);
+ updateStateBits(&drawPixmapMask, STATE_BRUSH_ALPHA, false);
+
+ updateStateBits(&drawPixmapMask, STATE_PEN_ENABLED, true);
+
+ updateStateBits(&drawPixmapMask, STATE_ANTIALIASING, true);
+ updateStateBits(&drawPixmapMask, STATE_ALPHA, false);
+ updateStateBits(&drawPixmapMask, STATE_BLENDING_COMPLEX, false);
+
+ updateStateBits(&drawPixmapMask, STATE_CLIPSYS_COMPLEX, false);
+ updateStateBits(&drawPixmapMask, STATE_CLIP_COMPLEX, false);
+ }
+
+ void setSourceOverPixmapMask() {
+ setSourcePixmapMask();
+ }
+
+ void setSourceOverScaledPixmapMask() {
+ setSourceOverPixmapMask();
+ updateStateBits(&drawRectMask, STATE_XFORM_SCALE, true);
+ }
+
+ QBlittable::Capabilities m_capabilities;
+ uint fillRectMask;
+ uint drawRectMask;
+ uint drawPixmapMask;
+ uint capabillitiesState;
+};
+
+class QBlitterPaintEnginePrivate : public QPaintEngineExPrivate
+{
+ Q_DECLARE_PUBLIC(QBlitterPaintEngine);
+public:
+ QBlitterPaintEnginePrivate(QBlittablePixmapData *p)
+ : QPaintEngineExPrivate(),
+ pmData(p),
+ isBlitterLocked(false),
+ hasXForm(false)
+
+ {
+ raster = new QRasterPaintEngine(p->buffer());
+ capabillities = new CapabilitiesToStateMask(pmData->blittable()->capabilities());
+ }
+
+ inline void lock() {
+ if (!isBlitterLocked) {
+ raster->d_func()->rasterBuffer->prepare(pmData->blittable()->lock());
+ isBlitterLocked = true;
+ }
+ }
+
+ inline void unlock() {
+ if (isBlitterLocked) {
+ pmData->blittable()->unlock();
+ isBlitterLocked = false;
+ }
+ }
+
+ void fillRect(const QRectF &rect, const QColor &color) {
+ Q_Q(QBlitterPaintEngine);
+ pmData->unmarkRasterOverlay(rect);
+ QRectF targetRect = rect;
+ if (hasXForm) {
+ targetRect = q->state()->matrix.mapRect(rect);
+ }
+ const QClipData *clipData = q->clip();
+ if (clipData) {
+ if (clipData->hasRectClip) {
+ unlock();
+ pmData->blittable()->fillRect(targetRect & clipData->clipRect, color);
+ } else if (clipData->hasRegionClip) {
+ QVector<QRect> rects = clipData->clipRegion.rects();
+ for ( int i = 0; i < rects.size(); i++ ) {
+ QRect intersectRect = rects.at(i).intersected(targetRect.toRect());
+ if (!intersectRect.isEmpty()) {
+ unlock();
+ pmData->blittable()->fillRect(intersectRect,color);
+ }
+ }
+ }
+ } else {
+ if (targetRect.x() >= 0 && targetRect.y() >= 0
+ && targetRect.width() <= raster->paintDevice()->width()
+ && targetRect.height() <= raster->paintDevice()->height()) {
+ unlock();
+ pmData->blittable()->fillRect(targetRect,color);
+ } else {
+ QRectF deviceRect(0,0,raster->paintDevice()->width(), raster->paintDevice()->height());
+ unlock();
+ pmData->blittable()->fillRect(deviceRect&targetRect,color);
+ }
+ }
+ }
+
+ void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr) {
+ QRectF intersectedRect = clip.intersected(target);
+ if (intersectedRect.isEmpty())
+ return;
+ QRectF source = sr;
+ if(intersectedRect.size() != target.size()) {
+ qreal deltaTop = target.top() - intersectedRect.top();
+ qreal deltaLeft = target.left() - intersectedRect.left();
+ qreal deltaBottom = target.bottom() - intersectedRect.bottom();
+ qreal deltaRight = target.right() - intersectedRect.right();
+ source.adjust(-deltaLeft,-deltaTop,-deltaRight,-deltaBottom);
+ }
+ pmData->unmarkRasterOverlay(intersectedRect);
+ pmData->blittable()->drawPixmap(intersectedRect, pm, source);
+ }
+
+ void updateClip() {
+ Q_Q(QBlitterPaintEngine);
+ const QClipData *clip = q->clip();
+ bool complex = clip && !(clip->hasRectClip || clip->hasRegionClip);
+ capabillities->updateState(STATE_CLIP_COMPLEX, complex);
+ }
+
+ void systemStateChanged() {
+ raster->d_func()->systemStateChanged();
+ }
+
+ QRasterPaintEngine *raster;
+
+ QBlittablePixmapData *pmData;
+ bool isBlitterLocked;
+
+ CapabilitiesToStateMask *capabillities;
+
+ uint hasXForm;
+};
+
+QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePixmapData *p)
+ : QPaintEngineEx(*(new QBlitterPaintEnginePrivate(p)))
+{
+}
+
+QBlitterPaintEngine::~QBlitterPaintEngine()
+{
+}
+
+QPainterState *QBlitterPaintEngine::createState(QPainterState *orig) const
+{
+ Q_D(const QBlitterPaintEngine);
+ return d->raster->createState(orig);
+}
+
+bool QBlitterPaintEngine::begin(QPaintDevice *pdev)
+{
+ Q_D(QBlitterPaintEngine);
+
+ setActive(true);
+ bool ok = d->raster->begin(pdev);
+#ifdef QT_BLITTER_RASTEROVERLAY
+ d->pmData->unmergeOverlay();
+#endif
+ return ok;
+}
+
+
+bool QBlitterPaintEngine::end()
+{
+ Q_D(QBlitterPaintEngine);
+
+ setActive(false);
+#ifdef QT_BLITTER_RASTEROVERLAY
+ d->pmData->mergeOverlay();
+#endif
+ return d->raster->end();
+}
+
+
+void QBlitterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
+{
+ Q_D(QBlitterPaintEngine);
+ if (path.shape() == QVectorPath::RectangleHint) {
+ QRectF rect(((QPointF *) path.points())[0], ((QPointF *) path.points())[2]);
+ fillRect(rect, brush);
+ } else {
+ d->lock();
+ d->pmData->markRasterOverlay(path);
+ d->raster->fill(path, brush);
+ }
+}
+
+void QBlitterPaintEngine::fillRect(const QRectF &rect, const QColor &color)
+{
+ Q_D(QBlitterPaintEngine);
+ if (d->capabillities->canBlitterFillRect() && color.alpha() == 0xff) {
+ d->fillRect(rect, color);
+ } else {
+ d->lock();
+ d->pmData->markRasterOverlay(rect);
+ d->raster->fillRect(rect, color);
+ }
+}
+
+void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
+{
+ if(rect.size().isEmpty())
+ return;
+
+ Q_D(QBlitterPaintEngine);
+
+ if (qbrush_style(brush) == Qt::SolidPattern
+ && qbrush_color(brush).alpha() == 0xff
+ && d->capabillities->canBlitterFillRect())
+ {
+ d->fillRect(rect, qbrush_color(brush));
+ }else if (brush.style() == Qt::TexturePattern
+ && d->capabillities->canBlitterDrawPixmap(rect,brush.texture(),rect))
+ {
+ bool rectIsFilled = false;
+ QRectF transformedRect = state()->matrix.mapRect(rect);
+ qreal x = transformedRect.x();
+ qreal y = transformedRect.y();
+ QPixmap pm = brush.texture();
+ d->unlock();
+ int srcX = int(rect.x() - state()->brushOrigin.x()) % pm.width();
+ if (srcX < 0)
+ srcX = pm.width() + srcX;
+ const int startX = srcX;
+ int srcY = int(rect.y() - state()->brushOrigin.y()) % pm.height();
+ if (srcY < 0)
+ srcY = pm.height() + srcY;
+ while (!rectIsFilled) {
+ qreal blitWidth = (pm.width() ) - srcX;
+ qreal blitHeight = (pm.height() ) - srcY;
+ if (x + blitWidth > transformedRect.right())
+ blitWidth = transformedRect.right() -x;
+ if (y + blitHeight > transformedRect.bottom())
+ blitHeight = transformedRect.bottom() - y;
+ const QClipData *clipData = clip();
+ if (clipData->hasRectClip) {
+ QRect targetRect = QRect(x,y,blitWidth,blitHeight).intersected(clipData->clipRect);
+ if (targetRect.isValid()) {
+ int tmpSrcX = srcX + (targetRect.x() - x);
+ int tmpSrcY = srcY + (targetRect.y() - y);
+ QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height());
+ d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect);
+ }
+ } else if (clipData->hasRegionClip) {
+ QVector<QRect> clipRects = clipData->clipRegion.rects();
+ QRect unclippedTargetRect(x,y,blitWidth,blitHeight);
+ QRegion intersectedRects = clipData->clipRegion.intersected(unclippedTargetRect);
+
+ for ( int i = 0; i < intersectedRects.rects().size(); i++ ) {
+ QRect targetRect = intersectedRects.rects().at(i);
+ if (!targetRect.isValid() || targetRect.isEmpty())
+ continue;
+ int tmpSrcX = srcX + (targetRect.x() - x);
+ int tmpSrcY = srcY + (targetRect.y() - y);
+ QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height());
+ d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect);
+ }
+ }
+ x+=blitWidth;
+ if (x>=transformedRect.right()) {
+ x = transformedRect.x();
+ srcX = startX;
+ srcY = 0;
+ y+=blitHeight;
+ if (y>=transformedRect.bottom())
+ rectIsFilled = true;
+ } else
+ srcX = 0;
+ }
+ } else {
+ d->lock();
+ d->pmData->markRasterOverlay(rect);
+ d->raster->fillRect(rect, brush);
+ }
+
+}
+
+void QBlitterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->pmData->markRasterOverlay(path);
+ d->raster->stroke(path, pen);
+}
+
+void QBlitterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->clip(path, op);
+ d->updateClip();
+}
+void QBlitterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op){
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->clip(rect,op);
+ d->updateClip();
+}
+void QBlitterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->clip(region,op);
+ d->updateClip();
+}
+
+void QBlitterPaintEngine::clipEnabledChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->clipEnabledChanged();
+}
+
+void QBlitterPaintEngine::penChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->penChanged();
+ d->capabillities->updateState(STATE_PEN_ENABLED,qpen_style(state()->pen) != Qt::NoPen);
+}
+
+void QBlitterPaintEngine::brushChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->brushChanged();
+
+ bool solid = qbrush_style(state()->brush) == Qt::SolidPattern;
+
+ d->capabillities->updateState(STATE_BRUSH_PATTERN, !solid);
+ d->capabillities->updateState(STATE_BRUSH_ALPHA,
+ qbrush_color(state()->brush).alpha() < 255);
+}
+
+void QBlitterPaintEngine::brushOriginChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->brushOriginChanged();
+}
+
+void QBlitterPaintEngine::opacityChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->opacityChanged();
+
+ bool translucent = state()->opacity < 1;
+ d->capabillities->updateState(STATE_ALPHA,translucent);
+}
+
+void QBlitterPaintEngine::compositionModeChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->compositionModeChanged();
+
+ bool nonTrivial = state()->composition_mode != QPainter::CompositionMode_SourceOver
+ && state()->composition_mode != QPainter::CompositionMode_Source;
+
+ d->capabillities->updateState(STATE_BLENDING_COMPLEX,nonTrivial);
+}
+
+void QBlitterPaintEngine::renderHintsChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->renderHintsChanged();
+
+ bool aa = state()->renderHints & QPainter::Antialiasing;
+ d->capabillities->updateState(STATE_ANTIALIASING, aa);
+
+}
+
+void QBlitterPaintEngine::transformChanged()
+{
+ Q_D(QBlitterPaintEngine);
+ d->raster->transformChanged();
+
+ QTransform::TransformationType type = state()->matrix.type();
+
+ d->capabillities->updateState(STATE_XFORM_COMPLEX, type > QTransform::TxScale);
+ d->capabillities->updateState(STATE_XFORM_SCALE, type > QTransform::TxTranslate);
+
+ d->hasXForm = type >= QTransform::TxTranslate;
+
+}
+
+void QBlitterPaintEngine::drawRects(const QRect *rects, int rectCount)
+{
+ Q_D(QBlitterPaintEngine);
+ if (d->capabillities->canBlitterDrawRectMask()) {
+ for (int i=0; i<rectCount; ++i) {
+ d->fillRect(rects[i], qbrush_color(state()->brush));
+ }
+ } else {
+ d->pmData->markRasterOverlay(rects,rectCount);
+ QPaintEngineEx::drawRects(rects, rectCount);
+ }
+}
+
+void QBlitterPaintEngine::drawRects(const QRectF *rects, int rectCount)
+{
+ Q_D(QBlitterPaintEngine);
+ if (d->capabillities->canBlitterDrawRectMask()) {
+ for (int i=0; i<rectCount; ++i) {
+ d->fillRect(rects[i], qbrush_color(state()->brush));
+ }
+ } else {
+ d->pmData->markRasterOverlay(rects,rectCount);
+ QPaintEngineEx::drawRects(rects, rectCount);
+ }
+}
+
+void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
+{
+ Q_D(QBlitterPaintEngine);
+ if (d->capabillities->canBlitterDrawPixmap(r,pm,sr)) {
+
+ d->unlock();
+ QRectF targetRect = r;
+ if (d->hasXForm) {
+ targetRect = state()->matrix.mapRect(r);
+ }
+ const QClipData *clipData = clip();
+ if (clipData) {
+ if (clipData->hasRectClip) {
+ d->clipAndDrawPixmap(clipData->clipRect,targetRect,pm,sr);
+ }else if (clipData->hasRegionClip) {
+ QVector<QRect>rects = clipData->clipRegion.rects();
+ for (int i = 0; i<rects.size(); i++) {
+ d->clipAndDrawPixmap(rects.at(i),targetRect,pm,sr);
+ }
+ }
+ } else {
+ QRectF deviceRect(0,0,d->raster->paintDevice()->width(), d->raster->paintDevice()->height());
+ d->clipAndDrawPixmap(deviceRect,targetRect,pm,sr);
+ }
+ }else {
+ d->lock();
+ d->pmData->markRasterOverlay(r);
+ d->raster->drawPixmap(r, pm, sr);
+ }
+}
+
+void QBlitterPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
+ Qt::ImageConversionFlags flags)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->pmData->markRasterOverlay(r);
+ d->raster->drawImage(r, pm, sr, flags);
+}
+
+
+void QBlitterPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->drawTextItem(pos, ti);
+ d->pmData->markRasterOverlay(pos,ti);
+}
+
+void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->raster->drawStaticTextItem(sti);
+
+//#### d->pmData->markRasterOverlay(sti);
+ qWarning("not implemented: markRasterOverlay for QStaticTextItem");
+
+}
+
+
+void QBlitterPaintEngine::drawEllipse(const QRectF &r)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ d->pmData->markRasterOverlay(r);
+ d->raster->drawEllipse(r);
+}
+
+void QBlitterPaintEngine::setState(QPainterState *s)
+{
+ Q_D(QBlitterPaintEngine);
+ d->lock();
+ QPaintEngineEx::setState(s);
+ d->raster->setState(s);
+
+ clipEnabledChanged();
+ penChanged();
+ brushChanged();
+ brushOriginChanged();
+ opacityChanged();
+ compositionModeChanged();
+ renderHintsChanged();
+ transformChanged();
+
+ d->updateClip();
+}
+
+inline QRasterPaintEngine *QBlitterPaintEngine::raster() const
+{
+ Q_D(const QBlitterPaintEngine);
+ return d->raster;
+}
+
+QT_END_NAMESPACE
+#endif //QT_NO_BLITTABLE
+
diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h
new file mode 100644
index 0000000000..c8aa536fcd
--- /dev/null
+++ b/src/gui/painting/qpaintengine_blitter_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTENGINE_BLITTER_P_H
+#define QPAINTENGINE_BLITTER_P_H
+
+#include "private/qpaintengineex_p.h"
+#include "private/qpaintengine_raster_p.h"
+
+#ifndef QT_NO_BLITTABLE
+QT_BEGIN_NAMESPACE
+
+class QBlitterPaintEnginePrivate;
+class QBlittablePixmapData;
+class QBlittable;
+
+class Q_GUI_EXPORT QBlitterPaintEngine : public QPaintEngineEx
+{
+ Q_DECLARE_PRIVATE(QBlitterPaintEngine);
+public:
+ QBlitterPaintEngine(QBlittablePixmapData *p);
+ ~QBlitterPaintEngine();
+
+ virtual QPainterState *createState(QPainterState *orig) const;
+
+ virtual QPaintEngine::Type type() const { return Blitter; }
+
+ virtual bool begin(QPaintDevice *pdev);
+ virtual bool end();
+
+ virtual void fill(const QVectorPath &path, const QBrush &brush);
+ virtual void stroke(const QVectorPath &path, const QPen &pen);
+
+ virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
+ virtual void clip(const QRect &rect, Qt::ClipOperation op);
+ virtual void clip(const QRegion &region, Qt::ClipOperation op);
+
+ virtual void clipEnabledChanged();
+ virtual void penChanged();
+ virtual void brushChanged();
+ virtual void brushOriginChanged();
+ virtual void opacityChanged();
+ virtual void compositionModeChanged();
+ virtual void renderHintsChanged();
+ virtual void transformChanged();
+
+ virtual void fillRect(const QRectF &rect, const QBrush &brush);
+ virtual void fillRect(const QRectF &rect, const QColor &color);
+
+ virtual void drawRects(const QRect *rects, int rectCount);
+ virtual void drawRects(const QRectF *rects, int rectCount);
+
+ virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
+
+ virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags);
+
+ virtual void drawTextItem(const QPointF &pos, const QTextItem &ti);
+ virtual void drawStaticTextItem(QStaticTextItem *);
+
+ virtual void drawEllipse(const QRectF &r);
+
+ virtual void setState(QPainterState *s);
+
+ inline QPainterState *state() { return raster()->state(); }
+ inline const QPainterState *state() const { const QPainterState *state = raster()->state(); return state;}
+ inline const QClipData *clip(){return raster()->d_func()->clip();}
+
+private:
+ QRasterPaintEngine *raster() const;
+};
+
+QT_END_NAMESPACE
+#endif //QT_NO_BLITTABLE
+#endif // QPAINTENGINE_BLITTER_P_H
+
diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp
index c3aac1b12e..2f35dcd40a 100644
--- a/src/gui/painting/qpaintengine_mac.cpp
+++ b/src/gui/painting/qpaintengine_mac.cpp
@@ -57,6 +57,8 @@
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
+#include <private/qfontengine_coretext_p.h>
+#include <private/qfontengine_mac_p.h>
#include <private/qnumeric_p.h>
#include <private/qpainter_p.h>
#include <private/qpainterpath_p.h>
@@ -131,8 +133,9 @@ QMacCGContext::QMacCGContext(QPainter *p)
CGContextTranslateCTM(context, native.dx(), native.dy());
}
+ } else {
+ CGContextRetain(context);
}
- CGContextRetain(context);
}
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 682731ab04..47caa9f124 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -96,6 +96,8 @@
# include <private/qabstractfontengine_p.h>
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
# include <private/qfontengine_s60_p.h>
+#elif defined(Q_WS_QPA)
+# include <private/qfontengine_ft_p.h>
#endif
#if defined(Q_WS_WIN64)
@@ -124,9 +126,6 @@ void dumpClip(int width, int height, const QClipData *clip);
// 4 pixels.
#define int_dim(pos, dim) (int(pos+dim) - int(pos))
-// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
-static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-
#ifdef Q_WS_WIN
extern bool qt_cleartype_enabled;
#endif
@@ -444,7 +443,7 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
if (device->devType() == QInternal::Pixmap) {
QPixmap *pixmap = static_cast<QPixmap *>(device);
QPixmapData *pd = pixmap->pixmapData();
- if (pd->classId() == QPixmapData::RasterClass)
+ if (pd->classId() == QPixmapData::RasterClass || pd->classId() == QPixmapData::BlitterClass)
d->device = pd->buffer();
} else {
d->device = device;
@@ -663,31 +662,23 @@ QRasterPaintEngineState::QRasterPaintEngineState()
QRasterPaintEngineState::QRasterPaintEngineState(QRasterPaintEngineState &s)
: QPainterState(s)
+ , stroker(s.stroker)
+ , lastBrush(s.lastBrush)
+ , brushData(s.brushData)
+ , lastPen(s.lastPen)
+ , penData(s.penData)
+ , fillFlags(s.fillFlags)
+ , strokeFlags(s.strokeFlags)
+ , pixmapFlags(s.pixmapFlags)
+ , intOpacity(s.intOpacity)
+ , txscale(s.txscale)
+ , flag_bits(s.flag_bits)
+ , clip(s.clip)
+ , dirty(s.dirty)
{
- stroker = s.stroker;
-
- lastBrush = s.lastBrush;
- brushData = s.brushData;
brushData.tempImage = 0;
-
- lastPen = s.lastPen;
- penData = s.penData;
penData.tempImage = 0;
-
- fillFlags = s.fillFlags;
- strokeFlags = s.strokeFlags;
- pixmapFlags = s.pixmapFlags;
-
- intOpacity = s.intOpacity;
-
- txscale = s.txscale;
-
- flag_bits = s.flag_bits;
-
- clip = s.clip;
flags.has_clip_ownership = false;
-
- dirty = s.dirty;
}
/*!
@@ -1769,10 +1760,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- int x1 = qRound(rect.x() + aliasedCoordinateDelta);
- int y1 = qRound(rect.y() + aliasedCoordinateDelta);
- int x2 = qRound(rect.right() + aliasedCoordinateDelta);
- int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
+ int x1 = qRound(rect.x());
+ int y1 = qRound(rect.y());
+ int x2 = qRound(rect.right());
+ int y2 = qRound(rect.bottom());
if (x2 < x1)
qSwap(x1, x2);
@@ -2041,7 +2032,6 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly
*/
void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
{
- Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
#ifdef QT_DEBUG_DRAW
@@ -2062,9 +2052,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
if (mode != PolylineMode) {
// Do the fill...
if (s->brushData.blend) {
- d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque());
fillPolygon(points, pointCount, mode);
- d->outlineMapper->setCoordinateRounding(false);
}
}
@@ -2116,7 +2104,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
if (s->brushData.blend) {
// Compose polygon fill..,
ensureOutlineMapper();
- d->outlineMapper->setCoordinateRounding(s->penData.blend != 0);
d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
d->outlineMapper->moveTo(*points);
const QPoint *p = points;
@@ -2130,7 +2117,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
&s->brushData);
d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
- d->outlineMapper->setCoordinateRounding(false);
}
}
@@ -2178,13 +2164,11 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC
: LineDrawNormal);
int dashOffset = int(s->lastPen.dashOffset());
- const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta);
-
// Draw all the line segments.
for (int i=1; i<pointCount; ++i) {
- QPointF lp1 = points[i-1] * s->matrix + offs;
- QPointF lp2 = points[i] * s->matrix + offs;
+ QPointF lp1 = points[i-1] * s->matrix;
+ QPointF lp2 = points[i] * s->matrix;
const QRectF brect(lp1, lp2);
ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
@@ -2206,8 +2190,8 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC
// Polygons are implicitly closed.
if (needs_closing) {
- QPointF lp1 = points[pointCount-1] * s->matrix + offs;
- QPointF lp2 = points[0] * s->matrix + offs;
+ QPointF lp1 = points[pointCount-1] * s->matrix;
+ QPointF lp2 = points[0] * s->matrix;
const QRectF brect(lp1, lp2);
ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
@@ -2506,7 +2490,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
const QClipData *clip = d->clip();
QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy());
- if (s->flags.fast_images) {
+ if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
if (func) {
if (!clip) {
@@ -2595,10 +2579,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
int sr_b = qCeil(sr.bottom()) - 1;
if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
- // as fillRect will apply the aliased coordinate delta we need to
- // subtract it here as we don't use it for image drawing
QTransform old = s->matrix;
- s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta);
// Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied.
QRgb color = img.pixel(sr_l, sr_t);
@@ -2690,7 +2671,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
bool exceedsPrecision = targetBounds.width() > 0xffff
|| targetBounds.height() > 0xffff;
- if (s->flags.fast_images && !exceedsPrecision) {
+ if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
if (s->matrix.type() > QTransform::TxScale) {
SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()];
if (func && (!clip || clip->hasRectClip)) {
@@ -2742,11 +2723,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
d->initializeRasterizer(&d->image_filler_xform);
d->rasterizer->setAntialiased(s->flags.antialiased);
- const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta);
-
const QRectF &rect = r.normalized();
- const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs;
- const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs;
+ const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
+ const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
if (s->flags.tx_noshear)
d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
@@ -2755,18 +2734,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
return;
}
#endif
- const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta;
QPainterPath path;
path.addRect(r);
QTransform m = s->matrix;
s->matrix = QTransform(m.m11(), m.m12(), m.m13(),
m.m21(), m.m22(), m.m23(),
- m.m31() - offs, m.m32() - offs, m.m33());
+ m.m31(), m.m32(), m.m33());
fillPath(path, &d->image_filler_xform);
s->matrix = m;
} else {
-
- if (s->flags.fast_images) {
+ if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) {
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
if (func) {
QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy());
@@ -3115,6 +3092,7 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
}
cache->populate(fontEngine, numGlyphs, glyphs, positions);
+ cache->fillInPendingGlyphs();
const QImage &image = cache->image();
int bpl = image.bytesPerLine();
@@ -3129,13 +3107,21 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
int margin = cache->glyphMargin();
- const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
+ bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
const uchar *bits = image.bits();
for (int i=0; i<numGlyphs; ++i) {
- const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
- int x = qFloor(positions[i].x + offs) + c.baseLineX - margin;
- int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
+
+ QFixed subPixelPosition;
+ if (supportsSubPixelPositions)
+ subPixelPosition = cache->subPixelPositionForX(positions[i].x);
+ QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
+ const QTextureGlyphCache::Coord &c = cache->coords[glyph];
+ if (c.isNull())
+ continue;
+
+ int x = qFloor(positions[i].x) + c.baseLineX - margin;
+ int y = qFloor(positions[i].y) - c.baseLineY - margin;
// printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
// c.x, c.y,
@@ -3173,15 +3159,13 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti)
fe->setFontScale(matrix.m11());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
- const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta);
-
for (int i=0; i<glyphs.size(); ++i) {
TOpenFontCharMetrics tmetrics;
const TUint8 *glyphBitmapBytes;
TSize glyphBitmapSize;
fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize);
- const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta);
- const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta);
+ const int x = qFloor(positions[i].x + tmetrics.HorizBearingX());
+ const int y = qFloor(positions[i].y - tmetrics.HorizBearingY());
alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight);
}
@@ -3394,7 +3378,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
#if defined(Q_WS_QWS)
if (fontEngine->type() == QFontEngine::Box) {
- fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti);
+ fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti);
return;
}
@@ -3403,11 +3387,38 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
|| (fontEngine->type() == QFontEngine::Proxy
&& !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline()))
)) {
- fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti);
+ fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti);
return;
}
#endif // Q_WS_QWS
+#ifdef Q_WS_QPA
+ if (s->matrix.type() < QTransform::TxScale) {
+
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> glyphs;
+ QTransform matrix = state()->transform();
+
+ qreal _x = qFloor(p.x());
+ qreal _y = qFloor(p.y());
+ matrix.translate(_x, _y);
+
+ fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+ if (glyphs.size() == 0)
+ return;
+
+ for(int i = 0; i < glyphs.size(); i++) {
+ QImage img = fontEngine->alphaMapForGlyph(glyphs[i]);
+ glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
+ alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(),
+ qRound(positions[i].x + metrics.x),
+ qRound(positions[i].y + metrics.y),
+ img.width(), img.height());
+ }
+ return;
+ }
+#endif //Q_WS_QPA
+
#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
@@ -3464,7 +3475,6 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
return;
}
- QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
FT_Face lockedFace = 0;
int depth;
@@ -3512,8 +3522,8 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
};
alphaPenBlt(glyph->data, pitch, depth,
- qFloor(positions[i].x + offs) + glyph->x,
- qFloor(positions[i].y + offs) - glyph->y,
+ qFloor(positions[i].x) + glyph->x,
+ qFloor(positions[i].y) - glyph->y,
glyph->width, glyph->height);
}
if (lockedFace)
@@ -3650,8 +3660,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
int m11 = int(s->matrix.m11());
int m22 = int(s->matrix.m22());
- int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta);
- int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta);
+ int dx = qFloor(s->matrix.dx());
+ int dy = qFloor(s->matrix.dy());
for (int i=0; i<lineCount; ++i) {
int dashOffset = int(s->lastPen.dashOffset());
if (s->flags.int_xform) {
@@ -3755,7 +3765,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
for (int i=0; i<lineCount; ++i) {
int dashOffset = int(s->lastPen.dashOffset());
- QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta);
+ QLineF line = lines[i] * s->matrix;
const QRectF brect(QPointF(line.x1(), line.y1()),
QPointF(line.x2(), line.y2()));
ProcessSpans penBlend = d->getPenFunc(brect, &s->penData);
@@ -4289,11 +4299,19 @@ void QRasterPaintEnginePrivate::recalculateFastImages()
QRasterPaintEngineState *s = q->state();
s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform)
- && rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver
&& s->matrix.type() <= QTransform::TxShear;
}
+bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const
+{
+ Q_Q(const QRasterPaintEngine);
+ const QRasterPaintEngineState *s = q->state();
+ return s->flags.fast_images
+ && (mode == QPainter::CompositionMode_SourceOver
+ || (mode == QPainter::CompositionMode_Source
+ && !image.hasAlphaChannel()));
+}
QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color)
{
@@ -4620,38 +4638,40 @@ void QClipData::fixup()
return;
}
-// qDebug("QClipData::fixup: count=%d",count);
int y = -1;
ymin = m_spans[0].y;
ymax = m_spans[count-1].y + 1;
xmin = INT_MAX;
xmax = 0;
+ const int firstLeft = m_spans[0].x;
+ const int firstRight = m_spans[0].x + m_spans[0].len;
bool isRect = true;
- int left = m_spans[0].x;
- int right = m_spans[0].x + m_spans[0].len;
for (int i = 0; i < count; ++i) {
- if (m_spans[i].y != y) {
- if (m_spans[i].y != y + 1 && y != -1) {
+ QT_FT_Span_& span = m_spans[i];
+
+ if (span.y != y) {
+ if (span.y != y + 1 && y != -1)
isRect = false;
- }
- y = m_spans[i].y;
- m_clipLines[y].spans = m_spans+i;
- m_clipLines[y].count = 0;
-// qDebug() << " new line: y=" << y;
- }
- ++m_clipLines[y].count;
- int sl = (int) m_spans[i].x;
- int sr = sl + m_spans[i].len;
+ y = span.y;
+ m_clipLines[y].spans = &span;
+ m_clipLines[y].count = 1;
+ } else
+ ++m_clipLines[y].count;
+
+ const int spanLeft = span.x;
+ const int spanRight = spanLeft + span.len;
+
+ if (spanLeft < xmin)
+ xmin = spanLeft;
- xmin = qMin(xmin, (int)m_spans[i].x);
- xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len);
+ if (spanRight > xmax)
+ xmax = spanRight;
- if (sl != left || sr != right)
+ if (spanLeft != firstLeft || spanRight != firstRight)
isRect = false;
}
-// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : "");
if (isRect) {
hasRectClip = true;
@@ -4987,8 +5007,8 @@ protected:
int size, int opacity) const;
uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) {
if (cache.size() == maxCacheSize()) {
- int elem_to_remove = qrand() % maxCacheSize();
- cache.remove(cache.keys()[elem_to_remove]); // may remove more than 1, but OK
+ // may remove more than 1, but OK
+ cache.erase(cache.begin() + (qrand() % maxCacheSize()));
}
CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
generateGradientColorTable(gradient, cache_entry.buffer, paletteSize(), opacity);
@@ -5139,7 +5159,8 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
case Qt::SolidPattern: {
type = Solid;
QColor c = qbrush_color(brush);
- solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha));
+ QRgb rgba = c.rgba();
+ solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha));
if ((solid.color & 0xff000000) == 0
&& compositionMode == QPainter::CompositionMode_SourceOver) {
type = None;
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 6c2d28d00d..7f902a8ceb 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -254,6 +254,8 @@ protected:
QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *);
private:
friend struct QSpanData;
+ friend class QBlitterPaintEngine;
+ friend class QBlitterPaintEnginePrivate;
void init();
void fillRect(const QRectF &rect, QSpanData *data);
@@ -340,6 +342,7 @@ public:
void initializeRasterizer(QSpanData *data);
void recalculateFastImages();
+ bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const;
QPaintDevice *device;
QScopedPointer<QOutlineMapper> outlineMapper;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index a32443f75c..a5f4251074 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -61,6 +61,8 @@
#include "qstyle.h"
#include "qthread.h"
#include "qvarlengtharray.h"
+#include "qstatictext.h"
+#include "qglyphs.h"
#include <private/qfontengine_p.h>
#include <private/qpaintengine_p.h>
@@ -70,8 +72,8 @@
#include <private/qwidget_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
-#include <qstatictext.h>
#include <private/qstatictext_p.h>
+#include <private/qglyphs_p.h>
#include <private/qstylehelper_p.h>
QT_BEGIN_NAMESPACE
@@ -92,7 +94,7 @@ void qt_format_text(const QFont &font,
QPainter *painter);
static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
QTextCharFormat::UnderlineStyle underlineStyle,
- const QTextItem::RenderFlags flags, qreal width,
+ QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat);
// Helper function to calculate left most position, width and flags for decoration drawing
static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray,
@@ -149,6 +151,13 @@ static inline uint line_emulation(uint emulation)
| QPaintEngine_OpaqueBackground);
}
+static bool qt_paintengine_supports_transformations(QPaintEngine::Type type)
+{
+ return type == QPaintEngine::OpenGL2
+ || type == QPaintEngine::OpenVG
+ || type == QPaintEngine::OpenGL;
+}
+
#ifndef QT_NO_DEBUG
static bool qt_painter_thread_test(int devType, const char *what, bool extraCondition = false)
{
@@ -162,6 +171,10 @@ static bool qt_painter_thread_test(int devType, const char *what, bool extraCond
#endif
break;
default:
+#ifdef Q_WS_X11
+ if (QApplication::testAttribute(Qt::AA_X11InitThreads))
+ return true;
+#endif
if (!extraCondition && QThread::currentThread() != qApp->thread()) {
qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
return false;
@@ -2701,6 +2714,63 @@ QPainterPath QPainter::clipPath() const
}
/*!
+ Returns the bounding rectangle of the current clip if there is a clip;
+ otherwise returns an empty rectangle. Note that the clip region is
+ given in logical coordinates.
+
+ The bounding rectangle is not guaranteed to be tight.
+
+ \sa setClipRect(), setClipPath(), setClipRegion()
+
+ \since 4.8
+ */
+
+QRectF QPainter::clipBoundingRect() const
+{
+ Q_D(const QPainter);
+
+ if (!d->engine) {
+ qWarning("QPainter::clipBoundingRect: Painter not active");
+ return QRectF();
+ }
+
+ // Accumulate the bounding box in device space. This is not 100%
+ // precise, but it fits within the guarantee and it is resonably
+ // fast.
+ QRectF bounds;
+ for (int i=0; i<d->state->clipInfo.size(); ++i) {
+ QRectF r;
+ const QPainterClipInfo &info = d->state->clipInfo.at(i);
+
+ if (info.clipType == QPainterClipInfo::RectClip)
+ r = info.rect;
+ else if (info.clipType == QPainterClipInfo::RectFClip)
+ r = info.rectf;
+ else if (info.clipType == QPainterClipInfo::RegionClip)
+ r = info.region.boundingRect();
+ else
+ r = info.path.boundingRect();
+
+ r = info.matrix.mapRect(r);
+
+ if (i == 0)
+ bounds = r;
+ else if (info.operation == Qt::IntersectClip)
+ bounds &= r;
+ else if (info.operation == Qt::UniteClip)
+ bounds |= r;
+ }
+
+
+ // Map the rectangle back into logical space using the inverse
+ // matrix.
+ if (!d->txinv)
+ const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
+
+ return d->invMatrix.mapRect(bounds);
+}
+
+/*!
\fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
Enables clipping, and sets the clip region to the given \a
@@ -5256,7 +5326,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
#endif
if (d->extended) {
@@ -5326,7 +5396,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
if (!d->engine || pm.isNull())
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), "drawPixmap()", true);
#endif
qreal x = r.x();
@@ -5711,17 +5781,59 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
}
+/*!
+ Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
+ edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
+ selected on \a glyphs and at offsets given by the positions in \a glyphs.
+
+ \since 4.8
+
+ \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes()
+*/
+void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs)
+{
+ Q_D(QPainter);
+
+ QFont oldFont = d->state->font;
+ d->state->font = glyphs.font();
+
+ QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
+ QVector<QPointF> glyphPositions = glyphs.positions();
+
+ int count = qMin(glyphIndexes.size(), glyphPositions.size());
+ QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count);
+
+ bool paintEngineSupportsTransformations =
+ d->extended != 0
+ ? qt_paintengine_supports_transformations(d->extended->type())
+ : false;
+ for (int i=0; i<count; ++i) {
+ QPointF processedPosition = position + glyphPositions.at(i);
+ if (!paintEngineSupportsTransformations)
+ processedPosition = d->state->transform().map(processedPosition);
+ fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition);
+ }
+
+ d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count);
+
+ d->state->font = oldFont;
+}
void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
int glyphCount)
{
+ QVarLengthArray<QFixedPoint, 128> positions(glyphCount);
+ for (int i=0; i<glyphCount; ++i)
+ positions[i] = QFixedPoint::fromPointF(positionArray[i]);
+
QPainterPrivate *painter_d = QPainterPrivate::get(painter);
- painter_d->drawGlyphs(glyphArray, positionArray, glyphCount);
+ painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount);
}
-void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray,
- int glyphCount)
+void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount)
{
+ Q_Q(QPainter);
+
updateState(state);
QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
@@ -5736,12 +5848,27 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
}
- QVarLengthArray<QFixedPoint, 128> positions;
+ QFixed leftMost;
+ QFixed rightMost;
+ QFixed baseLine;
for (int i=0; i<glyphCount; ++i) {
- QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
- positions.append(fp);
+ glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]);
+ if (i == 0 || leftMost > positions[i].x)
+ leftMost = positions[i].x;
+
+ // We don't support glyphs that do not share a common baseline. If this turns out to
+ // be a relevant use case, then we need to find clusters of glyphs that share a baseline
+ // and do a drawTextItemDecorations call per cluster.
+ if (i == 0 || baseLine < positions[i].y)
+ baseLine = positions[i].y;
+
+ // We use the advance rather than the actual bounds to match the algorithm in drawText()
+ if (i == 0 || rightMost < positions[i].x + gm.xoff)
+ rightMost = positions[i].x + gm.xoff;
}
+ QFixed width = rightMost - leftMost;
+
if (extended != 0) {
QStaticTextItem staticTextItem;
staticTextItem.color = state->pen.color();
@@ -5749,7 +5876,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
staticTextItem.setFontEngine(fontEngine);
staticTextItem.numGlyphs = glyphCount;
staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
- staticTextItem.glyphPositions = positions.data();
+ staticTextItem.glyphPositions = positions;
extended->drawStaticTextItem(&staticTextItem);
} else {
@@ -5766,7 +5893,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
textItem.glyphs.numGlyphs = glyphCount;
textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
- textItem.glyphs.offsets = positions.data();
+ textItem.glyphs.offsets = positions;
textItem.glyphs.advances_x = advances.data();
textItem.glyphs.advances_y = advances.data();
textItem.glyphs.justifications = glyphJustifications.data();
@@ -5774,6 +5901,21 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
engine->drawTextItem(QPointF(0, 0), textItem);
}
+
+ QTextItemInt::RenderFlags flags;
+ if (state->font.underline())
+ flags |= QTextItemInt::Underline;
+ if (state->font.overline())
+ flags |= QTextItemInt::Overline;
+ if (state->font.strikeOut())
+ flags |= QTextItemInt::StrikeOut;
+
+ drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()),
+ fontEngine,
+ (state->font.underline()
+ ? QTextCharFormat::SingleUnderline
+ : QTextCharFormat::NoUnderline),
+ flags, width.toReal(), QTextCharFormat());
}
/*!
@@ -5862,10 +6004,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
return;
}
- bool paintEngineSupportsTransformations = d->extended->type() == QPaintEngine::OpenGL2
- || d->extended->type() == QPaintEngine::OpenVG
- || d->extended->type() == QPaintEngine::OpenGL;
-
+ bool paintEngineSupportsTransformations = qt_paintengine_supports_transformations(d->extended->type());
if (paintEngineSupportsTransformations && !staticText_d->untransformedCoordinates) {
staticText_d->untransformedCoordinates = true;
staticText_d->needsRelayout = true;
@@ -6309,7 +6448,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe,
QTextCharFormat::UnderlineStyle underlineStyle,
- const QTextItem::RenderFlags flags, qreal width,
+ QTextItem::RenderFlags flags, qreal width,
const QTextCharFormat &charFormat)
{
if (underlineStyle == QTextCharFormat::NoUnderline
@@ -6697,7 +6836,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()");
+ qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true);
#endif
qreal sw = pixmap.width();
@@ -7877,7 +8016,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
}
void qt_format_text(const QFont &fnt, const QRectF &_r,
int tf, const QTextOption *option, const QString& str, QRectF *brect,
- int tabstops, int *, int tabarraylen,
+ int tabstops, int *ta, int tabarraylen,
QPainter *painter)
{
@@ -7997,6 +8136,16 @@ start_lengthVariant:
engine.option = *option;
}
+ if (engine.option.tabStop() < 0 && tabstops > 0)
+ engine.option.setTabStop(tabstops);
+
+ if (engine.option.tabs().isEmpty() && ta) {
+ QList<qreal> tabs;
+ for (int i = 0; i < tabarraylen; i++)
+ tabs.append(qreal(ta[i]));
+ engine.option.setTabArray(tabs);
+ }
+
engine.option.setTextDirection(layout_direction);
if (tf & Qt::AlignJustify)
engine.option.setAlignment(Qt::AlignJustify);
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 0d7829e327..ae2fdf2055 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -79,6 +79,7 @@ class QTextItem;
class QMatrix;
class QTransform;
class QStaticText;
+class QGlyphs;
class QPainterPrivateDeleter;
@@ -221,6 +222,8 @@ public:
void setClipping(bool enable);
bool hasClipping() const;
+ QRectF clipBoundingRect() const;
+
void save();
void restore();
@@ -396,6 +399,8 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
+ void drawGlyphs(const QPointF &position, const QGlyphs &glyphs);
+
void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
inline void drawStaticText(int left, int top, const QStaticText &staticText);
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 0e0c11f939..26d8fc3cc7 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE
class QPaintEngine;
class QEmulationPaintEngine;
class QPaintEngineEx;
+struct QFixedPoint;
struct QTLWExtra;
@@ -228,7 +229,7 @@ public:
void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
- void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount);
+ void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount);
void updateMatrix();
void updateInvMatrix();
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 7ecf10a1ff..fddc4d07fc 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -576,6 +576,14 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other)
}
/*!
+ \fn void QPainterPath::swap(QPainterPath &other)
+ \since 4.8
+
+ Swaps painter path \a other with this painter path. This operation is very
+ fast and never fails.
+*/
+
+/*!
Destroys this QPainterPath object.
*/
QPainterPath::~QPainterPath()
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 4d166af517..3c23282d8e 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -95,7 +95,12 @@ public:
explicit QPainterPath(const QPointF &startPoint);
QPainterPath(const QPainterPath &other);
QPainterPath &operator=(const QPainterPath &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPainterPath &operator=(QPainterPath &&other)
+ { qSwap(d_ptr, other.d_ptr); return *this; }
+#endif
~QPainterPath();
+ inline void swap(QPainterPath &other) { d_ptr.swap(other.d_ptr); }
void closeSubpath();
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 4e8408b7b4..bc30038139 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -915,7 +915,6 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize)
return psToStr[paperSize];
}
-
// -------------------------- base engine, shared code between PS and PDF -----------------------
QPdfBaseEngine::QPdfBaseEngine(QPdfBaseEnginePrivate &dd, PaintEngineFeatures f)
@@ -1157,6 +1156,8 @@ void QPdfBaseEngine::updateState(const QPaintEngineState &state)
}
if (flags & DirtyBrush) {
d->brush = state.brush();
+ if (d->brush.color().alpha() == 0 && d->brush.style() == Qt::SolidPattern)
+ d->brush.setStyle(Qt::NoBrush);
d->hasBrush = d->brush.style() != Qt::NoBrush;
}
if (flags & DirtyBrushOrigin) {
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 08f9504772..b69458dca5 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -383,6 +383,14 @@ QPen &QPen::operator=(const QPen &p)
}
/*!
+ \fn void QPen::swap(QPen &other)
+ \since 4.8
+
+ Swaps pen \a other with this pen. This operation is very
+ fast and never fails.
+*/
+
+/*!
Returns the pen as a QVariant.
*/
QPen::operator QVariant() const
diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h
index 4298f81b00..001cd448e0 100644
--- a/src/gui/painting/qpen.h
+++ b/src/gui/painting/qpen.h
@@ -74,6 +74,11 @@ public:
~QPen();
QPen &operator=(const QPen &pen);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QPen &operator=(QPen &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QPen &other) { qSwap(d, other.d); }
Qt::PenStyle style() const;
void setStyle(Qt::PenStyle);
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index 0cf2ef5bf4..41b686adef 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -700,6 +700,22 @@ QPolygon QPolygonF::toPolygon() const
}
/*!
+ \fn void QPolygon::swap(QPolygon &other)
+ \since 4.8
+
+ Swaps polygon \a other with this polygon. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ \fn void QPolygonF::swap(QPolygonF &other)
+ \since 4.8
+
+ Swaps polygon \a other with this polygon. This operation is very
+ fast and never fails.
+*/
+
+/*!
Returns the polygon as a QVariant
*/
QPolygon::operator QVariant() const
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index b89b2a5268..0f4a8b3450 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -67,6 +67,8 @@ public:
inline QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {}
QPolygon(const QRect &r, bool closed=false);
QPolygon(int nPoints, const int *points);
+ inline void swap(QPolygon &other) { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps
+
operator QVariant() const;
void translate(int dx, int dy);
@@ -139,6 +141,7 @@ public:
inline QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {}
QPolygonF(const QRectF &r);
QPolygonF(const QPolygon &a);
+ inline void swap(QPolygonF &other) { QVector<QPointF>::swap(other); } // prevent QVector<QPointF><->QPolygonF swaps
inline void translate(qreal dx, qreal dy);
void translate(const QPointF &offset);
diff --git a/src/gui/painting/qprinterinfo.qdoc b/src/gui/painting/qprinterinfo.cpp
index c3c0f83f91..f680ce1950 100644
--- a/src/gui/painting/qprinterinfo.qdoc
+++ b/src/gui/painting/qprinterinfo.cpp
@@ -25,6 +25,16 @@
**
****************************************************************************/
+#include "qprinterinfo.h"
+#include "qprinterinfo_p.h"
+
+#ifndef QT_NO_PRINTER
+
+QT_BEGIN_NAMESPACE
+
+QPrinterInfoPrivate QPrinterInfoPrivate::shared_null;
+
+
/*!
\class QPrinterInfo
@@ -59,60 +69,94 @@
*/
/*!
- \fn QPrinterInfo::QPrinterInfo()
-
Constructs an empty QPrinterInfo object.
\sa isNull()
*/
+QPrinterInfo::QPrinterInfo()
+ : d_ptr(&QPrinterInfoPrivate::shared_null)
+{
+}
/*!
- \fn QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
-
- Constructs a copy of \a src.
+ Constructs a copy of \a other.
*/
+QPrinterInfo::QPrinterInfo(const QPrinterInfo &other)
+ : d_ptr(new QPrinterInfoPrivate(*other.d_ptr))
+{
+}
/*!
- \fn QPrinterInfo::QPrinterInfo(const QPrinter& printer)
-
Constructs a QPrinterInfo object from \a printer.
*/
+QPrinterInfo::QPrinterInfo(const QPrinter &printer)
+ : d_ptr(&QPrinterInfoPrivate::shared_null)
+{
+ foreach (const QPrinterInfo &printerInfo, availablePrinters()) {
+ if (printerInfo.printerName() == printer.printerName()) {
+ d_ptr.reset(new QPrinterInfoPrivate(*printerInfo.d_ptr));
+ break;
+ }
+ }
+}
/*!
- \fn QPrinterInfo::~QPrinterInfo()
+ \internal
+*/
+QPrinterInfo::QPrinterInfo(const QString &name)
+ : d_ptr(new QPrinterInfoPrivate(name))
+{
+}
+/*!
Destroys the QPrinterInfo object. References to the values in the
object become invalid.
*/
+QPrinterInfo::~QPrinterInfo()
+{
+}
/*!
- \fn QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
-
- Sets the QPrinterInfo object to be equal to \a src.
+ Sets the QPrinterInfo object to be equal to \a other.
*/
+QPrinterInfo &QPrinterInfo::operator=(const QPrinterInfo &other)
+{
+ Q_ASSERT(d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*other.d_ptr));
+ return *this;
+}
/*!
- \fn QString QPrinterInfo::printerName() const
-
Returns the name of the printer.
\sa QPrinter::setPrinterName()
*/
+QString QPrinterInfo::printerName() const
+{
+ const Q_D(QPrinterInfo);
+ return d->name;
+}
/*!
- \fn bool QPrinterInfo::isNull() const
-
Returns whether this QPrinterInfo object holds a printer definition.
An empty QPrinterInfo object could result for example from calling
defaultPrinter() when there are no printers on the system.
*/
+bool QPrinterInfo::isNull() const
+{
+ const Q_D(QPrinterInfo);
+ return d == &QPrinterInfoPrivate::shared_null;
+}
/*!
- \fn bool QPrinterInfo::isDefault() const
-
Returns whether this printer is the default printer.
*/
+bool QPrinterInfo::isDefault() const
+{
+ const Q_D(QPrinterInfo);
+ return d->isDefault;
+}
/*!
\fn QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
@@ -123,3 +167,7 @@
Not all printer drivers support this query, so the list may be empty.
On Mac OS X 10.3, this function always returns an empty list.
*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprinterinfo.h b/src/gui/painting/qprinterinfo.h
index 2ac07a8e5f..34379613de 100644
--- a/src/gui/painting/qprinterinfo.h
+++ b/src/gui/painting/qprinterinfo.h
@@ -42,9 +42,10 @@
#ifndef QPRINTERINFO_H
#define QPRINTERINFO_H
-#include <QtGui/QPrinter>
#include <QtCore/QList>
+#include <QtGui/QPrinter>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -56,15 +57,13 @@ class QPrinterInfoPrivate;
class QPrinterInfoPrivateDeleter;
class Q_GUI_EXPORT QPrinterInfo
{
-Q_DECLARE_PRIVATE(QPrinterInfo)
-
public:
QPrinterInfo();
- QPrinterInfo(const QPrinterInfo& src);
- QPrinterInfo(const QPrinter& printer);
+ QPrinterInfo(const QPrinterInfo &other);
+ QPrinterInfo(const QPrinter &printer);
~QPrinterInfo();
- QPrinterInfo& operator=(const QPrinterInfo& src);
+ QPrinterInfo &operator=(const QPrinterInfo &other);
QString printerName() const;
bool isNull() const;
@@ -75,8 +74,10 @@ public:
static QPrinterInfo defaultPrinter();
private:
- QPrinterInfo(const QString& name);
+ QPrinterInfo(const QString &name);
+private:
+ Q_DECLARE_PRIVATE(QPrinterInfo)
QScopedPointer<QPrinterInfoPrivate, QPrinterInfoPrivateDeleter> d_ptr;
};
diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp
index bafe2b2457..b24ab70267 100644
--- a/src/gui/painting/qprinterinfo_mac.cpp
+++ b/src/gui/painting/qprinterinfo_mac.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qprinterinfo.h"
+#include "qprinterinfo_p.h"
#include "private/qt_mac_p.h"
@@ -47,189 +48,71 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PRINTER
-class QPrinterInfoPrivate
-{
-Q_DECLARE_PUBLIC(QPrinterInfo)
-public:
- ~QPrinterInfoPrivate();
- QPrinterInfoPrivate();
- QPrinterInfoPrivate(const QString& name);
-
-private:
- QPrinterInfo* q_ptr;
-
- QString m_name;
- bool m_default;
- bool m_isNull;
-};
-
-static QPrinterInfoPrivate nullQPrinterInfoPrivate;
-
-class QPrinterInfoPrivateDeleter
-{
-public:
- static inline void cleanup(QPrinterInfoPrivate *d)
- {
- if (d != &nullQPrinterInfoPrivate)
- delete d;
- }
-};
-
-extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size);
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
+extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF &size);
QList<QPrinterInfo> QPrinterInfo::availablePrinters()
{
QList<QPrinterInfo> printers;
- OSStatus status = noErr;
- QCFType<CFArrayRef> printerList;
- status = PMServerCreatePrinterList(kPMServerLocal, &printerList);
- if (status == noErr) {
- CFIndex count = CFArrayGetCount(printerList);
- for (CFIndex i=0; i<count; ++i) {
- PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i)));
- QString name = QCFString::toQString(PMPrinterGetName(printer));
- printers.append(QPrinterInfo(name));
- if (PMPrinterIsDefault(printer)) {
- printers[i].d_ptr->m_default = true;
- }
+ QCFType<CFArrayRef> array;
+ if (PMServerCreatePrinterList(kPMServerLocal, &array) == noErr) {
+ CFIndex count = CFArrayGetCount(array);
+ for (int i = 0; i < count; ++i) {
+ PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
+ QString printerName = QCFString::toQString(PMPrinterGetName(printer));
+
+ QPrinterInfo printerInfo(printerName);
+ if (PMPrinterIsDefault(printer))
+ printerInfo.d_ptr->isDefault = true;
+ printers.append(printerInfo);
}
}
return printers;
}
-QPrinterInfo QPrinterInfo::defaultPrinter(){
- QList<QPrinterInfo> printers = availablePrinters();
- for (int c = 0; c < printers.size(); ++c) {
- if (printers[c].isDefault()) {
- return printers[c];
- }
- }
- return QPrinterInfo();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-QPrinterInfo::QPrinterInfo(const QPrinter& prn)
- : d_ptr(&nullQPrinterInfoPrivate)
+QPrinterInfo QPrinterInfo::defaultPrinter()
{
- QList<QPrinterInfo> list = availablePrinters();
- for (int c = 0; c < list.size(); ++c) {
- if (prn.printerName() == list[c].printerName()) {
- *this = list[c];
- return;
- }
+ QList<QPrinterInfo> printers = availablePrinters();
+ foreach (const QPrinterInfo &printerInfo, printers) {
+ if (printerInfo.isDefault())
+ return printerInfo;
}
-}
-
-QPrinterInfo::~QPrinterInfo()
-{
-}
-
-QPrinterInfo::QPrinterInfo()
- : d_ptr(&nullQPrinterInfoPrivate)
-{
-}
-
-QPrinterInfo::QPrinterInfo(const QString& name)
- : d_ptr(new QPrinterInfoPrivate(name))
-{
- d_ptr->q_ptr = this;
-}
-
-QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
- : d_ptr(&nullQPrinterInfoPrivate)
-{
- *this = src;
-}
-
-QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
-{
- Q_ASSERT(d_ptr);
- d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
- d_ptr->q_ptr = this;
- return *this;
-}
-
-QString QPrinterInfo::printerName() const
-{
- const Q_D(QPrinterInfo);
- return d->m_name;
-}
-bool QPrinterInfo::isNull() const
-{
- const Q_D(QPrinterInfo);
- return d->m_isNull;
-}
-
-bool QPrinterInfo::isDefault() const
-{
- const Q_D(QPrinterInfo);
- return d->m_default;
+ return printers.value(0);
}
QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
const Q_D(QPrinterInfo);
- PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->m_name));
+ QList<QPrinter::PaperSize> paperSizes;
+ if (isNull())
+ return paperSizes;
- if (!cfPrn) return QList<QPrinter::PaperSize>();
+ PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->name));
+ if (!cfPrn)
+ return paperSizes;
CFArrayRef array;
- OSStatus status = PMPrinterGetPaperList(cfPrn, &array);
-
- if (status != 0) {
+ if (PMPrinterGetPaperList(cfPrn, &array) != noErr) {
PMRelease(cfPrn);
- return QList<QPrinter::PaperSize>();
+ return paperSizes;
}
- QList<QPrinter::PaperSize> paperList;
int count = CFArrayGetCount(array);
- for (int c = 0; c < count; c++) {
- PMPaper paper = static_cast<PMPaper>(
- const_cast<void*>(
- CFArrayGetValueAtIndex(array, c)));
+ for (int i = 0; i < count; ++i) {
+ PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i)));
double width, height;
- status = PMPaperGetWidth(paper, &width);
- status |= PMPaperGetHeight(paper, &height);
- if (status != 0) continue;
-
- QSizeF size(width * 0.3527, height * 0.3527);
- paperList.append(qSizeFTopaperSize(size));
+ if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
+ QSizeF size(width * 0.3527, height * 0.3527);
+ paperSizes.append(qSizeFTopaperSize(size));
+ }
}
PMRelease(cfPrn);
- return paperList;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-QPrinterInfoPrivate::QPrinterInfoPrivate() :
- q_ptr(NULL),
- m_default(false),
- m_isNull(true)
-{
-}
-
-QPrinterInfoPrivate::QPrinterInfoPrivate(const QString& name) :
- q_ptr(NULL),
- m_name(name),
- m_default(false),
- m_isNull(false)
-{
-}
-
-QPrinterInfoPrivate::~QPrinterInfoPrivate()
-{
+ return paperSizes;
}
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprinterinfo_p.h b/src/gui/painting/qprinterinfo_p.h
new file mode 100644
index 0000000000..7781d59623
--- /dev/null
+++ b/src/gui/painting/qprinterinfo_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPRINTERINFO_P_H
+#define QPRINTERINFO_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qglobal.h"
+
+#ifndef QT_NO_PRINTER
+
+#include "QtCore/qlist.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPrinterInfoPrivate
+{
+public:
+ QPrinterInfoPrivate(const QString& name = QString()) :
+ name(name), isDefault(false)
+#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA)
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ , cupsPrinterIndex(0), hasPaperSizes(false)
+#endif
+#endif
+ {}
+ ~QPrinterInfoPrivate()
+ {}
+
+ static QPrinterInfoPrivate shared_null;
+
+ QString name;
+ bool isDefault;
+
+#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)) || defined(Q_WS_QPA)
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ int cupsPrinterIndex;
+ mutable bool hasPaperSizes;
+ mutable QList<QPrinter::PaperSize> paperSizes;
+#endif
+#endif
+};
+
+
+class QPrinterInfoPrivateDeleter
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &QPrinterInfoPrivate::shared_null)
+ delete d;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PRINTER
+
+#endif // QPRINTERINFO_P_H
diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp
index ed8ce80fa9..38e9590b1d 100644
--- a/src/gui/painting/qprinterinfo_unix.cpp
+++ b/src/gui/painting/qprinterinfo_unix.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qprinterinfo.h"
+#include "qprinterinfo_p.h"
#include <qfile.h>
#include <qfileinfo.h>
@@ -60,42 +61,66 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PRINTER
-class QPrinterInfoPrivate
-{
-Q_DECLARE_PUBLIC(QPrinterInfo)
-public:
- QPrinterInfoPrivate();
- QPrinterInfoPrivate(const QString& name);
- ~QPrinterInfoPrivate();
-
- static QPrinter::PaperSize string2PaperSize(const QString& str);
- static QString pageSize2String(QPrinter::PaperSize size);
-
-private:
- QString m_name;
- bool m_isNull;
- bool m_default;
- mutable bool m_mustGetPaperSizes;
- mutable QList<QPrinter::PaperSize> m_paperSizes;
- int m_cupsPrinterIndex;
-
- QPrinterInfo* q_ptr;
+#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+// preserver names in ascending order for the binary search
+static const struct NamedPaperSize {
+ const char *const name;
+ QPrinter::PaperSize size;
+} named_sizes_map[QPrinter::NPageSize] = {
+ { "A0", QPrinter::A0 },
+ { "A1", QPrinter::A1 },
+ { "A2", QPrinter::A2 },
+ { "A3", QPrinter::A3 },
+ { "A4", QPrinter::A4 },
+ { "A5", QPrinter::A5 },
+ { "A6", QPrinter::A6 },
+ { "A7", QPrinter::A7 },
+ { "A8", QPrinter::A8 },
+ { "A9", QPrinter::A9 },
+ { "B0", QPrinter::B0 },
+ { "B1", QPrinter::B1 },
+ { "B10", QPrinter::B10 },
+ { "B2", QPrinter::B2 },
+ { "B4", QPrinter::B4 },
+ { "B5", QPrinter::B5 },
+ { "B6", QPrinter::B6 },
+ { "B7", QPrinter::B7 },
+ { "B8", QPrinter::B8 },
+ { "B9", QPrinter::B9 },
+ { "C5E", QPrinter::C5E },
+ { "Comm10E", QPrinter::Comm10E },
+ { "Custom", QPrinter::Custom },
+ { "DLE", QPrinter::DLE },
+ { "Executive", QPrinter::Executive },
+ { "Folio", QPrinter::Folio },
+ { "Ledger", QPrinter::Ledger },
+ { "Legal", QPrinter::Legal },
+ { "Letter", QPrinter::Letter },
+ { "Tabloid", QPrinter::Tabloid }
};
-static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+inline bool operator<(const char *name, const NamedPaperSize &data)
+{ return qstrcmp(name, data.name) < 0; }
+inline bool operator<(const NamedPaperSize &data, const char *name)
+{ return qstrcmp(data.name, name) < 0; }
-class QPrinterInfoPrivateDeleter
+static inline QPrinter::PaperSize string2PaperSize(const char *name)
{
-public:
- static inline void cleanup(QPrinterInfoPrivate *d)
- {
- if (d != &nullQPrinterInfoPrivate)
- delete d;
- }
-};
+ const NamedPaperSize *r = qBinaryFind(named_sizes_map, named_sizes_map + QPrinter::NPageSize, name);
+ if (r - named_sizes_map != QPrinter::NPageSize)
+ return r->size;
+ return QPrinter::Custom;
+}
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
+static inline const char *paperSize2String(QPrinter::PaperSize size)
+{
+ for (int i = 0; i < QPrinter::NPageSize; ++i) {
+ if (size == named_sizes_map[i].size)
+ return named_sizes_map[i].name;
+ }
+ return 0;
+}
+#endif
void qt_perhapsAddPrinter(QList<QPrinterDescription> *printers, const QString &name,
QString host, QString comment,
@@ -784,12 +809,12 @@ int qt_getLprPrinters(QList<QPrinterDescription>& printers)
#endif
}
+ QRegExp ps(QLatin1String("[^a-z]ps(?:[^a-z]|$)"));
+ QRegExp lp(QLatin1String("[^a-z]lp(?:[^a-z]|$)"));
+
int quality = 0;
int best = 0;
for (int i = 0; i < printers.size(); ++i) {
- QRegExp ps(QLatin1String("[^a-z]ps(?:[^a-z]|$)"));
- QRegExp lp(QLatin1String("[^a-z]lp(?:[^a-z]|$)"));
-
QString name = printers.at(i).name;
QString comment = printers.at(i).comment;
if (quality < 5 && name == dollarPrinter) {
@@ -824,331 +849,77 @@ int qt_getLprPrinters(QList<QPrinterDescription>& printers)
QList<QPrinterInfo> QPrinterInfo::availablePrinters()
{
- QList<QPrinterInfo> list;
+ QList<QPrinterInfo> printers;
#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
- QCUPSSupport cups;
if (QCUPSSupport::isAvailable()) {
- //const ppd_file_t* cupsPPD = cups.currentPPD();
+ QCUPSSupport cups;
int cupsPrinterCount = cups.availablePrintersCount();
const cups_dest_t* cupsPrinters = cups.availablePrinters();
-
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
- list.append(QPrinterInfo(printerName));
+
+ QPrinterInfo printerInfo(printerName);
if (cupsPrinters[i].is_default)
- list[i].d_ptr->m_default = true;
- list[i].d_ptr->m_cupsPrinterIndex = i;
+ printerInfo.d_ptr->isDefault = true;
+ printerInfo.d_ptr->cupsPrinterIndex = i;
+ printers.append(printerInfo);
}
- } else {
+ } else
#endif
+ {
QList<QPrinterDescription> lprPrinters;
int defprn = qt_getLprPrinters(lprPrinters);
// populating printer combo
- QList<QPrinterDescription>::const_iterator i = lprPrinters.constBegin();
- for(; i != lprPrinters.constEnd(); ++i) {
- list.append(QPrinterInfo((*i).name));
- }
- if (defprn >= 0 && defprn < lprPrinters.size()) {
- list[defprn].d_ptr->m_default = true;
- }
-#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
+ foreach (const QPrinterDescription &description, lprPrinters)
+ printers.append(QPrinterInfo(description.name));
+ if (defprn >= 0 && defprn < printers.size())
+ printers[defprn].d_ptr->isDefault = true;
}
-#endif
- return list;
+ return printers;
}
QPrinterInfo QPrinterInfo::defaultPrinter()
{
- QList<QPrinterInfo> prnList = availablePrinters();
- for (int i = 0; i < prnList.size(); ++i) {
- if (prnList[i].isDefault())
- return prnList[i];
+ QList<QPrinterInfo> printers = availablePrinters();
+ foreach (const QPrinterInfo &printerInfo, printers) {
+ if (printerInfo.isDefault())
+ return printerInfo;
}
- return (prnList.size() > 0) ? prnList[0] : QPrinterInfo();
-}
-
-QPrinterInfo::QPrinterInfo()
- : d_ptr(&nullQPrinterInfoPrivate)
-{
-}
-QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
- : d_ptr(&nullQPrinterInfoPrivate)
-{
- *this = src;
+ return printers.value(0);
}
-QPrinterInfo::QPrinterInfo(const QPrinter& printer)
- : d_ptr(new QPrinterInfoPrivate(printer.printerName()))
+QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
-
- Q_D(QPrinterInfo);
- d->q_ptr = this;
-
#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
- QCUPSSupport cups;
- if (QCUPSSupport::isAvailable()) {
- int cupsPrinterCount = cups.availablePrintersCount();
- const cups_dest_t* cupsPrinters = cups.availablePrinters();
-
- for (int i = 0; i < cupsPrinterCount; ++i) {
- QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
- if (cupsPrinters[i].instance)
- printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
- if (printerName == printer.printerName()) {
- if (cupsPrinters[i].is_default)
- d->m_default = true;
- d->m_cupsPrinterIndex = i;
- return;
- }
- }
- } else {
-#endif
- QList<QPrinterDescription> lprPrinters;
- int defprn = qt_getLprPrinters(lprPrinters);
- // populating printer combo
- QList<QPrinterDescription>::const_iterator i = lprPrinters.constBegin();
- int c;
- for(c = 0; i != lprPrinters.constEnd(); ++i, ++c) {
- if (i->name == printer.printerName()) {
- if (defprn == c)
- d->m_default = true;
- return;
- }
- }
-#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
- }
-#endif
-
- // Printer not found.
- d_ptr.reset(&nullQPrinterInfoPrivate);
-}
-
-QPrinterInfo::QPrinterInfo(const QString& name)
- : d_ptr(new QPrinterInfoPrivate(name))
-{
- d_ptr->q_ptr = this;
-}
-
-QPrinterInfo::~QPrinterInfo()
-{
-}
-
-QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
-{
- Q_ASSERT(d_ptr);
- d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
- d_ptr->q_ptr = this;
- return *this;
-}
-
-QString QPrinterInfo::printerName() const
-{
const Q_D(QPrinterInfo);
- return d->m_name;
-}
-
-bool QPrinterInfo::isNull() const
-{
- const Q_D(QPrinterInfo);
- return d->m_isNull;
-}
-bool QPrinterInfo::isDefault() const
-{
- const Q_D(QPrinterInfo);
- return d->m_default;
-}
+ if (isNull())
+ return d->paperSizes;
-QList< QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
-{
- const Q_D(QPrinterInfo);
- if (d->m_mustGetPaperSizes) {
- d->m_mustGetPaperSizes = false;
+ if (!d->hasPaperSizes) {
+ d->hasPaperSizes = true;
-#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
- QCUPSSupport cups;
if (QCUPSSupport::isAvailable()) {
// Find paper sizes from CUPS.
- cups.setCurrentPrinter(d->m_cupsPrinterIndex);
+ QCUPSSupport cups;
+ cups.setCurrentPrinter(d->cupsPrinterIndex);
const ppd_option_t* sizes = cups.pageSizes();
if (sizes) {
- for (int j = 0; j < sizes->num_choices; ++j) {
- d->m_paperSizes.append(
- QPrinterInfoPrivate::string2PaperSize(
- QLatin1String(sizes->choices[j].choice)));
- }
+ for (int j = 0; j < sizes->num_choices; ++j)
+ d->paperSizes.append(string2PaperSize(sizes->choices[j].choice));
}
}
-#endif
-
}
- return d->m_paperSizes;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-QPrinterInfoPrivate::QPrinterInfoPrivate()
-{
- m_isNull = true;
- m_default = false;
- m_mustGetPaperSizes = true;
- m_cupsPrinterIndex = 0;
- q_ptr = 0;
-}
-
-QPrinterInfoPrivate::QPrinterInfoPrivate(const QString& name)
-{
- m_name = name;
- m_isNull = false;
- m_default = false;
- m_mustGetPaperSizes = true;
- m_cupsPrinterIndex = 0;
- q_ptr = 0;
-}
-QPrinterInfoPrivate::~QPrinterInfoPrivate()
-{
-}
-
-QPrinter::PaperSize QPrinterInfoPrivate::string2PaperSize(const QString& str)
-{
- if (str == QLatin1String("A4")) {
- return QPrinter::A4;
- } else if (str == QLatin1String("B5")) {
- return QPrinter::B5;
- } else if (str == QLatin1String("Letter")) {
- return QPrinter::Letter;
- } else if (str == QLatin1String("Legal")) {
- return QPrinter::Legal;
- } else if (str == QLatin1String("Executive")) {
- return QPrinter::Executive;
- } else if (str == QLatin1String("A0")) {
- return QPrinter::A0;
- } else if (str == QLatin1String("A1")) {
- return QPrinter::A1;
- } else if (str == QLatin1String("A2")) {
- return QPrinter::A2;
- } else if (str == QLatin1String("A3")) {
- return QPrinter::A3;
- } else if (str == QLatin1String("A5")) {
- return QPrinter::A5;
- } else if (str == QLatin1String("A6")) {
- return QPrinter::A6;
- } else if (str == QLatin1String("A7")) {
- return QPrinter::A7;
- } else if (str == QLatin1String("A8")) {
- return QPrinter::A8;
- } else if (str == QLatin1String("A9")) {
- return QPrinter::A9;
- } else if (str == QLatin1String("B0")) {
- return QPrinter::B0;
- } else if (str == QLatin1String("B1")) {
- return QPrinter::B1;
- } else if (str == QLatin1String("B10")) {
- return QPrinter::B10;
- } else if (str == QLatin1String("B2")) {
- return QPrinter::B2;
- } else if (str == QLatin1String("B3")) {
- return QPrinter::B3;
- } else if (str == QLatin1String("B4")) {
- return QPrinter::B4;
- } else if (str == QLatin1String("B6")) {
- return QPrinter::B6;
- } else if (str == QLatin1String("B7")) {
- return QPrinter::B7;
- } else if (str == QLatin1String("B8")) {
- return QPrinter::B8;
- } else if (str == QLatin1String("B9")) {
- return QPrinter::B9;
- } else if (str == QLatin1String("C5E")) {
- return QPrinter::C5E;
- } else if (str == QLatin1String("Comm10E")) {
- return QPrinter::Comm10E;
- } else if (str == QLatin1String("DLE")) {
- return QPrinter::DLE;
- } else if (str == QLatin1String("Folio")) {
- return QPrinter::Folio;
- } else if (str == QLatin1String("Ledger")) {
- return QPrinter::Ledger;
- } else if (str == QLatin1String("Tabloid")) {
- return QPrinter::Tabloid;
- } else {
- return QPrinter::Custom;
- }
-}
-
-QString QPrinterInfoPrivate::pageSize2String(QPrinter::PaperSize size)
-{
- switch (size) {
- case QPrinter::A4:
- return QLatin1String("A4");
- case QPrinter::B5:
- return QLatin1String("B5");
- case QPrinter::Letter:
- return QLatin1String("Letter");
- case QPrinter::Legal:
- return QLatin1String("Legal");
- case QPrinter::Executive:
- return QLatin1String("Executive");
- case QPrinter::A0:
- return QLatin1String("A0");
- case QPrinter::A1:
- return QLatin1String("A1");
- case QPrinter::A2:
- return QLatin1String("A2");
- case QPrinter::A3:
- return QLatin1String("A3");
- case QPrinter::A5:
- return QLatin1String("A5");
- case QPrinter::A6:
- return QLatin1String("A6");
- case QPrinter::A7:
- return QLatin1String("A7");
- case QPrinter::A8:
- return QLatin1String("A8");
- case QPrinter::A9:
- return QLatin1String("A9");
- case QPrinter::B0:
- return QLatin1String("B0");
- case QPrinter::B1:
- return QLatin1String("B1");
- case QPrinter::B10:
- return QLatin1String("B10");
- case QPrinter::B2:
- return QLatin1String("B2");
- case QPrinter::B3:
- return QLatin1String("B3");
- case QPrinter::B4:
- return QLatin1String("B4");
- case QPrinter::B6:
- return QLatin1String("B6");
- case QPrinter::B7:
- return QLatin1String("B7");
- case QPrinter::B8:
- return QLatin1String("B8");
- case QPrinter::B9:
- return QLatin1String("B9");
- case QPrinter::C5E:
- return QLatin1String("C5E");
- case QPrinter::Comm10E:
- return QLatin1String("Comm10E");
- case QPrinter::DLE:
- return QLatin1String("DLE");
- case QPrinter::Folio:
- return QLatin1String("Folio");
- case QPrinter::Ledger:
- return QLatin1String("Ledger");
- case QPrinter::Tabloid:
- return QLatin1String("Tabloid");
- default:
- return QLatin1String("Custom");
- }
+ return d->paperSizes;
+#else
+ return QList<QPrinter::PaperSize>();
+#endif
}
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp
index 144b7156ed..2c4014d8dc 100644
--- a/src/gui/painting/qprinterinfo_win.cpp
+++ b/src/gui/painting/qprinterinfo_win.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qprinterinfo.h"
+#include "qprinterinfo_p.h"
#include <qstringlist.h>
@@ -51,59 +52,25 @@ QT_BEGIN_NAMESPACE
extern QPrinter::PaperSize mapDevmodePaperSize(int s);
-class QPrinterInfoPrivate
-{
-Q_DECLARE_PUBLIC(QPrinterInfo)
-public:
- ~QPrinterInfoPrivate();
- QPrinterInfoPrivate();
- QPrinterInfoPrivate(const QString& name);
-
-private:
- QString m_name;
- bool m_default;
- bool m_isNull;
-
- QPrinterInfo* q_ptr;
-};
-
-static QPrinterInfoPrivate nullQPrinterInfoPrivate;
-
-class QPrinterInfoPrivateDeleter
-{
-public:
- static inline void cleanup(QPrinterInfoPrivate *d)
- {
- if (d != &nullQPrinterInfoPrivate)
- delete d;
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
QList<QPrinterInfo> QPrinterInfo::availablePrinters()
{
QList<QPrinterInfo> printers;
- LPBYTE buffer;
+
DWORD needed = 0;
DWORD returned = 0;
-
- if ( !EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned))
- {
- buffer = new BYTE[needed];
- if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL,
- 4, buffer, needed, &needed, &returned))
- {
- delete [] buffer;
- return printers;
- }
- PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer);
- QPrinterInfo defPrn = defaultPrinter();
- for (uint i = 0; i < returned; ++i) {
- printers.append(QPrinterInfo(QString::fromWCharArray(infoList[i].pPrinterName)));
- if (printers.at(i).printerName() == defPrn.printerName())
- printers[i].d_ptr->m_default = true;
+ if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned)) {
+ LPBYTE buffer = new BYTE[needed];
+ if (EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer, needed, &needed, &returned)) {
+ PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer);
+ QPrinterInfo defPrn = defaultPrinter();
+ for (uint i = 0; i < returned; ++i) {
+ QString printerName(QString::fromWCharArray(infoList[i].pPrinterName));
+
+ QPrinterInfo printerInfo(printerName);
+ if (printerInfo.printerName() == defPrn.printerName())
+ printerInfo.d_ptr->isDefault = true;
+ printers.append(printerInfo);
+ }
}
delete [] buffer;
}
@@ -117,127 +84,37 @@ QPrinterInfo QPrinterInfo::defaultPrinter()
wchar_t buffer[256];
GetProfileString(L"windows", L"device", (wchar_t*)noPrinters.utf16(), buffer, 256);
QString output = QString::fromWCharArray(buffer);
-
- // Filter out the name of the printer, which should be everything
- // before a comma.
- bool noConfiguredPrinters = (output == noPrinters);
- QStringList info = output.split(QLatin1Char(','));
- QString printerName = noConfiguredPrinters ? QString() : info.at(0);
-
- QPrinterInfo prn(printerName);
- prn.d_ptr->m_default = true;
- if (noConfiguredPrinters)
- prn.d_ptr->m_isNull = true;
- return prn;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-QPrinterInfo::QPrinterInfo()
- : d_ptr(&nullQPrinterInfoPrivate)
-{
-}
-
-QPrinterInfo::QPrinterInfo(const QString& name)
- : d_ptr(new QPrinterInfoPrivate(name))
-{
- d_ptr->q_ptr = this;
-}
-
-QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
- : d_ptr(&nullQPrinterInfoPrivate)
-{
- *this = src;
-}
-
-QPrinterInfo::QPrinterInfo(const QPrinter& prn)
- : d_ptr(&nullQPrinterInfoPrivate)
-{
- QList<QPrinterInfo> list = availablePrinters();
- for (int c = 0; c < list.size(); ++c) {
- if (prn.printerName() == list[c].printerName()) {
- *this = list[c];
- return;
- }
+ if (output != noPrinters) {
+ // Filter out the name of the printer, which should be everything before a comma.
+ QString printerName = output.split(QLatin1Char(',')).value(0);
+ QPrinterInfo printerInfo(printerName);
+ printerInfo.d_ptr->isDefault = true;
+ return printerInfo;
}
- *this = QPrinterInfo();
-}
-
-QPrinterInfo::~QPrinterInfo()
-{
-}
-
-QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
-{
- Q_ASSERT(d_ptr);
- d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
- d_ptr->q_ptr = this;
- return *this;
-}
-
-QString QPrinterInfo::printerName() const
-{
- const Q_D(QPrinterInfo);
- return d->m_name;
-}
-
-bool QPrinterInfo::isNull() const
-{
- const Q_D(QPrinterInfo);
- return d->m_isNull;
-}
-
-bool QPrinterInfo::isDefault() const
-{
- const Q_D(QPrinterInfo);
- return d->m_default;
+ return QPrinterInfo();
}
QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const
{
const Q_D(QPrinterInfo);
- QList<QPrinter::PaperSize> paperList;
- DWORD size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()),
- NULL, DC_PAPERS, NULL, NULL);
- if ((int)size == -1)
- return paperList;
-
- wchar_t *papers = new wchar_t[size];
- size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->m_name.utf16()),
- NULL, DC_PAPERS, papers, NULL);
+ QList<QPrinter::PaperSize> paperSizes;
+ if (isNull())
+ return paperSizes;
- for (int c = 0; c < (int)size; ++c) {
- paperList.append(mapDevmodePaperSize(papers[c]));
+ DWORD size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()),
+ NULL, DC_PAPERS, NULL, NULL);
+ if ((int)size != -1) {
+ wchar_t *papers = new wchar_t[size];
+ size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()),
+ NULL, DC_PAPERS, papers, NULL);
+ for (int c = 0; c < (int)size; ++c)
+ paperSizes.append(mapDevmodePaperSize(papers[c]));
+ delete [] papers;
}
- delete [] papers;
-
- return paperList;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-QPrinterInfoPrivate::QPrinterInfoPrivate() :
- m_default(false),
- m_isNull(true),
- q_ptr(NULL)
-{
-}
-
-QPrinterInfoPrivate::QPrinterInfoPrivate(const QString& name) :
- m_name(name),
- m_default(false),
- m_isNull(false),
- q_ptr(NULL)
-{
-}
-
-QPrinterInfoPrivate::~QPrinterInfoPrivate()
-{
+ return paperSizes;
}
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index bd38286967..75116c2420 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -62,8 +62,8 @@ typedef int Q16Dot16;
#define SPAN_BUFFER_SIZE 256
-#define COORD_ROUNDING 1 // 0: round up, 1: round down
-#define COORD_OFFSET 32 // 26.6, 32 is half a pixel
+#define COORD_ROUNDING 0 // 0: round up, 1: round down
+#define COORD_OFFSET 0 // 26.6, 32 is half a pixel
static inline QT_FT_Vector PointToVector(const QPointF &p)
{
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 478a00bf4e..d713346902 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -391,6 +391,14 @@ void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byt
*/
/*!
+ \fn void QRegion::swap(QRegion &other)
+ \since 4.8
+
+ Swaps region \a other with this region. This operation is very
+ fast and never fails.
+*/
+
+/*!
\relates QRegion
Writes the region \a r to the stream \a s and returns a reference
@@ -1620,7 +1628,7 @@ QT_END_INCLUDE_NAMESPACE
QT_BEGIN_INCLUDE_NAMESPACE
# include "qregion_win.cpp"
QT_END_INCLUDE_NAMESPACE
-#elif defined(Q_WS_QWS)
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
static QRegionPrivate qrp;
QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), &qrp};
#endif
@@ -4231,7 +4239,7 @@ QRect QRegion::boundingRect() const
Returns true if \a rect is guaranteed to be fully contained in \a region.
A false return value does not guarantee the opposite.
*/
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
Q_GUI_EXPORT
#endif
bool qt_region_strictContains(const QRegion &region, const QRect &rect)
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index f78ece84f5..1cd38d41b8 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -59,7 +59,7 @@ QT_MODULE(Gui)
template <class T> class QVector;
class QVariant;
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
struct QRegionPrivate;
#endif
@@ -81,7 +81,11 @@ public:
QRegion(const QBitmap &bitmap);
~QRegion();
QRegion &operator=(const QRegion &);
-
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QRegion &operator=(QRegion &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+ inline void swap(QRegion &other) { qSwap(d, other.d); }
#ifdef QT3_SUPPORT
inline QT3_SUPPORT bool isNull() const { return isEmpty(); }
#endif
@@ -163,7 +167,7 @@ public:
#endif
HIMutableShapeRef toHIMutableShape() const;
static QRegion fromHIShapeRef(HIShapeRef shape);
-#elif defined(Q_WS_QWS)
+#elif defined(Q_WS_QWS) || defined(Q_WS_QPA)
inline void *handle() const { return d->qt_rgn; }
#endif
#endif
@@ -203,7 +207,7 @@ private:
#elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
mutable RgnHandle unused; // Here for binary compatibility reasons. ### Qt 5 remove.
#endif
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
QRegionPrivate *qt_rgn;
#endif
};
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 2420f311ab..e75c0f58cb 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -65,8 +65,60 @@ static inline int qt_next_power_of_two(int v)
return v;
}
+int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
+{
+ // Test 12 different subpixel positions since it factors into 3*4 so it gives
+ // the coverage we need.
+
+ QList<QImage> images;
+ for (int i=0; i<12; ++i) {
+ QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0));
+
+ if (images.isEmpty()) {
+ QPainterPath path;
+ QFixedPoint point;
+ m_current_fontengine->addGlyphsToPath(&glyph, &point, 1, &path, QTextItem::RenderFlags());
+
+ // Glyph is space, return 0 to indicate that we need to keep trying
+ if (path.isEmpty())
+ break;
+
+ images.append(img);
+ } else {
+ bool found = false;
+ for (int j=0; j<images.size(); ++j) {
+ if (images.at(j) == img) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ images.append(img);
+ }
+ }
+
+ return images.size();
+}
+
+QFixed QTextureGlyphCache::subPixelPositionForX(QFixed x) const
+{
+ if (m_subPixelPositionCount == 0)
+ return QFixed();
+
+ QFixed subPixelPosition;
+ if (x != 0) {
+ subPixelPosition = x - x.floor();
+ QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
+
+ // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over
+ // the lower boundary for the selected rasterization by adding 1/64.
+ subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);
+ }
+ return subPixelPosition;
+}
+
bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
- const QFixedPoint *)
+ const QFixedPoint *positions)
{
#ifdef CACHE_DEBUG
printf("Populating with %d glyphs\n", numGlyphs);
@@ -77,17 +129,42 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
const int margin = glyphMargin();
const int paddingDoubled = glyphPadding() * 2;
- QHash<glyph_t, Coord> listItemCoordinates;
+ bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
+ if (m_subPixelPositionCount == 0) {
+ if (!supportsSubPixelPositions) {
+ m_subPixelPositionCount = 1;
+ } else {
+ int i = 0;
+ while (m_subPixelPositionCount == 0 && i < numGlyphs)
+ m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
+ }
+ }
+
+ QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates;
int rowHeight = 0;
+ QFontEngine::GlyphFormat format;
+ switch (m_type) {
+ case Raster_A8: format = QFontEngine::Format_A8; break;
+ case Raster_RGBMask: format = QFontEngine::Format_A32; break;
+ default: format = QFontEngine::Format_Mono; break;
+ }
+
// check each glyph for its metrics and get the required rowHeight.
for (int i=0; i < numGlyphs; ++i) {
const glyph_t glyph = glyphs[i];
- if (coords.contains(glyph))
+
+ QFixed subPixelPosition;
+ if (supportsSubPixelPositions) {
+ QFixed x = positions != 0 ? positions[i].x : QFixed();
+ subPixelPosition = subPixelPositionForX(x);
+ }
+
+ if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
continue;
- if (listItemCoordinates.contains(glyph))
+ if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
continue;
- glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform);
+ glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, m_transform, format);
#ifdef CACHE_DEBUG
printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
@@ -98,11 +175,16 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
metrics.yoff.toReal(),
metrics.x.toReal(),
metrics.y.toReal());
-#endif
+#endif
+ GlyphAndSubPixelPosition key(glyph, subPixelPosition);
int glyph_width = metrics.width.ceil().toInt();
int glyph_height = metrics.height.ceil().toInt();
- if (glyph_height == 0 || glyph_width == 0)
+ if (glyph_height == 0 || glyph_width == 0) {
+ // Avoid multiple calls to boundingBox() for non-printable characters
+ Coord c = { 0, 0, 0, 0, 0, 0 };
+ coords.insert(key, c);
continue;
+ }
glyph_width += margin * 2 + 4;
glyph_height += margin * 2 + 4;
// align to 8-bit boundary
@@ -115,30 +197,35 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
metrics.x.round().truncate(),
-metrics.y.truncate() }; // baseline for horizontal scripts
- listItemCoordinates.insert(glyph, c);
+ listItemCoordinates.insert(key, c);
rowHeight = qMax(rowHeight, glyph_height);
}
if (listItemCoordinates.isEmpty())
return true;
rowHeight += margin * 2 + paddingDoubled;
- if (isNull())
- createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight));
+
+ if (m_w == 0) {
+ if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH)
+ m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH;
+ else
+ m_w = qt_next_power_of_two(fontEngine->maxCharWidth());
+ }
// now actually use the coords and paint the wanted glyps into cache.
- QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin();
+ QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = listItemCoordinates.begin();
+ int requiredWidth = m_w;
while (iter != listItemCoordinates.end()) {
Coord c = iter.value();
m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2);
- if (m_cx + c.w > m_w) {
- int new_width = m_w*2;
+ if (m_cx + c.w > requiredWidth) {
+ int new_width = requiredWidth*2;
while (new_width < m_cx + c.w)
new_width *= 2;
if (new_width <= maxTextureWidth()) {
- resizeTextureData(new_width, m_h);
- m_w = new_width;
+ requiredWidth = new_width;
} else {
// no room on the current line, start new glyph strip
m_cx = 0;
@@ -146,36 +233,58 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
m_currentRowHeight = c.h + margin * 2; // New row
}
}
- if (m_cy + c.h > m_h) {
- int new_height = m_h*2;
- while (new_height < m_cy + c.h)
- new_height *= 2;
-
- if (maxTextureHeight() > 0 && new_height > maxTextureHeight()) {
- // We can't make a new texture of the required size, so
- // bail out
- return false;
- }
-
- // if no room in the current texture - realloc a larger texture
- resizeTextureData(m_w, new_height);
- m_h = new_height;
- }
c.x = m_cx;
c.y = m_cy;
- fillTexture(c, iter.key());
coords.insert(iter.key(), c);
+ m_pendingGlyphs.insert(iter.key(), c);
m_cx += c.w + paddingDoubled;
++iter;
}
-
return true;
+
+}
+
+void QTextureGlyphCache::fillInPendingGlyphs()
+{
+ if (m_pendingGlyphs.isEmpty())
+ return;
+
+ int requiredHeight = m_h;
+ int requiredWidth = m_w; // Use a minimum size to avoid a lot of initial reallocations
+ {
+ QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin();
+ while (iter != m_pendingGlyphs.end()) {
+ Coord c = iter.value();
+ requiredHeight = qMax(requiredHeight, c.y + c.h);
+ requiredWidth = qMax(requiredWidth, c.x + c.w);
+ ++iter;
+ }
+ }
+
+ if (isNull() || requiredHeight > m_h || requiredWidth > m_w) {
+ if (isNull())
+ createCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
+ else
+ resizeCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight));
+ }
+
+ {
+ QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin();
+ while (iter != m_pendingGlyphs.end()) {
+ GlyphAndSubPixelPosition key = iter.key();
+ fillTexture(iter.value(), key.glyph, key.subPixelPosition);
+
+ ++iter;
+ }
+ }
+
+ m_pendingGlyphs.clear();
}
-QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
+QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const
{
#if defined(Q_WS_X11)
if (m_transform.type() > QTransform::TxTranslate) {
@@ -208,9 +317,9 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
} else
#endif
if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
- return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
+ return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, glyphMargin(), m_transform);
else
- return m_current_fontengine->alphaMapForGlyph(g, m_transform);
+ return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform);
return QImage();
}
@@ -254,9 +363,9 @@ int QImageTextureGlyphCache::glyphMargin() const
#endif
}
-void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
+void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition)
{
- QImage mask = textureMapForGlyph(g);
+ QImage mask = textureMapForGlyph(g, subPixelPosition);
#ifdef CACHE_DEBUG
printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
@@ -341,7 +450,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
QPoint base(c.x + glyphMargin(), c.y + glyphMargin() + c.baseLineY-1);
if (m_image.rect().contains(base))
m_image.setPixel(base, 255);
- m_image.save(QString::fromLatin1("cache-%1.png").arg(int(this)));
+ m_image.save(QString::fromLatin1("cache-%1.png").arg(qint64(this)));
#endif
}
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 17f0d8910c..922e2901bd 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -81,11 +81,24 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
public:
QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
: QFontEngineGlyphCache(matrix, type), m_current_fontengine(0),
- m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
+ m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0), m_subPixelPositionCount(0)
{ }
virtual ~QTextureGlyphCache() { }
+ struct GlyphAndSubPixelPosition
+ {
+ GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
+
+ bool operator==(const GlyphAndSubPixelPosition &other) const
+ {
+ return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
+ }
+
+ glyph_t glyph;
+ QFixed subPixelPosition;
+ };
+
struct Coord {
int x;
int y;
@@ -94,17 +107,23 @@ public:
int baseLineX;
int baseLineY;
+
+ bool isNull() const
+ {
+ return w == 0 || h == 0;
+ }
};
bool populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
const QFixedPoint *positions);
+ void fillInPendingGlyphs();
virtual void createTextureData(int width, int height) = 0;
virtual void resizeTextureData(int width, int height) = 0;
virtual int glyphMargin() const { return 0; }
virtual int glyphPadding() const { return 0; }
- virtual void fillTexture(const Coord &coord, glyph_t glyph) = 0;
+ virtual void fillTexture(const Coord &coord, glyph_t glyph, QFixed subPixelPosition) = 0;
inline void createCache(int width, int height) {
m_w = width;
@@ -112,24 +131,42 @@ public:
createTextureData(width, height);
}
- inline bool isNull() const { return m_w <= 0 || m_h <= 0; }
+ inline void resizeCache(int width, int height)
+ {
+ resizeTextureData(width, height);
+ m_w = width;
+ m_h = height;
+ }
- QHash<glyph_t, Coord> coords;
+ inline bool isNull() const { return m_h == 0; }
- QImage textureMapForGlyph(glyph_t g) const;
+ QHash<GlyphAndSubPixelPosition, Coord> coords;
virtual int maxTextureWidth() const { return QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; }
virtual int maxTextureHeight() const { return -1; }
+ QImage textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const;
+
+ QFixed subPixelPositionForX(QFixed x) const;
+
protected:
+ int calculateSubPixelPositionCount(glyph_t) const;
+
QFontEngine *m_current_fontengine;
+ QHash<GlyphAndSubPixelPosition, Coord> m_pendingGlyphs;
int m_w; // image width
int m_h; // image height
int m_cx; // current x
int m_cy; // current y
int m_currentRowHeight; // Height of last row
+ int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
};
+inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g)
+{
+ return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
+}
+
class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
{
@@ -139,7 +176,7 @@ public:
virtual int glyphMargin() const;
virtual void createTextureData(int width, int height);
virtual void resizeTextureData(int width, int height);
- virtual void fillTexture(const Coord &c, glyph_t glyph);
+ virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition);
inline const QImage &image() const { return m_image; }
diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp
new file mode 100644
index 0000000000..02ba8db83a
--- /dev/null
+++ b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qunifiedtoolbarsurface_mac_p.h"
+#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qbackingstore_p.h>
+#include <private/qmainwindowlayout_p.h>
+
+#include <QDebug>
+
+#ifdef QT_MAC_USE_COCOA
+
+QT_BEGIN_NAMESPACE
+
+QUnifiedToolbarSurface::QUnifiedToolbarSurface(QWidget *widget)
+ : QRasterWindowSurface(widget, false), d_ptr(new QUnifiedToolbarSurfacePrivate)
+{
+ d_ptr->image = 0;
+ d_ptr->inSetGeometry = false;
+ setStaticContentsSupport(true);
+
+ setGeometry(QRect(QPoint(0, 0), QSize(widget->width(), 100))); // FIXME: Fix height.
+}
+
+QUnifiedToolbarSurface::~QUnifiedToolbarSurface()
+{
+ if (d_ptr->image)
+ delete d_ptr->image;
+}
+
+QPaintDevice *QUnifiedToolbarSurface::paintDevice()
+{
+ return &d_ptr->image->image;
+}
+
+void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &offset)
+{
+ if (object != 0) {
+ if (object->isWidgetType()) {
+ QWidget *widget = qobject_cast<QWidget *>(object);
+
+ // We redirect the painting only if the widget is in the same window
+ // and is not a window in itself.
+ if (!(widget->windowType() & Qt::Window)) {
+ widget->d_func()->unifiedSurface = this;
+ widget->d_func()->isInUnifiedToolbar = true;
+ widget->d_func()->toolbar_offset = offset;
+
+ for (int i = 0; i < object->children().size(); ++i) {
+ recursiveRedirect(object->children().at(i), offset);
+ }
+ }
+ }
+ }
+}
+
+void QUnifiedToolbarSurface::insertToolbar(QWidget *toolbar, const QPoint &offset)
+{
+ setGeometry(QRect(QPoint(0, 0), QSize(offset.x() + toolbar->width(), 100))); // FIXME
+ recursiveRedirect(toolbar, offset);
+}
+
+void QUnifiedToolbarSurface::setGeometry(const QRect &rect)
+{
+ QWindowSurface::setGeometry(rect);
+ Q_D(QUnifiedToolbarSurface);
+ d->inSetGeometry = true;
+ if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height())
+ prepareBuffer(QImage::Format_ARGB32_Premultiplied, window());
+ d->inSetGeometry = false;
+
+ // FIXME: set unified toolbar height.
+}
+
+void QUnifiedToolbarSurface::beginPaint(const QRegion &rgn)
+{
+ QPainter p(&d_ptr->image->image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ const QVector<QRect> rects = rgn.rects();
+ const QColor blank = Qt::transparent;
+ for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
+ p.fillRect(*it, blank);
+ }
+}
+
+void QUnifiedToolbarSurface::updateToolbarOffset(QWidget *widget)
+{
+ QMainWindowLayout *mlayout = qobject_cast<QMainWindowLayout*> (widget->window()->layout());
+ mlayout->updateUnifiedToolbarOffset();
+}
+
+void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
+{
+ Q_D(QUnifiedToolbarSurface);
+
+ QRegion flushingRegion(widget->rect());
+
+ if (!d->image || rgn.rectCount() == 0) {
+ return;
+ }
+
+ Q_UNUSED(offset);
+
+ // Get a context for the widget.
+ CGContextRef context;
+ if (!(widget->d_func()->hasOwnContext)) {
+ widget->d_func()->ut_rg = rgn;
+ widget->d_func()->ut_pt = offset;
+ qt_mac_display(widget);
+ return;
+ } else {
+ // We render the content of the toolbar in the surface.
+ updateToolbarOffset(widget);
+ QRect beginPaintRect(widget->d_func()->toolbar_offset.x(), widget->d_func()->toolbar_offset.y(), widget->geometry().width(), widget->geometry().height());
+ QRegion beginPaintRegion(beginPaintRect);
+
+ context = widget->d_func()->cgContext;
+ beginPaint(beginPaintRegion);
+ widget->render(widget->d_func()->unifiedSurface->paintDevice(), widget->d_func()->toolbar_offset, QRegion(), QWidget::DrawChildren);
+ }
+
+ CGContextSaveGState(context);
+
+ int areaX = widget->d_func()->toolbar_offset.x();
+ int areaY = widget->d_func()->toolbar_offset.y();
+ int areaWidth = widget->geometry().width();
+ int areaHeight = widget->geometry().height();
+ const CGRect area = CGRectMake(areaX, areaY, areaWidth, areaHeight);
+
+ // Clip to region.
+ const QVector<QRect> &rects = flushingRegion.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect &rect = rects.at(i);
+ CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()));
+ }
+ CGContextAddRect(context, area);
+ CGContextClip(context);
+
+
+ CGImageRef image = CGBitmapContextCreateImage(d->image->cg);
+ CGImageRef subImage = CGImageCreateWithImageInRect(image, area);
+
+ const CGRect drawingArea = CGRectMake(0, 0, areaWidth, areaHeight);
+ qt_mac_drawCGImage(context, &drawingArea, subImage);
+
+ CGImageRelease(subImage);
+ CGImageRelease(image);
+
+ CGContextFlush(context);
+
+ // Restore context.
+ CGContextRestoreGState(context);
+ CGContextRelease(context);
+ widget->d_func()->cgContext = 0;
+ widget->d_func()->hasOwnContext = false;
+}
+
+void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widget)
+{
+ Q_D(QUnifiedToolbarSurface);
+
+ int width = geometry().width();
+ int height = geometry().height();
+ if (d->image) {
+ width = qMax(d->image->width(), width);
+ height = qMax(d->image->height(), height);
+ }
+
+ if (width == 0 || height == 0) {
+ delete d->image;
+ d->image = 0;
+ return;
+ }
+
+ QNativeImage *oldImage = d->image;
+
+ d->image = new QNativeImage(width, height, format, false, widget);
+
+ if (oldImage && d->inSetGeometry && hasStaticContents()) {
+ // Make sure we use the const version of bits() (no detach).
+ const uchar *src = const_cast<const QImage &>(oldImage->image).bits();
+ uchar *dst = d->image->image.bits();
+
+ const int srcBytesPerLine = oldImage->image.bytesPerLine();
+ const int dstBytesPerLine = d->image->image.bytesPerLine();
+ const int bytesPerPixel = oldImage->image.depth() >> 3;
+
+ QRegion staticRegion(staticContents());
+ // Make sure we're inside the boundaries of the old image.
+ staticRegion &= QRect(0, 0, oldImage->image.width(), oldImage->image.height());
+ const QVector<QRect> &rects = staticRegion.rects();
+ const QRect *srcRect = rects.constData();
+
+ // Copy the static content of the old image into the new one.
+ int numRectsLeft = rects.size();
+ do {
+ const int bytesOffset = srcRect->x() * bytesPerPixel;
+ const int dy = srcRect->y();
+
+ // Adjust src and dst to point to the right offset.
+ const uchar *s = src + dy * srcBytesPerLine + bytesOffset;
+ uchar *d = dst + dy * dstBytesPerLine + bytesOffset;
+ const int numBytes = srcRect->width() * bytesPerPixel;
+
+ int numScanLinesLeft = srcRect->height();
+ do {
+ ::memcpy(d, s, numBytes);
+ d += dstBytesPerLine;
+ s += srcBytesPerLine;
+ } while (--numScanLinesLeft);
+
+ ++srcRect;
+ } while (--numRectsLeft);
+ }
+
+ delete oldImage;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_MAC_USE_COCOA
diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac_p.h b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h
new file mode 100644
index 0000000000..3bc040464e
--- /dev/null
+++ b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUNIFIEDTOOLBARSURFACE_MAC_P_H
+#define QUNIFIEDTOOLBARSURFACE_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qwindowsurface_raster_p.h>
+#include <QWidget>
+#include <private/qwidget_p.h>
+#include <private/qnativeimage_p.h>
+
+#ifdef QT_MAC_USE_COCOA
+
+QT_BEGIN_NAMESPACE
+
+class QNativeImage;
+
+
+class QUnifiedToolbarSurfacePrivate
+{
+public:
+ QNativeImage *image;
+ uint inSetGeometry : 1;
+};
+
+class Q_GUI_EXPORT QUnifiedToolbarSurface : public QRasterWindowSurface
+{
+public:
+ QUnifiedToolbarSurface(QWidget *widget);
+ ~QUnifiedToolbarSurface();
+
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+ void setGeometry(const QRect &rect);
+ void beginPaint(const QRegion &rgn);
+ void insertToolbar(QWidget *toolbar, const QPoint &offset);
+
+private:
+ QPaintDevice *paintDevice();
+ void updateToolbarOffset(QWidget *widget);
+ void prepareBuffer(QImage::Format format, QWidget *widget);
+ void recursiveRedirect(QObject *widget, const QPoint &offset);
+
+ Q_DECLARE_PRIVATE(QUnifiedToolbarSurface)
+ QScopedPointer<QUnifiedToolbarSurfacePrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_MAC_USE_COCOA
+
+#endif // QUNIFIEDTOOLBARSURFACE_MAC_P_H
diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp
index b84f26ed3b..029b9dc14c 100644
--- a/src/gui/painting/qwindowsurface.cpp
+++ b/src/gui/painting/qwindowsurface.cpp
@@ -58,7 +58,11 @@ public:
}
QWidget *window;
+#if !defined(Q_WS_QPA)
QRect geometry;
+#else
+ QSize size;
+#endif //Q_WS_QPA
QRegion staticContents;
QList<QImage*> bufferImages;
uint staticContentsSupport : 1;
@@ -70,7 +74,7 @@ public:
\since 4.3
\internal
\preliminary
- \ingroup qws
+ \ingroup qws qpa
\brief The QWindowSurface class provides the drawing area for top-level
windows.
@@ -114,11 +118,11 @@ public:
/*!
Constructs an empty surface for the given top-level \a window.
*/
-QWindowSurface::QWindowSurface(QWidget *window)
+QWindowSurface::QWindowSurface(QWidget *window, bool setDefaultSurface)
: d_ptr(new QWindowSurfacePrivate(window))
{
if (!QApplicationPrivate::runtime_graphics_system) {
- if(window)
+ if(setDefaultSurface && window)
window->setWindowSurface(this);
}
}
@@ -153,6 +157,7 @@ void QWindowSurface::endPaint(const QRegion &)
d_ptr->bufferImages.clear();
}
+#if !defined(Q_WS_QPA)
/*!
Sets the currently allocated area to be the given \a rect.
@@ -173,6 +178,26 @@ QRect QWindowSurface::geometry() const
{
return d_ptr->geometry;
}
+#else
+
+/*!
+ Sets the size of the windowsurface to be \a size.
+
+ \sa size()
+*/
+void QWindowSurface::resize(const QSize &size)
+{
+ d_ptr->size = size;
+}
+
+/*!
+ Returns the current size of the windowsurface.
+*/
+QSize QWindowSurface::size() const
+{
+ return d_ptr->size;
+}
+#endif //Q_WS_QPA
/*!
Scrolls the given \a area \a dx pixels to the right and \a dy
@@ -329,7 +354,13 @@ void QWindowSurface::setPartialUpdateSupport(bool enable)
d_ptr->partialUpdateSupport = enable;
}
-void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
+#ifdef Q_WS_QPA
+#define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT
+#else
+#define Q_EXPORT_SCROLLRECT
+#endif
+
+void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
{
// make sure we don't detach
uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
diff --git a/src/gui/painting/qwindowsurface_mac.cpp b/src/gui/painting/qwindowsurface_mac.cpp
index 88d41baa71..620a50f3ea 100644
--- a/src/gui/painting/qwindowsurface_mac.cpp
+++ b/src/gui/painting/qwindowsurface_mac.cpp
@@ -82,6 +82,7 @@ void QMacWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint
extern CGContextRef qt_mac_graphicsContextFor(QWidget *);
CGContextRef context = qt_mac_graphicsContextFor(widget);
#endif
+ CGContextRetain(context);
CGContextSaveGState(context);
// Flip context.
@@ -109,6 +110,7 @@ void QMacWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint
#else
CGContextFlush(context);
#endif
+ CGContextRelease(context);
}
void QMacWindowSurface::setGeometry(const QRect &rect)
diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h
index 6275ec0c80..62137ef13b 100644
--- a/src/gui/painting/qwindowsurface_p.h
+++ b/src/gui/painting/qwindowsurface_p.h
@@ -63,11 +63,12 @@ class QRect;
class QPoint;
class QImage;
class QWindowSurfacePrivate;
+class QPlatformWindow;
class Q_GUI_EXPORT QWindowSurface
{
public:
- QWindowSurface(QWidget *window);
+ QWindowSurface(QWidget *window, bool setDefaultSurface = true);
virtual ~QWindowSurface();
QWidget *window() const;
@@ -79,8 +80,14 @@ public:
// can be larger than just the offset from the top-level widget as there may also be window
// decorations which are painted into the window surface.
virtual void flush(QWidget *widget, const QRegion &region, const QPoint &offset) = 0;
+#if !defined(Q_WS_QPA)
virtual void setGeometry(const QRect &rect);
QRect geometry() const;
+#else
+ virtual void resize(const QSize &size);
+ QSize size() const;
+ inline QRect geometry() const { return QRect(QPoint(), size()); } //### cleanup before Qt 5
+#endif
virtual bool scroll(const QRegion &area, int dx, int dy);
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index ccb10ff7f0..d0b9239a48 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -64,6 +64,9 @@
#ifdef Q_WS_MAC
#include <private/qt_cocoa_helpers_mac_p.h>
+#include <QMainWindow>
+#include <private/qmainwindowlayout_p.h>
+#include <QToolBar>
#endif
QT_BEGIN_NAMESPACE
@@ -82,8 +85,8 @@ public:
uint inSetGeometry : 1;
};
-QRasterWindowSurface::QRasterWindowSurface(QWidget *window)
- : QWindowSurface(window), d_ptr(new QRasterWindowSurfacePrivate)
+QRasterWindowSurface::QRasterWindowSurface(QWidget *window, bool setDefaultSurface)
+ : QWindowSurface(window, setDefaultSurface), d_ptr(new QRasterWindowSurfacePrivate)
{
#ifdef Q_WS_X11
d_ptr->gc = XCreateGC(X11->display, window->handle(), 0, 0);
@@ -248,9 +251,29 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
#ifdef Q_WS_MAC
-// qDebug() << "Flushing" << widget << rgn << offset;
+ // This is mainly done for native components like native "open file" dialog.
+ if (widget->testAttribute(Qt::WA_DontShowOnScreen)) {
+ return;
+ }
-// d->image->image.save("flush.png");
+#ifdef QT_MAC_USE_COCOA
+ // Unified toolbar hack.
+ QMainWindow* mWindow = qobject_cast<QMainWindow*>(widget->window());
+ if (mWindow) {
+ QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout());
+ QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList;
+
+ for (int i = 0; i < toolbarList.size(); ++i) {
+ QToolBar* toolbar = toolbarList.at(i);
+ if (mLayout->toolBarArea(toolbar) == Qt::TopToolBarArea) {
+ QWidget* tbWidget = (QWidget*) toolbar;
+ if (tbWidget->d_func()->unifiedSurface) {
+ tbWidget->d_func()->unifiedSurface->flush(tbWidget, rgn, offset);
+ }
+ }
+ }
+ }
+#endif // QT_MAC_USE_COCOA
Q_UNUSED(offset);
// Get a context for the widget.
@@ -262,6 +285,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
extern CGContextRef qt_mac_graphicsContextFor(QWidget *);
CGContextRef context = qt_mac_graphicsContextFor(widget);
#endif
+ CGContextRetain(context);
CGContextSaveGState(context);
// Flip context.
@@ -282,20 +306,21 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
CGImageRef subImage = CGImageCreateWithImageInRect(image, area);
qt_mac_drawCGImage(context, &area, subImage);
+
CGImageRelease(subImage);
CGImageRelease(image);
-// CGSize size = { d->image->image.width(), d->image->image.height() };
-// CGLayerRef layer = CGLayerCreateWithContext(d->image->cg, size, 0);
-// CGPoint pt = { 0, 0 };
-// CGContextDrawLayerAtPoint(context, pt, layer);
-// CGLayerRelease(layer);
-
- // Restore context.
- CGContextRestoreGState(context);
#ifndef QT_MAC_USE_COCOA
QDEndCGContext(port, &context);
+#else
+ CGContextFlush(context);
#endif
+
+ // Restore context.
+ CGContextRestoreGState(context);
+ CGContextRelease(context);
+
+
#endif // Q_WS_MAC
#ifdef Q_OS_SYMBIAN
@@ -323,6 +348,25 @@ void QRasterWindowSurface::setGeometry(const QRect &rect)
prepareBuffer(QNativeImage::systemFormat(), window());
}
d->inSetGeometry = false;
+
+#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ QMainWindow* mWindow = qobject_cast<QMainWindow*>(window());
+ if (mWindow) {
+ QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout());
+ QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList;
+
+ for (int i = 0; i < toolbarList.size(); ++i) {
+ QToolBar* toolbar = toolbarList.at(i);
+ if (mLayout->toolBarArea(toolbar) == Qt::TopToolBarArea) {
+ QWidget* tbWidget = (QWidget*) toolbar;
+ if (tbWidget->d_func()->unifiedSurface) {
+ tbWidget->d_func()->unifiedSurface->setGeometry(rect);
+ }
+ }
+ }
+ }
+#endif // Q_WS_MAC && QT_MAC_USE_COCOA
+
}
// from qwindowsurface.cpp
diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h
index 42f4bb5434..b6e61e1435 100644
--- a/src/gui/painting/qwindowsurface_raster_p.h
+++ b/src/gui/painting/qwindowsurface_raster_p.h
@@ -97,7 +97,7 @@ class QNativeImage;
class Q_GUI_EXPORT QRasterWindowSurface : public QWindowSurface
{
public:
- QRasterWindowSurface(QWidget *widget);
+ QRasterWindowSurface(QWidget *widget, bool setDefaultSurface = true);
~QRasterWindowSurface();
QPaintDevice *paintDevice();
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
index 7dc5cb7592..a8608181a9 100644
--- a/src/gui/painting/qwindowsurface_s60.cpp
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -77,7 +77,8 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget)
}
// We create empty CFbsBitmap here -> it will be resized in setGeometry
- CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new
+ CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new
+ Q_CHECK_PTR(bitmap);
qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) );
QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType);
diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp
index 8c2c68aa00..2324bc2d4f 100644
--- a/src/gui/painting/qwindowsurface_x11.cpp
+++ b/src/gui/painting/qwindowsurface_x11.cpp
@@ -149,6 +149,8 @@ void QX11WindowSurface::setGeometry(const QRect &rect)
return;
#ifndef QT_NO_XRENDER
if (d_ptr->translucentBackground) {
+ QPixmap::x11SetDefaultScreen(d_ptr->widget->x11Info().screen());
+
QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
data->xinfo = d_ptr->widget->x11Info();
data->resize(size.width(), size.height());
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index 2fbec15e85..8a2a88b04d 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -3763,6 +3763,7 @@ int QCleanlooksStyle::pixelMetric(PixelMetric metric, const QStyleOption *option
break;
case PM_MenuBarItemSpacing:
ret = 6;
+ break;
case PM_MenuBarHMargin:
ret = 0;
break;
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index de5920e6f8..8f99d6ad26 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -2218,7 +2218,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (vopt->state & QStyle::State_HasFocus) {
QStyleOptionFocusRect o;
o.QStyleOption::operator=(*vopt);
- o.rect = subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
+ o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
o.state |= QStyle::State_KeyboardFocusChange;
o.state |= QStyle::State_Item;
QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled)
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index 83ce5cb454..277e3025b5 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -1706,12 +1706,17 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
fakePos = maximum;
else if (scrollBar->sliderPosition > scrollBar->minimum)
fakePos = maximum - 1;
- GtkObject *adjustment = d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0);
- if (horizontal)
- d->gtk_range_set_adjustment((GtkRange*)(gtkHScrollBar), (GtkAdjustment*)(adjustment));
- else
- d->gtk_range_set_adjustment((GtkRange*)(gtkVScrollBar), (GtkAdjustment*)(adjustment));
+
+ GtkRange *range = (GtkRange*)(horizontal ? gtkHScrollBar : gtkVScrollBar);
+ GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range);
+
+ if (adjustment) {
+ d->gtk_adjustment_configure(adjustment, fakePos, 0, maximum, 0, 0, 0);
+ } else {
+ adjustment = (GtkAdjustment*)d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0);
+ d->gtk_range_set_adjustment(range, adjustment);
+ }
if (scrollBar->subControls & SC_ScrollBarGroove) {
GtkStateType state = GTK_STATE_ACTIVE;
@@ -1990,15 +1995,29 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
style = scaleWidget->style;
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
- GtkObject *adjustment = d->gtk_adjustment_new(slider->sliderPosition,
- slider->minimum,
- slider->maximum,
- slider->singleStep,
- slider->singleStep,
- slider->pageStep);
+
+ GtkRange *range = (GtkRange*)scaleWidget;
+ GtkAdjustment *adjustment = d->gtk_range_get_adjustment(range);
+ if (adjustment) {
+ d->gtk_adjustment_configure(adjustment,
+ slider->sliderPosition,
+ slider->minimum,
+ slider->maximum,
+ slider->singleStep,
+ slider->singleStep,
+ slider->pageStep);
+ } else {
+ adjustment = (GtkAdjustment*)d->gtk_adjustment_new(slider->sliderPosition,
+ slider->minimum,
+ slider->maximum,
+ slider->singleStep,
+ slider->singleStep,
+ slider->pageStep);
+ d->gtk_range_set_adjustment(range, adjustment);
+ }
+
int outerSize;
- d->gtk_range_set_adjustment ((GtkRange*)(scaleWidget), (GtkAdjustment*)(adjustment));
- d->gtk_range_set_inverted((GtkRange*)(scaleWidget), !horizontal);
+ d->gtk_range_set_inverted(range, !horizontal);
d->gtk_widget_style_get(scaleWidget, "trough-border", &outerSize, NULL);
outerSize++;
@@ -2998,8 +3017,7 @@ void QGtkStyle::drawControl(ControlElement element,
else if (bar->progress > bar->minimum)
fakePos = maximum - 1;
- GtkObject *adjustment = d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0);
- d->gtk_progress_set_adjustment((GtkProgress*)(gtkProgressBar), (GtkAdjustment*)(adjustment));
+ d->gtk_progress_configure((GtkProgress*)gtkProgressBar, fakePos, 0, maximum);
QRect progressBar;
diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp
index 1e2dd7ceb8..d7c53c9a91 100644
--- a/src/gui/styles/qgtkstyle_p.cpp
+++ b/src/gui/styles/qgtkstyle_p.cpp
@@ -121,7 +121,8 @@ Ptr_gtk_combo_box_entry_new QGtkStylePrivate::gtk_combo_box_entry_new = 0;
Ptr_gtk_progress_bar_new QGtkStylePrivate::gtk_progress_bar_new = 0;
Ptr_gtk_container_add QGtkStylePrivate::gtk_container_add = 0;
Ptr_gtk_menu_shell_append QGtkStylePrivate::gtk_menu_shell_append = 0;
-Ptr_gtk_progress_set_adjustment QGtkStylePrivate::gtk_progress_set_adjustment = 0;
+Ptr_gtk_progress_configure QGtkStylePrivate::gtk_progress_configure = 0;
+Ptr_gtk_range_get_adjustment QGtkStylePrivate::gtk_range_get_adjustment = 0;
Ptr_gtk_range_set_adjustment QGtkStylePrivate::gtk_range_set_adjustment = 0;
Ptr_gtk_range_set_inverted QGtkStylePrivate::gtk_range_set_inverted = 0;
Ptr_gtk_icon_factory_lookup_default QGtkStylePrivate::gtk_icon_factory_lookup_default = 0;
@@ -145,6 +146,7 @@ Ptr_gtk_paint_focus QGtkStylePrivate::gtk_paint_focus = 0;
Ptr_gtk_paint_arrow QGtkStylePrivate::gtk_paint_arrow = 0;
Ptr_gtk_paint_handle QGtkStylePrivate::gtk_paint_handle = 0;
Ptr_gtk_paint_expander QGtkStylePrivate::gtk_paint_expander = 0;
+Ptr_gtk_adjustment_configure QGtkStylePrivate::gtk_adjustment_configure = 0;
Ptr_gtk_adjustment_new QGtkStylePrivate::gtk_adjustment_new = 0;
Ptr_gtk_paint_hline QGtkStylePrivate::gtk_paint_hline = 0;
Ptr_gtk_paint_vline QGtkStylePrivate::gtk_paint_vline = 0;
@@ -376,7 +378,8 @@ void QGtkStylePrivate::resolveGtk() const
gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new");
gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new");
gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new");
- gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)libgtk.resolve("gtk_progress_set_adjustment");
+ gtk_progress_configure = (Ptr_gtk_progress_configure)libgtk.resolve("gtk_progress_configure");
+ gtk_range_get_adjustment = (Ptr_gtk_range_get_adjustment)libgtk.resolve("gtk_range_get_adjustment");
gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment");
gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted");
gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add");
@@ -405,6 +408,7 @@ void QGtkStylePrivate::resolveGtk() const
gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension");
gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline");
gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline");
+ gtk_adjustment_configure = (Ptr_gtk_adjustment_configure)libgtk.resolve("gtk_adjustment_configure");
gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new");
gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu");
gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default");
diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h
index 5cf1c59c0a..15a98c8257 100644
--- a/src/gui/styles/qgtkstyle_p.h
+++ b/src/gui/styles/qgtkstyle_p.h
@@ -174,8 +174,9 @@ typedef GtkWidget* (*Ptr_gtk_frame_new)(const gchar *);
typedef GtkWidget* (*Ptr_gtk_expander_new)(const gchar*);
typedef GtkWidget* (*Ptr_gtk_statusbar_new)(void);
typedef GtkSettings* (*Ptr_gtk_settings_get_default)(void);
+typedef GtkAdjustment* (*Ptr_gtk_range_get_adjustment)(GtkRange *);
typedef void (*Ptr_gtk_range_set_adjustment)(GtkRange *, GtkAdjustment *);
-typedef void (*Ptr_gtk_progress_set_adjustment)(GtkProgress *, GtkAdjustment *);
+typedef void (*Ptr_gtk_progress_configure)(GtkProgress *, double, double, double);
typedef void (*Ptr_gtk_range_set_inverted)(GtkRange*, bool);
typedef void (*Ptr_gtk_container_add)(GtkContainer *container, GtkWidget *widget);
typedef GtkIconSet* (*Ptr_gtk_icon_factory_lookup_default) (const gchar*);
@@ -198,6 +199,7 @@ typedef void (*Ptr_gtk_paint_arrow) (GtkStyle*,GdkWindow*, GtkStateType, GtkSha
typedef void (*Ptr_gtk_paint_option) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint);
typedef void (*Ptr_gtk_paint_flat_box) (GtkStyle*,GdkWindow*, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint , gint , gint , gint);
typedef void (*Ptr_gtk_paint_extension) (GtkStyle *, GdkWindow *, GtkStateType, GtkShadowType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint, gint, GtkPositionType);
+typedef void (*Ptr_gtk_adjustment_configure) (GtkAdjustment *, double, double, double, double, double, double);
typedef GtkObject* (*Ptr_gtk_adjustment_new) (double, double, double, double, double, double);
typedef void (*Ptr_gtk_paint_hline) (GtkStyle *, GdkWindow *, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint y);
typedef void (*Ptr_gtk_paint_vline) (GtkStyle *, GdkWindow *, GtkStateType, const GdkRectangle *, GtkWidget *, const gchar *, gint, gint, gint);
@@ -393,7 +395,8 @@ public:
static Ptr_gtk_progress_bar_new gtk_progress_bar_new;
static Ptr_gtk_container_add gtk_container_add;
static Ptr_gtk_menu_shell_append gtk_menu_shell_append;
- static Ptr_gtk_progress_set_adjustment gtk_progress_set_adjustment;
+ static Ptr_gtk_progress_configure gtk_progress_configure;
+ static Ptr_gtk_range_get_adjustment gtk_range_get_adjustment;
static Ptr_gtk_range_set_adjustment gtk_range_set_adjustment;
static Ptr_gtk_range_set_inverted gtk_range_set_inverted;
static Ptr_gtk_icon_factory_lookup_default gtk_icon_factory_lookup_default;
@@ -416,6 +419,7 @@ public:
static Ptr_gtk_paint_arrow gtk_paint_arrow;
static Ptr_gtk_paint_handle gtk_paint_handle;
static Ptr_gtk_paint_expander gtk_paint_expander;
+ static Ptr_gtk_adjustment_configure gtk_adjustment_configure;
static Ptr_gtk_adjustment_new gtk_adjustment_new;
static Ptr_gtk_paint_vline gtk_paint_vline;
static Ptr_gtk_paint_hline gtk_paint_hline;
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 39b0eacdc9..ac05789cff 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -1566,8 +1566,7 @@ void QMacStylePrivate::timerEvent(QTimerEvent *)
progressBars.removeAt(i);
} else {
if (QProgressBar *pb = qobject_cast<QProgressBar *>(maybeProgress)) {
- if (pb->maximum() == 0 || pb->value() > 0
- && pb->value() < pb->maximum()) {
+ if (pb->maximum() == 0 || (pb->value() > 0 && pb->value() < pb->maximum())) {
if (doAnimate(AquaProgressBar))
pb->update();
}
@@ -1642,7 +1641,7 @@ bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e)
case QEvent::FocusOut:
case QEvent::Show:
case QEvent::WindowActivate: {
- QList<QPushButton *> list = qFindChildren<QPushButton *>(btn->window());
+ QList<QPushButton *> list = btn->window()->findChildren<QPushButton *>();
for (int i = 0; i < list.size(); ++i) {
QPushButton *pBtn = list.at(i);
if ((e->type() == QEvent::FocusOut
@@ -1948,10 +1947,9 @@ void QMacStyle::unpolish(QWidget* w)
rubber->setAttribute(Qt::WA_NoSystemBackground, true);
}
- if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w)) {
+ if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w))
frame->setAttribute(Qt::WA_NoSystemBackground, true);
- frame->setAutoFillBackground(true);
- }
+
QWindowsStyle::unpolish(w);
}
@@ -3609,7 +3607,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
break;
}
}
- bool stretchTabs = (!verticalTabs && tabRect.height() > 22 || verticalTabs && tabRect.width() > 22);
+ bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22);
switch (tp) {
case QStyleOptionTab::Beginning:
@@ -4034,7 +4032,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bdi.version = qt_mac_hitheme_version;
bdi.state = kThemeMenuBarNormal;
bdi.attributes = 0;
- HIRect hirect = qt_hirectForQRect(mi->rect);
HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal);
}
@@ -5336,8 +5333,8 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
case SC_GroupBoxCheckBox: {
// Cheat and use the smaller font if we need to
bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
- bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)
- || !QApplication::desktopSettingsAware());
+ bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont))
+ || !QApplication::desktopSettingsAware();
int tw;
int h;
int margin = flat || hasNoText ? 0 : 12;
@@ -5540,6 +5537,57 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
// hack to work around horrible sizeHint() code in QAbstractSpinBox
sz.setHeight(sz.height() - 3);
break;
+ case QStyle::CT_TabWidget:
+ // the size between the pane and the "contentsRect" (+4,+4)
+ // (the "contentsRect" is on the inside of the pane)
+ sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget);
+ /**
+ This is supposed to show the relationship between the tabBar and
+ the stack widget of a QTabWidget.
+ Unfortunately ascii is not a good way of representing graphics.....
+ PS: The '=' line is the painted frame.
+
+ top ---+
+ |
+ |
+ |
+ | vvv just outside the painted frame is the "pane"
+ - -|- - - - - - - - - - <-+
+ TAB BAR +=====^============ | +2 pixels
+ - - -|- - -|- - - - - - - <-+
+ | | ^ ^^^ just inside the painted frame is the "contentsRect"
+ | | |
+ | overlap |
+ | | |
+ bottom ------+ <-+ +14 pixels
+ |
+ v
+ ------------------------------ <- top of stack widget
+
+
+ To summarize:
+ * 2 is the distance between the pane and the contentsRect
+ * The 14 and the 1's are the distance from the contentsRect to the stack widget.
+ (same value as used in SE_TabWidgetTabContents)
+ * overlap is how much the pane should overlap the tab bar
+ */
+ // then add the size between the stackwidget and the "contentsRect"
+
+ if (const QStyleOptionTabWidgetFrame *twf
+ = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ QSize extra(0,0);
+ const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget);
+ const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap;
+
+ if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) {
+ extra = QSize(2, gapBetweenTabbarAndStackWidget + 1);
+ } else {
+ extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2);
+ }
+ sz+= extra;
+ }
+
+ break;
case QStyle::CT_TabBarTab:
if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget);
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 3698818af9..02ce60efab 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -1054,7 +1054,7 @@ void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOpt
bool reverse = option->direction == Qt::RightToLeft;
QStyleOptionFrame frameOpt;
#ifndef QT_NO_LINEEDIT
- if (QLineEdit *lineedit = qFindChild<QLineEdit *>(widget))
+ if (QLineEdit *lineedit = widget->findChild<QLineEdit *>())
frameOpt.initFrom(lineedit);
#else
Q_UNUSED(widget)
@@ -1362,11 +1362,8 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
// Panel of a line edit inside combo box or spin box is drawn in CC_ComboBox and CC_SpinBox
if (widget) {
-#ifndef QT_NO_COMBOBOX
- if (qobject_cast<const QComboBox *>(widget->parentWidget()))
- break;
-#endif
#ifndef QT_NO_SPINBOX
+ // Spinbox doesn't need a separate palette for the lineedit
if (qobject_cast<const QAbstractSpinBox *>(widget->parentWidget()))
break;
#endif
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index bf3a240a84..c5e95f2e29 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -1417,7 +1417,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
bool isScrollBarVisible = false;
int scrollBarWidth = 0;
- QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget);
+ QList<QScrollBar *> scrollBars = widget->findChildren<QScrollBar *>();
for (int i = 0; i < scrollBars.size(); ++i) {
QScrollBar *scrollBar = scrollBars.at(i);
if (scrollBar && scrollBar->orientation() == Qt::Vertical) {
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 2b3dffcd73..1b13d8c046 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -99,14 +99,7 @@ public:
};
-static QHash<const QWidget *, QVector<StyleRule> > *styleRulesCache = 0;
-static QHash<const QWidget *, QHash<int, bool> > *hasStyleRuleCache = 0;
-typedef QHash<int, QHash<quint64, QRenderRule> > QRenderRules;
-static QHash<const QWidget *, QRenderRules> *renderRulesCache = 0;
-static QHash<const QWidget *, QPalette> *customPaletteWidgets = 0; // widgets whose palette we tampered
-static QHash<const void *, StyleSheet> *styleSheetCache = 0; // parsed style sheets
-static QSet<const QWidget *> *autoFillDisabledWidgets = 0;
-
+static QStyleSheetStyleCaches *styleSheetCaches = 0;
/* RECURSION_GUARD:
* the QStyleSheetStyle is a proxy. If used with others proxy style, we may end up with something like:
@@ -1525,8 +1518,8 @@ private:
QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
{
- QHash<const QWidget *, QVector<StyleRule> >::const_iterator cacheIt = styleRulesCache->constFind(w);
- if (cacheIt != styleRulesCache->constEnd())
+ QHash<const QWidget *, QVector<StyleRule> >::const_iterator cacheIt = styleSheetCaches->styleRulesCache.constFind(w);
+ if (cacheIt != styleSheetCaches->styleRulesCache.constEnd())
return cacheIt.value();
if (!initWidget(w)) {
@@ -1536,12 +1529,12 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
QStyleSheetStyleSelector styleSelector;
StyleSheet defaultSs;
- QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCache->constFind(baseStyle());
- if (defaultCacheIt == styleSheetCache->constEnd()) {
+ QHash<const void *, StyleSheet>::const_iterator defaultCacheIt = styleSheetCaches->styleSheetCache.constFind(baseStyle());
+ if (defaultCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
defaultSs = getDefaultStyleSheet();
QStyle *bs = baseStyle();
- styleSheetCache->insert(bs, defaultSs);
- QObject::connect(bs, SIGNAL(destroyed(QObject*)), this, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection);
+ styleSheetCaches->styleSheetCache.insert(bs, defaultSs);
+ QObject::connect(bs, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(styleDestroyed(QObject*)), Qt::UniqueConnection);
} else {
defaultSs = defaultCacheIt.value();
}
@@ -1549,8 +1542,8 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
if (!qApp->styleSheet().isEmpty()) {
StyleSheet appSs;
- QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCache->constFind(qApp);
- if (appCacheIt == styleSheetCache->constEnd()) {
+ QHash<const void *, StyleSheet>::const_iterator appCacheIt = styleSheetCaches->styleSheetCache.constFind(qApp);
+ if (appCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
QString ss = qApp->styleSheet();
if (ss.startsWith(QLatin1String("file:///")))
ss.remove(0, 8);
@@ -1559,7 +1552,7 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
qWarning("Could not parse application stylesheet");
appSs.origin = StyleSheetOrigin_Inline;
appSs.depth = 1;
- styleSheetCache->insert(qApp, appSs);
+ styleSheetCaches->styleSheetCache.insert(qApp, appSs);
} else {
appSs = appCacheIt.value();
}
@@ -1571,8 +1564,8 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
if (wid->styleSheet().isEmpty())
continue;
StyleSheet ss;
- QHash<const void *, StyleSheet>::const_iterator widCacheIt = styleSheetCache->constFind(wid);
- if (widCacheIt == styleSheetCache->constEnd()) {
+ QHash<const void *, StyleSheet>::const_iterator widCacheIt = styleSheetCaches->styleSheetCache.constFind(wid);
+ if (widCacheIt == styleSheetCaches->styleSheetCache.constEnd()) {
parser.init(wid->styleSheet());
if (!parser.parse(&ss)) {
parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}'));
@@ -1580,7 +1573,7 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
qWarning("Could not parse stylesheet of widget %p", wid);
}
ss.origin = StyleSheetOrigin_Inline;
- styleSheetCache->insert(wid, ss);
+ styleSheetCaches->styleSheetCache.insert(wid, ss);
} else {
ss = widCacheIt.value();
}
@@ -1595,7 +1588,7 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
StyleSelector::NodePtr n;
n.ptr = (void *)w;
QVector<QCss::StyleRule> rules = styleSelector.styleRulesForNode(n);
- styleRulesCache->insert(w, rules);
+ styleSheetCaches->styleRulesCache.insert(w, rules);
return rules;
}
@@ -1724,7 +1717,7 @@ static void qt_check_if_internal_widget(const QWidget **w, int *element)
QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, int element, quint64 state) const
{
qt_check_if_internal_widget(&w, &element);
- QHash<quint64, QRenderRule> &cache = (*renderRulesCache)[w][element];
+ QHash<quint64, QRenderRule> &cache = styleSheetCaches->renderRulesCache[w][element];
QHash<quint64, QRenderRule>::const_iterator cacheIt = cache.constFind(state);
if (cacheIt != cache.constEnd())
return cacheIt.value();
@@ -2035,7 +2028,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *o
bool QStyleSheetStyle::hasStyleRule(const QWidget *w, int part) const
{
- QHash<int, bool> &cache = (*hasStyleRuleCache)[w];
+ QHash<int, bool> &cache = styleSheetCaches->hasStyleRuleCache[w];
QHash<int, bool>::const_iterator cacheIt = cache.constFind(part);
if (cacheIt != cache.constEnd())
return cacheIt.value();
@@ -2342,7 +2335,7 @@ static QWidget *embeddedWidget(QWidget *w)
#ifndef QT_NO_SPINBOX
if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w))
- return qFindChild<QLineEdit *>(sb);
+ return sb->findChild<QLineEdit *>();
#endif
#ifndef QT_NO_SCROLLAREA
@@ -2565,7 +2558,7 @@ void QStyleSheetStyle::setPalette(QWidget *w)
rule.configurePalette(&p, map[i].group, ew, ew != w);
}
- customPaletteWidgets->insert(w, w->palette());
+ styleSheetCaches->customPaletteWidgets.insert(w, w->palette());
w->setPalette(p);
if (ew != w)
ew->setPalette(p);
@@ -2573,32 +2566,32 @@ void QStyleSheetStyle::setPalette(QWidget *w)
void QStyleSheetStyle::unsetPalette(QWidget *w)
{
- if (customPaletteWidgets->contains(w)) {
- QPalette p = customPaletteWidgets->value(w);
+ if (styleSheetCaches->customPaletteWidgets.contains(w)) {
+ QPalette p = styleSheetCaches->customPaletteWidgets.value(w);
w->setPalette(p);
QWidget *ew = embeddedWidget(w);
if (ew != w)
ew->setPalette(p);
- customPaletteWidgets->remove(w);
+ styleSheetCaches->customPaletteWidgets.remove(w);
}
QVariant oldFont = w->property("_q_styleSheetWidgetFont");
if (oldFont.isValid()) {
- w->setFont(qVariantValue<QFont>(oldFont));
+ w->setFont(qvariant_cast<QFont>(oldFont));
}
- if (autoFillDisabledWidgets->contains(w)) {
+ if (styleSheetCaches->autoFillDisabledWidgets.contains(w)) {
embeddedWidget(w)->setAutoFillBackground(true);
- autoFillDisabledWidgets->remove(w);
+ styleSheetCaches->autoFillDisabledWidgets.remove(w);
}
}
static void updateWidgets(const QList<const QWidget *>& widgets)
{
- if (!styleRulesCache->isEmpty() || !hasStyleRuleCache->isEmpty() || !renderRulesCache->isEmpty()) {
+ if (!styleSheetCaches->styleRulesCache.isEmpty() || !styleSheetCaches->hasStyleRuleCache.isEmpty() || !styleSheetCaches->renderRulesCache.isEmpty()) {
for (int i = 0; i < widgets.size(); ++i) {
const QWidget *widget = widgets.at(i);
- styleRulesCache->remove(widget);
- hasStyleRuleCache->remove(widget);
- renderRulesCache->remove(widget);
+ styleSheetCaches->styleRulesCache.remove(widget);
+ styleSheetCaches->hasStyleRuleCache.remove(widget);
+ styleSheetCaches->renderRulesCache.remove(widget);
}
}
for (int i = 0; i < widgets.size(); ++i) {
@@ -2622,12 +2615,7 @@ QStyleSheetStyle::QStyleSheetStyle(QStyle *base)
{
++numinstances;
if (numinstances == 1) {
- styleRulesCache = new QHash<const QWidget *, QVector<StyleRule> >;
- hasStyleRuleCache = new QHash<const QWidget *, QHash<int, bool> >;
- renderRulesCache = new QHash<const QWidget *, QRenderRules>;
- customPaletteWidgets = new QHash<const QWidget *, QPalette>;
- styleSheetCache = new QHash<const void *, StyleSheet>;
- autoFillDisabledWidgets = new QSet<const QWidget *>;
+ styleSheetCaches = new QStyleSheetStyleCaches;
}
}
@@ -2635,18 +2623,7 @@ QStyleSheetStyle::~QStyleSheetStyle()
{
--numinstances;
if (numinstances == 0) {
- delete styleRulesCache;
- styleRulesCache = 0;
- delete hasStyleRuleCache;
- hasStyleRuleCache = 0;
- delete renderRulesCache;
- renderRulesCache = 0;
- delete customPaletteWidgets;
- customPaletteWidgets = 0;
- delete styleSheetCache;
- styleSheetCache = 0;
- delete autoFillDisabledWidgets;
- autoFillDisabledWidgets = 0;
+ delete styleSheetCaches;
}
}
QStyle *QStyleSheetStyle::baseStyle() const
@@ -2658,19 +2635,19 @@ QStyle *QStyleSheetStyle::baseStyle() const
return QApplication::style();
}
-void QStyleSheetStyle::widgetDestroyed(QObject *o)
+void QStyleSheetStyleCaches::widgetDestroyed(QObject *o)
{
- styleRulesCache->remove((const QWidget *)o);
- hasStyleRuleCache->remove((const QWidget *)o);
- renderRulesCache->remove((const QWidget *)o);
- customPaletteWidgets->remove((const QWidget *)o);
- styleSheetCache->remove((const QWidget *)o);
- autoFillDisabledWidgets->remove((const QWidget *)o);
+ styleRulesCache.remove((const QWidget *)o);
+ hasStyleRuleCache.remove((const QWidget *)o);
+ renderRulesCache.remove((const QWidget *)o);
+ customPaletteWidgets.remove((const QWidget *)o);
+ styleSheetCache.remove((const QWidget *)o);
+ autoFillDisabledWidgets.remove((const QWidget *)o);
}
-void QStyleSheetStyle::styleDestroyed(QObject *o)
+void QStyleSheetStyleCaches::styleDestroyed(QObject *o)
{
- styleSheetCache->remove(o);
+ styleSheetCache.remove(o);
}
/*!
@@ -2688,7 +2665,7 @@ bool QStyleSheetStyle::initWidget(const QWidget *w) const
return false;
const_cast<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true);
- QObject::connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(widgetDestroyed(QObject*)));
+ QObject::connect(w, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(widgetDestroyed(QObject*)), Qt::UniqueConnection);
return true;
}
@@ -2700,12 +2677,12 @@ void QStyleSheetStyle::polish(QWidget *w)
if (!initWidget(w))
return;
- if (styleRulesCache->contains(w)) {
+ if (styleSheetCaches->styleRulesCache.contains(w)) {
// the widget accessed its style pointer before polish (or repolish)
// (exemple: the QAbstractSpinBox constructor ask for the stylehint)
- styleRulesCache->remove(w);
- hasStyleRuleCache->remove(w);
- renderRulesCache->remove(w);
+ styleSheetCaches->styleRulesCache.remove(w);
+ styleSheetCaches->hasStyleRuleCache.remove(w);
+ styleSheetCaches->renderRulesCache.remove(w);
}
setGeometry(w);
setProperties(w);
@@ -2771,7 +2748,7 @@ void QStyleSheetStyle::polish(QWidget *w)
QWidget *ew = embeddedWidget(w);
if (ew->autoFillBackground()) {
ew->setAutoFillBackground(false);
- autoFillDisabledWidgets->insert(w);
+ styleSheetCaches->autoFillDisabledWidgets.insert(w);
if (ew != w) { //eg. viewport of a scrollarea
//(in order to draw the background anyway in case we don't.)
ew->setAttribute(Qt::WA_StyledBackground, true);
@@ -2795,20 +2772,20 @@ void QStyleSheetStyle::polish(QPalette &pal)
void QStyleSheetStyle::repolish(QWidget *w)
{
- QList<const QWidget *> children = qFindChildren<const QWidget *>(w, QString());
+ QList<const QWidget *> children = w->findChildren<const QWidget *>(QString());
children.append(w);
- styleSheetCache->remove(w);
+ styleSheetCaches->styleSheetCache.remove(w);
updateWidgets(children);
}
void QStyleSheetStyle::repolish(QApplication *app)
{
Q_UNUSED(app);
- const QList<const QWidget*> allWidgets = styleRulesCache->keys();
- styleSheetCache->remove(qApp);
- styleRulesCache->clear();
- hasStyleRuleCache->clear();
- renderRulesCache->clear();
+ const QList<const QWidget*> allWidgets = styleSheetCaches->styleRulesCache.keys();
+ styleSheetCaches->styleSheetCache.remove(qApp);
+ styleSheetCaches->styleRulesCache.clear();
+ styleSheetCaches->hasStyleRuleCache.clear();
+ styleSheetCaches->renderRulesCache.clear();
updateWidgets(allWidgets);
}
@@ -2819,10 +2796,10 @@ void QStyleSheetStyle::unpolish(QWidget *w)
return;
}
- styleRulesCache->remove(w);
- hasStyleRuleCache->remove(w);
- renderRulesCache->remove(w);
- styleSheetCache->remove(w);
+ styleSheetCaches->styleRulesCache.remove(w);
+ styleSheetCaches->hasStyleRuleCache.remove(w);
+ styleSheetCaches->renderRulesCache.remove(w);
+ styleSheetCaches->styleSheetCache.remove(w);
unsetPalette(w);
w->setProperty("_q_stylesheet_minw", QVariant());
w->setProperty("_q_stylesheet_minh", QVariant());
@@ -2849,10 +2826,10 @@ void QStyleSheetStyle::unpolish(QApplication *app)
{
baseStyle()->unpolish(app);
RECURSION_GUARD(return)
- styleRulesCache->clear();
- hasStyleRuleCache->clear();
- renderRulesCache->clear();
- styleSheetCache->remove(qApp);
+ styleSheetCaches->styleRulesCache.clear();
+ styleSheetCaches->hasStyleRuleCache.clear();
+ styleSheetCaches->renderRulesCache.clear();
+ styleSheetCaches->styleSheetCache.remove(qApp);
}
#ifndef QT_NO_TABBAR
@@ -3048,6 +3025,13 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window);
drawItemText(p, labelRect, alignment, pal, gb->state & State_Enabled,
gb->text, QPalette::WindowText);
+
+ if (gb->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*gb);
+ fropt.rect = labelRect;
+ drawPrimitive(PE_FrameFocusRect, &fropt, p, w);
+ }
}
return;
@@ -4150,6 +4134,10 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_DownArrow;
break;
+ case PE_IndicatorArrowUp:
+ pseudoElement = PseudoElement_UpArrow;
+ break;
+
case PE_IndicatorRadioButton:
pseudoElement = PseudoElement_ExclusiveIndicator;
break;
@@ -4250,7 +4238,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
case PE_Widget:
if (!rule.hasDrawable()) {
QWidget *container = containerWidget(w);
- if (autoFillDisabledWidgets->contains(container)
+ if (styleSheetCaches->autoFillDisabledWidgets.contains(container)
&& (container == w || !renderRule(container, opt).hasBackground())) {
//we do not have a background, but we disabled the autofillbackground anyway. so fill the background now.
// (this may happen if we have rules like :focus)
@@ -5074,7 +5062,7 @@ QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon,
if (!s.isEmpty()) {
QRenderRule rule = renderRule(w, opt);
if (rule.hasStyleHint(s))
- return qVariantValue<QIcon>(rule.styleHint(s));
+ return qvariant_cast<QIcon>(rule.styleHint(s));
}
return baseStyle()->standardIcon(standardIcon, opt, w);
}
@@ -5092,7 +5080,7 @@ QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QS
if (!s.isEmpty()) {
QRenderRule rule = renderRule(w, opt);
if (rule.hasStyleHint(s)) {
- QIcon icon = qVariantValue<QIcon>(rule.styleHint(s));
+ QIcon icon = qvariant_cast<QIcon>(rule.styleHint(s));
return icon.pixmap(16, 16); // ###: unhard-code this if someone complains
}
}
@@ -5186,7 +5174,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
case SH_ComboBox_PopupFrameStyle:
#ifndef QT_NO_COMBOBOX
if (qobject_cast<const QComboBox *>(w)) {
- QAbstractItemView *view = qFindChild<QAbstractItemView *>(w);
+ QAbstractItemView *view = w->findChild<QAbstractItemView *>();
if (view) {
view->ensurePolished();
QRenderRule subRule = renderRule(view, PseudoElement_None);
diff --git a/src/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h
index 38c51f553e..1f331b2642 100644
--- a/src/gui/styles/qstylesheetstyle_p.h
+++ b/src/gui/styles/qstylesheetstyle_p.h
@@ -145,10 +145,6 @@ protected Q_SLOTS:
protected:
bool event(QEvent *e);
-private Q_SLOTS:
- void widgetDestroyed(QObject *);
- void styleDestroyed(QObject *);
-
private:
int refcount;
@@ -186,6 +182,22 @@ private:
Q_DECLARE_PRIVATE(QStyleSheetStyle)
};
+class QStyleSheetStyleCaches : public QObject
+{
+ Q_OBJECT
+public Q_SLOTS:
+ void widgetDestroyed(QObject *);
+ void styleDestroyed(QObject *);
+public:
+ QHash<const QWidget *, QVector<QCss::StyleRule> > styleRulesCache;
+ QHash<const QWidget *, QHash<int, bool> > hasStyleRuleCache;
+ typedef QHash<int, QHash<quint64, QRenderRule> > QRenderRules;
+ QHash<const QWidget *, QRenderRules> renderRulesCache;
+ QHash<const QWidget *, QPalette> customPaletteWidgets; // widgets whose palette we tampered
+ QHash<const void *, QCss::StyleSheet> styleSheetCache; // parsed style sheets
+ QSet<const QWidget *> autoFillDisabledWidgets;
+};
+
QT_END_NAMESPACE
#endif // QT_NO_STYLE_STYLESHEET
diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp
index 7fd9f20443..d7947bc653 100644
--- a/src/gui/styles/qwindowscestyle.cpp
+++ b/src/gui/styles/qwindowscestyle.cpp
@@ -2294,6 +2294,7 @@ int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QW
break;
case SH_EtchDisabledText:
ret = false;
+ break;
case SH_RequestSoftwareInputPanel:
ret = RSIP_OnMouseClick;
break;
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index e7598a2c2c..44f3f92d8b 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -176,7 +176,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
widget = widget->window();
// Alt has been pressed - find all widgets that care
- QList<QWidget *> l = qFindChildren<QWidget *>(widget);
+ QList<QWidget *> l = widget->findChildren<QWidget *>();
for (int pos=0 ; pos < l.size() ; ++pos) {
QWidget *w = l.at(pos);
if (w->isWindow() || !w->isVisible() ||
@@ -199,7 +199,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
// Update state and repaint the menu bars.
d->alt_down = false;
#ifndef QT_NO_MENUBAR
- QList<QMenuBar *> l = qFindChildren<QMenuBar *>(widget);
+ QList<QMenuBar *> l = widget->findChildren<QMenuBar *>();
for (int i = 0; i < l.size(); ++i)
l.at(i)->update();
#endif
@@ -1161,7 +1161,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
if (!menuBar && qobject_cast<const QMenu *>(widget)) {
QWidget *w = QApplication::activeWindow();
if (w && w != widget)
- menuBar = qFindChild<QMenuBar *>(w);
+ menuBar = w->findChild<QMenuBar *>();
}
// If we paint a menu bar draw underlines if is in the keyboardState
if (menuBar) {
diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp
index 24d8555927..7f1a3ab678 100644
--- a/src/gui/styles/qwindowsvistastyle.cpp
+++ b/src/gui/styles/qwindowsvistastyle.cpp
@@ -588,10 +588,6 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget()))
resolve_mask = spinbox->palette().resolve();
#endif // QT_NO_SPINBOX
-#ifndef QT_NO_COMBOBOX
- if (QComboBox *combobox = qobject_cast<QComboBox*>(widget->parentWidget()))
- resolve_mask = combobox->palette().resolve();
-#endif // QT_NO_COMBOBOX
}
if (resolve_mask & (1 << QPalette::Base)) {
// Base color is set for this widget, so use it
@@ -842,10 +838,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
const QDialogButtonBox *buttonBox = 0;
if (qobject_cast<const QMessageBox *> (widget))
- buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
+ buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
#ifndef QT_NO_INPUTDIALOG
else if (qobject_cast<const QInputDialog *> (widget))
- buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
+ buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
#endif // QT_NO_INPUTDIALOG
if (buttonBox) {
@@ -2396,14 +2392,14 @@ void QWindowsVistaStyle::polish(QWidget *widget)
}
} else if (qobject_cast<QMessageBox *> (widget)) {
widget->setAttribute(Qt::WA_StyledBackground);
- QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
+ QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
if (buttonBox)
buttonBox->setContentsMargins(0, 9, 0, 0);
}
#ifndef QT_NO_INPUTDIALOG
else if (qobject_cast<QInputDialog *> (widget)) {
widget->setAttribute(Qt::WA_StyledBackground);
- QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
+ QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
if (buttonBox)
buttonBox->setContentsMargins(0, 9, 0, 0);
}
@@ -2435,14 +2431,14 @@ void QWindowsVistaStyle::unpolish(QWidget *widget)
widget->setAttribute(Qt::WA_Hover, false);
else if (qobject_cast<QMessageBox *> (widget)) {
widget->setAttribute(Qt::WA_StyledBackground, false);
- QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox"));
+ QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
if (buttonBox)
buttonBox->setContentsMargins(0, 0, 0, 0);
}
#ifndef QT_NO_INPUTDIALOG
else if (qobject_cast<QInputDialog *> (widget)) {
widget->setAttribute(Qt::WA_StyledBackground, false);
- QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox"));
+ QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
if (buttonBox)
buttonBox->setContentsMargins(0, 0, 0, 0);
}
diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp
index 629a8c639c..74a20fce29 100644
--- a/src/gui/styles/qwindowsxpstyle.cpp
+++ b/src/gui/styles/qwindowsxpstyle.cpp
@@ -4054,7 +4054,7 @@ void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h)
bufferPos += sprintf(bufferPos, "\n};\n\n");
printf(bufferDump);
- delete bufferDump;
+ delete[] bufferDump;
++pCount;
}
}
diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri
index b22a908fdf..b6eeec9af8 100644
--- a/src/gui/styles/styles.pri
+++ b/src/gui/styles/styles.pri
@@ -35,7 +35,7 @@ contains( styles, all ) {
styles = mac windows windowsxp windowsvista
}
-x11|embedded|!macx-*:styles -= mac
+x11|embedded|qpa|!macx-*:styles -= mac
x11{
QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE
diff --git a/src/gui/symbian/qsymbianevent.cpp b/src/gui/symbian/qsymbianevent.cpp
index 5c54532e08..e177d1702b 100644
--- a/src/gui/symbian/qsymbianevent.cpp
+++ b/src/gui/symbian/qsymbianevent.cpp
@@ -40,6 +40,9 @@
****************************************************************************/
#include "qsymbianevent.h"
+#include <qdebug.h>
+
+#include <w32std.h>
QT_BEGIN_NAMESPACE
@@ -140,4 +143,34 @@ int QSymbianEvent::resourceChangeType() const
return (m_type == ResourceChangeEvent) ? m_eventValue : 0;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QSymbianEvent *o)
+{
+ if (!o) {
+ dbg << "QSymbianEvent(0x0)";
+ return dbg;
+ }
+ dbg.nospace() << "QSymbianEvent(";
+ switch (o->type()) {
+ case QSymbianEvent::InvalidEvent:
+ dbg << "InvalidEvent";
+ break;
+ case QSymbianEvent::WindowServerEvent:
+ dbg << "WindowServerEvent, Type = " << o->windowServerEvent()->Type();
+ break;
+ case QSymbianEvent::CommandEvent:
+ dbg << "CommandEvent, command = " << o->command();
+ break;
+ case QSymbianEvent::ResourceChangeEvent:
+ dbg << "ResourceChangeEvent, resourceChangeType = " << o->resourceChangeType();
+ break;
+ default:
+ dbg << "Unknown event type";
+ break;
+ }
+ dbg << ")";
+ return dbg.space();
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/symbian/qsymbianevent.h b/src/gui/symbian/qsymbianevent.h
index 5fd5a9e601..cf05f63176 100644
--- a/src/gui/symbian/qsymbianevent.h
+++ b/src/gui/symbian/qsymbianevent.h
@@ -95,6 +95,10 @@ inline bool QSymbianEvent::isValid() const
return m_type != InvalidEvent;
}
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QSymbianEvent *o);
+#endif
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 5aac5ea6c6..54ca7cc802 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -68,6 +68,8 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-background-role", QtBackgroundRole },
{ "-qt-block-indent", QtBlockIndent },
{ "-qt-list-indent", QtListIndent },
+ { "-qt-list-number-prefix", QtListNumberPrefix },
+ { "-qt-list-number-suffix", QtListNumberSuffix },
{ "-qt-paragraph-type", QtParagraphType },
{ "-qt-style-features", QtStyleFeatures },
{ "-qt-table-type", QtTableType },
@@ -120,6 +122,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "image", QtImage },
{ "image-position", QtImageAlignment },
{ "left", Left },
+ { "line-height", LineHeight },
{ "list-style", ListStyle },
{ "list-style-type", ListStyleType },
{ "margin" , Margin },
@@ -403,7 +406,7 @@ int ValueExtractor::lengthValue(const Declaration &decl)
if (decl.d->values.count() < 1)
return 0;
LengthData data = lengthValue(decl.d->values.at(0));
- decl.d->parsed = qVariantFromValue<LengthData>(data);
+ decl.d->parsed = QVariant::fromValue<LengthData>(data);
return lengthValueFromData(data,f);
}
@@ -435,7 +438,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m)
QList<QVariant> v;
for (i = 0; i < 4; i++) {
- v += qVariantFromValue<LengthData>(datas[i]);
+ v += QVariant::fromValue<LengthData>(datas[i]);
m[i] = lengthValueFromData(datas[i], f);
}
decl.d->parsed = v;
@@ -541,7 +544,7 @@ QSize ValueExtractor::sizeValue(const Declaration &decl)
else
x[1] = x[0];
QList<QVariant> v;
- v << qVariantFromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]);
+ v << QVariant::fromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]);
decl.d->parsed = v;
return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f));
}
@@ -916,7 +919,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
data.width = lengthValue(decl.d->values.at(i));
*width = lengthValueFromData(data.width, f);
if (++i >= decl.d->values.count()) {
- decl.d->parsed = qVariantFromValue<BorderData>(data);
+ decl.d->parsed = QVariant::fromValue<BorderData>(data);
return;
}
}
@@ -925,7 +928,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
if (data.style != BorderStyle_Unknown) {
*style = data.style;
if (++i >= decl.d->values.count()) {
- decl.d->parsed = qVariantFromValue<BorderData>(data);
+ decl.d->parsed = QVariant::fromValue<BorderData>(data);
return;
}
} else {
@@ -935,7 +938,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
data.color = parseBrushValue(decl.d->values.at(i), pal);
*color = brushFromData(data.color, pal);
if (data.color.type != BrushData::DependsOnThePalette)
- decl.d->parsed = qVariantFromValue<BorderData>(data);
+ decl.d->parsed = QVariant::fromValue<BorderData>(data);
}
static void parseShorthandBackgroundProperty(const QVector<Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)
@@ -1032,16 +1035,8 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re
parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal);
*brush = brushFromData(brushData, pal);
if (brushData.type != BrushData::DependsOnThePalette) {
-#if defined Q_CC_MSVC && _MSC_VER <= 1300
- BackgroundData data;
- data.brush = brushData;
- data.image = *image;
- data.repeat = *repeat;
- data.alignment = *alignment;
-#else
BackgroundData data = { brushData, *image, *repeat, *alignment };
-#endif
- decl.d->parsed = qVariantFromValue<BackgroundData>(data);
+ decl.d->parsed = QVariant::fromValue<BackgroundData>(data);
}
}
break;
@@ -1319,10 +1314,10 @@ QColor Declaration::colorValue(const QPalette &pal) const
ColorData color = parseColorValue(d->values.at(0));
if(color.type == ColorData::Role) {
- d->parsed = qVariantFromValue<int>(color.role);
+ d->parsed = QVariant::fromValue<int>(color.role);
return pal.color((QPalette::ColorRole)(color.role));
} else {
- d->parsed = qVariantFromValue<QColor>(color.color);
+ d->parsed = QVariant::fromValue<QColor>(color.color);
return color.color;
}
}
@@ -1342,11 +1337,11 @@ QBrush Declaration::brushValue(const QPalette &pal) const
BrushData data = parseBrushValue(d->values.at(0), pal);
if(data.type == BrushData::Role) {
- d->parsed = qVariantFromValue<int>(data.role);
+ d->parsed = QVariant::fromValue<int>(data.role);
return pal.color((QPalette::ColorRole)(data.role));
} else {
if (data.type != BrushData::DependsOnThePalette)
- d->parsed = qVariantFromValue<QBrush>(data.brush);
+ d->parsed = QVariant::fromValue<QBrush>(data.brush);
return data.brush;
}
}
@@ -1376,11 +1371,11 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const
continue;
BrushData data = parseBrushValue(d->values.at(i), pal);
if(data.type == BrushData::Role) {
- v += qVariantFromValue<int>(data.role);
+ v += QVariant::fromValue<int>(data.role);
c[i] = pal.color((QPalette::ColorRole)(data.role));
} else {
if (data.type != BrushData::DependsOnThePalette) {
- v += qVariantFromValue<QBrush>(data.brush);
+ v += QVariant::fromValue<QBrush>(data.brush);
} else {
v += QVariant();
}
@@ -1453,7 +1448,7 @@ QSize Declaration::sizeValue() const
else
x[1] = x[0];
QSize size(x[0], x[1]);
- d->parsed = qVariantFromValue<QSize>(size);
+ d->parsed = QVariant::fromValue<QSize>(size);
return size;
}
@@ -1475,7 +1470,7 @@ QRect Declaration::rectValue() const
if (args.count() != 4)
return QRect();
QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
- d->parsed = qVariantFromValue<QRect>(rect);
+ d->parsed = QVariant::fromValue<QRect>(rect);
return rect;
}
@@ -1496,10 +1491,10 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const
for (i = 0; i < qMin(d->values.count(), 4); i++) {
ColorData color = parseColorValue(d->values.at(i));
if(color.type == ColorData::Role) {
- v += qVariantFromValue<int>(color.role);
+ v += QVariant::fromValue<int>(color.role);
c[i] = pal.color((QPalette::ColorRole)(color.role));
} else {
- v += qVariantFromValue<QColor>(color.color);
+ v += QVariant::fromValue<QColor>(color.color);
c[i] = color.color;
}
}
@@ -1691,7 +1686,7 @@ QIcon Declaration::iconValue() const
i++;
}
- d->parsed = qVariantFromValue<QIcon>(icon);
+ d->parsed = QVariant::fromValue<QIcon>(icon);
return icon;
}
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index cb2cfd3c1d..79c46b3664 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -178,6 +178,9 @@ enum Property {
OutlineBottomRightRadius,
FontVariant,
TextTransform,
+ QtListNumberPrefix,
+ QtListNumberSuffix,
+ LineHeight,
NumProperties
};
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 24d8fafe65..084b7ac988 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -75,6 +75,10 @@
#ifdef Q_OS_SYMBIAN
#include <private/qt_s60_p.h>
#endif
+#ifdef Q_WS_QPA
+#include <QtGui/qplatformscreen_qpa.h>
+#include <QtGui/private/qapplication_p.h>
+#endif
#include <QMutexLocker>
@@ -172,6 +176,17 @@ Q_GUI_EXPORT int qt_defaultDpiX()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4)));
+#elif defined(Q_WS_QPA)
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ if (pi) {
+ QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0);
+ const QSize screenSize = screen->geometry().size();
+ const QSize physicalSize = screen->physicalSize();
+ dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4)));
+ } else {
+ //PI has not been initialised, or it is being initialised. Give a default dpi
+ dpi = 100;
+ }
#elif defined(Q_OS_SYMBIAN)
dpi = S60->defaultDpiX;
#endif // Q_WS_X11
@@ -200,6 +215,17 @@ Q_GUI_EXPORT int qt_defaultDpiY()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4)));
+#elif defined(Q_WS_QPA)
+ QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
+ if (pi) {
+ QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0);
+ const QSize screenSize = screen->geometry().size();
+ const QSize physicalSize = screen->physicalSize();
+ dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4)));
+ } else {
+ //PI has not been initialised, or it is being initialised. Give a default dpi
+ dpi = 100;
+ }
#elif defined(Q_OS_SYMBIAN)
dpi = S60->defaultDpiY;
#endif // Q_WS_X11
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 178394bd82..e7e8a40483 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -226,7 +226,10 @@ public:
bool operator<(const QFont &) const;
operator QVariant() const;
bool isCopyOf(const QFont &) const;
-
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QFont &operator=(QFont &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
#ifdef Q_WS_WIN
HFONT handle() const;
@@ -315,6 +318,7 @@ private:
friend class QPainterReplayer;
friend class QPaintBufferEngine;
friend class QCommandLinkButtonPrivate;
+ friend class QFontEngine;
#ifndef QT_NO_DATASTREAM
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &);
diff --git a/src/gui/text/qfont_mac.cpp b/src/gui/text/qfont_mac.cpp
index b2e5f6e981..daf68c03ea 100644
--- a/src/gui/text/qfont_mac.cpp
+++ b/src/gui/text/qfont_mac.cpp
@@ -42,6 +42,7 @@
#include "qfont.h"
#include "qfont_p.h"
#include "qfontengine_p.h"
+#include "qfontengine_mac_p.h"
#include "qfontinfo.h"
#include "qfontmetrics.h"
#include "qpaintdevice.h"
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index bb69aa10ed..0a3f76daef 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -192,6 +192,11 @@ public:
QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); }
QFontPrivate *smallCapsFontPrivate() const;
+ static QFontPrivate *get(const QFont &font)
+ {
+ return font.d.data();
+ }
+
void resolve(uint mask, const QFontPrivate *other);
private:
QFontPrivate &operator=(const QFontPrivate &) { return *this; }
diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp
new file mode 100644
index 0000000000..5fed18bc5e
--- /dev/null
+++ b/src/gui/text/qfont_qpa.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/QPlatformFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+void QFont::initialize()
+{
+ QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
+}
+
+void QFont::cleanup()
+{
+ QFontCache::cleanup();
+}
+
+
+/*****************************************************************************
+ QFont member functions
+ *****************************************************************************/
+
+Qt::HANDLE QFont::handle() const
+{
+ return 0;
+}
+
+QString QFont::rawName() const
+{
+ return QLatin1String("unknown");
+}
+
+void QFont::setRawName(const QString &)
+{
+}
+
+QString QFont::defaultFamily() const
+{
+ QString familyName;
+ switch(d->request.styleHint) {
+ case QFont::Times:
+ familyName = QString::fromLatin1("times");
+ case QFont::Courier:
+ case QFont::Monospace:
+ familyName = QString::fromLatin1("monospace");
+ case QFont::Decorative:
+ familyName = QString::fromLatin1("old english");
+ case QFont::Helvetica:
+ case QFont::System:
+ default:
+ familyName = QString::fromLatin1("helvetica");
+ }
+
+ QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QUnicodeTables::Common);
+ if (list.size()) {
+ familyName = list.at(0);
+ }
+ return familyName;
+}
+
+QString QFont::lastResortFamily() const
+{
+ return QString::fromLatin1("helvetica");
+}
+
+QString QFont::lastResortFont() const
+{
+ qFatal("QFont::lastResortFont: Cannot find any reasonable font");
+ // Shut compiler up
+ return QString();
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 5cecf08bef..20c72dde6b 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -50,13 +50,19 @@
#include "private/qunicodetables_p.h"
#include "qfontengine_p.h"
+#ifdef Q_WS_QPA
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/qplatformfontdatabase_qpa.h>
+#include "qabstractfileengine.h"
+#endif
+
#ifdef Q_WS_X11
#include <locale.h>
#endif
#include <stdlib.h>
#include <limits.h>
-#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
+#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
# include <ft2build.h>
# include FT_TRUETYPE_TABLES_H
#endif
@@ -75,10 +81,6 @@
# define FM_DEBUG if (false) qDebug
#endif
-#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
-# define for if(0){}else for
-#endif
-
QT_BEGIN_NAMESPACE
#define SMOOTH_SCALABLE 0xffff
@@ -143,7 +145,7 @@ struct QtFontEncoding
uchar pitch : 8;
};
-struct QtFontSize
+struct QtFontSize
{
#ifdef Q_WS_X11
QtFontEncoding *encodings;
@@ -151,10 +153,14 @@ struct QtFontSize
uint yres = 0, uint avgwidth = 0, bool add = false);
unsigned short count : 16;
#endif // Q_WS_X11
+
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
QByteArray fileName;
int fileIndex;
-#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QPA)
+ void *handle;
+#endif
unsigned short pixelSize : 16;
};
@@ -230,7 +236,7 @@ struct QtFontStyle
delete [] weightName;
delete [] setwidthName;
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
while (count) {
// bitfield count-- in while condition does not work correctly in mwccsym2
count--;
@@ -240,6 +246,12 @@ struct QtFontStyle
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
pixelSizes[count].fileName.~QByteArray();
#endif
+#if defined (Q_WS_QPA)
+ QPlatformIntegration *integration = QApplicationPrivate::platformIntegration();
+ if (integration) { //on shut down there will be some that we don't release.
+ integration->fontDatabase()->releaseHandle(pixelSizes[count].handle);
+ }
+#endif
}
#endif
free(pixelSizes);
@@ -255,7 +267,7 @@ struct QtFontStyle
const char *weightName;
const char *setwidthName;
#endif // Q_WS_X11
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
bool antialiased;
#endif
@@ -305,6 +317,9 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
new (&pixelSizes[count].fileName) QByteArray;
pixelSizes[count].fileIndex = 0;
#endif
+#if defined(Q_WS_QPA)
+ pixelSizes[count].handle = 0;
+#endif
return pixelSizes + (count++);
}
@@ -361,7 +376,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
}
-struct QtFontFamily
+struct QtFontFamily
{
enum WritingSystemStatus {
Unknown = 0,
@@ -387,9 +402,12 @@ struct QtFontFamily
fixedPitchComputed(false),
#endif
name(n), count(0), foundries(0)
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
, bogusWritingSystems(false)
#endif
+#if defined(Q_WS_QPA)
+ , askedForFallback(false)
+#endif
{
memset(writingSystems, 0, sizeof(writingSystems));
}
@@ -427,10 +445,13 @@ struct QtFontFamily
int count;
QtFontFoundry **foundries;
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
bool bogusWritingSystems;
QStringList fallbackFamilies;
#endif
+#if defined (Q_WS_QPA)
+ bool askedForFallback;
+#endif
unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
QtFontFoundry *foundry(const QString &f, bool = false);
@@ -475,6 +496,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
// ### copied to tools/makeqpf/qpf2.cpp
#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
+
// see the Unicode subset bitfields in the MSDN docs
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
// Any,
@@ -642,6 +664,9 @@ public:
}
int count;
+#if defined(Q_WS_X11) && !defined(QT_NO_FONTCONFIG)
+ QString systemLang;
+#endif
QtFontFamily **families;
struct ApplicationFont {
@@ -667,7 +692,7 @@ public:
bool loadFromCache(const QString &fontPath);
void addQPF2File(const QByteArray &file);
#endif // Q_WS_QWS
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
void addFont(const QString &familyname, const char *foundryname, int weight,
bool italic, int pixelSize, const QByteArray &file, int fileIndex,
bool antialiased,
@@ -678,10 +703,12 @@ public:
#endif
#if defined(Q_WS_QWS)
QDataStream *stream;
- QStringList fallbackFamilies;
#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
const QSymbianFontDatabaseExtras *symbianExtras;
#endif
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ QStringList fallbackFamilies;
+#endif
};
void QFontDatabasePrivate::invalidate()
@@ -730,7 +757,7 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
return families[pos];
}
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
const QByteArray &file, int fileIndex, bool antialiased,
const QList<QFontDatabase::WritingSystem> &writingSystems)
@@ -963,7 +990,7 @@ static void match(int script, const QFontDef &request,
const QString &family_name, const QString &foundry_name, int force_encoding_id,
QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false);
-#if defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef)
{
fontDef->family = desc.family->name;
@@ -992,7 +1019,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
#endif
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA)
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
{
// look for the requested font in the engine data cache
@@ -1053,6 +1080,8 @@ QT_BEGIN_INCLUDE_NAMESPACE
# include "qfontdatabase_win.cpp"
#elif defined(Q_WS_QWS)
# include "qfontdatabase_qws.cpp"
+#elif defined(Q_WS_QPA)
+# include "qfontdatabase_qpa.cpp"
#elif defined(Q_OS_SYMBIAN)
# include "qfontdatabase_s60.cpp"
#endif
@@ -1338,6 +1367,7 @@ static void match(int script, const QFontDef &request,
styleKey.stretch = request.stretch;
char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
+
FM_DEBUG("QFontDatabase::match\n"
" request:\n"
" family: %s [%s], script: %d\n"
@@ -2427,10 +2457,12 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
sample += QChar(0x4f8b);
break;
case Japanese:
- sample += QChar(0x3050);
- sample += QChar(0x3060);
- sample += QChar(0x30b0);
- sample += QChar(0x30c0);
+ sample += QChar(0x30b5);
+ sample += QChar(0x30f3);
+ sample += QChar(0x30d7);
+ sample += QChar(0x30eb);
+ sample += QChar(0x3067);
+ sample += QChar(0x3059);
break;
case Korean:
sample += QChar(0xac00);
@@ -2483,7 +2515,7 @@ void QFontDatabase::createDatabase()
{ initializeDb(); }
// used from qfontengine_ft.cpp
-QByteArray qt_fontdata_from_index(int index)
+Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
{
QMutexLocker locker(fontDatabaseMutex());
return privateDb()->applicationFonts.value(index).data;
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 69a24843dd..3e9483b097 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -152,7 +152,7 @@ public:
private:
static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
-#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request);
#endif
static void load(const QFontPrivate *d, int script);
@@ -167,6 +167,7 @@ private:
friend class QFontEngineMultiXLFD;
friend class QFontEngineMultiQWS;
friend class QFontEngineMultiS60;
+ friend class QFontEngineMultiQPA;
QFontDatabasePrivate *d;
};
diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp
index 6dfec28b02..ad2c1b2ea6 100644
--- a/src/gui/text/qfontdatabase_mac.cpp
+++ b/src/gui/text/qfontdatabase_mac.cpp
@@ -45,6 +45,8 @@
#include <qabstractfileengine.h>
#include <stdlib.h>
#include <qendian.h>
+#include <private/qfontengine_coretext_p.h>
+#include <private/qfontengine_mac_p.h>
QT_BEGIN_NAMESPACE
@@ -293,8 +295,12 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
// previous versions
family_list << QApplication::font().defaultFamily();
+#if defined(QT_MAC_USE_COCOA)
+ QCFString fontName = NULL, familyName = NULL;
+#else
ATSFontFamilyRef familyRef = 0;
ATSFontRef fontRef = 0;
+#endif
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *db = privateDb();
@@ -304,26 +310,20 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
for (int k = 0; k < db->count; ++k) {
if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) {
QByteArray family_name = db->families[k]->name.toUtf8();
+#if defined(QT_MAC_USE_COCOA)
+ QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL);
+ if (ctFont) {
+ fontName = CTFontCopyFullName(ctFont);
+ familyName = CTFontCopyFamilyName(ctFont);
+ goto FamilyFound;
+ }
+#else
familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
if (familyRef) {
fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault);
goto FamilyFound;
- } else {
-#if defined(QT_MAC_USE_COCOA)
- // ATS and CT disagrees on what the family name should be,
- // use CT to look up the font if ATS fails.
- QCFString familyName = QString::fromAscii(family_name);
- QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL);
- QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef);
- QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute);
-
- familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault);
- if (familyRef) {
- fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault);
- goto FamilyFound;
- }
-#endif
}
+#endif
}
}
}
@@ -331,92 +331,18 @@ FamilyFound:
//fill in the engine's font definition
QFontDef fontDef = d->request; //copy..
if(fontDef.pointSize < 0)
- fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi);
+ fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi);
else
- fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi);
-#if 0
- ItemCount name_count;
- if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) {
- ItemCount actualName_size;
- if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) {
- QByteArray actualName(actualName_size);
- if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size)
- fontDef.family = QString::fromUtf8(actualName);
- }
- }
-#else
- {
- QCFString actualName;
- if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
- fontDef.family = actualName;
- }
-#endif
+ fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi);
#ifdef QT_MAC_USE_COCOA
- QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning);
-#elif 1
- QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning);
+ fontDef.family = familyName;
+ QFontEngine *engine = new QCoreTextFontEngineMulti(fontName, fontDef, d->kerning);
#else
- ATSFontFamilyRef atsFamily = familyRef;
- ATSFontFamilyRef atsFontRef = fontRef;
-
- FMFont fontID;
- FMFontFamily fmFamily;
- FMFontStyle fntStyle = 0;
- fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily);
- if (fmFamily == kInvalidFontFamily) {
- // Use the ATSFont then...
- fontID = FMGetFontFromATSFontRef(atsFontRef);
- } else {
- if (fontDef.weight >= QFont::Bold)
- fntStyle |= ::bold;
- if (fontDef.style != QFont::StyleNormal)
- fntStyle |= ::italic;
-
- FMFontStyle intrinsicStyle;
- FMFont fnt = 0;
- if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr)
- fontID = FMGetATSFontRefFromFont(fnt);
- }
-
- OSStatus status;
-
- const int maxAttributeCount = 5;
- ATSUAttributeTag tags[maxAttributeCount + 1];
- ByteCount sizes[maxAttributeCount + 1];
- ATSUAttributeValuePtr values[maxAttributeCount + 1];
- int attributeCount = 0;
-
- Fixed size = FixRatio(fontDef.pixelSize, 1);
- tags[attributeCount] = kATSUSizeTag;
- sizes[attributeCount] = sizeof(size);
- values[attributeCount] = &size;
- ++attributeCount;
-
- tags[attributeCount] = kATSUFontTag;
- sizes[attributeCount] = sizeof(fontID);
- values[attributeCount] = &fontID;
- ++attributeCount;
-
- CGAffineTransform transform = CGAffineTransformIdentity;
- if (fontDef.stretch != 100) {
- transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
- tags[attributeCount] = kATSUFontMatrixTag;
- sizes[attributeCount] = sizeof(transform);
- values[attributeCount] = &transform;
- ++attributeCount;
- }
-
- ATSUStyle style;
- status = ATSUCreateStyle(&style);
- Q_ASSERT(status == noErr);
-
- Q_ASSERT(attributeCount < maxAttributeCount + 1);
- status = ATSUSetAttributes(style, attributeCount, tags, sizes, values);
- Q_ASSERT(status == noErr);
-
- QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0);
- ATSUDisposeStyle(style);
+ QCFString actualName;
+ if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr)
+ fontDef.family = actualName;
+ QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning);
#endif
d->engineData->engine = engine;
engine->ref.ref(); //a ref for the engineData->engine
diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp
new file mode 100644
index 0000000000..e54093ce2e
--- /dev/null
+++ b/src/gui/text/qfontdatabase_qpa.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlibraryinfo.h"
+#include <QtCore/qsettings.h>
+
+#include "qfontengine_qpa_p.h"
+#include "qplatformdefs.h"
+
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/qplatformfontdatabase_qpa.h>
+
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &foundryname, int weight,
+ QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize,
+ const QSupportedWritingSystems &writingSystems, void *handle)
+{
+ QFontDatabasePrivate *d = privateDb();
+ // qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
+ QtFontStyle::Key styleKey;
+ styleKey.style = style;
+ styleKey.weight = weight;
+ styleKey.stretch = stretch;
+ QtFontFamily *f = d->family(familyName, true);
+
+ for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
+ if (writingSystems.supported(QFontDatabase::WritingSystem(i))) {
+ f->writingSystems[i] = QtFontFamily::Supported;
+ } else {
+ f->writingSystems[i] = QtFontFamily::Unsupported;
+ }
+ }
+
+ QtFontFoundry *foundry = f->foundry(foundryname, true);
+ QtFontStyle *fontStyle = foundry->style(styleKey, true);
+ fontStyle->smoothScalable = scalable;
+ fontStyle->antialiased = antialiased;
+ QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
+ size->handle = handle;
+}
+
+static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QUnicodeTables::Script &script)
+{
+ QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,script);
+ QFontDatabasePrivate *db = privateDb();
+
+ QStringList::iterator i;
+ for (i = retList.begin(); i != retList.end(); ++i) {
+ bool contains = false;
+ for (int j = 0; j < db->count; j++) {
+ QtFontFamily *qtFamily = db->families[j];
+ if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) {
+ contains = true;
+ break;
+ }
+ }
+ if (!contains) {
+ i = retList.erase(i);
+ i--;
+ }
+ }
+ return retList;
+}
+
+static void initializeDb()
+{
+ static int initialized = false;
+
+ if (!initialized) {
+ //init by asking for the platformfontdb for the first time :)
+ QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
+ initialized = true;
+ }
+}
+
+#ifndef QT_NO_SETTINGS
+// called from qapplication_qws.cpp
+void qt_applyFontDatabaseSettings(const QSettings &settings)
+{
+ initializeDb();
+ QFontDatabasePrivate *db = privateDb();
+ for (int i = 0; i < db->count; ++i) {
+ QtFontFamily *family = db->families[i];
+ if (settings.contains(family->name))
+ family->fallbackFamilies = settings.value(family->name).toStringList();
+ }
+
+ if (settings.contains(QLatin1String("Global Fallbacks")))
+ db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList();
+}
+#endif // QT_NO_SETTINGS
+
+static inline void load(const QString & = QString(), int = -1)
+{
+ initializeDb();
+}
+
+static
+QFontEngine *loadSingleEngine(int script,
+ const QFontDef &request,
+ QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size)
+{
+ Q_UNUSED(foundry);
+
+ Q_ASSERT(size);
+ int pixelSize = size->pixelSize;
+ if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE))
+ pixelSize = request.pixelSize;
+
+ QFontDef def = request;
+ def.pixelSize = pixelSize;
+
+ QFontCache::Key key(def,script);
+ QFontEngine *engine = QFontCache::instance()->findEngine(key);
+ if (!engine) {
+ QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase();
+ engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle);
+ if (engine) {
+ QFontCache::Key key(def,script);
+ QFontCache::instance()->instance()->insertEngine(key,engine);
+ }
+ }
+ return engine;
+}
+
+static
+QFontEngine *loadEngine(int script, const QFontDef &request,
+ QtFontFamily *family, QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size)
+{
+
+ QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
+ //make sure that the db has all fallback families
+ if (engine
+ && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {
+
+ if (family && !family->askedForFallback) {
+ family->fallbackFamilies = fallbackFamilies(family->name,QFont::Style(style->key.style),QUnicodeTables::Script(script));
+
+ family->askedForFallback = true;
+ }
+
+ QStringList fallbacks = privateDb()->fallbackFamilies;
+ if (family && !family->fallbackFamilies.isEmpty())
+ fallbacks = family->fallbackFamilies;
+
+ engine = new QFontEngineMultiQPA(engine, script, fallbacks);
+ }
+
+ return engine;
+}
+
+static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
+{
+ QFontDatabasePrivate *db = privateDb();
+
+ fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);
+
+ db->reregisterAppFonts = true;
+}
+
+bool QFontDatabase::removeApplicationFont(int handle)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ QFontDatabasePrivate *db = privateDb();
+ if (handle < 0 || handle >= db->applicationFonts.count())
+ return false;
+
+ db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
+
+ db->reregisterAppFonts = true;
+ db->invalidate();
+ return true;
+}
+
+bool QFontDatabase::removeAllApplicationFonts()
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ QFontDatabasePrivate *db = privateDb();
+ if (db->applicationFonts.isEmpty())
+ return false;
+
+ db->applicationFonts.clear();
+ db->invalidate();
+ return true;
+}
+
+bool QFontDatabase::supportsThreadedFontRendering()
+{
+ return true;
+}
+
+/*!
+ \internal
+*/
+QFontEngine *
+QFontDatabase::findFont(int script, const QFontPrivate *fp,
+ const QFontDef &request)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ const int force_encoding_id = -1;
+
+ if (!privateDb()->count)
+ initializeDb();
+
+ QFontEngine *engine;
+ QFontCache::Key key(request, script);
+ engine = QFontCache::instance()->findEngine(key);
+ if (engine) {
+ qDebug() << "Cache hit level 1";
+ return engine;
+ }
+
+ QString family_name, foundry_name;
+
+ parseFontName(request.family, foundry_name, family_name);
+
+ if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
+ engine =new QTestFontEngine(request.pixelSize);
+ engine->fontDef = request;
+ }
+
+ QtFontDesc desc;
+ match(script, request, family_name, foundry_name, force_encoding_id, &desc);
+ if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) {
+ engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
+ } else {
+ FM_DEBUG(" NO MATCH FOUND\n");
+ }
+
+ if (engine) {
+ initFontDef(desc, request, &engine->fontDef);
+
+ if (fp) {
+ QFontDef def = request;
+ if (def.family.isEmpty()) {
+ def.family = fp->request.family;
+ def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
+ }
+ }
+ }
+
+ if (!engine) {
+ if (!request.family.isEmpty()) {
+ QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QUnicodeTables::Script(script));
+ for (int i = 0; i < fallbacks.size(); i++) {
+ QFontDef def = request;
+ def.family = fallbacks.at(i);
+ QFontCache::Key key(def,script);
+ engine = QFontCache::instance()->findEngine(key);
+ if (!engine) {
+ QtFontDesc desc;
+ match(script, def, def.family, QLatin1String(""), 0, &desc);
+ if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) {
+ continue;
+ }
+ engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size);
+ if (engine) {
+ initFontDef(desc, def, &engine->fontDef);
+ break;
+ }
+ }
+ }
+ }
+
+ if (!engine)
+ engine = new QFontEngineBox(request.pixelSize);
+
+ FM_DEBUG("returning box engine");
+ }
+
+ if (fp && fp->dpi > 0) {
+ engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
+ } else {
+ engine->fontDef.pointSize = request.pointSize;
+ }
+
+ return engine;
+}
+
+void QFontDatabase::load(const QFontPrivate *d, int script)
+{
+ QFontDef req = d->request;
+
+ if (req.pixelSize == -1) {
+ req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
+ req.pixelSize = qRound(req.pixelSize);
+ }
+ if (req.pointSize < 0)
+ req.pointSize = req.pixelSize*72.0/d->dpi;
+ if (req.weight == 0)
+ req.weight = QFont::Normal;
+ if (req.stretch == 0)
+ req.stretch = 100;
+
+ QFontCache::Key key(req, script);
+
+ if (!d->engineData)
+ getEngineData(d, key);
+
+ // the cached engineData could have already loaded the engine we want
+ if (d->engineData->engines[script])
+ return;
+
+ QFontEngine *fe = QFontCache::instance()->findEngine(key);
+
+ // list of families to try
+ QStringList family_list;
+
+ if (!req.family.isEmpty()) {
+ family_list = familyList(req);
+
+ // add the default family
+ QString defaultFamily = QApplication::font().family();
+ if (! family_list.contains(defaultFamily))
+ family_list << defaultFamily;
+
+ }
+
+ // null family means find the first font matching the specified script
+ family_list << QString();
+
+ QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
+ for (; !fe && it != end; ++it) {
+ req.family = *it;
+
+ fe = QFontDatabase::findFont(script, d, req);
+ if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty())
+ fe = 0;
+ }
+
+ if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
+ for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
+ if (!d->engineData->engines[i]) {
+ d->engineData->engines[i] = fe;
+ fe->ref.ref();
+ }
+ }
+ } else {
+ d->engineData->engines[script] = fe;
+ fe->ref.ref();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index a0126f12ec..d076de05d3 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -40,8 +40,10 @@
****************************************************************************/
#include "qdir.h"
+#if defined(Q_WS_QWS)
#include "qscreen_qws.h" //so we can check for rotation
#include "qwindowsystem_qws.h"
+#endif
#include "qlibraryinfo.h"
#include "qabstractfileengine.h"
#include <QtCore/qsettings.h>
@@ -153,7 +155,11 @@ extern QString qws_fontCacheDir();
#ifndef QT_FONTS_ARE_RESOURCES
bool QFontDatabasePrivate::loadFromCache(const QString &fontPath)
{
+#ifdef Q_WS_QWS
const bool weAreTheServer = QWSServer::instance();
+#else
+ const bool weAreTheServer = true; // assume single-process
+#endif
QString fontDirFile = fontPath + QLatin1String("/fontdir");
@@ -382,12 +388,14 @@ static void initializeDb()
}
#endif
+#ifndef QT_NO_QWS_QPF2
QDir dir(fontpath, QLatin1String("*.qpf2"));
for (int i = 0; i < int(dir.count()); ++i) {
const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
//qDebug() << "looking at" << file;
db->addQPF2File(file);
}
+#endif
#endif //QT_FONTS_ARE_RESOURCES
@@ -688,6 +696,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp,
{
QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry,
style, size));
+#ifndef QT_NO_QWS_QPF
if (!engine.isNull()
&& script == QUnicodeTables::Common
&& !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
@@ -701,6 +710,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp,
engine.take();
engine.reset(fe);
}
+#endif
return engine.take();
}
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index a4a5665720..2186058e9f 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -1018,6 +1018,13 @@ static void loadFontConfig()
QFontDatabasePrivate *db = privateDb();
FcFontSet *fonts;
+ FcPattern *pattern = FcPatternCreate();
+ FcDefaultSubstitute(pattern);
+ FcChar8 *lang = 0;
+ if (FcPatternGetString(pattern, FC_LANG, 0, &lang) == FcResultMatch)
+ db->systemLang = QString::fromUtf8((const char *) lang);
+ FcPatternDestroy(pattern);
+
QString familyName;
FcChar8 *value = 0;
int weight_value;
@@ -1455,6 +1462,7 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD
weight_value = FC_WEIGHT_DEMIBOLD;
else if (request.weight < (QFont::Bold + QFont::Black) / 2)
weight_value = FC_WEIGHT_BOLD;
+ FcPatternDel(pattern, FC_WEIGHT);
FcPatternAddInteger(pattern, FC_WEIGHT, weight_value);
int slant_value = FC_SLANT_ROMAN;
@@ -1462,20 +1470,25 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD
slant_value = FC_SLANT_ITALIC;
else if (request.style == QFont::StyleOblique)
slant_value = FC_SLANT_OBLIQUE;
+ FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, slant_value);
double size_value = qMax(qreal(1.), request.pixelSize);
+ FcPatternDel(pattern, FC_PIXEL_SIZE);
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value);
int stretch = request.stretch;
if (!stretch)
stretch = 100;
+ FcPatternDel(pattern, FC_WIDTH);
FcPatternAddInteger(pattern, FC_WIDTH, stretch);
if (X11->display && QX11Info::appDepth(screen) <= 8) {
+ FcPatternDel(pattern, FC_ANTIALIAS);
// can't do antialiasing on 8bpp
FcPatternAddBool(pattern, FC_ANTIALIAS, false);
} else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) {
+ FcPatternDel(pattern, FC_ANTIALIAS);
FcPatternAddBool(pattern, FC_ANTIALIAS,
!(request.styleStrategy & QFont::NoAntialias));
}
@@ -1484,6 +1497,7 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD
Q_ASSERT(script < QUnicodeTables::ScriptCount);
FcLangSet *ls = FcLangSetCreate();
FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]);
+ FcPatternDel(pattern, FC_LANG);
FcPatternAddLangSet(pattern, FC_LANG, ls);
FcLangSetDestroy(ls);
}
@@ -2030,6 +2044,7 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
int count = 0;
QStringList families;
+ QFontDatabasePrivate *db = privateDb();
FcPattern *pattern = 0;
do {
@@ -2041,8 +2056,19 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
FcPatternDel(pattern, FC_FILE);
FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData());
- FcChar8 *fam = 0;
- if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) {
+ FcChar8 *fam = 0, *familylang = 0;
+ int i, n = 0;
+ for (i = 0; ; i++) {
+ if (FcPatternGetString(pattern, FC_FAMILYLANG, i, &familylang) != FcResultMatch)
+ break;
+ QString familyLang = QString::fromUtf8((const char *) familylang);
+ if (familyLang.compare(db->systemLang, Qt::CaseInsensitive) == 0) {
+ n = i;
+ break;
+ }
+ }
+
+ if (FcPatternGetString(pattern, FC_FAMILY, n, &fam) == FcResultMatch) {
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
families << family;
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 44346d1e38..3adf4ebc13 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -184,10 +184,6 @@ QFontEngine::QFontEngine()
QFontEngine::~QFontEngine()
{
- for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(),
- end = m_glyphCaches.constEnd(); it != end; ++it) {
- delete it->cache;
- }
m_glyphCaches.clear();
qHBFreeFace(hbFace);
}
@@ -241,6 +237,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
return metrics;
}
+QFont QFontEngine::createExplicitFont() const
+{
+ return createExplicitFontWithName(fontDef.family);
+}
+
+QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const
+{
+ QFont font(familyName);
+ font.setStyleStrategy(QFont::NoFontMerging);
+ font.setWeight(fontDef.weight);
+ font.setItalic(fontDef.style == QFont::StyleItalic);
+ if (fontDef.pointSize < 0)
+ font.setPixelSize(fontDef.pixelSize);
+ else
+ font.setPointSizeF(fontDef.pointSize);
+ return font;
+}
+
QFixed QFontEngine::xHeight() const
{
QGlyphLayoutArray<8> glyphs;
@@ -480,7 +494,7 @@ static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, i
path->closeSubpath();
}
-void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
+Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path)
{
uint *grid = new uint[(w+1)*(h+1)];
// set up edges
@@ -591,6 +605,12 @@ void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int n
addBitmapFontToPath(x, y, g, path, flags);
}
+QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/)
+{
+ // For font engines don't support subpixel positioning
+ return alphaMapForGlyph(glyph);
+}
+
QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
{
QImage i = alphaMapForGlyph(glyph);
@@ -601,7 +621,20 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
return i;
}
-QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int /* margin */, const QTransform &t)
+QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+{
+ if (! supportsSubPixelPositions())
+ return alphaMapForGlyph(glyph, t);
+
+ QImage i = alphaMapForGlyph(glyph, subPixelPosition);
+ if (t.type() > QTransform::TxTranslate)
+ i = i.transformed(t).convertToFormat(QImage::Format_Indexed8);
+ Q_ASSERT(i.depth() <= 8); // To verify that transformed didn't change the format...
+
+ return i;
+}
+
+QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, int /* margin */, const QTransform &t)
{
QImage alphaMask = alphaMapForGlyph(glyph, t);
QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);
@@ -711,14 +744,16 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data)
{
Q_ASSERT(data);
- GlyphCacheEntry entry = { key, data };
+ GlyphCacheEntry entry;
+ entry.context = key;
+ entry.cache = data;
if (m_glyphCaches.contains(entry))
return;
// Limit the glyph caches to 4. This covers all 90 degree rotations and limits
// memory use when there is continuous or random rotation
if (m_glyphCaches.size() == 4)
- delete m_glyphCaches.takeLast().cache;
+ m_glyphCaches.removeLast();
m_glyphCaches.push_front(entry);
@@ -727,7 +762,7 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data)
QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const
{
for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) {
- QFontEngineGlyphCache *c = it->cache;
+ QFontEngineGlyphCache *c = it->cache.data();
if (key == it->context
&& type == c->cacheType()
&& qtransform_equals_no_translate(c->m_transform, transform)) {
@@ -737,7 +772,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache:
return 0;
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
{
uint left_right = (left << 16) + right;
@@ -1181,7 +1216,7 @@ glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti)
{
if (!ti.glyphs.numGlyphs)
diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm
new file mode 100644
index 0000000000..2ae60b15f4
--- /dev/null
+++ b/src/gui/text/qfontengine_coretext.mm
@@ -0,0 +1,733 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfontengine_coretext_p.h"
+
+#include <QtCore/qendian.h>
+#include <QtCore/qsettings.h>
+
+#include <private/qimage_p.h>
+
+#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+
+QT_BEGIN_NAMESPACE
+
+static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
+
+QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning)
+ : QFontEngineMulti(0)
+{
+ this->fontDef = fontDef;
+ CTFontSymbolicTraits symbolicTraits = 0;
+ if (fontDef.weight >= QFont::Bold)
+ symbolicTraits |= kCTFontBoldTrait;
+ switch (fontDef.style) {
+ case QFont::StyleNormal:
+ break;
+ case QFont::StyleItalic:
+ case QFont::StyleOblique:
+ symbolicTraits |= kCTFontItalicTrait;
+ break;
+ }
+
+ transform = CGAffineTransformIdentity;
+ if (fontDef.stretch != 100) {
+ transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
+ }
+
+ QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize);
+ QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform);
+ ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits);
+
+ // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
+ // not exist for the given font. (for example italic)
+ if (ctfont == 0) {
+ ctfont = baseFont;
+ CFRetain(ctfont);
+ }
+
+ attributeDict = CFDictionaryCreateMutable(0, 2,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(attributeDict, NSFontAttributeName, ctfont);
+ if (!kerning) {
+ float zero = 0.0;
+ QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
+ CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern);
+ }
+
+ QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this);
+ fe->ref.ref();
+ engines.append(fe);
+
+}
+
+QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
+{
+ CFRelease(ctfont);
+}
+
+uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef id) const
+{
+ for (int i = 0; i < engines.count(); ++i) {
+ if (CFEqual(engineAt(i)->ctfont, id))
+ return i;
+ }
+
+ QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
+ QCoreTextFontEngine *fe = new QCoreTextFontEngine(id, fontDef, that);
+ fe->ref.ref();
+ that->engines.append(fe);
+ return engines.count() - 1;
+}
+
+bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags,
+ unsigned short *logClusters, const HB_CharAttributes *) const
+{
+ QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0,
+ reinterpret_cast<const UniChar *>(str),
+ len, kCFAllocatorNull);
+ QCFType<CFAttributedStringRef> attributedString = CFAttributedStringCreate(0, cfstring, attributeDict);
+ QCFType<CTTypesetterRef> typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
+ CFRange range = {0, 0};
+ QCFType<CTLineRef> line = CTTypesetterCreateLine(typeSetter, range);
+ CFArrayRef array = CTLineGetGlyphRuns(line);
+ uint arraySize = CFArrayGetCount(array);
+ glyph_t *outGlyphs = glyphs->glyphs;
+ HB_GlyphAttributes *outAttributes = glyphs->attributes;
+ QFixed *outAdvances_x = glyphs->advances_x;
+ QFixed *outAdvances_y = glyphs->advances_y;
+ glyph_t *initialGlyph = outGlyphs;
+
+ if (arraySize == 0) {
+ // CoreText failed to shape the text we gave it, so we assume one glyph
+ // per character and build a list of invalid glyphs with zero advance
+ *nglyphs = len;
+ for (int i = 0; i < len; ++i) {
+ outGlyphs[i] = 0;
+ if (logClusters)
+ logClusters[i] = i;
+ outAdvances_x[i] = QFixed();
+ outAdvances_y[i] = QFixed();
+ outAttributes[i].clusterStart = true;
+ }
+ return true;
+ }
+
+ const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft);
+
+ bool outOBounds = false;
+ for (uint i = 0; i < arraySize; ++i) {
+ CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i));
+ CFIndex glyphCount = CTRunGetGlyphCount(run);
+ if (glyphCount == 0)
+ continue;
+
+ Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
+ CFRange stringRange = CTRunGetStringRange(run);
+ UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1);
+ bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF;
+ if (endWithPDF)
+ glyphCount++;
+
+ if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) {
+ outOBounds = true;
+ }
+ if (!outOBounds) {
+ CFDictionaryRef runAttribs = CTRunGetAttributes(run);
+ //NSLog(@"Dictionary %@", runAttribs);
+ if (!runAttribs)
+ runAttribs = attributeDict;
+ CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName));
+ const uint fontIndex = (fontIndexForFont(runFont) << 24);
+ //NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
+ if (endWithPDF)
+ glyphCount--;
+
+ QVarLengthArray<CGGlyph, 512> cgglyphs(0);
+ const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
+ if (!tmpGlyphs) {
+ cgglyphs.resize(glyphCount);
+ CTRunGetGlyphs(run, range, cgglyphs.data());
+ tmpGlyphs = cgglyphs.constData();
+ }
+ QVarLengthArray<CGPoint, 512> cgpoints(0);
+ const CGPoint *tmpPoints = CTRunGetPositionsPtr(run);
+ if (!tmpPoints) {
+ cgpoints.resize(glyphCount);
+ CTRunGetPositions(run, range, cgpoints.data());
+ tmpPoints = cgpoints.constData();
+ }
+
+ const int rtlOffset = rtl ? (glyphCount - 1) : 0;
+ const int rtlSign = rtl ? -1 : 1;
+
+ if (logClusters) {
+ CFRange stringRange = CTRunGetStringRange(run);
+ QVarLengthArray<CFIndex, 512> stringIndices(0);
+ const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run);
+ if (!tmpIndices) {
+ stringIndices.resize(glyphCount);
+ CTRunGetStringIndices(run, range, stringIndices.data());
+ tmpIndices = stringIndices.constData();
+ }
+
+ const int firstGlyphIndex = outGlyphs - initialGlyph;
+ outAttributes[0].clusterStart = true;
+
+ CFIndex k = 0;
+ CFIndex i = 0;
+ for (i = stringRange.location;
+ (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
+ if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) {
+ logClusters[i] = k + firstGlyphIndex;
+ outAttributes[k].clusterStart = true;
+ ++k;
+ } else {
+ logClusters[i] = k + firstGlyphIndex - 1;
+ }
+ }
+ // in case of a ligature at the end, fill the remaining logcluster entries
+ for (;i < stringRange.location + stringRange.length; i++) {
+ logClusters[i] = k + firstGlyphIndex - 1;
+ }
+ }
+ for (CFIndex i = 0; i < glyphCount - 1; ++i) {
+ int idx = rtlOffset + rtlSign * i;
+ outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
+ outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
+ outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ outAdvances_x[idx] = outAdvances_x[idx].round();
+ outAdvances_y[idx] = outAdvances_y[idx].round();
+ }
+ }
+ CGSize lastGlyphAdvance;
+ CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
+
+ outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
+ outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
+ (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(lastGlyphAdvance.width).round()
+ : QFixed::fromReal(lastGlyphAdvance.width);
+
+ if (endWithPDF) {
+ logClusters[stringRange.location + stringRange.length - 1] = glyphCount;
+ outGlyphs[glyphCount] = 0xFFFF;
+ outAdvances_x[glyphCount] = 0;
+ outAdvances_y[glyphCount] = 0;
+ outAttributes[glyphCount].clusterStart = true;
+ outAttributes[glyphCount].dontPrint = true;
+ glyphCount++;
+ }
+ }
+ outGlyphs += glyphCount;
+ outAttributes += glyphCount;
+ outAdvances_x += glyphCount;
+ outAdvances_y += glyphCount;
+ }
+ *nglyphs = (outGlyphs - initialGlyph);
+ return !outOBounds;
+}
+
+bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QTextEngine::ShaperFlags flags) const
+{
+ *nglyphs = len;
+ QCFType<CFStringRef> cfstring;
+
+ QVarLengthArray<CGGlyph> cgGlyphs(len);
+ CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
+
+ for (int i = 0; i < len; ++i) {
+ if (cgGlyphs[i]) {
+ glyphs->glyphs[i] = cgGlyphs[i];
+ } else {
+ if (!cfstring)
+ cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull);
+ QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1));
+ CGGlyph substituteGlyph = 0;
+ CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1);
+ if (substituteGlyph) {
+ const uint fontIndex = (fontIndexForFont(substituteFont) << 24);
+ glyphs->glyphs[i] = substituteGlyph | fontIndex;
+ if (!(flags & QTextEngine::GlyphIndicesOnly)) {
+ CGSize advance;
+ CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1);
+ glyphs->advances_x[i] = QFixed::fromReal(advance.width);
+ glyphs->advances_y[i] = QFixed::fromReal(advance.height);
+ }
+ }
+ }
+ }
+
+ if (flags & QTextEngine::GlyphIndicesOnly)
+ return true;
+
+ QVarLengthArray<CGSize> advances(len);
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
+
+ for (int i = 0; i < len; ++i) {
+ if (glyphs->glyphs[i] & 0xff000000)
+ continue;
+ glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
+ glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
+ }
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ for (int i = 0; i < len; ++i) {
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = glyphs->advances_y[i].round();
+ }
+ }
+
+ return true;
+}
+
+void QCoreTextFontEngineMulti::recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
+{
+}
+void QCoreTextFontEngineMulti::doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
+{
+}
+
+void QCoreTextFontEngineMulti::loadEngine(int)
+{
+ // Do nothing
+ Q_ASSERT(false);
+}
+
+
+
+QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
+ QCoreTextFontEngineMulti *multiEngine)
+{
+ fontDef = def;
+ parentEngine = multiEngine;
+ synthesisFlags = 0;
+ ctfont = font;
+ CFRetain(ctfont);
+ cgFont = CTFontCopyGraphicsFont(ctfont, NULL);
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
+ if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) {
+ synthesisFlags |= SynthesizedBold;
+ }
+
+ if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait)) {
+ synthesisFlags |= SynthesizedItalic;
+ }
+ transform = CGAffineTransformIdentity;
+ if (fontDef.stretch != 100) {
+ transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
+ }
+ QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ if (os2Table.size() >= 10)
+ fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8));
+
+ QSettings appleSettings(QLatin1String("apple.com"));
+ QVariant appleValue = appleSettings.value(QLatin1String("AppleAntiAliasingThreshold"));
+ if (appleValue.isValid())
+ antialiasing_threshold = appleValue.toInt();
+ else
+ antialiasing_threshold = -1;
+}
+
+QCoreTextFontEngine::~QCoreTextFontEngine()
+{
+ CFRelease(cgFont);
+ CFRelease(ctfont);
+}
+
+bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *, QTextEngine::ShaperFlags) const
+{
+ return false;
+}
+
+glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
+{
+ QFixed w;
+ bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics;
+
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ w += round ? glyphs.effectiveAdvance(i).round()
+ : glyphs.effectiveAdvance(i);
+ }
+ return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0);
+}
+glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
+{
+ glyph_metrics_t ret;
+ CGGlyph g = glyph;
+ CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
+ if (synthesisFlags & QFontEngine::SynthesizedItalic) {
+ rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW;
+ }
+ ret.width = QFixed::fromReal(rect.size.width);
+ ret.height = QFixed::fromReal(rect.size.height);
+ ret.x = QFixed::fromReal(rect.origin.x);
+ ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
+ CGSize advances[1];
+ CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
+ ret.xoff = QFixed::fromReal(advances[0].width);
+ ret.yoff = QFixed::fromReal(advances[0].height);
+
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+ ret.xoff = ret.xoff.round();
+ ret.yoff = ret.yoff.round();
+ }
+
+ return ret;
+}
+
+QFixed QCoreTextFontEngine::ascent() const
+{
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
+ : QFixed::fromReal(CTFontGetAscent(ctfont));
+}
+QFixed QCoreTextFontEngine::descent() const
+{
+ QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ d = d.round();
+
+ // subtract a pixel to even out the historical +1 in QFontMetrics::height().
+ // Fix in Qt 5.
+ return d - 1;
+}
+QFixed QCoreTextFontEngine::leading() const
+{
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
+ : QFixed::fromReal(CTFontGetLeading(ctfont));
+}
+QFixed QCoreTextFontEngine::xHeight() const
+{
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
+ : QFixed::fromReal(CTFontGetXHeight(ctfont));
+}
+QFixed QCoreTextFontEngine::averageCharWidth() const
+{
+ // ### Need to implement properly and get the information from the OS/2 Table.
+ return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ ? QFontEngine::averageCharWidth().round()
+ : QFontEngine::averageCharWidth();
+}
+
+qreal QCoreTextFontEngine::maxCharWidth() const
+{
+ // ### Max Help!
+ return 0;
+
+}
+qreal QCoreTextFontEngine::minLeftBearing() const
+{
+ // ### Min Help!
+ return 0;
+
+}
+qreal QCoreTextFontEngine::minRightBearing() const
+{
+ // ### Max Help! (even thought it's right)
+ return 0;
+
+}
+
+void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
+{
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> glyphs;
+ QTransform matrix;
+ matrix.translate(x, y);
+ getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+ if (glyphs.size() == 0)
+ return;
+
+ CGContextSetFontSize(ctx, fontDef.pixelSize);
+
+ CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
+
+ CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
+
+ CGAffineTransformConcat(cgMatrix, oldTextMatrix);
+
+ if (synthesisFlags & QFontEngine::SynthesizedItalic)
+ cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
+
+ cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
+
+ CGContextSetTextMatrix(ctx, cgMatrix);
+
+ CGContextSetTextDrawingMode(ctx, kCGTextFill);
+
+
+ QVarLengthArray<CGSize> advances(glyphs.size());
+ QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
+
+ for (int i = 0; i < glyphs.size() - 1; ++i) {
+ advances[i].width = (positions[i + 1].x - positions[i].x).toReal();
+ advances[i].height = (positions[i + 1].y - positions[i].y).toReal();
+ cgGlyphs[i] = glyphs[i];
+ }
+ advances[glyphs.size() - 1].width = 0;
+ advances[glyphs.size() - 1].height = 0;
+ cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1];
+
+ CGContextSetFont(ctx, cgFont);
+ //NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont));
+
+ CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
+
+ CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
+
+ if (synthesisFlags & QFontEngine::SynthesizedBold) {
+ CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
+ positions[0].y.toReal());
+
+ CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
+ }
+
+ CGContextSetTextMatrix(ctx, oldTextMatrix);
+}
+
+struct ConvertPathInfo
+{
+ ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {}
+ QPainterPath *path;
+ QPointF pos;
+};
+
+static void convertCGPathToQPainterPath(void *info, const CGPathElement *element)
+{
+ ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info);
+ switch(element->type) {
+ case kCGPathElementMoveToPoint:
+ myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(),
+ element->points[0].y + myInfo->pos.y());
+ break;
+ case kCGPathElementAddLineToPoint:
+ myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(),
+ element->points[0].y + myInfo->pos.y());
+ break;
+ case kCGPathElementAddQuadCurveToPoint:
+ myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(),
+ element->points[0].y + myInfo->pos.y(),
+ element->points[1].x + myInfo->pos.x(),
+ element->points[1].y + myInfo->pos.y());
+ break;
+ case kCGPathElementAddCurveToPoint:
+ myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(),
+ element->points[0].y + myInfo->pos.y(),
+ element->points[1].x + myInfo->pos.x(),
+ element->points[1].y + myInfo->pos.y(),
+ element->points[2].x + myInfo->pos.x(),
+ element->points[2].y + myInfo->pos.y());
+ break;
+ case kCGPathElementCloseSubpath:
+ myInfo->path->closeSubpath();
+ break;
+ default:
+ qDebug() << "Unhandled path transform type: " << element->type;
+ }
+
+}
+
+void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,
+ QPainterPath *path, QTextItem::RenderFlags)
+{
+ CGAffineTransform cgMatrix = CGAffineTransformIdentity;
+ cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
+
+ if (synthesisFlags & QFontEngine::SynthesizedItalic)
+ cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
+
+ for (int i = 0; i < nGlyphs; ++i) {
+ QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix);
+ ConvertPathInfo info(path, positions[i].toPointF());
+ CGPathApply(cgpath, &info, convertCGPathToQPainterPath);
+ }
+}
+
+QFont QCoreTextFontEngine::createExplicitFont() const
+{
+ QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont));
+ return createExplicitFontWithName(familyName);
+}
+
+QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa)
+{
+ const glyph_metrics_t br = boundingBox(glyph);
+ QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32);
+ im.fill(0);
+
+ CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ uint cgflags = kCGImageAlphaNoneSkipFirst;
+#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
+ cgflags |= kCGBitmapByteOrder32Host;
+#endif
+ CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
+ 8, im.bytesPerLine(), colorspace,
+ cgflags);
+ CGContextSetFontSize(ctx, fontDef.pixelSize);
+ CGContextSetShouldAntialias(ctx, aa ||
+ (fontDef.pointSize > antialiasing_threshold
+ && !(fontDef.styleStrategy & QFont::NoAntialias)));
+ CGContextSetShouldSmoothFonts(ctx, aa);
+ CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
+ CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
+
+ CGAffineTransformConcat(cgMatrix, oldTextMatrix);
+
+ if (synthesisFlags & QFontEngine::SynthesizedItalic)
+ cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
+
+ cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
+
+ CGContextSetTextMatrix(ctx, cgMatrix);
+ CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
+ CGContextSetTextDrawingMode(ctx, kCGTextFill);
+
+ CGContextSetFont(ctx, cgFont);
+
+ qreal pos_x = -br.x.toReal() + subPixelPosition.toReal();
+ qreal pos_y = im.height() + br.y.toReal() - 1;
+ CGContextSetTextPosition(ctx, pos_x, pos_y);
+
+ CGSize advance;
+ advance.width = 0;
+ advance.height = 0;
+ CGGlyph cgGlyph = glyph;
+ CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
+
+ if (synthesisFlags & QFontEngine::SynthesizedBold) {
+ CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
+ CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
+ }
+
+ CGContextRelease(ctx);
+
+ return im;
+}
+
+QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+{
+ QImage im = imageForGlyph(glyph, subPixelPosition, 0, false);
+
+ QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
+ QVector<QRgb> colors(256);
+ for (int i=0; i<256; ++i)
+ colors[i] = qRgba(0, 0, 0, i);
+ indexed.setColorTable(colors);
+
+ for (int y=0; y<im.height(); ++y) {
+ uint *src = (uint*) im.scanLine(y);
+ uchar *dst = indexed.scanLine(y);
+ for (int x=0; x<im.width(); ++x) {
+ *dst = qGray(*src);
+ ++dst;
+ ++src;
+ }
+ }
+
+ return indexed;
+}
+
+QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &x)
+{
+ if (x.type() >= QTransform::TxScale)
+ return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, margin, x);
+
+ QImage im = imageForGlyph(glyph, subPixelPosition, margin, true);
+ qGamma_correct_back_to_linear_cs(&im);
+ return im;
+}
+
+void QCoreTextFontEngine::recalcAdvances(int numGlyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
+{
+ Q_ASSERT(false);
+ Q_UNUSED(numGlyphs);
+ Q_UNUSED(glyphs);
+ Q_UNUSED(flags);
+}
+
+QFontEngine::FaceId QCoreTextFontEngine::faceId() const
+{
+ return QFontEngine::FaceId();
+}
+
+bool QCoreTextFontEngine::canRender(const QChar *string, int len)
+{
+ QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
+ QCFType<CFStringRef>(CFStringCreateWithCharactersNoCopy(0,
+ reinterpret_cast<const UniChar *>(string),
+ len, kCFAllocatorNull)),
+ CFRangeMake(0, len));
+ return retFont != 0;
+ return false;
+}
+
+ bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+ {
+ QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
+ if (!table || !length)
+ return false;
+ CFIndex tableLength = CFDataGetLength(table);
+ int availableLength = *length;
+ *length = tableLength;
+ if (buffer) {
+ if (tableLength > availableLength)
+ return false;
+ CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
+ }
+ return true;
+ }
+
+void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *)
+{
+ // ###
+}
+
+QT_END_NAMESPACE
+
+#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+
diff --git a/src/gui/text/qfontengine_coretext_p.h b/src/gui/text/qfontengine_coretext_p.h
new file mode 100644
index 0000000000..b4450fa304
--- /dev/null
+++ b/src/gui/text/qfontengine_coretext_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTENGINE_CORETEXT_P_H
+#define QFONTENGINE_CORETEXT_P_H
+
+#include <private/qfontengine_p.h>
+
+#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+
+class QCoreTextFontEngineMulti;
+class QCoreTextFontEngine : public QFontEngine
+{
+public:
+ QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
+ QCoreTextFontEngineMulti *multiEngine = 0);
+ ~QCoreTextFontEngine();
+ virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
+ virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
+
+ virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
+ virtual glyph_metrics_t boundingBox(glyph_t glyph);
+
+ virtual QFixed ascent() const;
+ virtual QFixed descent() const;
+ virtual QFixed leading() const;
+ virtual QFixed xHeight() const;
+ virtual qreal maxCharWidth() const;
+ virtual QFixed averageCharWidth() const;
+
+ virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
+ QPainterPath *path, QTextItem::RenderFlags);
+
+ virtual const char *name() const { return "QCoreTextFontEngine"; }
+
+ virtual bool canRender(const QChar *string, int len);
+
+ virtual int synthesized() const { return synthesisFlags; }
+ virtual bool supportsSubPixelPositions() const { return true; }
+
+ virtual Type type() const { return QFontEngine::Mac; }
+
+ void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight);
+
+ virtual FaceId faceId() const;
+ virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const;
+ virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
+ virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
+ virtual qreal minRightBearing() const;
+ virtual qreal minLeftBearing() const;
+ virtual QFont createExplicitFont() const;
+
+private:
+ QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful);
+ CTFontRef ctfont;
+ CGFontRef cgFont;
+ QCoreTextFontEngineMulti *parentEngine;
+ int synthesisFlags;
+ CGAffineTransform transform;
+ friend class QCoreTextFontEngineMulti;
+ int antialiasing_threshold;
+};
+
+class QCoreTextFontEngineMulti : public QFontEngineMulti
+{
+public:
+ QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning);
+ ~QCoreTextFontEngineMulti();
+
+ virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
+ QTextEngine::ShaperFlags flags) const;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
+ QTextEngine::ShaperFlags flags,
+ unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
+
+
+ virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
+ virtual void doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
+
+ virtual const char *name() const { return "CoreText"; }
+protected:
+ virtual void loadEngine(int at);
+
+private:
+ inline const QCoreTextFontEngine *engineAt(int i) const
+ { return static_cast<const QCoreTextFontEngine *>(engines.at(i)); }
+
+ uint fontIndexForFont(CTFontRef id) const;
+ CTFontRef ctfont;
+ mutable QCFType<CFMutableDictionaryRef> attributeDict;
+ CGAffineTransform transform;
+ friend class QFontDialogPrivate;
+};
+
+#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+
+#endif // QFONTENGINE_CORETEXT_P_H
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index e89b508601..f5e9e1ca9a 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -723,7 +723,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
metrics = face->size->metrics;
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
/*
TrueType fonts with embedded bitmaps may have a bitmap font specific
ascent/descent in the EBLC table. There is no direct public API
@@ -755,16 +755,42 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
return true;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const
+void QFontEngineFT::setDefaultHintStyle(HintStyle style)
+{
+ default_hint_style = style;
+}
+
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
{
Glyph *g = set->getGlyph(glyph);
- if (g)
+ if (g && g->format == format)
return g;
int load_flags = FT_LOAD_DEFAULT | default_load_flags;
+ int load_target = default_hint_style == HintLight
+ ? FT_LOAD_TARGET_LIGHT
+ : FT_LOAD_TARGET_NORMAL;
+
+ if (format == Format_Mono) {
+ load_target = FT_LOAD_TARGET_MONO;
+ } else if (format == Format_A32) {
+ if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
+ if (default_hint_style == HintFull)
+ load_target = FT_LOAD_TARGET_LCD;
+ } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
+ if (default_hint_style == HintFull)
+ load_target = FT_LOAD_TARGET_LCD_V;
+ }
+ }
+
if (set->outline_drawing)
load_flags = FT_LOAD_NO_BITMAP;
+ if (default_hint_style == HintNone)
+ load_flags |= FT_LOAD_NO_HINTING;
+ else
+ load_flags |= load_target;
+
// apply our matrix to this, but note that the metrics will not be affected by this.
FT_Face face = lockFace();
FT_Matrix matrix = this->matrix;
@@ -1758,6 +1784,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix)
{
+ return alphaMapBoundingBox(glyph, matrix, QFontEngine::Format_None);
+}
+
+glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, QFontEngine::GlyphFormat format)
+{
FT_Face face = 0;
glyph_metrics_t overall;
QGlyphSet *glyphSet = 0;
@@ -1801,9 +1832,9 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
glyphSet = &defaultGlyphSet;
}
Glyph * g = glyphSet->getGlyph(glyph);
- if (!g) {
+ if (!g || g->format != format) {
face = lockFace();
- g = loadGlyphMetrics(glyphSet, glyph);
+ g = loadGlyphMetrics(glyphSet, glyph, format);
}
if (g) {
@@ -1865,10 +1896,10 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
return img;
}
-QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransform &t)
+QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t)
{
if (t.type() > QTransform::TxTranslate)
- return QFontEngine::alphaRGBMapForGlyph(g, margin, t);
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
lockFace();
@@ -1877,7 +1908,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor
Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
if (!glyph) {
unlockFace();
- return QFontEngine::alphaRGBMapForGlyph(g, margin, t);
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
}
QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 93a6d16aaf..abdbd2099b 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -130,13 +130,6 @@ private:
class Q_GUI_EXPORT QFontEngineFT : public QFontEngine
{
public:
- enum GlyphFormat {
- Format_None,
- Format_Render = Format_None,
- Format_Mono,
- Format_A8,
- Format_A32
- };
/* we don't cache glyphs that are too large anyway, so we can make this struct rather small */
struct Glyph {
@@ -241,7 +234,9 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t);
- virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
+ virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix,
+ QFontEngine::GlyphFormat format);
virtual void removeGlyphFromCache(glyph_t glyph);
virtual int glyphCount() const;
@@ -282,6 +277,14 @@ private:
virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
+ enum HintStyle {
+ HintNone,
+ HintLight,
+ HintMedium,
+ HintFull
+ };
+
+ void setDefaultHintStyle(HintStyle style);
protected:
void freeGlyphSets();
@@ -293,12 +296,6 @@ protected:
QFreetypeFace *freetype;
int default_load_flags;
- enum HintStyle {
- HintNone,
- HintLight,
- HintMedium,
- HintFull
- };
HintStyle default_hint_style;
@@ -311,7 +308,7 @@ protected:
bool embeddedbitmap;
private:
- QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph) const;
+ QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const;
GlyphFormat defaultFormat;
FT_Matrix matrix;
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index 1c21f91bce..7751bbe62f 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qfontengine_mac_p.h"
+
#include <private/qapplication_p.h>
#include <private/qfontengine_p.h>
#include <private/qpainter_p.h>
@@ -53,6 +55,7 @@
#include <qdebug.h>
#include <qendian.h>
#include <qmath.h>
+#include <private/qimage_p.h>
#include <ApplicationServices/ApplicationServices.h>
#include <AppKit/AppKit.h>
@@ -119,679 +122,6 @@ OSStatus QMacFontPath::closePath(void *data)
}
-
-void qmacfontengine_gamma_correct(QImage *image)
-{
- extern uchar qt_pow_rgb_gamma[256];
-
- // gamma correct the pixels back to linear color space...
- int h = image->height();
- int w = image->width();
-
- for (int y=0; y<h; ++y) {
- uint *pixels = (uint *) image->scanLine(y);
- for (int x=0; x<w; ++x) {
- uint p = pixels[x];
- uint r = qt_pow_rgb_gamma[qRed(p)];
- uint g = qt_pow_rgb_gamma[qGreen(p)];
- uint b = qt_pow_rgb_gamma[qBlue(p)];
- pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
- }
- }
-}
-
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning)
- : QFontEngineMulti(0)
-{
- this->fontDef = fontDef;
- CTFontSymbolicTraits symbolicTraits = 0;
- if (fontDef.weight >= QFont::Bold)
- symbolicTraits |= kCTFontBoldTrait;
- switch (fontDef.style) {
- case QFont::StyleNormal:
- break;
- case QFont::StyleItalic:
- case QFont::StyleOblique:
- symbolicTraits |= kCTFontItalicTrait;
- break;
- }
-
- QCFString name;
- ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name);
-
- transform = CGAffineTransformIdentity;
- if (fontDef.stretch != 100) {
- transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
- }
-
- QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize);
- QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform);
- ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits);
-
- // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
- // not exist for the given font. (for example italic)
- if (ctfont == 0) {
- ctfont = baseFont;
- CFRetain(ctfont);
- }
-
- attributeDict = CFDictionaryCreateMutable(0, 2,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CFDictionaryAddValue(attributeDict, NSFontAttributeName, ctfont);
- if (!kerning) {
- float zero = 0.0;
- QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero);
- CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern);
- }
-
- QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this);
- fe->ref.ref();
- engines.append(fe);
-
-}
-
-QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
-{
- CFRelease(ctfont);
-}
-
-uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef id) const
-{
- for (int i = 0; i < engines.count(); ++i) {
- if (CFEqual(engineAt(i)->ctfont, id))
- return i;
- }
-
- QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
- QCoreTextFontEngine *fe = new QCoreTextFontEngine(id, fontDef, that);
- fe->ref.ref();
- that->engines.append(fe);
- return engines.count() - 1;
-}
-
-bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags,
- unsigned short *logClusters, const HB_CharAttributes *) const
-{
- QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0,
- reinterpret_cast<const UniChar *>(str),
- len, kCFAllocatorNull);
- QCFType<CFAttributedStringRef> attributedString = CFAttributedStringCreate(0, cfstring, attributeDict);
- QCFType<CTTypesetterRef> typeSetter = CTTypesetterCreateWithAttributedString(attributedString);
- CFRange range = {0, 0};
- QCFType<CTLineRef> line = CTTypesetterCreateLine(typeSetter, range);
- CFArrayRef array = CTLineGetGlyphRuns(line);
- uint arraySize = CFArrayGetCount(array);
- glyph_t *outGlyphs = glyphs->glyphs;
- HB_GlyphAttributes *outAttributes = glyphs->attributes;
- QFixed *outAdvances_x = glyphs->advances_x;
- QFixed *outAdvances_y = glyphs->advances_y;
- glyph_t *initialGlyph = outGlyphs;
-
- if (arraySize == 0) {
- // CoreText failed to shape the text we gave it, so we assume one glyph
- // per character and build a list of invalid glyphs with zero advance
- *nglyphs = len;
- for (int i = 0; i < len; ++i) {
- outGlyphs[i] = 0;
- if (logClusters)
- logClusters[i] = i;
- outAdvances_x[i] = QFixed();
- outAdvances_y[i] = QFixed();
- outAttributes[i].clusterStart = true;
- }
- return true;
- }
-
- const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft);
-
- bool outOBounds = false;
- for (uint i = 0; i < arraySize; ++i) {
- CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i));
- CFIndex glyphCount = CTRunGetGlyphCount(run);
- if (glyphCount == 0)
- continue;
-
- Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl);
-
- if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) {
- outOBounds = true;
- }
- if (!outOBounds) {
- CFDictionaryRef runAttribs = CTRunGetAttributes(run);
- //NSLog(@"Dictionary %@", runAttribs);
- if (!runAttribs)
- runAttribs = attributeDict;
- CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName));
- const uint fontIndex = (fontIndexForFont(runFont) << 24);
- //NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
- QVarLengthArray<CGGlyph, 512> cgglyphs(0);
- const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
- if (!tmpGlyphs) {
- cgglyphs.resize(glyphCount);
- CTRunGetGlyphs(run, range, cgglyphs.data());
- tmpGlyphs = cgglyphs.constData();
- }
- QVarLengthArray<CGPoint, 512> cgpoints(0);
- const CGPoint *tmpPoints = CTRunGetPositionsPtr(run);
- if (!tmpPoints) {
- cgpoints.resize(glyphCount);
- CTRunGetPositions(run, range, cgpoints.data());
- tmpPoints = cgpoints.constData();
- }
-
- const int rtlOffset = rtl ? (glyphCount - 1) : 0;
- const int rtlSign = rtl ? -1 : 1;
-
- if (logClusters) {
- CFRange stringRange = CTRunGetStringRange(run);
- QVarLengthArray<CFIndex, 512> stringIndices(0);
- const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run);
- if (!tmpIndices) {
- stringIndices.resize(glyphCount);
- CTRunGetStringIndices(run, range, stringIndices.data());
- tmpIndices = stringIndices.constData();
- }
-
- const int firstGlyphIndex = outGlyphs - initialGlyph;
- outAttributes[0].clusterStart = true;
-
- CFIndex k = 0;
- CFIndex i = 0;
- for (i = stringRange.location;
- (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
- if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) {
- logClusters[i] = k + firstGlyphIndex;
- outAttributes[k].clusterStart = true;
- ++k;
- } else {
- logClusters[i] = k + firstGlyphIndex - 1;
- }
- }
- // in case of a ligature at the end, fill the remaining logcluster entries
- for (;i < stringRange.location + stringRange.length; i++) {
- logClusters[i] = k + firstGlyphIndex - 1;
- }
- }
- for (CFIndex i = 0; i < glyphCount - 1; ++i) {
- int idx = rtlOffset + rtlSign * i;
- outGlyphs[idx] = tmpGlyphs[i] | fontIndex;
- outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x);
- outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y);
-
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- outAdvances_x[idx] = outAdvances_x[idx].round();
- outAdvances_y[idx] = outAdvances_y[idx].round();
- }
- }
- CGSize lastGlyphAdvance;
- CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1);
-
- outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex;
- outAdvances_x[rtl ? 0 : (glyphCount - 1)] =
- (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFixed::fromReal(lastGlyphAdvance.width).round()
- : QFixed::fromReal(lastGlyphAdvance.width);
- }
- outGlyphs += glyphCount;
- outAttributes += glyphCount;
- outAdvances_x += glyphCount;
- outAdvances_y += glyphCount;
- }
- *nglyphs = (outGlyphs - initialGlyph);
- return !outOBounds;
-}
-
-bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
- int *nglyphs, QTextEngine::ShaperFlags flags) const
-{
- *nglyphs = len;
- QCFType<CFStringRef> cfstring;
-
- QVarLengthArray<CGGlyph> cgGlyphs(len);
- CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
-
- for (int i = 0; i < len; ++i) {
- if (cgGlyphs[i]) {
- glyphs->glyphs[i] = cgGlyphs[i];
- } else {
- if (!cfstring)
- cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull);
- QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1));
- CGGlyph substituteGlyph = 0;
- CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1);
- if (substituteGlyph) {
- const uint fontIndex = (fontIndexForFont(substituteFont) << 24);
- glyphs->glyphs[i] = substituteGlyph | fontIndex;
- if (!(flags & QTextEngine::GlyphIndicesOnly)) {
- CGSize advance;
- CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1);
- glyphs->advances_x[i] = QFixed::fromReal(advance.width);
- glyphs->advances_y[i] = QFixed::fromReal(advance.height);
- }
- }
- }
- }
-
- if (flags & QTextEngine::GlyphIndicesOnly)
- return true;
-
- QVarLengthArray<CGSize> advances(len);
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len);
-
- for (int i = 0; i < len; ++i) {
- if (glyphs->glyphs[i] & 0xff000000)
- continue;
- glyphs->advances_x[i] = QFixed::fromReal(advances[i].width);
- glyphs->advances_y[i] = QFixed::fromReal(advances[i].height);
- }
-
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- for (int i = 0; i < len; ++i) {
- glyphs->advances_x[i] = glyphs->advances_x[i].round();
- glyphs->advances_y[i] = glyphs->advances_y[i].round();
- }
- }
-
- return true;
-}
-
-void QCoreTextFontEngineMulti::recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
-{
-}
-void QCoreTextFontEngineMulti::doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const
-{
-}
-
-void QCoreTextFontEngineMulti::loadEngine(int)
-{
- // Do nothing
- Q_ASSERT(false);
-}
-
-
-
-QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
- QCoreTextFontEngineMulti *multiEngine)
-{
- fontDef = def;
- parentEngine = multiEngine;
- synthesisFlags = 0;
- ctfont = font;
- CFRetain(ctfont);
- ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0);
- cgFont = CGFontCreateWithPlatformFont(&atsfont);
- CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont);
- if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) {
- synthesisFlags |= SynthesizedBold;
- }
-
- if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait)) {
- synthesisFlags |= SynthesizedItalic;
- }
- transform = CGAffineTransformIdentity;
- if (fontDef.stretch != 100) {
- transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1);
- }
- QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
- if (os2Table.size() >= 10)
- fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8));
-}
-
-QCoreTextFontEngine::~QCoreTextFontEngine()
-{
- CFRelease(ctfont);
- CFRelease(cgFont);
-}
-
-bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *, QTextEngine::ShaperFlags) const
-{
- return false;
-}
-
-glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
-{
- QFixed w;
- bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics;
-
- for (int i = 0; i < glyphs.numGlyphs; ++i) {
- w += round ? glyphs.effectiveAdvance(i).round()
- : glyphs.effectiveAdvance(i);
- }
- return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0);
-}
-glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
-{
- glyph_metrics_t ret;
- CGGlyph g = glyph;
- CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1);
- ret.width = QFixed::fromReal(rect.size.width);
- ret.height = QFixed::fromReal(rect.size.height);
- ret.x = QFixed::fromReal(rect.origin.x);
- ret.y = -QFixed::fromReal(rect.origin.y) - ret.height;
- CGSize advances[1];
- CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1);
- ret.xoff = QFixed::fromReal(advances[0].width);
- ret.yoff = QFixed::fromReal(advances[0].height);
-
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
- ret.xoff = ret.xoff.round();
- ret.yoff = ret.yoff.round();
- }
-
- return ret;
-}
-
-QFixed QCoreTextFontEngine::ascent() const
-{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
- : QFixed::fromReal(CTFontGetAscent(ctfont));
-}
-QFixed QCoreTextFontEngine::descent() const
-{
- QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
- if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- d = d.round();
-
- // subtract a pixel to even out the historical +1 in QFontMetrics::height().
- // Fix in Qt 5.
- return d - 1;
-}
-QFixed QCoreTextFontEngine::leading() const
-{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
- : QFixed::fromReal(CTFontGetLeading(ctfont));
-}
-QFixed QCoreTextFontEngine::xHeight() const
-{
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
- : QFixed::fromReal(CTFontGetXHeight(ctfont));
-}
-QFixed QCoreTextFontEngine::averageCharWidth() const
-{
- // ### Need to implement properly and get the information from the OS/2 Table.
- return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
- ? QFontEngine::averageCharWidth().round()
- : QFontEngine::averageCharWidth();
-}
-
-qreal QCoreTextFontEngine::maxCharWidth() const
-{
- // ### Max Help!
- return 0;
-
-}
-qreal QCoreTextFontEngine::minLeftBearing() const
-{
- // ### Min Help!
- return 0;
-
-}
-qreal QCoreTextFontEngine::minRightBearing() const
-{
- // ### Max Help! (even thought it's right)
- return 0;
-
-}
-
-void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
-{
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> glyphs;
- QTransform matrix;
- matrix.translate(x, y);
- getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
- if (glyphs.size() == 0)
- return;
-
- CGContextSetFontSize(ctx, fontDef.pixelSize);
-
- CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
-
- CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
-
- CGAffineTransformConcat(cgMatrix, oldTextMatrix);
-
- if (synthesisFlags & QFontEngine::SynthesizedItalic)
- cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0));
-
- cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
-
- CGContextSetTextMatrix(ctx, cgMatrix);
-
- CGContextSetTextDrawingMode(ctx, kCGTextFill);
-
-
- QVarLengthArray<CGSize> advances(glyphs.size());
- QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
-
- for (int i = 0; i < glyphs.size() - 1; ++i) {
- advances[i].width = (positions[i + 1].x - positions[i].x).toReal();
- advances[i].height = (positions[i + 1].y - positions[i].y).toReal();
- cgGlyphs[i] = glyphs[i];
- }
- advances[glyphs.size() - 1].width = 0;
- advances[glyphs.size() - 1].height = 0;
- cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1];
-
- CGContextSetFont(ctx, cgFont);
- //NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont));
-
- CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
-
- CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
-
- if (synthesisFlags & QFontEngine::SynthesizedBold) {
- CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
- positions[0].y.toReal());
-
- CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
- }
-
- CGContextSetTextMatrix(ctx, oldTextMatrix);
-}
-
-struct ConvertPathInfo
-{
- ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {}
- QPainterPath *path;
- QPointF pos;
-};
-
-static void convertCGPathToQPainterPath(void *info, const CGPathElement *element)
-{
- ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info);
- switch(element->type) {
- case kCGPathElementMoveToPoint:
- myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(),
- element->points[0].y + myInfo->pos.y());
- break;
- case kCGPathElementAddLineToPoint:
- myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(),
- element->points[0].y + myInfo->pos.y());
- break;
- case kCGPathElementAddQuadCurveToPoint:
- myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(),
- element->points[0].y + myInfo->pos.y(),
- element->points[1].x + myInfo->pos.x(),
- element->points[1].y + myInfo->pos.y());
- break;
- case kCGPathElementAddCurveToPoint:
- myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(),
- element->points[0].y + myInfo->pos.y(),
- element->points[1].x + myInfo->pos.x(),
- element->points[1].y + myInfo->pos.y(),
- element->points[2].x + myInfo->pos.x(),
- element->points[2].y + myInfo->pos.y());
- break;
- case kCGPathElementCloseSubpath:
- myInfo->path->closeSubpath();
- break;
- default:
- qDebug() << "Unhandled path transform type: " << element->type;
- }
-
-}
-
-void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs,
- QPainterPath *path, QTextItem::RenderFlags)
-{
-
- CGAffineTransform cgMatrix = CGAffineTransformIdentity;
- cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1);
-
- if (synthesisFlags & QFontEngine::SynthesizedItalic)
- cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0));
-
-
- for (int i = 0; i < nGlyphs; ++i) {
- QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix);
- ConvertPathInfo info(path, positions[i].toPointF());
- CGPathApply(cgpath, &info, convertCGPathToQPainterPath);
- }
-}
-
-QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa)
-{
- const glyph_metrics_t br = boundingBox(glyph);
- QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32);
- im.fill(0);
-
- CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
- uint cgflags = kCGImageAlphaNoneSkipFirst;
-#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
- cgflags |= kCGBitmapByteOrder32Host;
-#endif
- CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(),
- 8, im.bytesPerLine(), colorspace,
- cgflags);
- CGContextSetFontSize(ctx, fontDef.pixelSize);
- CGContextSetShouldAntialias(ctx, aa ||
- (fontDef.pointSize > qt_antialiasing_threshold
- && !(fontDef.styleStrategy & QFont::NoAntialias)));
- CGContextSetShouldSmoothFonts(ctx, aa);
- CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
- CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
-
- CGAffineTransformConcat(cgMatrix, oldTextMatrix);
-
- if (synthesisFlags & QFontEngine::SynthesizedItalic)
- cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0));
-
- cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
-
- CGContextSetTextMatrix(ctx, cgMatrix);
- CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
- CGContextSetTextDrawingMode(ctx, kCGTextFill);
-
- ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0);
- QCFType<CGFontRef> cgFont = CGFontCreateWithPlatformFont(&atsfont);
- CGContextSetFont(ctx, cgFont);
-
- qreal pos_x = -br.x.toReal()+1, pos_y = im.height()+br.y.toReal();
- CGContextSetTextPosition(ctx, pos_x, pos_y);
-
- CGSize advance;
- advance.width = 0;
- advance.height = 0;
- CGGlyph cgGlyph = glyph;
- CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
-
- if (synthesisFlags & QFontEngine::SynthesizedBold) {
- CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
- CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1);
- }
-
- CGContextRelease(ctx);
-
- return im;
-}
-
-QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph)
-{
- QImage im = imageForGlyph(glyph, 0, false);
-
- QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
- QVector<QRgb> colors(256);
- for (int i=0; i<256; ++i)
- colors[i] = qRgba(0, 0, 0, i);
- indexed.setColorTable(colors);
-
- for (int y=0; y<im.height(); ++y) {
- uint *src = (uint*) im.scanLine(y);
- uchar *dst = indexed.scanLine(y);
- for (int x=0; x<im.width(); ++x) {
- *dst = qGray(*src);
- ++dst;
- ++src;
- }
- }
-
- return indexed;
-}
-
-QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &x)
-{
- if (x.type() >= QTransform::TxScale)
- return QFontEngine::alphaRGBMapForGlyph(glyph, margin, x);
-
- QImage im = imageForGlyph(glyph, margin, true);
- qmacfontengine_gamma_correct(&im);
- return im;
-}
-
-void QCoreTextFontEngine::recalcAdvances(int numGlyphs, QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
-{
- Q_ASSERT(false);
- Q_UNUSED(numGlyphs);
- Q_UNUSED(glyphs);
- Q_UNUSED(flags);
-}
-
-QFontEngine::FaceId QCoreTextFontEngine::faceId() const
-{
- return QFontEngine::FaceId();
-}
-
-bool QCoreTextFontEngine::canRender(const QChar *string, int len)
-{
- QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
- QCFType<CFStringRef>(CFStringCreateWithCharactersNoCopy(0,
- reinterpret_cast<const UniChar *>(string),
- len, kCFAllocatorNull)),
- CFRangeMake(0, len));
- return retFont != 0;
- return false;
-}
-
- bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
- {
- QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
- if (!table || !length)
- return false;
- CFIndex tableLength = CFDataGetLength(table);
- int availableLength = *length;
- *length = tableLength;
- if (buffer) {
- if (tableLength > availableLength)
- return false;
- CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
- }
- return true;
- }
-
-void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *)
-{
- // ###
-}
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-
#ifndef QT_MAC_USE_COCOA
QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning)
: QFontEngineMulti(0)
@@ -1419,6 +749,7 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len)
return uc;
}
+// Not used directly for shaping, only used to calculate m_averageCharWidth
bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
{
if (!cmap) {
@@ -1591,6 +922,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint
DisposeATSCubicClosePathUPP(closePath);
}
+QFont QFontEngineMac::createExplicitFont() const
+{
+ FMFont fmFont = FMGetFontFromATSFontRef(fontID);
+
+ FMFontFamily fmFamily;
+ FMFontStyle fmStyle;
+ QString familyName;
+ if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) {
+ ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily);
+ QCFString cfFamilyName;;
+ ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName);
+ familyName = cfFamilyName;
+ } else {
+ QCFString cfFontName;
+ ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName);
+ familyName = cfFontName;
+ }
+
+ return createExplicitFontWithName(familyName);
+}
+
void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path,
QTextItem::RenderFlags)
{
@@ -1677,7 +1029,7 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
return indexed;
}
-QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t)
+QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t)
{
QImage im = imageForGlyph(glyph, margin, true);
@@ -1685,7 +1037,7 @@ QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTra
im = im.transformed(t);
}
- qmacfontengine_gamma_correct(&im);
+ qGamma_correct_back_to_linear_cs(&im);
return im;
}
diff --git a/src/gui/text/qfontengine_mac_p.h b/src/gui/text/qfontengine_mac_p.h
new file mode 100644
index 0000000000..5577c765a6
--- /dev/null
+++ b/src/gui/text/qfontengine_mac_p.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTENGINE_MAC_P_H
+#define QFONTENGINE_MAC_P_H
+
+#include <private/qfontengine_p.h>
+
+#ifndef QT_MAC_USE_COCOA
+class QFontEngineMacMulti;
+class QFontEngineMac : public QFontEngine
+{
+ friend class QFontEngineMacMulti;
+public:
+ QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine = 0);
+ virtual ~QFontEngineMac();
+
+ virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *numGlyphs, QTextEngine::ShaperFlags flags) const;
+ virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
+
+ virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
+ virtual glyph_metrics_t boundingBox(glyph_t glyph);
+
+ virtual QFixed ascent() const;
+ virtual QFixed descent() const;
+ virtual QFixed leading() const;
+ virtual QFixed xHeight() const;
+ virtual qreal maxCharWidth() const;
+ virtual QFixed averageCharWidth() const;
+
+ virtual QFont createExplicitFont() const;
+
+ virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
+ QPainterPath *path, QTextItem::RenderFlags);
+
+ virtual const char *name() const { return "QFontEngineMac"; }
+
+ virtual bool canRender(const QChar *string, int len);
+
+ virtual int synthesized() const { return synthesisFlags; }
+
+ virtual Type type() const { return QFontEngine::Mac; }
+
+ void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight);
+
+ virtual FaceId faceId() const;
+ virtual QByteArray getSfntTable(uint tag) const;
+ virtual Properties properties() const;
+ virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
+ virtual QImage alphaMapForGlyph(glyph_t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
+
+private:
+ QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
+
+ ATSUFontID fontID;
+ QCFType<CGFontRef> cgFont;
+ ATSUStyle style;
+ int synthesisFlags;
+ mutable QGlyphLayout kashidaGlyph;
+ QFontEngineMacMulti *multiEngine;
+ mutable const unsigned char *cmap;
+ mutable bool symbolCMap;
+ mutable QByteArray cmapTable;
+ CGAffineTransform transform;
+ QFixed m_ascent;
+ QFixed m_descent;
+ QFixed m_leading;
+ qreal m_maxCharWidth;
+ QFixed m_xHeight;
+ QFixed m_averageCharWidth;
+};
+
+class QFontEngineMacMulti : public QFontEngineMulti
+{
+ friend class QFontEngineMac;
+public:
+ // internal
+ struct ShaperItem
+ {
+ inline ShaperItem() : string(0), from(0), length(0),
+ log_clusters(0), charAttributes(0) {}
+
+ const QChar *string;
+ int from;
+ int length;
+ QGlyphLayout glyphs;
+ unsigned short *log_clusters;
+ const HB_CharAttributes *charAttributes;
+ QTextEngine::ShaperFlags flags;
+ };
+
+ QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning);
+ virtual ~QFontEngineMacMulti();
+
+ virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,
+ unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
+
+ virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
+ virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
+
+ virtual const char *name() const { return "ATSUI"; }
+
+ virtual bool canRender(const QChar *string, int len);
+
+ inline ATSUFontID macFontID() const { return fontID; }
+
+protected:
+ virtual void loadEngine(int at);
+
+private:
+ inline const QFontEngineMac *engineAt(int i) const
+ { return static_cast<const QFontEngineMac *>(engines.at(i)); }
+
+ bool stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, ShaperItem *item) const;
+
+ int fontIndexForFontID(ATSUFontID id) const;
+
+ ATSUFontID fontID;
+ uint kerning : 1;
+
+ mutable ATSUTextLayout textLayout;
+ mutable ATSUStyle style;
+ CGAffineTransform transform;
+};
+#endif //!QT_MAC_USE_COCOA
+
+#endif // QFONTENGINE_MAC_P_H
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index ea2d925f5a..bbb242bda9 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -120,6 +120,14 @@ public:
TestFontEngine = 0x1000
};
+ enum GlyphFormat {
+ Format_None,
+ Format_Render = Format_None,
+ Format_Mono,
+ Format_A8,
+ Format_A32
+ };
+
QFontEngine();
virtual ~QFontEngine();
@@ -155,6 +163,7 @@ public:
SynthesizedStretch = 0x4
};
virtual int synthesized() const { return 0; }
+ virtual bool supportsSubPixelPositions() const { return false; }
virtual QFixed emSquareSize() const { return ascent(); }
@@ -168,11 +177,15 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_QPA)
virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0;
#endif
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
+
+ /* Creates a QFont object to represent this particular QFontEngine */
+ virtual QFont createExplicitFont() const;
+
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
@@ -183,8 +196,15 @@ public:
* Returns an image indexed_8 with index values ranging from 0=fully transparent to 255=opaque
*/
virtual QImage alphaMapForGlyph(glyph_t);
+ virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
- virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
+ virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t);
+
+ virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, GlyphFormat /*format*/)
+ {
+ return boundingBox(glyph, matrix);
+ }
virtual void removeGlyphFromCache(glyph_t);
@@ -237,7 +257,7 @@ public:
bool symbol;
mutable HB_FontRec hbFont;
mutable HB_Face hbFace;
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
struct KernPair {
uint left_right;
QFixed adjust;
@@ -254,13 +274,14 @@ public:
int glyphFormat;
protected:
+ QFont createExplicitFontWithName(const QString &familyName) const;
static const QVector<QRgb> &grayPalette();
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
private:
struct GlyphCacheEntry {
void *context;
- QFontEngineGlyphCache *cache;
+ QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
bool operator==(const GlyphCacheEntry &other) { return context == other.context && cache == other.cache; }
};
@@ -412,214 +433,6 @@ protected:
QVector<QFontEngine *> engines;
};
-#if defined(Q_WS_MAC)
-
-struct QCharAttributes;
-class QFontEngineMacMulti;
-# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-class QCoreTextFontEngineMulti;
-class QCoreTextFontEngine : public QFontEngine
-{
-public:
- QCoreTextFontEngine(CTFontRef font, const QFontDef &def,
- QCoreTextFontEngineMulti *multiEngine = 0);
- ~QCoreTextFontEngine();
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
- virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
-
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
- virtual glyph_metrics_t boundingBox(glyph_t glyph);
-
- virtual QFixed ascent() const;
- virtual QFixed descent() const;
- virtual QFixed leading() const;
- virtual QFixed xHeight() const;
- virtual qreal maxCharWidth() const;
- virtual QFixed averageCharWidth() const;
-
- virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
- QPainterPath *path, QTextItem::RenderFlags);
-
- virtual const char *name() const { return "QCoreTextFontEngine"; }
-
- virtual bool canRender(const QChar *string, int len);
-
- virtual int synthesized() const { return synthesisFlags; }
-
- virtual Type type() const { return QFontEngine::Mac; }
-
- void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight);
-
- virtual FaceId faceId() const;
- virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const;
- virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
- virtual QImage alphaMapForGlyph(glyph_t);
- virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
- virtual qreal minRightBearing() const;
- virtual qreal minLeftBearing() const;
-
-
-private:
- QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
- CTFontRef ctfont;
- CGFontRef cgFont;
- QCoreTextFontEngineMulti *parentEngine;
- int synthesisFlags;
- CGAffineTransform transform;
- friend class QCoreTextFontEngineMulti;
-};
-
-class QCoreTextFontEngineMulti : public QFontEngineMulti
-{
-public:
- QCoreTextFontEngineMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef,
- const QFontDef &fontDef, bool kerning);
- ~QCoreTextFontEngineMulti();
-
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
- QTextEngine::ShaperFlags flags) const;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
- QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
-
-
- virtual void recalcAdvances(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
- virtual void doKerning(int , QGlyphLayout *, QTextEngine::ShaperFlags) const;
-
- virtual const char *name() const { return "CoreText"; }
-protected:
- virtual void loadEngine(int at);
-
-private:
- inline const QCoreTextFontEngine *engineAt(int i) const
- { return static_cast<const QCoreTextFontEngine *>(engines.at(i)); }
-
- uint fontIndexForFont(CTFontRef id) const;
- CTFontRef ctfont;
- mutable QCFType<CFMutableDictionaryRef> attributeDict;
- CGAffineTransform transform;
- friend class QFontDialogPrivate;
-};
-# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-
-#ifndef QT_MAC_USE_COCOA
-class QFontEngineMac : public QFontEngine
-{
- friend class QFontEngineMacMulti;
-public:
- QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine = 0);
- virtual ~QFontEngineMac();
-
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *numGlyphs, QTextEngine::ShaperFlags flags) const;
- virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
- virtual glyph_metrics_t boundingBox(glyph_t glyph);
-
- virtual QFixed ascent() const;
- virtual QFixed descent() const;
- virtual QFixed leading() const;
- virtual QFixed xHeight() const;
- virtual qreal maxCharWidth() const;
- virtual QFixed averageCharWidth() const;
-
- virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
- QPainterPath *path, QTextItem::RenderFlags);
-
- virtual const char *name() const { return "QFontEngineMac"; }
-
- virtual bool canRender(const QChar *string, int len);
-
- virtual int synthesized() const { return synthesisFlags; }
-
- virtual Type type() const { return QFontEngine::Mac; }
-
- void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight);
-
- virtual FaceId faceId() const;
- virtual QByteArray getSfntTable(uint tag) const;
- virtual Properties properties() const;
- virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
- virtual QImage alphaMapForGlyph(glyph_t);
- virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
-
-private:
- QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
-
- ATSUFontID fontID;
- QCFType<CGFontRef> cgFont;
- ATSUStyle style;
- int synthesisFlags;
- mutable QGlyphLayout kashidaGlyph;
- QFontEngineMacMulti *multiEngine;
- mutable const unsigned char *cmap;
- mutable bool symbolCMap;
- mutable QByteArray cmapTable;
- CGAffineTransform transform;
- QFixed m_ascent;
- QFixed m_descent;
- QFixed m_leading;
- qreal m_maxCharWidth;
- QFixed m_xHeight;
- QFixed m_averageCharWidth;
-};
-
-class QFontEngineMacMulti : public QFontEngineMulti
-{
- friend class QFontEngineMac;
-public:
- // internal
- struct ShaperItem
- {
- inline ShaperItem() : string(0), from(0), length(0),
- log_clusters(0), charAttributes(0) {}
-
- const QChar *string;
- int from;
- int length;
- QGlyphLayout glyphs;
- unsigned short *log_clusters;
- const HB_CharAttributes *charAttributes;
- QTextEngine::ShaperFlags flags;
- };
-
- QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning);
- virtual ~QFontEngineMacMulti();
-
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,
- unsigned short *logClusters, const HB_CharAttributes *charAttributes) const;
-
- virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
- virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-
- virtual const char *name() const { return "ATSUI"; }
-
- virtual bool canRender(const QChar *string, int len);
-
- inline ATSUFontID macFontID() const { return fontID; }
-
-protected:
- virtual void loadEngine(int at);
-
-private:
- inline const QFontEngineMac *engineAt(int i) const
- { return static_cast<const QFontEngineMac *>(engines.at(i)); }
-
- bool stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, ShaperItem *item) const;
-
- int fontIndexForFontID(ATSUFontID id) const;
-
- ATSUFontID fontID;
- uint kerning : 1;
-
- mutable ATSUTextLayout textLayout;
- mutable ATSUStyle style;
- CGAffineTransform transform;
-};
-#endif //!QT_MAC_USE_COCOA
-#endif
-
class QTestFontEngine : public QFontEngineBox
{
public:
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp
new file mode 100644
index 0000000000..cccbc92fc4
--- /dev/null
+++ b/src/gui/text/qfontengine_qpa.cpp
@@ -0,0 +1,691 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfontengine_qpa_p.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QBuffer>
+
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/QPlatformFontDatabase>
+#include <QtGui/private/qpaintengine_raster_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG_HEADER
+//#define DEBUG_FONTENGINE
+
+static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = {
+ QFontEngineQPA::StringType, // FontName
+ QFontEngineQPA::StringType, // FileName
+ QFontEngineQPA::UInt32Type, // FileIndex
+ QFontEngineQPA::UInt32Type, // FontRevision
+ QFontEngineQPA::StringType, // FreeText
+ QFontEngineQPA::FixedType, // Ascent
+ QFontEngineQPA::FixedType, // Descent
+ QFontEngineQPA::FixedType, // Leading
+ QFontEngineQPA::FixedType, // XHeight
+ QFontEngineQPA::FixedType, // AverageCharWidth
+ QFontEngineQPA::FixedType, // MaxCharWidth
+ QFontEngineQPA::FixedType, // LineThickness
+ QFontEngineQPA::FixedType, // MinLeftBearing
+ QFontEngineQPA::FixedType, // MinRightBearing
+ QFontEngineQPA::FixedType, // UnderlinePosition
+ QFontEngineQPA::UInt8Type, // GlyphFormat
+ QFontEngineQPA::UInt8Type, // PixelSize
+ QFontEngineQPA::UInt8Type, // Weight
+ QFontEngineQPA::UInt8Type, // Style
+ QFontEngineQPA::StringType, // EndOfHeader
+ QFontEngineQPA::BitFieldType// WritingSystems
+};
+
+
+#if defined(DEBUG_HEADER)
+# define DEBUG_VERIFY qDebug
+#else
+# define DEBUG_VERIFY if (0) qDebug
+#endif
+
+#define READ_VERIFY(type, variable) \
+ if (tagPtr + sizeof(type) > endPtr) { \
+ DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \
+ return 0; \
+ } \
+ variable = qFromBigEndian<type>(tagPtr); \
+ DEBUG_VERIFY() << "read value" << variable << "of type " #type; \
+ tagPtr += sizeof(type)
+
+template <typename T>
+T readValue(const uchar *&data)
+{
+ T value = qFromBigEndian<T>(data);
+ data += sizeof(T);
+ return value;
+}
+
+#define VERIFY(condition) \
+ if (!(condition)) { \
+ DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \
+ return 0; \
+ }
+
+#define VERIFY_TAG(condition) \
+ if (!(condition)) { \
+ DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \
+ return 0; \
+ }
+
+static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr)
+{
+ quint16 tag, length;
+ READ_VERIFY(quint16, tag);
+ READ_VERIFY(quint16, length);
+ if (tag == QFontEngineQPA::Tag_EndOfHeader)
+ return endPtr;
+ if (tag < QFontEngineQPA::NumTags) {
+ switch (tagTypes[tag]) {
+ case QFontEngineQPA::BitFieldType:
+ case QFontEngineQPA::StringType:
+ // can't do anything...
+ break;
+ case QFontEngineQPA::UInt32Type:
+ VERIFY_TAG(length == sizeof(quint32));
+ break;
+ case QFontEngineQPA::FixedType:
+ VERIFY_TAG(length == sizeof(quint32));
+ break;
+ case QFontEngineQPA::UInt8Type:
+ VERIFY_TAG(length == sizeof(quint8));
+ break;
+ }
+#if defined(DEBUG_HEADER)
+ if (length == 1)
+ qDebug() << "tag data" << hex << *tagPtr;
+ else if (length == 4)
+ qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3];
+#endif
+ }
+ return tagPtr + length;
+}
+
+const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const
+{
+ if (!g || g >= glyphMapEntries)
+ return 0;
+ const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset);
+ quint32 glyphPos = qFromBigEndian<quint32>(gmapPtr[g]);
+ if (glyphPos > glyphDataSize) {
+ if (glyphPos == 0xffffffff)
+ return 0;
+#if defined(DEBUG_FONTENGINE)
+ qDebug() << "glyph" << g << "outside of glyphData, remapping font file";
+#endif
+ if (glyphPos > glyphDataSize)
+ return 0;
+ }
+ return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos);
+}
+
+bool QFontEngineQPA::verifyHeader(const uchar *data, int size)
+{
+ VERIFY(size >= int(sizeof(Header)));
+ const Header *header = reinterpret_cast<const Header *>(data);
+ if (header->magic[0] != 'Q'
+ || header->magic[1] != 'P'
+ || header->magic[2] != 'F'
+ || header->magic[3] != '2')
+ return false;
+
+ VERIFY(header->majorVersion <= CurrentMajorVersion);
+ const quint16 dataSize = qFromBigEndian<quint16>(header->dataSize);
+ VERIFY(size >= int(sizeof(Header)) + dataSize);
+
+ const uchar *tagPtr = data + sizeof(Header);
+ const uchar *tagEndPtr = tagPtr + dataSize;
+ while (tagPtr < tagEndPtr - 3) {
+ tagPtr = verifyTag(tagPtr, tagEndPtr);
+ VERIFY(tagPtr);
+ }
+
+ VERIFY(tagPtr <= tagEndPtr);
+ return true;
+}
+
+QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag)
+{
+ const Header *header = reinterpret_cast<const Header *>(data);
+ const uchar *tagPtr = data + sizeof(Header);
+ const uchar *endPtr = tagPtr + qFromBigEndian<quint16>(header->dataSize);
+ while (tagPtr < endPtr - 3) {
+ quint16 tag = readValue<quint16>(tagPtr);
+ quint16 length = readValue<quint16>(tagPtr);
+ if (tag == requestedTag) {
+ switch (tagTypes[requestedTag]) {
+ case StringType:
+ return QVariant(QString::fromUtf8(reinterpret_cast<const char *>(tagPtr), length));
+ case UInt32Type:
+ return QVariant(readValue<quint32>(tagPtr));
+ case UInt8Type:
+ return QVariant(uint(*tagPtr));
+ case FixedType:
+ return QVariant(QFixed::fromFixed(readValue<quint32>(tagPtr)).toReal());
+ case BitFieldType:
+ return QVariant(QByteArray(reinterpret_cast<const char *>(tagPtr), length));
+ }
+ return QVariant();
+ } else if (tag == Tag_EndOfHeader) {
+ break;
+ }
+ tagPtr += length;
+ }
+
+ return QVariant();
+}
+
+
+
+static inline unsigned int getChar(const QChar *str, int &i, const int len)
+{
+ unsigned int uc = str[i].unicode();
+ if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
+ uint low = str[i+1].unicode();
+ if (low >= 0xdc00 && low < 0xe000) {
+ uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
+ ++i;
+ }
+ }
+ return uc;
+}
+
+QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data)
+ : fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size())
+{
+ fontDef = def;
+ cache_cost = 100;
+ externalCMap = 0;
+ cmapOffset = 0;
+ cmapSize = 0;
+ glyphMapOffset = 0;
+ glyphMapEntries = 0;
+ glyphDataOffset = 0;
+ glyphDataSize = 0;
+ kerning_pairs_loaded = false;
+ readOnly = true;
+
+#if defined(DEBUG_FONTENGINE)
+ qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
+#endif
+
+ if (!verifyHeader(fontData, dataSize)) {
+#if defined(DEBUG_FONTENGINE)
+ qDebug() << "verifyHeader failed!";
+#endif
+ return;
+ }
+
+ const Header *header = reinterpret_cast<const Header *>(fontData);
+
+ readOnly = (header->lock == 0xffffffff);
+
+ const uchar *imgData = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize);
+ const uchar *endPtr = fontData + dataSize;
+ while (imgData <= endPtr - 8) {
+ quint16 blockTag = readValue<quint16>(imgData);
+ imgData += 2; // skip padding
+ quint32 blockSize = readValue<quint32>(imgData);
+
+ if (blockTag == CMapBlock) {
+ cmapOffset = imgData - fontData;
+ cmapSize = blockSize;
+ } else if (blockTag == GMapBlock) {
+ glyphMapOffset = imgData - fontData;
+ glyphMapEntries = blockSize / 4;
+ } else if (blockTag == GlyphBlock) {
+ glyphDataOffset = imgData - fontData;
+ glyphDataSize = blockSize;
+ }
+
+ imgData += blockSize;
+ }
+
+ face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString());
+ face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt();
+
+ // get the real cmap
+ if (cmapOffset) {
+ int tableSize = cmapSize;
+ const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize);
+ if (cmapPtr)
+ cmapOffset = cmapPtr - fontData;
+ else
+ cmapOffset = 0;
+ } else if (externalCMap) {
+ int tableSize = cmapSize;
+ externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize);
+ }
+
+ // verify all the positions in the glyphMap
+ if (glyphMapOffset) {
+ const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset);
+ for (uint i = 0; i < glyphMapEntries; ++i) {
+ quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]);
+ if (glyphDataPos == 0xffffffff)
+ continue;
+ if (glyphDataPos >= glyphDataSize) {
+ // error
+ glyphMapOffset = 0;
+ glyphMapEntries = 0;
+ break;
+ }
+ }
+ }
+
+#if defined(DEBUG_FONTENGINE)
+ if (!isValid())
+ qDebug() << "fontData" << fontData << "dataSize" << dataSize
+ << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset
+ << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset
+ << "fd" << fd << "glyphDataSize" << glyphDataSize;
+#endif
+}
+
+QFontEngineQPA::~QFontEngineQPA()
+{
+}
+
+bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const
+{
+ Q_UNUSED(tag);
+ Q_UNUSED(buffer);
+ *length = 0;
+ return false;
+}
+
+bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
+{
+ if (*nglyphs < len) {
+ *nglyphs = len;
+ return false;
+ }
+
+#if defined(DEBUG_FONTENGINE)
+ QSet<QChar> seenGlyphs;
+#endif
+
+ const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset);
+
+ bool mirrored = flags & QTextEngine::RightToLeft;
+ int glyph_pos = 0;
+ if (symbol) {
+ for (int i = 0; i < len; ++i) {
+ unsigned int uc = getChar(str, i, len);
+ if (mirrored)
+ uc = QChar::mirroredChar(uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
+ ++glyph_pos;
+ }
+ } else {
+ for (int i = 0; i < len; ++i) {
+ unsigned int uc = getChar(str, i, len);
+ if (mirrored)
+ uc = QChar::mirroredChar(uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+#if 0 && defined(DEBUG_FONTENGINE)
+ QChar c(uc);
+ if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
+ qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
+
+ seenGlyphs.insert(c);
+#endif
+ ++glyph_pos;
+ }
+ }
+
+ *nglyphs = glyph_pos;
+ glyphs->numGlyphs = glyph_pos;
+ recalcAdvances(glyphs, flags);
+ return true;
+}
+
+void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const
+{
+ for (int i = 0; i < glyphs->numGlyphs; ++i) {
+ const Glyph *g = findGlyph(glyphs->glyphs[i]);
+ if (!g) {
+ glyphs->glyphs[i] = 0;
+ continue;
+ }
+ glyphs->advances_x[i] = g->advance;
+ glyphs->advances_y[i] = 0;
+ }
+}
+
+QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g)
+{
+ const Glyph *glyph = findGlyph(g);
+ if (!glyph)
+ return QImage();
+
+ const uchar *bits = ((const uchar *) glyph) + sizeof(Glyph);
+
+ QImage image(bits,glyph->width, glyph->height, glyph->bytesPerLine, QImage::Format_Indexed8);
+
+ return image;
+}
+
+void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
+{
+ addBitmapFontToPath(x, y, glyphs, path, flags);
+}
+
+glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs)
+{
+ glyph_metrics_t overall;
+ // initialize with line height, we get the same behaviour on all platforms
+ overall.y = -ascent();
+ overall.height = ascent() + descent() + 1;
+
+ QFixed ymax = 0;
+ QFixed xmax = 0;
+ for (int i = 0; i < glyphs.numGlyphs; i++) {
+ const Glyph *g = findGlyph(glyphs.glyphs[i]);
+ if (!g)
+ continue;
+
+ QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
+ QFixed y = overall.yoff + glyphs.offsets[i].y + g->y;
+ overall.x = qMin(overall.x, x);
+ overall.y = qMin(overall.y, y);
+ xmax = qMax(xmax, x + g->width);
+ ymax = qMax(ymax, y + g->height);
+ overall.xoff += g->advance;
+ }
+ overall.height = qMax(overall.height, ymax - overall.y);
+ overall.width = xmax - overall.x;
+
+ return overall;
+}
+
+glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph)
+{
+ glyph_metrics_t overall;
+ const Glyph *g = findGlyph(glyph);
+ if (!g)
+ return overall;
+ overall.x = g->x;
+ overall.y = g->y;
+ overall.width = g->width;
+ overall.height = g->height;
+ overall.xoff = g->advance;
+ return overall;
+}
+
+QFixed QFontEngineQPA::ascent() const
+{
+ return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>());
+}
+
+QFixed QFontEngineQPA::descent() const
+{
+ return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>());
+}
+
+QFixed QFontEngineQPA::leading() const
+{
+ return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>());
+}
+
+qreal QFontEngineQPA::maxCharWidth() const
+{
+ return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>();
+}
+
+qreal QFontEngineQPA::minLeftBearing() const
+{
+ return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>();
+}
+
+qreal QFontEngineQPA::minRightBearing() const
+{
+ return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>();
+}
+
+QFixed QFontEngineQPA::underlinePosition() const
+{
+ return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>());
+}
+
+QFixed QFontEngineQPA::lineThickness() const
+{
+ return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>());
+}
+
+QFontEngine::Type QFontEngineQPA::type() const
+{
+ return QFontEngine::QPF2;
+}
+
+bool QFontEngineQPA::canRender(const QChar *string, int len)
+{
+ const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset);
+
+ if (symbol) {
+ for (int i = 0; i < len; ++i) {
+ unsigned int uc = getChar(string, i, len);
+ glyph_t g = getTrueTypeGlyphIndex(cmap, uc);
+ if(!g && uc < 0x100)
+ g = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
+ if (!g)
+ return false;
+ }
+ } else {
+ for (int i = 0; i < len; ++i) {
+ unsigned int uc = getChar(string, i, len);
+ if (!getTrueTypeGlyphIndex(cmap, uc))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool QFontEngineQPA::isValid() const
+{
+ return fontData && dataSize && (cmapOffset || externalCMap)
+ && glyphMapOffset && glyphDataOffset && glyphDataSize > 0;
+}
+
+void QPAGenerator::generate()
+{
+ writeHeader();
+ writeGMap();
+ writeBlock(QFontEngineQPA::GlyphBlock, QByteArray());
+
+ dev->seek(4); // position of header.lock
+ writeUInt32(0);
+}
+
+void QPAGenerator::writeHeader()
+{
+ QFontEngineQPA::Header header;
+
+ header.magic[0] = 'Q';
+ header.magic[1] = 'P';
+ header.magic[2] = 'F';
+ header.magic[3] = '2';
+ header.lock = 1;
+ header.majorVersion = QFontEngineQPA::CurrentMajorVersion;
+ header.minorVersion = QFontEngineQPA::CurrentMinorVersion;
+ header.dataSize = 0;
+ dev->write((const char *)&header, sizeof(header));
+
+ writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8());
+
+ QFontEngine::FaceId face = fe->faceId();
+ writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename);
+ writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index);
+
+ {
+ uchar data[4];
+ uint len = 4;
+ bool ok = fe->getSfntTableData(MAKE_TAG('h', 'e', 'a', 'd'), data, &len);
+ if (ok) {
+ const quint32 revision = qFromBigEndian<quint32>(data);
+ writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision);
+ }
+ }
+
+ writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent());
+ writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent());
+ writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading());
+ writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight());
+ writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth());
+ writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth()));
+ writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness());
+ writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing()));
+ writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing()));
+ writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition());
+ writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize);
+ writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight);
+ writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style);
+
+ writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs);
+
+ writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray());
+ align4();
+
+ const quint64 size = dev->pos();
+ header.dataSize = qToBigEndian<quint16>(size - sizeof(header));
+ dev->seek(0);
+ dev->write((const char *)&header, sizeof(header));
+ dev->seek(size);
+}
+
+void QPAGenerator::writeGMap()
+{
+ const quint16 glyphCount = fe->glyphCount();
+
+ writeUInt16(QFontEngineQPA::GMapBlock);
+ writeUInt16(0); // padding
+ writeUInt32(glyphCount * 4);
+
+ QByteArray &buffer = dev->buffer();
+ const int numBytes = glyphCount * sizeof(quint32);
+ qint64 pos = buffer.size();
+ buffer.resize(pos + numBytes);
+ qMemSet(buffer.data() + pos, 0xff, numBytes);
+ dev->seek(pos + numBytes);
+}
+
+void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data)
+{
+ writeUInt16(tag);
+ writeUInt16(0); // padding
+ const int padSize = ((data.size() + 3) / 4) * 4 - data.size();
+ writeUInt32(data.size() + padSize);
+ dev->write(data);
+ for (int i = 0; i < padSize; ++i)
+ writeUInt8(0);
+}
+
+void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string)
+{
+ writeUInt16(tag);
+ writeUInt16(string.length());
+ dev->write(string);
+}
+
+void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value)
+{
+ writeUInt16(tag);
+ writeUInt16(sizeof(value));
+ writeUInt32(value);
+}
+
+void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value)
+{
+ writeUInt16(tag);
+ writeUInt16(sizeof(value));
+ writeUInt8(value);
+}
+
+void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value)
+{
+ writeUInt16(tag);
+ writeUInt16(sizeof(quint32));
+ writeUInt32(value.value());
+}
+
+
+/*
+ Creates a new multi QPA engine.
+
+ This function takes ownership of the QFontEngine, increasing it's refcount.
+*/
+QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks)
+ : QFontEngineMulti(fallbacks.size() + 1),
+ fallbackFamilies(fallbacks), script(_script)
+{
+ engines[0] = fe;
+ fe->ref.ref();
+ fontDef = engines[0]->fontDef;
+}
+
+void QFontEngineMultiQPA::loadEngine(int at)
+{
+ Q_ASSERT(at < engines.size());
+ Q_ASSERT(engines.at(at) == 0);
+
+ QFontDef request = fontDef;
+ request.styleStrategy |= QFont::NoFontMerging;
+ request.family = fallbackFamilies.at(at-1);
+ engines[at] = QFontDatabase::findFont(script,
+ /*fontprivate*/0,
+ request);
+ Q_ASSERT(engines[at]);
+ engines[at]->ref.ref();
+ engines[at]->fontDef = request;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h
new file mode 100644
index 0000000000..467fca617e
--- /dev/null
+++ b/src/gui/text/qfontengine_qpa_p.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTENGINE_QPA_P_H
+#define QFONTENGINE_QPA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include <QtCore/qconfig.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qendian.h>
+#include <QtCore/QBuffer>
+
+#include "qfontengine_p.h"
+
+#include <QtCore/QFile>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QFontEngine;
+class QFreetypeFace;
+class QBuffer;
+
+class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine
+{
+public:
+ // if you add new tags please make sure to update the tables in
+ // qpfutil.cpp and tools/makeqpf/qpf2.cpp
+ enum HeaderTag {
+ Tag_FontName, // 0 string
+ Tag_FileName, // 1 string
+ Tag_FileIndex, // 2 quint32
+ Tag_FontRevision, // 3 quint32
+ Tag_FreeText, // 4 string
+ Tag_Ascent, // 5 QFixed
+ Tag_Descent, // 6 QFixed
+ Tag_Leading, // 7 QFixed
+ Tag_XHeight, // 8 QFixed
+ Tag_AverageCharWidth, // 9 QFixed
+ Tag_MaxCharWidth, // 10 QFixed
+ Tag_LineThickness, // 11 QFixed
+ Tag_MinLeftBearing, // 12 QFixed
+ Tag_MinRightBearing, // 13 QFixed
+ Tag_UnderlinePosition, // 14 QFixed
+ Tag_GlyphFormat, // 15 quint8
+ Tag_PixelSize, // 16 quint8
+ Tag_Weight, // 17 quint8
+ Tag_Style, // 18 quint8
+ Tag_EndOfHeader, // 19 string
+ Tag_WritingSystems, // 20 bitfield
+
+ NumTags
+ };
+
+ enum TagType {
+ StringType,
+ FixedType,
+ UInt8Type,
+ UInt32Type,
+ BitFieldType
+ };
+
+ struct Tag
+ {
+ quint16 tag;
+ quint16 size;
+ };
+
+ enum GlyphFormat {
+ BitmapGlyphs = 1,
+ AlphamapGlyphs = 8
+ };
+
+ enum {
+ CurrentMajorVersion = 2,
+ CurrentMinorVersion = 0
+ };
+
+ // The CMap is identical to the TrueType CMap table format
+ // The GMap table is a normal array with the total number of
+ // covered glyphs in the TrueType font
+ enum BlockTag {
+ CMapBlock,
+ GMapBlock,
+ GlyphBlock
+ };
+
+ struct Q_PACKED Header
+ {
+ char magic[4]; // 'QPF2'
+ quint32 lock; // values: 0 = unlocked, 0xffffffff = read-only, otherwise qws client id of locking process
+ quint8 majorVersion;
+ quint8 minorVersion;
+ quint16 dataSize;
+ };
+
+ struct Q_PACKED Block
+ {
+ quint16 tag;
+ quint16 pad;
+ quint32 dataSize;
+ };
+
+ struct Q_PACKED Glyph
+ {
+ quint8 width;
+ quint8 height;
+ quint8 bytesPerLine;
+ qint8 x;
+ qint8 y;
+ qint8 advance;
+ };
+
+ QFontEngineQPA(const QFontDef &def, const QByteArray &data);
+ ~QFontEngineQPA();
+
+ FaceId faceId() const { return face_id; }
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
+
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
+ void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
+
+ void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags);
+ QImage alphaMapForGlyph(glyph_t t);
+
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
+ glyph_metrics_t boundingBox(glyph_t glyph);
+
+ QFixed ascent() const;
+ QFixed descent() const;
+ QFixed leading() const;
+ qreal maxCharWidth() const;
+ qreal minLeftBearing() const;
+ qreal minRightBearing() const;
+ QFixed underlinePosition() const;
+ QFixed lineThickness() const;
+
+ Type type() const;
+
+ bool canRender(const QChar *string, int len);
+ inline const char *name() const { return "QPF2"; }
+
+ virtual int glyphCount() const { return glyphMapEntries; }
+
+ bool isValid() const;
+
+ const Glyph *findGlyph(glyph_t g) const;
+
+ static bool verifyHeader(const uchar *data, int size);
+ static QVariant extractHeaderField(const uchar *data, HeaderTag tag);
+
+private:
+
+ const uchar *fontData;
+ int dataSize;
+ const uchar *externalCMap;
+ quint32 cmapOffset;
+ int cmapSize;
+ quint32 glyphMapOffset;
+ quint32 glyphMapEntries;
+ quint32 glyphDataOffset;
+ quint32 glyphDataSize;
+ QString internalFileName;
+ QString encodedFileName;
+ bool readOnly;
+
+ FaceId face_id;
+ QByteArray freetypeCMapTable;
+ mutable bool kerning_pairs_loaded;
+};
+
+struct QPAGenerator
+{
+ QPAGenerator(QBuffer *device, QFontEngine *engine)
+ : dev(device), fe(engine) {}
+
+ void generate();
+ void writeHeader();
+ void writeGMap();
+ void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data);
+
+ void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string);
+ void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value);
+ void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value);
+ void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value);
+
+ void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
+ void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); }
+ void writeUInt8(quint8 value) { dev->write((const char *)&value, sizeof(value)); }
+ void writeInt8(qint8 value) { dev->write((const char *)&value, sizeof(value)); }
+
+ void align4() { while (dev->pos() & 3) { dev->putChar('\0'); } }
+
+ QBuffer *dev;
+ QFontEngine *fe;
+};
+
+class QFontEngineMultiQPA : public QFontEngineMulti
+{
+public:
+ QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks);
+
+ void loadEngine(int at);
+
+private:
+ QStringList fallbackFamilies;
+ int script;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFONTENGINE_QPA_P_H
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
index b572cdd049..4317ee6a3c 100644
--- a/src/gui/text/qfontengine_s60.cpp
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -108,7 +108,8 @@ QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const
Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
TInt error = KErrNone;
TInt tableByteLength = 0;
- TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength));
+ TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength);
+ Q_CHECK_PTR(table);
const QByteArray result(static_cast<const char*>(table), tableByteLength);
m_trueTypeExtension->ReleaseTrueTypeTable(table);
return result;
@@ -138,8 +139,8 @@ bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *len
TInt error = KErrNone;
TInt tableByteLength;
- TAny *table =
- q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength));
+ TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength);
+ Q_CHECK_PTR(table);
if (error != KErrNone) {
return false;
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index 167e19af64..ecb0384724 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -1251,7 +1251,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform)
#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D
-QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t)
+QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t)
{
HFONT font = hfont;
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index f60a5c3956..22085e8f3d 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -104,7 +104,7 @@ public:
virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); }
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
- virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform);
+ virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
#ifndef Q_CC_MINGW
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index 1b0fbf1f16..d5ec58407d 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -992,7 +992,7 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
face_id.filename = file_name;
face_id.index = face_index;
- canUploadGlyphsToServer = qApp->thread() == QThread::currentThread();
+ canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread());
subpixelType = Subpixel_None;
if (antialias) {
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index f85f4b9842..8f8d93daf9 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
-class QFontEngineGlyphCache
+class QFontEngineGlyphCache: public QSharedData
{
public:
enum Type {
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index ca8500bdc3..5cd85fb3ac 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -443,6 +443,21 @@ bool QFontMetrics::inFont(QChar ch) const
}
/*!
+ Returns true if the character encoded in UCS-4/UTF-32 is a valid
+ character in the font; otherwise returns false.
+*/
+bool QFontMetrics::inFontUcs4(uint ucs4) const
+{
+ const int script = QUnicodeTables::script(ucs4);
+ QFontEngine *engine = d->engineForScript(script);
+ Q_ASSERT(engine != 0);
+ if (engine->type() == QFontEngine::Box)
+ return false;
+ QString utf16 = QString::fromUcs4(&ucs4, 1);
+ return engine->canRender(utf16.data(), utf16.length());
+}
+
+/*!
Returns the left bearing of character \a ch in the font.
The left bearing is the right-ward distance of the left-most pixel
@@ -1315,6 +1330,21 @@ bool QFontMetricsF::inFont(QChar ch) const
}
/*!
+ Returns true if the character encoded in UCS-4/UTF-32 is a valid
+ character in the font; otherwise returns false.
+*/
+bool QFontMetricsF::inFontUcs4(uint ucs4) const
+{
+ const int script = QUnicodeTables::script(ucs4);
+ QFontEngine *engine = d->engineForScript(script);
+ Q_ASSERT(engine != 0);
+ if (engine->type() == QFontEngine::Box)
+ return false;
+ QString utf16 = QString::fromUcs4(&ucs4, 1);
+ return engine->canRender(utf16.data(), utf16.length());
+}
+
+/*!
Returns the left bearing of character \a ch in the font.
The left bearing is the right-ward distance of the left-most pixel
@@ -1779,7 +1809,7 @@ qreal QFontMetricsF::lineWidth() const
Use the boundingRect() function in combination with
QString::left() instead.
-
+
\oldcode
QRect rect = boundingRect(text, len);
\newcode
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index 71b7abe8b0..5fe8676993 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -71,6 +71,10 @@ public:
~QFontMetrics();
QFontMetrics &operator=(const QFontMetrics &);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QFontMetrics &operator=(QFontMetrics &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
int ascent() const;
int descent() const;
@@ -85,6 +89,7 @@ public:
int averageCharWidth() const;
bool inFont(QChar) const;
+ bool inFontUcs4(uint ucs4) const;
int leftBearing(QChar) const;
int rightBearing(QChar) const;
@@ -148,7 +153,10 @@ public:
QFontMetricsF &operator=(const QFontMetricsF &);
QFontMetricsF &operator=(const QFontMetrics &);
-
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QFontMetricsF &operator=(QFontMetricsF &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
qreal ascent() const;
qreal descent() const;
qreal height() const;
@@ -162,6 +170,7 @@ public:
qreal averageCharWidth() const;
bool inFont(QChar) const;
+ bool inFontUcs4(uint ucs4) const;
qreal leftBearing(QChar) const;
qreal rightBearing(QChar) const;
diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp
new file mode 100644
index 0000000000..2447752581
--- /dev/null
+++ b/src/gui/text/qglyphs.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglyphs.h"
+#include "qglyphs_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGlyphs
+ \brief the QGlyphs class provides direct access to the internal glyphs in a font
+ \since 4.8
+
+ \ingroup text
+ \mainclass
+
+ When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points
+ into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode
+ representation of the text and the QFont object will in this case serve as a convenient
+ abstraction that hides the details of what actually takes place when displaying the text
+ on-screen. For instance, by the time the text actually reaches the screen, it may be represented
+ by a set of fonts in addition to the one specified by the user, e.g. in case the originally
+ selected font did not support all the writing systems contained in the text.
+
+ Under certain circumstances, it can be useful as an application developer to have more low-level
+ control over which glyphs in a specific font are drawn to the screen. This could for instance
+ be the case in applications that use an external font engine and text shaper together with Qt.
+ QGlyphs provides an interface to the raw data needed to get text on the screen. It
+ contains a list of glyph indexes, a position for each glyph and a font.
+
+ It is the user's responsibility to ensure that the selected font actually contains the
+ provided glyph indexes.
+
+ QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs
+ objects, and QPainter::drawGlyphs() can be used to draw the glyphs.
+*/
+
+
+/*!
+ Constructs an empty QGlyphs object.
+*/
+QGlyphs::QGlyphs() : d(new QGlyphsPrivate)
+{
+}
+
+/*!
+ Constructs a QGlyphs object which is a copy of \a other.
+*/
+QGlyphs::QGlyphs(const QGlyphs &other)
+{
+ d = other.d;
+}
+
+/*!
+ Destroys the QGlyphs.
+*/
+QGlyphs::~QGlyphs()
+{
+ // Required for QExplicitlySharedDataPointer
+}
+
+/*!
+ \internal
+*/
+void QGlyphs::detach()
+{
+ if (d->ref != 1)
+ d.detach();
+}
+
+/*!
+ Assigns \a other to this QGlyphs object.
+*/
+QGlyphs &QGlyphs::operator=(const QGlyphs &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes,
+ the list of positions and the font are all equal, otherwise returns false.
+*/
+bool QGlyphs::operator==(const QGlyphs &other) const
+{
+ return ((d == other.d)
+ || (d->glyphIndexes == other.d->glyphIndexes
+ && d->glyphPositions == other.d->glyphPositions
+ && d->font == other.d->font));
+}
+
+/*!
+ Compares \a other to this QGlyphs object. Returns true if any of the list of glyph
+ indexes, the list of positions or the font are different, otherwise returns false.
+*/
+bool QGlyphs::operator!=(const QGlyphs &other) const
+{
+ return !(*this == other);
+}
+
+/*!
+ \internal
+
+ Adds together the lists of glyph indexes and positions in \a other and this QGlyphs
+ object and returns the result. The font in the returned QGlyphs will be the same as in
+ this QGlyphs object.
+*/
+QGlyphs QGlyphs::operator+(const QGlyphs &other) const
+{
+ QGlyphs ret(*this);
+ ret += other;
+ return ret;
+}
+
+/*!
+ \internal
+
+ Appends the glyph indexes and positions in \a other to this QGlyphs object and returns
+ a reference to the current object.
+*/
+QGlyphs &QGlyphs::operator+=(const QGlyphs &other)
+{
+ detach();
+
+ d->glyphIndexes += other.d->glyphIndexes;
+ d->glyphPositions += other.d->glyphPositions;
+
+ return *this;
+}
+
+/*!
+ Returns the font selected for this QGlyphs object.
+
+ \sa setFont()
+*/
+QFont QGlyphs::font() const
+{
+ return d->font;
+}
+
+/*!
+ Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly
+ resolvable font which defines glyphs for the specified glyph indexes.
+
+ \sa font(), setGlyphIndexes()
+*/
+void QGlyphs::setFont(const QFont &font)
+{
+ detach();
+ d->font = font;
+}
+
+/*!
+ Returns the glyph indexes for this QGlyphs object.
+
+ \sa setGlyphIndexes(), setPositions()
+*/
+QVector<quint32> QGlyphs::glyphIndexes() const
+{
+ return d->glyphIndexes;
+}
+
+/*!
+ Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must
+ be valid for the selected font.
+*/
+void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes)
+{
+ detach();
+ d->glyphIndexes = glyphIndexes;
+}
+
+/*!
+ Returns the position of the edge of the baseline for each glyph in this set of glyph indexes.
+*/
+QVector<QPointF> QGlyphs::positions() const
+{
+ return d->glyphPositions;
+}
+
+/*!
+ Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to
+ \a positions.
+*/
+void QGlyphs::setPositions(const QVector<QPointF> &positions)
+{
+ detach();
+ d->glyphPositions = positions;
+}
+
+/*!
+ Clears all data in the QGlyphs object.
+*/
+void QGlyphs::clear()
+{
+ detach();
+ d->glyphPositions = QVector<QPointF>();
+ d->glyphIndexes = QVector<quint32>();
+ d->font = QFont();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h
new file mode 100644
index 0000000000..282ecb47c5
--- /dev/null
+++ b/src/gui/text/qglyphs.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLYPHS_H
+#define QGLYPHS_H
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qfont.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGlyphsPrivate;
+class Q_GUI_EXPORT QGlyphs
+{
+public:
+ QGlyphs();
+ QGlyphs(const QGlyphs &other);
+ ~QGlyphs();
+
+ QFont font() const;
+ void setFont(const QFont &font);
+
+ QVector<quint32> glyphIndexes() const;
+ void setGlyphIndexes(const QVector<quint32> &glyphIndexes);
+
+ QVector<QPointF> positions() const;
+ void setPositions(const QVector<QPointF> &positions);
+
+ void clear();
+
+ QGlyphs &operator=(const QGlyphs &other);
+ bool operator==(const QGlyphs &other) const;
+ bool operator!=(const QGlyphs &other) const;
+
+private:
+ friend class QGlyphsPrivate;
+ friend class QTextLine;
+
+ QGlyphs operator+(const QGlyphs &other) const;
+ QGlyphs &operator+=(const QGlyphs &other);
+
+ void detach();
+ QExplicitlySharedDataPointer<QGlyphsPrivate> d;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QGLYPHS_H
diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h
new file mode 100644
index 0000000000..c39f5d0e56
--- /dev/null
+++ b/src/gui/text/qglyphs_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLYPHS_P_H
+#define QGLYPHS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of internal files. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qfont.h>
+#include "qglyphs.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGlyphsPrivate: public QSharedData
+{
+public:
+ QGlyphsPrivate()
+ {
+ }
+
+ QGlyphsPrivate(const QGlyphsPrivate &other)
+ : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font)
+ {
+ }
+
+ QVector<quint32> glyphIndexes;
+ QVector<QPointF> glyphPositions;
+ QFont font;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGLYPHS_P_H
diff --git a/src/gui/text/qpfutil.cpp b/src/gui/text/qpfutil.cpp
index 4a0e29f742..734d4c3592 100644
--- a/src/gui/text/qpfutil.cpp
+++ b/src/gui/text/qpfutil.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-static QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = {
+static const QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = {
QFontEngineQPF::StringType, // FontName
QFontEngineQPF::StringType, // FileName
QFontEngineQPF::UInt32Type, // FileIndex
diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp
new file mode 100644
index 0000000000..d6dff413c0
--- /dev/null
+++ b/src/gui/text/qplatformfontdatabase_qpa.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformfontdatabase_qpa.h"
+#include <QtGui/private/qfontengine_p.h>
+#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDir>
+
+QT_BEGIN_NAMESPACE
+
+extern void qt_registerFont(const QString &familyname, const QString &foundryname, int weight,
+ QFont::Style style, int stretch, bool antialiased,bool scalable, int pixelSize,
+ const QSupportedWritingSystems &writingSystems, void *hanlde);
+
+void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
+{
+ if (dataArray.size() == 0)
+ return;
+
+ const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
+ if (QFontEngineQPA::verifyHeader(data, dataArray.size())) {
+ QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString();
+ int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt();
+ QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight);
+ QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style);
+ QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray();
+
+ if (!fontName.isEmpty() && pixelSize) {
+ QFont::Weight fontWeight = QFont::Normal;
+ if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt)
+ fontWeight = QFont::Weight(weight.toInt());
+
+ QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt());
+
+ QSupportedWritingSystems writingSystems;
+ for (int i = 0; i < writingSystemBits.count(); ++i) {
+ uchar currentByte = writingSystemBits.at(i);
+ for (int j = 0; j < 8; ++j) {
+ if (currentByte & 1)
+ writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j));
+ currentByte >>= 1;
+ }
+ }
+ QFont::Stretch stretch = QFont::Unstretched;
+ registerFont(fontName,QString(),fontWeight,fontStyle,stretch,true,false,pixelSize,writingSystems,handle);
+ }
+ } else {
+ qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?";
+ }
+}
+
+void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight,
+ QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize,
+ const QSupportedWritingSystems &writingSystems, void *usrPtr)
+{
+ if (scalable)
+ pixelSize = 0;
+ qt_registerFont(familyname,foundryname,weight,style,stretch,antialiased,scalable,pixelSize,writingSystems,usrPtr);
+}
+
+class QWritingSystemsPrivate
+{
+public:
+ QWritingSystemsPrivate()
+ : ref(1)
+ , vector(QFontDatabase::WritingSystemsCount,false)
+ {
+ }
+
+ QWritingSystemsPrivate(const QWritingSystemsPrivate *other)
+ : ref(1)
+ , vector(other->vector)
+ {
+ }
+
+ QAtomicInt ref;
+ QVector<bool> vector;
+};
+
+QSupportedWritingSystems::QSupportedWritingSystems()
+{
+ d = new QWritingSystemsPrivate;
+}
+
+QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other)
+{
+ d = other.d;
+ d->ref.ref();
+}
+
+QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other)
+{
+ if (d != other.d) {
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = other.d;
+ }
+ return *this;
+}
+
+QSupportedWritingSystems::~QSupportedWritingSystems()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+void QSupportedWritingSystems::detach()
+{
+ if (d->ref != 1) {
+ QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d);
+ if (!d->ref.deref())
+ delete d;
+ d = newd;
+ }
+}
+
+void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support)
+{
+ detach();
+ d->vector[writingSystem] = support;
+}
+
+bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const
+{
+ return d->vector.at(writingSystem);
+}
+
+/*!
+ \class QSupportedWritingSystems
+ \brief The QSupportedWritingSystems class is used when registering fonts with the internal Qt
+ fontdatabase
+ \ingroup painting
+
+ Its to provide an easy to use interface for indicating what writing systems a specific font
+ supports.
+
+*/
+
+/*!
+ This function is called once at startup by Qts internal fontdatabase. Reimplement this function
+ in a subclass for a convenient place to initialise the internal fontdatabase.
+
+ The default implementation looks in the fontDir() location and registers all qpf2 fonts.
+*/
+void QPlatformFontDatabase::populateFontDatabase()
+{
+ QString fontpath = fontDir();
+
+ if(!QFile::exists(fontpath)) {
+ qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?",
+ qPrintable(fontpath));
+ }
+
+ QDir dir(fontpath);
+ dir.setNameFilters(QStringList() << QLatin1String("*.qpf2"));
+ dir.refresh();
+ for (int i = 0; i < int(dir.count()); ++i) {
+ const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
+ QFile file(QString::fromLocal8Bit(fileName));
+ if (file.open(QFile::ReadOnly)) {
+ const QByteArray fileData = file.readAll();
+ QByteArray *fileDataPtr = new QByteArray(fileData);
+ registerQPF2Font(fileData, fileDataPtr);
+ }
+ }
+}
+
+/*!
+
+*/
+QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle)
+{
+ Q_UNUSED(script);
+ Q_UNUSED(handle);
+ QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
+ QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
+ qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script;
+ return engine;
+}
+
+/*!
+
+*/
+QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const
+{
+ Q_UNUSED(family);
+ Q_UNUSED(style);
+ Q_UNUSED(script);
+ return QStringList();
+}
+
+/*!
+ Adds an application font. Returns a list of family names, or an empty list if the font could
+ not be added
+*/
+QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
+{
+ Q_UNUSED(fontData);
+ Q_UNUSED(fileName);
+
+ qWarning("This plugin does not support application fonts");
+ return QStringList();
+}
+
+/*!
+
+*/
+void QPlatformFontDatabase::releaseHandle(void *handle)
+{
+ QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
+ delete fileDataPtr;
+}
+
+/*!
+
+*/
+QString QPlatformFontDatabase::fontDir() const
+{
+ QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR"));
+ if (fontpath.isEmpty()) {
+#ifndef QT_NO_SETTINGS
+ fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath);
+ fontpath += QLatin1String("/fonts");
+#endif
+ }
+
+ return fontpath;
+}
+
+/*!
+ \class QPlatformFontDatabase
+ \brief The QPlatformFontDatabase makes it possible to customize how fonts are picked up, and
+ and how they are rendered
+
+ \ingroup painting
+
+ QPlatformFontDatabase is the superclass which is intended to let platform implementations use
+ native font handling.
+
+ Qt has its internal fontdatabase which it uses to pick up available fonts. To be able
+ to populate this database subclass this class, and reimplement populateFontDatabase().
+
+ Use the function registerFont to populate the internal fontdatabase.
+
+ Sometimes a specified font does not have the required glyphs, then the fallbackForFamily
+ function is called.
+
+ \sa QSupportedWritingSystems
+*/
+QT_END_NAMESPACE
diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h
new file mode 100644
index 0000000000..aa465ab9ca
--- /dev/null
+++ b/src/gui/text/qplatformfontdatabase_qpa.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMFONTDATABASE_QPA_H
+#define QPLATFORMFONTDATABASE_QPA_H
+
+#include <QtCore/qconfig.h>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+#include <QtGui/QFontDatabase>
+#include <QtGui/private/qfont_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWritingSystemsPrivate;
+
+class Q_GUI_EXPORT QSupportedWritingSystems
+{
+public:
+
+ QSupportedWritingSystems();
+ QSupportedWritingSystems(const QSupportedWritingSystems &other);
+ QSupportedWritingSystems &operator=(const QSupportedWritingSystems &other);
+ ~QSupportedWritingSystems();
+
+ void setSupported(QFontDatabase::WritingSystem, bool supported = true);
+ bool supported(QFontDatabase::WritingSystem) const;
+
+private:
+ void detach();
+
+ QWritingSystemsPrivate *d;
+
+ friend Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &);
+ friend Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &);
+};
+
+Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &);
+Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &);
+
+class QFontRequestPrivate;
+
+class Q_GUI_EXPORT QPlatformFontDatabase
+{
+public:
+ virtual void populateFontDatabase();
+ virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle);
+ virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const;
+ virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
+ virtual void releaseHandle(void *handle);
+
+ virtual QString fontDir() const;
+
+ //callback
+ static void registerQPF2Font(const QByteArray &dataArray, void *handle);
+ static void registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight,
+ QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize,
+ const QSupportedWritingSystems &writingSystems, void *handle);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPLATFORMFONTDATABASE_QPA_H
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 58bfbc6461..89ca6bf8c1 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -64,6 +64,7 @@
#include "qgraphicssceneevent.h"
#include "qprinter.h"
#include "qtextdocumentwriter.h"
+#include "private/qtextcursor_p.h"
#include <qtextformat.h>
#include <qdatetime.h>
@@ -1904,6 +1905,8 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
}
layout->setAdditionalFormats(overrides);
cursor.endEditBlock();
+ if (cursor.d)
+ cursor.d->setX();
}
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -2894,7 +2897,7 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget
if (widget)
style = widget->style();
style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret);
- selection.format = qVariantValue<QTextFormat>(ret.variant).toCharFormat();
+ selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat();
} else {
QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive;
selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight));
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index dc55e0ee85..4eaeb41ee9 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -230,6 +230,7 @@ private:
QSharedDataPointer<QTextCursorPrivate> d;
friend class QTextDocumentFragmentPrivate;
friend class QTextCopyHelper;
+ friend class QTextControlPrivate;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 673ae4648c..be67279cb4 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1985,6 +1985,8 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
if (fi.exists()) {
resourceUrl =
QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name);
+ } else if (currentURL.isEmpty()) {
+ resourceUrl.setScheme(QLatin1String("file"));
}
}
@@ -2602,14 +2604,40 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
default: html += QLatin1String("<ul"); // ### should not happen
}
- html += QLatin1String(" style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;");
+ QString styleString = QString::fromLatin1("margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;");
if (format.hasProperty(QTextFormat::ListIndent)) {
- html += QLatin1String(" -qt-list-indent: ");
- html += QString::number(format.indent());
- html += QLatin1Char(';');
+ styleString += QLatin1String(" -qt-list-indent: ");
+ styleString += QString::number(format.indent());
+ styleString += QLatin1Char(';');
+ }
+
+ if (format.hasProperty(QTextFormat::ListNumberPrefix)) {
+ QString numberPrefix = format.numberPrefix();
+ numberPrefix.replace(QLatin1Char('"'), QLatin1String("\\22"));
+ numberPrefix.replace(QLatin1Char('\''), QLatin1String("\\27")); // FIXME: There's a problem in the CSS parser the prevents this from being correctly restored
+ styleString += QLatin1String(" -qt-list-number-prefix: ");
+ styleString += QLatin1Char('\'');
+ styleString += numberPrefix;
+ styleString += QLatin1Char('\'');
+ styleString += QLatin1Char(';');
}
+ if (format.hasProperty(QTextFormat::ListNumberSuffix)) {
+ if (format.numberSuffix() != QLatin1String(".")) { // this is our default
+ QString numberSuffix = format.numberSuffix();
+ numberSuffix.replace(QLatin1Char('"'), QLatin1String("\\22"));
+ numberSuffix.replace(QLatin1Char('\''), QLatin1String("\\27")); // see above
+ styleString += QLatin1String(" -qt-list-number-suffix: ");
+ styleString += QLatin1Char('\'');
+ styleString += numberSuffix;
+ styleString += QLatin1Char('\'');
+ styleString += QLatin1Char(';');
+ }
+ }
+
+ html += QLatin1String(" style=\"");
+ html += styleString;
html += QLatin1String("\">");
}
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index b4bd8583b0..7890b38067 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -682,6 +682,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
QTextListFormat listFmt;
listFmt.setStyle(style);
+ if (!currentNode->textListNumberPrefix.isNull())
+ listFmt.setNumberPrefix(currentNode->textListNumberPrefix);
+ if (!currentNode->textListNumberSuffix.isNull())
+ listFmt.setNumberSuffix(currentNode->textListNumberSuffix);
++indent;
if (currentNode->hasCssListIndent)
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index d721c91d90..157b7bc417 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2506,6 +2506,23 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
fd->currentLayoutStruct = 0;
}
+static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
+ QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
+{
+ *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
+ *lineBreakHeight = *lineHeight;
+ if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
+ *lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
+ else
+ *lineAdjustment = QFixed::fromReal(line.height()) - *lineHeight;
+ }
+ else {
+ *lineBreakHeight = QFixed::fromReal(line.height());
+ *lineAdjustment = 0;
+ }
+}
+
void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosition, const QTextBlockFormat &blockFormat,
QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat)
{
@@ -2639,8 +2656,12 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
- QFixed lineHeight = QFixed::fromReal(line.height());
- if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) {
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
+ if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
@@ -2652,7 +2673,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
right -= text_indent;
}
- line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy).toReal()));
+ line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy - lineAdjustment).toReal()));
layoutStruct->y += lineHeight;
layoutStruct->contentsWidth
= qMax<QFixed>(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + line.naturalTextWidth()) + totalRightMargin);
@@ -2672,11 +2693,16 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
- const QFixed lineHeight = QFixed::fromReal(line.height());
+
+ QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
+ qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+
if (layoutStruct->pageHeight != QFIXED_MAX) {
- if (layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom)
+ if (layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom)
layoutStruct->newPage();
- line.setPosition(QPointF(line.position().x(), layoutStruct->y.toReal() - tl->position().y()));
+ line.setPosition(QPointF(line.position().x(), (layoutStruct->y - lineAdjustment).toReal() - tl->position().y()));
}
layoutStruct->y += lineHeight;
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index b511b5a237..415fa4b71f 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -612,7 +612,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon
} else {
eor = current;
}
- dir = QChar::DirON; status.eor = QChar::DirAN;
+ dir = QChar::DirAN; status.eor = QChar::DirAN;
break;
case QChar::DirCS:
if(status.eor == QChar::DirAN) {
@@ -1233,6 +1233,8 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
shaper_item.num_glyphs -= itemBoundaries[k + 1];
}
shaper_item.initialGlyphCount = shaper_item.num_glyphs;
+ if (shaper_item.num_glyphs < shaper_item.item.length)
+ shaper_item.num_glyphs = shaper_item.item.length;
QFontEngine *actualFontEngine = font;
uint engineIdx = 0;
@@ -1257,7 +1259,8 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const
}
const QGlyphLayout g = availableGlyphs(&si).mid(glyph_pos);
- moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
+ if (shaper_item.num_glyphs > shaper_item.item.length)
+ moveGlyphData(g.mid(shaper_item.num_glyphs), g.mid(shaper_item.initialGlyphCount), remaining_glyphs);
shaper_item.glyphs = g.glyphs;
shaper_item.attributes = g.attributes;
@@ -1389,6 +1392,7 @@ void QTextEngine::invalidate()
maxWidth = 0;
if (specialData)
specialData->resolvedFormatIndices.clear();
+ feCache.reset();
}
void QTextEngine::clearLineData()
@@ -1780,6 +1784,13 @@ QFont QTextEngine::font(const QScriptItem &si) const
return font;
}
+QTextEngine::FontEngineCache::FontEngineCache()
+{
+ reset();
+}
+
+//we cache the previous results of this function, as calling it numerous times with the same effective
+//input is common (and hard to cache at a higher level)
QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const
{
QFontEngine *engine = 0;
@@ -1788,28 +1799,47 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
QFont font = fnt;
if (hasFormats()) {
- QTextCharFormat f = format(&si);
- font = f.font();
-
- if (block.docHandle() && block.docHandle()->layout()) {
- // Make sure we get the right dpi on printers
- QPaintDevice *pdev = block.docHandle()->layout()->paintDevice();
- if (pdev)
- font = QFont(font, pdev);
+ if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) {
+ engine = feCache.prevFontEngine;
+ scaledEngine = feCache.prevScaledFontEngine;
} else {
- font = font.resolve(fnt);
- }
- engine = font.d->engineForScript(script);
- QTextCharFormat::VerticalAlignment valign = f.verticalAlignment();
- if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
- if (font.pointSize() != -1)
- font.setPointSize((font.pointSize() * 2) / 3);
- else
- font.setPixelSize((font.pixelSize() * 2) / 3);
- scaledEngine = font.d->engineForScript(script);
+ QTextCharFormat f = format(&si);
+ font = f.font();
+
+ if (block.docHandle() && block.docHandle()->layout()) {
+ // Make sure we get the right dpi on printers
+ QPaintDevice *pdev = block.docHandle()->layout()->paintDevice();
+ if (pdev)
+ font = QFont(font, pdev);
+ } else {
+ font = font.resolve(fnt);
+ }
+ engine = font.d->engineForScript(script);
+ QTextCharFormat::VerticalAlignment valign = f.verticalAlignment();
+ if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) {
+ if (font.pointSize() != -1)
+ font.setPointSize((font.pointSize() * 2) / 3);
+ else
+ font.setPixelSize((font.pixelSize() * 2) / 3);
+ scaledEngine = font.d->engineForScript(script);
+ }
+ feCache.prevFontEngine = engine;
+ feCache.prevScaledFontEngine = scaledEngine;
+ feCache.prevScript = script;
+ feCache.prevPosition = si.position;
+ feCache.prevLength = length(&si);
}
} else {
- engine = font.d->engineForScript(script);
+ if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1)
+ engine = feCache.prevFontEngine;
+ else {
+ engine = font.d->engineForScript(script);
+ feCache.prevFontEngine = engine;
+ feCache.prevScript = script;
+ feCache.prevPosition = -1;
+ feCache.prevLength = -1;
+ feCache.prevScaledFontEngine = 0;
+ }
}
if (si.analysis.flags == QScriptAnalysis::SmallCaps) {
@@ -2353,30 +2383,29 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (flags & Qt::TextShowMnemonic) {
itemize();
+ HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
+ if (!attributes)
+ return QString();
for (int i = 0; i < layoutData->items.size(); ++i) {
QScriptItem &si = layoutData->items[i];
if (!si.num_glyphs)
shape(i);
- HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
- if (!attributes)
- return QString();
-
unsigned short *logClusters = this->logClusters(&si);
QGlyphLayout glyphs = shapedGlyphs(&si);
const int end = si.position + length(&si);
- for (int i = si.position; i < end - 1; ++i)
+ for (int i = si.position; i < end - 1; ++i) {
if (layoutData->string.at(i) == QLatin1Char('&')) {
const int gp = logClusters[i - si.position];
glyphs.attributes[gp].dontPrint = true;
attributes[i + 1].charStop = false;
attributes[i + 1].whiteSpace = false;
attributes[i + 1].lineBreakType = HB_NoBreak;
- if (i < end - 1
- && layoutData->string.at(i + 1) == QLatin1Char('&'))
+ if (layoutData->string.at(i + 1) == QLatin1Char('&'))
++i;
}
+ }
}
}
@@ -2438,7 +2467,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (mode == Qt::ElideRight) {
QFixed currentWidth;
- int pos = 0;
+ int pos;
int nextBreak = 0;
do {
@@ -2458,7 +2487,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
return layoutData->string.left(pos) + ellipsisText;
} else if (mode == Qt::ElideLeft) {
QFixed currentWidth;
- int pos = layoutData->string.length();
+ int pos;
int nextBreak = layoutData->string.length();
do {
diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp
index ce42241fc8..c0a1e647da 100644
--- a/src/gui/text/qtextengine_mac.cpp
+++ b/src/gui/text/qtextengine_mac.cpp
@@ -41,6 +41,9 @@
#include "qtextengine_p.h"
+#include <private/qfontengine_coretext_p.h>
+#include <private/qfontengine_mac_p.h>
+
QT_BEGIN_NAMESPACE
// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 34723ab1b7..50d1ff8e65 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -128,7 +128,7 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis
TabOrObject = Tab,
Object = 7
};
- unsigned short script : 8;
+ unsigned short script : 7;
unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
unsigned short flags : 3;
inline bool operator == (const QScriptAnalysis &other) const {
@@ -385,7 +385,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine
QFixed textWidth;
QFixed textAdvance;
int from;
- signed int length : 29;
+ signed int length : 28;
mutable uint justified : 1;
mutable uint gridfitted : 1;
uint hasTrailingSpaces : 1;
@@ -435,7 +435,7 @@ public:
uint hasBidi : 1;
uint layoutState : 2;
uint memory_on_stack : 1;
- bool haveCharAttributes;
+ uint haveCharAttributes : 1;
QString string;
bool reallocate(int totalGlyphs);
};
@@ -556,6 +556,23 @@ public:
mutable QScriptLineArray lines;
+ struct FontEngineCache {
+ FontEngineCache();
+ mutable QFontEngine *prevFontEngine;
+ mutable QFontEngine *prevScaledFontEngine;
+ mutable int prevScript;
+ mutable int prevPosition;
+ mutable int prevLength;
+ inline void reset() {
+ prevFontEngine = 0;
+ prevScaledFontEngine = 0;
+ prevScript = -1;
+ prevPosition = -1;
+ prevLength = -1;
+ }
+ };
+ mutable FontEngineCache feCache;
+
QString text;
QFont fnt;
QTextBlock block;
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index c009ce7849..c9af4014d8 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -541,6 +541,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value TabPositions Specifies the tab positions. The tab positions are structs of QTextOption::Tab which are stored in
a QList (internally, in a QList<QVariant>).
\value BlockIndent
+ \value LineHeight
+ \value LineHeightType
\value BlockNonBreakableLines
\value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
@@ -933,7 +935,7 @@ qreal QTextFormat::doubleProperty(int propertyId) const
const QVariant prop = d->property(propertyId);
if (prop.userType() != QVariant::Double && prop.userType() != QMetaType::Float)
return 0.;
- return qVariantValue<qreal>(prop);
+ return qvariant_cast<qreal>(prop);
}
/*!
@@ -1856,6 +1858,10 @@ QFont QTextCharFormat::font() const
indentation is set with setIndent(), the indentation of the first
line with setTextIndent().
+ Line spacing is set with setLineHeight() and retrieved via lineHeight()
+ and lineHeightType(). The types of line spacing available are in the
+ LineHeightTypes enum.
+
Line breaking can be enabled and disabled with setNonBreakableLines().
The brush used to paint the paragraph's background
@@ -1872,6 +1878,22 @@ QFont QTextCharFormat::font() const
*/
/*!
+ \since 4.8
+ \enum QTextBlockFormat::LineHeightTypes
+
+ This enum describes the various types of line spacing support paragraphs can have.
+
+ \value SingleHeight This is the default line height: single spacing.
+ \value ProportionalHeight This sets the spacing proportional to the line (in percentage).
+ For example, set to 200 for double spacing.
+ \value FixedHeight This sets the line height to a fixed line height (in pixels).
+ \value MinimumHeight This sets the minimum line height (in pixels).
+ \value LineDistanceHeight This adds the specified height between lines (in pixels).
+
+ \sa lineHeight(), lineHeightType(), setLineHeight()
+*/
+
+/*!
\fn QTextBlockFormat::QTextBlockFormat()
Constructs a new QTextBlockFormat.
@@ -1903,7 +1925,7 @@ void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs)
QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin();
while (iter != tabs.constEnd()) {
QVariant v;
- qVariantSetValue<QTextOption::Tab>(v, *iter);
+ v.setValue<QTextOption::Tab>(*iter);
list.append(v);
++iter;
}
@@ -1925,7 +1947,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant);
QList<QVariant>::Iterator iter = variantsList.begin();
while(iter != variantsList.end()) {
- answer.append( qVariantValue<QTextOption::Tab>(*iter));
+ answer.append( qvariant_cast<QTextOption::Tab>(*iter));
++iter;
}
return answer;
@@ -2089,6 +2111,51 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
/*!
+ \fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
+ \since 4.8
+
+ This sets the line height for the paragraph to the value in height
+ which is dependant on heightType, described by the LineHeightTypes enum.
+
+ \sa LineHeightTypes, lineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling) const
+ \since 4.8
+
+ This returns what the height of the lines in the paragraph will be depending
+ on the given height of the script line and the scaling. The value that is returned
+ is also dependant on the given LineHeightType of the paragraph as well as the LineHeight
+ setting that has been set for the paragraph. The scaling is needed for the heights
+ that include a fixed number of pixels, to scale them appropriately for printing.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeight() const
+ \since 4.8
+
+ This returns the LineHeight property for the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeightType()
+*/
+
+
+/*!
+ \fn qreal QTextBlockFormat::lineHeightType() const
+ \since 4.8
+
+ This returns the LineHeightType property of the paragraph.
+
+ \sa LineHeightTypes, setLineHeight(), lineHeight()
+*/
+
+
+/*!
\fn void QTextBlockFormat::setNonBreakableLines(bool b)
If \a b is true, the lines in the paragraph are treated as
@@ -2235,6 +2302,44 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
\sa setIndent()
*/
+/*!
+ \fn void QTextListFormat::setNumberPrefix(const QString &numberPrefix)
+ \since 4.8
+
+ Sets the list format's number prefix. This can be used with all
+ sorted list types. It does not have any effect on unsorted list types.
+
+ \sa numberPrefix()
+*/
+
+/*!
+ \fn int QTextListFormat::numberPrefix() const
+ \since 4.8
+
+ Returns the list format's number prefix.
+
+ \sa setNumberPrefix()
+*/
+
+/*!
+ \fn void QTextListFormat::setNumberSuffix(const QString &numberSuffix)
+ \since 4.8
+
+ Sets the list format's number suffix. This can be used with all
+ sorted list types. It does not have any effect on unsorted list types.
+ The default suffix is ".".
+
+ \sa numberSuffix()
+*/
+
+/*!
+ \fn int QTextListFormat::numberSuffix() const
+ \since 4.8
+
+ Returns the list format's number suffix.
+
+ \sa setNumberSuffix()
+*/
/*!
\class QTextFrameFormat
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index eb9146fc22..9a573a0467 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -164,6 +164,8 @@ public:
TextIndent = 0x1034,
TabPositions = 0x1035,
BlockIndent = 0x1040,
+ LineHeight = 0x1048,
+ LineHeightType = 0x1049,
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
@@ -202,6 +204,8 @@ public:
// list properties
ListStyle = 0x3000,
ListIndent = 0x3001,
+ ListNumberPrefix = 0x3002,
+ ListNumberSuffix = 0x3003,
// table and frame properties
FrameBorder = 0x4000,
@@ -529,6 +533,14 @@ inline void QTextCharFormat::setTableCellColumnSpan(int _tableCellColumnSpan)
class Q_GUI_EXPORT QTextBlockFormat : public QTextFormat
{
public:
+ enum LineHeightTypes {
+ SingleHeight = 0,
+ ProportionalHeight = 1,
+ FixedHeight = 2,
+ MinimumHeight = 3,
+ LineDistanceHeight = 4
+ };
+
QTextBlockFormat();
bool isValid() const { return isBlockFormat(); }
@@ -566,6 +578,14 @@ public:
inline int indent() const
{ return intProperty(BlockIndent); }
+ inline void setLineHeight(qreal height, int heightType)
+ { setProperty(LineHeight, height); setProperty(LineHeightType, heightType); }
+ inline qreal lineHeight(qreal scriptLineHeight, qreal scaling) const;
+ inline qreal lineHeight() const
+ { return doubleProperty(LineHeight); }
+ inline int lineHeightType() const
+ { return intProperty(LineHeightType); }
+
inline void setNonBreakableLines(bool b)
{ setProperty(BlockNonBreakableLines, b); }
inline bool nonBreakableLines() const
@@ -590,6 +610,23 @@ inline void QTextBlockFormat::setAlignment(Qt::Alignment aalignment)
inline void QTextBlockFormat::setIndent(int aindent)
{ setProperty(BlockIndent, aindent); }
+inline qreal QTextBlockFormat::lineHeight(qreal scriptLineHeight, qreal scaling = 1.0) const
+{
+ switch(intProperty(LineHeightType)) {
+ case SingleHeight:
+ return(scriptLineHeight);
+ case ProportionalHeight:
+ return(scriptLineHeight * doubleProperty(LineHeight) / 100.0);
+ case FixedHeight:
+ return(doubleProperty(LineHeight) * scaling);
+ case MinimumHeight:
+ return(qMax(scriptLineHeight, doubleProperty(LineHeight) * scaling));
+ case LineDistanceHeight:
+ return(scriptLineHeight + doubleProperty(LineHeight) * scaling);
+ }
+ return(0);
+}
+
class Q_GUI_EXPORT QTextListFormat : public QTextFormat
{
public:
@@ -617,6 +654,14 @@ public:
inline int indent() const
{ return intProperty(ListIndent); }
+ inline void setNumberPrefix(const QString &numberPrefix);
+ inline QString numberPrefix() const
+ { return stringProperty(ListNumberPrefix); }
+
+ inline void setNumberSuffix(const QString &numberSuffix);
+ inline QString numberSuffix() const
+ { return stringProperty(ListNumberSuffix); }
+
protected:
explicit QTextListFormat(const QTextFormat &fmt);
friend class QTextFormat;
@@ -628,6 +673,12 @@ inline void QTextListFormat::setStyle(Style astyle)
inline void QTextListFormat::setIndent(int aindent)
{ setProperty(ListIndent, aindent); }
+inline void QTextListFormat::setNumberPrefix(const QString &np)
+{ setProperty(ListNumberPrefix, np); }
+
+inline void QTextListFormat::setNumberSuffix(const QString &ns)
+{ setProperty(ListNumberSuffix, ns); }
+
class Q_GUI_EXPORT QTextImageFormat : public QTextCharFormat
{
public:
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index e685197c47..3513a280c6 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1250,6 +1250,20 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::QtBlockIndent:
blockFormat.setIndent(decl.d->values.first().variant.toInt());
break;
+ case QCss::LineHeight: {
+ qreal lineHeight;
+ if (decl.realValue(&lineHeight, "px")) {
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::FixedHeight);
+ } else {
+ bool ok;
+ QString value = decl.d->values.first().toString();
+ lineHeight = value.toDouble(&ok);
+ if (ok)
+ blockFormat.setLineHeight(lineHeight, QTextBlockFormat::ProportionalHeight);
+ else
+ blockFormat.setLineHeight(0, QTextBlockFormat::SingleHeight);
+ }
+ break; }
case QCss::TextIndent: {
qreal indent = 0;
if (decl.realValue(&indent, "px"))
@@ -1323,6 +1337,12 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::ListStyle:
setListStyle(decl.d->values);
break;
+ case QCss::QtListNumberPrefix:
+ textListNumberPrefix = decl.d->values.first().variant.toString();
+ break;
+ case QCss::QtListNumberSuffix:
+ textListNumberSuffix = decl.d->values.first().variant.toString();
+ break;
default: break;
}
}
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 5e2b456c9f..4c44efd851 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -180,6 +180,8 @@ struct QTextHtmlParserNode {
uint displayMode : 3; // QTextHtmlElement::DisplayMode
uint hasHref : 1;
QTextListFormat::Style listStyle;
+ QString textListNumberPrefix;
+ QString textListNumberSuffix;
QString imageName;
qreal imageWidth;
qreal imageHeight;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index a996f59a86..354e8a9c3e 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -52,6 +52,8 @@
#include "qtextformat_p.h"
#include "qstyleoption.h"
#include "qpainterpath.h"
+#include "qglyphs.h"
+#include "qglyphs_p.h"
#include <limits.h>
#include <qdebug.h>
@@ -165,7 +167,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line)
/*!
Returns the inline object's rectangle.
- \sa ascent() descent() width()
+ \sa ascent(), descent(), width()
*/
QRectF QTextInlineObject::rect() const
{
@@ -176,7 +178,7 @@ QRectF QTextInlineObject::rect() const
/*!
Returns the inline object's width.
- \sa ascent() descent() rect()
+ \sa ascent(), descent(), rect()
*/
qreal QTextInlineObject::width() const
{
@@ -186,7 +188,7 @@ qreal QTextInlineObject::width() const
/*!
Returns the inline object's ascent.
- \sa descent() width() rect()
+ \sa descent(), width(), rect()
*/
qreal QTextInlineObject::ascent() const
{
@@ -196,7 +198,7 @@ qreal QTextInlineObject::ascent() const
/*!
Returns the inline object's descent.
- \sa ascent() width() rect()
+ \sa ascent(), width(), rect()
*/
qreal QTextInlineObject::descent() const
{
@@ -207,18 +209,17 @@ qreal QTextInlineObject::descent() const
Returns the inline object's total height. This is equal to
ascent() + descent() + 1.
- \sa ascent() descent() width() rect()
+ \sa ascent(), descent(), width(), rect()
*/
qreal QTextInlineObject::height() const
{
return eng->layoutData->items[itm].height().toReal();
}
-
/*!
Sets the inline object's width to \a w.
- \sa width() ascent() descent() rect()
+ \sa width(), ascent(), descent(), rect()
*/
void QTextInlineObject::setWidth(qreal w)
{
@@ -228,7 +229,7 @@ void QTextInlineObject::setWidth(qreal w)
/*!
Sets the inline object's ascent to \a a.
- \sa ascent() setDescent() width() rect()
+ \sa ascent(), setDescent(), width(), rect()
*/
void QTextInlineObject::setAscent(qreal a)
{
@@ -238,7 +239,7 @@ void QTextInlineObject::setAscent(qreal a)
/*!
Sets the inline object's decent to \a d.
- \sa descent() setAscent() width() rect()
+ \sa descent(), setAscent(), width(), rect()
*/
void QTextInlineObject::setDescent(qreal d)
{
@@ -246,7 +247,7 @@ void QTextInlineObject::setDescent(qreal d)
}
/*!
- The position of the inline object within the text layout.
+ The position of the inline object within the text layout.
*/
int QTextInlineObject::textPosition() const
{
@@ -254,8 +255,8 @@ int QTextInlineObject::textPosition() const
}
/*!
- Returns an integer describing the format of the inline object
- within the text layout.
+ Returns an integer describing the format of the inline object
+ within the text layout.
*/
int QTextInlineObject::formatIndex() const
{
@@ -263,7 +264,7 @@ int QTextInlineObject::formatIndex() const
}
/*!
- Returns format of the inline object within the text layout.
+ Returns format of the inline object within the text layout.
*/
QTextFormat QTextInlineObject::format() const
{
@@ -273,7 +274,7 @@ QTextFormat QTextInlineObject::format() const
}
/*!
- Returns if the object should be laid out right-to-left or left-to-right.
+ Returns if the object should be laid out right-to-left or left-to-right.
*/
Qt::LayoutDirection QTextInlineObject::textDirection() const
{
@@ -325,7 +326,6 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const
boundingRect(), and a minimumWidth() and a maximumWidth().
\sa QStaticText
-
*/
/*!
@@ -398,16 +398,19 @@ QTextLayout::~QTextLayout()
Sets the layout's font to the given \a font. The layout is
invalidated and must be laid out again.
- \sa text()
+ \sa font()
*/
void QTextLayout::setFont(const QFont &font)
{
d->fnt = font;
+ d->feCache.reset();
}
/*!
Returns the current font that is used for the layout, or a default
font if none is set.
+
+ \sa setFont()
*/
QFont QTextLayout::font() const
{
@@ -441,10 +444,10 @@ QString QTextLayout::text() const
}
/*!
- Sets the text option structure that controls the layout process to the
- given \a option.
+ Sets the text option structure that controls the layout process to the
+ given \a option.
- \sa textOption() QTextOption
+ \sa textOption()
*/
void QTextLayout::setTextOption(const QTextOption &option)
{
@@ -452,9 +455,9 @@ void QTextLayout::setTextOption(const QTextOption &option)
}
/*!
- Returns the current text option used to control the layout process.
+ Returns the current text option used to control the layout process.
- \sa setTextOption() QTextOption
+ \sa setTextOption()
*/
QTextOption QTextLayout::textOption() const
{
@@ -464,6 +467,8 @@ QTextOption QTextLayout::textOption() const
/*!
Sets the \a position and \a text of the area in the layout that is
processed before editing occurs.
+
+ \sa preeditAreaPosition(), preeditAreaText()
*/
void QTextLayout::setPreeditArea(int position, const QString &text)
{
@@ -492,6 +497,8 @@ void QTextLayout::setPreeditArea(int position, const QString &text)
/*!
Returns the position of the area in the text layout that will be
processed before editing occurs.
+
+ \sa preeditAreaText()
*/
int QTextLayout::preeditAreaPosition() const
{
@@ -500,6 +507,8 @@ int QTextLayout::preeditAreaPosition() const
/*!
Returns the text that is inserted in the layout before editing occurs.
+
+ \sa preeditAreaPosition()
*/
QString QTextLayout::preeditAreaText() const
{
@@ -508,8 +517,7 @@ QString QTextLayout::preeditAreaText() const
/*!
- Sets the additional formats supported by the text layout to \a
- formatList.
+ Sets the additional formats supported by the text layout to \a formatList.
\sa additionalFormats(), clearAdditionalFormats()
*/
@@ -535,6 +543,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
}
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
+ d->feCache.reset();
}
/*!
@@ -599,6 +608,8 @@ bool QTextLayout::cacheEnabled() const
/*!
Begins the layout process.
+
+ \sa endLayout()
*/
void QTextLayout::beginLayout()
{
@@ -616,6 +627,8 @@ void QTextLayout::beginLayout()
/*!
Ends the layout process.
+
+ \sa beginLayout()
*/
void QTextLayout::endLayout()
{
@@ -634,35 +647,33 @@ void QTextLayout::endLayout()
d->freeMemory();
}
-/*! \since 4.4
+/*!
+ \since 4.4
-Clears the line information in the layout. After having called
-this function, lineCount() returns 0.
- */
+ Clears the line information in the layout. After having called
+ this function, lineCount() returns 0.
+*/
void QTextLayout::clearLayout()
{
d->clearLineData();
}
-
/*!
Returns the next valid cursor position after \a oldPos that
respects the given cursor \a mode.
+ Returns value of \a oldPos, if \a oldPos is not a valid cursor position.
- \sa isValidCursorPosition() previousCursorPosition()
+ \sa isValidCursorPosition(), previousCursorPosition()
*/
int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
{
-// qDebug("looking for next cursor pos for %d", oldPos);
const HB_CharAttributes *attributes = d->attributes();
- if (!attributes)
- return 0;
- int len = d->block.isValid() ?
- (d->block.length() - 1)
- : d->layoutData->string.length();
-
- if (oldPos >= len)
+ int len = d->block.isValid() ? d->block.length() - 1
+ : d->layoutData->string.length();
+ Q_ASSERT(len <= d->layoutData->string.length());
+ if (!attributes || oldPos < 0 || oldPos >= len)
return oldPos;
+
if (mode == SkipCharacters) {
oldPos++;
while (oldPos < len && !attributes[oldPos].charStop)
@@ -679,22 +690,23 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
while (oldPos < len && d->atSpace(oldPos))
oldPos++;
}
-// qDebug(" -> %d", oldPos);
+
return oldPos;
}
/*!
Returns the first valid cursor position before \a oldPos that
respects the given cursor \a mode.
+ Returns value of \a oldPos, if \a oldPos is not a valid cursor position.
- \sa isValidCursorPosition() nextCursorPosition()
+ \sa isValidCursorPosition(), nextCursorPosition()
*/
int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
{
-// qDebug("looking for previous cursor pos for %d", oldPos);
const HB_CharAttributes *attributes = d->attributes();
- if (!attributes || oldPos <= 0)
- return 0;
+ if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length())
+ return oldPos;
+
if (mode == SkipCharacters) {
oldPos--;
while (oldPos && !attributes[oldPos].charStop)
@@ -712,7 +724,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
oldPos--;
}
}
-// qDebug(" -> %d", oldPos);
+
return oldPos;
}
@@ -739,7 +751,6 @@ bool QTextLayout::isValidCursorPosition(int pos) const
return attributes[pos].charStop;
}
-
/*!
Returns a new text line to be laid out if there is text to be
inserted into the layout; otherwise returns an invalid text line.
@@ -801,7 +812,7 @@ int QTextLayout::lineCount() const
/*!
Returns the \a{i}-th line of text in this text layout.
- \sa lineCount() lineForTextPosition()
+ \sa lineCount(), lineForTextPosition()
*/
QTextLine QTextLayout::lineAt(int i) const
{
@@ -811,7 +822,7 @@ QTextLine QTextLayout::lineAt(int i) const
/*!
Returns the line that contains the cursor position specified by \a pos.
- \sa isValidCursorPosition() lineAt()
+ \sa isValidCursorPosition(), lineAt()
*/
QTextLine QTextLayout::lineForTextPosition(int pos) const
{
@@ -902,8 +913,9 @@ qreal QTextLayout::maximumWidth() const
return d->maxWidth.toReal();
}
+
/*!
- \internal
+ \internal
*/
void QTextLayout::setFlags(int flags)
{
@@ -1028,6 +1040,35 @@ QScriptItem &QTextLineItemIterator::next()
return *si;
}
+static QFixed offsetInLigature(const unsigned short *logClusters,
+ const QGlyphLayout &glyphs,
+ int pos, int max, int glyph_pos)
+{
+ int offsetInCluster = 0;
+ for (int i = pos - 1; i >= 0; i--) {
+ if (logClusters[i] == glyph_pos)
+ offsetInCluster++;
+ else
+ break;
+ }
+
+ // in the case that the offset is inside a (multi-character) glyph,
+ // interpolate the position.
+ if (offsetInCluster > 0) {
+ int clusterLength = 0;
+ for (int i = pos - offsetInCluster; i < max; i++) {
+ if (logClusters[i] == glyph_pos)
+ clusterLength++;
+ else
+ break;
+ }
+ if (clusterLength)
+ return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength;
+ }
+
+ return 0;
+}
+
bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const
{
*selectionX = *selectionWidth = 0;
@@ -1067,8 +1108,19 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec
swidth += glyphs.effectiveAdvance(g);
}
- *selectionX = x + soff;
- *selectionWidth = swidth;
+ // If the starting character is in the middle of a ligature,
+ // selection should only contain the right part of that ligature
+ // glyph, so we need to get the width of the left part here and
+ // add it to *selectionX
+ QFixed leftOffsetInLigature = offsetInLigature(logClusters, glyphs, from,
+ to, start_glyph);
+ *selectionX = x + soff + leftOffsetInLigature;
+ *selectionWidth = swidth - leftOffsetInLigature;
+ // If the ending character is also part of a ligature, swidth does
+ // not contain that part yet, we also need to find out the width of
+ // that left part
+ *selectionWidth += offsetInLigature(logClusters, glyphs, to,
+ eng->length(item), end_glyph);
}
return true;
}
@@ -1114,9 +1166,26 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
return clip.isValid() ? (rect & clip) : rect;
}
+
+/*!
+ Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an
+ expensive function, and should not be called in a time sensitive context.
+
+ \since 4.8
+
+ \sa draw(), QPainter::drawGlyphs()
+*/
+QList<QGlyphs> QTextLayout::glyphs() const
+{
+ QList<QGlyphs> glyphs;
+ for (int i=0; i<d->lines.size(); ++i)
+ glyphs += QTextLine(i, d).glyphs(-1, -1);
+
+ return glyphs;
+}
+
/*!
- Draws the whole layout on the painter \a p at the position specified by
- \a pos.
+ Draws the whole layout on the painter \a p at the position specified by \a pos.
The rendered layout includes the given \a selections and is clipped within
the rectangle specified by \a clip.
*/
@@ -1290,12 +1359,12 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
}
/*!
- \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const
- \overload
+ \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const
+ \overload
- Draws a text cursor with the current pen at the given \a position using the
- \a painter specified.
- The corresponding position within the text is specified by \a cursorPosition.
+ Draws a text cursor with the current pen at the given \a position using the
+ \a painter specified.
+ The corresponding position within the text is specified by \a cursorPosition.
*/
void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const
{
@@ -1303,11 +1372,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
}
/*!
- \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const
+ \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const
- Draws a text cursor with the current pen and the specified \a width at the given \a position using the
- \a painter specified.
- The corresponding position within the text is specified by \a cursorPosition.
+ Draws a text cursor with the current pen and the specified \a width at the given \a position using the
+ \a painter specified.
+ The corresponding position within the text is specified by \a cursorPosition.
*/
void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const
{
@@ -1438,7 +1507,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
/*!
Returns the line's bounding rectangle.
- \sa x() y() textLength() width()
+ \sa x(), y(), textLength(), width()
*/
QRectF QTextLine::rect() const
{
@@ -1464,7 +1533,7 @@ QRectF QTextLine::naturalTextRect() const
/*!
Returns the line's x position.
- \sa rect() y() textLength() width()
+ \sa rect(), y(), textLength(), width()
*/
qreal QTextLine::x() const
{
@@ -1474,7 +1543,7 @@ qreal QTextLine::x() const
/*!
Returns the line's y position.
- \sa x() rect() textLength() width()
+ \sa x(), rect(), textLength(), width()
*/
qreal QTextLine::y() const
{
@@ -1484,7 +1553,7 @@ qreal QTextLine::y() const
/*!
Returns the line's width as specified by the layout() function.
- \sa naturalTextWidth() x() y() textLength() rect()
+ \sa naturalTextWidth(), x(), y(), textLength(), rect()
*/
qreal QTextLine::width() const
{
@@ -1495,7 +1564,7 @@ qreal QTextLine::width() const
/*!
Returns the line's ascent.
- \sa descent() height()
+ \sa descent(), height()
*/
qreal QTextLine::ascent() const
{
@@ -1505,7 +1574,7 @@ qreal QTextLine::ascent() const
/*!
Returns the line's descent.
- \sa ascent() height()
+ \sa ascent(), height()
*/
qreal QTextLine::descent() const
{
@@ -1517,7 +1586,7 @@ qreal QTextLine::descent() const
if leading is not included. If leading is included, this equals to
ascent() + descent() + leading() + 1.
- \sa ascent() descent() leading() setLeadingIncluded()
+ \sa ascent(), descent(), leading(), setLeadingIncluded()
*/
qreal QTextLine::height() const
{
@@ -1529,24 +1598,25 @@ qreal QTextLine::height() const
Returns the line's leading.
- \sa ascent() descent() height()
+ \sa ascent(), descent(), height()
*/
qreal QTextLine::leading() const
{
return eng->lines[i].leading.toReal();
}
-/*! \since 4.6
+/*!
+ \since 4.6
- Includes positive leading into the line's height if \a included is true;
- otherwise does not include leading.
+ Includes positive leading into the line's height if \a included is true;
+ otherwise does not include leading.
- By default, leading is not included.
+ By default, leading is not included.
- Note that negative leading is ignored, it must be handled
- in the code using the text lines by letting the lines overlap.
+ Note that negative leading is ignored, it must be handled
+ in the code using the text lines by letting the lines overlap.
- \sa leadingIncluded()
+ \sa leadingIncluded()
*/
void QTextLine::setLeadingIncluded(bool included)
@@ -1555,20 +1625,21 @@ void QTextLine::setLeadingIncluded(bool included)
}
-/*! \since 4.6
+/*!
+ \since 4.6
- Returns true if positive leading is included into the line's height; otherwise returns false.
+ Returns true if positive leading is included into the line's height;
+ otherwise returns false.
- By default, leading is not included.
+ By default, leading is not included.
- \sa setLeadingIncluded()
+ \sa setLeadingIncluded()
*/
bool QTextLine::leadingIncluded() const
{
return eng->lines[i].leadingIncluded;
}
-
/*!
Returns the width of the line that is occupied by text. This is
always \<= to width(), and is the minimum width that could be used
@@ -1579,14 +1650,15 @@ qreal QTextLine::naturalTextWidth() const
return eng->lines[i].textWidth.toReal();
}
-/*! \since 4.7
- Returns the horizontal advance of the text. The advance of the text
- is the distance from its position to the next position at which
- text would naturally be drawn.
+/*!
+ \since 4.7
+ Returns the horizontal advance of the text. The advance of the text
+ is the distance from its position to the next position at which
+ text would naturally be drawn.
- By adding the advance to the position of the text line and using this
- as the position of a second text line, you will be able to position
- the two lines side-by-side without gaps in-between.
+ By adding the advance to the position of the text line and using this
+ as the position of a second text line, you will be able to position
+ the two lines side-by-side without gaps in-between.
*/
qreal QTextLine::horizontalAdvance() const
{
@@ -1764,7 +1836,8 @@ static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &gly
++line.length;
} while (pos < end && logClusters[pos] == glyphPosition);
do { // calculate the textWidth for the rest of the current cluster.
- line.textWidth += glyphs.advances_x[glyphPosition] * !glyphs.attributes[glyphPosition].dontPrint;
+ if (!glyphs.attributes[glyphPosition].dontPrint)
+ line.textWidth += glyphs.advances_x[glyphPosition];
++glyphPosition;
} while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart);
@@ -1842,14 +1915,14 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.currentPosition = qMax(line.from, current.position);
end = current.position + eng->length(item);
lbh.glyphs = eng->shapedGlyphs(&current);
+ QFontEngine *fontEngine = eng->fontEngine(current);
+ if (lbh.fontEngine != fontEngine) {
+ lbh.fontEngine = fontEngine;
+ lbh.minimumRightBearing = qMin(QFixed(),
+ QFixed::fromReal(fontEngine->minRightBearing()));
+ }
}
const QScriptItem &current = eng->layoutData->items[item];
- QFontEngine *fontEngine = eng->fontEngine(current);
- if (lbh.fontEngine != fontEngine) {
- lbh.fontEngine = fontEngine;
- lbh.minimumRightBearing = qMin(QFixed(),
- QFixed::fromReal(fontEngine->minRightBearing()));
- }
lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
@@ -2014,9 +2087,10 @@ found:
eng->maxWidth += lbh.spaceData.textWidth;
if (eng->option.flags() & QTextOption::IncludeTrailingSpaces)
line.textWidth += lbh.spaceData.textWidth;
- line.length += lbh.spaceData.length;
- if (lbh.spaceData.length)
+ if (lbh.spaceData.length) {
+ line.length += lbh.spaceData.length;
line.hasTrailingSpaces = true;
+ }
line.justified = false;
line.gridfitted = false;
@@ -2170,6 +2244,151 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
}
+namespace {
+ struct GlyphInfo
+ {
+ GlyphInfo(const QGlyphLayout &layout, const QPointF &position,
+ const QTextItemInt::RenderFlags &renderFlags)
+ : glyphLayout(layout), itemPosition(position), flags(renderFlags)
+ {
+ }
+
+ QGlyphLayout glyphLayout;
+ QPointF itemPosition;
+ QTextItem::RenderFlags flags;
+ };
+}
+
+/*!
+ \internal
+
+ Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in
+ QScriptItems that overlap with the range defined by \a from and \a length. The arguments
+ specify characters, relative to the text in the layout. Note that it is not possible to
+ use this function to retrieve a subset of the glyphs in a QScriptItem.
+
+ \since 4.8
+
+ \sa QTextLayout::glyphs()
+*/
+QList<QGlyphs> QTextLine::glyphs(int from, int length) const
+{
+ const QScriptLine &line = eng->lines[i];
+
+ if (line.length == 0)
+ return QList<QGlyphs>();
+
+ QHash<QFontEngine *, GlyphInfo> glyphLayoutHash;
+
+ QTextLineItemIterator iterator(eng, i);
+ qreal y = line.y.toReal() + line.base().toReal();
+ while (!iterator.atEnd()) {
+ QScriptItem &si = iterator.next();
+ if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
+ continue;
+
+ QPointF pos(iterator.x.toReal(), y);
+ if (from >= 0 && length >= 0 &&
+ (from >= si.position + eng->length(&si) || from + length <= si.position))
+ continue;
+
+ QFont font = eng->font(si);
+
+ QTextItem::RenderFlags flags;
+ if (font.overline())
+ flags |= QTextItem::Overline;
+ if (font.underline())
+ flags |= QTextItem::Underline;
+ if (font.strikeOut())
+ flags |= QTextItem::StrikeOut;
+ if (si.analysis.bidiLevel % 2)
+ flags |= QTextItem::RightToLeft;
+
+ QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart,
+ iterator.glyphsEnd - iterator.glyphsStart);
+
+ if (glyphLayout.numGlyphs > 0) {
+ QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
+ if (mainFontEngine->type() == QFontEngine::Multi) {
+ QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine);
+ int start = 0;
+ int end;
+ int which = glyphLayout.glyphs[0] >> 24;
+ for (end = 0; end < glyphLayout.numGlyphs; ++end) {
+ const int e = glyphLayout.glyphs[end] >> 24;
+ if (e == which)
+ continue;
+
+ QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
+ glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
+ GlyphInfo(subLayout, pos, flags));
+
+ start = end;
+ which = e;
+ }
+
+ QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
+ glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
+ GlyphInfo(subLayout, pos, flags));
+
+ } else {
+ glyphLayoutHash.insertMulti(mainFontEngine,
+ GlyphInfo(glyphLayout, pos, flags));
+ }
+ }
+ }
+
+ QHash<QPair<QFontEngine *, int>, QGlyphs> glyphsHash;
+
+ QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys();
+ for (int i=0; i<keys.size(); ++i) {
+ QFontEngine *fontEngine = keys.at(i);
+
+ // Make a font for this particular engine
+ QFont font = fontEngine->createExplicitFont();
+
+ QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine);
+ for (int j=0; j<glyphLayouts.size(); ++j) {
+ const QPointF &pos = glyphLayouts.at(j).itemPosition;
+ const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout;
+ const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags;
+
+ font.setOverline(flags.testFlag(QTextItem::Overline));
+ font.setUnderline(flags.testFlag(QTextItem::Underline));
+ font.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
+
+ QVarLengthArray<glyph_t> glyphsArray;
+ QVarLengthArray<QFixedPoint> positionsArray;
+
+ fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray,
+ positionsArray);
+ Q_ASSERT(glyphsArray.size() == positionsArray.size());
+
+ QVector<quint32> glyphs;
+ QVector<QPointF> positions;
+ for (int i=0; i<glyphsArray.size(); ++i) {
+ glyphs.append(glyphsArray.at(i) & 0xffffff);
+ positions.append(positionsArray.at(i).toPointF() + pos);
+ }
+
+ QGlyphs glyphIndexes;
+ glyphIndexes.setGlyphIndexes(glyphs);
+ glyphIndexes.setPositions(positions);
+
+ QPair<QFontEngine *, int> key(fontEngine, int(flags));
+
+ if (!glyphsHash.contains(key))
+ glyphsHash.insert(key, QGlyphs());
+
+ QGlyphs &target = glyphsHash[key];
+ target += glyphIndexes;
+ target.setFont(font);
+ }
+ }
+
+ return glyphsHash.values();
+}
+
/*!
\fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const
@@ -2219,8 +2438,12 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
QTextCharFormat format;
if (eng->hasFormats() || selection) {
- if (!suppressColors)
- format = eng->format(&si);
+ format = eng->format(&si);
+ if (suppressColors) {
+ format.clearForeground();
+ format.clearBackground();
+ format.clearProperty(QTextFormat::TextUnderlineColor);
+ }
if (selection)
format.merge(selection->format);
@@ -2366,21 +2589,20 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
}
/*!
- \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const
+ \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const
- \overload
+ \overload
*/
-
/*!
- Converts the cursor position \a cursorPos to the corresponding x position
- inside the line, taking account of the \a edge.
+ Converts the cursor position \a cursorPos to the corresponding x position
+ inside the line, taking account of the \a edge.
- If \a cursorPos is not a valid cursor position, the nearest valid
- cursor position will be used instead, and cpos will be modified to
- point to this valid cursor position.
+ If \a cursorPos is not a valid cursor position, the nearest valid
+ cursor position will be used instead, and cpos will be modified to
+ point to this valid cursor position.
- \sa xToCursor()
+ \sa xToCursor()
*/
qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
{
@@ -2479,14 +2701,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
if(pos == l)
x += si->width;
} else {
- int offsetInCluster = 0;
- for (int i=pos-1; i >= 0; i--) {
- if (logClusters[i] == glyph_pos)
- offsetInCluster++;
- else
- break;
- }
-
if (reverse) {
int end = qMin(lineEnd, si->position + l) - si->position;
int glyph_end = end == l ? si->num_glyphs : logClusters[end];
@@ -2498,17 +2712,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
for (int i = glyph_start; i < glyph_pos; i++)
x += glyphs.effectiveAdvance(i);
}
- if (offsetInCluster > 0) { // in the case that the offset is inside a (multi-character) glyph, interpolate the position.
- int clusterLength = 0;
- for (int i=pos - offsetInCluster; i < line.length; i++) {
- if (logClusters[i] == glyph_pos)
- clusterLength++;
- else
- break;
- }
- if (clusterLength)
- x+= glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength;
- }
+ x += offsetInLigature(logClusters, glyphs, pos, line.length, glyph_pos);
}
*cursorPos = pos + si->position;
@@ -2516,12 +2720,12 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
}
/*!
- \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const
+ \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const
- Converts the x-coordinate \a x, to the nearest matching cursor
- position, depending on the cursor position type, \a cpos.
+ Converts the x-coordinate \a x, to the nearest matching cursor
+ position, depending on the cursor position type, \a cpos.
- \sa cursorToX()
+ \sa cursorToX()
*/
int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
{
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 44451ecbd2..0f64c338d5 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -49,6 +49,7 @@
#include <QtCore/qobject.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
+#include <QtGui/qglyphs.h>
QT_BEGIN_HEADER
@@ -166,6 +167,8 @@ public:
qreal minimumWidth() const;
qreal maximumWidth() const;
+ QList<QGlyphs> glyphs() const;
+
QTextEngine *engine() const { return d; }
void setFlags(int flags);
private:
@@ -236,7 +239,10 @@ public:
private:
QTextLine(int line, QTextEngine *e) : i(line), eng(e) {}
void layout_helper(int numGlyphs);
+ QList<QGlyphs> glyphs(int from, int length) const;
+
friend class QTextLayout;
+ friend class QTextFragment;
int i;
QTextEngine *eng;
};
diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp
index 3528d932ed..21935aa915 100644
--- a/src/gui/text/qtextlist.cpp
+++ b/src/gui/text/qtextlist.cpp
@@ -191,6 +191,13 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
QString result;
const int style = format().style();
+ QString numberPrefix;
+ QString numberSuffix = QLatin1String(".");
+
+ if (format().hasProperty(QTextFormat::ListNumberPrefix))
+ numberPrefix = format().numberPrefix();
+ if (format().hasProperty(QTextFormat::ListNumberSuffix))
+ numberSuffix = format().numberSuffix();
switch (style) {
case QTextListFormat::ListDecimal:
@@ -232,7 +239,7 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
if (q > 0) {
int startDigit = i + (i+3)/4;
int numDigits;
- if (i % 4) {
+ if (i % 4) {
// c[i] == 4|5|9|40|50|90|400|500|900
if ((i-2) % 4) {
// c[i] == 4|9|40|90|400|900 => with subtraction (IV, IX, XL, XC, ...)
@@ -263,8 +270,9 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
Q_ASSERT(false);
}
if (blockIt.textDirection() == Qt::RightToLeft)
- return result.prepend(QLatin1Char('.'));
- return result + QLatin1Char('.');
+ return numberSuffix + result + numberPrefix;
+ else
+ return numberPrefix + result + numberSuffix;
}
/*!
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index e323fd0f64..c5b6e14a74 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1655,6 +1655,35 @@ QTextBlock::iterator &QTextBlock::iterator::operator--()
than the \a other text fragment; otherwise returns false.
*/
+/*!
+ Returns the glyphs of this text fragment. The positions of the glyphs are
+ relative to the position of the QTextBlock's layout.
+
+ \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs()
+*/
+QList<QGlyphs> QTextFragment::glyphs() const
+{
+ if (!p || !n)
+ return QList<QGlyphs>();
+
+ int pos = position();
+ int len = length();
+ if (len == 0)
+ return QList<QGlyphs>();
+
+ int blockNode = p->blockMap().findNode(pos);
+
+ const QTextBlockData *blockData = p->blockMap().fragment(blockNode);
+ QTextLayout *layout = blockData->layout;
+
+ QList<QGlyphs> ret;
+ for (int i=0; i<layout->lineCount(); ++i) {
+ QTextLine textLine = layout->lineAt(i);
+ ret += textLine.glyphs(pos, len);
+ }
+
+ return ret;
+}
/*!
Returns the position of this text fragment in the document.
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index d5c1e8df79..fface3ffea 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -44,6 +44,7 @@
#include <QtCore/qobject.h>
#include <QtGui/qtextformat.h>
+#include <QtGui/qglyphs.h>
QT_BEGIN_HEADER
@@ -315,6 +316,8 @@ public:
int charFormatIndex() const;
QString text() const;
+ QList<QGlyphs> glyphs() const;
+
private:
const QTextDocumentPrivate *p;
int n;
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 0c9655b6fd..c2e47f3df6 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -636,7 +636,15 @@ void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat f
|| style == QTextListFormat::ListUpperRoman) {
writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number"));
writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style));
- writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1("."));
+
+ if (format.hasProperty(QTextFormat::ListNumberSuffix))
+ writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), format.numberSuffix());
+ else
+ writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1("."));
+
+ if (format.hasProperty(QTextFormat::ListNumberPrefix))
+ writer.writeAttribute(styleNS, QString::fromLatin1("num-prefix"), format.numberPrefix());
+
} else {
writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-bullet"));
writer.writeAttribute(textNS, QString::fromLatin1("bullet-char"), bulletChar(style));
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index af8daa5d99..daafdd9db4 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -25,7 +25,7 @@ HEADERS += \
text/qabstracttextdocumentlayout.h \
text/qtextdocumentlayout_p.h \
text/qtextcursor.h \
- text/qtextcursor_p.h \
+ text/qtextcursor_p.h \
text/qtextdocumentfragment.h \
text/qtextdocumentfragment_p.h \
text/qtextimagehandler_p.h \
@@ -39,7 +39,9 @@ HEADERS += \
text/qzipwriter_p.h \
text/qtextodfwriter_p.h \
text/qstatictext_p.h \
- text/qstatictext.h
+ text/qstatictext.h \
+ text/qglyphs.h \
+ text/qglyphs_p.h
SOURCES += \
text/qfont.cpp \
@@ -69,7 +71,8 @@ SOURCES += \
text/qcssparser.cpp \
text/qzip.cpp \
text/qtextodfwriter.cpp \
- text/qstatictext.cpp
+ text/qstatictext.cpp \
+ text/qglyphs.cpp
win32 {
SOURCES += \
@@ -89,10 +92,16 @@ unix:x11 {
text/qfontengine_ft.cpp
}
-!embedded:!x11:mac {
+!embedded:!qpa:!x11:mac {
+ HEADERS += \
+ text/qfontengine_mac_p.h
+ OBJECTIVE_HEADERS += \
+ text/qfontengine_coretext_p.h
SOURCES += \
- text/qfont_mac.cpp
- OBJECTIVE_SOURCES += text/qfontengine_mac.mm
+ text/qfont_mac.cpp
+ OBJECTIVE_SOURCES += \
+ text/qfontengine_coretext.mm \
+ text/qfontengine_mac.mm
}
embedded {
@@ -110,6 +119,19 @@ embedded {
DEFINES += QT_NO_FONTCONFIG
}
+qpa {
+ SOURCES += \
+ text/qfont_qpa.cpp \
+ text/qfontengine_qpa.cpp \
+ text/qplatformfontdatabase_qpa.cpp
+
+ HEADERS += \
+ text/qplatformfontdatabase_qpa.h
+
+ DEFINES += QT_NO_FONTCONFIG
+ DEFINES += QT_NO_FREETYPE
+}
+
symbian {
SOURCES += \
text/qfont_s60.cpp
@@ -129,6 +151,7 @@ symbian {
}
}
+!qpa {
contains(QT_CONFIG, freetype) {
SOURCES += \
../3rdparty/freetype/src/base/ftbase.c \
@@ -202,6 +225,7 @@ contains(QT_CONFIG, freetype) {
contains(QT_CONFIG, fontconfig) {
CONFIG += opentype
}
+}#!qpa
DEFINES += QT_NO_OPENTYPE
INCLUDEPATH += ../3rdparty/harfbuzz/src
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index 12f4acfe5b..27684bf91e 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -220,7 +220,7 @@ QModelIndex QCompletionModel::mapToSource(const QModelIndex& index) const
{
Q_D(const QCompletionModel);
if (!index.isValid())
- return QModelIndex();
+ return engine->curParent;
int row;
QModelIndex parent = engine->curParent;
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 514246ede8..cb5a3ef560 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -45,7 +45,7 @@
#include <qdebug.h>
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_WS_QPA)
#include "qdesktopservices_qws.cpp"
#elif defined(Q_WS_X11)
#include "qdesktopservices_x11.cpp"
diff --git a/src/gui/util/qdesktopservices_mac.cpp b/src/gui/util/qdesktopservices_mac.cpp
index de715760db..e9868471cb 100644
--- a/src/gui/util/qdesktopservices_mac.cpp
+++ b/src/gui/util/qdesktopservices_mac.cpp
@@ -49,6 +49,8 @@
#include <private/qcore_mac_p.h>
#include <qcoreapplication.h>
+#include <ApplicationServices/ApplicationServices.h>
+
QT_BEGIN_NAMESPACE
/*
diff --git a/src/gui/util/qflickgesture.cpp b/src/gui/util/qflickgesture.cpp
new file mode 100644
index 0000000000..eb0cc8dd13
--- /dev/null
+++ b/src/gui/util/qflickgesture.cpp
@@ -0,0 +1,677 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesture.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qwidget.h"
+#include "qgraphicsitem.h"
+#include "qgraphicsscene.h"
+#include "qgraphicssceneevent.h"
+#include "qgraphicsview.h"
+#include "qscroller.h"
+#include "private/qevent_p.h"
+#include "private/qflickgesture_p.h"
+#include "qdebug.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+//#define QFLICKGESTURE_DEBUG
+
+#ifdef QFLICKGESTURE_DEBUG
+# define qFGDebug qDebug
+#else
+# define qFGDebug while (false) qDebug
+#endif
+
+extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
+static QMouseEvent *copyMouseEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove: {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ return new QMouseEvent(me->type(), QPoint(0, 0), me->globalPos(), me->button(), me->buttons(), me->modifiers());
+ }
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseMove: {
+ QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(e);
+#if 1
+ QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress :
+ (me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove);
+ return new QMouseEvent(met, QPoint(0, 0), me->screenPos(), me->button(), me->buttons(), me->modifiers());
+#else
+ QGraphicsSceneMouseEvent *copy = new QGraphicsSceneMouseEvent(me->type());
+ copy->setPos(me->pos());
+ copy->setScenePos(me->scenePos());
+ copy->setScreenPos(me->screenPos());
+ for (int i = 0x1; i <= 0x10; i <<= 1) {
+ Qt::MouseButton button = Qt::MouseButton(i);
+ copy->setButtonDownPos(button, me->buttonDownPos(button));
+ copy->setButtonDownScenePos(button, me->buttonDownScenePos(button));
+ copy->setButtonDownScreenPos(button, me->buttonDownScreenPos(button));
+ }
+ copy->setLastPos(me->lastPos());
+ copy->setLastScenePos(me->lastScenePos());
+ copy->setLastScreenPos(me->lastScreenPos());
+ copy->setButtons(me->buttons());
+ copy->setButton(me->button());
+ copy->setModifiers(me->modifiers());
+ return copy;
+#endif
+ }
+ default:
+ return 0;
+ }
+}
+
+class PressDelayHandler : public QObject
+{
+private:
+ PressDelayHandler(QObject *parent = 0)
+ : QObject(parent)
+ , pressDelayTimer(0)
+ , sendingEvent(false)
+ , mouseButton(Qt::NoButton)
+ , mouseTarget(0)
+ { }
+
+ static PressDelayHandler *inst;
+
+public:
+ enum {
+ UngrabMouseBefore = 1,
+ RegrabMouseAfterwards = 2
+ };
+
+ static PressDelayHandler *instance()
+ {
+ static PressDelayHandler *inst = 0;
+ if (!inst)
+ inst = new PressDelayHandler(QCoreApplication::instance());
+ return inst;
+ }
+
+ bool shouldEventBeIgnored(QEvent *) const
+ {
+ return sendingEvent;
+ }
+
+ bool isDelaying() const
+ {
+ return !pressDelayEvent.isNull();
+ }
+
+ void pressed(QEvent *e, int delay)
+ {
+ if (!pressDelayEvent) {
+ pressDelayEvent.reset(copyMouseEvent(e));
+ pressDelayTimer = startTimer(delay);
+ mouseTarget = QApplication::widgetAt(pressDelayEvent->globalPos());
+ mouseButton = pressDelayEvent->button();
+ qFGDebug() << "QFG: consuming/delaying mouse press";
+ } else {
+ qFGDebug() << "QFG: NOT consuming/delaying mouse press";
+ }
+ e->setAccepted(true);
+ }
+
+ bool released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive)
+ {
+ // consume this event if the scroller was or is active
+ bool result = scrollerWasActive || scrollerIsActive;
+
+ // stop the timer
+ if (pressDelayTimer) {
+ killTimer(pressDelayTimer);
+ pressDelayTimer = 0;
+ }
+ // we still haven't even sent the press, so do it now
+ if (pressDelayEvent && mouseTarget && !scrollerIsActive) {
+ QScopedPointer<QMouseEvent> releaseEvent(copyMouseEvent(e));
+
+ qFGDebug() << "QFG: re-sending mouse press (due to release) for " << mouseTarget;
+ sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore);
+
+ qFGDebug() << "QFG: faking mouse release (due to release) for " << mouseTarget;
+ sendMouseEvent(releaseEvent.data());
+
+ result = true; // consume this event
+ } else if (mouseTarget && scrollerIsActive) {
+ // we grabbed the mouse expicitly when the scroller became active, so undo that now
+ sendMouseEvent(0, UngrabMouseBefore);
+ }
+ pressDelayEvent.reset(0);
+ mouseTarget = 0;
+ return result;
+ }
+
+ void scrollerWasIntercepted()
+ {
+ qFGDebug() << "QFG: deleting delayed mouse press, since scroller was only intercepted";
+ if (pressDelayEvent) {
+ // we still haven't even sent the press, so just throw it away now
+ if (pressDelayTimer) {
+ killTimer(pressDelayTimer);
+ pressDelayTimer = 0;
+ }
+ pressDelayEvent.reset(0);
+ }
+ mouseTarget = 0;
+ }
+
+ void scrollerBecameActive()
+ {
+ if (pressDelayEvent) {
+ // we still haven't even sent the press, so just throw it away now
+ qFGDebug() << "QFG: deleting delayed mouse press, since scroller is active now";
+ if (pressDelayTimer) {
+ killTimer(pressDelayTimer);
+ pressDelayTimer = 0;
+ }
+ pressDelayEvent.reset(0);
+ mouseTarget = 0;
+ } else if (mouseTarget) {
+ // we did send a press, so we need to fake a release now
+ Qt::MouseButtons mouseButtons = QApplication::mouseButtons();
+
+ // release all pressed mouse buttons
+ /*for (int i = 0; i < 32; ++i) {
+ if (mouseButtons & (1 << i)) {
+ Qt::MouseButton b = static_cast<Qt::MouseButton>(1 << i);
+ mouseButtons &= ~b;
+ QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
+
+ qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
+ QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway,
+ b, mouseButtons, QApplication::keyboardModifiers());
+ sendMouseEvent(&re);
+ }
+ }*/
+
+ QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
+
+ qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
+ QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway,
+ mouseButton, QApplication::mouseButtons() & ~mouseButton,
+ QApplication::keyboardModifiers());
+ sendMouseEvent(&re, RegrabMouseAfterwards);
+ // don't clear the mouseTarget just yet, since we need to explicitly ungrab the mouse on release!
+ }
+ }
+
+protected:
+ void timerEvent(QTimerEvent *e)
+ {
+ if (e->timerId() == pressDelayTimer) {
+ if (pressDelayEvent && mouseTarget) {
+ qFGDebug() << "QFG: timer event: re-sending mouse press to " << mouseTarget;
+ sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore);
+ }
+ pressDelayEvent.reset(0);
+
+ if (pressDelayTimer) {
+ killTimer(pressDelayTimer);
+ pressDelayTimer = 0;
+ }
+ }
+ }
+
+ void sendMouseEvent(QMouseEvent *me, int flags = 0)
+ {
+ if (mouseTarget) {
+ sendingEvent = true;
+
+ QGraphicsItem *grabber = 0;
+ if (mouseTarget->parentWidget()) {
+ if (QGraphicsView *gv = qobject_cast<QGraphicsView *>(mouseTarget->parentWidget())) {
+ if (gv->scene())
+ grabber = gv->scene()->mouseGrabberItem();
+ }
+ }
+
+ if (grabber && (flags & UngrabMouseBefore)) {
+ // GraphicsView Mouse Handling Workaround #1:
+ // we need to ungrab the mouse before re-sending the press,
+ // since the scene had already set the mouse grabber to the
+ // original (and consumed) event's receiver
+ qFGDebug() << "QFG: ungrabbing" << grabber;
+ grabber->ungrabMouse();
+ }
+
+ if (me) {
+ QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()), me->globalPos(), me->button(), me->buttons(), me->modifiers());
+ qt_sendSpontaneousEvent(mouseTarget, &copy);
+ }
+
+ if (grabber && (flags & RegrabMouseAfterwards)) {
+ // GraphicsView Mouse Handling Workaround #2:
+ // we need to re-grab the mouse after sending a faked mouse
+ // release, since we still need the mouse moves for the gesture
+ // (the scene will clear the item's mouse grabber status on
+ // release).
+ qFGDebug() << "QFG: re-grabbing" << grabber;
+ grabber->grabMouse();
+ }
+ sendingEvent = false;
+ }
+ }
+
+
+private:
+ int pressDelayTimer;
+ QScopedPointer<QMouseEvent> pressDelayEvent;
+ bool sendingEvent;
+ Qt::MouseButton mouseButton;
+ QPointer<QWidget> mouseTarget;
+};
+
+
+/*!
+ \internal
+ \class QFlickGesture
+ \since 4.8
+ \brief The QFlickGesture class describes a flicking gesture made by the user.
+ \ingroup gestures
+ The QFlickGesture is more complex than the QPanGesture that uses QScroller and QScrollerProperties
+ to decide if it is triggered.
+ This gesture is reacting on touch event as compared to the QMouseFlickGesture.
+
+ \sa {Gestures Programming}, QScroller, QScrollerProperties, QMouseFlickGesture
+*/
+
+/*!
+ \internal
+*/
+QFlickGesture::QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent)
+ : QGesture(*new QFlickGesturePrivate, parent)
+{
+ d_func()->q_ptr = this;
+ d_func()->receiver = receiver;
+ d_func()->receiverScroller = (receiver && QScroller::hasScroller(receiver)) ? QScroller::scroller(receiver) : 0;
+ d_func()->button = button;
+}
+
+QFlickGesture::~QFlickGesture()
+{ }
+
+QFlickGesturePrivate::QFlickGesturePrivate()
+ : receiverScroller(0), button(Qt::NoButton), macIgnoreWheel(false)
+{ }
+
+
+//
+// QFlickGestureRecognizer
+//
+
+
+QFlickGestureRecognizer::QFlickGestureRecognizer(Qt::MouseButton button)
+{
+ this->button = button;
+}
+
+/*! \reimp
+ */
+QGesture *QFlickGestureRecognizer::create(QObject *target)
+{
+ QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target);
+ if (go && button == Qt::NoButton) {
+ go->setAcceptTouchEvents(true);
+ }
+ return new QFlickGesture(target, button);
+}
+
+/*! \internal
+ The recognize function detects a touch event suitable to start the attached QScroller.
+ The QFlickGesture will be triggered as soon as the scroller is no longer in the state
+ QScroller::Inactive or QScroller::Pressed. It will be finished or canceled
+ at the next QEvent::TouchEnd.
+ Note that the QScroller might continue scrolling (kinetically) at this point.
+ */
+QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
+ QObject *watched,
+ QEvent *event)
+{
+ Q_UNUSED(watched);
+
+ static QElapsedTimer monotonicTimer;
+ if (!monotonicTimer.isValid())
+ monotonicTimer.start();
+
+ QFlickGesture *q = static_cast<QFlickGesture *>(state);
+ QFlickGesturePrivate *d = q->d_func();
+
+ QScroller *scroller = d->receiverScroller;
+ if (!scroller)
+ return Ignore; // nothing to do without a scroller?
+
+ QWidget *receiverWidget = qobject_cast<QWidget *>(d->receiver);
+ QGraphicsObject *receiverGraphicsObject = qobject_cast<QGraphicsObject *>(d->receiver);
+
+ // this is only set for events that we inject into the event loop via sendEvent()
+ if (PressDelayHandler::instance()->shouldEventBeIgnored(event)) {
+ //qFGDebug() << state << "QFG: ignored event: " << event->type();
+ return Ignore;
+ }
+
+ const QMouseEvent *me = 0;
+ const QGraphicsSceneMouseEvent *gsme = 0;
+ const QTouchEvent *te = 0;
+ QPoint globalPos;
+
+ // qFGDebug() << "FlickGesture "<<state<<"watched:"<<watched<<"receiver"<<d->receiver<<"event"<<event->type()<<"button"<<button;
+
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ if (!receiverWidget)
+ return Ignore;
+ if (button != Qt::NoButton) {
+ me = static_cast<const QMouseEvent *>(event);
+ globalPos = me->globalPos();
+ }
+ break;
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseMove:
+ if (!receiverGraphicsObject)
+ return Ignore;
+ if (button != Qt::NoButton) {
+ gsme = static_cast<const QGraphicsSceneMouseEvent *>(event);
+ globalPos = gsme->screenPos();
+ }
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchEnd:
+ case QEvent::TouchUpdate:
+ if (button == Qt::NoButton) {
+ te = static_cast<const QTouchEvent *>(event);
+ if (!te->touchPoints().isEmpty())
+ globalPos = te->touchPoints().at(0).screenPos().toPoint();
+ }
+ break;
+
+#if defined(Q_WS_MAC)
+ // the only way to distinguish between real mouse wheels and wheel
+ // events generated by the native 2 finger swipe gesture is to listen
+ // for these events (according to Apple's Cocoa Event-Handling Guide)
+
+ case QEvent::NativeGesture: {
+ QNativeGestureEvent *nge = static_cast<QNativeGestureEvent *>(event);
+ if (nge->gestureType == QNativeGestureEvent::GestureBegin)
+ d->macIgnoreWheel = true;
+ else if (nge->gestureType == QNativeGestureEvent::GestureEnd)
+ d->macIgnoreWheel = false;
+ break;
+ }
+#endif
+
+ // consume all wheel events if the scroller is active
+ case QEvent::Wheel:
+ if (d->macIgnoreWheel || (scroller->state() != QScroller::Inactive))
+ return Ignore | ConsumeEventHint;
+ break;
+
+ // consume all dbl click events if the scroller is active
+ case QEvent::MouseButtonDblClick:
+ if (scroller->state() != QScroller::Inactive)
+ return Ignore | ConsumeEventHint;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!me && !gsme && !te) // Neither mouse nor touch
+ return Ignore;
+
+ // get the current pointer position in local coordinates.
+ QPointF point;
+ QScroller::Input inputType = (QScroller::Input) 0;
+
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ if (me && me->button() == button && me->buttons() == button) {
+ point = me->globalPos();
+ inputType = QScroller::InputPress;
+ } else if (me) {
+ scroller->stop();
+ return CancelGesture;
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if (me && me->button() == button) {
+ point = me->globalPos();
+ inputType = QScroller::InputRelease;
+ }
+ break;
+ case QEvent::MouseMove:
+#ifdef Q_OS_SYMBIAN
+ // Qt on Symbian tracks the button state internally, while Qt on Win/Mac/Unix
+ // relies on the windowing system to report the current buttons state.
+ if (me && (me->buttons() == button || !me->buttons())) {
+#else
+ if (me && me->buttons() == button) {
+#endif
+ point = me->globalPos();
+ inputType = QScroller::InputMove;
+ }
+ break;
+
+ case QEvent::GraphicsSceneMousePress:
+ if (gsme && gsme->button() == button && gsme->buttons() == button) {
+ point = gsme->scenePos();
+ inputType = QScroller::InputPress;
+ } else if (gsme) {
+ scroller->stop();
+ return CancelGesture;
+ }
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ if (gsme && gsme->button() == button) {
+ point = gsme->scenePos();
+ inputType = QScroller::InputRelease;
+ }
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+#ifdef Q_OS_SYMBIAN
+ // Qt on Symbian tracks the button state internally, while Qt on Win/Mac/Unix
+ // relies on the windowing system to report the current buttons state.
+ if (gsme && (gsme->buttons() == button || !me->buttons())) {
+#else
+ if (gsme && gsme->buttons() == button) {
+#endif
+ point = gsme->scenePos();
+ inputType = QScroller::InputMove;
+ }
+ break;
+
+ case QEvent::TouchBegin:
+ inputType = QScroller::InputPress;
+ // fall through
+ case QEvent::TouchEnd:
+ if (!inputType)
+ inputType = QScroller::InputRelease;
+ // fallthrough
+ case QEvent::TouchUpdate:
+ if (!inputType)
+ inputType = QScroller::InputMove;
+
+ if (te->deviceType() == QTouchEvent::TouchPad) {
+ if (te->touchPoints().count() != 2) // 2 fingers on pad
+ return Ignore;
+
+ point = te->touchPoints().at(0).startScenePos() +
+ ((te->touchPoints().at(0).scenePos() - te->touchPoints().at(0).startScenePos()) +
+ (te->touchPoints().at(1).scenePos() - te->touchPoints().at(1).startScenePos())) / 2;
+ } else { // TouchScreen
+ if (te->touchPoints().count() != 1) // 1 finger on screen
+ return Ignore;
+
+ point = te->touchPoints().at(0).scenePos();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // Check for an active scroller at globalPos
+ if (inputType == QScroller::InputPress) {
+ foreach (QScroller *as, QScroller::activeScrollers()) {
+ if (as != scroller) {
+ QRegion scrollerRegion;
+
+ if (QWidget *w = qobject_cast<QWidget *>(as->target())) {
+ scrollerRegion = QRect(w->mapToGlobal(QPoint(0, 0)), w->size());
+ } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(as->target())) {
+ if (go->scene() && !go->scene()->views().isEmpty()) {
+ foreach (QGraphicsView *gv, go->scene()->views())
+ scrollerRegion |= gv->mapFromScene(go->mapToScene(go->boundingRect()))
+ .translated(gv->mapToGlobal(QPoint(0, 0)));
+ }
+ }
+ // active scrollers always have priority
+ if (scrollerRegion.contains(globalPos))
+ return Ignore;
+ }
+ }
+ }
+
+ bool scrollerWasDragging = (scroller->state() == QScroller::Dragging);
+ bool scrollerWasScrolling = (scroller->state() == QScroller::Scrolling);
+
+ if (inputType) {
+ if (QWidget *w = qobject_cast<QWidget *>(d->receiver))
+ point = w->mapFromGlobal(point.toPoint());
+ else if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(d->receiver))
+ point = go->mapFromScene(point);
+
+ // inform the scroller about the new event
+ scroller->handleInput(inputType, point, monotonicTimer.elapsed());
+ }
+
+ // depending on the scroller state return the gesture state
+ Result result(0);
+ bool scrollerIsActive = (scroller->state() == QScroller::Dragging ||
+ scroller->state() == QScroller::Scrolling);
+
+ // Consume all mouse events while dragging or scrolling to avoid nasty
+ // side effects with Qt's standard widgets.
+ if ((me || gsme) && scrollerIsActive)
+ result |= ConsumeEventHint;
+
+ // The only problem with this approach is that we consume the
+ // MouseRelease when we start the scrolling with a flick gesture, so we
+ // have to fake a MouseRelease "somewhere" to not mess with the internal
+ // states of Qt's widgets (a QPushButton would stay in 'pressed' state
+ // forever, if it doesn't receive a MouseRelease).
+ if (me || gsme) {
+ if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive)
+ PressDelayHandler::instance()->scrollerBecameActive();
+ else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive))
+ PressDelayHandler::instance()->scrollerWasIntercepted();
+ }
+
+ if (!inputType) {
+ result |= Ignore;
+ } else {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::GraphicsSceneMousePress:
+ if (scroller->state() == QScroller::Pressed) {
+ int pressDelay = int(1000 * scroller->scrollerProperties().scrollMetric(QScrollerProperties::MousePressEventDelay).toReal());
+ if (pressDelay > 0) {
+ result |= ConsumeEventHint;
+
+ PressDelayHandler::instance()->pressed(event, pressDelay);
+ event->accept();
+ }
+ }
+ // fall through
+ case QEvent::TouchBegin:
+ q->setHotSpot(globalPos);
+ result |= scrollerIsActive ? TriggerGesture : MayBeGesture;
+ break;
+
+ case QEvent::MouseMove:
+ case QEvent::GraphicsSceneMouseMove:
+ if (PressDelayHandler::instance()->isDelaying())
+ result |= ConsumeEventHint;
+ // fall through
+ case QEvent::TouchUpdate:
+ result |= scrollerIsActive ? TriggerGesture : Ignore;
+ break;
+
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::MouseButtonRelease:
+ if (PressDelayHandler::instance()->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
+ result |= ConsumeEventHint;
+ // fall through
+ case QEvent::TouchEnd:
+ result |= scrollerIsActive ? FinishGesture : CancelGesture;
+ break;
+
+ default:
+ result |= Ignore;
+ break;
+ }
+ }
+ return result;
+}
+
+
+/*! \reimp
+ */
+void QFlickGestureRecognizer::reset(QGesture *state)
+{
+ QGestureRecognizer::reset(state);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
diff --git a/src/gui/util/qflickgesture_p.h b/src/gui/util/qflickgesture_p.h
new file mode 100644
index 0000000000..c3c263bacd
--- /dev/null
+++ b/src/gui/util/qflickgesture_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFLICKGESTURE_P_H
+#define QFLICKGESTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qevent.h"
+#include "qgesturerecognizer.h"
+#include "private/qgesture_p.h"
+#include "qscroller.h"
+#include "qscopedpointer.h"
+
+#ifndef QT_NO_GESTURES
+
+QT_BEGIN_NAMESPACE
+
+class QFlickGesturePrivate;
+class QGraphicsItem;
+
+class Q_GUI_EXPORT QFlickGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFlickGesture)
+
+public:
+ QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = 0);
+ ~QFlickGesture();
+
+ friend class QFlickGestureRecognizer;
+};
+
+class PressDelayHandler;
+
+class QFlickGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QFlickGesture)
+public:
+ QFlickGesturePrivate();
+
+ QPointer<QObject> receiver;
+ QScroller *receiverScroller;
+ Qt::MouseButton button; // NoButton == Touch
+ bool macIgnoreWheel;
+ static PressDelayHandler *pressDelayHandler;
+};
+
+class QFlickGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QFlickGestureRecognizer(Qt::MouseButton button);
+
+ QGesture *create(QObject *target);
+ QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+
+private:
+ Qt::MouseButton button; // NoButton == Touch
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_GESTURES
+
+#endif // QFLICKGESTURE_P_H
diff --git a/src/gui/util/qscroller.cpp b/src/gui/util/qscroller.cpp
new file mode 100644
index 0000000000..2ca4a6e4b8
--- /dev/null
+++ b/src/gui/util/qscroller.cpp
@@ -0,0 +1,1999 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevent.h"
+#include "qwidget.h"
+#include "qscroller.h"
+#include "private/qflickgesture_p.h"
+#include "private/qscroller_p.h"
+#include "qscrollerproperties.h"
+#include "private/qscrollerproperties_p.h"
+#include "qnumeric.h"
+#include "math.h"
+
+#include <QTime>
+#include <QElapsedTimer>
+#include <QMap>
+#include <QApplication>
+#include <QAbstractScrollArea>
+#include <QGraphicsObject>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QDesktopWidget>
+#include <QtCore/qmath.h>
+#include <QtGui/qevent.h>
+#include <qnumeric.h>
+
+#include <QtDebug>
+
+#if defined(Q_WS_X11)
+# include "private/qt_x11_p.h"
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
+//#define QSCROLLER_DEBUG
+
+#ifdef QSCROLLER_DEBUG
+# define qScrollerDebug qDebug
+#else
+# define qScrollerDebug while (false) qDebug
+#endif
+
+QDebug &operator<<(QDebug &dbg, const QScrollerPrivate::ScrollSegment &s)
+{
+ dbg << "\n Time: start:" << s.startTime << " duration:" << s.deltaTime;
+ dbg << "\n Pos: start:" << s.startPos << " delta:" << s.deltaPos;
+ dbg << "\n Curve: type:" << s.curve.type() << " max progress:" << s.maxProgress << "\n";
+ return dbg;
+}
+
+
+// a few helper operators to make the code below a lot more readable:
+// otherwise a lot of ifs would have to be multi-line to check both the x
+// and y coordinate separately.
+
+// returns true only if the abs. value of BOTH x and y are <= f
+inline bool operator<=(const QPointF &p, qreal f)
+{
+ return (qAbs(p.x()) <= f) && (qAbs(p.y()) <= f);
+}
+
+// returns true only if the abs. value of BOTH x and y are < f
+inline bool operator<(const QPointF &p, qreal f)
+{
+ return (qAbs(p.x()) < f) && (qAbs(p.y()) < f);
+}
+
+// returns true if the abs. value of EITHER x or y are >= f
+inline bool operator>=(const QPointF &p, qreal f)
+{
+ return (qAbs(p.x()) >= f) || (qAbs(p.y()) >= f);
+}
+
+// returns true if the abs. value of EITHER x or y are > f
+inline bool operator>(const QPointF &p, qreal f)
+{
+ return (qAbs(p.x()) > f) || (qAbs(p.y()) > f);
+}
+
+// returns a new point with both coordinates having the abs. value of the original one
+inline QPointF qAbs(const QPointF &p)
+{
+ return QPointF(qAbs(p.x()), qAbs(p.y()));
+}
+
+// returns a new point with all components of p1 multiplied by the corresponding components of p2
+inline QPointF operator*(const QPointF &p1, const QPointF &p2)
+{
+ return QPointF(p1.x() * p2.x(), p1.y() * p2.y());
+}
+
+// returns a new point with all components of p1 divided by the corresponding components of p2
+inline QPointF operator/(const QPointF &p1, const QPointF &p2)
+{
+ return QPointF(p1.x() / p2.x(), p1.y() / p2.y());
+}
+
+inline QPointF clampToRect(const QPointF &p, const QRectF &rect)
+{
+ qreal x = qBound(rect.left(), p.x(), rect.right());
+ qreal y = qBound(rect.top(), p.y(), rect.bottom());
+ return QPointF(x, y);
+}
+
+// returns -1, 0 or +1 according to r being <0, ==0 or >0
+inline int qSign(qreal r)
+{
+ return (r < 0) ? -1 : ((r > 0) ? 1 : 0);
+}
+
+// this version is not mathematically exact, but it just works for every
+// easing curve type (even custom ones)
+
+static qreal differentialForProgress(const QEasingCurve &curve, qreal pos)
+{
+ const qreal dx = 0.01;
+ qreal left = (pos < qreal(0.5)) ? pos : pos - qreal(dx);
+ qreal right = (pos >= qreal(0.5)) ? pos : pos + qreal(dx);
+ qreal d = (curve.valueForProgress(right) - curve.valueForProgress(left)) / qreal(dx);
+
+ //qScrollerDebug() << "differentialForProgress(type: " << curve.type() << ", pos: " << pos << ") = " << d;
+
+ return d;
+}
+
+// this version is not mathematically exact, but it just works for every
+// easing curve type (even custom ones)
+
+static qreal progressForValue(const QEasingCurve &curve, qreal value)
+{
+ if (curve.type() >= QEasingCurve::InElastic &&
+ curve.type() < QEasingCurve::Custom) {
+ qWarning("progressForValue(): QEasingCurves of type %d do not have an inverse, since they are not injective.", curve.type());
+ return value;
+ }
+ if (value < qreal(0) || value > qreal(1))
+ return value;
+
+ qreal progress = value, left(0), right(1);
+ for (int iterations = 6; iterations; --iterations) {
+ qreal v = curve.valueForProgress(progress);
+ if (v < value)
+ left = progress;
+ else if (v > value)
+ right = progress;
+ else
+ break;
+ progress = (left + right) / qreal(2);
+ }
+ return progress;
+}
+
+
+class QScrollTimer : public QAbstractAnimation
+{
+public:
+ QScrollTimer(QScrollerPrivate *_d)
+ : d(_d), ignoreUpdate(false), skip(0)
+ { }
+
+ int duration() const
+ {
+ return -1;
+ }
+
+ void start()
+ {
+ // QAbstractAnimation::start() will immediately call
+ // updateCurrentTime(), but our state is not set correctly yet
+ ignoreUpdate = true;
+ QAbstractAnimation::start();
+ ignoreUpdate = false;
+ skip = 0;
+ }
+
+protected:
+ void updateCurrentTime(int /*currentTime*/)
+ {
+ if (!ignoreUpdate) {
+ if (++skip >= d->frameRateSkip()) {
+ skip = 0;
+ d->timerTick();
+ }
+ }
+ }
+
+private:
+ QScrollerPrivate *d;
+ bool ignoreUpdate;
+ int skip;
+};
+
+/*!
+ \class QScroller
+ \brief The QScroller class enables kinetic scrolling for any scrolling widget or graphics item.
+ \since 4.8
+
+ With kinetic scrolling, the user can push the widget in a given
+ direction and it will continue to scroll in this direction until it is
+ stopped either by the user or by friction. Aspects of inertia, friction
+ and other physical concepts can be changed in order to fine-tune an
+ intuitive user experience.
+
+ The QScroller object is the object that stores the current position and
+ speed of the scrolling and takes care of updates.
+ QScroller can be triggered by a flick gesture
+
+ \code
+ QWidget *w = ...;
+ QScroller::grabGesture(w, QScroller::LeftMouseButtonGesture);
+ \endcode
+
+ or directly like this:
+
+ \code
+ QWidget *w = ...;
+ QScroller *scroller = QScroller::scroller(w);
+ scroller->scrollTo(QPointF(100, 100));
+ \endcode
+
+ The scrolled QObjects will be receive a QScrollPrepareEvent whenever the scroller needs to
+ update its geometry information and a QScrollEvent whenever the content of the object should
+ actually be scrolled.
+
+ The scroller uses the global QAbstractAnimation timer to generate its QScrollEvents, but this
+ can be slowed down with QScrollerProperties::FrameRate on a per-QScroller basis.
+
+ Several examples in the \c scroller examples directory show how QScroller,
+ QScrollEvent and the scroller gesture can be used.
+
+ Even though this kinetic scroller has a huge number of settings available via
+ QScrollerProperties, we recommend that you leave them all at their default, platform optimized
+ values. In case you really want to change them you can experiment with the \c plot example in
+ the \c scroller examples directory first.
+
+ \sa QScrollEvent, QScrollPrepareEvent, QScrollerProperties
+*/
+
+
+QMap<QObject *, QScroller *> QScrollerPrivate::allScrollers;
+QSet<QScroller *> QScrollerPrivate::activeScrollers;
+
+/*!
+ Returns \c true if a QScroller object was already created for \a target; \c false otherwise.
+
+ \sa scroller()
+*/
+bool QScroller::hasScroller(QObject *target)
+{
+ return (QScrollerPrivate::allScrollers.value(target));
+}
+
+/*!
+ Returns the scroller for the given \a target.
+ As long as the object exist this function will always return the same QScroller.
+ If a QScroller does not exist yet for the \a target, it will implicitly be created.
+ At no point will two QScrollers be active on one object.
+
+ \sa hasScroller(), target()
+*/
+QScroller *QScroller::scroller(QObject *target)
+{
+ if (!target) {
+ qWarning("QScroller::scroller() was called with a null target.");
+ return 0;
+ }
+
+ if (QScrollerPrivate::allScrollers.contains(target))
+ return QScrollerPrivate::allScrollers.value(target);
+
+ QScroller *s = new QScroller(target);
+ QScrollerPrivate::allScrollers.insert(target, s);
+ return s;
+}
+
+/*!
+ \overload
+ This is the const version of scroller().
+*/
+const QScroller *QScroller::scroller(const QObject *target)
+{
+ return scroller(const_cast<QObject*>(target));
+}
+
+/*!
+ Returns an application wide list of currently active, i.e. state() !=
+ QScroller::Inactive, QScroller objects.
+ This routine is mostly useful when writing your own gesture recognizer.
+*/
+QList<QScroller *> QScroller::activeScrollers()
+{
+ return QScrollerPrivate::activeScrollers.toList();
+}
+
+/*!
+ Returns the target object of this scroller.
+ \sa hasScroller(), scroller()
+ */
+QObject *QScroller::target() const
+{
+ Q_D(const QScroller);
+ return d->target;
+}
+
+/*!
+ \fn QScroller::scrollerPropertiesChanged(const QScrollerProperties &newProperties);
+
+ QScroller emits this signal whenever its scroller properties have been
+ changed. \a newProperties are the new scroller properties.
+
+ \sa scrollerProperties
+*/
+
+
+/*! \property QScroller::scrollerProperties
+ \brief The scroller properties of this scroller.
+ The properties will be used by the QScroller to determine its scrolling behaviour.
+*/
+QScrollerProperties QScroller::scrollerProperties() const
+{
+ Q_D(const QScroller);
+ return d->properties;
+}
+
+void QScroller::setScrollerProperties(const QScrollerProperties &sp)
+{
+ Q_D(QScroller);
+ if (d->properties != sp) {
+ d->properties = sp;
+ emit scrollerPropertiesChanged(sp);
+
+ // we need to force the recalculation here, since the overshootPolicy may have changed and
+ // existing segments may include an overshoot animation.
+ d->recalcScrollingSegments(true);
+ }
+}
+
+
+/*!
+ Registers a custom scroll gesture recognizer and grabs it for the \a
+ target and returns the resulting gesture type. If \a scrollGestureType is
+ set to TouchGesture the gesture will trigger on touch events - if set to
+ one of LeftMouseButtonGesture, RightMouseButtonGesture or
+ MiddleMouseButtonGesture it will trigger on mouse events of the
+ corresponding button.
+
+ Only one scroll gesture can be active on a single object at the same
+ time, so if you call this function twice on the same object, it will
+ ungrab the existing gesture before grabbing the new one.
+
+ Please note: To avoid nasty side-effects, all mouse events will be
+ consumed while the gesture is triggered. Since the mouse press event is
+ not consumed, the gesture needs to also send a fake mouse release event
+ at the global position \c{(INT_MIN, INT_MIN)} to make sure that it
+ doesn't mess with the internal states of the widget that received the
+ mouse press in the first place (which could e.g. be a QPushButton
+ inside a QScrollArea).
+*/
+Qt::GestureType QScroller::grabGesture(QObject *target, ScrollerGestureType scrollGestureType)
+{
+ // ensure that a scroller for target is created
+ QScroller *s = scroller(target);
+ if (!s)
+ return Qt::GestureType(0);
+
+ QScrollerPrivate *sp = s->d_ptr;
+ if (sp->recognizer)
+ ungrabGesture(target); // ungrab the old gesture
+
+ Qt::MouseButton button;
+ switch (scrollGestureType) {
+ case LeftMouseButtonGesture : button = Qt::LeftButton; break;
+ case RightMouseButtonGesture : button = Qt::RightButton; break;
+ case MiddleMouseButtonGesture: button = Qt::MiddleButton; break;
+ default :
+ case TouchGesture : button = Qt::NoButton; break; // NoButton == Touch
+ }
+
+ sp->recognizer = new QFlickGestureRecognizer(button);
+ sp->recognizerType = QGestureRecognizer::registerRecognizer(sp->recognizer);
+
+ if (target->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(target);
+ widget->grabGesture(sp->recognizerType);
+ if (scrollGestureType == TouchGesture)
+ widget->setAttribute(Qt::WA_AcceptTouchEvents);
+
+ } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target)) {
+ if (scrollGestureType == TouchGesture)
+ go->setAcceptTouchEvents(true);
+ go->grabGesture(sp->recognizerType);
+ }
+ return sp->recognizerType;
+}
+
+/*!
+ Returns the gesture type currently grabbed for the \a target or 0 if no
+ gesture is grabbed.
+*/
+Qt::GestureType QScroller::grabbedGesture(QObject *target)
+{
+ QScroller *s = scroller(target);
+ if (s && s->d_ptr)
+ return s->d_ptr->recognizerType;
+ else
+ return Qt::GestureType(0);
+}
+
+/*!
+ Ungrabs the gesture for the \a target.
+*/
+void QScroller::ungrabGesture(QObject *target)
+{
+ QScroller *s = scroller(target);
+ if (!s)
+ return;
+
+ QScrollerPrivate *sp = s->d_ptr;
+ if (!sp->recognizer)
+ return; // nothing to do
+
+ if (target->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(target);
+ widget->ungrabGesture(sp->recognizerType);
+
+ } else if (QGraphicsObject *go = qobject_cast<QGraphicsObject*>(target)) {
+ go->ungrabGesture(sp->recognizerType);
+ }
+
+ QGestureRecognizer::unregisterRecognizer(sp->recognizerType);
+ // do not delete the recognizer. The QGestureManager is doing this.
+ sp->recognizer = 0;
+}
+
+/*!
+ \internal
+*/
+QScroller::QScroller(QObject *target)
+ : d_ptr(new QScrollerPrivate(this, target))
+{
+ Q_ASSERT(target); // you can't create a scroller without a target in any normal way
+ Q_D(QScroller);
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QScroller::~QScroller()
+{
+ Q_D(QScroller);
+ QGestureRecognizer::unregisterRecognizer(d->recognizerType);
+ // do not delete the recognizer. The QGestureManager is doing this.
+ d->recognizer = 0;
+ QScrollerPrivate::allScrollers.remove(d->target);
+ QScrollerPrivate::activeScrollers.remove(this);
+
+ delete d_ptr;
+}
+
+
+/*!
+ \fn QScroller::stateChanged(QScroller::State newState);
+
+ QScroller emits this signal whenever the state changes. \a newState is the new State.
+
+ \sa state
+*/
+
+/*!
+ \property QScroller::state
+ \brief the state of the scroller
+
+ \sa QScroller::State
+*/
+QScroller::State QScroller::state() const
+{
+ Q_D(const QScroller);
+ return d->state;
+}
+
+/*!
+ Stops the scroller and resets the state back to Inactive.
+*/
+void QScroller::stop()
+{
+ Q_D(QScroller);
+ if (d->state != Inactive) {
+ QPointF here = clampToRect(d->contentPosition, d->contentPosRange);
+ qreal snapX = d->nextSnapPos(here.x(), 0, Qt::Horizontal);
+ qreal snapY = d->nextSnapPos(here.y(), 0, Qt::Vertical);
+ QPointF snap = here;
+ if (!qIsNaN(snapX))
+ snap.setX(snapX);
+ if (!qIsNaN(snapY))
+ snap.setY(snapY);
+ d->contentPosition = snap;
+ d->overshootPosition = QPointF(0, 0);
+
+ d->setState(Inactive);
+ }
+}
+
+/*!
+ \brief Returns the pixel per meter metric for the scrolled widget.
+
+ The value is reported for both the x and y axis separately by using a QPointF.
+
+ \note Please note that this value should be physically correct, while the actual DPI settings
+ that Qt returns for the display may be reported wrongly (on purpose) by the underlying
+ windowing system (e.g. Mac OS X or Maemo 5).
+*/
+QPointF QScroller::pixelPerMeter() const
+{
+ Q_D(const QScroller);
+ QPointF ppm = d->pixelPerMeter;
+
+ if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(d->target)) {
+ QTransform viewtr;
+ //TODO: the first view isn't really correct - maybe use an additional field in the prepare event?
+ if (go->scene() && !go->scene()->views().isEmpty())
+ viewtr = go->scene()->views().first()->viewportTransform();
+ QTransform tr = go->deviceTransform(viewtr);
+ if (tr.isScaling()) {
+ QPointF p0 = tr.map(QPointF(0, 0));
+ QPointF px = tr.map(QPointF(1, 0));
+ QPointF py = tr.map(QPointF(0, 1));
+ ppm.rx() /= QLineF(p0, px).length();
+ ppm.ry() /= QLineF(p0, py).length();
+ }
+ }
+ return ppm;
+}
+
+/*!
+ \brief Returns the current velocity of the scroller.
+
+ Returns the current scrolling velocity in meter per second when in the state Scrolling.
+ Returns a null velocity otherwise.
+
+ The velocity is reported for both the x and y axis separately by using a QPointF.
+
+ \sa pixelPerMeter()
+*/
+QPointF QScroller::velocity() const
+{
+ Q_D(const QScroller);
+ const QScrollerPropertiesPrivate *sp = d->properties.d.data();
+
+ switch (state()) {
+ case Dragging:
+ return d->releaseVelocity;
+ case Scrolling: {
+ QPointF vel;
+ qint64 now = d->monotonicTimer.elapsed();
+
+ if (!d->xSegments.isEmpty()) {
+ const QScrollerPrivate::ScrollSegment &s = d->xSegments.head();
+ qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress);
+ qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / s.maxProgress / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress);
+ vel.setX(v);
+ }
+
+ if (!d->ySegments.isEmpty()) {
+ const QScrollerPrivate::ScrollSegment &s = d->ySegments.head();
+ qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress);
+ qreal v = qSign(s.deltaPos) * qreal(s.deltaTime) / s.maxProgress / qreal(1000) * sp->decelerationFactor * qreal(0.5) * differentialForProgress(s.curve, progress);
+ vel.setY(v);
+ }
+ //qScrollerDebug() << "Velocity: " << vel;
+ return vel;
+ }
+ default:
+ return QPointF(0, 0);
+ }
+}
+
+/*!
+ \brief Returns the target position for the scroll movement.
+
+ Returns the planned final position for the current scroll movement or the current
+ position if the scroller is not in the scrolling state.
+ The result is undefined when the scroller is in the inactive state.
+
+ The target position is in pixel.
+
+ \sa pixelPerMeter(), scrollTo()
+*/
+QPointF QScroller::finalPosition() const
+{
+ Q_D(const QScroller);
+ return QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal),
+ d->scrollingSegmentsEndPos(Qt::Vertical));
+}
+
+/*!
+ Starts scrolling the widget so that point \a pos is at the top-left position in
+ the viewport.
+
+ The behaviour when scrolling outside the valid scroll area is undefined.
+ In this case the scroller might or might not overshoot.
+
+ The scrolling speed will be calculated so that the given position will
+ be reached after a platform-defined time span (e.g. 1 second for Maemo 5).
+
+ \a pos is given in viewport coordinates.
+
+ \sa ensureVisible()
+*/
+void QScroller::scrollTo(const QPointF &pos)
+{
+ // we could make this adjustable via QScrollerProperties
+ scrollTo(pos, 300);
+}
+
+/*! \overload
+
+ This version will reach its destination position in \a scrollTime milli seconds.
+*/
+void QScroller::scrollTo(const QPointF &pos, int scrollTime)
+{
+ Q_D(QScroller);
+
+ if (d->state == Pressed || d->state == Dragging )
+ return;
+
+ // no need to resend a prepare event if we are already scrolling
+ if (d->state == Inactive && !d->prepareScrolling(QPointF()))
+ return;
+
+ QPointF newpos = clampToRect(pos, d->contentPosRange);
+ qreal snapX = d->nextSnapPos(newpos.x(), 0, Qt::Horizontal);
+ qreal snapY = d->nextSnapPos(newpos.y(), 0, Qt::Vertical);
+ if (!qIsNaN(snapX))
+ newpos.setX(snapX);
+ if (!qIsNaN(snapY))
+ newpos.setY(snapY);
+
+ qScrollerDebug() << "QScroller::scrollTo(req:" << pos << " [pix] / snap:" << newpos << ", " << scrollTime << " [ms])";
+
+ if (newpos == d->contentPosition + d->overshootPosition)
+ return;
+
+ QPointF vel = velocity();
+
+ if (scrollTime < 0)
+ scrollTime = 0;
+ qreal time = qreal(scrollTime) / 1000;
+
+ d->createScrollToSegments(vel.x(), time, newpos.x(), Qt::Horizontal, QScrollerPrivate::ScrollTypeScrollTo);
+ d->createScrollToSegments(vel.y(), time, newpos.y(), Qt::Vertical, QScrollerPrivate::ScrollTypeScrollTo);
+
+ if (!scrollTime)
+ d->setContentPositionHelperScrolling();
+ d->setState(scrollTime ? Scrolling : Inactive);
+}
+
+/*!
+ Starts scrolling so that the rectangle \a rect is visible inside the
+ viewport with additional margins specified in pixels by \a xmargin and \a ymargin around
+ the rect.
+
+ In cases where it is not possible to fit the rect plus margins inside the viewport the contents
+ are scrolled so that as much as possible is visible from \a rect.
+
+ The scrolling speed will be calculated so that the given position will
+ be reached after a platform-defined time span (e.g. 1 second for Maemo 5).
+
+ This function performs the actual scrolling by calling scrollTo().
+*/
+void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin)
+{
+ // we could make this adjustable via QScrollerProperties
+ ensureVisible(rect, xmargin, ymargin, 1000);
+}
+
+/*! \overload
+
+ This version will reach its destination position in \a scrollTime milli seconds.
+*/
+void QScroller::ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, int scrollTime)
+{
+ Q_D(QScroller);
+
+ if (d->state == Pressed || d->state == Dragging )
+ return;
+
+ if (d->state == Inactive && !d->prepareScrolling(QPointF()))
+ return;
+
+ // -- calculate the current pos (or the position after the current scroll)
+ QPointF startPos = d->contentPosition + d->overshootPosition;
+ startPos = QPointF(d->scrollingSegmentsEndPos(Qt::Horizontal),
+ d->scrollingSegmentsEndPos(Qt::Vertical));
+
+ QRectF marginRect(rect.x() - xmargin, rect.y() - ymargin,
+ rect.width() + 2 * xmargin, rect.height() + 2 * ymargin);
+
+ QSizeF visible = d->viewportSize;
+ QRectF visibleRect(startPos, visible);
+
+ qScrollerDebug() << "QScroller::ensureVisible(" << rect << " [pix], " << xmargin << " [pix], " << ymargin << " [pix], " << scrollTime << "[ms])";
+ qScrollerDebug() << " --> content position:" << d->contentPosition;
+
+ if (visibleRect.contains(marginRect))
+ return;
+
+ QPointF newPos = startPos;
+
+ if (visibleRect.width() < rect.width()) {
+ // at least try to move the rect into view
+ if (rect.left() > visibleRect.left())
+ newPos.setX(rect.left());
+ else if (rect.right() < visibleRect.right())
+ newPos.setX(rect.right() - visible.width());
+
+ } else if (visibleRect.width() < marginRect.width()) {
+ newPos.setX(rect.center().x() - visibleRect.width() / 2);
+ } else if (marginRect.left() > visibleRect.left()) {
+ newPos.setX(marginRect.left());
+ } else if (marginRect.right() < visibleRect.right()) {
+ newPos.setX(marginRect.right() - visible.width());
+ }
+
+ if (visibleRect.height() < rect.height()) {
+ // at least try to move the rect into view
+ if (rect.top() > visibleRect.top())
+ newPos.setX(rect.top());
+ else if (rect.bottom() < visibleRect.bottom())
+ newPos.setX(rect.bottom() - visible.height());
+
+ } else if (visibleRect.height() < marginRect.height()) {
+ newPos.setY(rect.center().y() - visibleRect.height() / 2);
+ } else if (marginRect.top() > visibleRect.top()) {
+ newPos.setY(marginRect.top());
+ } else if (marginRect.bottom() < visibleRect.bottom()) {
+ newPos.setY(marginRect.bottom() - visible.height());
+ }
+
+ // clamp to maximum content position
+ newPos = clampToRect(newPos, d->contentPosRange);
+ if (newPos == startPos)
+ return;
+
+ scrollTo(newPos, scrollTime);
+}
+
+/*! This function resends the QScrollPrepareEvent.
+ * Calling resendPrepareEvent triggers a QScrollPrepareEvent from the scroller.
+ * This will allow the receiver to re-set content position and content size while
+ * scrolling.
+ * Calling this function while in the Inactive state is useless as the prepare event
+ * is send again right before scrolling starts.
+ */
+void QScroller::resendPrepareEvent()
+{
+ Q_D(QScroller);
+ d->prepareScrolling(d->pressPosition);
+}
+
+/*! Set the snap positions for the horizontal axis.
+ * Set the snap positions to a list of \a positions.
+ * This will overwrite all previously set snap positions and also a previously
+ * set snapping interval.
+ * Snapping can be deactivated by setting an empty list of positions.
+ */
+void QScroller::setSnapPositionsX(const QList<qreal> &positions)
+{
+ Q_D(QScroller);
+ d->snapPositionsX = positions;
+ d->snapIntervalX = 0.0;
+
+ d->recalcScrollingSegments();
+}
+
+/*! Set the snap positions for the horizontal axis.
+ * Set the snap positions to regular spaced intervals.
+ * The first snap position will be at \a first from the beginning of the list. The next at \a first + \a interval and so on.
+ * This can be used to implement a list header.
+ * This will overwrite all previously set snap positions and also a previously
+ * set snapping interval.
+ * Snapping can be deactivated by setting an interval of 0.0
+ */
+void QScroller::setSnapPositionsX(qreal first, qreal interval)
+{
+ Q_D(QScroller);
+ d->snapFirstX = first;
+ d->snapIntervalX = interval;
+ d->snapPositionsX.clear();
+
+ d->recalcScrollingSegments();
+}
+
+/*! Set the snap positions for the vertical axis.
+ * Set the snap positions to a list of \a positions.
+ * This will overwrite all previously set snap positions and also a previously
+ * set snapping interval.
+ * Snapping can be deactivated by setting an empty list of positions.
+ */
+void QScroller::setSnapPositionsY(const QList<qreal> &positions)
+{
+ Q_D(QScroller);
+ d->snapPositionsY = positions;
+ d->snapIntervalY = 0.0;
+
+ d->recalcScrollingSegments();
+}
+
+/*! Set the snap positions for the vertical axis.
+ * Set the snap positions to regular spaced intervals.
+ * The first snap position will be at \a first. The next at \a first + \a interval and so on.
+ * This will overwrite all previously set snap positions and also a previously
+ * set snapping interval.
+ * Snapping can be deactivated by setting an interval of 0.0
+ */
+void QScroller::setSnapPositionsY(qreal first, qreal interval)
+{
+ Q_D(QScroller);
+ d->snapFirstY = first;
+ d->snapIntervalY = interval;
+ d->snapPositionsY.clear();
+
+ d->recalcScrollingSegments();
+}
+
+
+
+// -------------- private ------------
+
+QScrollerPrivate::QScrollerPrivate(QScroller *q, QObject *_target)
+ : target(_target)
+ , recognizer(0)
+ , recognizerType(Qt::CustomGesture)
+ , state(QScroller::Inactive)
+ , firstScroll(true)
+ , pressTimestamp(0)
+ , lastTimestamp(0)
+ , snapFirstX(-1.0)
+ , snapIntervalX(0.0)
+ , snapFirstY(-1.0)
+ , snapIntervalY(0.0)
+ , scrollTimer(new QScrollTimer(this))
+ , q_ptr(q)
+{
+ connect(target, SIGNAL(destroyed(QObject*)), this, SLOT(targetDestroyed()));
+}
+
+void QScrollerPrivate::init()
+{
+ setDpiFromWidget(0);
+ monotonicTimer.start();
+}
+
+void QScrollerPrivate::sendEvent(QObject *o, QEvent *e)
+{
+ qt_sendSpontaneousEvent(o, e);
+}
+
+const char *QScrollerPrivate::stateName(QScroller::State state)
+{
+ switch (state) {
+ case QScroller::Inactive: return "inactive";
+ case QScroller::Pressed: return "pressed";
+ case QScroller::Dragging: return "dragging";
+ case QScroller::Scrolling: return "scrolling";
+ default: return "(invalid)";
+ }
+}
+
+const char *QScrollerPrivate::inputName(QScroller::Input input)
+{
+ switch (input) {
+ case QScroller::InputPress: return "press";
+ case QScroller::InputMove: return "move";
+ case QScroller::InputRelease: return "release";
+ default: return "(invalid)";
+ }
+}
+
+void QScrollerPrivate::targetDestroyed()
+{
+ scrollTimer->stop();
+ delete q_ptr;
+}
+
+void QScrollerPrivate::timerTick()
+{
+ struct timerevent {
+ QScroller::State state;
+ typedef void (QScrollerPrivate::*timerhandler_t)();
+ timerhandler_t handler;
+ };
+
+ timerevent timerevents[] = {
+ { QScroller::Dragging, &QScrollerPrivate::timerEventWhileDragging },
+ { QScroller::Scrolling, &QScrollerPrivate::timerEventWhileScrolling },
+ };
+
+ for (int i = 0; i < int(sizeof(timerevents) / sizeof(*timerevents)); ++i) {
+ timerevent *te = timerevents + i;
+
+ if (state == te->state) {
+ (this->*te->handler)();
+ return;
+ }
+ }
+
+ scrollTimer->stop();
+}
+
+/*!
+ This function is used by gesture recognizers to inform the scroller about a new input event.
+ The scroller will change its internal state() according to the input event and its attached
+ scroller properties. Since the scroller doesn't care about the actual kind of input device the
+ event came from, you need to decompose the event into the \a input type, a \a position and a
+ milli-second \a timestamp. The \a position needs to be in the target's coordinate system.
+ The return value is \c true if the event should be consumed by the calling filter or \c false
+ if the event should be forwarded to the control.
+
+ \note Using grabGesture() should be sufficient for most use cases though.
+*/
+bool QScroller::handleInput(Input input, const QPointF &position, qint64 timestamp)
+{
+ Q_D(QScroller);
+
+ qScrollerDebug() << "QScroller::handleInput(" << input << ", " << d->stateName(d->state) << ", " << position << ", " << timestamp << ")";
+ struct statechange {
+ State state;
+ Input input;
+ typedef bool (QScrollerPrivate::*inputhandler_t)(const QPointF &position, qint64 timestamp);
+ inputhandler_t handler;
+ };
+
+ statechange statechanges[] = {
+ { QScroller::Inactive, InputPress, &QScrollerPrivate::pressWhileInactive },
+ { QScroller::Pressed, InputMove, &QScrollerPrivate::moveWhilePressed },
+ { QScroller::Pressed, InputRelease, &QScrollerPrivate::releaseWhilePressed },
+ { QScroller::Dragging, InputMove, &QScrollerPrivate::moveWhileDragging },
+ { QScroller::Dragging, InputRelease, &QScrollerPrivate::releaseWhileDragging },
+ { QScroller::Scrolling, InputPress, &QScrollerPrivate::pressWhileScrolling }
+ };
+
+ for (int i = 0; i < int(sizeof(statechanges) / sizeof(*statechanges)); ++i) {
+ statechange *sc = statechanges + i;
+
+ if (d->state == sc->state && input == sc->input)
+ return (d->*sc->handler)(position - d->overshootPosition, timestamp);
+ }
+ return false;
+}
+
+#if !defined(Q_WS_MAC)
+// the Mac version is implemented in qscroller_mac.mm
+
+QPointF QScrollerPrivate::realDpi(int screen)
+{
+# ifdef Q_WS_MAEMO_5
+ Q_UNUSED(screen);
+
+ // The DPI value is hardcoded to 96 on Maemo5:
+ // https://projects.maemo.org/bugzilla/show_bug.cgi?id=152525
+ // This value (260) is only correct for the N900 though, but
+ // there's no way to get the real DPI at run time.
+ return QPointF(260, 260);
+
+# elif defined(Q_WS_X11) && !defined(QT_NO_XRANDR)
+ if (X11->use_xrandr && X11->ptrXRRSizes) {
+ int nsizes = 0;
+ XRRScreenSize *sizes = X11->ptrXRRSizes(X11->display, screen == -1 ? X11->defaultScreen : screen, &nsizes);
+ if (nsizes > 0 && sizes && sizes->width && sizes->height && sizes->mwidth && sizes->mheight) {
+ qScrollerDebug() << "XRandR DPI:" << QPointF(qreal(25.4) * qreal(sizes->width) / qreal(sizes->mwidth),
+ qreal(25.4) * qreal(sizes->height) / qreal(sizes->mheight));
+ return QPointF(qreal(25.4) * qreal(sizes->width) / qreal(sizes->mwidth),
+ qreal(25.4) * qreal(sizes->height) / qreal(sizes->mheight));
+ }
+ }
+# endif
+
+ QWidget *w = QApplication::desktop()->screen(screen);
+ return QPointF(w->physicalDpiX(), w->physicalDpiY());
+}
+
+#endif // !Q_WS_MAC
+
+
+/*! \internal
+ Returns the resolution of the used screen.
+*/
+QPointF QScrollerPrivate::dpi() const
+{
+ return pixelPerMeter * qreal(0.0254);
+}
+
+/*! \internal
+ Sets the resolution used for scrolling.
+ This resolution is only used by the kinetic scroller. If you change this
+ then the scroller will behave quite different as a lot of the values are
+ given in physical distances (millimeter).
+*/
+void QScrollerPrivate::setDpi(const QPointF &dpi)
+{
+ pixelPerMeter = dpi / qreal(0.0254);
+}
+
+/*! \internal
+ Sets the dpi used for scrolling to the value of the widget.
+*/
+void QScrollerPrivate::setDpiFromWidget(QWidget *widget)
+{
+ QDesktopWidget *dw = QApplication::desktop();
+ setDpi(realDpi(widget ? dw->screenNumber(widget) : dw->primaryScreen()));
+}
+
+/*! \internal
+ Updates the velocity during dragging.
+ Sets releaseVelocity.
+*/
+void QScrollerPrivate::updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime)
+{
+ if (deltaTime <= 0)
+ return;
+
+ Q_Q(QScroller);
+ QPointF ppm = q->pixelPerMeter();
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+ QPointF deltaPixel = deltaPixelRaw;
+
+ qScrollerDebug() << "QScroller::updateVelocity(" << deltaPixelRaw << " [delta pix], " << deltaTime << " [delta ms])";
+
+ // faster than 2.5mm/ms seems bogus (that would be a screen height in ~20 ms)
+ if (((deltaPixelRaw / qreal(deltaTime)).manhattanLength() / ((ppm.x() + ppm.y()) / 2) * 1000) > qreal(2.5))
+ deltaPixel = deltaPixelRaw * qreal(2.5) * ppm / 1000 / (deltaPixelRaw / qreal(deltaTime)).manhattanLength();
+
+ QPointF newv = -deltaPixel / qreal(deltaTime) * qreal(1000) / ppm;
+ if (releaseVelocity != QPointF(0, 0))
+ newv = newv * sp->dragVelocitySmoothingFactor + releaseVelocity * (qreal(1) - sp->dragVelocitySmoothingFactor);
+
+ releaseVelocity.setX(qBound(-sp->maximumVelocity, newv.x(), sp->maximumVelocity));
+ releaseVelocity.setY(qBound(-sp->maximumVelocity, newv.y(), sp->maximumVelocity));
+
+ qScrollerDebug() << " --> new velocity:" << releaseVelocity;
+}
+
+void QScrollerPrivate::pushSegment(ScrollType type, qreal deltaTime, qreal startPos, qreal endPos, QEasingCurve::Type curve, Qt::Orientation orientation, qreal maxProgress)
+{
+ if (startPos == endPos)
+ return;
+
+ ScrollSegment s;
+ if (orientation == Qt::Horizontal && !xSegments.isEmpty())
+ s.startTime = xSegments.last().startTime + xSegments.last().deltaTime;
+ else if (orientation == Qt::Vertical && !ySegments.isEmpty())
+ s.startTime = ySegments.last().startTime + ySegments.last().deltaTime;
+ else
+ s.startTime = monotonicTimer.elapsed();
+
+ s.startPos = startPos;
+ s.deltaPos = endPos - startPos;
+ s.deltaTime = deltaTime * 1000;
+ s.maxProgress = maxProgress;
+ s.curve.setType(curve);
+ s.type = type;
+
+ if (orientation == Qt::Horizontal)
+ xSegments.enqueue(s);
+ else
+ ySegments.enqueue(s);
+
+ qScrollerDebug() << "+++ Added a new ScrollSegment: " << s;
+}
+
+
+/*! \internal
+ Clears the old segments and recalculates them if the current segments are not longer valid
+*/
+void QScrollerPrivate::recalcScrollingSegments(bool forceRecalc)
+{
+ Q_Q(QScroller);
+ QPointF ppm = q->pixelPerMeter();
+
+ releaseVelocity = q->velocity();
+
+ if (forceRecalc || !scrollingSegmentsValid(Qt::Horizontal))
+ createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal);
+
+ if (forceRecalc || !scrollingSegmentsValid(Qt::Vertical))
+ createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical);
+}
+
+/*! \internal
+ Returns the end position after the current scroll has finished.
+*/
+qreal QScrollerPrivate::scrollingSegmentsEndPos(Qt::Orientation orientation) const
+{
+ const QQueue<ScrollSegment> *segments;
+ qreal endPos;
+
+ if (orientation == Qt::Horizontal) {
+ segments = &xSegments;
+ endPos = contentPosition.x() + overshootPosition.x();
+ } else {
+ segments = &ySegments;
+ endPos = contentPosition.y() + overshootPosition.y();
+ }
+
+ if (!segments->isEmpty()) {
+ const ScrollSegment &last = segments->last();
+ endPos = last.startPos + last.deltaPos;
+ }
+
+ return endPos;
+}
+
+/*! \internal
+ Checks if the scroller segment end in a valid position.
+*/
+bool QScrollerPrivate::scrollingSegmentsValid(Qt::Orientation orientation)
+{
+ QQueue<ScrollSegment> *segments;
+ qreal minPos;
+ qreal maxPos;
+
+ if (orientation == Qt::Horizontal) {
+ segments = &xSegments;
+ minPos = contentPosRange.left();
+ maxPos = contentPosRange.right();
+ } else {
+ segments = &ySegments;
+ minPos = contentPosRange.top();
+ maxPos = contentPosRange.bottom();
+ }
+
+ if (segments->isEmpty())
+ return true;
+
+ const ScrollSegment &last = segments->last();
+ qreal endPos = last.startPos + last.deltaPos;
+
+ if (last.type == ScrollTypeScrollTo)
+ return true; // scrollTo is always valid
+
+ if (last.type == ScrollTypeOvershoot &&
+ endPos != minPos && endPos != maxPos)
+ return false;
+
+ if (endPos < minPos || endPos > maxPos)
+ return false;
+
+ if (endPos == minPos || endPos == maxPos) // the begin and the end of the list are always ok
+ return true;
+
+ qreal nextSnap = nextSnapPos(endPos, 0, orientation);
+ if (!qIsNaN(nextSnap) && endPos != nextSnap)
+ return false;
+
+ return true;
+}
+
+/*! \internal
+ Creates the sections needed to scroll to the specific \a endPos to the segments queue.
+*/
+void QScrollerPrivate::createScrollToSegments(qreal v, qreal deltaTime, qreal endPos, Qt::Orientation orientation, ScrollType type)
+{
+ Q_UNUSED(v);
+
+ if (orientation == Qt::Horizontal) {
+ xSegments.clear();
+ } else {
+ ySegments.clear();
+ }
+
+ qScrollerDebug() << "+++ createScrollToSegments: t:" << deltaTime << "ep:" << endPos << "o:" << int(orientation);
+
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+
+ qreal startPos = (orientation == Qt::Horizontal) ? contentPosition.x() + overshootPosition.x()
+ : contentPosition.y() + overshootPosition.y();
+ qreal deltaPos = endPos - startPos;
+
+ pushSegment(type, deltaTime * 0.3, startPos, startPos + deltaPos * 0.5, QEasingCurve::InQuad, orientation);
+ pushSegment(type, deltaTime * 0.7, startPos + deltaPos * 0.5, endPos, sp->scrollingCurve.type(), orientation);
+}
+
+/*! \internal
+*/
+void QScrollerPrivate::createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation)
+{
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+
+ QScrollerProperties::OvershootPolicy policy;
+ qreal minPos;
+ qreal maxPos;
+ qreal viewSize;
+
+ if (orientation == Qt::Horizontal) {
+ xSegments.clear();
+ policy = sp->hOvershootPolicy;
+ minPos = contentPosRange.left();
+ maxPos = contentPosRange.right();
+ viewSize = viewportSize.width();
+ } else {
+ ySegments.clear();
+ policy = sp->vOvershootPolicy;
+ minPos = contentPosRange.top();
+ maxPos = contentPosRange.bottom();
+ viewSize = viewportSize.height();
+ }
+
+ bool alwaysOvershoot = (policy == QScrollerProperties::OvershootAlwaysOn);
+ bool noOvershoot = (policy == QScrollerProperties::OvershootAlwaysOff) || !sp->overshootScrollDistanceFactor;
+ bool canOvershoot = !noOvershoot && (alwaysOvershoot || maxPos);
+
+ qScrollerDebug() << "+++ createScrollingSegments: s:" << startPos << "maxPos:" << maxPos << "o:" << int(orientation);
+
+ // -- check if we are in overshoot
+ if (startPos < minPos) {
+ createScrollToSegments(v, sp->overshootScrollTime * 0.5, minPos, orientation, ScrollTypeOvershoot);
+ return;
+ }
+
+ if (startPos > maxPos) {
+ createScrollToSegments(v, sp->overshootScrollTime * 0.5, maxPos, orientation, ScrollTypeOvershoot);
+ return;
+ }
+
+ qScrollerDebug() << "v = " << v << ", decelerationFactor = " << sp->decelerationFactor << ", curveType = " << sp->scrollingCurve.type();
+
+ // This is only correct for QEasingCurve::OutQuad (linear velocity,
+ // constant deceleration), but the results look and feel ok for OutExpo
+ // and OutSine as well
+
+ // v(t) = deltaTime * a * 0.5 * differentialForProgress(t / deltaTime)
+ // v(0) = vrelease
+ // v(deltaTime) = 0
+ // deltaTime = (2 * vrelease) / (a * differntial(0))
+
+ // pos(t) = integrate(v(t)dt)
+ // pos(t) = vrelease * t - 0.5 * a * t * t
+ // pos(t) = deltaTime * a * 0.5 * progress(t / deltaTime) * deltaTime
+ // deltaPos = pos(deltaTime)
+
+ qreal deltaTime = (qreal(2) * qAbs(v)) / (sp->decelerationFactor * differentialForProgress(sp->scrollingCurve, 0));
+ qreal deltaPos = qSign(v) * deltaTime * deltaTime * qreal(0.5) * sp->decelerationFactor * ppm;
+ qreal endPos = startPos + deltaPos;
+
+ qScrollerDebug() << " Real Delta:" << deltaPos;
+
+ // -- determine snap points
+ qreal nextSnap = nextSnapPos(endPos, 0, orientation);
+ qreal lowerSnapPos = nextSnapPos(startPos, -1, orientation);
+ qreal higherSnapPos = nextSnapPos(startPos, 1, orientation);
+
+ qScrollerDebug() << " Real Delta:" << lowerSnapPos <<"-"<<nextSnap <<"-"<<higherSnapPos;
+
+ // - check if we can reach another snap point
+ if (nextSnap > higherSnapPos || qIsNaN(higherSnapPos))
+ higherSnapPos = nextSnap;
+ if (nextSnap < lowerSnapPos || qIsNaN(lowerSnapPos))
+ lowerSnapPos = nextSnap;
+
+ if (qAbs(v) < sp->minimumVelocity) {
+
+ qScrollerDebug() << "### below minimum Vel" << orientation;
+
+ // - no snap points or already at one
+ if (qIsNaN(nextSnap) || nextSnap == startPos)
+ return; // nothing to do, no scrolling needed.
+
+ // - decide which point to use
+
+ qreal snapDistance = higherSnapPos - lowerSnapPos;
+
+ qreal pressDistance = (orientation == Qt::Horizontal) ?
+ lastPosition.x() - pressPosition.x() :
+ lastPosition.y() - pressPosition.y();
+
+ // if not dragged far enough, pick the next snap point.
+ if (sp->snapPositionRatio == 0.0 || qAbs(pressDistance / sp->snapPositionRatio) > snapDistance)
+ endPos = nextSnap;
+ else if (pressDistance < 0.0)
+ endPos = lowerSnapPos;
+ else
+ endPos = higherSnapPos;
+
+ deltaPos = endPos - startPos;
+ pushSegment(ScrollTypeFlick, sp->snapTime * 0.3, startPos, startPos + deltaPos * 0.3, QEasingCurve::InQuad, orientation);
+ pushSegment(ScrollTypeFlick, sp->snapTime * 0.7, startPos + deltaPos * 0.3, endPos, sp->scrollingCurve.type(), orientation);
+ return;
+ }
+
+ // - go to the next snappoint if there is one
+ if (v > 0 && !qIsNaN(higherSnapPos)) {
+ // change the time in relation to the changed end position
+ if (endPos - startPos)
+ deltaTime *= qAbs((higherSnapPos - startPos) / (endPos - startPos));
+ if (deltaTime > sp->snapTime)
+ deltaTime = sp->snapTime;
+ endPos = higherSnapPos;
+
+ } else if (v < 0 && !qIsNaN(lowerSnapPos)) {
+ // change the time in relation to the changed end position
+ if (endPos - startPos)
+ deltaTime *= qAbs((lowerSnapPos - startPos) / (endPos - startPos));
+ if (deltaTime > sp->snapTime)
+ deltaTime = sp->snapTime;
+ endPos = lowerSnapPos;
+
+ // -- check if we are overshooting
+ } else if (endPos < minPos || endPos > maxPos) {
+ qreal stopPos = endPos < minPos ? minPos : maxPos;
+
+ qScrollerDebug() << "Overshoot: delta:" << (stopPos - startPos);
+
+ qreal maxProgress = progressForValue(sp->scrollingCurve, qAbs((stopPos - startPos) / deltaPos));
+ qScrollerDebug() << "Overshoot maxp:" << maxProgress;
+
+ pushSegment(ScrollTypeFlick, deltaTime * maxProgress, startPos, stopPos, sp->scrollingCurve.type(), orientation, maxProgress);
+
+ if (canOvershoot) {
+ qreal endV = qSign(v) * deltaTime * sp->decelerationFactor * qreal(0.5) * differentialForProgress(sp->scrollingCurve, maxProgress);
+ qScrollerDebug() << "Overshoot: velocity" << endV;
+ qScrollerDebug() << "Overshoot: maxVelocity" << sp->maximumVelocity;
+ qScrollerDebug() << "Overshoot: viewsize" << viewSize;
+ qScrollerDebug() << "Overshoot: factor" << sp->overshootScrollDistanceFactor;
+
+ qreal oDistance = viewSize * sp->overshootScrollDistanceFactor * endV / sp->maximumVelocity;
+ qreal oDeltaTime = sp->overshootScrollTime;
+
+ pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.3, stopPos, stopPos + oDistance, sp->scrollingCurve.type(), orientation);
+ pushSegment(ScrollTypeOvershoot, oDeltaTime * 0.7, stopPos + oDistance, stopPos, sp->scrollingCurve.type(), orientation);
+ }
+ return;
+ }
+
+ pushSegment(ScrollTypeFlick, deltaTime, startPos, endPos, sp->scrollingCurve.type(), orientation);
+}
+
+
+/*! Prepares scrolling by sending a QScrollPrepareEvent to the receiver widget.
+ Returns true if the scrolling was accepted and a target was returned.
+*/
+bool QScrollerPrivate::prepareScrolling(const QPointF &position)
+{
+ QScrollPrepareEvent spe(position);
+ spe.ignore();
+ sendEvent(target, &spe);
+
+ qScrollerDebug() << "QScrollPrepareEvent returned from" << target << "with" << spe.isAccepted() << "mcp:" << spe.contentPosRange() << "cp:" << spe.contentPos();
+ if (spe.isAccepted()) {
+ QPointF oldContentPos = contentPosition + overshootPosition;
+ QPointF contentDelta = spe.contentPos() - oldContentPos;
+
+ viewportSize = spe.viewportSize();
+ contentPosRange = spe.contentPosRange();
+ if (contentPosRange.width() < 0)
+ contentPosRange.setWidth(0);
+ if (contentPosRange.height() < 0)
+ contentPosRange.setHeight(0);
+ contentPosition = clampToRect(spe.contentPos(), contentPosRange);
+ overshootPosition = spe.contentPos() - contentPosition;
+
+ // - check if the content position was moved
+ if (contentDelta != QPointF(0, 0)) {
+ // need to correct all segments
+ for (int i = 0; i < xSegments.count(); i++)
+ xSegments[i].startPos -= contentDelta.x();
+
+ for (int i = 0; i < ySegments.count(); i++)
+ ySegments[i].startPos -= contentDelta.y();
+ }
+
+ if (QWidget *w = qobject_cast<QWidget *>(target))
+ setDpiFromWidget(w);
+ if (QGraphicsObject *go = qobject_cast<QGraphicsObject *>(target)) {
+ //TODO: the first view isn't really correct - maybe use an additional field in the prepare event?
+ if (go->scene() && !go->scene()->views().isEmpty())
+ setDpiFromWidget(go->scene()->views().first());
+ }
+
+ if (state == QScroller::Scrolling) {
+ recalcScrollingSegments();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void QScrollerPrivate::handleDrag(const QPointF &position, qint64 timestamp)
+{
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+
+ QPointF deltaPixel = position - lastPosition;
+ qint64 deltaTime = timestamp - lastTimestamp;
+
+ if (sp->axisLockThreshold) {
+ int dx = qAbs(deltaPixel.x());
+ int dy = qAbs(deltaPixel.y());
+ if (dx || dy) {
+ bool vertical = (dy > dx);
+ qreal alpha = qreal(vertical ? dx : dy) / qreal(vertical ? dy : dx);
+ //qScrollerDebug() << "QScroller::handleDrag() -- axis lock:" << alpha << " / " << axisLockThreshold << "- isvertical:" << vertical << "- dx:" << dx << "- dy:" << dy;
+ if (alpha <= sp->axisLockThreshold) {
+ if (vertical)
+ deltaPixel.setX(0);
+ else
+ deltaPixel.setY(0);
+ }
+ }
+ }
+
+ // calculate velocity (if the user would release the mouse NOW)
+ updateVelocity(deltaPixel, deltaTime);
+
+ // restrict velocity, if content is not scrollable
+ QRectF max = contentPosRange;
+ bool canScrollX = (max.width() > 0) || (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn);
+ bool canScrollY = (max.height() > 0) || (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn);
+
+ if (!canScrollX) {
+ deltaPixel.setX(0);
+ releaseVelocity.setX(0);
+ }
+ if (!canScrollY) {
+ deltaPixel.setY(0);
+ releaseVelocity.setY(0);
+ }
+
+// if (firstDrag) {
+// // Do not delay the first drag
+// setContentPositionHelper(q->contentPosition() - overshootDistance - deltaPixel);
+// dragDistance = QPointF(0, 0);
+// } else {
+ dragDistance += deltaPixel;
+// }
+//qScrollerDebug() << "######################" << deltaPixel << position.y() << lastPosition.y();
+ if (canScrollX)
+ lastPosition.setX(position.x());
+ if (canScrollY)
+ lastPosition.setY(position.y());
+ lastTimestamp = timestamp;
+}
+
+bool QScrollerPrivate::pressWhileInactive(const QPointF &position, qint64 timestamp)
+{
+ if (prepareScrolling(position)) {
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+
+ if (!contentPosRange.isNull() ||
+ (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn) ||
+ (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn)) {
+
+ lastPosition = pressPosition = position;
+ lastTimestamp = pressTimestamp = timestamp;
+ setState(QScroller::Pressed);
+ }
+ }
+ return false;
+}
+
+bool QScrollerPrivate::releaseWhilePressed(const QPointF &, qint64)
+{
+ if (overshootPosition != QPointF(0.0, 0.0)) {
+ setState(QScroller::Scrolling);
+ return true;
+ } else {
+ setState(QScroller::Inactive);
+ return false;
+ }
+}
+
+bool QScrollerPrivate::moveWhilePressed(const QPointF &position, qint64 timestamp)
+{
+ Q_Q(QScroller);
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+ QPointF ppm = q->pixelPerMeter();
+
+ QPointF deltaPixel = position - pressPosition;
+
+ bool moveAborted = false;
+ bool moveStarted = (((deltaPixel / ppm).manhattanLength()) > sp->dragStartDistance);
+
+ // check the direction of the mouse drag and abort if it's too much in the wrong direction.
+ if (moveStarted) {
+ QRectF max = contentPosRange;
+ bool canScrollX = (max.width() > 0);
+ bool canScrollY = (max.height() > 0);
+
+ if (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn)
+ canScrollX = true;
+ if (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn)
+ canScrollY = true;
+
+ if (qAbs(deltaPixel.x() / ppm.x()) < qAbs(deltaPixel.y() / ppm.y())) {
+ if (!canScrollY)
+ moveAborted = true;
+ } else {
+ if (!canScrollX)
+ moveAborted = true;
+ }
+ }
+
+ if (moveAborted) {
+ setState(QScroller::Inactive);
+ moveStarted = false;
+
+ } else if (moveStarted) {
+ setState(QScroller::Dragging);
+
+ // subtract the dragStartDistance
+ deltaPixel = deltaPixel - deltaPixel * (sp->dragStartDistance / deltaPixel.manhattanLength());
+
+ if (deltaPixel != QPointF(0, 0)) {
+ // handleDrag updates lastPosition, lastTimestamp and velocity
+ handleDrag(pressPosition + deltaPixel, timestamp);
+ }
+ }
+ return moveStarted;
+}
+
+bool QScrollerPrivate::moveWhileDragging(const QPointF &position, qint64 timestamp)
+{
+ // handleDrag updates lastPosition, lastTimestamp and velocity
+ handleDrag(position, timestamp);
+ return true;
+}
+
+void QScrollerPrivate::timerEventWhileDragging()
+{
+ if (dragDistance != QPointF(0, 0)) {
+ qScrollerDebug() << "QScroller::timerEventWhileDragging() -- dragDistance:" << dragDistance;
+
+ setContentPositionHelperDragging(-dragDistance);
+ dragDistance = QPointF(0, 0);
+ }
+}
+
+bool QScrollerPrivate::releaseWhileDragging(const QPointF &position, qint64 timestamp)
+{
+ Q_Q(QScroller);
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+
+ // handleDrag updates lastPosition, lastTimestamp and velocity
+ handleDrag(position, timestamp);
+
+ // check if we moved at all - this can happen if you stop a running
+ // scroller with a press and release shortly afterwards
+ QPointF deltaPixel = position - pressPosition;
+ if (((deltaPixel / q->pixelPerMeter()).manhattanLength()) > sp->dragStartDistance) {
+
+ // handle accelerating flicks
+ if ((oldVelocity != QPointF(0, 0)) && sp->acceleratingFlickMaximumTime &&
+ ((timestamp - pressTimestamp) < qint64(sp->acceleratingFlickMaximumTime * 1000))) {
+
+ // - determine if the direction was changed
+ int signX = 0, signY = 0;
+ if (releaseVelocity.x())
+ signX = (releaseVelocity.x() > 0) == (oldVelocity.x() > 0) ? 1 : -1;
+ if (releaseVelocity.y())
+ signY = (releaseVelocity.y() > 0) == (oldVelocity.y() > 0) ? 1 : -1;
+
+ if (signX > 0)
+ releaseVelocity.setX(qBound(-sp->maximumVelocity,
+ oldVelocity.x() * sp->acceleratingFlickSpeedupFactor,
+ sp->maximumVelocity));
+ if (signY > 0)
+ releaseVelocity.setY(qBound(-sp->maximumVelocity,
+ oldVelocity.y() * sp->acceleratingFlickSpeedupFactor,
+ sp->maximumVelocity));
+ }
+ }
+
+ QPointF ppm = q->pixelPerMeter();
+ createScrollingSegments(releaseVelocity.x(), contentPosition.x() + overshootPosition.x(), ppm.x(), Qt::Horizontal);
+ createScrollingSegments(releaseVelocity.y(), contentPosition.y() + overshootPosition.y(), ppm.y(), Qt::Vertical);
+
+ qScrollerDebug() << "QScroller::releaseWhileDragging() -- velocity:" << releaseVelocity << "-- minimum velocity:" << sp->minimumVelocity << "overshoot" << overshootPosition;
+
+ if (xSegments.isEmpty() && ySegments.isEmpty())
+ setState(QScroller::Inactive);
+ else
+ setState(QScroller::Scrolling);
+
+ return true;
+}
+
+void QScrollerPrivate::timerEventWhileScrolling()
+{
+ qScrollerDebug() << "QScroller::timerEventWhileScrolling()";
+
+ setContentPositionHelperScrolling();
+ if (xSegments.isEmpty() && ySegments.isEmpty())
+ setState(QScroller::Inactive);
+}
+
+bool QScrollerPrivate::pressWhileScrolling(const QPointF &position, qint64 timestamp)
+{
+ Q_Q(QScroller);
+
+ if ((q->velocity() <= properties.d->maximumClickThroughVelocity) &&
+ (overshootPosition == QPointF(0.0, 0.0))) {
+ setState(QScroller::Inactive);
+ return false;
+ } else {
+ lastPosition = pressPosition = position;
+ lastTimestamp = pressTimestamp = timestamp;
+ setState(QScroller::Pressed);
+ setState(QScroller::Dragging);
+ return true;
+ }
+}
+
+/*! \internal
+ This function handles all state changes of the scroller.
+*/
+void QScrollerPrivate::setState(QScroller::State newstate)
+{
+ Q_Q(QScroller);
+ bool sendLastScroll = false;
+
+ if (state == newstate)
+ return;
+
+ qScrollerDebug() << q << "QScroller::setState(" << stateName(newstate) << ")";
+
+ switch (newstate) {
+ case QScroller::Inactive:
+ scrollTimer->stop();
+
+ // send the last scroll event (but only after the current state change was finished)
+ if (!firstScroll)
+ sendLastScroll = true;
+
+ releaseVelocity = QPointF(0, 0);
+ break;
+
+ case QScroller::Pressed:
+ scrollTimer->stop();
+
+ oldVelocity = releaseVelocity;
+ releaseVelocity = QPointF(0, 0);
+ break;
+
+ case QScroller::Dragging:
+ dragDistance = QPointF(0, 0);
+ if (state == QScroller::Pressed)
+ scrollTimer->start();
+ break;
+
+ case QScroller::Scrolling:
+ scrollTimer->start();
+ break;
+ }
+
+ qSwap(state, newstate);
+
+ if (sendLastScroll) {
+ QScrollEvent se(contentPosition, overshootPosition, QScrollEvent::ScrollFinished);
+ sendEvent(target, &se);
+ firstScroll = true;
+ }
+ if (state == QScroller::Dragging || state == QScroller::Scrolling)
+ activeScrollers.insert(q);
+ else
+ activeScrollers.remove(q);
+ emit q->stateChanged(state);
+}
+
+
+/*! \internal
+ Helps when setting the content position.
+ It will try to move the content by the requested delta but stop in case
+ when we are coming back from an overshoot or a scrollTo.
+ It will also indicate a new overshooting condition by the overshootX and oversthootY flags.
+
+ In this cases it will reset the velocity variables and other flags.
+
+ Also keeps track of the current over-shooting value in overshootPosition.
+
+ \a deltaPos is the amount of pixels the current content position should be moved
+*/
+void QScrollerPrivate::setContentPositionHelperDragging(const QPointF &deltaPos)
+{
+ Q_Q(QScroller);
+ QPointF ppm = q->pixelPerMeter();
+ const QScrollerPropertiesPrivate *sp = properties.d.data();
+ QPointF v = q->velocity();
+
+ if (sp->overshootDragResistanceFactor)
+ overshootPosition /= sp->overshootDragResistanceFactor;
+
+ QPointF oldPos = contentPosition + overshootPosition;
+ QPointF newPos = oldPos + deltaPos;
+
+ qScrollerDebug() << "QScroller::setContentPositionHelperDragging(" << deltaPos << " [pix])";
+ qScrollerDebug() << " --> overshoot:" << overshootPosition << "- old pos:" << oldPos << "- new pos:" << newPos;
+
+ QPointF oldClampedPos = clampToRect(oldPos, contentPosRange);
+ QPointF newClampedPos = clampToRect(newPos, contentPosRange);
+
+ // --- handle overshooting and stop if the coordinate is going back inside the normal area
+ bool alwaysOvershootX = (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOn);
+ bool alwaysOvershootY = (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOn);
+ bool noOvershootX = (sp->hOvershootPolicy == QScrollerProperties::OvershootAlwaysOff) ||
+ ((state == QScroller::Dragging) && !sp->overshootDragResistanceFactor) ||
+ !sp->overshootDragDistanceFactor;
+ bool noOvershootY = (sp->vOvershootPolicy == QScrollerProperties::OvershootAlwaysOff) ||
+ ((state == QScroller::Dragging) && !sp->overshootDragResistanceFactor) ||
+ !sp->overshootDragDistanceFactor;
+ bool canOvershootX = !noOvershootX && (alwaysOvershootX || contentPosRange.width());
+ bool canOvershootY = !noOvershootY && (alwaysOvershootY || contentPosRange.height());
+
+ qreal oldOvershootX = (canOvershootX) ? oldPos.x() - oldClampedPos.x() : 0;
+ qreal oldOvershootY = (canOvershootY) ? oldPos.y() - oldClampedPos.y() : 0;
+
+ qreal newOvershootX = (canOvershootX) ? newPos.x() - newClampedPos.x() : 0;
+ qreal newOvershootY = (canOvershootY) ? newPos.y() - newClampedPos.y() : 0;
+
+ qreal maxOvershootX = viewportSize.width() * sp->overshootDragDistanceFactor;
+ qreal maxOvershootY = viewportSize.height() * sp->overshootDragDistanceFactor;
+
+ qScrollerDebug() << " --> noOs:" << noOvershootX << "drf:" << sp->overshootDragResistanceFactor << "mdf:" << sp->overshootScrollDistanceFactor << "ossP:"<<sp->hOvershootPolicy;
+ qScrollerDebug() << " --> canOS:" << canOvershootX << "newOS:" << newOvershootX << "maxOS:" << maxOvershootX;
+
+ if (sp->overshootDragResistanceFactor) {
+ oldOvershootX *= sp->overshootDragResistanceFactor;
+ oldOvershootY *= sp->overshootDragResistanceFactor;
+ newOvershootX *= sp->overshootDragResistanceFactor;
+ newOvershootY *= sp->overshootDragResistanceFactor;
+ }
+
+ // -- stop at the maximum overshoot distance
+
+ newOvershootX = qBound(-maxOvershootX, newOvershootX, maxOvershootX);
+ newOvershootY = qBound(-maxOvershootY, newOvershootY, maxOvershootY);
+
+ overshootPosition.setX(newOvershootX);
+ overshootPosition.setY(newOvershootY);
+ contentPosition = newClampedPos;
+
+ QScrollEvent se(contentPosition, overshootPosition, firstScroll ? QScrollEvent::ScrollStarted : QScrollEvent::ScrollUpdated);
+ sendEvent(target, &se);
+ firstScroll = false;
+
+ qScrollerDebug() << " --> new position:" << newClampedPos << "- new overshoot:" << overshootPosition <<
+ "- overshoot x/y?:" << overshootPosition;
+}
+
+
+qreal QScrollerPrivate::nextSegmentPosition(QQueue<ScrollSegment> &segments, qint64 now, qreal oldPos)
+{
+ qreal pos = oldPos;
+
+ // check the X segments for new positions
+ while (!segments.isEmpty()) {
+ const ScrollSegment s = segments.head();
+
+ if ((s.startTime + s.deltaTime) <= now) {
+ segments.dequeue();
+ pos = s.startPos + s.deltaPos;
+ } else if (s.startTime <= now) {
+ qreal progress = qreal(now - s.startTime) / (qreal(s.deltaTime) / s.maxProgress);
+ pos = s.startPos + s.deltaPos * s.curve.valueForProgress(progress) / s.curve.valueForProgress(s.maxProgress);
+ break;
+ } else {
+ break;
+ }
+ }
+ return pos;
+}
+
+void QScrollerPrivate::setContentPositionHelperScrolling()
+{
+ qint64 now = monotonicTimer.elapsed();
+ QPointF newPos = contentPosition + overshootPosition;
+
+ newPos.setX(nextSegmentPosition(xSegments, now, newPos.x()));
+ newPos.setY(nextSegmentPosition(ySegments, now, newPos.y()));
+
+ // -- set the position and handle overshoot
+ qScrollerDebug() << "QScroller::setContentPositionHelperScrolling()";
+ qScrollerDebug() << " --> overshoot:" << overshootPosition << "- new pos:" << newPos;
+
+ QPointF newClampedPos = clampToRect(newPos, contentPosRange);
+
+ overshootPosition = newPos - newClampedPos;
+ contentPosition = newClampedPos;
+
+ QScrollEvent se(contentPosition, overshootPosition, firstScroll ? QScrollEvent::ScrollStarted : QScrollEvent::ScrollUpdated);
+ sendEvent(target, &se);
+ firstScroll = false;
+
+ qScrollerDebug() << " --> new position:" << newClampedPos << "- new overshoot:" << overshootPosition;
+}
+
+/*! \internal
+ * Returns the next snap point in direction.
+ * If \a direction >0 it will return the next snap point that is larger than the current position.
+ * If \a direction <0 it will return the next snap point that is smaller than the current position.
+ * If \a direction ==0 it will return the nearest snap point (or the current position if we are already
+ * on a snap point.
+ * Returns the nearest snap position or NaN if no such point could be found.
+ */
+qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientation)
+{
+ qreal bestSnapPos = Q_QNAN;
+ qreal bestSnapPosDist = Q_INFINITY;
+
+ qreal minPos;
+ qreal maxPos;
+
+ if (orientation == Qt::Horizontal) {
+ minPos = contentPosRange.left();
+ maxPos = contentPosRange.right();
+ } else {
+ minPos = contentPosRange.top();
+ maxPos = contentPosRange.bottom();
+ }
+
+ if (orientation == Qt::Horizontal) {
+ // the snap points in the list
+ foreach (qreal snapPos, snapPositionsX) {
+ qreal snapPosDist = snapPos - p;
+ if ((dir > 0 && snapPosDist < 0) ||
+ (dir < 0 && snapPosDist > 0))
+ continue; // wrong direction
+ if (snapPos < minPos || snapPos > maxPos )
+ continue; // invalid
+
+ if (qIsNaN(bestSnapPos) ||
+ qAbs(snapPosDist) < bestSnapPosDist ) {
+ bestSnapPos = snapPos;
+ bestSnapPosDist = qAbs(snapPosDist);
+ }
+ }
+
+ // the snap point interval
+ if (snapIntervalX > 0.0) {
+ qreal first = minPos + snapFirstX;
+ qreal snapPos;
+ if (dir > 0)
+ snapPos = qCeil((p - first) / snapIntervalX) * snapIntervalX + first;
+ else if (dir < 0)
+ snapPos = qFloor((p - first) / snapIntervalX) * snapIntervalX + first;
+ else if (p <= first)
+ snapPos = first;
+ else
+ {
+ qreal last = qFloor((maxPos - first) / snapIntervalX) * snapIntervalX + first;
+ if (p >= last)
+ snapPos = last;
+ else
+ snapPos = qRound((p - first) / snapIntervalX) * snapIntervalX + first;
+ }
+
+ if (snapPos >= first && snapPos <= maxPos ) {
+ qreal snapPosDist = snapPos - p;
+
+ if (qIsNaN(bestSnapPos) ||
+ qAbs(snapPosDist) < bestSnapPosDist ) {
+ bestSnapPos = snapPos;
+ bestSnapPosDist = qAbs(snapPosDist);
+ }
+ }
+ }
+
+ } else { // (orientation == Qt::Vertical)
+ // the snap points in the list
+ foreach (qreal snapPos, snapPositionsY) {
+ qreal snapPosDist = snapPos - p;
+ if ((dir > 0 && snapPosDist < 0) ||
+ (dir < 0 && snapPosDist > 0))
+ continue; // wrong direction
+ if (snapPos < minPos || snapPos > maxPos )
+ continue; // invalid
+
+ if (qIsNaN(bestSnapPos) ||
+ qAbs(snapPosDist) < bestSnapPosDist) {
+ bestSnapPos = snapPos;
+ bestSnapPosDist = qAbs(snapPosDist);
+ }
+ }
+
+ // the snap point interval
+ if (snapIntervalY > 0.0) {
+ qreal first = minPos + snapFirstY;
+ qreal snapPos;
+ if (dir > 0)
+ snapPos = qCeil((p - first) / snapIntervalY) * snapIntervalY + first;
+ else if (dir < 0)
+ snapPos = qFloor((p - first) / snapIntervalY) * snapIntervalY + first;
+ else if (p <= first)
+ snapPos = first;
+ else
+ {
+ qreal last = qFloor((maxPos - first) / snapIntervalY) * snapIntervalY + first;
+ if (p >= last)
+ snapPos = last;
+ else
+ snapPos = qRound((p - first) / snapIntervalY) * snapIntervalY + first;
+ }
+
+ if (snapPos >= first && snapPos <= maxPos ) {
+ qreal snapPosDist = snapPos - p;
+
+ if (qIsNaN(bestSnapPos) ||
+ qAbs(snapPosDist) < bestSnapPosDist) {
+ bestSnapPos = snapPos;
+ bestSnapPosDist = qAbs(snapPosDist);
+ }
+ }
+ }
+ }
+
+ return bestSnapPos;
+}
+
+/*!
+ \enum QScroller::State
+
+ This enum contains the different QScroller states.
+
+ \value Inactive The scroller is not scrolling and nothing is pressed.
+ \value Pressed A touch event was received or the mouse button pressed but the scroll area is currently not dragged.
+ \value Dragging The scroll area is currently following the touch point or mouse.
+ \value Scrolling The scroll area is moving on it's own.
+*/
+
+/*!
+ \enum QScroller::ScrollerGestureType
+
+ This enum contains the different gesture types that are supported by the QScroller gesture recognizer.
+
+ \value TouchGesture The gesture recognizer will only trigger on touch
+ events. Specifically it will react on single touch points when using a
+ touch screen and dual touch points when using a touchpad.
+ \value LeftMouseButtonGesture The gesture recognizer will only trigger on left mouse button events.
+ \value MiddleMouseButtonGesture The gesture recognizer will only trigger on middle mouse button events.
+ \value RightMouseButtonGesture The gesture recognizer will only trigger on right mouse button events.
+*/
+
+/*!
+ \enum QScroller::Input
+
+ This enum contains an input device agnostic view of input events that are relevant for QScroller.
+
+ \value InputPress The user pressed the input device (e.g. QEvent::MouseButtonPress,
+ QEvent::GraphicsSceneMousePress, QEvent::TouchBegin)
+
+ \value InputMove The user moved the input device (e.g. QEvent::MouseMove,
+ QEvent::GraphicsSceneMouseMove, QEvent::TouchUpdate)
+
+ \value InputRelease The user released the input device (e.g. QEvent::MouseButtonRelease,
+ QEvent::GraphicsSceneMouseRelease, QEvent::TouchEnd)
+
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qscroller.h b/src/gui/util/qscroller.h
new file mode 100644
index 0000000000..7d7e1ca952
--- /dev/null
+++ b/src/gui/util/qscroller.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCROLLER_H
+#define QSCROLLER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QPointF>
+#include <QtGui/QScrollerProperties>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWidget;
+class QScrollerPrivate;
+class QScrollerProperties;
+class QFlickGestureRecognizer;
+class QMouseFlickGestureRecognizer;
+
+class Q_GUI_EXPORT QScroller : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QScrollerProperties scrollerProperties READ scrollerProperties WRITE setScrollerProperties NOTIFY scrollerPropertiesChanged)
+ Q_ENUMS(State)
+
+public:
+ enum State
+ {
+ Inactive,
+ Pressed,
+ Dragging,
+ Scrolling
+ };
+
+ enum ScrollerGestureType
+ {
+ TouchGesture,
+ LeftMouseButtonGesture,
+ RightMouseButtonGesture,
+ MiddleMouseButtonGesture
+ };
+
+ enum Input
+ {
+ InputPress = 1,
+ InputMove,
+ InputRelease
+ };
+
+ static bool hasScroller(QObject *target);
+
+ static QScroller *scroller(QObject *target);
+ static const QScroller *scroller(const QObject *target);
+
+ static Qt::GestureType grabGesture(QObject *target, ScrollerGestureType gestureType = TouchGesture);
+ static Qt::GestureType grabbedGesture(QObject *target);
+ static void ungrabGesture(QObject *target);
+
+ static QList<QScroller *> activeScrollers();
+
+ QObject *target() const;
+
+ State state() const;
+
+ bool handleInput(Input input, const QPointF &position, qint64 timestamp = 0);
+
+ void stop();
+ QPointF velocity() const;
+ QPointF finalPosition() const;
+ QPointF pixelPerMeter() const;
+
+ QScrollerProperties scrollerProperties() const;
+
+ void setSnapPositionsX( const QList<qreal> &positions );
+ void setSnapPositionsX( qreal first, qreal interval );
+ void setSnapPositionsY( const QList<qreal> &positions );
+ void setSnapPositionsY( qreal first, qreal interval );
+
+public Q_SLOTS:
+ void setScrollerProperties(const QScrollerProperties &prop);
+ void scrollTo(const QPointF &pos);
+ void scrollTo(const QPointF &pos, int scrollTime);
+ void ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin);
+ void ensureVisible(const QRectF &rect, qreal xmargin, qreal ymargin, int scrollTime);
+ void resendPrepareEvent();
+
+Q_SIGNALS:
+ void stateChanged(QScroller::State newstate);
+ void scrollerPropertiesChanged(const QScrollerProperties &);
+
+private:
+ QScrollerPrivate *d_ptr;
+
+ QScroller(QObject *target);
+ virtual ~QScroller();
+
+ Q_DISABLE_COPY(QScroller)
+ Q_DECLARE_PRIVATE(QScroller)
+
+ friend class QFlickGestureRecognizer;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCROLLER_H
diff --git a/src/gui/util/qscroller_mac.mm b/src/gui/util/qscroller_mac.mm
new file mode 100644
index 0000000000..3203036987
--- /dev/null
+++ b/src/gui/util/qscroller_mac.mm
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+#include "qscroller_p.h"
+
+#ifdef Q_WS_MAC
+
+QPointF QScrollerPrivate::realDpi(int screen)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSArray *nsscreens = [NSScreen screens];
+
+ if (screen < 0 || screen >= int([nsscreens count]))
+ screen = 0;
+
+ NSScreen *nsscreen = [nsscreens objectAtIndex:screen];
+ CGDirectDisplayID display = [[[nsscreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
+
+ CGSize mmsize = CGDisplayScreenSize(display);
+ if (mmsize.width > 0 && mmsize.height > 0) {
+ return QPointF(CGDisplayPixelsWide(display) / mmsize.width,
+ CGDisplayPixelsHigh(display) / mmsize.height) * qreal(25.4);
+ } else {
+ return QPointF();
+ }
+ [pool release];
+}
+
+#endif
diff --git a/src/gui/util/qscroller_p.h b/src/gui/util/qscroller_p.h
new file mode 100644
index 0000000000..98f34f7619
--- /dev/null
+++ b/src/gui/util/qscroller_p.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCROLLER_P_H
+#define QSCROLLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QPointer>
+#include <QQueue>
+#include <QSet>
+#include <QEasingCurve>
+#include <QElapsedTimer>
+#include <QSizeF>
+#include <QPointF>
+#include <QRectF>
+#include <qscroller.h>
+#include <qscrollerproperties.h>
+#include <private/qscrollerproperties_p.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+class QFlickGestureRecognizer;
+
+class QScrollTimer;
+
+class QScrollerPrivate : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PUBLIC(QScroller)
+
+public:
+ QScrollerPrivate(QScroller *q, QObject *target);
+ void init();
+
+ void sendEvent(QObject *o, QEvent *e);
+
+ void setState(QScroller::State s);
+
+ enum ScrollType {
+ ScrollTypeFlick = 0,
+ ScrollTypeScrollTo,
+ ScrollTypeOvershoot
+ };
+
+ struct ScrollSegment {
+ qint64 startTime;
+ qint64 deltaTime;
+ qreal startPos;
+ qreal deltaPos;
+ QEasingCurve curve;
+ qreal maxProgress;
+ ScrollType type;
+ };
+
+ bool pressWhileInactive(const QPointF &position, qint64 timestamp);
+ bool moveWhilePressed(const QPointF &position, qint64 timestamp);
+ bool releaseWhilePressed(const QPointF &position, qint64 timestamp);
+ bool moveWhileDragging(const QPointF &position, qint64 timestamp);
+ bool releaseWhileDragging(const QPointF &position, qint64 timestamp);
+ bool pressWhileScrolling(const QPointF &position, qint64 timestamp);
+
+ void timerTick();
+ void timerEventWhileDragging();
+ void timerEventWhileScrolling();
+
+ bool prepareScrolling(const QPointF &position);
+ void handleDrag(const QPointF &position, qint64 timestamp);
+
+ QPointF realDpi(int screen);
+ QPointF dpi() const;
+ void setDpi(const QPointF &dpi);
+ void setDpiFromWidget(QWidget *widget);
+
+ void updateVelocity(const QPointF &deltaPixelRaw, qint64 deltaTime);
+ void pushSegment(ScrollType type, qreal deltaTime, qreal startPos, qreal endPos, QEasingCurve::Type curve, Qt::Orientation orientation, qreal maxProgress = 1.0);
+ void recalcScrollingSegments(bool forceRecalc = false);
+ qreal scrollingSegmentsEndPos(Qt::Orientation orientation) const;
+ bool scrollingSegmentsValid(Qt::Orientation orientation);
+ void createScrollToSegments(qreal v, qreal deltaTime, qreal endPos, Qt::Orientation orientation, ScrollType type);
+ void createScrollingSegments(qreal v, qreal startPos, qreal ppm, Qt::Orientation orientation);
+
+ void setContentPositionHelperDragging(const QPointF &deltaPos);
+ void setContentPositionHelperScrolling();
+
+ qreal nextSnapPos(qreal p, int dir, Qt::Orientation orientation);
+ static qreal nextSegmentPosition(QQueue<ScrollSegment> &segments, qint64 now, qreal oldPos);
+
+ inline int frameRateSkip() const { return properties.d.data()->frameRate; }
+
+ static const char *stateName(QScroller::State state);
+ static const char *inputName(QScroller::Input input);
+
+public slots:
+ void targetDestroyed();
+
+public:
+ // static
+ static QMap<QObject *, QScroller *> allScrollers;
+ static QSet<QScroller *> activeScrollers;
+
+ // non static
+ QObject *target;
+ QScrollerProperties properties;
+ QFlickGestureRecognizer *recognizer;
+ Qt::GestureType recognizerType;
+
+ // scroller state:
+
+ // QPointer<QObject> scrollTarget;
+ QSizeF viewportSize;
+ QRectF contentPosRange;
+ QPointF contentPosition;
+ QPointF overshootPosition; // the number of pixels we are overshooting (before overshootDragResistanceFactor)
+
+ // state
+
+ bool enabled;
+ QScroller::State state;
+ bool firstScroll; // true if we haven't already send a scroll event
+
+ QPointF oldVelocity; // the release velocity of the last drag
+
+ QPointF pressPosition;
+ QPointF lastPosition;
+ qint64 pressTimestamp;
+ qint64 lastTimestamp;
+
+ QPointF dragDistance; // the distance we should move during the next drag timer event
+
+ QQueue<ScrollSegment> xSegments;
+ QQueue<ScrollSegment> ySegments;
+
+ // snap positions
+ QList<qreal> snapPositionsX;
+ qreal snapFirstX;
+ qreal snapIntervalX;
+ QList<qreal> snapPositionsY;
+ qreal snapFirstY;
+ qreal snapIntervalY;
+
+ QPointF pixelPerMeter;
+
+ QElapsedTimer monotonicTimer;
+
+ QPointF releaseVelocity; // the starting velocity of the scrolling state
+ QScrollTimer *scrollTimer;
+
+ QScroller *q_ptr;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QSCROLLER_P_H
+
diff --git a/src/gui/util/qscrollerproperties.cpp b/src/gui/util/qscrollerproperties.cpp
new file mode 100644
index 0000000000..2e52959e6f
--- /dev/null
+++ b/src/gui/util/qscrollerproperties.cpp
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QPointer>
+#include <QObject>
+#include <QtCore/qmath.h>
+#ifdef Q_WS_WIN
+# include <QLibrary>
+#endif
+
+#include "qscrollerproperties.h"
+#include "private/qscrollerproperties_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QScrollerPropertiesPrivate *userDefaults = 0;
+static QScrollerPropertiesPrivate *systemDefaults = 0;
+
+QScrollerPropertiesPrivate *QScrollerPropertiesPrivate::defaults()
+{
+ if (!systemDefaults) {
+ QScrollerPropertiesPrivate spp;
+ spp.mousePressEventDelay = qreal(0.25);
+ spp.dragStartDistance = qreal(5.0 / 1000);
+ spp.dragVelocitySmoothingFactor = qreal(0.8);
+ spp.axisLockThreshold = qreal(0);
+ spp.scrollingCurve.setType(QEasingCurve::OutQuad);
+ spp.decelerationFactor = qreal(0.125);
+ spp.minimumVelocity = qreal(50.0 / 1000);
+ spp.maximumVelocity = qreal(500.0 / 1000);
+ spp.maximumClickThroughVelocity = qreal(66.5 / 1000);
+ spp.acceleratingFlickMaximumTime = qreal(1.25);
+ spp.acceleratingFlickSpeedupFactor = qreal(3.0);
+ spp.snapPositionRatio = qreal(0.5);
+ spp.snapTime = qreal(0.3);
+ spp.overshootDragResistanceFactor = qreal(0.5);
+ spp.overshootDragDistanceFactor = qreal(1);
+ spp.overshootScrollDistanceFactor = qreal(0.5);
+ spp.overshootScrollTime = qreal(0.7);
+# ifdef Q_WS_WIN
+ if (QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback"))
+ spp.overshootScrollTime = qreal(0.35);
+# endif
+ spp.hOvershootPolicy = QScrollerProperties::OvershootWhenScrollable;
+ spp.vOvershootPolicy = QScrollerProperties::OvershootWhenScrollable;
+ spp.frameRate = QScrollerProperties::Standard;
+
+ systemDefaults = new QScrollerPropertiesPrivate(spp);
+ }
+ return new QScrollerPropertiesPrivate(userDefaults ? *userDefaults : *systemDefaults);
+}
+
+/*!
+ \class QScrollerProperties
+ \brief The QScrollerProperties class stores the settings for a QScroller.
+ \since 4.8
+
+ The QScrollerProperties class stores the parameters used by QScroller.
+
+ The default settings are platform dependant and Qt will emulate the
+ platform behaviour for kinetic scrolling.
+
+ As a convention the QScrollerProperties are in physical units (meter,
+ seconds) and will be converted by QScroller using the current DPI.
+
+ \sa QScroller
+*/
+
+/*!
+ Constructs new scroller properties.
+*/
+QScrollerProperties::QScrollerProperties()
+ : d(QScrollerPropertiesPrivate::defaults())
+{
+}
+
+/*!
+ Constructs a copy of \a sp.
+*/
+QScrollerProperties::QScrollerProperties(const QScrollerProperties &sp)
+ : d(new QScrollerPropertiesPrivate(*sp.d))
+{
+}
+
+/*!
+ Assigns \a sp to these scroller properties and returns a reference to these scroller properties.
+*/
+QScrollerProperties &QScrollerProperties::operator=(const QScrollerProperties &sp)
+{
+ *d.data() = *sp.d.data();
+ return *this;
+}
+
+/*!
+ Destroys the scroller properties.
+*/
+QScrollerProperties::~QScrollerProperties()
+{
+}
+
+/*!
+ Returns true if these scroller properties are equal to \a sp; otherwise returns false.
+*/
+bool QScrollerProperties::operator==(const QScrollerProperties &sp) const
+{
+ return *d.data() == *sp.d.data();
+}
+
+/*!
+ Returns true if these scroller properties are different from \a sp; otherwise returns false.
+*/
+bool QScrollerProperties::operator!=(const QScrollerProperties &sp) const
+{
+ return !(*d.data() == *sp.d.data());
+}
+
+bool QScrollerPropertiesPrivate::operator==(const QScrollerPropertiesPrivate &p) const
+{
+ bool same = true;
+ same &= (mousePressEventDelay == p.mousePressEventDelay);
+ same &= (dragStartDistance == p.dragStartDistance);
+ same &= (dragVelocitySmoothingFactor == p.dragVelocitySmoothingFactor);
+ same &= (axisLockThreshold == p.axisLockThreshold);
+ same &= (scrollingCurve == p.scrollingCurve);
+ same &= (decelerationFactor == p.decelerationFactor);
+ same &= (minimumVelocity == p.minimumVelocity);
+ same &= (maximumVelocity == p.maximumVelocity);
+ same &= (maximumClickThroughVelocity == p.maximumClickThroughVelocity);
+ same &= (acceleratingFlickMaximumTime == p.acceleratingFlickMaximumTime);
+ same &= (acceleratingFlickSpeedupFactor == p.acceleratingFlickSpeedupFactor);
+ same &= (snapPositionRatio == p.snapPositionRatio);
+ same &= (snapTime == p.snapTime);
+ same &= (overshootDragResistanceFactor == p.overshootDragResistanceFactor);
+ same &= (overshootDragDistanceFactor == p.overshootDragDistanceFactor);
+ same &= (overshootScrollDistanceFactor == p.overshootScrollDistanceFactor);
+ same &= (overshootScrollTime == p.overshootScrollTime);
+ same &= (hOvershootPolicy == p.hOvershootPolicy);
+ same &= (vOvershootPolicy == p.vOvershootPolicy);
+ same &= (frameRate == p.frameRate);
+ return same;
+}
+
+/*!
+ Sets the scroller properties returned by the default constructor to \a sp.
+
+ Use this function to override the platform default properties returned by the default
+ constructor. If you only want to change the scroller properties of a single scroller, then use
+ QScroller::setScrollerProperties()
+
+ \note Calling this function will not change the content of already existing
+ QScrollerProperties objects.
+
+ \sa unsetDefaultScrollerProperties()
+*/
+void QScrollerProperties::setDefaultScrollerProperties(const QScrollerProperties &sp)
+{
+ if (!userDefaults)
+ userDefaults = new QScrollerPropertiesPrivate(*sp.d);
+ else
+ *userDefaults = *sp.d;
+}
+
+/*!
+ Sets the scroller properties returned by the default constructor back to the platform default
+ properties.
+
+ \sa setDefaultScrollerProperties()
+*/
+void QScrollerProperties::unsetDefaultScrollerProperties()
+{
+ delete userDefaults;
+ userDefaults = 0;
+}
+
+/*!
+ Query the \a metric value of the scroller properties.
+
+ \sa setScrollMetric(), ScrollMetric
+*/
+QVariant QScrollerProperties::scrollMetric(ScrollMetric metric) const
+{
+ switch (metric) {
+ case MousePressEventDelay: return d->mousePressEventDelay;
+ case DragStartDistance: return d->dragStartDistance;
+ case DragVelocitySmoothingFactor: return d->dragVelocitySmoothingFactor;
+ case AxisLockThreshold: return d->axisLockThreshold;
+ case ScrollingCurve: return d->scrollingCurve;
+ case DecelerationFactor: return d->decelerationFactor;
+ case MinimumVelocity: return d->minimumVelocity;
+ case MaximumVelocity: return d->maximumVelocity;
+ case MaximumClickThroughVelocity: return d->maximumClickThroughVelocity;
+ case AcceleratingFlickMaximumTime: return d->acceleratingFlickMaximumTime;
+ case AcceleratingFlickSpeedupFactor:return d->acceleratingFlickSpeedupFactor;
+ case SnapPositionRatio: return d->snapPositionRatio;
+ case SnapTime: return d->snapTime;
+ case OvershootDragResistanceFactor: return d->overshootDragResistanceFactor;
+ case OvershootDragDistanceFactor: return d->overshootDragDistanceFactor;
+ case OvershootScrollDistanceFactor: return d->overshootScrollDistanceFactor;
+ case OvershootScrollTime: return d->overshootScrollTime;
+ case HorizontalOvershootPolicy: return QVariant::fromValue(d->hOvershootPolicy);
+ case VerticalOvershootPolicy: return QVariant::fromValue(d->vOvershootPolicy);
+ case FrameRate: return QVariant::fromValue(d->frameRate);
+ case ScrollMetricCount: break;
+ }
+ return QVariant();
+}
+
+/*!
+ Set a specific value of the \a metric ScrollerMetric to \a value.
+
+ \sa scrollMetric(), ScrollMetric
+*/
+void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &value)
+{
+ switch (metric) {
+ case MousePressEventDelay: d->mousePressEventDelay = value.toReal(); break;
+ case DragStartDistance: d->dragStartDistance = value.toReal(); break;
+ case DragVelocitySmoothingFactor: d->dragVelocitySmoothingFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
+ case AxisLockThreshold: d->axisLockThreshold = qBound(qreal(0), value.toReal(), qreal(1)); break;
+ case ScrollingCurve: d->scrollingCurve = value.toEasingCurve(); break;
+ case DecelerationFactor: d->decelerationFactor = value.toReal(); break;
+ case MinimumVelocity: d->minimumVelocity = value.toReal(); break;
+ case MaximumVelocity: d->maximumVelocity = value.toReal(); break;
+ case MaximumClickThroughVelocity: d->maximumClickThroughVelocity = value.toReal(); break;
+ case AcceleratingFlickMaximumTime: d->acceleratingFlickMaximumTime = value.toReal(); break;
+ case AcceleratingFlickSpeedupFactor:d->acceleratingFlickSpeedupFactor = value.toReal(); break;
+ case SnapPositionRatio: d->snapPositionRatio = qBound(qreal(0), value.toReal(), qreal(1)); break;
+ case SnapTime: d->snapTime = value.toReal(); break;
+ case OvershootDragResistanceFactor: d->overshootDragResistanceFactor = value.toReal(); break;
+ case OvershootDragDistanceFactor: d->overshootDragDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
+ case OvershootScrollDistanceFactor: d->overshootScrollDistanceFactor = qBound(qreal(0), value.toReal(), qreal(1)); break;
+ case OvershootScrollTime: d->overshootScrollTime = value.toReal(); break;
+ case HorizontalOvershootPolicy: d->hOvershootPolicy = value.value<QScrollerProperties::OvershootPolicy>(); break;
+ case VerticalOvershootPolicy: d->vOvershootPolicy = value.value<QScrollerProperties::OvershootPolicy>(); break;
+ case FrameRate: d->frameRate = value.value<QScrollerProperties::FrameRates>(); break;
+ case ScrollMetricCount: break;
+ }
+}
+
+/*!
+ \enum QScrollerProperties::FrameRates
+
+ This enum describes the available frame rates used while dragging or scrolling.
+
+ \value Fps60 60 frames per second
+ \value Fps30 30 frames per second
+ \value Fps20 20 frames per second
+ \value Standard the default value is 60 frames per second (which corresponds to QAbstractAnimation).
+*/
+
+/*!
+ \enum QScrollerProperties::OvershootPolicy
+
+ This enum describes the various modes of overshooting.
+
+ \value OvershootWhenScrollable Overshooting is when the content is scrollable. This is the
+ default.
+
+ \value OvershootAlwaysOff Overshooting is never enabled (even when the content is scrollable).
+
+ \value OvershootAlwaysOn Overshooting is always enabled (even when the content is not
+ scrollable).
+*/
+
+/*!
+ \enum QScrollerProperties::ScrollMetric
+
+ This enum contains the different scroll metric types. When not indicated otherwise the
+ setScrollMetric function expects a QVariant of a real value.
+
+ See the QScroller documentation for a further explanation of the concepts behind the different
+ values.
+
+ \value MousePressEventDelay This is the time a mouse press event will be delayed when starting
+ a flick gesture in \c{[s]}. If the gesture is triggered within that time, no mouse press or
+ release will be sent to the scrolled object. If it triggers after that delay the (delayed)
+ mouse press plus a faked release event (at global postion \c{QPoint(-QWIDGETSIZE_MAX,
+ -QWIDGETSIZE_MAX)} will be sent. If the gesture is canceled, then both the (delayed) mouse
+ press plus the real release event will be delivered.
+
+ \value DragStartDistance This is the minimum distance the touch or mouse point needs to be
+ moved before the flick gesture is triggered in \c m.
+
+ \value DragVelocitySmoothingFactor A value that describes how much new drag velocities are
+ included in the final scrolling velocity. This value should be in the range between \c 0 and
+ \c 1. The lower the value, the more smoothing will be applied to the dragging velocity. The
+ default value is \c 0.8.
+
+ \value AxisLockThreshold If greater than zero a scroll movement will be restricted to one axis
+ only if the movement is inside an angle about the axis. The threshold must be in the range \c 0
+ to \c 1.
+
+ \value ScrollingCurve The QEasingCurve used when decelerating the scrolling velocity after an
+ user initiated flick. Please note that this is the easing curve for the positions, \bold{not}
+ the velocity: the default is QEasingCurve::OutQuad, which results is a linear decrease in
+ velocity (1st derivative) and a constant deceleration (2nd derivative).
+
+ \value DecelerationFactor This factor influences how long it takes the scroller to decelerate
+ to 0 velocity. The actual value heavily depends on the chosen ScrollingCurve, but for most
+ types the value should be in the range from \c 0.1 to \c 2.0
+
+ \value MinimumVelocity The minimum velocity that is needed after ending the touch or releasing
+ the mouse to start scrolling in \c{m/s}.
+
+ \value MaximumVelocity This is the maximum velocity that can be reached in \c{m/s}.
+
+ \value MaximumClickThroughVelocity This is the maximum allowed scroll speed for a click-through
+ in \c{m/s}. This means that a click on a currently (slowly) scrolling object will not only stop
+ the scrolling but the click event will also be delivered to the UI control - this is very
+ useful when using exponential-type scrolling curves.
+
+ \value AcceleratingFlickMaximumTime This is the maximum time in \c seconds that a flick gesture
+ can take to be recognized as an accelerating flick. If set to zero no such gesture will be
+ detected. An "accelerating flick" is a flick gesture executed on an already scrolling object.
+ In such cases the scrolling speed is multiplied by AcceleratingFlickSpeedupFactor in order to
+ accelerate it.
+
+ \value AcceleratingFlickSpeedupFactor The current speed will be multiplied by this number if an
+ accelerating flick is detected. Should be \c{> 1}.
+
+ \value SnapPositionRatio This is the distance that the user must drag the area beween two snap
+ points in order to snap it to the next position. e.g. \c{0.33} means that the scroll must only
+ reach one third of the distance between two snap points to snap to the next one. The ratio must
+ be in the range \c 0 to \c 1.
+
+ \value SnapTime This is the time factor for the scrolling curve. A lower value means that the
+ scrolling will take longer. The scrolling distance is independet of this value.
+
+ \value OvershootDragResistanceFactor This value is the factor between the mouse dragging and
+ the actual scroll area movement (during overshoot). The factor must be in the range \c 0 to \c
+ 1.
+
+ \value OvershootDragDistanceFactor This is the maximum distance for overshoot movements while
+ dragging. The actual overshoot distance will be calculated by multiplying this value with the
+ viewport size of the scrolled object. The factor must be in the range \c 0 to \c 1.
+
+ \value OvershootScrollDistanceFactor This is the maximum distance for overshoot movements while
+ scrolling. The actual overshoot distance will be calculated by multiplying this value with the
+ viewport size of the scrolled object. The factor must be in the range \c 0 to \c 1.
+
+ \value OvershootScrollTime This is the time in \c seconds that will be used to play the
+ complete overshoot animation.
+
+ \value HorizontalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy).
+
+ \value VerticalOvershootPolicy This is the horizontal overshooting policy (see OvershootPolicy).
+
+ \value FrameRate This is the frame rate which should be used while dragging or scrolling.
+ QScroller uses a QAbstractAnimation timer internally to sync all scrolling operations to other
+ animations that might be active at the same time. If the Standard value of 60 frames per
+ second is too fast for your use case, you can lower the frames per second with this setting
+ (while still being in-sync with QAbstractAnimation). Please note that only the values of the
+ FrameRates enum are allowed here.
+
+ \value ScrollMetricCount This is just used when enumerating the metrics. It is always the last
+ entry.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qscrollerproperties.h b/src/gui/util/qscrollerproperties.h
new file mode 100644
index 0000000000..e292d8d5e9
--- /dev/null
+++ b/src/gui/util/qscrollerproperties.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCROLLERPROPERTIES_H
+#define QSCROLLERPROPERTIES_H
+
+#include <QtCore/QScopedPointer>
+#include <QtCore/QMetaType>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QScroller;
+class QScrollerPrivate;
+class QScrollerPropertiesPrivate;
+
+class Q_GUI_EXPORT QScrollerProperties
+{
+public:
+ QScrollerProperties();
+ QScrollerProperties(const QScrollerProperties &sp);
+ QScrollerProperties &operator=(const QScrollerProperties &sp);
+ virtual ~QScrollerProperties();
+
+ bool operator==(const QScrollerProperties &sp) const;
+ bool operator!=(const QScrollerProperties &sp) const;
+
+ static void setDefaultScrollerProperties(const QScrollerProperties &sp);
+ static void unsetDefaultScrollerProperties();
+
+ enum OvershootPolicy
+ {
+ OvershootWhenScrollable,
+ OvershootAlwaysOff,
+ OvershootAlwaysOn
+ };
+
+ enum FrameRates {
+ Standard,
+ Fps60,
+ Fps30,
+ Fps20
+ };
+
+ enum ScrollMetric
+ {
+ MousePressEventDelay, // qreal [s]
+ DragStartDistance, // qreal [m]
+ DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
+ AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|)
+
+ ScrollingCurve, // QEasingCurve
+ DecelerationFactor, // slope of the curve
+
+ MinimumVelocity, // qreal [m/s]
+ MaximumVelocity, // qreal [m/s]
+ MaximumClickThroughVelocity, // qreal [m/s]
+
+ AcceleratingFlickMaximumTime, // qreal [s]
+ AcceleratingFlickSpeedupFactor, // qreal [1..]
+
+ SnapPositionRatio, // qreal [0..1]
+ SnapTime, // qreal [s]
+
+ OvershootDragResistanceFactor, // qreal [0..1]
+ OvershootDragDistanceFactor, // qreal [0..1]
+ OvershootScrollDistanceFactor, // qreal [0..1]
+ OvershootScrollTime, // qreal [s]
+
+ HorizontalOvershootPolicy, // enum OvershootPolicy
+ VerticalOvershootPolicy, // enum OvershootPolicy
+ FrameRate, // enum FrameRates
+
+ ScrollMetricCount
+ };
+
+ QVariant scrollMetric(ScrollMetric metric) const;
+ void setScrollMetric(ScrollMetric metric, const QVariant &value);
+
+protected:
+ QScopedPointer<QScrollerPropertiesPrivate> d;
+
+private:
+ QScrollerProperties(QScrollerPropertiesPrivate &dd);
+
+ friend class QScrollerPropertiesPrivate;
+ friend class QScroller;
+ friend class QScrollerPrivate;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QScrollerProperties::OvershootPolicy)
+Q_DECLARE_METATYPE(QScrollerProperties::FrameRates)
+
+QT_END_HEADER
+
+#endif // QSCROLLERPROPERTIES_H
diff --git a/src/gui/util/qscrollerproperties_p.h b/src/gui/util/qscrollerproperties_p.h
new file mode 100644
index 0000000000..093f615b78
--- /dev/null
+++ b/src/gui/util/qscrollerproperties_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCROLLERPROPERTIES_P_H
+#define QSCROLLERPROPERTIES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QPointF>
+#include <QEasingCurve>
+#include <qscrollerproperties.h>
+
+QT_BEGIN_NAMESPACE
+
+class QScrollerPropertiesPrivate
+{
+public:
+ static QScrollerPropertiesPrivate *defaults();
+
+ bool operator==(const QScrollerPropertiesPrivate &) const;
+
+ qreal mousePressEventDelay;
+ qreal dragStartDistance;
+ qreal dragVelocitySmoothingFactor;
+ qreal axisLockThreshold;
+ QEasingCurve scrollingCurve;
+ qreal decelerationFactor;
+ qreal minimumVelocity;
+ qreal maximumVelocity;
+ qreal maximumClickThroughVelocity;
+ qreal acceleratingFlickMaximumTime;
+ qreal acceleratingFlickSpeedupFactor;
+ qreal snapPositionRatio;
+ qreal snapTime;
+ qreal overshootDragResistanceFactor;
+ qreal overshootDragDistanceFactor;
+ qreal overshootScrollDistanceFactor;
+ qreal overshootScrollTime;
+ QScrollerProperties::OvershootPolicy hOvershootPolicy;
+ QScrollerProperties::OvershootPolicy vOvershootPolicy;
+ QScrollerProperties::FrameRates frameRate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSCROLLERPROPERTIES_P_H
+
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index d1c4ff812c..2814a2d30a 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -6,6 +6,11 @@ HEADERS += \
util/qcompleter_p.h \
util/qdesktopservices.h \
util/qsystemtrayicon_p.h \
+ util/qscroller.h \
+ util/qscroller_p.h \
+ util/qscrollerproperties.h \
+ util/qscrollerproperties_p.h \
+ util/qflickgesture_p.h \
util/qundogroup.h \
util/qundostack.h \
util/qundostack_p.h \
@@ -15,6 +20,9 @@ SOURCES += \
util/qsystemtrayicon.cpp \
util/qcompleter.cpp \
util/qdesktopservices.cpp \
+ util/qscroller.cpp \
+ util/qscrollerproperties.cpp \
+ util/qflickgesture.cpp \
util/qundogroup.cpp \
util/qundostack.cpp \
util/qundoview.cpp
@@ -33,12 +41,12 @@ unix:x11 {
util/qsystemtrayicon_x11.cpp
}
-embedded {
+embedded|qpa {
SOURCES += \
util/qsystemtrayicon_qws.cpp
}
-!embedded:!x11:mac {
+!embedded:!qpa:!x11:mac {
OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm
}
@@ -56,4 +64,8 @@ symbian {
} else {
DEFINES += USE_SCHEMEHANDLER
}
-} \ No newline at end of file
+}
+
+macx {
+ OBJECTIVE_SOURCES += util/qscroller_mac.mm
+}
diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp
index 10a645271f..d45c56b72d 100644
--- a/src/gui/widgets/qabstractbutton.cpp
+++ b/src/gui/widgets/qabstractbutton.cpp
@@ -319,7 +319,7 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
return group->d_func()->buttonList;
#endif
- QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent);
+ QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>();
if (autoExclusive) {
for (int i = candidates.count() - 1; i >= 0; --i) {
QAbstractButton *candidate = candidates.at(i);
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 510411613e..7460f32782 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -53,6 +53,8 @@
#include "qpainter.h"
#include "qmargins.h"
+#include <QDebug>
+
#include "qabstractscrollarea_p.h"
#include <qwidget.h>
@@ -62,6 +64,10 @@
#include <private/qt_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#endif
+#ifdef Q_WS_WIN
+# include <qlibrary.h>
+# include <windows.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -295,9 +301,14 @@ void QAbstractScrollAreaPrivate::init()
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layoutChildren();
#ifndef Q_WS_MAC
-#ifndef QT_NO_GESTURES
+# ifndef QT_NO_GESTURES
viewport->grabGesture(Qt::PanGesture);
+# endif
#endif
+#ifdef Q_WS_MAEMO_5
+# ifndef QT_NO_GESTURES
+ // viewport->grabGesture(Qt::TouchFlickGesture);
+# endif
#endif
}
@@ -552,6 +563,11 @@ void QAbstractScrollArea::setViewport(QWidget *widget)
d->viewport->grabGesture(Qt::PanGesture);
#endif
#endif
+#ifdef Q_WS_MAEMO_5
+#ifndef QT_NO_GESTURES
+// d->viewport->grabGesture(Qt::TouchFlickGesture);
+#endif
+#endif
d->layoutChildren();
if (isVisible())
d->viewport->show();
@@ -986,6 +1002,66 @@ bool QAbstractScrollArea::event(QEvent *e)
return false;
}
#endif // QT_NO_GESTURES
+ case QEvent::ScrollPrepare:
+ {
+ QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
+ if (d->canStartScrollingAt(se->startPos().toPoint())) {
+ QScrollBar *hBar = horizontalScrollBar();
+ QScrollBar *vBar = verticalScrollBar();
+
+ se->setViewportSize(QSizeF(viewport()->size()));
+ se->setContentPosRange(QRectF(0, 0, hBar->maximum(), vBar->maximum()));
+ se->setContentPos(QPointF(hBar->value(), vBar->value()));
+ se->accept();
+ return true;
+ }
+ return false;
+ }
+ case QEvent::Scroll:
+ {
+ QScrollEvent *se = static_cast<QScrollEvent *>(e);
+
+ QScrollBar *hBar = horizontalScrollBar();
+ QScrollBar *vBar = verticalScrollBar();
+ hBar->setValue(se->contentPos().x());
+ vBar->setValue(se->contentPos().y());
+
+#ifdef Q_WS_WIN
+ typedef BOOL (*PtrBeginPanningFeedback)(HWND);
+ typedef BOOL (*PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL);
+ typedef BOOL (*PtrEndPanningFeedback)(HWND, BOOL);
+
+ static PtrBeginPanningFeedback ptrBeginPanningFeedback = 0;
+ static PtrUpdatePanningFeedback ptrUpdatePanningFeedback = 0;
+ static PtrEndPanningFeedback ptrEndPanningFeedback = 0;
+
+ if (!ptrBeginPanningFeedback)
+ ptrBeginPanningFeedback = (PtrBeginPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "BeginPanningFeedback");
+ if (!ptrUpdatePanningFeedback)
+ ptrUpdatePanningFeedback = (PtrUpdatePanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "UpdatePanningFeedback");
+ if (!ptrEndPanningFeedback)
+ ptrEndPanningFeedback = (PtrEndPanningFeedback) QLibrary::resolve(QLatin1String("UxTheme"), "EndPanningFeedback");
+
+ if (ptrBeginPanningFeedback && ptrUpdatePanningFeedback && ptrEndPanningFeedback) {
+ WId wid = window()->winId();
+
+ if (!se->overshootDistance().isNull() && d->overshoot.isNull())
+ ptrBeginPanningFeedback(wid);
+ if (!se->overshootDistance().isNull())
+ ptrUpdatePanningFeedback(wid, -se->overshootDistance().x(), -se->overshootDistance().y(), false);
+ if (se->overshootDistance().isNull() && !d->overshoot.isNull())
+ ptrEndPanningFeedback(wid, true);
+ } else
+#endif
+ {
+ QPoint delta = d->overshoot - se->overshootDistance().toPoint();
+ if (!delta.isNull())
+ viewport()->move(viewport()->pos() + delta);
+ }
+ d->overshoot = se->overshootDistance().toPoint();
+
+ return true;
+ }
case QEvent::StyleChange:
case QEvent::LayoutDirectionChange:
case QEvent::ApplicationLayoutDirectionChange:
@@ -1047,6 +1123,9 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e)
case QEvent::GestureOverride:
return event(e);
#endif
+ case QEvent::ScrollPrepare:
+ case QEvent::Scroll:
+ return event(e);
default:
break;
}
@@ -1303,6 +1382,30 @@ void QAbstractScrollArea::scrollContentsBy(int, int)
viewport()->update();
}
+bool QAbstractScrollAreaPrivate::canStartScrollingAt( const QPoint &startPos )
+{
+ Q_Q(QAbstractScrollArea);
+
+ // don't start scrolling when a drag mode has been set.
+ // don't start scrolling on a movable item.
+ if (QGraphicsView *view = qobject_cast<QGraphicsView *>(q)) {
+ if (view->dragMode() != QGraphicsView::NoDrag)
+ return false;
+
+ QGraphicsItem *childItem = view->itemAt(startPos);
+
+ if (childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
+ return false;
+ }
+
+ // don't start scrolling on a QAbstractSlider
+ if (qobject_cast<QAbstractSlider *>(q->viewport()->childAt(startPos))) {
+ return false;
+ }
+
+ return true;
+}
+
void QAbstractScrollAreaPrivate::_q_hslide(int x)
{
Q_Q(QAbstractScrollArea);
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index 85536e38b8..76e1c34868 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -84,11 +84,13 @@ public:
int left, top, right, bottom; // viewport margin
int xoffset, yoffset;
+ QPoint overshoot;
void init();
void layoutChildren();
// ### Fix for 4.4, talk to Bjoern E or Girish.
virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {}
+ bool canStartScrollingAt( const QPoint &startPos );
void _q_hslide(int);
void _q_vslide(int);
diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h
index 8af61c4ec4..8887b47b47 100644
--- a/src/gui/widgets/qabstractslider_p.h
+++ b/src/gui/widgets/qabstractslider_p.h
@@ -117,7 +117,7 @@ public:
;
}
- inline int bound(int val) const { return qMax(minimum, qMin(maximum, val)); }
+ virtual int bound(int val) const { return qMax(minimum, qMin(maximum, val)); }
inline int overflowSafeAdd(int add) const
{
int newValue = value + add;
diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp
index d3a6472170..df2512c1c8 100644
--- a/src/gui/widgets/qcheckbox.cpp
+++ b/src/gui/widgets/qcheckbox.cpp
@@ -300,6 +300,15 @@ QSize QCheckBox::sizeHint() const
return d->sizeHint;
}
+
+/*!
+ \reimp
+*/
+QSize QCheckBox::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
/*!
\reimp
*/
diff --git a/src/gui/widgets/qcheckbox.h b/src/gui/widgets/qcheckbox.h
index f8d5d1c3cf..ae2e93291f 100644
--- a/src/gui/widgets/qcheckbox.h
+++ b/src/gui/widgets/qcheckbox.h
@@ -65,6 +65,7 @@ public:
QSize sizeHint() const;
+ QSize minimumSizeHint() const;
void setTristate(bool y = true);
bool isTristate() const;
diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm
index ddd56f8e52..d5c8eb89d2 100644
--- a/src/gui/widgets/qcocoamenu_mac.mm
+++ b/src/gui/widgets/qcocoamenu_mac.mm
@@ -44,6 +44,7 @@
#ifdef QT_MAC_USE_COCOA
#import <private/qcocoamenu_mac_p.h>
#import <private/qcocoamenuloader_mac_p.h>
+#import <private/qcocoaapplication_mac_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
#include <private/qapplication_p.h>
#include <private/qaction_p.h>
@@ -60,6 +61,7 @@ QT_FORWARD_DECLARE_CLASS(QEvent)
QT_BEGIN_NAMESPACE
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication.cpp
+extern NSString *qt_mac_removePrivateUnicode(NSString* string);
QT_END_NAMESPACE
QT_USE_NAMESPACE
@@ -78,7 +80,7 @@ QT_USE_NAMESPACE
return self;
}
-- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item;
+- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item
{
Q_UNUSED(menu);
@@ -99,7 +101,7 @@ QT_USE_NAMESPACE
}
}
-- (void)menuWillOpen:(NSMenu*)menu;
+- (void)menuWillOpen:(NSMenu*)menu
{
while (QWidget *popup
= QApplication::activePopupWidget())
@@ -109,7 +111,7 @@ QT_USE_NAMESPACE
qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible());
}
-- (void)menuDidClose:(NSMenu*)menu;
+- (void)menuDidClose:(NSMenu*)menu
{
qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, false);
if (previousAction) {
@@ -156,10 +158,13 @@ QT_USE_NAMESPACE
// In every other case we return NO, which means that Cocoa can do as it pleases
// (i.e., fire the menu action).
NSMenuItem *whichItem;
+ // Change the private unicode keys to the ones used in setting the "Key Equivalents"
+ NSString *characters = qt_mac_removePrivateUnicode([event characters]);
if ([self hasShortcut:menu
- forKey:[event characters]
- forModifiers:([event modifierFlags] & NSDeviceIndependentModifierFlagsMask)
- whichItem:&whichItem]) {
+ forKey:characters
+ // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
+ forModifiers:([event modifierFlags] & (NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask))
+ whichItem:&whichItem]) {
QWidget *widget = 0;
QAction *qaction = 0;
if (whichItem && [whichItem tag]) {
@@ -170,6 +175,9 @@ QT_USE_NAMESPACE
qApp->activePopupWidget()->focusWidget() : qApp->activePopupWidget());
else if (QApplicationPrivate::focus_widget)
widget = QApplicationPrivate::focus_widget;
+ // If we could not find any receivers, pass it to the active window
+ if (!widget)
+ widget = qApp->activeWindow();
if (qaction && widget) {
int key = qaction->shortcut();
QKeyEvent accel_ev(QEvent::ShortcutOverride, (key & (~Qt::KeyboardModifierMask)),
@@ -177,11 +185,10 @@ QT_USE_NAMESPACE
accel_ev.ignore();
qt_sendSpontaneousEvent(widget, &accel_ev);
if (accel_ev.isAccepted()) {
- if (qt_dispatchKeyEvent(event, widget)) {
- *target = nil;
- *action = nil;
- return YES;
- }
+ qt_dispatchKeyEvent(event, widget);
+ *target = nil;
+ *action = nil;
+ return YES;
}
}
}
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 3e5f1b33f4..79461377f4 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu"));
QVariant value = index.data(Qt::ForegroundRole);
- if (qVariantCanConvert<QBrush>(value)) {
+ if (value.canConvert<QBrush>()) {
resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value));
resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value));
resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
@@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt
menuOption.icon = qvariant_cast<QPixmap>(variant);
break;
}
- if (qVariantCanConvert<QBrush>(index.data(Qt::BackgroundRole))) {
+ if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) {
menuOption.palette.setBrush(QPalette::All, QPalette::Background,
qvariant_cast<QBrush>(index.data(Qt::BackgroundRole)));
}
@@ -369,6 +369,7 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent)
if (timerEvent->timerId() == adjustSizeTimer.timerId()) {
adjustSizeTimer.stop();
if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) {
+ combo->updateGeometry();
combo->adjustSize();
combo->update();
}
@@ -1088,6 +1089,8 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
container->setPalette(q->palette());
container->setWindowOpacity(1.0);
}
+ if (lineEdit)
+ lineEdit->setPalette(q->palette());
}
/*!
@@ -1298,7 +1301,7 @@ QComboBox::~QComboBox()
By default, this property has a value of 10.
\note This property is ignored for non-editable comboboxes in styles that returns
- false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
+ true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
*/
int QComboBox::maxVisibleItems() const
{
@@ -2008,11 +2011,18 @@ void QComboBox::setCurrentIndex(int index)
void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi)
{
Q_Q(QComboBox);
- bool indexChanged = (mi != currentIndex);
+
+ QModelIndex normalized;
+ if (mi.column() != modelColumn)
+ normalized = model->index(mi.row(), modelColumn, mi.parent());
+ if (!normalized.isValid())
+ normalized = mi; // Fallback to passed index.
+
+ bool indexChanged = (normalized != currentIndex);
if (indexChanged)
- currentIndex = QPersistentModelIndex(mi);
+ currentIndex = QPersistentModelIndex(normalized);
if (lineEdit) {
- QString newText = q->itemText(currentIndex.row());
+ QString newText = q->itemText(normalized.row());
if (lineEdit->text() != newText)
lineEdit->setText(newText);
updateLineEditGeometry();
diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h
index 0128aa7be2..fd6f68af2d 100644
--- a/src/gui/widgets/qcombobox.h
+++ b/src/gui/widgets/qcombobox.h
@@ -68,7 +68,7 @@ class Q_GUI_EXPORT QComboBox : public QWidget
Q_PROPERTY(bool editable READ isEditable WRITE setEditable)
Q_PROPERTY(int count READ count)
Q_PROPERTY(QString currentText READ currentText)
- Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged USER true)
Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems)
Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount)
Q_PROPERTY(InsertPolicy insertPolicy READ insertPolicy WRITE setInsertPolicy)
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index f3d37ec18d..cd84b87564 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -337,7 +337,7 @@ private:
QComboBox *mCombo;
};
-class QComboBoxPrivate : public QWidgetPrivate
+class Q_AUTOTEST_EXPORT QComboBoxPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QComboBox)
public:
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 276042fc09..63371138c7 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -890,7 +890,13 @@ void QDateTimeEdit::setDisplayFormat(const QString &format)
const bool dateShown = (d->sections & DateSections_Mask);
Q_ASSERT(dateShown || timeShown);
if (timeShown && !dateShown) {
+ QTime time = d->value.toTime();
setDateRange(d->value.toDate(), d->value.toDate());
+ if (d->minimum.toTime() >= d->maximum.toTime()) {
+ setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
+ // if the time range became invalid during the adjustment, the time would have been reset
+ setTime(time);
+ }
} else if (dateShown && !timeShown) {
setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX);
d->value = QDateTime(d->value.toDate(), QTime(), d->spec);
@@ -1654,6 +1660,15 @@ void QDateTimeEditPrivate::updateTimeSpec()
minimum = minimum.toDateTime().toTimeSpec(spec);
maximum = maximum.toDateTime().toTimeSpec(spec);
value = value.toDateTime().toTimeSpec(spec);
+
+ // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range)
+ const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask);
+ if (!dateShown) {
+ if (minimum.toTime() >= maximum.toTime()){
+ minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec);
+ maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec);
+ }
+ }
}
void QDateTimeEditPrivate::updateEdit()
diff --git a/src/gui/widgets/qdial.cpp b/src/gui/widgets/qdial.cpp
index 86981e0fd6..19e8d231ca 100644
--- a/src/gui/widgets/qdial.cpp
+++ b/src/gui/widgets/qdial.cpp
@@ -83,6 +83,7 @@ public:
int valueFromPoint(const QPoint &) const;
double angle(const QPoint &, const QPoint &) const;
void init();
+ virtual int bound(int val) const;
};
void QDialPrivate::init()
@@ -97,6 +98,20 @@ void QDialPrivate::init()
#endif
}
+int QDialPrivate::bound(int val) const
+{
+ if (wrapping) {
+ if ((val >= minimum) && (val <= maximum))
+ return val;
+ val = minimum + ((val - minimum) % (maximum - minimum));
+ if (val < minimum)
+ val += maximum - minimum;
+ return val;
+ } else {
+ return QAbstractSliderPrivate::bound(val);
+ }
+}
+
/*!
Initialize \a option with the values from this QDial. This method
is useful for subclasses when they need a QStyleOptionSlider, but don't want
diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp
index 78f45dfe5b..5f17a2bdd0 100644
--- a/src/gui/widgets/qdialogbuttonbox.cpp
+++ b/src/gui/widgets/qdialogbuttonbox.cpp
@@ -1229,7 +1229,7 @@ bool QDialogButtonBox::event(QEvent *event)
break;
}
- foreach (QPushButton *pb, qFindChildren<QPushButton *>(dialog ? dialog : this)) {
+ foreach (QPushButton *pb, (dialog ? dialog : this)->findChildren<QPushButton *>()) {
if (pb->isDefault() && pb != firstAcceptButton) {
hasDefault = true;
break;
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index c5ce414654..4714d2f2c9 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -1072,7 +1072,7 @@ void QLabel::paintEvent(QPaintEvent *)
else
#endif
if (d->isTextLabel) {
- QRectF lr = d->layoutRect();
+ QRectF lr = d->layoutRect().toAlignedRect();
QStyleOption opt;
opt.initFrom(this);
#ifndef QT_NO_STYLE_STYLESHEET
diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp
index 0da4f6aa63..062bb61385 100644
--- a/src/gui/widgets/qlinecontrol.cpp
+++ b/src/gui/widgets/qlinecontrol.cpp
@@ -112,7 +112,7 @@ void QLineControl::updateDisplayText(bool forceUpdate)
Copies the currently selected text into the clipboard using the given
\a mode.
-
+
\note If the echo mode is set to a mode other than Normal then copy
will not work. This is to prevent using copy as a method of bypassing
password features of the line control.
@@ -486,7 +486,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event)
/*!
\internal
- Draws the display text for the line control using the given
+ Draws the display text for the line control using the given
\a painter, \a clip, and \a offset. Which aspects of the display text
are drawn is specified by the given \a flags.
diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h
index 3147b88575..636cee7bb0 100644
--- a/src/gui/widgets/qlineedit.h
+++ b/src/gui/widgets/qlineedit.h
@@ -283,6 +283,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool))
#endif
Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged())
+ Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &))
};
#endif // QT_NO_LINEEDIT
diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp
index d1eb71fe79..23ac61384f 100644
--- a/src/gui/widgets/qlineedit_p.cpp
+++ b/src/gui/widgets/qlineedit_p.cpp
@@ -59,6 +59,13 @@ QT_BEGIN_NAMESPACE
const int QLineEditPrivate::verticalMargin(1);
const int QLineEditPrivate::horizontalMargin(2);
+QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const
+{
+ QRect cr = adjustedContentsRect();
+ int cix = cr.x() - hscroll + horizontalMargin;
+ return rect.translated(QPoint(cix, vscroll));
+}
+
int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
{
QRect cr = adjustedContentsRect();
@@ -68,11 +75,7 @@ int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const
QRect QLineEditPrivate::cursorRect() const
{
- QRect cr = adjustedContentsRect();
- int cix = cr.x() - hscroll + horizontalMargin;
- QRect crect = control->cursorRect();
- crect.moveTo(crect.topLeft() + QPoint(cix, vscroll));
- return crect;
+ return adjustedControlRect(control->cursorRect());
}
#ifndef QT_NO_COMPLETER
@@ -141,6 +144,11 @@ void QLineEditPrivate::_q_selectionChanged()
emit q->selectionChanged();
}
+void QLineEditPrivate::_q_updateNeeded(const QRect &rect)
+{
+ q_func()->update(adjustedControlRect(rect));
+}
+
void QLineEditPrivate::init(const QString& txt)
{
Q_Q(QLineEdit);
@@ -176,7 +184,7 @@ void QLineEditPrivate::init(const QString& txt)
q, SLOT(update()));
QObject::connect(control, SIGNAL(updateNeeded(QRect)),
- q, SLOT(update()));
+ q, SLOT(_q_updateNeeded(QRect)));
QStyleOptionFrameV2 opt;
q->initStyleOption(&opt);
@@ -216,9 +224,8 @@ void QLineEditPrivate::setCursorVisible(bool visible)
if ((bool)cursorVisible == visible)
return;
cursorVisible = visible;
- QRect r = cursorRect();
if (control->inputMask().isEmpty())
- q->update(r);
+ q->update(cursorRect());
else
q->update();
}
diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h
index 873190fd27..32f6077438 100644
--- a/src/gui/widgets/qlineedit_p.h
+++ b/src/gui/widgets/qlineedit_p.h
@@ -94,6 +94,8 @@ public:
#endif
void init(const QString&);
+ QRect adjustedControlRect(const QRect &) const;
+
int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const;
QRect cursorRect() const;
void setCursorVisible(bool visible);
@@ -129,6 +131,7 @@ public:
void _q_editFocusChange(bool);
#endif
void _q_selectionChanged();
+ void _q_updateNeeded(const QRect &);
#ifndef QT_NO_COMPLETER
void _q_completionHighlighted(QString);
#endif
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index d8f8e9154b..a786e2f309 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -1516,14 +1516,21 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3)
return;
- // ### Disable the unified toolbar when using anything but the native graphics system.
- // ### Disable when using alien widgets as well
- if (windowSurface() || testAttribute(Qt::WA_NativeWindow) == false)
+ // ### Disable when using alien widgets
+ if (testAttribute(Qt::WA_NativeWindow) == false) {
return;
+ }
d->useHIToolBar = set;
createWinId(); // We need the hiview for down below.
+#ifdef QT_MAC_USE_COCOA
+ // Activate the unified toolbar with the raster engine.
+ if (windowSurface()) {
+ d->layout->unifiedSurface = new QUnifiedToolbarSurface(this);
+ }
+#endif // QT_MAC_USE_COCOA
+
d->layout->updateHIToolBarStatus();
// Enabling the unified toolbar clears the opaque size grip setting, update it.
d->macUpdateOpaqueSizeGrip();
@@ -1634,7 +1641,7 @@ QMenu *QMainWindow::createPopupMenu()
Q_D(QMainWindow);
QMenu *menu = 0;
#ifndef QT_NO_DOCKWIDGET
- QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this);
+ QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>();
if (dockwidgets.size()) {
menu = new QMenu(this);
for (int i = 0; i < dockwidgets.size(); ++i) {
@@ -1648,7 +1655,7 @@ QMenu *QMainWindow::createPopupMenu()
}
#endif // QT_NO_DOCKWIDGET
#ifndef QT_NO_TOOLBAR
- QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this);
+ QList<QToolBar *> toolbars = findChildren<QToolBar *>();
if (toolbars.size()) {
if (!menu)
menu = new QMenu(this);
diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm
index 8ba96fb91e..9a23ca76c2 100644
--- a/src/gui/widgets/qmainwindowlayout_mac.mm
+++ b/src/gui/widgets/qmainwindowlayout_mac.mm
@@ -43,6 +43,7 @@
#include <qtoolbar.h>
#include <private/qtoolbarlayout_p.h>
#include <private/qt_cocoa_helpers_mac_p.h>
+#include <private/qtoolbar_p.h>
#ifndef QT_MAC_USE_COCOA
#include <Carbon/Carbon.h>
@@ -408,6 +409,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar
beforeIndex = qtoolbarsInUnifiedToolbarList.size();
int toolbarIndex = qtoolbarsInUnifiedToolbarList.indexOf(toolbar);
+
#ifndef QT_MAC_USE_COCOA
HIToolbarRef macToolbar = NULL;
if ((GetWindowToolbar(window, &macToolbar) == noErr) && !macToolbar) {
@@ -444,6 +446,18 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar
#endif
}
qtoolbarsInUnifiedToolbarList.insert(beforeIndex, toolbar);
+
+ // Adding to the unified toolbar surface for the raster engine.
+ if (layoutState.mainWindow->windowSurface()) {
+ QPoint offset(0, 0);
+ for (int i = 0; i < beforeIndex; ++i) {
+ offset.setX(offset.x() + qtoolbarsInUnifiedToolbarList.at(i)->size().width());
+ }
+#ifdef QT_MAC_USE_COCOA
+ unifiedSurface->insertToolbar(toolbar, offset);
+#endif // QT_MAC_USE_COCOA
+ }
+
#ifndef QT_MAC_USE_COCOA
QCFType<HIToolbarItemRef> outItem;
const QObject *stupidArray[] = { toolbar, this };
@@ -460,6 +474,19 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar
#endif
}
+#ifdef QT_MAC_USE_COCOA
+void QMainWindowLayout::updateUnifiedToolbarOffset()
+{
+ QPoint offset(0, 0);
+
+ for (int i = 1; i < qtoolbarsInUnifiedToolbarList.length(); ++i) {
+ offset.setX(offset.x() + qtoolbarsInUnifiedToolbarList.at(i - 1)->size().width());
+ qtoolbarsInUnifiedToolbarList.at(i)->d_func()->toolbar_offset = offset;
+ }
+}
+#endif // QT_MAC_USE_COCOA
+
+
void QMainWindowLayout::removeFromMacToolbar(QToolBar *toolbar)
{
QHash<void *, QToolBar *>::iterator it = unifiedToolbarHash.begin();
@@ -533,11 +560,11 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const
QMacCocoaAutoReleasePool pool;
QWidgetItem layoutItem(tb);
QSize size = layoutItem.maximumSize();
- NSSize nssize = NSMakeSize(size.width(), size.height() - 2);
+ NSSize nssize = NSMakeSize(size.width(), size.height());
[item setMaxSize:nssize];
size = layoutItem.minimumSize();
nssize.width = size.width();
- nssize.height = size.height() - 2;
+ nssize.height = size.height();
[item setMinSize:nssize];
}
#else
diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h
index 489e913cd1..2a444325c3 100644
--- a/src/gui/widgets/qmainwindowlayout_p.h
+++ b/src/gui/widgets/qmainwindowlayout_p.h
@@ -85,7 +85,11 @@ typedef HIObjectRef HIToolbarItemRef;
typedef const void * CFTypeRef;
typedef const struct __CFString * CFStringRef;
-#endif
+# ifdef QT_MAC_USE_COCOA
+#include <private/qunifiedtoolbarsurface_mac_p.h>
+# endif // QT_MAC_USE_COCOA
+
+#endif // Q_WS_MAC
QT_BEGIN_NAMESPACE
@@ -338,7 +342,13 @@ public:
bool activateUnifiedToolbarAfterFullScreen;
void syncUnifiedToolbarVisibility();
bool blockVisiblityCheck;
-#endif
+
+#ifdef QT_MAC_USE_COCOA
+ QUnifiedToolbarSurface *unifiedSurface;
+ void updateUnifiedToolbarOffset();
+#endif // QT_MAC_USE_COCOA
+
+#endif // Q_WS_MAC
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp
index 58d28f6e79..6f2b67608c 100644
--- a/src/gui/widgets/qmdisubwindow.cpp
+++ b/src/gui/widgets/qmdisubwindow.cpp
@@ -2203,7 +2203,7 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
void QMdiSubWindowPrivate::setSizeGripVisible(bool visible) const
{
// See if we can find any size grips
- QList<QSizeGrip *> sizeGrips = qFindChildren<QSizeGrip *>(q_func());
+ QList<QSizeGrip *> sizeGrips = q_func()->findChildren<QSizeGrip *>();
foreach (QSizeGrip *grip, sizeGrips)
grip->setVisible(visible);
}
@@ -2319,7 +2319,7 @@ void QMdiSubWindow::setWidget(QWidget *widget)
widget->setParent(this);
#ifndef QT_NO_SIZEGRIP
- QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(widget);
+ QSizeGrip *sizeGrip = widget->findChild<QSizeGrip *>();
if (sizeGrip)
sizeGrip->installEventFilter(this);
if (d->sizeGrip)
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 9a6d24c9d9..c09b5a4c72 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -2809,7 +2809,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e)
if (d->sloppyRegion.contains(e->pos())) {
d->sloppyAction = action;
QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6);
- } else {
+ } else if (action != d->currentAction) {
d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this));
}
}
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index f8f263779f..daac91632a 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -51,6 +51,10 @@
#include <QtGui/qpixmap.h>
#endif
+#ifdef Q_WS_WINCE
+#include <windef.h> // for HMENU
+#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index ad3ca8116d..2977558a75 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -1254,15 +1254,11 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
NSString *keySequenceToKeyEqivalent(const QKeySequence &accel)
{
quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL));
- extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp
- QChar keyEquiv = qt_macSymbolForQtKey(accel_key);
- if (keyEquiv.isNull()) {
- if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15)
- keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey;
- else
- keyEquiv = unichar(QChar(accel_key).toLower().unicode());
- }
- return [NSString stringWithCharacters:&keyEquiv.unicode() length:1];
+ extern QChar qtKey2CocoaKey(Qt::Key key);
+ QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key));
+ if (cocoa_key.isNull())
+ cocoa_key = QChar(accel_key).toLower().unicode();
+ return [NSString stringWithCharacters:&cocoa_key.unicode() length:1];
}
// return the cocoa modifier mask for the QKeySequence (currently only looks at the first one).
@@ -2052,8 +2048,7 @@ bool QMenuBar::macUpdateMenuBar()
{
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
- if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)))
- return QMenuBarPrivate::macUpdateMenuBarImmediatly();
+ qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar));
return true;
#else
return QMenuBarPrivate::macUpdateMenuBarImmediatly();
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
index f9c5d82e49..d614bb8a77 100644
--- a/src/gui/widgets/qmenu_symbian.cpp
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -264,7 +264,8 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id)
// However if we don't have any items, we still need the item array. Otherwise
// menupane will crash. That's why we create item array here manually, and
// AddMenuItemL will then use the existing array.
- CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray);
+ CEikMenuPane::CItemArray* itemArray = new CEikMenuPane::CItemArray;
+ Q_CHECK_PTR(itemArray);
menuPane->SetItemArray(itemArray);
menuPane->SetItemArrayOwnedExternally(EFalse);
diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp
index d2bc7aa389..86a78ad50a 100644
--- a/src/gui/widgets/qmenu_wince.cpp
+++ b/src/gui/widgets/qmenu_wince.cpp
@@ -113,8 +113,6 @@ static void resolveAygLibs()
if (!aygResolved) {
aygResolved = true;
QLibrary aygLib(QLatin1String("aygshell"));
- if (!aygLib.load())
- return;
ptrCreateMenuBar = (AygCreateMenuBar) aygLib.resolve("SHCreateMenuBar");
ptrEnableSoftKey = (AygEnableSoftKey) aygLib.resolve("SHEnableSoftkey");
}
diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp
index 6af5de4c7a..bb13017dbc 100644
--- a/src/gui/widgets/qradiobutton.cpp
+++ b/src/gui/widgets/qradiobutton.cpp
@@ -207,6 +207,14 @@ QSize QRadioButton::sizeHint() const
/*!
\reimp
*/
+QSize QRadioButton::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+/*!
+ \reimp
+*/
bool QRadioButton::hitButton(const QPoint &pos) const
{
QStyleOptionButton opt;
diff --git a/src/gui/widgets/qradiobutton.h b/src/gui/widgets/qradiobutton.h
index c21ba11e62..b720498897 100644
--- a/src/gui/widgets/qradiobutton.h
+++ b/src/gui/widgets/qradiobutton.h
@@ -62,6 +62,7 @@ public:
explicit QRadioButton(const QString &text, QWidget *parent=0);
QSize sizeHint() const;
+ QSize minimumSizeHint() const;
protected:
bool event(QEvent *e);
diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp
index 266b163889..f2ea1bfe89 100644
--- a/src/gui/widgets/qsizegrip.cpp
+++ b/src/gui/widgets/qsizegrip.cpp
@@ -78,15 +78,6 @@ static QWidget *qt_sizegrip_topLevelWidget(QWidget* w)
return w;
}
-static inline bool hasHeightForWidth(QWidget *widget)
-{
- if (!widget)
- return false;
- if (QLayout *layout = widget->layout())
- return layout->hasHeightForWidth();
- return widget->sizePolicy().hasHeightForWidth();
-}
-
class QSizeGripPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QSizeGrip)
@@ -318,7 +309,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
#ifdef Q_WS_X11
// Use a native X11 sizegrip for "real" top-level windows if supported.
if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE))
- && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) {
+ && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) {
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE);
@@ -340,7 +331,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
}
#endif // Q_WS_X11
#ifdef Q_WS_WIN
- if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) {
+ if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) {
uint orientation = 0;
if (d->atBottom())
orientation = d->atLeft() ? SZ_SIZEBOTTOMLEFT : SZ_SIZEBOTTOMRIGHT;
@@ -429,12 +420,12 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e)
#ifdef Q_WS_X11
if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE))
- && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw))
+ && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth())
return;
#endif
#ifdef Q_WS_WIN
if (tlw->isWindow() && GetSystemMenu(tlw->winId(), FALSE) != 0 && internalWinId()
- && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) {
+ && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) {
MSG msg;
while(PeekMessage(&msg, winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
return;
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 02a4cc2b30..22fd2a9cc4 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -697,6 +697,9 @@ void QDoubleSpinBox::setSuffix(const QString &suffix)
d->suffix = suffix;
d->updateEdit();
+
+ d->cachedSizeHint = QSize();
+ updateGeometry();
}
/*!
diff --git a/src/gui/widgets/qsplashscreen.cpp b/src/gui/widgets/qsplashscreen.cpp
index a70e361429..75280cb54f 100644
--- a/src/gui/widgets/qsplashscreen.cpp
+++ b/src/gui/widgets/qsplashscreen.cpp
@@ -64,7 +64,6 @@ public:
int currAlign;
inline QSplashScreenPrivate();
- void drawContents();
};
/*!
@@ -121,10 +120,9 @@ public:
perhaps Qt::WindowStaysOnTopHint.
*/
QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f)
- : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | f)
+ : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | Qt::FramelessWindowHint | f)
{
- d_func()->pixmap = pixmap;
- setPixmap(d_func()->pixmap); // Does an implicit repaint
+ setPixmap(pixmap); // Does an implicit repaint
}
/*!
@@ -165,7 +163,6 @@ void QSplashScreen::mousePressEvent(QMouseEvent *)
*/
void QSplashScreen::repaint()
{
- d_func()->drawContents();
QWidget::repaint();
QApplication::flush();
}
@@ -241,23 +238,13 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap)
{
Q_D(QSplashScreen);
- if (pixmap.hasAlpha()) {
- QPixmap opaque(pixmap.size());
- QPainter p(&opaque);
- p.fillRect(0, 0, pixmap.width(), pixmap.height(), palette().background());
- p.drawPixmap(0, 0, pixmap);
- p.end();
- d->pixmap = opaque;
- } else {
- d->pixmap = pixmap;
- }
+ d->pixmap = pixmap;
+ setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
- QRect r(0, 0, d->pixmap.size().width(), d->pixmap.size().height());
- resize(d->pixmap.size());
+ QRect r(QPoint(), d->pixmap.size());
+ resize(r.size());
move(QApplication::desktop()->screenGeometry().center() - r.center());
- if (!isVisible())
- d->drawContents();
- else
+ if (isVisible())
repaint();
}
@@ -271,23 +258,6 @@ const QPixmap QSplashScreen::pixmap() const
}
/*!
- \internal
-*/
-void QSplashScreenPrivate::drawContents()
-{
- Q_Q(QSplashScreen);
- QPixmap textPix = pixmap;
- if (!textPix.isNull()) {
- QPainter painter(&textPix);
- painter.initFrom(q);
- q->drawContents(&painter);
- QPalette p = q->palette();
- p.setBrush(q->backgroundRole(), QBrush(textPix));
- q->setPalette(p);
- }
-}
-
-/*!
\internal
*/
inline QSplashScreenPrivate::QSplashScreenPrivate() : currAlign(Qt::AlignLeft)
@@ -304,8 +274,7 @@ void QSplashScreen::drawContents(QPainter *painter)
{
Q_D(QSplashScreen);
painter->setPen(d->currColor);
- QRect r = rect();
- r.setRect(r.x() + 5, r.y() + 5, r.width() - 10, r.height() - 10);
+ QRect r = rect().adjusted(5, 5, -5, -5);
if (Qt::mightBeRichText(d->currStatus)) {
QTextDocument doc;
#ifdef QT_NO_TEXTHTMLPARSER
@@ -346,6 +315,13 @@ void QSplashScreen::drawContents(QPainter *painter)
/*! \reimp */
bool QSplashScreen::event(QEvent *e)
{
+ if (e->type() == QEvent::Paint) {
+ Q_D(QSplashScreen);
+ QPainter painter(this);
+ if (!d->pixmap.isNull())
+ painter.drawPixmap(QPoint(), d->pixmap);
+ drawContents(&painter);
+ }
return QWidget::event(e);
}
diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp
index 62822ab9ae..a1c225bad4 100644
--- a/src/gui/widgets/qstackedwidget.cpp
+++ b/src/gui/widgets/qstackedwidget.cpp
@@ -49,12 +49,54 @@
QT_BEGIN_NAMESPACE
+/**
+ QStackedLayout does not support height for width (simply because it does not reimplement
+ heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking
+ binary compatibility. (QLayout is subject to multiple inheritance).
+ However, we can fix QStackedWidget by simply using a modified version of QStackedLayout
+ that reimplements the hfw-related functions:
+ */
+class QStackedLayoutHFW : public QStackedLayout
+{
+public:
+ QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {}
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
+};
+
+bool QStackedLayoutHFW::hasHeightForWidth() const
+{
+ const int n = count();
+
+ for (int i = 0; i < n; ++i) {
+ if (QLayoutItem *item = itemAt(i)) {
+ if (item->hasHeightForWidth())
+ return true;
+ }
+ }
+ return false;
+}
+
+int QStackedLayoutHFW::heightForWidth(int width) const
+{
+ const int n = count();
+
+ int hfw = 0;
+ for (int i = 0; i < n; ++i) {
+ if (QLayoutItem *item = itemAt(i)) {
+ hfw = qMax(hfw, item->heightForWidth(width));
+ }
+ }
+ return hfw;
+}
+
+
class QStackedWidgetPrivate : public QFramePrivate
{
Q_DECLARE_PUBLIC(QStackedWidget)
public:
QStackedWidgetPrivate():layout(0){}
- QStackedLayout *layout;
+ QStackedLayoutHFW *layout;
bool blockChildAdd;
};
@@ -138,7 +180,7 @@ QStackedWidget::QStackedWidget(QWidget *parent)
: QFrame(*new QStackedWidgetPrivate, parent)
{
Q_D(QStackedWidget);
- d->layout = new QStackedLayout(this);
+ d->layout = new QStackedLayoutHFW(this);
connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int)));
connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int)));
}
diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp
index 32337724eb..c5d0892122 100644
--- a/src/gui/widgets/qtabbar.cpp
+++ b/src/gui/widgets/qtabbar.cpp
@@ -1292,6 +1292,8 @@ QSize QTabBar::sizeHint() const
QSize QTabBar::minimumSizeHint() const
{
Q_D(const QTabBar);
+ if (d->layoutDirty)
+ const_cast<QTabBarPrivate*>(d)->layoutTabs();
if (!d->useScrollButtons) {
QRect r;
for (int i = 0; i < d->tabList.count(); ++i)
@@ -1304,22 +1306,23 @@ QSize QTabBar::minimumSizeHint() const
return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height());
}
+// Compute the most-elided possible text, for minimumSizeHint
static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
{
- if (text.length() <= 7)
+ if (text.length() <= 3)
return text;
static const QLatin1String Ellipses("...");
QString ret;
switch (mode) {
case Qt::ElideRight:
- ret = text.left(4) + Ellipses;
+ ret = text.left(2) + Ellipses;
break;
case Qt::ElideMiddle:
- ret = text.left(2) + Ellipses + text.right(2);
+ ret = text.left(1) + Ellipses + text.right(1);
break;
case Qt::ElideLeft:
- ret = Ellipses + text.right(4);
+ ret = Ellipses + text.right(2);
break;
case Qt::ElideNone:
ret = text;
@@ -1966,7 +1969,7 @@ void QTabBar::keyPressEvent(QKeyEvent *event)
event->ignore();
return;
}
- int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
+ int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;
d->setCurrentNextEnabledIndex(offset);
}
diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp
index b7bc30fe58..c296b77370 100644
--- a/src/gui/widgets/qtabwidget.cpp
+++ b/src/gui/widgets/qtabwidget.cpp
@@ -195,6 +195,7 @@ public:
void _q_removeTab(int);
void _q_tabMoved(int from, int to);
void init();
+ bool hasHeightForWidth() const;
QTabBar *tabs;
QStackedWidget *stack;
@@ -246,6 +247,15 @@ void QTabWidgetPrivate::init()
}
+bool QTabWidgetPrivate::hasHeightForWidth() const
+{
+ bool has = size_policy.hasHeightForWidth();
+ if (!has && stack)
+ has = qt_widget_private(stack)->hasHeightForWidth();
+ return has;
+}
+
+
/*!
Initialize \a option with the values from this QTabWidget. This method is useful
for subclasses when they need a QStyleOptionTabWidgetFrame, but don't want to fill
@@ -816,8 +826,8 @@ QSize QTabWidget::sizeHint() const
{
Q_D(const QTabWidget);
QSize lc(0, 0), rc(0, 0);
- QStyleOption opt(0);
- opt.init(this);
+ QStyleOptionTabWidgetFrameV2 opt;
+ initStyleOption(&opt);
opt.state = QStyle::State_None;
if (d->leftCornerWidget)
@@ -865,14 +875,58 @@ QSize QTabWidget::minimumSizeHint() const
QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t);
- QStyleOption opt(0);
- opt.rect = rect();
+ QStyleOptionTabWidgetFrameV2 opt;
+ initStyleOption(&opt);
opt.palette = palette();
opt.state = QStyle::State_None;
return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this)
.expandedTo(QApplication::globalStrut());
}
+/*
+ \reimp
+*/
+int QTabWidget::heightForWidth(int width) const
+{
+ Q_D(const QTabWidget);
+ QStyleOptionTabWidgetFrameV2 opt;
+ initStyleOption(&opt);
+ opt.state = QStyle::State_None;
+
+ QSize zero(0,0);
+ const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this)
+ .expandedTo(QApplication::globalStrut());
+
+ QSize lc(0, 0), rc(0, 0);
+ if (d->leftCornerWidget)
+ lc = d->leftCornerWidget->sizeHint();
+ if(d->rightCornerWidget)
+ rc = d->rightCornerWidget->sizeHint();
+ if (!d->dirty) {
+ QTabWidget *that = (QTabWidget*)this;
+ that->setUpLayout(true);
+ }
+ QSize t(d->tabs->sizeHint());
+
+ if(usesScrollButtons())
+ t = t.boundedTo(QSize(200,200));
+ else
+ t = t.boundedTo(QApplication::desktop()->size());
+
+ const bool tabIsHorizontal = (d->pos == North || d->pos == South);
+ const int contentsWidth = width - padding.width();
+ int stackWidth = contentsWidth;
+ if (!tabIsHorizontal)
+ stackWidth -= qMax(t.width(), qMax(lc.width(), rc.width()));
+
+ int stackHeight = d->stack->heightForWidth(stackWidth);
+ QSize s(stackWidth, stackHeight);
+
+ QSize contentSize = basicSize(tabIsHorizontal, lc, rc, s, t);
+ return (contentSize + padding).expandedTo(QApplication::globalStrut()).height();
+}
+
+
/*!
\reimp
*/
diff --git a/src/gui/widgets/qtabwidget.h b/src/gui/widgets/qtabwidget.h
index cabb78db39..b0e6fb3891 100644
--- a/src/gui/widgets/qtabwidget.h
+++ b/src/gui/widgets/qtabwidget.h
@@ -129,6 +129,7 @@ public:
QSize sizeHint() const;
QSize minimumSizeHint() const;
+ int heightForWidth(int width) const;
void setCornerWidget(QWidget * w, Qt::Corner corner = Qt::TopRightCorner);
QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp
index 8f64e20102..2c9f15cfd9 100644
--- a/src/gui/widgets/qtoolbutton.cpp
+++ b/src/gui/widgets/qtoolbutton.cpp
@@ -394,9 +394,6 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const
option->toolButtonStyle = Qt::ToolButtonTextOnly;
else if (option->toolButtonStyle != Qt::ToolButtonTextOnly)
option->toolButtonStyle = Qt::ToolButtonIconOnly;
- } else {
- if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly)
- option->toolButtonStyle = Qt::ToolButtonIconOnly;
}
option->pos = pos();
diff --git a/src/gui/widgets/qvalidator.h b/src/gui/widgets/qvalidator.h
index 6627062b27..5a0162afd5 100644
--- a/src/gui/widgets/qvalidator.h
+++ b/src/gui/widgets/qvalidator.h
@@ -101,7 +101,7 @@ class Q_GUI_EXPORT QIntValidator : public QValidator
public:
explicit QIntValidator(QObject * parent = 0);
- QIntValidator(int bottom, int top, QObject * parent);
+ QIntValidator(int bottom, int top, QObject *parent = 0);
~QIntValidator();
QValidator::State validate(QString &, int &) const;
@@ -142,7 +142,7 @@ class Q_GUI_EXPORT QDoubleValidator : public QValidator
public:
explicit QDoubleValidator(QObject * parent = 0);
- QDoubleValidator(double bottom, double top, int decimals, QObject * parent);
+ QDoubleValidator(double bottom, double top, int decimals, QObject *parent = 0);
~QDoubleValidator();
enum Notation {
@@ -186,7 +186,7 @@ class Q_GUI_EXPORT QRegExpValidator : public QValidator
public:
explicit QRegExpValidator(QObject *parent = 0);
- QRegExpValidator(const QRegExp& rx, QObject *parent);
+ QRegExpValidator(const QRegExp& rx, QObject *parent = 0);
~QRegExpValidator();
virtual QValidator::State validate(QString& input, int& pos) const;
diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp
index 5c37ccd905..bf50d07947 100644
--- a/src/gui/widgets/qworkspace.cpp
+++ b/src/gui/widgets/qworkspace.cpp
@@ -2923,7 +2923,7 @@ void QWorkspaceChild::setActive(bool b)
iconw->setActive(act);
update();
- QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget);
+ QList<QWidget*> wl = childWidget->findChildren<QWidget*>();
if (act) {
for (int i = 0; i < wl.size(); ++i) {
QWidget *w = wl.at(i);
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 937b8d69ed..669b83830f 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -144,7 +144,7 @@ SOURCES += \
widgets/qplaintextedit.cpp \
widgets/qprintpreviewwidget.cpp
-!embedded:mac {
+!embedded:!qpa:mac {
HEADERS += widgets/qmacnativewidget_mac.h \
widgets/qmaccocoaviewcontainer_mac.h
OBJECTIVE_HEADERS += widgets/qcocoatoolbardelegate_mac_p.h \