Wayland support - #425
Conversation
|
Good stuff, let me know when you need some additional testing and code reviews :) |
ba05b57 to
b751909
Compare
|
Hey @floooh tl;dr: Operate on wayland input-events on a per-frame basis, or pipe them through sokol directly? I am currently working on combining wayland's input events (pointer, and touch) into sokol, and I am contemplating how to best approach this. Wayland has a mechanism called "pointer-frames", where multiple input events are batched together. Think of it as the compositor essentially accumulating individual events (e.g. mouse-move, button release, scroll-wheel, etc.) before comitting them as packages to the client. More or less. Similar to the option of comitting rendered frames to the compositor unchecked, or alternatively using the frame-callback to only render and eglSwapBuffer on demand. Theoretically I don't need to adhere to this pointer-frame mechanism, but it of course is the "wayland-way"™. I could also blindly pipe the events from wayland through sokol into the user event-cb. Good introduction for wayland pointer frames:
My questions for how I should proceed (also other questions regarding input-handling):
I hope these questions aren't too complicatedly formulated. ✌️ Edit: Whoops, didn't notice I was writing a short novel. 😅 |
|
Just some quick notes, I need to look in detail later into the linked documentation: Currently all backends directly forward most events from the platform to the sokol event callback. This means that it's not guaranteed when the event callback will be called relative to the frame callback and how often. E.g. it's not guaranteed whether mouse events can arrive at a higher-than-frame frequency or not (PS: uh this sounds wrong, of course a sokol-app event callback can never "interrupt" the frame callback because it runs on the same thread, but theoretically at least, the event callback might be called multiple times between two frame-callback invocations with mouse-moved events). Those "non-guarantees" also give more freedom for platforms that don't work that way. So for Wayland I'd say "whatever works best or is less code" :) Regarding "pointer-events" vs mouse-events and touch-events: If Wayland has separate event types for mouse- and touch-input, then those should be used to feed the sokol mouse- and touch-events. For instance UWP has generic pointer-events (which essentially tries to emulate a mouse pointer with touch input), and that's a mess (for instance when handling multiple pressed mouse buttons). If a sokol-app application wants to provide unified mouse- and touch-input, it should do so explicitely. Only the 4 "standard" low-level multi-touch event types should be implemented (if provided by Wayland): touches-began, touches-moved, touches-ended and touches-cancelled. This is basically the common set of touch events across platforms where more "sophisticated" cross-platform gesture recognizers can be implemented on top. But IMHO for the initial implementation we can also ignore touch events. |
b751909 to
5cd9115
Compare
|
After some more reading of the wayland references I have I found the way to add touch-support, but I was unable to test it due to lacking hardware. I did emulate the way wayland registers touch events using the pointer-callbacks and some dummy state machine, just to make sure my implementation doesn't misbehave for the most simplest cases (e.g. one touch-down, some movements, cancel/touch-up). ✌️ |
46a38c5 to
b4304b1
Compare
|
For transparency's sake: I spent the last couple of days getting to know the wayland way to implement pointer-locks, and I managed to implement a working solution in my wayland-only demo that I use for reference when adding wayland behavior to sokol. It turned out to have a bit more to it, than I thought. Generally what we need to do is:
Now functionality-wise this would be enough, but what I neglected until now was the display of a cursor image. When a pointer enters a wayland surface the cursor surface itself is in an undefined state. So to ultimately hide the cursor as described in the sokol header documentation text, we additionally need to:
Yeah, this is what I needed to find out to understand what I need to do to add this functionality to sokol. ✌️ |
|
IMHO if some sort of mouse capture works (meaning mouse coordinates are reported while a mouse button is pressed also when the mouse is outside the window area), then mouse-lock can be ignored in the beginning. IFIR on X11 and macOS this was automatically the case, only Windows needed special handling. Proper mouse lock (where the mouse pointer is hidden and the mouse doesn't bump against the screen borders) is mostly needed for camera-controls, while mouse capture is important for UI applications (e.g. grab a slider and drag it around with the mouse leaving the window area). |
3c9eaf8 to
741acf9
Compare
|
@floooh Can you outline, what the Situation in the wayland branch:
Now, theoretically I could emit the Any insights? I checked how sokol handles the Win and macOS capabilities, but neither documentation I found were rather helpful. I'll leave it out for now, but if you find the time to elaborate, it would help. Thanks in advance. 🙇♂️ ✌️ I noticed I am probably using a bunch of wayland-specific lingo that might not be obvious, feel free to inquire what I mean. 😜 |
|
UPDATE_CURSOR is a bit of a hack currently to allow application code to override the cursor image. Eventually this might be replaced with proper custom cursor image support similar to GLFW. You can ignore this in Wayland (currently UPDATE_CURSOR events are only generated in the Win32 and macOS backends). |
99e711a to
b5ee8a6
Compare
|
Two topics I contemplated today:
|
Hmmm that doesn't sound too good, depends of course how much needs to be added. How commonly are those extensions supported? What are the downsides of not embedding the required definitions? Are those headers hard to come by? |
As far as I can tell most wayland installations bring them all.
We would need require the user to:
Yes, they aren't distributed as C files, but as XML files. The user usually has to create the source files via the I suspect we can get away, if I wayland-scan the protocol extensions once, and hand-pick the necessary definitions/implementations into the sokol header. This way we would have access to the necessary signatures, and would not require the user to do anything on top. Again, I'll tinker a bit with it, and let you know with a working solution. This way you don't need to stress about it for now. 😄 |
I see, hmm, in that case I guess it's best to pick out the definitions we need and embed them in sokol_app.h, can't be worse than all the GL definitions in the Win32 GL loader ;) |
b5ee8a6 to
3a8399c
Compare
|
@floooh Moin. I am currently working through the drag'n'drop API of wayland and had a question regarding Sokol client's intended behavior regarding dnd-sources: Is there an entrypoint, where these clients start the dnd-operations as sources? All I found is how sokol clients are destinations for dnd. I will start implementing this particular part of the behavior. Let me know, if I am missing something relevant. Happy holidays [(already)|(belatedly)] (depending on when you read this message, and whether we interact again before then). ✌️ 😎 |
3a8399c to
a3cf191
Compare
|
Oh boi, I got caught up playing Bloodborne the last few weeks. 😅 I will try to focus now on this project a bit more. I rebased my branched on the latest master and will now work to get the drag and drop API working as intended. 👍 |
a3cf191 to
a508553
Compare
|
Finally managed to put the time and effort into adding support for drag and drop.
After that I will see to checking whether the rendering features need extra setup for wayland. Or maybe create a Github check to automate code testing for the wayland branch. Hey and after that I only need some code internal cleanup. So there is an end to the tunnel. 😅 ✌️ |
a508553 to
df75935
Compare
|
After drafting a first implementation of the primary selection support to sokol, I think I will rather remove this feature from the backlog. Couple of reasons:
It was not a lot of effort or even difficult to research and implement the functionality (you mainly have to add a primary selection device manager, get a device, register a callback, and read the offered selection). So if this will be requested in the future, let me know. ✌️🤓 |
|
I didn't even know what "primary selection" is and had to look it up ;) |
Oh right, I may have been too close to the substance. Primary Selection is a "feature" of the X display, that allows the user to highlight text to select in one application and pasting the implicitly copied text with the use of the middle mouse button. It is an alternative mechanism to the main selection buffer that requires the user to explicitly copy selected text. See here for a critical - because wayland-centered - view on the topic: https://wiki.gnome.org/Initiatives/Wayland/PrimarySelection |
I have two thoughts:
As reference only KDE supports SSD, Gnome doesn't. (Interestingly enough KDE was incepted because none of the apps at that time looked/felt the same.) A quick test yielded different CSD on Gnome for firefox and the libdecor demo application, the same apps on KDE Plasma was coherent.
Realistically this means without much political pressure this PR is only a baseline for others to work off of. I would maintain it if I so desire, but it will always "just" be a fork of sokol. Right?
I understand. What would you suggest then? I mean honestly I am a bit disappointed to abandon the work I already poured in it, but I have learned enough to have made it worthwhile for myself. The only consequence would be no built-in wayland support for sokol users (only maybe via xwayland). |
|
I was hoping this would lead to eventual inclusion of direct kmsdrm rendering but I get the idea of not cluttering things. Sokol is so close to being the perfect app wrapper for everything. Just not embedded or new display server for now. Very sad... |
|
To chime in, I too I'm eager to see this come to fruition, I think Sokol_app is awesome and being able to have a single header drop in replacement to GLFW is awesome as well, not that GLFW isn't awesome, it is, but from a portability pov having your graphical app being fully self-contained is highly appealing. I am also highly pleased with the progress made as I'm seeing nearly all of the check boxes have been ticked 🥳 kudos!! 👏🏼 |
|
I tried running this PR as-is with a sample program and also with it rebased to the latest master, but for both I get the same segfault at Some WIP on a rebase to latest master: master...digitalsignalperson:sokol-custom:wayland-pr-rebase If I test the original version, or the one rebased on master, I get a segfault during initialization. My setup is arch linux, and tested kde plasma 6.0.4 and sway compositors. Testing this from sokol-samples: Backtrace of the segfault: It fails when we call Also FYI you can use native wayland windows using GLFW with sokol (without sokol_app.h). I added my notes to that in #425 |
|
I got it working here master...digitalsignalperson:sokol-custom:wayland-pr-rebase after a couple small changes 22c243d
But so far I've only tested with the cube-sapp.c demo. Also for reference, the big section of protocol code can be generated with # xdg-shell-protocol:
wayland-scanner client-header \
< /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml \
> xdg-shell-protocol.h
wayland-scanner private-code \
< /usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml \
> xdg-shell-protocol.c
# pointer-constraints-unstable-v1-protocol:
wayland-scanner client-header \
< /usr/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml \
> pointer-constraints-unstable-v1-protocol.h
wayland-scanner private-code \
< /usr/share/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml \
> pointer-constraints-unstable-v1-protocol.c
# relative-pointer-unstable-v1-protocol:
wayland-scanner client-header \
< /usr/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml \
> relative-pointer-unstable-v1-protocol.h
wayland-scanner private-code \
< /usr/share/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml \
> relative-pointer-unstable-v1-protocol.cWhich could be included like this Would it make sense to let this code be autogenerated in a build script and reduced to those include lines? Or would that break with the single header philosophy... Regenerating that code today generates a huge number of lines which minus the comments I assume is identical to what is currently in the patch anyway. |
|
I made another branch to make maintaining a wayland fork easier: master...digitalsignalperson:sokol-custom:wayland-external This moved the whole wayland implementation into an external header so that if
So upstream changes to FWIW with respect to the stuff about gnome/decorations, for myself I don't care about those. I don't need window chrome or what I'm creating needing to look "native". If I wanted that I'd use Qt. The whole point for me using sokol is to be able to make any custom GUI/graphics I want, so it's pretty much the opposite of wanting native look and feel. Also for window moving and resizing Super+LMB to drag or Super+RMB to resize is my expectation from the compositor. That said, I totally understand if for the general case all these things being deal breakers for merging. By the way thank you @fleischie and @floooh for doing all this work/support in this PR to make wayland a possiblity! |
|
@digitalsignalperson Hello. 👋 First of all: Thank you for your effort. Second: I did make a mistake with the queue creation, which was hidden in previous versions of wayland (i.e. back when I first started with it). You cannot create an event-queue from a display and set it back onto the same display. In newer versions this is a segfault as you found out and your solution is also very much correct. I just never got around to fix it and update this PR. Third: I also thought about separating the wayland-branch from sokol's main header. This way development would have been easier to continue while keeping sokol's main development unencumbered. But I overall stopped spending time on this PR unfortunately. So again I really appreciate your effort. I don't know if I can muster the energy to update this PR itself after this long a time, or whether you want to take over. I'm still here and open for discussions if you want. 🙂 |
|
Hi @fleischie, thanks for the message. One technical question, I noticed when exiting the program it says warning: Any ideas where from? |
|
@digitalsignalperson I don't know for sure. I have some ideas how this works, but I need to check again.
Edit: I lied, the If you are very pedantic you could try to run the proxy-wrapper/queue destroy calls sequentially until you find the call, that triggers the warning you described. But practically if you already found a working solution I don't think it's necessary. 🤷 |
|
Ignoring those cleanup errors for now since they aren't the biggest issue, when trying more complicated applications things crash when calling wl_display_dispatch_queue_pending() with Many sokol-samples I try work as expected (cube-sapp, shapes-sapp, sdf-sapp). I'm getting the assertion fail with imgui-sapp, cimgui-sapp, nuklear-sapp. They show the window and appear to render at least enough frames I can see the full UI before it crashes. I thought maybe this is a hint https://bugzilla.mozilla.org/show_bug.cgi?id=1685055 but I think we are doing all of wl_display_prepare_read_queue(), wl_display_dispatch_queue_pending(), and reading events in the same thread. Maybe the issue is similar to the need for wl_proxy_create_wrapper for setting up the queue. Which I also realized the lifetime of the wrapper only needs to be like this I think struct wl_display* wrapped_display = (struct wl_display*)wl_proxy_create_wrapper(_sapp_wl.display);
_sapp_wl.event_queue = wl_display_create_queue(_sapp_wl.display);
wl_proxy_set_queue((struct wl_proxy *) wrapped_display, _sapp_wl.event_queue);
if (NULL == _sapp_wl.event_queue) {
_sapp_fail("wayland: wl_proxy_set_queue() failed");
}
_sapp_wl.registry = wl_display_get_registry(wrapped_display);
wl_registry_add_listener(_sapp_wl.registry, &_sapp_wl_registry_listener, NULL);
wl_display_roundtrip_queue(_sapp_wl.display, _sapp_wl.event_queue);
wl_proxy_wrapper_destroy(wrapped_display);but I didn't get anywhere with my naive poking around |
|
@digitalsignalperson shouldn't this be |
|
@fleischie searching for other usages, I find similar void update_wl_queue()
{
wl_display_roundtrip_queue(wl_display_ptr, queue);
}
void init_wayland_data()
{
if (!wl_display_ptr)
return;
struct wl_display *display_wrapped = (struct wl_display*)wl_proxy_create_wrapper(wl_display_ptr);
queue = wl_display_create_queue(wl_display_ptr);
wl_proxy_set_queue((struct wl_proxy*)display_wrapped, queue);
wl_registry *registry = wl_display_get_registry(display_wrapped);
wl_proxy_wrapper_destroy(display_wrapped);
wl_registry_add_listener(registry, ®istry_listener, NULL);
update_wl_queue();
update_wl_queue();
keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
update_wl_queue();
}where the vanilla display pointer is used for everything except wl_proxy_set_queue and wl_display_get_registry, and destroyed immediately after. Also interesting here https://github.com/intel/external-wayland/blob/7a4d77bc392e8a2225b8a52ec83959e206c6ab39/src/wayland-client.c#L1225 in wl_display_roundtrip_queue it creates a temporary wrapper. /** Block until all pending request are processed by the server
*
* \param display The display context object
* \param queue The queue on which to run the roundtrip
* \return The number of dispatched events on success or -1 on failure
*
* This function blocks until the server has processed all currently issued
* requests by sending a request to the display server and waiting for a
* reply before returning.
*
* This function uses wl_display_dispatch_queue() internally. It is not allowed
* to call this function while the thread is being prepared for reading events,
* and doing so will cause a dead lock.
*
* \note This function may dispatch other events being received on the given
* queue.
*
* \sa wl_display_roundtrip()
* \memberof wl_display
*/
WL_EXPORT int
wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue)
{
struct wl_display *display_wrapper;
struct wl_callback *callback;
int done, ret = 0;
done = 0;
display_wrapper = wl_proxy_create_wrapper(display);
if (!display_wrapper)
return -1;
wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
callback = wl_display_sync(display_wrapper);
wl_proxy_wrapper_destroy(display_wrapper);
if (callback == NULL)
return -1;
wl_callback_add_listener(callback, &sync_listener, &done);
while (!done && ret >= 0)
ret = wl_display_dispatch_queue(display, queue);
if (ret == -1 && !done)
wl_callback_destroy(callback);
return ret;
}That docstring also feels like it may have some useful hints, where we are also blocking until exhausting the event queue and using wl_display_dispatch_queue_pending per /* exhaust event queue */
while (0 > wl_display_prepare_read_queue(_sapp_wl.display, _sapp_wl.event_queue)) {
wl_display_dispatch_queue_pending(_sapp_wl.display, _sapp_wl.event_queue);
}
wl_display_flush(_sapp_wl.display);
int event_count = epoll_wait(_sapp_wl.epoll_fd, _sapp_wl.events, _SAPP_WAYLAND_MAX_EPOLL_EVENTS, -1);
for (int i = 0; i < event_count; i++) {
if (_sapp_wl.event_fd == _sapp_wl.events[i].data.fd) {
/* NOTE: check _sapp_wl_setup() for wl_proxy_set_queue()
* call, that sets the custom event_queue as proxy for
* default display, that's why the following call is not
* explicitly stating the queue to read events for/from */
wl_display_read_events(_sapp_wl.display);
}
}
_sapp_frame();
eglSwapBuffers(_sapp_wl.egl_display, _sapp_wl.egl_surface);
wl_surface_damage_buffer(_sapp_wl.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(_sapp_wl.surface);
wl_display_dispatch_queue_pending(_sapp_wl.display, _sapp_wl.event_queue); |
|
woot, progress! disabling the data_device listener (comment out also I think that last code snippet I pasted starting at "exaust event queue" can be reduced to wl_display_dispatch_queue(_sapp_wl.display, _sapp_wl.event_queue);
_sapp_frame();
eglSwapBuffers(_sapp_wl.egl_display, _sapp_wl.egl_surface);
wl_surface_damage_buffer(_sapp_wl.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(_sapp_wl.surface);where wl_display_dispatch_queue() looks like it's doing the same things https://gitlab.freedesktop.org/wayland/wayland/-/blob/main/src/wayland-client.c?ref_type=heads#L1999 Edit: eh not entirely sure about the last part. Just hacking around and breaking things trying to understand how things work.. |
|
Fixed the issue with data_device listener (clipboard handling issue) digitalsignalperson@6d1b636 Now imgui demos work with copy/paste, and I tested droptest-sapp works too Edit: Also fixed scrolling (x and y were backwards and inverted) and scaled them so one vertical mousewheel click scrolls 3 lines, and one horizontal mousewheel click scrolls about 5 columns. digitalsignalperson@30d94ff I'm curious for feedback if this is universal or just for my compositor and mouse Summary of changesPer: digitalsignalperson/sokol-custom@wayland-external-init...digitalsignalperson:sokol-custom:wayland-external (also this before refactor to seperate files master...digitalsignalperson:sokol-custom:wayland-pr-rebase)
|
|
Noting for window chrome, this could optionally be enabled in a really basic way with no dependencies in maybe a few hundred lines of C like in this example: https://github.com/danielwolbach/wayland-window/blob/main/source/main.c Aside: it'd be a fun project to make the chrome itself with sokol_gfx and do something like glowing/animated with shaders :) |
That sounds like a lot!!! Sokol should be able to do a window titlebar in under a 100 sloc... |
|
What exactly is "window chrome" referring to here? |
|
Is this still being worked on? I am hoping for proper wayland support for sokol as I want to avoid using xwayland.
I assume they mean the window decorations; the bar with window manager controls like maximize, minimize and close. On X11 there is also "window shadowing" which is hiding the window while keeping the window decorations visible which I believe is not part of the xdg-shell protocol on wayland. |
|
This PR isn't going to be merged. I mainly keep it around as a reference for some later hypothetical direct Wayland support (which isn't anywhere on my mental roadmap though). There's just still too many missing bits and pieces, like RenderDoc not working yet (although it seems like work has been started again: baldurk/renderdoc#853
You don't "use" xwayland, it's just there and used automatically ;) So far I haven't seen any downsides when running via XWayland to provide a consistency layer on top of the Wayland compositor. One thing I've been rolling around the back of my head is to add an SDL 'meta-backend' to sokol_app.h, on Linux this would also be a more robust solution than the native sokol_app.h backend since I'm sure that SDL has accumulated a lot more workarounds for compatibility problems than sokol_app.h over time. Also no ETA for that though :) |
I think it was already mentioned by other people that HiDPI does not work properly in Xwayland, which makes UI blurry (and no one wants to give their users a headache). Now as every major UI library got native Wayland support, you don't see this often in other apps. There is a workaround in a form of
|
|
I'm running a Wayland-only HighDPI laptop via Kubuntu for quite a while now and I cannot reproduce these issues except the last one (no DPI change when moving to a display with different DPI - even if XWayland would support that, sokol_app.h only polls DPI once at startup anyway on Linux). My DPI scale is 200% but even fractional scaling doesn't look any better or worse than on Windows (provided sokol_app.h runs with the Multiple displays with differing DPIs isn't a deal breaker - definitely not enough reason to replace the X11 backend with a Wayland backend (FWIW sokol_app.h didn't support dynamic DPI for a very long time on any platform). RenderDoc not working or missing window decorations because GNOME doesn't want to support server-side-decorations are dealbreakers though. FWIW if GNOME would support server-side-decoration that would help convince me that maybe Wayland is actually a good thing to support, but the way how everybody is writing their own Wayland implementation instead of joining forces and building a single Wayland implementation is just completely bonkers (like pretty much every idea coming out of Redhat IMHO). Those basic and fundamental design warts of Wayland have been discussed to death though, and with the snail's pace Wayland is progressing I'm planning to have a look once in a decade or so and maybe reconsider ;) |
|
I am contemplating closing this PR:
If I was to restart this project - i.e. native wayland support for sokol - I would probably create a util file that needs to be included additionally to the main sokol main app. |
|
@fleischie that sounds wise... This is getting nasty big. |
I really hope you reconsider, I think it's better to have a native wayland backend and use optionally (under a flag) use |
|
Tbh, it's more likely that sokol_app.h will get a meta-backend which calls into SDL for window management and input events, for Linux that would be the most robust solution since SDL is essentially a massive accumulation of workarounds for window system bugs and design warts. What Wayland really needs to be useful (for 3D API window system glue libraries at least) is an official and preinstalled client library that's designed by somebody who isn't locked in an ivory tower, and that client library should provide a common set of window system features, no matter what extensions the underlying Wayland compositor provides. Currently XWayland is that missing Wayland cient library, but it's only accessibly via shitty APIs (either xlib or xcb), but at least the feature set is complete. |
|
Having a SDL backend would be really nice (that could also mean access to gamecontrols + gyro). |
Hello,
after some effort to understand the (basic) in-n-outs of how to setup a wayland-client I embarked on adding support for wayland for the sokol_app.h header lib. I just started implementing this, but for transparency reasons I opted to make this PR public as soon as possible (i.e. after the first commit).
Supersedes #173
✌️
Todo:
sapp_frame()call from wayland's frame-done-cb unconditionally to main loopSend<- No priority for now.UPDATE_CURSORevent (need to clarify intent of this flag)Check if wayland natively supports setting the windowed-state<- Not as far as I can tellCheck if<- Not as far as I can tellICONIFIED/RESTOREDcan be supportedAdd support for primary selection (as made popular by X11, via protocol extension)Primary SelectionAdd server-side decorations.Add support for setting an app icon(not possible as far as I can tell)Note:
I will probably work this list from top to bottom (and thus re-arrange the list according to my personal priorities). Please let me know, if you have any comments/feedback/etc regarding this PR in general, the prioritized Todo-list, or regarding testing a specific feature. Especially as I am mainly using Sway, which being a tiling-manager may not be the most versatile environment to develop wayland-clients against (re: window decorations, auto-floating windows, etc.) But this can be arranged if a) desired, or b) necessary (after feedback).
Edits
Edit 2022-12-21:
Edit 2022-07-18:
app_idsetting again: It turns out it requires a more recent version oflibwayland-devthan what the Ubuntu distro of the CI provides. (I am using Arch locally and it has v1.21, Ubuntu seems to have v1.18). As this feature was a relatively small patch, this shouldn't be too problematic currently.Edit 2022-07-01:
app_id, which is used by the compositor to figure out the relevant .desktop-file and group apps, etc.,Edit 2022-06-17:
SOKOL_CALLOC/SOKOL_FREEwith the updated_sapp_malloc/_sapp_free,Edit 2021-09-23:
Edit 2021-09-02:
Edit 2021-03-07:
Edit 2021-02-23:
Edit 2021-02-21:
gl_force_gles2request) as well as query egl context for ultimately used api version,Edit 2021-02-14:
Edit 2021-02-12:
Edit 2021-02-11:
Edit 2020-12-20:
Edit 2020-12-03:
Edit 2020-12-02:
UPDATE_CURSORtodo. (I'll add a comment to the PR discussion about my thoughts.)Edit 2020-12-01:
Edit 2020-11-24:
Edit 2020-11-22:
Edit 2020-11-19:
Edit 2020-11-13: