Bad input lag in GNOME Wayland when run in fullscreen
An award-winning drawing program for children of all ages
Brought to you by:
wkendrick
Hi,
Tux Paint exhibits unusable input lag on GNOME (Wayland) when painting with the brush or any tool with a dynamically updated cursor. The problem happens only in fullscreen.
Every mouse motion event during painting triggers brush_draw() and finishes with SDL_RendererPresent() to update the screen. Unfortunately, each call to SDL_RendererPresent() waits for VSync and this produces the horrible lag.
I've tried to use the following without success:
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0")and SDL_RenderSetVSync(renderer, 0);Moving forward, I think Tux Paint's responsiveness could be improved by completing moving away from the rendering assumptions made in SDL 1.2 and decoupling frame rate from input rate.
Hi, thanks for reporting this,
this issue reminds me a report that came on a private mail, sumaryzing:
lag in fullscreen, work in windowed mode, run in Arch Linux (which uses SDL3 via sdl2-compat) with Plasma and a very high resolution mouse.
The user fixed it for himself by lowering the mouse resolution, and we added a filter in tuxpaint.c to discard very small mouse events.
https://sourceforge.net/p/tuxpaint/tuxpaint/ci/8c6f8a9dc3aa7f778efc263ed1a73c1401c1060c/
If you can compile Tux Paint from source, you could try if latest source solves also the lag on your computer.
HTH
Pere
FYI, I believe I can simulate the behavior under my environment (Kubuntu 24.04.4 LTS with X-Window) by shoving an
SDL_Delay(17);(approx. 1000 / 60) after the call tobrush_draw()in theevent.type == SDL_MOUSEMOTION->button_down || emulate_button_pressed->cur_tool == TOOL_BRUSHsection of the main event loop.I'm curious if the change Pere noted helps the actual situation under Wayland. Or if there are other "don't wait for vsync" hints we can add when opening our window...?
Hi,
The report was based on my experience on both the Flatpak and git master (96a8cde5).
Although I have a mouse running at 1000 DPI and high polling rate for gaming (first-person shooter), the issue has little to do with either.
I've inserted
SDL_GetTicks()into the code to measure the input (to display) latency and the results were extremely predictable, averaging around the display's refresh interval. When the refresh rate was set at 100Hz, the delay was 10ms. At 60Hz, it was around 15 to 17ms.There are a couple of solutions off the top of my head:
SDL_RenderPresent()from waiting on VSync. As mentioned, setting hints did not help in my case (SDL 2.32, GNOME 50+ Wayland)SDL_RenderPresent()SDL_RenderPresent()I am not sure which is the best way forward as I'm still unfamiliar with the behaviour of the SDL2 renderer API.
Last edit: Chong Kai Xiong 2026-05-23
Hi, I've just installed Wayland + Gnome in my box, here are some findings:
In SDL2,
I can force lag even in X11 windowed by creating the renderer with VSync enabled.
renderer = SDL_CreateRenderer(window_screen, -1, SDL_RENDERER_PRESENTVSYNC);
As noted, none of the documented ways to disable VSync works in SDL2 if I created the renderer with VSync enabled.
I do not understand why VSync is force enabled in Wayland + Gnome 50 + fullscreen, this doesn't happen in my box with Wayland + Gnome 48 + fullscreen(the latest available in Debian Sid)
Does Gnome 50 have any option to enable/disable VSync?
Now for SDL3:
(https://sourceforge.net/u/perepujal/tuxpaint/ci/sdl3/tree/)
I get lag if I set the VSync in the renderer to SDL_RENDERER_VSYNC_ADAPTIVE, but I can recover the right behavior by disabling VSync:
renderer = SDL_CreateRenderer(window_screen, NULL);
SDL_SetRenderVSync(renderer, SDL_RENDERER_VSYNC_ADAPTIVE); / This would enable lag /
SDL_SetRenderVSync(renderer, SDL_RENDERER_VSYNC_DISABLED); / This disables lag, and is the default when creating a renderer in SDL3 /
Hi again, the attached patch to the master branch is just a proof of concept, it fixes the lag on my box, but it is neither curated nor fully tested.
Basically it discards some screen refreshes if the lag is too much, more or less in the same way as we already discard mouse motion events if the computer can't process them.
First it creates the renderer with VSync enabled to be able to test in all conditions, this should not be in the final patch, I guess.
For the rendering stuff, it fully refreshes all the screen, SDL_UpdateRect() directly calls SDL_Flip() otherwise there was some parts not rendered that looked ugly, my box can handle full screen rendering happily, but this must be carefully tested in low end/older computers.
To test the lag, just comment out the "if(ignoring_refresh) return; lines" in the SDL_Flip() function, then uncomment them and see the difference.
HTH
Pere
Thanks @perepujal -- I've committed it in https://sourceforge.net/p/tuxpaint/tuxpaint/ci/d707ca93924f13fc4edca80c4939d89fa70ce4c1/
FYI, my system:
xorg-serverversion21.1.11sdl2-configreporting 2.30.0sdl-configreporting1.2.68)When I run
tuxpaint --fullscreen(no other options, so 800x600 mode):@descender can you pull down master branch and test whether Pere's patch helps under your environment?
Thanks in advance!
Hi William,
I've tested the latest from master. The issue persists for me.
Now it even seems to affect
--fullscreen=yes. Pop-up dialogs take a while to show up as well.I'm currently on Bluefin 44 (Fedora-based) running GNOME 50.1 on Wayland.
SDL versions:
sdl2-compat 2.32.68SDL3 3.4.10Display settings:
Tested with VRR on and off.
If it matters, my mouse resolution is at 1600 dpi, with a polling rate set to 2000Hz.
Last edit: Chong Kai Xiong 2026-06-09
I have also made a call for testing this patch over on the
tuxpaint-develmailing list (https://sourceforge.net/p/tuxpaint/mailman/tuxpaint-devel/).@descender -- Pere made another attempt, this time throwing the Tux Paint main loop into its own thread. I have just (finally) committed the change to
masterbranch, in https://sourceforge.net/p/tuxpaint/tuxpaint/ci/d7d87a5f72095ca6ed1b4defb8bfa43ccd28810e/Can you by any chance test this out and see if it helps your situation? (In the meantime, I'll post to
tuxpaint-maintainers@list to ask the port maintainers to check whether or not the change adversely affects anything.)@vindaci reports crashing on macOS, due to the fact that SDL_PollEvent() must be part of the main thread. So we either need to (a) address that (more reworking of the codebase), or (b) promote the new
MAINLOOP_THREADoption to a first-class compile-time option (i.e. inMakefile), so that certain builds can be created with & without this new feature.