Skip to content

fix: web wallpaper init/properties, Steam path; configurable texture budget - #30

Merged
CaptSilver merged 11 commits into
CaptSilver:mainfrom
cyber-g0d:regression-fixes
Sep 15, 2026
Merged

CaptSilver merged 11 commits into
CaptSilver:mainfrom
cyber-g0d:regression-fixes

Conversation

@cyber-g0d

Copy link
Copy Markdown

Fixes regressions found while bringing the plugin to a working state on CachyOS / KDE Plasma 6 / Wayland (RTX 4090).

Web wallpapers (blank/white/black screen)

  • Expose setLoaded, pushGeneralProperties, pushUserProperties to QML as writable Q_PROPERTY (webobj.loaded, webobj.generalProperties, webobj.userProperties) instead of calling non-Q_INVOKABLE C++ methods. QML calls to plain public methods failed with TypeError: ... is not a function, breaking the init handshake and leaving web wallpapers (e.g. ASCII firework) blank.
  • settings.localContentCanAccessFileUrls = true so file:// sub-resources load from the injected data: wrapper.

Steam library path

  • config.qml: getProjectDirs(Common.urlNative(cfg_SteamLibraryPath)) so the base Steam path is preserved (was dropping to root-anchored /steamapps/...).

Scene texture budget (separate, in backend_scene submodule)

  • kMaxTotalBytes now overridable at build time via -DWEK_MAX_TEX_BYTES (default 2 GiB, #ifndef + CMake). A fixed 1 GiB cap dropped huge sprites (Hackercore 7680x8000) to 1x1 fallback (blank). Low-VRAM can lower; high-VRAM can raise.

Full details in README 'Known fixes'. Working-tree verified on CachyOS/Plasma 6/Wayland.

- SafeWallpaperBridge: expose 'loaded' as a writable Q_PROPERTY
  (QML previously called non-Q_INVOKABLE setLoaded -> TypeError,
  white screen for web wallpapers). QtWebView now writes webobj.loaded.
- config.qml: getProjectDirs(Common.urlNative(cfg_SteamLibraryPath))
  so the full absolute Steam library path is used (fixes root-anchored
  /steamapps/... watcher paths and broken web sub-resource resolution).
…urces

- SafeWallpaperBridge: generalProperties/userProperties now Q_PROPERTY WRITE
  (QML writes webobj.generalProperties/userProperties = ... instead of
  calling non-Q_INVOKABLE push* methods -> fixes 'not a function' TypeError
  that left web wallpapers initializing with defaults/blank).
- QtWebView.qml: localContentCanAccessFileUrls=true so bundle.js/style.css
  subresources resolve from the injected data: wrapper.
@takanashi-tetsuya

Copy link
Copy Markdown
Contributor

#29
mouse interaction does not work

@CaptSilver CaptSilver left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the point of adding this to the readme.. trying to keep the readme small.

@CaptSilver CaptSilver self-assigned this Sep 15, 2026
@cyber-g0d

Copy link
Copy Markdown
Author

Thanks for reviewing this. Agreed — I’ll remove the README additions and keep the README focused.

The functional changes are independent of that documentation:

  • SafeWallpaperBridge QML property/callability fix;
  • file URL access for web wallpaper sub-resources;
  • Steam library path/watch-path fix;
  • configurable texture budget.

I’m also treating the mouse-input change separately. The initial z:1000 fix restores web-wallpaper interaction but can interfere with Plasma desktop icon clicks, so I’m testing a safer event-routing approach rather than presenting the current workaround as a complete fix.

Regarding desktop mode vs folder mode: I’ll verify the behavior specifically in desktop mode and report the result before proposing another mouse-related change.

CaptSilver and others added 5 commits September 15, 2026 07:42
Fixes CaptSilver#29.

Since the QWebChannel surface of SafeWallpaperBridge was locked down,
its setters have been plain public methods. That keeps them off the
channel, but QML cannot call plain methods either, so the first
webobj.setLoaded(false) in QtWebView.qml threw a TypeError on every
web wallpaper load and the page never loaded at all. The QML tests kept
passing because they run against a stub whose setters are JavaScript
functions.

Giving the three properties a WRITE accessor makes QML assignment work
but also makes them settable by the page: QWebChannel dispatches
property writes through QMetaProperty::write regardless of whether the
setter is Q_INVOKABLE. So the properties stay READ + NOTIFY, and a new
SafeWallpaperBridgeController — a QML type that is never placed in a
WebChannel's registeredObjects — forwards Q_INVOKABLE setLoaded /
pushUserProperties / pushGeneralProperties to the bridge. QtWebView.qml
declares one per bridge and calls it where it used to call the bridge.

Tests: metaObject_allPropertiesAreReadOnly fails on a header with WRITE
accessors; metaObject_hasNoQObjectPointerProperty keeps the controller
unreachable through the bridge; tst_safewallpaperbridgecontroller drives
the real classes through a QQmlEngine and asserts loaded, both maps and
the sigInit / sigUserProperties / sigGeneralProperties signals — the
test that was missing when the setters went silent. The QML suite gets a
controller stub and a case asserting only the bridge is on the
WebChannel.
… notes

- settings.localContentCanAccessFileUrls = true in QtWebView.qml: this is
  QtWebEngine's default, and plugin.cpp already runs Chromium with
  --disable-web-security, which supersedes it.
- Common.getProjectDirs(Common.urlNative(cfg_SteamLibraryPath)) in
  config.qml: both consumers of workshopDirs already pass every
  directory through urlNative, so the wrap changes nothing; main.qml
  keeps passing the raw value to the same function.
- The README section "Known fixes in this branch" described the state of
  a branch rather than the project; the commit messages carry it.
… Plasma 6.6/Wayland"

This reverts commit e89afab.

Moving MouseGrabber from the desktop's icon and widget layer at z:-1 to
Window.contentItem at z:1000 puts it above Folder View icons, widgets
and drag-select for the whole screen, and mousePressEvent accepts every
press, so all of those stop receiving clicks whenever an interactive
wallpaper hooks the mouse. The hover re-delivery as a synthetic
MouseMove reaches every backend, not only the web one, so the scene
backend handles each hover sample twice with the buttons reported as
none; tst_mousegrabber::hoverMove_forwardsToTarget fails on it. The
message also says getMouseTarget() now returns web.children[0], but the
diff removes that binding and returns the view itself.

The observation that Chromium ignores QHoverEvents and needs a real
mouse move to update the page's cursor is worth its own change, gated
to the web backend and with a reproduction, in a separate pull request.
…6.6/Wayland

- MouseGrabber is created under Window.contentItem (was: QQuickGridView),
  so z:1000 outranks Plasma's desktop input layers globally; z:-1 left it
  behind a desktop input item and press/release were swallowed while
  hover still arrived.
- hoverMoveEvent re-delivers hover as a QMouseEvent(MouseMove): Chromium
  ignores synthetic QHoverEvents, so DOM mousemove never fired and
  interactive web wallpapers saw the cursor parked at (0,0) (creatures
  crawled into the top-left corner).
- getMouseTarget() targets the WebEngineView's internal input delegate
  (web.children[0]) — the only item that accepts synthetic mouse events;
  the view shell silently dropped them.
- PRESS/RELEASE qInfo logging for delivery verification.

Verified on Plasma 6.6/Wayland (CachyOS, RTX 4090): hover/press/release
reach the page, interactive reptile cursor tracks the mouse.
@CaptSilver
CaptSilver self-requested a review September 15, 2026 13:36

@CaptSilver CaptSilver left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything else needed changing here?

@cyber-g0d

Copy link
Copy Markdown
Author

Thanks for the update. The current PR state looks good, and the tester confirmed that it works on Plasma 6.6/Wayland. I agree that the mouse-event changes should remain separate from this PR.

One thing I noticed is that gh pr checks does not report any checks for the latest PR head, although the earlier Ubuntu, Arch, Fedora, and unit-test checks passed. Could you confirm whether this is expected after the latest commits?

…ime override

WPTexImageParser's cumulative budget now charges each mip only for the bytes it keeps resident (the compressed LZ4 source and stbi container bytes were charged although they are freed right after decoding), the MP4 placeholder is charged too, the default is 2 GiB, and WEKDE_MAX_TEX_BYTES / WEK_MAX_TEX_BYTES override it at runtime / build time. Large multi-frame sprites that the old 1 GiB cap replaced with a 1x1 fallback render again.
@CaptSilver
CaptSilver merged commit 5c3d184 into CaptSilver:main Sep 15, 2026
@CaptSilver

Copy link
Copy Markdown
Owner

I am not sure about that.. apparently I got an error..

This workflow run required approval but was not approved before it expired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants