Resizing on linux is incredibly slow [LINUX]
Software Versions
- Python: 3.12
- OS: Arch Linux
- Kivy: 2.3.1 from pip, and Archipelago bundled 2.3.1
- Kivy installation method: pip wheel and bundled package
Describe the bug when resizing the window, it remembers every frame and takes ages to get to each when resizing videos showing what i mean:
https://github.com/user-attachments/assets/91d43995-b18e-4999-9ea5-f2d3d265ae54 https://github.com/user-attachments/assets/da24aa7d-0df5-4c6c-9c37-72c83b72c273 one is the Archipelago app the other is the text example found in this repo, using kivy 2.3.1 from pip
Expected behavior resizing to behave, this isn't my system being slow, other applications work fine even during this process.
To Reproduce be on Wayland (unsure if wayland only) desktop on Arch Linux and resize any kivy app, can even use the text example found at: https://github.com/kivy/kivy/blob/master/examples/text/pango_demo.py
Additional context unsure if this is at all related to https://github.com/kivy/kivy/issues/8150, i don't think it is, as many xwayland apps don't have this issue, but i can't find anything else even tangentially related
also, when this is happening the UI of either app becomes unusable until it finishes - which makes this much much more frusterating.
I once had the same issue and worked around it by enabling "Don't show window content while dragging them" in my window manager settings. Your window manager probably has a similar option — I recommend trying it.
Can confirm, same happening on Linux in the Sideband application, and it's super annoying.
The issue is caused by this line: https://github.com/kivy/kivy/blob/9cc56fbd0da3c2654afe09a827d814c365d01d46/kivy/core/window/window_sdl2.py#L244
elif action == 'windowresized':
self._size = largs
self._win.resize_window(*self._size)
# Force kivy to render the frame now, so that the canvas is drawn.
EventLoop.idle() # <-- This is the problem
Since resize events will be queued and can be sent at a very high rate, that line forces Kivy to render a frame for each of the received resize events!
Probably, it should just be removed, or at least have some sort of throttling applied. I can't imagine that rendering every single resize event as a separate frame is the intended behaviour ;)
For anyone else who got too tired of this, here's a run-time patch to fix it from your own app:
###################################################
# Kivy/SDL2 run-time patch to fix horribly slow
# window resize updates on Linux. For more info:
# https://github.com/kivy/kivy/issues/9106
#
_sdl2_window_event_filter_original = None
_sdl2_window_event_filter_instance = None
def _sdl2_window_event_filter_proxy(action, *largs):
global _sdl2_window_event_filter_original
global _sdl2_window_event_filter_instance
if not action == 'windowresized': return _sdl2_window_event_filter_original(action, *largs)
else:
_sdl2_window_event_filter_instance._size = largs
_sdl2_window_event_filter_instance._win.resize_window(*_sdl2_window_event_filter_instance._size)
# The only change this patched method makes is to
# remove the offending "EventLoop.idle()" statement
# EventLoop.idle()
return 0
def patch_sdl_window_events(patch_target):
if RNS.vendor.platformutils.is_linux():
global _sdl2_window_event_filter_original
global _sdl2_window_event_filter_instance
_sdl2_window_event_filter_original = patch_target._event_filter
_sdl2_window_event_filter_instance = patch_target
patch_target._event_filter = _sdl2_window_event_filter_proxy
patch_target._win.set_event_filter(patch_target._event_filter)
#
# End of Kivy/SDL2 patch ##########################
# Somewhere in your code after app init:
patch_sdl_window_events(Window)