I did a few experiments on Windows11, there does not seem to be a way to get a touch event for a window that is not in focus. The touch that gets the Window in focus, does not fire the on_mouse_down or on_touch_down events. I also experimented with the EventManagerBase class, same result. The hover events work as expected, but the touch events are only sent when the Window is in focus.
I realized that we know that when the window comes into focus, we know that there was a touch on the window. Below is the idea roughly implemented – but It demonstrates the idea can work. I bind a callback to Window.focus. We know that a touch event occurred at the current mouse position. I use that info to walk with widget tree, and dispatch the proper events. The example below will work for a button, this can be easily extended to work for other widgets including a TextInput.
The code below includes a number of failed experiments that I have left in – but commented out, in case you want to experiment with them…
I manually changed the state of the button so the user sees the familiar button press.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.eventmanager import EventManagerBase
from functools import partial
kv = """
AnchorLayout:
Button:
size_hint: None, None
size: 200, 48
text: 'Touch Me'
on_press: print('button pressed')
on_release: print('button released')
"""
# class MotionButton(Button):
# def on_kv_post(self, base_widget):
# self.register_for_motion_event('hover')
#
# def on_motion(self, etype, me):
# print(f'{etype=} {me=}')
#
# class TouchHoverManager(EventManagerBase):
# type_ids = ('touch', 'hover')
#
# def start(self):
# # Create additional resources, bind callbacks to self.window
# pass
#
# def dispatch(self, etype, me):
# if me.type_id == 'touch':
# print('Touch event in dispatch')
# # Handle touch event
# elif me.type_id == 'hover':
# print('hover event in dispatch')
# # Handle hover event
#
# def stop(self):
# # Release resources
# pass
class WindowTouchApp(App):
def build(self):
# Window.bind(on_mouse_down=self._mouse_down)
# Window.bind(on_touch_down=self._touch_down)
# Window.bind(on_cursor_enter=self._cursor_enter)
# Window.bind(on_motion=self._motion)
Window.bind(focus=self._focus)
# Window.register_event_manager(TouchHoverManager())
return Builder.load_string(kv)
# def _mouse_down(self, obj, x, y, button, modifiers):
# print('mouse down')
# print(f'{obj=} {x=} {y=} {button=} {modifiers=}')
#
# def _touch_down(self, obj, touch):
# print('touch down')
# print(f'{obj=} {touch=}')
#
# def _cursor_enter(self, obj):
# print('cursor enter')
# print(f'{Window.focus=}')
# # if Window.focus == False:
# # Window.minimize()
# # Window.restore()
def _focus(self, win, value):
print(f'focus changed: focus={value} ')
if value:
pos = win.mouse_pos
print(f'{win.mouse_pos=}') # we know there was a touch event here
for w in self.root.walk_reverse(loopback=True):
print(w)
if w.collide_point(*pos) and isinstance(w, Button):
print('Button Collision Detected')
w.dispatch('on_press')
w.state = 'down'
p = partial(self._release_button, w)
Clock.schedule_once(p, .3)
return
def _release_button(self, button, _):
button.state = 'normal'
button.dispatch('on_release')
# def _motion(self, obj, etype, motionevent):
# print(f'motion {etype=} {motionevent=}')
WindowTouchApp().run()
--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63512c5f.9d0a0220.1d7c7.f5a4%40mx.google.com.
I’m glad to hear that worked out for you. One thing that has occurred to me and may require some additional testing is if a popup window is open. When the Popup is open the Window has 2 objects in the children list, the root widget and the popup. I’m not sure how Widget.walk() treats the popup window. You would want to make sure you look at the widgets in the Popup first (when the popup is open). Using pyautogui to generate a click() is a clever idea – that would cover all of the cases.
I suspect you could also create a MotionEvent with the pos data and have the Window Dispatch it…
https://kivy.org/doc/stable/guide/architecture.html?highlight=touch#widgets-and-event-dispatching
https://kivy.org/doc/stable/api-kivy.input.motionevent.html#module-kivy.input.motionevent
Good luck and enjoy!
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63574408.050a0220.5b739.3ea6%40mx.google.com.
Very interesting as I read the first of these recent messages, I thought there is no way to fix this – but perhaps hacking the underlying windowing system. I will be amazing if you can get the desired behavior from an environment variable!
I’ll give it a try.
“Would you happen to know if kivy-deps.sdl2 0.5.0 corresponds with SDL 2.0.5?” I don’t know. Some of the kivy devs are in the kivy discord. They might know.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63583dff.050a0220.dfd40.5370%40mx.google.com.
I did a quick test, setting the environment variable does not work. Then I found this: https://wiki.libsdl.org/CategoryHints
“The convention for naming hints is SDL_HINT_X, where "SDL_X" is the environment variable that can be used to override the default.”
I changed the environment variable name and…
It WORKS!!!
import os
os.environ["SDL_MOUSE_FOCUS_CLICKTHROUGH"] = '1'
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/6358793c.170a0220.6971e.6765SMTPIN_ADDED_MISSING%40gmr-mx.google.com.
Here you go:
[INFO ] [deps ] Successfully imported "kivy_deps.gstreamer" 0.3.3
[INFO ] [deps ] Successfully imported "kivy_deps.angle" 0.3.2
[INFO ] [deps ] Successfully imported "kivy_deps.glew" 0.3.1
[INFO ] [deps ] Successfully imported "kivy_deps.sdl2" 0.4.5
[INFO ] [Kivy ] v2.1.0
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63588837.050a0220.836d0.afbc%40mx.google.com.
Looking through the SDL docs – this is not a new feature. I would expect it will work for you on the older version.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/63588b3d.540a0220.5ac1.692a%40mx.google.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/6359295e.050a0220.9649e.7c17%40mx.google.com.