Release v1.1.4 - #51
Merged
Merged
Conversation
LVGL's keypad handling already synthesizes a CLICKED event after an ENTER key release for the focused object (indev_keypad_proc in lv_indev.c). pref_checkable_activate() and idr_checkbox_activate() were also listening on LV_EVENT_KEY for ENTER, so a single remote OK press fired the toggle twice, visually canceling out. Drop the redundant LV_EVENT_KEY registration/handling; CLICKED alone covers touch and remote/keypad activation.
apps_list_detect_change() always returned a NULL changes pointer, even when it determined the list was identical (num_changes=0). lv_gridview_set_data_advanced() treats changes==NULL as 'invalidate everything' regardless of num_changes, so every single poll -- even ones where nothing changed -- fully recycled and rebuilt every visible tile. Compounding this, appitem_bind() unconditionally called coverloader_display() on every rebind, restarting the cover art load even when the tile was already showing the correct app. Together these caused a visible flicker on every ~10s poll. Fixed by having apps_list_detect_change() return a non-NULL (if empty) sentinel whenever num_changes=0, so the widget skips the unnecessary full rebuild, and by skipping coverloader_display() in appitem_bind() when the view is already displaying the right app's cover. Confirmed via git history and a live fetch of mariotaku/moonlight-tv's current source that both of these are latent bugs shared with upstream, not something introduced by this fork.
apps_list_detect_change() flags almost any poll result as 'different' (e.g. the backend returning apps in a new order), forcing a full grid rebuild via lv_gridview_set_data_advanced(). lv_gridview itself already protects the currently-focused item's view from being recycled during that rebuild, so focus survives on its own whenever the grid currently owns input focus. The actual cause of the reported 'loses focus every ~10s' bug turned out to be elsewhere: show_ok() -- called on every successful poll via update_view_state(), not just on a genuine state transition -- unconditionally called lv_gridview_focus() using focus_backup, which is only updated on blur and never reflects live in-grid navigation. This silently snapped focus back to a stale position every ~10s regardless of where the user had actually navigated to. Confirmed via git blame that this unconditional call was added in 683e240 ('Add fractional refresh support and input improvements'); upstream's show_ok() has no such call. Fixed by only applying explicit focus there when the grid doesn't already have one. Also fixed a related, separately-diagnosed bug: lv_gridview_focus() reports its FOCUSED event via lv_indev_get_act(), which is NULL whenever focus is applied programmatically (group-focus mechanics, fragment lifecycle) rather than from a live keypress. LVGL's event handler only applies LV_STATE_FOCUS_KEY for a genuine keypad/encoder indev, so tiles focused this way were internally correct (grid->focused_index) but showed no selection outline at all. Added gridview_focus_with_key_state() to force the state directly after every programmatic focus call (show_ok, applist_focus_enter, apps_focus_rail, and launcher.controller.c's focus_detail), matching the pattern upstream's set_detail_opened() already uses for non-gridview objects. Also fixes a latent use-after-free: focus was being applied via lv_gridview_focus() before lv_gridview_set_data_advanced() updated the grid's internal data pointer, so it could bind against the apploader list we'd just freed. Reordered so data updates before focus.
Two code paths handle wheel scrolling for settings panes and host lists: wheel_handle_scrollable() for lists that overflow their visible area, and an enc_diff (LVGL encoder) fallback for lists that fit without needing to scroll. Both had their sign backwards relative to wheel_handle_gridview's established convention (wheel down / y > 0 reveals forward/later content) — confirmed and fixed on-device.
The shared settings 'detail' scroll container calls lv_obj_remove_style_all(), which also strips any scrollbar appearance, and nothing in the theme styles LV_PART_SCROLLBAR globally — so this pane (used by all settings panes, including Host) never showed a scrollbar at all. Add a plain muted-gray thumb matching native/browser scrollbar conventions.
wheel_handle_scrollable() scrolled with LV_ANIM_ON, queuing a ~200-400ms animation per wheel tick. Scrolling quickly outpaced the animation, making it feel sluggish/laggy compared to native/browser scrolling, which tracks input directly rather than animating each discrete tick. Switch to LV_ANIM_OFF.
appitem_style_init() set shadow_opa/shadow_width once (40/16, the intended subtle values per the comment above it), then immediately overrode both to 50/24 a few lines later -- a pre-existing duplicate that predates this branch (already present in upstream/main). With radius only LV_DPX(6), a shadow blur that much larger than the corner radius reads as a squared-off glow rather than a soft rounded shadow, which became clearly visible once the corner-rounding fix switched selection to a flush shadow-only style. Removed the duplicate so the smaller, actually-intended values apply.
Fixes a white/oversized border around the Aurora icon on the LG home screen: 1. icon.png/icon_large.png were shipped at 130x130/512x512 -- 1.6x and ~4x larger than webOS's actual slots (80x80/130x130, confirmed via both LG's docs and moonlight-tv's pre-rebrand assets). webOS was downscaling and letterboxing them, padding the leftover space with iconColor. 2. iconColor was left at the webOS-default #ffffff. Per LG's docs, iconColor is the app tile's permanent background, always visible behind the icon -- not just a fallback for transparent pixels. webos-homebrew-channel's appinfo.json confirms the convention: its iconColor (#cf0652) deliberately matches its own icon's branding, not left at the default. 3. The icon source baked in an inconsistent two-tone background (a dark rounded-square card on top of a separately-black canvas, not quite the same color, with rounded corners that any rectangular crop couldn't match) -- extracted the mark from a cleaner source instead, recomposed on a flat background matching the new iconColor (mariotaku#618), with padding matched to other apps' icon proportions on a live LG home screen.
The remaining square-shadow artifact on focused/unfocused tiles came from the soft drop shadow itself, not the corner radius/border fix from the previous commit -- against a near-black OLED background, LVGL's shadow blur has no darker tone to fade into, so it renders as a visible hard-edged rectangle around the rounded corners rather than a soft falloff. Since the theme targets OLED displays where shadows serve no purpose anyway, removed the cover-art shadow entirely (shadow_opa set to LV_OPA_TRANSP) instead of tuning it further. Selection remains indicated by the outline only.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…d chord Co-authored-by: Cursor <cursoragent@cursor.com>
Forward Select/Start to the host immediately instead of a same-frame pulse, and require a 4s hold for stats/virtual mouse toggles. Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the 4K-only integer mode override so NTSC presets send mode=WxHx119.88 (etc.) at all resolutions, matching non-4K behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep fractional NTSC out of 4K launch mode to avoid C5 black screen, remove the 3.6K resolution preset now that native 4K is the path, and document that bitrates above 250 Mbps rarely help and can increase loss. Co-authored-by: Cursor <cursoragent@cursor.com>
This was referenced Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pauseAtDecodeTimesetting + Starfish render-queue depth (RQ) in the stats overlayIncluded pull requests
Instrumentation (C5 4K investigation)
Pause at decode time (Starfish)toggle (default on; independent of Smooth frame pacing)SS4S_PlayerGetVideoRenderQueueLength+ overlayRQto observe Starfish backlog growth vs NDL QTest plan
RQgrows with delay; optional A/B with pause-at-decode-time off