Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] - Support for custom mouse cursors in sokol_app #615

Open
jeffkdev opened this issue Jan 17, 2022 · 3 comments
Open

[Feature Request] - Support for custom mouse cursors in sokol_app #615

jeffkdev opened this issue Jan 17, 2022 · 3 comments

Comments

@jeffkdev
Copy link

Sokol is close to supporting custom cursors icons with the addition of #78. I made a minimal implementation for Windows here
jeffkdev@54a44d9. I was thinking it would probably need to be changed to use pooled identifiers like the sokol_gfx resources. Currently sokol_app doesn't have any pooled resources, but if that was the eventual plan I could update the example do that as well.

I wasn't sure if this was worth tracking separately from the request of integrating cursors from sokol_imgui (#459). It looks like the author of that ticket is using cursor features from imgui internals, but ideally would be available in sokol_app directly. But feel free to close this if it feels like a duplicate.

@floooh
Copy link
Owner

floooh commented Jan 18, 2022

Looks like a good start. Yes, the cursor images should use a pool. The WIP multiwindow-branch has a sokol-gfx style pool integrated (for window objects), I can simply rip that out:

sokol/sokol_app.h

Lines 2641 to 2720 in 57688eb

/*=== POOL IMPLEMENTATION ====================================================*/
_SOKOL_PRIVATE void _sapp_init_pool(_sapp_pool_t* pool, int num) {
SOKOL_ASSERT(pool && (num >= 1));
/* slot 0 is reserved for the 'invalid id', so bump the pool size by 1 */
pool->size = num + 1;
pool->queue_top = 0;
/* generation counters indexable by pool slot index, slot 0 is reserved */
pool->gen_ctrs = (uint32_t*) SOKOL_CALLOC((size_t)pool->size, sizeof(uint32_t));
SOKOL_ASSERT(pool->gen_ctrs);
/* it's not a bug to only reserve 'num' here */
pool->free_queue = (int*) SOKOL_CALLOC((size_t)num, sizeof(int));
SOKOL_ASSERT(pool->free_queue);
/* never allocate the zero-th pool item since the invalid id is 0 */
for (int i = pool->size-1; i >= 1; i--) {
pool->free_queue[pool->queue_top++] = i;
}
}
_SOKOL_PRIVATE void _sapp_discard_pool(_sapp_pool_t* pool) {
SOKOL_ASSERT(pool);
SOKOL_ASSERT(pool->free_queue);
SOKOL_FREE(pool->free_queue);
pool->free_queue = 0;
SOKOL_ASSERT(pool->gen_ctrs);
SOKOL_FREE(pool->gen_ctrs);
pool->gen_ctrs = 0;
pool->size = 0;
pool->queue_top = 0;
}
_SOKOL_PRIVATE int _sapp_pool_alloc_index(_sapp_pool_t* pool) {
SOKOL_ASSERT(pool);
SOKOL_ASSERT(pool->free_queue);
if (pool->queue_top > 0) {
int slot_index = pool->free_queue[--pool->queue_top];
SOKOL_ASSERT((slot_index > 0) && (slot_index < pool->size));
return slot_index;
}
else {
/* pool exhausted */
return _SAPP_INVALID_SLOT_INDEX;
}
}
_SOKOL_PRIVATE void _sapp_pool_free_index(_sapp_pool_t* pool, int slot_index) {
SOKOL_ASSERT((slot_index > _SAPP_INVALID_SLOT_INDEX) && (slot_index < pool->size));
SOKOL_ASSERT(pool);
SOKOL_ASSERT(pool->free_queue);
SOKOL_ASSERT(pool->queue_top < pool->size);
#ifdef SOKOL_DEBUG
/* debug check against double-free */
for (int i = 0; i < pool->queue_top; i++) {
SOKOL_ASSERT(pool->free_queue[i] != slot_index);
}
#endif
pool->free_queue[pool->queue_top++] = slot_index;
SOKOL_ASSERT(pool->queue_top <= (pool->size-1));
}
/* allocate the slot at slot_index:
- bump the slot's generation counter
- create a resource id from the generation counter and slot index
- set the slot's id to this id
- set the slot's state to ALLOC
- return the resource id
*/
_SOKOL_PRIVATE uint32_t _sapp_slot_alloc(_sapp_pool_t* pool, _sapp_slot_t* slot, int slot_index) {
SOKOL_ASSERT(pool && pool->gen_ctrs);
SOKOL_ASSERT((slot_index > _SAPP_INVALID_SLOT_INDEX) && (slot_index < pool->size));
SOKOL_ASSERT(slot->id == SAPP_INVALID_ID);
uint32_t ctr = ++pool->gen_ctrs[slot_index];
slot->id = (ctr<<_SAPP_SLOT_SHIFT)|(slot_index & _SAPP_SLOT_MASK);
return slot->id;
}
_SOKOL_PRIVATE int _sapp_slot_index(uint32_t id) {
int slot_index = (int) (id & _SAPP_SLOT_MASK);
SOKOL_ASSERT(_SAPP_INVALID_SLOT_INDEX != slot_index);
return slot_index;
}

@floooh
Copy link
Owner

floooh commented Jul 6, 2022

Just linking this for cross-reference:

#678

...it's not "custom cursor images" just yet, instead hardwired/builtin cursor types as needed by Dear ImGui, but its another step in the general direction of user-provided mouse cursors.

@jeffkdev
Copy link
Author

jeffkdev commented Jul 19, 2023

If anyone stumbles on this in the future, this is how you can do it on the current sokol version on Windows: jeffkdev@5dbc11b

sapp handles the sapp_win32_update_cursor call now so the application doesn't have to do anything with the event anymore.

Edit: icon bool was flipped in initial commit. Updated in this: jeffkdev@094e04f

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

No branches or pull requests

2 participants