From 05b18bdadea848557be3eae0209d6b80be65fbd2 Mon Sep 17 00:00:00 2001 From: Florian Egger Date: Mon, 13 Jul 2026 13:38:46 +0200 Subject: [PATCH] Improve e-ink support with forced refreshes and no animations - Add `einkRefresh()` helper calling `pdlc-cli --refresh` after rotation, brightness changes, waveform changes, and when the widget opens - Disable CSS transitions and animations globally to reduce ghosting - Remove button hover transform and transition effects - Update README with e-ink-specific guidance and tuning notes --- pinenote-shell/README.md | 11 ++++++++++- pinenote-shell/src/main.js | 23 ++++++++++++++++++++++- pinenote-shell/style.css | 8 ++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/pinenote-shell/README.md b/pinenote-shell/README.md index ff9b73f..d92ea1f 100644 --- a/pinenote-shell/README.md +++ b/pinenote-shell/README.md @@ -226,10 +226,19 @@ Common customization options: 2. **Missing applications**: Ensure your preferred terminal/browser exist 3. **Hyprland compatibility**: Test basic `hyprctl` commands manually first +### E-ink / PineNote-specific Tweaks + +The code and CSS are already tuned for e-ink: + +- **No CSS transitions or animations** in `style.css` to avoid ghosting. +- **E-ink refreshes are triggered automatically** after rotation, brightness changes, waveform changes, and when the widget opens. +- If you still see ghosting, increase the refresh frequency or add `einkRefresh()` after other interactive actions in `src/main.js`. + ### Performance Issues - The widget is designed to be lightweight and efficient -- For best performance on PineNote, consider reducing animation frequency +- For best performance on PineNote, avoid animations and continuous polling +- E-ink displays update slowly; the app uses GObject signals instead of polling wherever possible - Monitor system resources with `htop` or similar tools ## Future Enhancements diff --git a/pinenote-shell/src/main.js b/pinenote-shell/src/main.js index 278324b..bd3c1f8 100644 --- a/pinenote-shell/src/main.js +++ b/pinenote-shell/src/main.js @@ -4,7 +4,7 @@ import app from "ags/gtk3/app" import { Astal, Gtk, Gdk } from "ags/gtk3" import { execAsync } from "ags/process" import { readFile } from "ags/file" -import { createBinding, createState, createComputed } from "ags" +import { createBinding, createState, createComputed, createEffect } from "ags" import Hyprland from "gi://AstalHyprland" import Brightness from "gi://AstalBrightness" @@ -20,6 +20,14 @@ const notify = (msg) => execAsync(["notify-send", msg]).catch(console.error) const toTitleCase = (str) => str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase()) +// --- e-ink helpers -------------------------------------------------------- + +function einkRefresh() { + // Trigger a full display refresh after actions that cause large visual changes. + // Silently ignore failures if pdlc-cli is not installed. + execAsync(["pdlc-cli", "--refresh"]).catch(() => {}) +} + // --- managers -------------------------------------------------------------- class BrightnessController { @@ -36,6 +44,8 @@ class BrightnessController { set(level) { if (!this.screen) return this.screen.brightness = level / 100 + // PineNote: force an e-ink refresh so the brightness change is visible + einkRefresh() } } @@ -63,6 +73,8 @@ class ScreenRotator { ]) notify(`Screen rotated to ${rotation}`) + // PineNote: e-ink needs an explicit refresh after rotation + einkRefresh() } catch (err) { notify(`Failed to rotate screen: ${err.message}`) } @@ -139,6 +151,9 @@ class WaveformController { execAsync(["pdlc-cli", "--waveform", waveform]).catch((err) => console.log(`Could not apply waveform: ${err.message}`), ) + + // PineNote: refresh after changing waveform mode + einkRefresh() } } @@ -155,6 +170,12 @@ function PinenoteShell() { const [visible, setVisible] = createState(false) + // PineNote: when the widget is shown, force an e-ink refresh so the + // overlay draws cleanly on the slow display. + createEffect(() => { + if (visible()) einkRefresh() + }) + const brightnessLevel = brightness.screen ? createBinding(brightness.screen, "brightness")((v) => Math.round((v || 0) * 100)) : createState(100)[0] diff --git a/pinenote-shell/style.css b/pinenote-shell/style.css index dbbe93f..c4b216c 100644 --- a/pinenote-shell/style.css +++ b/pinenote-shell/style.css @@ -1,6 +1,9 @@ * { margin: 0; padding: 0; + /* E-ink displays ghost badly with animations/transitions */ + transition: none; + animation: none; } window.pinenote-shell-widget { @@ -69,12 +72,13 @@ window.pinenote-shell-widget button { padding: 12px; margin: 8px; color: #ffffff; - transition: all 0.3s ease; + /* E-ink: no hover transitions */ + transition: none; } window.pinenote-shell-widget button:hover { background-color: rgba(97, 175, 239, 0.4); - transform: scale(1.05); + /* E-ink: avoid transform/scale which causes ghosting */ } window.pinenote-shell-widget .brightness-button {