Skip to content

feat: add multiple project-owned custom cursor sets - #1098

Draft
prokop-solutions wants to merge 7 commits into
getopenscreen:mainfrom
prokop-solutions:codex/custom-cursor-upload
Draft

prokop-solutions wants to merge 7 commits into
getopenscreen:mainfrom
prokop-solutions:codex/custom-cursor-upload

Conversation

@prokop-solutions

@prokop-solutions prokop-solutions commented Oct 10, 2026 •

Copy link
Copy Markdown

Summary

The cursor picker currently offers bundled artwork only. This adds a (+) button with three image-only PNG/JPEG upload slots for arrow, hand, and text (I-beam) cursors. Uploading one image is enough; missing states use the default artwork.

The (+) button creates another independent set; at least five are supported, with no fixed set-count cap. Selecting a saved set opens its editing panel. Re-uploading a slot replaces only that set's image. Each image can be removed, or that set deleted, without losing other sets. Removing the selected set's last image restores Default. These changes use existing project undo history. Escape and outside clicks close the panel, and hand/text remain available in Cursor types.

Sets have stable IDs and persisted numbers, displayed through localized labels (English: Custom 1, German: Benutzerdefiniert 1). Deleting set 2 does not rename sets 3-5. An existing single custom upload is migrated on read; canceling an empty new panel creates no stored set. Presets carry the selected set's artwork and applying one preserves other project sets.

Images are embedded in the .openscreen project as data URLs, so reopening does not depend on the original upload paths. The existing native sprite pipeline uses those images for preview and export. Custom images also round-trip through style presets and the look inherited by new projects. New labels are translated across all 15 locales.

Custom images default to the corresponding hotspot from the first/default cursor set. Each image now has a hotspot editor (pencil button): set the point on the image, fine-adjust with arrow keys or X/Y percentage inputs, reset to default, and inspect a fixed-target preview at 100–200% zoom on light/dark backgrounds. Hotspots persist with each set and round-trip through presets, undo history, save/reopen, and the native scene pipeline. Uploading opens a draft editor; Cancel does not save the image or create an empty set. Saved set slots display their actual uploaded artwork.

This follow-up addresses configurable hotspot alignment, not a complete solution for alpha, size consistency, or custom Glass rendering across all renderers. The PR remains a draft pending the maintainers rendering direction.

Related issue

Fixes #1060

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging
  • Not platform-specific

Screenshots / video

Original prototype screenshot from #1060. This PR additionally supports multiple saved sets, plus per-image remove and delete-set controls shown as trash icons with tooltips.

Custom cursor upload panel

Hotspot editor follow-up

Hotspot editor with 200% preview zoom

Saved custom artwork and edit controls

Testing

  • npm run test: 320 files passed, 4,484 tests passed, 1 existing test skipped.
  • npx tsc --noEmit and npx tsc -p tsconfig.test.json --noEmit: passed.
  • npm run lint, npm run lint:fix, npm run i18n:check, npm run docs:check, and git diff --check: passed. Biome reports existing warnings, without errors.
  • npm run build-vite: passed. Built and ad-hoc signed a separate arm64 macOS QA app with the current Metal compositor and Swift helpers rebuilt. Local build environment changes are excluded from this PR.
  • Real OS mouse/keyboard smoke test on macOS 26.7.1: upload, replace, add all three states, remove one, delete all, Undo, default fallback, outside-click/Escape dismissal, save and app restart. Checked the project and a saved style preset contain the image data. A neutral 3-second fixture exercised arrow/hand/text states; native MP4 (640x480, 60 fps) and GIF (640x480, 15 fps) exports completed, and decoded frames at 0.5/1.5/2.5 seconds showed the corresponding uploaded artwork.
  • Follow-up real desktop pass on the multiple-set build: migrated the first set, uploaded four more, edited/deleted only set 2, verified remaining numbers, restored it with Undo, then saved and restarted with all five sets and the selected fifth set intact. Native preview and a fresh MP4 export displayed set 5's artwork (decoded the 0.5-second frame).
  • The partial desktop pass is recorded in technical-documentation/testing/manual-e2e-checklist.md. Fresh screen/audio/webcam recording, 3D cursor comparisons, unrelated editor features, and Windows/Linux desktop passes were not run; this is not release-promotion QA. GIF/preset desktop checks were not repeated after adding multiple sets; their automated tests pass.

Hotspot follow-up: both TypeScript checks, renderer build, lint/format, i18n/docs checks and full unit suite passed. Additional partial macOS desktop checks covered hotspot click/keyboard/numeric editing, light/dark backgrounds, Apply/Cancel/reset, Undo/Redo, save/restart and native 2D/extruded-3D preview and MP4 export. Decoded 2D frames confirmed the expected hotspot displacement. Preview zoom endpoints and uploaded set thumbnails were inspected in the installed app. Reliable OS drag verification, Glass behavior, Windows/Linux and release-promotion QA were not covered; pointer mapping/clamping is unit-tested.

Regression coverage includes five independent sets in English/German, stable numbering, legacy migration, duplicate/invalid set filtering, blank-MIME uploads, independent replacement, image/set deletion, project save/reload, preset round-trips without discarding other sets, and passing embedded sprites into native scenes.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@prokop-solutions prokop-solutions changed the title feat: add project-owned custom cursor uploads feat: add multiple project-owned custom cursor sets Oct 10, 2026
@EtienneLescot

EtienneLescot commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Thanks a lot @prokop-solutions, and sorry for the confusion: I closed this too fast, so it's reopened. We invited this PR, and the feature just isn't ripe on our side yet: keeping a custom image right across the 2D, 3D and Glass cursor renderers (alpha, size, hotspot) needs more thought before we review it. We'll come back to it here.

@prokop-solutions

prokop-solutions commented Oct 10, 2026 •

Copy link
Copy Markdown
Author

Thanks @EtienneLescot for taking the time to look into this and for clarifying the rendering concerns. No worries about reopening it!

Following your feedback, I have built and tested a hotspot editor on top of the custom cursor sets and now added the implementation to this draft PR (through ab28b3b). The PR description has been updated with the expanded scope and validation.

  • Each uploaded arrow, hand or text image can have its own hotspot, stored with the image in the project and carried through presets.
  • The editor supports setting the point on the image, fine adjustment with arrow keys and X/Y percentage inputs, and resetting to the corresponding hotspot from the first/default cursor set.
  • A fixed-target preview offers 100–200% zoom and light/dark backgrounds to inspect alignment without changing the actual video cursor size.
  • Existing images can be reopened via the pencil button; the set panel now displays the uploaded artwork rather than a generic upload icon.

Local macOS checks covered save/reopen, Undo/Redo, and native 2D and extruded-3D preview/MP4 export. A decoded 2D export confirmed that changing the hotspot moves the sprite by the expected amount. The latest local unit suite passes (4,484 tests; one skipped).

Would configurable, project-owned hotspots like this help address the hotspot/alignment part of the concern you mentioned? I have included it here for discussion, but can split it into a separate follow-up if that fits your preferred scope. I do not assume it resolves alpha handling, consistent sizing, or Glass renderer behavior; those still need a shared rendering decision and broader validation. No rush to review: I am happy to wait for your rendering direction.

Screenshots of the local prototype (German UI):

codex-clipboard-ba2dd1c3-560b-4a5c-a80a-c278b27fea86 openscreen-custom-set-current

This branch has not been deployed

No deployments
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.

[Feature]: Upload custom cursor images for arrow, hand, and text cursor

2 participants