Skip to content

fix(linux): gates de plataforma y cálculo del arrastre en Wayland (#168) - #169

Merged
egdev6 merged 8 commits into
egdev6:mainfrom
Rafaeldelinares:fix/wayland-desktop-compat
Oct 23, 2026
Merged

egdev6 merged 8 commits into
egdev6:mainfrom
Rafaeldelinares:fix/wayland-desktop-compat

Conversation

@Rafaeldelinares

@Rafaeldelinares Rafaeldelinares commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Nota del mantenedor (ajuste de alcance): este PR no resuelve la caja negra de transparencia en Wayland — el hardening de CSS (#root/.dock) transparentes es defensivo. La causa probable sigue en medición (DMABUF/x11, ver #168). Lo que sí resuelve: gates de plataforma para recovery/presence/open-delay, el cálculo del arrastre y las regresiones de hover. El movimiento bajo Wayland nativo sigue bloqueado por el protocolo xdg-shell; ver #180.

Ref #168

Reinicio el diff como un único commit limpio sobre main actual (e781046, ya con #163). Atiende las cinco peticiones de la review y añade un hallazgo sobre la punto 1.

El diff ahora

1. createWidgetRecovery acotado a Windows (#148)
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. 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 por mouseleave/mouseenter del DOM, que WebKitGTK soporta bien, y la sincronización de detailInsideRef queda también solo-macOS como proponías.

3. Cálculo del arrastre corregido
d.start arrancaba solo con outerPosition(), que en Wayland devuelve (0, 0), así que la aritmética por delta quedaba anclada a un origen falso. 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, 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, setPosition termina en gtk_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_DELAY por plataforma
350 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
#root y .dock declaran fondo transparente explícito en vez de heredarlo de html/body. El refactor :is(...) y el scoping data-auto-hide quedan revertidos: eran fuera de alcance, como señalaste.

Sobre noRedirectionBitmap — no se puede mover a tauri.windows.conf.json

Acepto el diagnóstico: es opción solo de Windows y en Linux la ignora tao, así que no explica la caja negra. Confirmado en tao 0.37.1: cuatro referencias, todas en platform_impl/windows/, cero en linux/ y wayland/.

Pero la mudanza que proponés no es viable como está. tauri-utils fusiona la config de plataforma con JSON Merge Patch (RFC 7396), y RFC 7396 reemplaza los arrays completos en vez de fusionarlos elemento a elemento:

tauri.conf.json          →  app.windows = [ { widget, 14 campos } ]
tauri.windows.conf.json  →  app.windows = [ { widget, 1 campo  } ]
resultado en Windows     →  app.windows = [ { widget, 1 campo  } ]

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ñadir tauri.linux.conf.json y tauri.macos.conf.json con 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: true en la base y este PR no toca tauri.conf.json. Para la ruta ya existe el patrón que usa lib.rs:791 con la ventana detail:

#[cfg(target_os = "windows")]
let detail_builder = detail_builder.no_redirection_bitmap(true);

Si en algún momento se quiere sacar de la config, la vía sería declarar la ventana widget en 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=1 y GDK_BACKEND=x11 en 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.md regenerado con node 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.
  • Manual en KDE Plasma 6 con la app ejecutada mediante X11/XWayland (GDK_BACKEND=x11, NVIDIA RTX 3060 Mobile, AppImage 36ec800): el segundo gesto desplazó la ventana nativa 406×270 px y al soltar se acopló al borde más cercano. En Wayland nativo, el arrastre no mueve la ventana porque xdg-shell descarta gtk_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

  • Validación en GNOME: no está hecha. En Wayland nativo el movimiento no depende ya de una heurística del frontend, sino de que xdg-shell permita reposicionar la ventana; el alcance y la alternativa X11 se deciden en bug(linux/wayland): la ventana no se puede posicionar: tira centrada, arrastre y cambio de monitor inoperativos #180. La ruta X11 quedó validada en KDE Plasma; GNOME/X11 sigue sin medir.
  • Como señalaste, setPosition sobre xdg_toplevel lo 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.

…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 egdev6 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

¡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.
@egdev6

egdev6 commented Oct 22, 2026

Copy link
Copy Markdown
Owner

@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

  • createWidgetRecovery acotado a Windows (fix(widget): recuperar posición y tamaño nativos #148): correcto y bien documentado. En xdg-shell outerPosition() es (0,0) por diseño, así que el ciclo de recuperación era un falso positivo estructural.
  • Muestreo de presencia solo en macOS (bug(macOS): el popup de detalle permanece visible tras dejar el hover (incluso moviendo el widget) #154): el hallazgo de que WebKitGTK devuelve (0,0) en vez de fallar es la clave del fix — el comentario original ("falla en silencio") era la premisa incorrecta. Volver al cierre por mouseenter/mouseleave del DOM es lo correcto en Linux.
  • Arrastre desde widgetBounds.current: buena solución — el caché lo escribe setWidgetBounds, no el compositor, así que es la única fuente síncrona fiable en xdg-shell. El descarte del (0,0) real solo cuando ya hay origen del caché está bien razonado.
  • La negativa argumentada a mover noRedirectionBitmap a override por plataforma es correcta: RFC 7396 reemplaza arrays completos, la fusión aplastaría la definición de la ventana. La vía Rust con #[cfg] (como lib.rs ya hace para detail) está bien señalada.
  • Honesto sobre lo que no resuelve (caja negra de WebKitGTK → bug(linux/wayland): ventana negra, bucle de reposicionamiento y cierre forzado del popup en 0.7.0 #168) y sobre la limitación de setPosition en varios compositores.

Sugerencias (ninguna bloqueante)

  1. Deduplicar los UA sniffs: Widget.tsx ahora tiene tres regex inline de plataforma (líneas ~35, ~526 y ~723), y el repo ya tiene el patrón testeable de src/lib/desktop-compat.ts (UA inyectable). Sugiero un helper tipo osFromUA(ua) en src/lib/ con tests, y que los tres puntos lo usen — evita que las regex diverjan (shortcuts.ts ya usa otra variante).
  2. Cobertura de tests para los gates: precisamente porque la UA es inyectable, un par de tests de OPEN_DELAY por plataforma y de los dos useEffect serían baratos y protegerían el comportamiento que este PR arregla (tercera vez que se toca).
  3. !important en styles.css: funcionalmente justificado para WebKitGTK, pero son 3 apariciones nuevas; anotarlas como primeros candidatos a eliminar si algún día se refactoriza el cascade.
  4. Caso borde del arrastre: si la ventana está realmente en (0,0) del monitor y hay caché, el release usa la rama delta (start + delta) en vez de wpos. Como start viene del mismo caché, la desviación solo puede ser redondeo del compositor — aceptable, pero teniéndolo presente si alguien reporta imán desplazado en la esquina superior-izquierda.

Sobre los pendientes que planteas

… 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).
@Rafaeldelinares

Copy link
Copy Markdown
Contributor Author

@egdev6 Listo: los cuatro puntos están atendidos y la rama ya está sobre main.

Rebase/merge (punto 4 de la review anterior)

Merge de origin/main (c2f7a12, mi propio #172) en c03f380. El único conflicto fue docs/i18n-inventory.md, que es generado: lo resolví regenerándolo (node scripts/i18n-inventory.mjs --out docs/i18n-inventory.md) en lugar de elegir un lado a mano. Ojo con un detalle que me costó un rato: el script graba el hash de árbol de src/ en la cabecera, así que hay que regenerarlo después del commit del merge, no antes — si no, --check pasa en local y falla en CI. Merger en vez de rebase para no reescribir el head que ya revisaste (ea7638b queda en el historial).

Gates locales sobre el head final: npm test (668 vitest + 221 node --test), npm run typecheck, scripts/i18n-inventory.mjs --check. Todo verde.

1. Deduplicar los UA sniffs

src/lib/os-detect.ts, con la UA inyectada como en desktop-compat.ts:

  • osFromUA(ua): 'windows' | 'macos' | 'linux'
  • openDelayForOs(os): 90 | 350, con el porqué de los dos valores en el propio módulo

Los tres puntos de Widget.tsx lo usan. Un test de equivalencia los ata al regex que reemplazan (/Windows|Macintosh|Mac OS X/), así que el refactor no puede cambiar comportamiento sin romper la suite.

Deliberadamente no toqué tres Detectores que también leen la UA, para no ampliar el alcance:

  • shortcuts.ts:58 — su isMac cubre iPhone/iPad vía navigator.platform; pasarle osFromUA cambiaría el comportamiento en iPad. Es candidato a otro PR, con su propio criterio.
  • ProviderGauge.tsx:89 — gate distinto (foco visible), no de plataforma de recoveries.
  • showDesktopCompat() en desktop-compat.ts — necesita distinguir Android (/Linux/ && !/Android/), cosa que un bucket de tres plataformas no modela. Documentado en el propio helper: linux es el bucket «resto», no una afirmación sobre el kernel.

2. Cobertura de los gates

Los dos useEffect tienen ahora un predicado nombrado y testeado junto a la lógica que protegen:

  • shouldAuditNativePosition(os) en widget-recovery.ts → solo windows
  • shouldSampleNativePresence(os) en detail-presence.ts → solo macos

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 @testing-library ni jsdom en devDependencies), así que los tests fijan el predicado del gate, no el useEffect en sí; el cuerpo del efecto ya está cubierto por widget-recovery.test.ts y detail-presence.test.ts. Montar Widget.tsx exigiría meter dos dependencias nuevas, y no me pareció el intercambio correcto para cerrar esto.

3. !important en styles.css

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 #root o .dock heredan fondo opaco) y la advertencia de que el síntoma es indistinguible de un fallo de WM.

4. Caso borde del arrastre en (0,0)

Documentado donde se decide: si el compositor informa (0,0) con origen en caché, el release toma la rama por delta, y como start sale del mismo caché que escribió setWidgetBounds, la desviación solo puede ser redondeo. Queda anotado que, si algún día se reporta el orbe imantado en la esquina superior izquierda, el redondeo es lo primero que hay que mirar.

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.
@egdev6

egdev6 commented Oct 23, 2026

Copy link
Copy Markdown
Owner

@Rafaeldelinares revisa fallo de tests xf

@Rafaeldelinares

Copy link
Copy Markdown
Contributor Author

Gracias por el aviso, @egdev6 — y perdón por el ruido.

No era un test roto: era el paso i18n text inventory is up to date (scripts/i18n-inventory.mjs --check).

La causa fue mía y de orden. Regeneré docs/i18n-inventory.md antes del commit que cambiaba src/, así que la cabecera del archivo —que graba el hash de árbol de HEAD:src— quedó con el hash del commit anterior. El gate compara ese hash, y al cambiar el HEAD en el commit siguiente el archivo quedó desactualizado contra sí mismo.

Corregido en 36ec800: un commit que solo toca el archivo generado, de modo que el hash de la cabecera sigue siendo válido para el árbol que lo acompaña. Antes de pushear lo comprobé de las dos formas — con el checkout normal y con core.autocrlf=true para emular el de Windows — y en los dos casos el gate pasa.

CI en 36ec800: 5/5 en verde (Linux, Windows, macOS ARM64, secrets scan y static code safety).

Dos aclaraciones:

  • Lo que arregla ese commit es solo el inventario. El merge de main, el helper osFromUA y los dos gates nombrados quedan idénticos a a4af4a4.
  • La trampa es más ancha que este PR: el archivo no se puede regenerar sin commitear antes, y el gate solo corre en Windows, así que en Linux no te avisa. Si te parece, la arreglo en su propio PR contra main — pero no la mezclo con este sin que lo pidas.

Reviso lo que veas. Gracias por mirarlo.

@egdev6

egdev6 commented Oct 23, 2026

Copy link
Copy Markdown
Owner

@Rafaeldelinares he revisado los commits nuevos (bb0155d→36ec800) y reproducido la verificación sobre el head (36ec800). Evaluación punto por punto de la review:

Evaluación de los 5 puntos

1. noRedirectionBitmap — ✅ resuelto por conservación, con argumento sólido. El PR ya no toca tauri.conf.json (verificado: diff vacío, el flag sigue en la base). Y el argumento contra la mudanza es correcto: tauri-utils fusiona la config de plataforma con JSON Merge Patch (RFC 7396), que reemplaza arrays completos — un tauri.windows.conf.json con solo app.windows=[{label:"widget", noRedirectionBitmap:true}] dejaría el widget sin width, transparent, decorations, etc. El diagnóstico «solo Windows en tao 0.37.1» (4 refs, todas en platform_impl/windows/) también cuadra. La vía alternativa queda bien documentada: declarar la ventana en Rust con #[cfg(windows)], como ya hace detail en lib.rs:791.

2. CSS data-auto-hide — ✅ revertido. Cero menciones en el diff de styles.css; solo quedan #root/.dock con fondo transparente explícito, y a4af4a4 documenta los tres !important con instrucciones de cuándo se pueden quitar.

3. OPEN_DELAY por plataforma — ✅. openDelayForOs(): 90 ms Windows/macOS, 350 ms Linux, con os-detect.test.ts que incluye un test de equivalencia contra el gate legacy (/Windows|Macintosh|Mac OS X/). El toggle por clic fuera del PR. No quedan regex legacy en Widget.tsx.

4. Rebase + i18n — ✅. Merged main, inventario regenerado, --check en verde, tsc limpio, 668 tests en verde.

5. Arrastre (0,0) — 🟡 a medias. El código está documentado (origen en caché y rama por delta en Widget.tsx). Pero la validación en GNOME sigue pendiente.

🟡 Observaciones

  1. Tensión título/descripción: el título dice «resolve wayland transparency» pero el cuerpo admite que la caja negra sigue sin resolverse con este diff (el sospechoso real es DMABUF, en medición con WEBKIT_DISABLE_DMABUF_RENDERER=1/GDK_BACKEND=x11). El CSS de transparencia es hardening defensivo, no el fix. Conviendría suavizar el título o dejarlo claro en la descripción para no crear la expectativa equivocada en el changelog.
  2. Señal de plataforma por UA: los gates usan osFromUA(navigator.userAgent) existiendo get_wm_info/wm_compat.rs (feat(linux): detección backend de compositor y superficies del escritorio (#107) #128) en el backend. El docstring de os-detect.ts lo justifica (decisiones OS-scoped, no compositor-scoped) y es aceptable — pero si algún día un UA custom entra en juego, el backend es la señal más robusta. Nit.

✅ Verificación reproducida (head 36ec800)

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.

@egdev6 egdev6 changed the title fix(linux): resolve wayland transparency, drag movement and hover regressions (#168) fix(linux): gates de plataforma para recovery/presence/open-delay y arrastre en Wayland (#168) Oct 23, 2026
@egdev6
egdev6 merged commit 2610926 into egdev6:main Oct 23, 2026
5 checks passed
@Rafaeldelinares Rafaeldelinares changed the title fix(linux): gates de plataforma para recovery/presence/open-delay y arrastre en Wayland (#168) fix(linux): gates de plataforma y cálculo del arrastre en Wayland (#168) Oct 25, 2026
@egdev6 egdev6 mentioned this pull request Oct 28, 2026
1 task done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants