Repository navigation
Description
Contexto y motivación
Quorb está concebido como una tira de estado y control continua. En Linux, al cambiar de escritorio virtual (workspaces en KDE Plasma, GNOME, etc.), la tira desaparece porque el gestor de ventanas la confina al escritorio donde se inició el proceso.
En #112 se incorporó set_visible_on_all_workspaces(true) en src-tauri/src/lib.rs:1083 con un gate #[cfg(target_os = "macos")] bajo la asunción de que en Linux bastaba con always_on_top («Windows/Linux have no Spaces and always-on-top already covers it»).
Sin embargo, en Linux (X11 / KDE / GNOME) always_on_top (_NET_WM_STATE_ABOVE) solo mantiene la ventana flotando por encima dentro del mismo escritorio virtual, pero no acompaña al usuario al cambiar de workspace. Para acompañar entre escritorios se requiere declarar la ventana como sticky (_NET_WM_STATE_STICKY / _NET_WM_DESKTOP = 0xFFFFFFFF).
Diagnóstico técnico
En el motor de ventanas de Quorb (tao 0.37.1), set_visible_on_all_workspaces(true) ya está plenamente implementado para Linux (tao/src/platform_impl/linux/window.rs:762 y event_loop.rs:424):
WindowRequest::SetVisibleOnAllWorkspaces(visible) => {
if visible {
window.stick();
} else {
window.unstick();
}
}La llamada a window.stick() de GTK envía al gestor de ventanas los mensajes EWMH oficiales para que la ventana se proyecte en todos los escritorios.
Alcance propuesto (Centrado en Linux)
Nos centramos exclusivamente en implementar y verificar esta paridad en Linux:
- Linux (X11 / XWayland):
- Ampliar el gate en
src-tauri/src/lib.rs:#[cfg(any(target_os = "macos", target_os = "linux"))] for label in [WIDGET, DETAIL, OVERLAY] { if let Some(w) = app.get_webview_window(label) { if let Err(e) = w.set_visible_on_all_workspaces(true) { eprintln!("No pude marcar «{label}» visible en todos los escritorios: {e}"); } } }
- Otorga paridad inmediata con macOS sin dependencias nuevas ni cambios en la capa de frontend.
- Ampliar el gate en
- Linux (Wayland nativo):
xdg-shellpor diseño no ofrece a clientes regulares una petición para declararse sticky sin protocolos privilegiados de compositor (wlr-layer-shell). Con el camino X11/XWayland (GDK_BACKEND=x11), queda cubierto en el entorno operativo de Linux.
Pregunta para el mantenedor / Decisión de producto
¿Preferís que este comportamiento sea predeterminado e inherente al widget (igual que en macOS desde #112), o considerás necesario que esté sujeto a un interruptor en Ajustes (ej. Ajustes > Comportamiento > Mostrar en todos los escritorios virtuales)?
Abrimos el hilo para acordar la dirección antes de preparar la PR.
Activity
egdev6 commentedon Nov 1, 2026
Gracias por el análisis, @Rafaeldelinares. Lo revisé contra
mainy el diagnóstico es correcto: ensrc-tauri/src/lib.rs:1083el marcado como visible en todos los escritorios solo se aplica en macOS, y el comentario delib.rs:1036-1041asume que en Linux basta con mantener la ventana siempre encima, que no la hace acompañar al cambiar de escritorio. Entao 0.37.1la llamada en Linux usagtk::Window::stick(), que también funciona antes de que la ventana tengaGdkWindow, así que no debería repetir el problema deset_ignore_cursor_events. En Wayland nativo no tendrá efecto, como indicas; queda cubierto el camino X11/XWayland.Sobre la decisión de producto: prefiero que sea el comportamiento predeterminado, sin opción en Ajustes, igual que en macOS desde #112. Una tira de estado que desaparece al cambiar de escritorio va contra su propósito. Si más adelante alguien necesita desactivarlo, se puede valorar entonces una opción.
Para la PR, además de ampliar el gate a Linux:
lib.rs:1036-1041y el mensaje de error, que menciona Spaces._NET_WM_STATE_STICKYconxpropy cambiar de escritorio con el panel transitorio, el panel anclado y el overlay.Adelante con la PR cuando quieras. ¡Gracias!
chore(i18n): actualizar hash del árbol src-tauri en el inventario (eg…
docs(i18n): regenerate inventory after main merge (egdev6#227)
fix(linux): hacer que el widget sea visible en todos los escritorios …
merge: integrar main del upstream (widget egdev6#214/egdev6#227/egdev…
Rafaeldelinares commentedon Nov 8, 2026
@egdev6 Fui a hacer la validación manual que pediste y antes que nada te debo una corrección sobre la PR #232: escribí que "al alternar entre escritorios virtuales (KDE Plasma 6 / X11) la tira permanece fija y visible", y eso no estaba medido. Solo había comprobado con
xpropque quedaba_NET_WM_STATE_STICKY. Midiendo el cambio de escritorio de verdad, en KDE Plasma con XWayland la tira no acompaña. Perdón por haberte hecho integrar con esa afirmación.Lo bueno es que encontré la causa, que no está en Quorb, y probé una salida. Te dejo todo con evidencia para que decidas.
Entorno: CachyOS (kernel 7.2.4-3-cachyos), KDE Plasma 6.7.5 / KWin 6.7.5 en sesión Wayland con 3 escritorios, Quorb
main79ee3cd(incluye #232 y #223) conGDK_BACKEND=x11, GTK 3.24.52. El cambio de escritorio lo hago por D-Bus (org.kde.KWin.setCurrentDesktop) y el estado lo leo de KWin (onAllDesktops) y conxprop.1. Lo que pasa hoy en
main_NET_WM_STATEde la tira_NET_WM_STATE_STICKY_NET_WM_DESKTOP0(no0xFFFFFFFF)onAllDesktopsfalse, solo en "Escritorio 1" (3/3 arranques)kwinrulesrcvacío)2. La causa: KWin ignora a propósito los escritorios de los clientes X11
El commit de KWin
55fd1912("Provide fake virtual desktop information to X clients", septiembre de 2025) pone esa información detrás deKWIN_XWAYLAND_ENABLE_NETWM_DESKTOP=1, que por defecto no está definida:En ese modo
WinInfo::changeDesktop()descarta los pedidos de los clientes, incluido "todos los escritorios". En esta máquina se ve directamente: con 3 escritorios reales, XWayland recibe_NET_NUMBER_OF_DESKTOPS = 1y_NET_DESKTOP_NAMES = "Desktop 1".Para descartar que fuera algo de Quorb o de cuándo se llama a
stick(), lo repetí con una ventana GTK3 mínima:onAllDesktopsstick()antes deshow()(lo que hace Quorb vía tao)falsestick()con la ventana ya mapeadafalsefalse_NET_WM_DESKTOP = 0xFFFFFFFFcon la ventana mapeadafalseshow()falseKWin atiende otros pedidos del cliente (F), pero ningún pedido de escritorio. Así que el código de #232 es correcto según EWMH y seguirá sirviendo en gestores X11 que lo respeten. En KWin con XWayland no alcanza.
3. Prototipo: marcar las ventanas desde KWin
Como prueba de concepto, sin tocar Quorb, cargué en KWin por D-Bus (
org.kde.kwin.Scripting.loadScript) un script que poneonAllDesktops = trueen las ventanas de Quorb, también en las que se crean después:Script de KWin del prototipo
Con eso se cumplen los tres casos que pediste. En todas las capturas KWin reporta
onAllDesktops: trueestando en el escritorio 2:Un detalle del prototipo: también marcó Ajustes, porque filtra por clase. Una versión real tendría que limitarse a la tira, el detalle y el overlay, igual que el gate de #232.
Opciones que veo
KWIN_XWAYLAND_ENABLE_NETWM_DESKTOP=1en el entorno de Plasma y volver a iniciar sesión. No requiere código. No lo probé porque implica reiniciar la sesión.Sin validar: una sesión Plasma X11 real (esta máquina no la tiene instalada) y GNOME.
¿Cuál de estas vías preferís? Si te sirve, pruebo la 1 y te traigo el resultado antes de que decidas.
egdev6 commentedon Nov 9, 2026
Gracias por corregir la validación y por investigar con tanto detalle, @Rafaeldelinares.
El cambio de #232 ya solicita la visibilidad para la tira, el detalle y el overlay en
src-tauri/src/lib.rs:1131-1136, pero tu prueba muestra que eso no basta en KWin/XWayland. Además,_NET_WM_STATE_STICKYpor sí solo no acredita que la ventana esté en todos los escritorios.He comprobado que KWin eliminó la variable
KWIN_XWAYLAND_ENABLE_NETWM_DESKTOPen este cambio, incluido en el upstream de 6.7.5. Salvo que CachyOS la haya recuperado con un parche, no esperaría que funcione, así que no hace falta reiniciar la sesión para probarla.Por ahora prefiero no cargar scripts automáticamente en el compositor. Mantengamos la issue abierta y el comportamiento predeterminado acordado. ¿Podrías probar, si te resulta posible, una regla de KWin creada por el usuario y comprobar si permite seleccionar solo la tira, el detalle y el overlay, sin afectar a Ajustes? La validación sería cambiar realmente de escritorio con el detalle transitorio y anclado y el overlay, comprobando
onAllDesktops. Plasma X11 y GNOME quedan pendientes para cuando haya un entorno disponible.Gracias de nuevo por la transparencia y las pruebas.
evidence(egdev6#227): KWin user window rule screenshots
Rafaeldelinares commentedon Nov 10, 2026
@egdev6 Tienes razón con la variable: la di por buena porque vi el commit que la introducía y no busqué si después la habían quitado. En esta máquina lo confirmé:
KWIN_XWAYLAND_ENABLE_NETWM_DESKTOPno aparece enlibkwin.so.6.7.5ni enkwin_wayland. Gracias por revisarlo.Probé la regla de KWin creada por el usuario. Con el título se puede seleccionar solo la tira, el detalle y el overlay, sin tocar Ajustes, y funciona sin cargar nada en el compositor.
Entorno: CachyOS, KDE Plasma 6.7.5 / KWin 6.7.5 en sesión Wayland con 3 escritorios, Quorb
main79ee3cdconGDK_BACKEND=x11. Cambio de escritorio real por D-Bus (org.kde.KWin.setCurrentDesktop), estado leído de KWin (onAllDesktops). Cada captura incluye el paginador de Plasma para que se vea qué escritorio está activo. Fuera de la prueba, la configuración de reglas de la máquina quedó como estaba.La regla
En la interfaz equivale a Preferencias del sistema → Gestión de ventanas → Reglas de ventanas: clase de ventana
[Qq]uorb(expresión regular), título^Quorb( · .+)?$(expresión regular) y Escritorio virtual: Forzar → Todos los escritorios.Dos detalles que encontré al armarla:
quorbcomo subcadena la regla no se aplicaba, porque KWin ve la clase comoQuorb…. Por eso uso[Qq]uorb.Quorb,Quorb · detalle/details,Quorb · efectos/effects, segúni18n.rs). Ajustes empieza por la palabra traducida (Ajustes · Quorb/Settings · Quorb), así que queda fuera. Las ventanas no exponenWM_WINDOW_ROLE, por lo que el título es lo más estable que hay.Resultados
onAllDesktops: trueonAllDesktops: trueonAllDesktops: falseen las 3 corridas, se queda en su escritorioLo que no quedó limpio
Quorb · efectoscononAllDesktops: trueya en el escritorio de destino. En las otras dos el efecto terminó antes de que llegara a medirlo: el confeti dura 4,2 s (DURATIONenOverlay.tsx) y cada captura tarda alrededor de un segundo. Por eso no tengo foto del confeti con la regla. Podría conseguirla con un efecto propio en vídeo más largo, si te parece necesario.Plasma X11 y GNOME siguen pendientes, como dijiste.
¿Quieres que la regla se documente en
docs/build-linux.mdcomo el camino para KDE en XWayland, o prefieres dejarla registrada solo aquí por ahora?egdev6 commentedon Nov 10, 2026
@Rafaeldelinares, gracias por la actualización y por distinguir lo observado de lo que no llegó a medirse. La regla aporta evidencia útil como workaround manual para CachyOS con Plasma/KWin 6.7.5 en Wayland y Quorb vía XWayland, no como solución general para KDE o Linux. Mantendría la issue abierta.
Los resultados que aportas apoyan el seguimiento del detalle transitorio y la exclusión de Ajustes. La desaparición del anclado en una corrida sigue sin causa identificada. En el overlay, las otras dos corridas terminaron antes de medirlo: no las contaría como dos fallos de visibilidad. Plasma X11 y GNOME siguen sin validar.
Antes de decidir su incorporación a
docs/build-linux.md, queda un matiz del alcance: el selector inicial de idioma también se crea con títuloQuorb(src-tauri/src/lib.rs:1031–1034). Confirmé que ese título coincide con^Quorb( · .+)?$, igual que los títulos ES/EN de tira, detalle y overlay; Ajustes queda fuera. Si el selector comparte la clase que ve KWin, la regla también podría afectarlo. ¿Puedes comprobar su clase y si la regla lo alcanza, cuando sea posible sin alterar tu configuración habitual?La propuesta de documentación es razonable si se presenta como regla optativa creada por el usuario, con el entorno probado y estas limitaciones explícitas, sin afirmar que solo afecta a tres ventanas hasta aclarar el selector. No implica cargar scripts automáticamente ni recuperar la variable eliminada. La decisión de incorporarla queda pendiente; no doy por resuelta la issue. Esta revisión contrastó el código y la expresión de títulos, no repitió las pruebas reales de KWin ni verificó visualmente las capturas.
evidence(egdev6#227): KWin rule also matches the first-run locale picker
Rafaeldelinares commentedon Nov 10, 2026
@egdev6 Lo comprobé y tenías razón: la regla también alcanza al selector de idioma del primer arranque. Corrijo lo que escribí en el comentario anterior: no selecciona "solo la tira, el detalle y el overlay". Ajustes sí queda fuera.
Entorno: el mismo de antes (CachyOS, KDE Plasma 6.7.5 / KWin 6.7.5 en Wayland, Quorb
main79ee3cdconGDK_BACKEND=x11). Para forzar el primer arranque sin tocar mi configuración, lancé Quorb conXDG_CONFIG_HOME,XDG_DATA_HOME,XDG_CACHE_HOMEyXDG_STATE_HOMEapuntando a un directorio temporal, que borré al terminar. La regla la puse solo durante la prueba y después restauré la configuración de KWin.WM_CLASS)quorb-79ee3cd/Quorb-79ee3cd, la misma que la tira, el detalle y el overlayQuorb, coincide con^Quorb( · .+)?$_NET_WM_WINDOW_TYPE_NORMAL, 420×268 con decoracionesonAllDesktops: falseonAllDesktops: true, y acompaña al cambiar del escritorio 1 al 2En ese momento el selector es la única ventana de Quorb; la tira todavía no existe.
Con la clase y el título actuales, la regla no puede distinguir el selector: las ventanas no exponen
WM_WINDOW_ROLEy el selector comparte clase y título con la tira. Veo dos formas de tratarlo:Quorb · idioma, o uno neutro, porque se muestra antes de elegir idioma) y ajustar la expresión para excluirlo. Es un cambio pequeño enopen_locale_picker.¿Cuál prefieres? Si vas por la documentación, la redactaría como regla optativa creada por el usuario, con el entorno probado y estas limitaciones explícitas, como indicaste.
egdev6 commentedon Nov 11, 2026
@Rafaeldelinares gracias por comprobarlo y por corregir el alcance, quedó muy claro.
Vamos por la opción 2: un título propio para el selector de idioma y una expresión que lo excluya. Un detalle: con un título como
Quorb · idioma, la expresión actual^Quorb( · .+)?$lo seguiría seleccionando, así que hacen falta los dos cambios juntos (el título enopen_locale_pickery la expresión documentada). Como el selector aparece antes de elegir idioma, conviene un título que no dependa de la traducción, para que la expresión sea estable.En
docs/build-linux.md, presentá la regla como optativa y creada por el usuario, con el entorno probado (CachyOS, Plasma/KWin 6.7.5 en Wayland, Quorb por XWayland) y las limitaciones medidas: el detalle anclado desapareció en una de tres pruebas, el overlay solo se pudo medir en una, y Plasma X11 y GNOME no están verificados. La issue sigue abierta, porque es un apaño manual y no un arreglo general.Rafaeldelinares commentedon Nov 11, 2026
@egdev6 Perfecto, vamos con la opción 2. ¿Me asignas #227? Lo implemento en cuanto lo vea asignado. Este es el plan, por si quieres ajustar algo antes:
Título del selector (
open_locale_picker, hoy.title("Quorb")ensrc-tauri/src/lib.rs:1061): propongoIdioma / Language · {canal}, un texto fijo y bilingüe que no pasa por la traducción. Sigue el mismo patrón que Ajustes (Ajustes · Quorb): primero la palabra y al final el nombre de la app. Así la expresión que empieza por el nombre de la app lo excluye, y no hay que tocarla si mañana se añade otro idioma. La alternativa sería enumerar en la expresión los títulos traducidos del detalle y del overlay (detalle|details|efectos|effects), pero cada idioma nuevo obligaría a actualizar la documentación.Expresión documentada: al revisarlo encontré que el canal Beta titula las ventanas
Quorb Beta,Quorb Beta · detalle, etc. (locale_relabelenlib.rs), así que^Quorb( · .+)?$no lo cubre. Documentaría^Quorb( Beta)?( · .+)?$, que deja fuera a Ajustes y al selector en los dos canales.Código: el título como constante, con un test que comprueba que no empieza por el nombre del canal, para que la regla documentada no pueda volver a alcanzarlo sin que falle un test. Como cambia un texto visible, regeneraré el inventario i18n después del commit del código.
Documentación (
docs/build-linux.md): la regla como optativa y creada por el usuario, en formato de archivo y con los pasos en Preferencias del sistema, con el entorno probado (CachyOS, Plasma/KWin 6.7.5 en Wayland, Quorb por XWayland) y las limitaciones medidas: el anclado desapareció en una de tres pruebas, el overlay solo se pudo medir en una, y Plasma X11 y GNOME no están verificados. Dejaré claro que es un apaño manual y no un arreglo general.Validación: repetiré la medición del selector con la regla y la configuración aislada, comprobando que queda con
onAllDesktops: false, además de una pasada rápida de tira, detalle y Ajustes. Todo irá con capturas en la PR.egdev6 commentedon Nov 11, 2026
@Rafaeldelinares te asigno #227. El plan está bien encaminado; algunos ajustes antes de empezar:
mainno existe un canal Beta:channel.rsdefine únicamente el perfil estable y rechaza cualquier otro identificador.Quorb Betasolo aparece como dato de prueba en el test delocale_relabel. Documenta la regla para el canal estable, sin el( Beta)?, para no describir un caso que no se puede compilar ni medir.Idioma / Language · Quorbme parece bien: es fijo, no depende de la traducción y deja fuera al selector con la expresión actual^Quorb( · .+)?$. Ten en cuenta que esa expresión no se vuelve más estricta; el selector queda fuera porque su título deja de empezar porQuorb. Así conviene explicarlo en la documentación.La documentación y la nueva medición, como propones: regla optativa creada por el usuario, entorno probado y limitaciones medidas. La issue se mantiene abierta como apaño manual, no como arreglo general.
evidence(egdev6#227): measurement screenshots for the KWin rule PR
fix(linux): give the locale picker its own title and document the KWi…
docs(i18n): regenerate the text inventory for the locale picker title (…
docs(odd): record the KWin rule measurement for #227
fix(linux): read the KWin rule only from its docs block and state the…
docs(i18n): refresh the inventory tree hash after the test change (#227)
Merge pull request #266 from Rafaeldelinares/fix/227-kwin-rule-locale…
evidence(egdev6#227): video and frame sequence of the KWin rule on 48…
merge: integrar main del upstream (widget #214/#227/#228, X11 #215, m…