diff --git a/CLAUDE.md b/CLAUDE.md index 6390bf1..4af1904 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -111,8 +111,9 @@ happens. A probe sent to explain a black screen must not be able to cause one. ### The start-page harness -Any change to `Store` or `HomePage` — what gets saved as a visit or favourite, and -the page built from it — is exercised off-device first: +Any change to `Store`, `HomePage` or `StartPage` — what gets saved as a visit or +favourite, the page built from it, and which of the three things the browser opens +at launch — is exercised off-device first: ```sh tools/startpage/run.sh @@ -123,7 +124,10 @@ a row, recording each the way the NUI engine reports it (a `data:` URL carrying page). Issue #53 was that loop with no guard: the start screen recorded itself as a visit on every launch, roughly doubled each time, and after nine launches was past the 2 MB Chromium will load — a black screen with no line anywhere, on a view that -was fine. Needs only the .NET 6 SDK under `~/.dotnet-local`. +was fine. It also holds `StartPage` (issue #79) to the three states, to "where I +left off" landing on the last real visit and never on the start screen, and to an +install made before the mode existed still opening where it always did. Needs only +the .NET 6 SDK under `~/.dotnet-local`. ### The site-rules harness diff --git a/README.md b/README.md index 8bc6473..a57b2ac 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,43 @@ browser simply won't start. Newer sets don't have this restriction. Not every remote sends the colour buttons, and the slim ones have none. **Switch site** is the second row of the menu, so hold OK and it is one press away. +Every digit is spoken for, so these live in the menu only (**hold OK**): + +| Menu row | What it does | +| --- | --- | +| **Keep an address…** | Type a URL and keep *that* as a tile, without going to it | +| **Open where I left off** | Launch straight back into the last page you were on | +| **Forget this site's settings** | Take a site back to your everywhere settings | +| **Pointer style** | Who draws the pointer — Overscan (keeps up) or the page (an arrow) | +| **Ad blocking on/off** | 2025+ package only | + +### Keeping a page you can't land on + +**Keep an address…** in the menu is for URLs that redirect. `https://www.instagram.com/reel` +sends you to one particular reel, so pressing `8` there would save that clip +for ever; type the address instead and the tile is the address. It's prefilled +with wherever you are, so it's usually a matter of deleting the end of it. + +### Where it opens + +By default, the start screen. Two ways to change that: + +- **Open where I left off** in the menu — it launches back into the last page you + were on. +- On the keyboard, **start** makes whatever you typed the fixed opening page. Press + it with nothing typed to go back to the start screen. + +Turning "where I left off" off again returns to your fixed address if you set one, +so you never have to type it twice. + +### The pointer + +On a heavy site the pointer used to slow down, because it was drawn *by the page* +and could only move as fast as the page would let it. Overscan now draws it itself +on the 2025+ package, so it keeps up whatever the site is doing. **Pointer style** +in the menu (key **2** on the older packages) switches back to the page-drawn +arrow, which looks nicer and is only as quick as the page. + ### Each site keeps its own settings Images and identity are remembered **for the site you set them on**. Turn images diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md index dea794b..441b65e 100644 --- a/docs/INTERNALS.md +++ b/docs/INTERNALS.md @@ -1232,6 +1232,55 @@ Details that matter: `input`/`change`, otherwise React-style frameworks ignore it. Enter is sent as real key events, falling back to `form.requestSubmit()`. +### A pointer inside the page moves at the page's speed + +The same reporter again, in #78: "if we load a heavy site cursor start to become +less responsive, when we load light site it is faster, default browser cursor +perform same on all sites." It was ours, not the engine's. + +Everything above describes a pointer that *lives in the page*, and the bill for +that had never been read. Each D-pad step was one script evaluation, and the +script it ran did an `elementFromPoint` and dispatched a `mousemove` — a forced +layout plus whatever the site's own move handlers do, which on Instagram or +Spotify is a great deal. So the pointer could only move as fast as the page's main +thread was willing to run our script, and that thread is the busiest object on the +television. The TV's own browser draws its pointer in the compositor, which is why +his comparison holds and why it always would have. + +Two halves, and neither is sufficient alone: + +- **The app draws the pointer.** DALi views over the web view on NUI, Evas + rectangles on ElmSharp, positioned from the same viewport fraction the script + was being sent. The ElmSharp build has had this behind key `2` since early on + and it was nobody's default; NUI never had it at all, and its old header said an + overlay "would need to track scroll and zoom itself". That was simply wrong — + the position is a fraction of the *viewport*, and the viewport is the view's own + rectangle, which is the entire reason it is kept as a fraction rather than as a + document point. +- **The page hears about it once a tick, not once a key press.** Both builds + already run a 150 ms timer, so a move marks itself pending and the tick flushes + it. A held key that used to be twenty hover updates is now six, and none of them + is in front of the drawing. + +The rule the second half must not break is that **the page and the pointer agree at +the moment of a click**. `PageScript.click()` hit-tests wherever `move()` last left +it, so a click that overtook its own pending move would land where the pointer used +to be. Both builds therefore put the pending move *into the click's own script*, +one evaluation, rather than sending it as a call before — two evaluations are two +chances for that ordering to be wrong, and the failure would be a click that +occasionally hits the wrong thing, which is the worst kind to be sent from a sofa. + +What this costs is up to 150 ms of hover lag behind the drawn pointer, and the +arrow: neither toolkit draws a triangle, so the app-drawn pointer is the ringed dot +the ElmSharp build has always used for its native style, while the page's arrow is +CSS borders. A dot that keeps up beats an arrow that does not, so **NUI defaults to +drawing it itself** and a menu row switches back. **The ElmSharp default is +unchanged**: #78 is a report from a 2025 set, the ewk packages are the ones where a +change cannot be tested before somebody installs it, and `src/nui` not being able +to break them is the whole reason the source is split this way. They get the +coalescing, which is the half that is safe everywhere, and key `2` was already +there for the rest. + ### The one thing a script cannot click: another origin's frame `elementFromPoint` stops at an `