OK, solved this the old way - using the cursor module - and it works smoother than the mouse cursor on my other setup that had not required it.
for my setup I redirect the KIVY_HOME variable to be part of my project or git repo and then copy the cursor.py module from the kivy installation folders into my local one
I did some optimizations for performance - below and added the ability to pass the exact display size and then one could
switch out the mouse function as desired. my setup is a machine that has to perform fast so I desired to reduce the
__all__ = ('start', 'stop')
from kivy.core.image import Image
from kivy.graphics import Color, Rectangle
from kivy import kivy_data_dir
from kivy.compat import string_types
from os.path import join
from functools import partial
# this is of course hard-coded to a certain screen size
# to use a different screen size copy and edit this function and change the displaywy
# parameter sent from the ini file
def _mouse_move_constrain(win, pos, /):
_x = pos[0]
_y = pos[1] - 26
# some constraints just to keep the cursor on the screen but they are not strictly necessary
if _x > 1910:
_x = 1910
if _y < -21:
_y = -21
win._cursor.pos = _x, _y
def _mouse_move_free(win, pos, /):
#
win._cursor.pos = pos[0], pos[1]
def _mouse_move(texture, size, display_size, win, pos, *args):
global startup_fun
if hasattr(win, '_cursor'):
# this is unlikely to run because we unbind this function on first call
c = win._cursor
c.pos = pos[0], pos[1] - 32
else:
# this is going to run ONE time per program run
with win.canvas.after:
Color(1, 1, 1, 1, mode='rgba')
win._cursor = c = Rectangle(texture=texture, size=size)
win.unbind(mouse_pos=startup_fun)
print("display size passed to $KIVY_HOME/mods/mycursor.py module is: {}".format(display_size))
if display_size == [1920, 1080]:
win.bind(mouse_pos=_mouse_move_constrain)
else:
win.bind(mouse_pos=_mouse_move_free)
"""
Start/stop are functions that will be called for every window opened in Kivy. When you are starting a module, you can
use these to store and manage the module state. Use the ctx variable as a dictionary. This context is unique for each
instance/start() call of the module, and will be passed to stop() too.
"""
def start(win, ctx):
global startup_fun
# this will run when Kivy is loaded - one time
cursor_texture = Image(
ctx.config.get('texture', join(kivy_data_dir, 'images', 'cursor.png'))
).texture
cursor_size = ctx.config.get('size')
if isinstance(cursor_size, string_types):
cursor_size = [int(x) for x in cursor_size.split('x')]
elif not cursor_size:
cursor_size = cursor_texture.size
# make sure to include a default size
displaywh = ctx.config.get('displaywh', [1920, 1080])
if isinstance(displaywh, string_types):
displaywh = [int(x) for x in displaywh.split('x')]
startup_fun = partial(_mouse_move, cursor_texture, cursor_size, displaywh)
win.bind(mouse_pos=startup_fun)
def stop(win, ctx):
# unknown if this ever runs. maybe if there is a way to unload the module then it will
win.unbind(mouse_pos=_mouse_move_constrain)