Keep the stars on screen long enough to click one
The rating strip was a sibling of the cell's TouchArea, declared after it so that hit-testing reached the stars first. That half worked: a star click set a rating without also opening the image. The other half did not. Hover is tracked per TouchArea, and Slint sends `Exit` to any item that drops out of the hit path. The strip taking the pointer is exactly that — `cell-touch` left the path, `has-hover` went false, and `show-empty` went with it. On an unrated cell the stars are drawn *only* on hover, so they vanished as the pointer arrived at them; the click then landed on the cell behind and opened the image. Reported as "the star menu disappears when I click on an image", which is precisely what it does. Nesting the strip inside `cell-touch` keeps both halves. Children are hit-tested before the element containing them, so a star still wins the click and still ends the walk before `cell-clicked` runs. And an ancestor stays on the item stack: it gets no `Exit`, and while a child holds the grab it is handed the event filter and never the event. Hover therefore holds for as long as the pointer is anywhere in the cell.
This commit is contained in:
+51
-30
@@ -1907,37 +1907,58 @@ export component LibraryGrid inherits Rectangle {
|
||||
// is why the toggling is idempotent-by-union in Rust
|
||||
// rather than this file trying to swallow one of them.
|
||||
double-clicked => { root.cell-double-clicked(i); }
|
||||
}
|
||||
|
||||
// --- the rating strip, ABOVE the cell's own hit area ---
|
||||
//
|
||||
// **Declared after `cell-touch` on purpose.** Slint hit-tests
|
||||
// later siblings first, so a strip nested inside the layout
|
||||
// above was underneath the cell-wide TouchArea: the click set
|
||||
// a rating *and* fell through to `cell-clicked`, which threw
|
||||
// the user into develop on every star press. Z-order is the
|
||||
// whole fix — there is no "handled" flag to set, and adding a
|
||||
// travel threshold or a timer would be faking arbitration
|
||||
// Slint already does correctly once the order is right.
|
||||
//
|
||||
// It sits over the foot of the thumbnail rather than below it:
|
||||
// the caption row is spoken for by the filename, and a third
|
||||
// row would cost thumbnail height on every cell to show
|
||||
// something that is usually empty.
|
||||
StarStrip {
|
||||
x: (parent.width - self.width) / 2;
|
||||
// Clear of the caption, which is the cell's last row.
|
||||
y: parent.height - self.height - 26px;
|
||||
rating: cell.rating;
|
||||
// Empty stars appear once the pointer is over the cell,
|
||||
// so there is something to aim at without filling the
|
||||
// grid with chrome. On touch there is no hover, so the
|
||||
// strip is always present where a rating exists — and a
|
||||
// long-press is not needed to discover it.
|
||||
show-empty: cell-touch.has-hover;
|
||||
can-trash: !root.viewing-trash;
|
||||
rate(n) => { root.cell-rated(i, n); }
|
||||
trash() => { root.cell-trashed(i); }
|
||||
// --- the rating strip, INSIDE the cell's hit area ---
|
||||
//
|
||||
// **A child of `cell-touch`, not a sibling of it.** Two
|
||||
// things have to be true at once here, and only this
|
||||
// nesting gets both.
|
||||
//
|
||||
// A star must take the click without it also reaching
|
||||
// `cell-clicked`, or every rating throws the user into
|
||||
// develop. Children are hit-tested before the element
|
||||
// they sit in, and a child that accepts ends the walk
|
||||
// before the TouchArea's own handler runs — so the star
|
||||
// wins, and it wins for the same reason a later sibling
|
||||
// used to.
|
||||
//
|
||||
// And the strip must not vanish as the pointer arrives
|
||||
// at it. As a *sibling* it did: hover is tracked per
|
||||
// TouchArea, Slint sends `Exit` to whatever drops out of
|
||||
// the hit path, and the strip taking the pointer dropped
|
||||
// `cell-touch` out of it. `has-hover` went false, which
|
||||
// took `show-empty` with it, which hid the very stars
|
||||
// the pointer was travelling towards — on an unrated
|
||||
// cell they disappeared, the click landed on the cell
|
||||
// behind them, and the image opened. That is the whole
|
||||
// of the "stars vanish when I click one" report.
|
||||
//
|
||||
// An *ancestor* stays in the path: it keeps its place on
|
||||
// the item stack, gets no `Exit`, and during a grab it is
|
||||
// handed only the filter and never the event. So hover
|
||||
// holds for as long as the pointer is anywhere in the
|
||||
// cell, stars included.
|
||||
//
|
||||
// It sits over the foot of the thumbnail rather than
|
||||
// below it: the caption row is spoken for by the
|
||||
// filename, and a third row would cost thumbnail height
|
||||
// on every cell to show something that is usually empty.
|
||||
StarStrip {
|
||||
x: (parent.width - self.width) / 2;
|
||||
// Clear of the caption, which is the cell's last row.
|
||||
y: parent.height - self.height - 26px;
|
||||
rating: cell.rating;
|
||||
// Empty stars appear once the pointer is over the
|
||||
// cell, so there is something to aim at without
|
||||
// filling the grid with chrome. On touch there is no
|
||||
// hover, so the strip is always present where a
|
||||
// rating exists — and a long-press is not needed to
|
||||
// discover it.
|
||||
show-empty: cell-touch.has-hover;
|
||||
can-trash: !root.viewing-trash;
|
||||
rate(n) => { root.cell-rated(i, n); }
|
||||
trash() => { root.cell-trashed(i); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user