Repository navigation
Conversation
|
They fix different failures of the single-monitor screen frame in the Current master builds that frame in two steps:
For a single monitor all three end at the same frame — the whole One practical overlap: this hunk sits ~40 lines below the |
|
I don't think this code is harmful or wrong as such, and I do think it raises a good/interesting issue, but I think it misses the point: Given that the X system can change screen geometry outside our control, we need a mechanism to handle it, and So when geometry changes, the fact should be detected ASAP, cached screen info cleared (the -resetScreens method), the notification should be sent, and then the app will regenerate screen information. If that mechanism is working the -screenList method is going to be called after the geometry change, so there's really no point trying to handle a geometry change within the -screenList code. If that mechanism is not working, then it seems to me that the correct solution would be to fix it: A slight complicating factor is that we might be caching information at multiple levels. In that case a single global notification is not sufficient because we need to ensure sequencing with each layer clearing cache at its own level before signalling the next higher level. So the question is not why -screenList produced 'bad' output, but why the app didn't get a notification and immediately correct itself for the new geometry? |
|
Thanks — the sequencing principle is exactly right, and it is what we
So the app does correct itself — for the previous transition. By the Our 12-line -screenList normalization (this PR) sidesteps the stale |
|
Following up on the two findings above — we now have the complete causal chain of the ±32 px jump, verified end-to-end with protocol-level tracing (an xtrace proxy on the app's connection), an independent three-connection watcher client, and pointer-level instrumentation of the gui and backend. Every link below is measured, not inferred. 1. Delivery model. The server defers RRScreenChangeNotify per client until that client's next request (protocol behavior, verified with the watcher). The app therefore receives transitions in bursts, often a transition late: in our trace the shrink notification was processed 3 s after the shrink, at the exact moment the grow transition was already applied server-side. 2. Stale RandR resources. On this stack (Xvfb + the dummy driver) the config timestamp is never bumped by mode/fb changes — every ScreenChangeNotify in the trace carried the same configTimestamp. XRRGetScreenResources therefore serves one-transition-stale state, so resetScreens/screenList derive the previous screen size (instrumented: the backend's screen size read 1280x800 while the server was already 1024x768, and 1024x768 while it was back at 1280x800). This is the layer #249's screenList normalization addresses; the RandR event branch needs the same treatment — a fresh read instead of the cached resources. 3. The gui remap race — the final step of the jump. 4. Side finding. The style-probing loops in The fix, split by layer — both parts are up:
Together they take our container harness from a ±32 px jump on every down→up cycle to a stable 1 px rounding difference, across repeated fresh runs and multi-cycle sequences. |
|
Thanks for digging into this so thoroughly. A few thoughts for consideration, mostly about how this composes with #217:
|
RRSetScreenSize (xrandr --fb -- and what streaming/remote-desktop servers use) does not bump the resources config timestamp that XRRGetScreenResources caches on, so crtc_info can serve stale geometry after a live resolution change. Xvfb additionally exposes several outputs with only one connected, so a check on the raw output count inside the loop does not fire. Normalize the frame after the RANDR loop, on the connected-output count, from DisplayWidth/DisplayHeight (already refreshed through XRRUpdateConfiguration when RRScreenChangeNotify arrives). Validated with a pixel-assertion harness (Xvfb+RandR, multi-hop 1280x800 <-> 1680x1050 at GSScaleFactor 2.0, GNUstep Workspace desktop): 13/13 assertions on baseline, after grow-resize and after back-resize, three consecutive runs. Before the fix the desktop window was clamped against the stale 1280-wide screen and ended up at origin.x = -400.
Runs its own Xvfb and re-executes itself for every reading, so each one is what a freshly launched application would see. Covers an fb-only resize (RRSetScreenSize without a mode change, what xrandr --fb and streaming servers issue), the same resize with _NET_WORKAREA published, and a mode change as the control case.
An fb-only resize leaves the CRTC reporting the mode it still drives rather than the X screen, and with no window manager there is no _NET_WORKAREA either: the root geometry is the only authority for the screen. Under a window manager the frame must stay the published work area, which the unconditional form overrode; the new test in Tests/x11 catches both directions.
4bf356d to
c786491
Compare
|
All four points taken, and the third turned out to be the key. I
So the CRTC data is not stale at all — after an fb-only resize it
One observation from writing the test: Xvfb exposes four outputs with |
On X11, the monitor frames in
-screenListare built fromXRRGetScreenResourcesCRTC data. An fb-only resize —RRSetScreenSize,what
xrandr --fband streaming/remote-desktop servers issue on everyviewport change — resizes the framebuffer without touching the CRTC,
which keeps reporting the mode it still drives; the resources config
timestamp does not change either, but the data is not stale: the CRTC
is accurate about the mode. Applications then lay out against a screen
that no longer matches the framebuffer. With GNUstep Workspace as a
streamed desktop (Selkies + Xvfb with RANDR), after
1280x800 -> 1680x1050 -> 1280x800 at GSScaleFactor 2.0 the desktop
window clamps itself against the 1280-wide CRTC and lands at
origin.x = -400, painting a quarter of the display.
When exactly one output is connected and no window manager publishes
_NET_WORKAREA, nothing but the root geometry describes the screen, sothis takes the frame from
DisplayWidth/DisplayHeight(refreshedthrough
XRRUpdateConfigurationwhenRRScreenChangeNotifyarrives)after the RANDR loop. Under a window manager the published work area
keeps governing the frame.
Tests/x11/screenframe.m runs its own Xvfb and checks all three: an
fb-only resize, the same resize with
_NET_WORKAREApublished, and amode change.