فهرست منبع

Fix touch app console bleed-through on linuxfb backend

Add explicit background rendering and forced full-scene repaint:

1. Canvas-based full-screen background that can be programmatically
   repainted when needed

2. Force entire scene graph repaint by briefly hiding/showing the
   main container - this marks all QML items as dirty, forcing Qt
   to redraw everything (not just the background)

3. Two-stage timer approach:
   - repaintTimer (150ms): Wait for framebuffer to be ready after unblank
   - repaintRestoreTimer (50ms): Restore visibility after hide

The root cause: linuxfb uses damage tracking and only redraws dirty regions.
After framebuffer unblank, Qt doesn't know the entire scene needs repainting.
Simply repainting the Canvas wasn't enough - we need to force Qt to mark
ALL items as needing repaint by toggling their parent's visibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris 1 ماه پیش
والد
کامیت
ca066b914d
4فایلهای تغییر یافته به همراه93 افزوده شده و 5 حذف شده
  1. 3 0
      dune-weaver-touch/dune-weaver-touch.service
  2. 11 0
      dune-weaver-touch/install.sh
  3. 76 5
      dune-weaver-touch/qml/main.qml
  4. 3 0
      dune-weaver-touch/run.sh

+ 3 - 0
dune-weaver-touch/dune-weaver-touch.service

@@ -10,6 +10,9 @@ Group=pi
 WorkingDirectory=/home/pi/dune-weaver-touch
 Environment=QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
 Environment=QT_QPA_FB_HIDECURSOR=1
+# Hide console cursor before starting (fallback if kernel param not set)
+ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/graphics/fbcon/cursor_blink || true'
+ExecStartPre=/bin/sh -c 'setterm --cursor off > /dev/tty1 || true'
 ExecStart=/home/pi/dune-weaver-touch/venv/bin/python /home/pi/dune-weaver-touch/main.py
 Restart=always
 RestartSec=10

+ 11 - 0
dune-weaver-touch/install.sh

@@ -80,6 +80,9 @@ Group=$ACTUAL_USER
 WorkingDirectory=$SCRIPT_DIR
 Environment=QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
 Environment=QT_QPA_FB_HIDECURSOR=1
+# Hide console cursor before starting (fallback if kernel param not set)
+ExecStartPre=/bin/sh -c 'echo 0 > /sys/class/graphics/fbcon/cursor_blink || true'
+ExecStartPre=/bin/sh -c 'setterm --cursor off > /dev/tty1 || true'
 ExecStart=$SCRIPT_DIR/venv/bin/python $SCRIPT_DIR/main.py
 Restart=always
 RestartSec=10
@@ -261,6 +264,14 @@ setup_kiosk_optimizations() {
         else
             echo "   ℹ️  Boot splash already enabled"
         fi
+
+        # Disable console cursor (the blinking underscore on fbcon)
+        if ! grep -q "vt.global_cursor_default=0" "$CMDLINE_FILE"; then
+            sed -i 's/$/ vt.global_cursor_default=0/' "$CMDLINE_FILE"
+            echo "   ✅ Console cursor disabled"
+        else
+            echo "   ℹ️  Console cursor already disabled"
+        fi
     fi
 
     echo "   🖥️  Kiosk optimizations applied"

+ 76 - 5
dune-weaver-touch/qml/main.qml

@@ -14,9 +14,7 @@ ApplicationWindow {
     height: 480
     title: "Dune Weaver Touch"
 
-    // Solid background to prevent console bleed-through on linuxfb
-    // linuxfb doesn't have proper compositing, so we need to ensure
-    // the entire window is filled with an opaque color
+    // Solid background color for ApplicationWindow
     color: Components.ThemeManager.backgroundColor
 
     property int currentPageIndex: 0
@@ -25,10 +23,28 @@ ApplicationWindow {
     property bool shouldNavigateToExecution: false
     property string currentPatternName: ""
     property string currentPatternPreview: ""
-    
+
+    // Property to force full repaint on linuxfb (toggle to trigger update)
+    property bool forceRepaint: false
+
     onCurrentPageIndexChanged: {
         console.log("📱 currentPageIndex changed to:", currentPageIndex)
     }
+
+    // Force full repaint function - call when screen wakes up
+    // On linuxfb, we need to force Qt to redraw the ENTIRE scene graph,
+    // not just individual components. The trick is to briefly hide/show
+    // the content which forces Qt to mark everything as dirty.
+    function triggerFullRepaint() {
+        console.log("🔄 Triggering full repaint for linuxfb")
+        forceRepaint = !forceRepaint
+        fullScreenBackground.requestPaint()
+
+        // Force entire scene graph repaint by toggling visibility
+        // This marks all items as dirty and forces a complete redraw
+        rotationContainer.visible = false
+        repaintRestoreTimer.start()
+    }
     
     onShouldNavigateToExecutionChanged: {
         if (shouldNavigateToExecution) {
@@ -75,6 +91,12 @@ ApplicationWindow {
         
         onScreenStateChanged: function(isOn) {
             console.log("🖥️ Screen state changed:", isOn ? "ON" : "OFF")
+            if (isOn) {
+                // Force full repaint when screen wakes up on linuxfb
+                // This is necessary because linuxfb doesn't automatically
+                // redraw the entire framebuffer after unblank
+                repaintTimer.start()
+            }
         }
         
         onBackendConnectionChanged: function(connected) {
@@ -115,7 +137,56 @@ ApplicationWindow {
     PatternModel {
         id: patternModel
     }
-    
+
+    // Timer to delay repaint slightly after screen wake (ensures framebuffer is ready)
+    Timer {
+        id: repaintTimer
+        interval: 150  // 150ms delay for framebuffer to be ready
+        repeat: false
+        onTriggered: {
+            window.triggerFullRepaint()
+        }
+    }
+
+    // Timer to restore visibility after hiding (completes the force-repaint trick)
+    Timer {
+        id: repaintRestoreTimer
+        interval: 50  // Brief 50ms hide
+        repeat: false
+        onTriggered: {
+            rotationContainer.visible = true
+            console.log("🎨 Full scene repaint completed")
+        }
+    }
+
+    // Full-screen opaque background using Canvas for forced repaint capability
+    // This is essential for linuxfb which doesn't have proper compositing
+    // and shows the Linux console through transparent areas
+    Canvas {
+        id: fullScreenBackground
+        anchors.fill: parent
+        z: -1  // Behind everything else
+
+        // Repaint when forceRepaint toggles or theme changes
+        property color bgColor: Components.ThemeManager.backgroundColor
+        property bool repaintTrigger: window.forceRepaint
+
+        onBgColorChanged: requestPaint()
+        onRepaintTriggerChanged: requestPaint()
+
+        onPaint: {
+            var ctx = getContext("2d")
+            ctx.fillStyle = bgColor
+            ctx.fillRect(0, 0, width, height)
+            console.log("🎨 Full screen background painted:", width, "x", height)
+        }
+
+        Component.onCompleted: {
+            // Force initial paint
+            requestPaint()
+        }
+    }
+
     // Rotation container for Pi 5 linuxfb
     Item {
         id: rotationContainer

+ 3 - 0
dune-weaver-touch/run.sh

@@ -63,6 +63,9 @@ elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
         echo "   Platform: Linux (using linuxfb backend)"
         export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
         export QT_QPA_FB_HIDECURSOR=1
+        # Hide console cursor (the blinking underscore)
+        echo 0 > /sys/class/graphics/fbcon/cursor_blink 2>/dev/null || true
+        setterm --cursor off > /dev/tty1 2>/dev/null || true
     else
         echo "   Platform: Linux (using xcb/X11 backend)"
         export QT_QPA_PLATFORM=xcb