@@ -102,6 +102,7 @@ export function CapturePreview({
102102 const [ speakerMuted , setSpeakerMuted ] = useState ( false ) ;
103103 const [ spaceWarning , setSpaceWarning ] = useState < number | null > ( null ) ;
104104 const [ containerDimensions , setContainerDimensions ] = useState ( { width : 0 , height : 0 } ) ;
105+ const [ waylandInputDiagnosticsDismissed , setWaylandInputDiagnosticsDismissed ] = useState ( false ) ;
105106
106107 const {
107108 session : createdSession ,
@@ -195,7 +196,8 @@ export function CapturePreview({
195196 const showWaylandInputDiagnostics =
196197 Boolean ( session ) &&
197198 inputDiagnostics ?. backend . startsWith ( 'wayland-' ) === true &&
198- ! inputDiagnostics . backendSupported ;
199+ ! inputDiagnostics . backendSupported &&
200+ ! waylandInputDiagnosticsDismissed ;
199201
200202 const hostHookOptions = useMemo (
201203 ( ) => ( {
@@ -1024,11 +1026,31 @@ export function CapturePreview({
10241026 < div className = "rounded-lg border border-amber-300/60 bg-amber-50 px-4 py-3 text-sm text-amber-950" >
10251027 < div className = "flex items-start gap-2" >
10261028 < AlertTriangle className = "mt-0.5 h-4 w-4 shrink-0" />
1027- < div className = "space-y-2" >
1028- < div className = "font-medium" > Wayland remote control backend unavailable</ div >
1029+ < div className = "min-w-0 flex-1 space-y-2" >
1030+ < div className = "flex items-start justify-between gap-3" >
1031+ < div className = "font-medium" > Wayland remote control backend unavailable</ div >
1032+ < button
1033+ type = "button"
1034+ className = "font-mono text-xs text-amber-900/80 hover:text-amber-950"
1035+ onClick = { ( ) => {
1036+ setWaylandInputDiagnosticsDismissed ( true ) ;
1037+ } }
1038+ aria-label = "Dismiss Wayland backend warning"
1039+ title = "Dismiss"
1040+ >
1041+ [x]
1042+ </ button >
1043+ </ div >
10291044 < div className = "text-amber-900/90" >
10301045 { inputDiagnostics . reason ?? 'Wayland input backend is not ready.' }
10311046 </ div >
1047+ { inputDiagnostics . backend === 'wayland-portal' && (
1048+ < div className = "text-amber-900/90" >
1049+ PairUX detected the Wayland portal, but PairUX portal-based input injection is
1050+ not implemented yet. This is informational only, not something you can enable in
1051+ portal settings today.
1052+ </ div >
1053+ ) }
10321054 < div className = "font-mono text-xs leading-relaxed text-amber-900/90" >
10331055 { ( ( ) => {
10341056 const portalDesktop =
@@ -1088,18 +1110,63 @@ export function CapturePreview({
10881110 } ) ( ) }
10891111 </ div >
10901112 < div className = "space-y-1 rounded border border-amber-300/50 bg-white/70 p-2 font-mono text-xs" >
1091- < div >
1092- # Preferred path (future PairUX backend): xdg-desktop-portal RemoteDesktop
1093- </ div >
1094- < div > systemctl --user status xdg-desktop-portal</ div >
1095- < div > # Install (Debian/Ubuntu)</ div >
1096- < div > sudo apt install ydotool</ div >
1097- < div > # Start daemon (may require root / uinput access)</ div >
1098- < div > sudo systemctl enable --now ydotool</ div >
1099- < div > # Or foreground debug</ div >
1100- < div > sudo ydotoold</ div >
1101- < div > # Check socket</ div >
1102- < div > ls -l $XDG_RUNTIME_DIR/.ydotool_socket /tmp/.ydotool_socket</ div >
1113+ { ( ( ) => {
1114+ const details = inputDiagnostics . details as
1115+ | {
1116+ ydotoolBinaryPath ?: string ;
1117+ ydotoolSocketPath ?: string ;
1118+ autoStartAttempted ?: boolean ;
1119+ autoStartMethod ?: string | null ;
1120+ autoStartError ?: string | null ;
1121+ currentDesktop ?: string ;
1122+ portalImplDetected ?: string | null ;
1123+ ydotool ?: {
1124+ details ?: {
1125+ ydotoolBinaryPath ?: string ;
1126+ ydotoolSocketPath ?: string ;
1127+ autoStartAttempted ?: boolean ;
1128+ autoStartMethod ?: string | null ;
1129+ autoStartError ?: string | null ;
1130+ } ;
1131+ } ;
1132+ portal ?: {
1133+ details ?: {
1134+ currentDesktop ?: string ;
1135+ portalImplDetected ?: string | null ;
1136+ } ;
1137+ } ;
1138+ }
1139+ | undefined ;
1140+
1141+ const ydotoolBinaryPath =
1142+ details ?. ydotoolBinaryPath ?? details ?. ydotool ?. details ?. ydotoolBinaryPath ;
1143+ const ydotoolSocketPath =
1144+ details ?. ydotoolSocketPath ?? details ?. ydotool ?. details ?. ydotoolSocketPath ;
1145+ const autoStartAttempted =
1146+ details ?. autoStartAttempted ?? details ?. ydotool ?. details ?. autoStartAttempted ;
1147+ const autoStartMethod =
1148+ details ?. autoStartMethod ?? details ?. ydotool ?. details ?. autoStartMethod ;
1149+ const autoStartError =
1150+ details ?. autoStartError ?? details ?. ydotool ?. details ?. autoStartError ;
1151+ const currentDesktop =
1152+ details ?. currentDesktop ?? details ?. portal ?. details ?. currentDesktop ;
1153+ const portalImplDetected =
1154+ details ?. portalImplDetected ?? details ?. portal ?. details ?. portalImplDetected ;
1155+
1156+ return (
1157+ < >
1158+ < div > Path status (auto-detected)</ div >
1159+ < div > backend={ inputDiagnostics . backend } </ div >
1160+ < div > desktop={ currentDesktop ?? 'n/a' } </ div >
1161+ < div > portalImpl={ portalImplDetected ?? 'n/a' } </ div >
1162+ < div > ydotoolBin={ ydotoolBinaryPath ?? 'n/a' } </ div >
1163+ < div > ydotoolSocket={ ydotoolSocketPath ?? 'n/a' } </ div >
1164+ < div > ydotoolAutoStart={ String ( autoStartAttempted ?? false ) } </ div >
1165+ < div > ydotoolStartMethod={ autoStartMethod ?? 'n/a' } </ div >
1166+ { autoStartError ? < div > ydotoolStartError={ autoStartError } </ div > : null }
1167+ </ >
1168+ ) ;
1169+ } ) ( ) }
11031170 </ div >
11041171 </ div >
11051172 </ div >
0 commit comments