Repository navigation
fix(linux): gates de plataforma y cálculo del arrastre en Wayland (#168) - #169
Conversation
…ressions (egdev6#107) Quorb v0.7.0 introduced multiplatform improvements (egdev6#143, egdev6#148, egdev6#154) that inadvertently broke Linux/Wayland due to differences in desktop protocols and WebKitGTK: - Window transparency: `noRedirectionBitmap: true` in tauri.conf.json bypassed compositing redirection buffers, rendering the widget as an opaque black box on Wayland compositors (KDE KWin, Mutter). - Widget disappearing / flickering: Windows DWM recovery loop (egdev6#148) queried `outerPosition()`, which Wayland xdg-shell intentionally reports as (0, 0), causing infinite repositioning loops. Guarded with `/Windows/.test(navigator.userAgent)`. - Premature popup closing: Detail presence polling (egdev6#154) queried `cursorPosition()`, which on Linux/GTK returns (0, 0) instead of throwing. Comparing (0, 0) against window geometry triggered immediate close timers every 400ms. Guarded with `/Macintosh/.test(navigator.userAgent)`. - Drag movement freeze: Drag start now initializes synchronously from `widgetBounds.current` and calculates move deltas from pointer offsets, avoiding freezes when window coordinates report (0, 0). - Hover ergonomics: Raised `OPEN_DELAY` from 90ms to 350ms to prevent accidental triggers, and enabled direct click-to-open/toggle on provider gauges.
egdev6
left a comment
There was a problem hiding this comment.
¡Gran trabajo de verificación en Plasma 6, @Rafaeldelinares! Los puntos 2 (gate de recovery a Windows) y 3 (gate del muestreo de presencia a macOS) están perfectos y encajan exactamente con lo acordado en #168 y con el fix de hover de #164. Pido cambios por lo siguiente:
1. No elimines noRedirectionBitmap globalmente — riesgo de regresión en Windows ⛔
Esa opción es solo de Windows (Tauri la documenta «on Windows») y se añadió deliberadamente en #143 para DirectComposition. En Linux se ignora, así que no puede ser lo que arregló tu caja negra — lo más probable es que el arreglo real sean tus cambios de CSS (#root transparent). Eliminarla de la base puede reintroducir los artefactos de Windows. Propuesta: muévela a un nuevo src-tauri/tauri.windows.conf.json (Tauri v2 hace merge de configs por plataforma) y deja la base limpia para Linux.
2. CSS: los cambios de selectores [data-auto-hide] quedan fuera de alcance
En styles.css los estados data-reveal (hidden/preparing/closing/…) ahora solo aplican con data-auto-hide. Eso cambia el comportamiento de ocultación cuando auto-hide está desactivado en cualquier plataforma, y no es necesario para el fix de Wayland. Justifícalo o sepáralo; el refactor :is(...) por sí solo sería bienvenido en otro PR.
3. OPEN_DELAY 350 ms global y toggle por clic — sin acuerdo de producto
Como comenté en #168, penaliza a Windows/macOS donde 90 ms funciona (y #164 ya mitiga las aperturas accidentales). Ámbito por plataforma o reviértelo; el toggle por clic es un cambio de UX multiplataforma que debería ir en issue propia con su decisión.
4. Rebase sobre main — la CI de Windows ya falla ⛔
El PR parte de un main anterior a #163 (i18n): falla el gate scripts/i18n-inventory.mjs --check y tu recuento de tests (628) no es el actual (main lleva 657 en vitest). Fusiona main, regenera docs/i18n-inventory.md (node scripts/i18n-inventory.mjs --out docs/i18n-inventory.md) y vuelve a pasar la suite completa.
5. Arrastre (0,0) ✓ con nota
La heurística funciona porque widgetBounds.current es la verdad incluso en el caso legítimo (0,0) — pero documenta en el código que depende de ello, y deja constancia en el PR de la validación en GNOME además de KWin (el posicionamiento por setPosition varía por compositor).
Con 1, 2 (resuelto o separado) y 4, y el punto 3 ámbito-correcto, lo apruebo encantado.
Atiende la review de egdev6#169 y los puntos 2–5 acordados en egdev6#168. Integra `main` (ya con egdev6#163) y corrige el diff anterior: - `createWidgetRecovery` (egdev6#148) queda acotado a Windows. En `xdg-shell` el compositor, por diseño, no expone la posición absoluta de una ventana cliente y `outerPosition()` devuelve (0, 0): el ciclo de 5 s concluía que la ventana estaba descolocada y la reubicaba. - El muestreo de presencia (egdev6#154) queda acotado a macOS. El PR asumía que en Wayland `cursorPosition()` fallaría; en WebKitGTK no falla, devuelve (0, 0), así que cada muestra concluía «cursor fuera» y cerraba el panel al instante. Linux vuelve a cerrar por los eventos del DOM. - El asa arrancaba su aritmética por delta desde `outerPosition()`, que en Wayland devuelve (0, 0). Ahora arranca desde `widgetBounds.current`, que es la verdad incluso en el caso legítimo (0, 0) porque lo escribe el propio `setWidgetBounds` que colocó la ventana, no una lectura del compositor. Queda documentado en el código. Al soltar, el imán usa el desplazamiento acumulado cuando el compositor no reporta posición. - `OPEN_DELAY` pasa a 350 ms solo fuera de Windows y macOS. En Linux el barrido del puntero no tiene más red de contención que el temporizador, porque el muestreo nativo es solo de macOS; en Windows y macOS los 90 ms originales se conservan y egdev6#164 ya mitiga la reapertura por foco. El toggle por clic sale del PR y se propone como issue de producto aparte. - `styles.css` declara el fondo transparente también en `#root` y `.dock`. El refactor `:is(...)` y el scoping `data-auto-hide` quedan revertidos: cambiaban la ocultación con auto-ocultar desactivado en cualquier plataforma y son fuera de alcance. `tauri.conf.json` y `ProviderGauge.tsx` vuelven a quedar idénticos a `main`. `noRedirectionBitmap` es opción solo de Windows (en `tao 0.37.1` hay cuatro referencias, todas en `platform_impl/windows/`, y ninguna en `linux/` ni `wayland/`), y no puede trasladarse a `tauri.windows.conf.json`: `tauri-utils` fusiona la config de plataforma con JSON Merge Patch (RFC 7396), que reemplaza los arrays completos, así que un `app.windows` en el override se tragaría la definición entera de la ventana en Windows.
El header graba `git rev-parse HEAD:src`; generado antes del commit, no coincidía con el árbol resultante y el gate de Windows lo rechazaba.
|
@Rafaeldelinares revisé el diff con calma. Veredicto: casi lista — nada bloqueante, y tus cinco puntos de la review anterior están bien atendidos. Lo que está bien resuelto
Sugerencias (ninguna bloqueante)
Sobre los pendientes que planteas
|
…ompat # Conflicts: # docs/i18n-inventory.md
… gates The three inline UA regexes in Widget.tsx (OPEN_DELAY, the DWM recovery audit of egdev6#148, the cursor presence sampling of egdev6#154) are now a single injected-UA helper, and each gate is a named, tested predicate next to the logic it guards. Behaviour is unchanged: the helpers keep the exact predicates they replace, and a regression test pins each one against the legacy regex it replaced. Follows the review of egdev6#169 (suggestions 1 and 2).
Records the two notes the egdev6#169 review asked to keep with the code: the three `!important` that make the transparent widget work under WebKitGTK are the first candidates to remove if the cascade is ever refactored, and a release from a real (0,0) corner takes the delta branch whose only possible deviation is compositor rounding. Regenerates docs/i18n-inventory.md over the merged tree (egdev6#169 review, point 4).
|
@egdev6 Listo: los cuatro puntos están atendidos y la rama ya está sobre Rebase/merge (punto 4 de la review anterior) Merge de Gates locales sobre el head final: 1. Deduplicar los UA sniffs
Los tres puntos de Deliberadamente no toqué tres Detectores que también leen la UA, para no ampliar el alcance:
2. Cobertura de los gates Los dos
Cada uno con su test de equivalencia contra el regex que sustituye. Para ser transparente sobre el alcance de esa cobertura: el repo no tiene harness de component tests (no hay 3. Anotados los tres como primeros candidatos a eliminar si algún día se refactoriza el cascade, con la razón por la que existen (WebKitGTK no respeta la transparencia si 4. Caso borde del arrastre en (0,0) Documentado donde se decide: si el compositor informa Pendientes que dejo como acordados: la validación en GNOME va como seguimiento en #168 (no alargo esta PR), y la caja negra de DMABUF tampoco es de este PR. Lo reenvío a review. Gracias por la paciencia con el mergelog. |
The previous regeneration ran before the commit that changed src/, so the header recorded the previous commit's src tree hash and the gate failed on the Windows job. The file is the only thing this commit changes, so the header stays valid. Verified with core.autocrlf=true to match the Windows checkout.
|
@Rafaeldelinares revisa fallo de tests xf |
|
Gracias por el aviso, @egdev6 — y perdón por el ruido. No era un test roto: era el paso La causa fue mía y de orden. Regeneré Corregido en CI en Dos aclaraciones:
Reviso lo que veas. Gracias por mirarlo. |
|
@Rafaeldelinares he revisado los commits nuevos ( Evaluación de los 5 puntos1. 2. CSS 3. 4. Rebase + i18n — ✅. Merged main, inventario regenerado, 5. Arrastre (0,0) — 🟡 a medias. El código está documentado (origen en caché y rama por delta en 🟡 Observaciones
✅ Verificación reproducida (head
|
| Check | Resultado |
|---|---|
vitest run --dir src |
668 passed (52 suites), incluidos los nuevos gates de os-detect, presence y recovery |
tsc --noEmit |
Limpio |
i18n-inventory --check |
✅ exit 0 |
| Rust propio del PR | Ninguno (diff vacío vs el merge de #172) — solo frontend |
tauri.conf.json |
Intacto ✅ |
Veredicto
Los 5 puntos están atendidos: 4 completamente y el 5 con el código documentado pero sin validación GNOME. Mi recomendación: aprobar dejando la validación GNOME como seguimiento documentado en #168 — el diff es conservador (los gates preservan el comportamiento exacto en Windows/macOS, testeado por equivalencia con los regex legacy) y la validación GNOME solo añadiría confianza sobre setPosition, que el PR ya no presenta como solución universal del protocolo. Con el ajuste de título, listo para merge.
Ref #168
Reinicio el diff como un único commit limpio sobre
mainactual (e781046, ya con #163). Atiende las cinco peticiones de la review y añade un hallazgo sobre la punto 1.El diff ahora
1.
createWidgetRecoveryacotado a Windows (#148)En
xdg-shellel compositor, por diseño, no expone la posición absoluta de una ventana cliente youterPosition()devuelve(0, 0). El ciclo de 5 s concluía que la ventana estaba descolocada y la reubicaba. Windows es el único backend donde DWM desplaza ventanas.2. Muestreo de presencia acotado a macOS (#154)
El PR asumía que en Wayland
cursorPosition()fallaría y «degradaría en silencio». En WebKitGTK no falla: devuelve(0, 0). Cada muestra de 400 ms concluía «cursor fuera» y cerraba el panel al instante. Con el gate, Linux vuelve a cerrar pormouseleave/mouseenterdel DOM, que WebKitGTK soporta bien, y la sincronización dedetailInsideRefqueda también solo-macOS como proponías.3. Cálculo del arrastre corregido
d.startarrancaba solo conouterPosition(), que en Wayland devuelve(0, 0), así que la aritmética por delta quedaba anclada a un origen falso. Ahora arranca desdewidgetBounds.current, que es la verdad incluso en el caso legítimo(0, 0)porque lo escribe el propiosetWidgetBoundsque colocó la ventana, no una lectura del compositor. Queda documentado en el código, y un(0, 0)real solo se descarta cuando ya existe un origen del caché. Al soltar, el imán usa el desplazamiento acumulado cuando el compositor no reporta posición.Este cambio corrige el lado de entrada del gesto. Bajo X11/XWayland, donde el compositor honra
setPosition, permite que la ventana siga al puntero y se acople al borde. Bajo Wayland nativo,setPositiontermina engtk_window_move()y el compositor no permite reposicionar una ventana ya mapeada: el cálculo queda correcto, pero el movimiento sigue sin poder realizarse. Ese lado de salida se trata por separado en #180.4.
OPEN_DELAYpor plataforma350 ms solo fuera de Windows y macOS; allí se conservan los 90 ms originales, con #164 ya mitigando la reapertura por foco. El toggle por clic sale del PR y lo abro como issue de producto aparte.
5.
styles.css#rooty.dockdeclaran fondo transparente explícito en vez de heredarlo dehtml/body. El refactor:is(...)y el scopingdata-auto-hidequedan revertidos: eran fuera de alcance, como señalaste.Sobre
noRedirectionBitmap— no se puede mover atauri.windows.conf.jsonAcepto el diagnóstico: es opción solo de Windows y en Linux la ignora
tao, así que no explica la caja negra. Confirmado entao 0.37.1: cuatro referencias, todas enplatform_impl/windows/, cero enlinux/ywayland/.Pero la mudanza que proponés no es viable como está.
tauri-utilsfusiona la config de plataforma con JSON Merge Patch (RFC 7396), y RFC 7396 reemplaza los arrays completos en vez de fusionarlos elemento a elemento:El widget se construiría sin
width,transparent,decorations,alwaysOnTop,skipTaskbar… Para no perderlos habría que duplicar la definición entera en el override, y añadirtauri.linux.conf.jsonytauri.macos.conf.jsoncon la misma definición menos el flag: tres copias que hay que editar en lockstep cada vez que cambie la ventana.Así que dejo
noRedirectionBitmap: trueen la base y este PR no tocatauri.conf.json. Para la ruta ya existe el patrón que usalib.rs:791con la ventanadetail:Si en algún momento se quiere sacar de la config, la vía sería declarar la ventana
widgeten Rust con el mismo#[cfg], en vez de un override de plataforma.La caja negra: sigue sin resolver y no es de este PR
Confirmo que no la arregla este diff, y que mi atribución inicial era incorrecta. La validación de
WEBKIT_DISABLE_DMABUF_RENDERER=1yGDK_BACKEND=x11en Plasma 6, junto con el alcance actual, queda en #168; la implementación de DMABUF va como PR aparte con detección en el arranque.Verificación
npm test: 52 suites, 668 tests, todos en verde.npm run typecheck: limpio.docs/i18n-inventory.mdregenerado connode scripts/i18n-inventory.mjs --out docs/i18n-inventory.md; el diff son solo números de línea desplazados por los comentarios añadidos, sin texto nuevo.GDK_BACKEND=x11, NVIDIA RTX 3060 Mobile, AppImage36ec800): el segundo gesto desplazó la ventana nativa406×270 pxy al soltar se acopló al borde más cercano. En Wayland nativo, el arrastre no mueve la ventana porque xdg-shell descartagtk_window_move()sobre una ventana mapeada; ese alcance está en bug(linux/wayland): la ventana no se puede posicionar: tira centrada, arrastre y cambio de monitor inoperativos #180. GNOME no se validó.Pendiente de la review anterior
setPositionsobrexdg_toplevello ignoran varios compositores. El fix del cálculo es correcto y queda validado bajo X11; no habilita el movimiento bajo Wayland nativo ni se presenta como solución universal del protocolo.