mirror of
https://github.com/sol1/rustguac.git
synced 2026-09-10 01:26:06 +00:00
patches: add 005-rdp-resize-dirty-flush (RDP resize black regions)
Addresses #118. After a dynamic RDP resize, guac_rdp_gdi_desktop_resize() resized the GDI buffer and display layer but never marked the layer dirty, so close_raw() flushed nothing and newly-exposed/stale regions rendered as solid black until something else repainted them. The patch marks the whole layer dirty and issues a RefreshRect for the new desktop area after the resize. Root cause diagnosed and fix supplied by @Bails309 on the issue; reworked here without the downstream debug logging and scoped to the resize function only (the end-paint handler shares the same close_raw call and must not be touched). Fixes the legacy bitmap path (rustguac's default, enable_gfx=false). The RDPGFX surface cache ignores RefreshRect so GFX sessions aren't addressed, but they have not reproduced the artifact in practice. Verified: applies cleanly via git apply against the pinned guacd 2980cf0; full guacd build with all five patches compiles and links the RDP plugin with no errors (only pre-existing FreeRDP deprecation warnings).
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
--- a/src/protocols/rdp/gdi.c
|
||||
+++ b/src/protocols/rdp/gdi.c
|
||||
@@ -188,6 +188,28 @@
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Server resized display to %ix%i",
|
||||
gdi->width, gdi->height);
|
||||
|
||||
+ /* Mark the entire resized layer dirty so guac_display_layer_close_raw()
|
||||
+ * flushes a full repaint to the client. Without this the dirty rect is
|
||||
+ * empty after a resize, so newly-exposed (or stale) regions of the layer
|
||||
+ * render as solid black until something else happens to repaint them.
|
||||
+ * See sol1/rustguac#118. */
|
||||
+ guac_rect_init(¤t_context->dirty, 0, 0, gdi->width, gdi->height);
|
||||
+
|
||||
+ /* Ask the server to re-send pixels for the full new desktop area. This
|
||||
+ * covers the legacy bitmap update path. The RDPGFX surface cache ignores
|
||||
+ * RefreshRect, so GFX sessions are not fixed by this and need a separate
|
||||
+ * approach. */
|
||||
+ if (context->update != NULL && context->update->RefreshRect != NULL
|
||||
+ && gdi->width > 0 && gdi->height > 0
|
||||
+ && gdi->width <= UINT16_MAX && gdi->height <= UINT16_MAX) {
|
||||
+ RECTANGLE_16 area;
|
||||
+ area.left = 0;
|
||||
+ area.top = 0;
|
||||
+ area.right = (UINT16) gdi->width;
|
||||
+ area.bottom = (UINT16) gdi->height;
|
||||
+ context->update->RefreshRect(context, 1, &area);
|
||||
+ }
|
||||
+
|
||||
guac_display_layer_close_raw(default_layer, current_context);
|
||||
|
||||
return retval;
|
||||
@@ -90,6 +90,32 @@ This approach avoids the socket contention issue that occurred when H.264 was se
|
||||
|
||||
**Requires:** RDP server with H.264 support (xrdp with x264, or Windows with AVC hardware encoder). Browser must support WebCodecs VideoDecoder (Chrome/Edge 94+, Firefox 130+).
|
||||
|
||||
## 005-rdp-resize-dirty-flush.patch
|
||||
|
||||
**Problem:** After a dynamic RDP display resize (browser window resized,
|
||||
`resize-method=display-update`), regions of the desktop render as solid black
|
||||
until something repaints them. `guac_rdp_gdi_desktop_resize()` resizes the
|
||||
FreeRDP GDI buffer and the guac display layer but never marks the layer dirty,
|
||||
so `guac_display_layer_close_raw()` flushes nothing and the client keeps its
|
||||
stale/blank canvas for the resized layer. See [sol1/rustguac#118](https://github.com/sol1/rustguac/issues/118) (reported by @Bails309, who diagnosed the root cause and supplied the fix).
|
||||
|
||||
**Fix:** In `guac_rdp_gdi_desktop_resize()`, after the layer resize and before
|
||||
`guac_display_layer_close_raw()`:
|
||||
|
||||
1. Mark the entire layer dirty (`guac_rect_init(¤t_context->dirty, ...)`) so a full repaint is flushed to the client.
|
||||
2. Issue a `RefreshRect` for the full new desktop so the server re-sends authoritative pixels (legacy bitmap update path).
|
||||
|
||||
**Scope:** Fixes the legacy bitmap update path, which is rustguac's default
|
||||
(`enable_gfx` defaults to false). The RDPGFX surface cache ignores
|
||||
`RefreshRect`, so GFX sessions are not addressed by this patch; in practice
|
||||
GFX sessions have not reproduced the artifact.
|
||||
|
||||
**Files patched:**
|
||||
|
||||
| File | Fix |
|
||||
|------|-----|
|
||||
| `src/protocols/rdp/gdi.c` | Mark layer dirty + `RefreshRect` after resize in `guac_rdp_gdi_desktop_resize()` |
|
||||
|
||||
## Applying patches
|
||||
|
||||
Patches are applied automatically by all build scripts (`build-deb.sh`, `build-rpm.sh`, `install.sh`, `dev.sh`, `Dockerfile`). To apply manually:
|
||||
|
||||
Reference in New Issue
Block a user