Skip to content

Commit e2d6bbd

Browse files
author
Ales Kutsepau
committed
use layers instead of clip on WebAssembly to fix content leaking
1 parent 0881aad commit e2d6bbd

6 files changed

Lines changed: 71 additions & 5 deletions

File tree

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import QtQuick
22
import QtQuick.Controls
33

4+
import EasyApplication.Gui.Globals as EaGlobals
5+
46
SwipeView {
57
//anchors.top: parent.top
68
//anchors.bottom: parent.bottom
79
//anchors.left: parent.left
810
//anchors.right: parent.right
911
//anchors.fill: parent
1012

11-
clip: true
13+
// WebAssembly: a layer instead of clip. See EaGlobals.Vars.isWasm and the
14+
// longer note in SideBar.qml. This is the outermost of the three swipe
15+
// views - the workflow pages - so its texture is the size of the content
16+
// area. If WebAssembly performance suffers, this is the first one to
17+
// reconsider.
18+
clip: !EaGlobals.Vars.isWasm
19+
layer.enabled: EaGlobals.Vars.isWasm
1220
interactive: false
1321
}

src/EasyApplication/Gui/Components/ListView.qml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,19 @@ ListView {
226226
? 2 * EaStyle.Sizes.tableRowHeight
227227
: tableRowHeight * visibleRowCount + _headerHeight
228228

229-
clip: true
229+
// WebAssembly: a layer instead of clip. See EaGlobals.Vars.isWasm.
230+
//
231+
// Both crop to this item's bounds, but a layer renders the subtree into
232+
// its own texture and creates no clip node. On wasm a clip node here is
233+
// lost whenever the scene is rebuilt - a tooltip appearing is enough -
234+
// and this list's border and rows are then drawn outside the group box
235+
// that should be hiding them.
236+
//
237+
// Cost: one texture the size of this list. Its height does not animate,
238+
// so there is no per-frame re-rasterisation.
239+
clip: !EaGlobals.Vars.isWasm
240+
layer.enabled: EaGlobals.Vars.isWasm
241+
230242
headerPositioning: ListView.OverlayHeader
231243
boundsBehavior: Flickable.StopAtBounds
232244
enabled: count > 0

src/EasyApplication/Gui/Components/MainContent.qml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import QtQuick
22
import QtQuick.Controls
33

4+
import EasyApplication.Gui.Globals as EaGlobals
45
import EasyApplication.Gui.Elements as EaElements
56

67
Item {
@@ -27,7 +28,11 @@ Item {
2728
anchors.left: mainAreaContainer.left
2829
anchors.right: mainAreaContainer.right
2930

30-
clip: true
31+
// WebAssembly: a layer instead of clip. See EaGlobals.Vars.isWasm and
32+
// the longer note in SideBar.qml - the same applies to the main
33+
// area's own tabs.
34+
clip: !EaGlobals.Vars.isWasm
35+
layer.enabled: EaGlobals.Vars.isWasm
3136
interactive: false
3237

3338
currentIndex: tabs.currentIndex

src/EasyApplication/Gui/Components/SideBar.qml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import QtQuick
22
import QtQuick.Controls
33
import QtQuick.Controls.Material
44

5+
import EasyApplication.Gui.Globals as EaGlobals
56
import EasyApplication.Gui.Style as EaStyle
67
import EasyApplication.Gui.Elements as EaElements
78

@@ -38,7 +39,19 @@ Item {
3839

3940
anchors.bottomMargin: EaStyle.Sizes.fontPixelSize
4041

41-
clip: true
42+
// WebAssembly: a layer instead of clip. See EaGlobals.Vars.isWasm.
43+
//
44+
// A SwipeView is a ListView, so switching tabs slides its content.
45+
// The pages either side are cropped by this clip, and on wasm a
46+
// clipped item that moves past the edge of an enclosing clip is drawn
47+
// outside it. Switching from Basic to Extra then paints the outgoing
48+
// page over whatever sits beside the sidebar.
49+
//
50+
// A layer crops to the same bounds through a texture, with no clip
51+
// node. Its size does not animate, so nothing is re-rasterised per
52+
// frame.
53+
clip: !EaGlobals.Vars.isWasm
54+
layer.enabled: EaGlobals.Vars.isWasm
4255
interactive: false
4356

4457
currentIndex: tabs.currentIndex

src/EasyApplication/Gui/Components/TableView.qml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,23 @@ ListView {
3030
tableRowHeight * (Math.min(count, maxRowCountShow) + 1 ) :
3131
tableRowHeight * (Math.min(count, maxRowCountShow))
3232

33-
clip: true
33+
// WebAssembly: a layer instead of clip.
34+
//
35+
// Both crop to this item's bounds, but a layer renders the subtree into
36+
// its own texture and never creates a clip node. On wasm a clip node here
37+
// is lost whenever the scene is rebuilt - a tooltip appearing is enough -
38+
// and the table's border and rows are then drawn outside the group box
39+
// that should be hiding them.
40+
//
41+
// Chosen over moving the border out of the list: the list's parent is
42+
// GroupBox's contentItem, which is a Row, so reparenting anything into it
43+
// changes the group's layout.
44+
//
45+
// Cost: one texture the size of this list. Its height does not animate,
46+
// so there is no per-frame re-rasterisation.
47+
clip: !EaGlobals.Vars.isWasm
48+
layer.enabled: EaGlobals.Vars.isWasm
49+
3450
headerPositioning: ListView.OverlayHeader
3551
boundsBehavior: Flickable.StopAtBounds
3652

src/EasyApplication/Gui/Globals/Vars.qml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ import EasyApplication.Gui.Logic as EaLogic
99
QtObject {
1010
id: object
1111

12+
// True when running in a browser through WebAssembly.
13+
//
14+
// Qt for WebAssembly loses a clip when the scene graph is rebuilt, or
15+
// when a clipped item scrolls past the edge of an enclosing clip, and the
16+
// hidden content is then drawn outside its container. Components that
17+
// must crop something use a layer instead of clip when this is true. A
18+
// layer crops to the same bounds but creates no clip node, at the cost of
19+
// one texture.
20+
//
21+
// Desktop is unaffected and keeps plain clipping, which is cheaper.
22+
readonly property bool isWasm: Qt.platform.os === 'wasm'
23+
1224
// Python objects
1325
readonly property bool isTestMode: typeof pyIsTestMode !== "undefined" && pyIsTestMode !== null ?
1426
pyIsTestMode :

0 commit comments

Comments
 (0)