From 76229f9c195896958fe957feace5e2342cdd2ba9 Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sun, 30 Nov 2025 20:55:10 +0100 Subject: [PATCH 1/8] Hover: Added module level docs for HoverManager. --- kivy_garden/hover/__init__.py | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index 2881415..1d31a0c 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -1,3 +1,62 @@ +""" +Hover manager and behavior +========================== + +This module defines three classes to handle hover events: + +1. Class :class:`HoverManager` provides dispatching of hover events to widgets + in :attr:`~kivy.core.window.WindowBase.children` list. +2. Class :class:`HoverBehavior` handles hover events for all widgets who + inherit from it. +3. Class :class:`MotionCollideBehavior` provides filtering of all events + (not just hover events) in such way that only grabbed events or events who + have "pos" in :attr:`~kivy.input.motionevent.MotionEvent.profile` and can + pass a collision check are passed through the + :meth:`~kivy.uix.widget.Widget.on_motion` method. + +A hover event is an instance of :attr:`~kivy.input.motionevent.MotionEvent` +class with its :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to +"hover". + +HoverManager +------------ + +Manager is responsible for dispatching of hover events to widgets in +the :attr:`~kivy.core.window.WindowBase.children` list. Widgets who registered for +hover events will receive them in their +:meth:`~kivy.uix.widget.Widget.on_motion` method. + +For your app to use a hover manager, you must register it with +:meth:`~kivy.core.window.WindowBase.register_event_manager` when app starts in +and then unregister it with +:meth:`~kivy.core.window.WindowBase.unregister_event_manager` when app stops. + +Example of how to register/unregister a hover manager:: + + from kivy.app import App + from kivy_garden.hover import HoverManager + + class HoverApp(App): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.hover_manager = HoverManager() + + def on_start(self): + super().on_start() + self.root_window.register_event_manager(self.hover_manager) + + def on_stop(self): + super().on_stop() + self.root_window.unregister_event_manager(self.hover_manager) + +Manager expects that widgets will grab the event if they want to always receive +event type "update" or "end" for that same event and also ungrab it when they +no longer want to receive it. To grab the event use +:meth:`~kivy.input.motionevent.MotionEvent.grab` and to ungrab use +:meth:`~kivy.input.motionevent.MotionEvent.ungrab`. +""" + from collections import defaultdict from kivy.eventmanager import EventManagerBase, MODE_DONT_DISPATCH @@ -24,8 +83,8 @@ class HoverManager(EventManagerBase): type_ids = ('hover',) event_repeat_timeout = 1 / 30.0 - """Minimum wait time to repeat existing static hover events and it - defaults to `1/30.0` seconds. Negative value will turn off the feature. + """Minimum wait time to repeat existing static hover events and it defaults + to `1/30.0` seconds. Negative value will turn off the feature. To change the default value use `event_repeat_timeout` keyword while making a manager instance or set it directly after the instance is made. Changing From b69f8d04516668886788402fdaab2d1b307867e1 Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sun, 14 Dec 2025 23:05:48 +0100 Subject: [PATCH 2/8] Hover: Added docs explaining how events are dispatched in hover manager. --- kivy_garden/hover/__init__.py | 40 ++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index 1d31a0c..dc3595c 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -22,12 +22,12 @@ class with its :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to ------------ Manager is responsible for dispatching of hover events to widgets in -the :attr:`~kivy.core.window.WindowBase.children` list. Widgets who registered for -hover events will receive them in their +the :attr:`~kivy.core.window.WindowBase.children` list. Widgets who registered +for hover events will receive them in their :meth:`~kivy.uix.widget.Widget.on_motion` method. For your app to use a hover manager, you must register it with -:meth:`~kivy.core.window.WindowBase.register_event_manager` when app starts in +:meth:`~kivy.core.window.WindowBase.register_event_manager` when app starts and then unregister it with :meth:`~kivy.core.window.WindowBase.unregister_event_manager` when app stops. @@ -50,11 +50,35 @@ def on_stop(self): super().on_stop() self.root_window.unregister_event_manager(self.hover_manager) -Manager expects that widgets will grab the event if they want to always receive -event type "update" or "end" for that same event and also ungrab it when they -no longer want to receive it. To grab the event use -:meth:`~kivy.input.motionevent.MotionEvent.grab` and to ungrab use -:meth:`~kivy.input.motionevent.MotionEvent.ungrab`. +Manager expects every widget to always grab the event if they want to receive +event type "end" for that same event while the event is in the grabbed state. +To grab the event use :meth:`~kivy.input.motionevent.MotionEvent.grab` and to +ungrab use :meth:`~kivy.input.motionevent.MotionEvent.ungrab`. Manager +manipulates event's "grab_list" when dispatching an event to widgets, which is +needed to ensure that widgets receive "end" event type for the same event. +It will also restore the original `grab_list`, received in its +:meth:`~kivy.eventmanager.EventManagerBase.dispatch` method, after the dispatch +is done. + +Event dispatching works in the following way: + +1. If an event is received for the first time, manager will dispatch it to all + widgets in `window.children` list and internally store the event itself, + copy of the new `grab_list`, and the time of the dispatch. Values are + stored for every event, per its + :attr:`~kivy.input.motionevent.MotionEvent.uid`. +2. When the same event is received for the second time, step 1. is done again + and then follows the dispatch to the widgets who grabbed that same event. + Manager will dispatch event type "end" to the widgets who are found in the + previously stored `grab_list` and not found in the event's current + `grab_list`. This way is ensured that widgets can handle their state if they + didn't receive "update" or "begin" event type in the 3. step. +3. If a hover event is static (its position doesn't change) and + `min_wait_time` greater than 0, manager will dispatch an event type "update" + to all events stored in step 1. using `min_wait_time` as timeout between + the static events. +4. On event type "end", data stored in step 1. is removed from the manager's + internal storage. """ from collections import defaultdict From 81286de32d9b069f3e41771492260e4cbeaf339e Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sat, 20 Dec 2025 21:31:59 +0100 Subject: [PATCH 3/8] Hover: Added module level docs for HoverBehavior class. --- kivy_garden/hover/__init__.py | 78 +++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index dc3595c..54565bd 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -79,6 +79,75 @@ def on_stop(self): the static events. 4. On event type "end", data stored in step 1. is removed from the manager's internal storage. + +HoverBehavior +------------- + +:class:`HoverBehavior` is a `mixin `_ +class which handles hover events received in +:meth:`~kivy.uix.widget.Widget.on_motion` method. It depends on +:class:`HoverManager` way of dispatching of hover events - events with +:attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover". + +For an overview of behaviors, please refer to the :mod:`~kivy.uix.behaviors` +documentation. + +As a mixin class, :class:`HoverBehavior` must be combined with other widgets:: + + class HoverLabel(HoverBehavior, Widget): + pass + +Behavior supports multi-hover - if one or multiple hover events are hovering +over the widget, then its property :attr:`HoverBehavior.hovered` will be set to +`True`. + +Example app showing a widget which when hovered with a mouse indicator will +change color from gray to green:: + + from kivy.app import App + from kivy.lang import Builder + from kivy.uix.widget import Widget + + from kivy_garden.hover import HoverBehavior, HoverManager + + Builder.load_string(\""" + : + canvas.before: + Color: + rgba: [0, 1, 0, 1] if self.hovered else [0.5, 0.5, 0.5, 1] + Rectangle: + pos: self.pos + size: self.size + \""") + + + class RootWidget(HoverBehavior, Widget): + pass + + + class HoverBehaviorApp(App): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.hover_manager = HoverManager() + + def build(self): + return RootWidget(size_hint=(0.5, 0.5), + pos_hint={'center_x': 0.5, 'center_y': 0.5}) + + def on_start(self): + super().on_start() + self.root_window.register_event_manager(self.hover_manager) + + def on_stop(self): + super().on_stop() + self.root_window.unregister_event_manager(self.hover_manager) + + + if __name__ == '__main__': + HoverBehaviorApp().run() + +See :class:`HoverBehavior` for details. """ from collections import defaultdict @@ -237,12 +306,13 @@ class HoverBehavior(object): `on_hover_event`: `(etype, me)` Dispatched when this widget receives a hover event. `on_hover_enter`: `(me, )` - Dispatched at first time hover event collides with this widget. + Dispatched at first time a hover event collides with this widget. `on_hover_update`: `(me, )` - Dispatched when hover event position changed, but it's still within - this widget. + Dispatched when a hover event position changed, but it's still + within this widget. `on_hover_leave`: `(me, )` - Dispatched when hover event is no longer collides with this widget. + Dispatched when a hover event is no longer within with this widget + or on event end. """ def _get_hovered(self): From 9b625b077600c9d73a865278e03b5598eeb3911f Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sat, 20 Dec 2025 23:21:28 +0100 Subject: [PATCH 4/8] Hover: Added module level docs for MotionCollideBehavior class. --- kivy_garden/hover/__init__.py | 39 ++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index 54565bd..b0876c0 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -148,6 +148,38 @@ def on_stop(self): HoverBehaviorApp().run() See :class:`HoverBehavior` for details. + +MotionCollideBehavior +--------------------- + +:class:`MotionCollideBehavior` is a +`mixin `_ class which filters-out events +which do not collide with a widget or events for which currently grabbed +widget is not the widget itself. + +For an overview of behaviors, please refer to the :mod:`~kivy.uix.behaviors` +documentation. + +Behavior is meant to be used with :class:`~kivy.uix.stencilview.StencilView` or +its subclasses so that hover events (events with +:attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover") don't get +handled when their position is outside the view. + +Example of using :class:`MotionCollideBehavior` with +:class:`~kivy.uix.recycleview.RecycleView`:: + + FilteredRecycleView(MotionCollideBehavior, RecycleView): + pass + +:class:`MotionCollideBehavior` overrides +:meth:`~kivy.uix.widget.Widget.on_motion` to add event filtering:: + + class MotionCollideBehavior(object): + + def on_motion(self, etype, me): + if me.grab_current is self \ + or 'pos' in me.profile and self.collide_point(*me.pos): + return super().on_motion(etype, me) """ from collections import defaultdict @@ -414,12 +446,13 @@ def on_hover_leave(self, me): class MotionCollideBehavior(object): """MotionCollideBehavior `mixin `_ - overrides :meth:`on_motion` to filter-out events which do not collide with - the widget or events which are not grabbed events. + overrides :meth:`~kivy.uix.widget.Widget.on_motion` to filter-out events + which do not collide with the widget or events which are not grabbed + events. It's recommended to use this behavior with :class:`~kivy.uix.stencilview.StencilView` or its subclasses - (`RecycleView`, `ScrollView`, etc.) so that hover events do not get handled + (`RecycleView`, `ScrollView`, etc.) so that hover events don't get handled when outside of stencil view. """ From b59acb9e05ef31ee79ffe0a1a6d3a566e8cbe4e3 Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sun, 21 Dec 2025 14:52:56 +0100 Subject: [PATCH 5/8] Examples: Reverted changes to simple and large app. --- examples/large_app.py | 4 ++-- examples/simple_app.py | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/large_app.py b/examples/large_app.py index 0c81a5a..854e601 100644 --- a/examples/large_app.py +++ b/examples/large_app.py @@ -38,7 +38,7 @@ normal_color: 0, 0, 0, 0 size_hint_y: None height: '30dp' - padding: '10dp', 0 + padding_x: '10dp' : @@ -326,7 +326,7 @@ def _get_background_color(self): class XHoverButton(HoverButton): def on_hovered(self, button, hovered): - self.padding = ('20dp', 0) if hovered else ('10dp', 0) + self.padding_x = '20dp' if hovered else '10dp' class HoverLabel(HoverBehavior, ButtonBehavior, Label): diff --git a/examples/simple_app.py b/examples/simple_app.py index 6f04617..882fbd3 100644 --- a/examples/simple_app.py +++ b/examples/simple_app.py @@ -21,15 +21,12 @@ class RootWidget(HoverBehavior, Label): def on_hover_enter(self, me): - super().on_hover_enter(me) self.text = f'Enter: {me.pos}' def on_hover_update(self, me): - super().on_hover_update(me) self.text = f'Update: {me.pos}' def on_hover_leave(self, me): - super().on_hover_leave(me) self.text = f'Leave: {me.pos}' From df5691fbc3423b07b2f2ebcb7098d39d17270325 Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sun, 21 Dec 2025 16:17:01 +0100 Subject: [PATCH 6/8] Hover: Updated module level docs. --- kivy_garden/hover/__init__.py | 54 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index b0876c0..1baf257 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -5,7 +5,7 @@ This module defines three classes to handle hover events: 1. Class :class:`HoverManager` provides dispatching of hover events to widgets - in :attr:`~kivy.core.window.WindowBase.children` list. + in the `Window`'s :attr:`~kivy.core.window.WindowBase.children` list. 2. Class :class:`HoverBehavior` handles hover events for all widgets who inherit from it. 3. Class :class:`MotionCollideBehavior` provides filtering of all events @@ -14,7 +14,7 @@ pass a collision check are passed through the :meth:`~kivy.uix.widget.Widget.on_motion` method. -A hover event is an instance of :attr:`~kivy.input.motionevent.MotionEvent` +A hover event is an instance of :class:`~kivy.input.motionevent.MotionEvent` class with its :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover". @@ -22,9 +22,10 @@ class with its :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to ------------ Manager is responsible for dispatching of hover events to widgets in -the :attr:`~kivy.core.window.WindowBase.children` list. Widgets who registered -for hover events will receive them in their -:meth:`~kivy.uix.widget.Widget.on_motion` method. +the :attr:`~kivy.core.window.WindowBase.children` list. Widgets must register +for hover events using +:meth:`~kivy.uix.widget.Widget.register_for_motion_event` to be able to receive +them in the :meth:`~kivy.uix.widget.Widget.on_motion` method. For your app to use a hover manager, you must register it with :meth:`~kivy.core.window.WindowBase.register_event_manager` when app starts @@ -52,33 +53,34 @@ def on_stop(self): Manager expects every widget to always grab the event if they want to receive event type "end" for that same event while the event is in the grabbed state. -To grab the event use :meth:`~kivy.input.motionevent.MotionEvent.grab` and to -ungrab use :meth:`~kivy.input.motionevent.MotionEvent.ungrab`. Manager -manipulates event's "grab_list" when dispatching an event to widgets, which is -needed to ensure that widgets receive "end" event type for the same event. -It will also restore the original `grab_list`, received in its +To grab an event use :meth:`~kivy.input.motionevent.MotionEvent.grab` and to +ungrab it use :meth:`~kivy.input.motionevent.MotionEvent.ungrab`. Manager +manipulates event's :attr:`~kivy.input.motionevent.MotionEvent.grab_list` +when dispatching an event to widgets, which is needed to ensure that widgets +receive "end" event type for the same event. It will also restore the original +:attr:`~kivy.input.motionevent.MotionEvent.grab_list`, received in its :meth:`~kivy.eventmanager.EventManagerBase.dispatch` method, after the dispatch is done. Event dispatching works in the following way: 1. If an event is received for the first time, manager will dispatch it to all - widgets in `window.children` list and internally store the event itself, - copy of the new `grab_list`, and the time of the dispatch. Values are - stored for every event, per its + widgets in the :attr:`~kivy.core.window.WindowBase.children` list and + internally store the event itself, copy of the new `grab_list`, and the time + of the dispatch. Values are stored for every event, per its :attr:`~kivy.input.motionevent.MotionEvent.uid`. -2. When the same event is received for the second time, step 1. is done again +2. When the same event is received for the second time, step 1. is done again, and then follows the dispatch to the widgets who grabbed that same event. Manager will dispatch event type "end" to the widgets who are found in the previously stored `grab_list` and not found in the event's current `grab_list`. This way is ensured that widgets can handle their state if they - didn't receive "update" or "begin" event type in the 3. step. + didn't receive "update" or "begin" event type in the second time dispatch. 3. If a hover event is static (its position doesn't change) and - `min_wait_time` greater than 0, manager will dispatch an event type "update" - to all events stored in step 1. using `min_wait_time` as timeout between - the static events. -4. On event type "end", data stored in step 1. is removed from the manager's - internal storage. + :attr:`HoverManager.min_wait_time` is greater than 0, manager will dispatch + an event type "update" to all events stored in step 1. using + :attr:`HoverManager.min_wait_time` as timeout between the static events. +4. On the event type "end", data stored in the step 1. is removed from the + manager's internal storage. HoverBehavior ------------- @@ -86,7 +88,7 @@ def on_stop(self): :class:`HoverBehavior` is a `mixin `_ class which handles hover events received in :meth:`~kivy.uix.widget.Widget.on_motion` method. It depends on -:class:`HoverManager` way of dispatching of hover events - events with +:class:`HoverManager` and its way of dispatching of hover events - events with :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover". For an overview of behaviors, please refer to the :mod:`~kivy.uix.behaviors` @@ -94,7 +96,7 @@ class which handles hover events received in As a mixin class, :class:`HoverBehavior` must be combined with other widgets:: - class HoverLabel(HoverBehavior, Widget): + class HoverWidget(HoverBehavior, Widget): pass Behavior supports multi-hover - if one or multiple hover events are hovering @@ -160,10 +162,10 @@ def on_stop(self): For an overview of behaviors, please refer to the :mod:`~kivy.uix.behaviors` documentation. -Behavior is meant to be used with :class:`~kivy.uix.stencilview.StencilView` or -its subclasses so that hover events (events with -:attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover") don't get -handled when their position is outside the view. +:class:`MotionCollideBehavior` is meant to be used with +:class:`~kivy.uix.stencilview.StencilView` or its subclasses so that hover +events (events with :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to +"hover") don't get handled when their position is outside the view. Example of using :class:`MotionCollideBehavior` with :class:`~kivy.uix.recycleview.RecycleView`:: From 8a79d4d17fdb63c4f5a7a284bb0f09f0405f434a Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sun, 21 Dec 2025 17:30:09 +0100 Subject: [PATCH 7/8] Examples: Remove changes from example apps. --- examples/large_app.py | 4 ++-- examples/simple_app.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/large_app.py b/examples/large_app.py index 854e601..0c81a5a 100644 --- a/examples/large_app.py +++ b/examples/large_app.py @@ -38,7 +38,7 @@ normal_color: 0, 0, 0, 0 size_hint_y: None height: '30dp' - padding_x: '10dp' + padding: '10dp', 0 : @@ -326,7 +326,7 @@ def _get_background_color(self): class XHoverButton(HoverButton): def on_hovered(self, button, hovered): - self.padding_x = '20dp' if hovered else '10dp' + self.padding = ('20dp', 0) if hovered else ('10dp', 0) class HoverLabel(HoverBehavior, ButtonBehavior, Label): diff --git a/examples/simple_app.py b/examples/simple_app.py index 882fbd3..6f04617 100644 --- a/examples/simple_app.py +++ b/examples/simple_app.py @@ -21,12 +21,15 @@ class RootWidget(HoverBehavior, Label): def on_hover_enter(self, me): + super().on_hover_enter(me) self.text = f'Enter: {me.pos}' def on_hover_update(self, me): + super().on_hover_update(me) self.text = f'Update: {me.pos}' def on_hover_leave(self, me): + super().on_hover_leave(me) self.text = f'Leave: {me.pos}' From 1c81f09c84ab9c392f5f0a3014dc70b3c33ae1a0 Mon Sep 17 00:00:00 2001 From: pythonic64 Date: Sat, 27 Dec 2025 17:37:15 +0100 Subject: [PATCH 8/8] Hover: Minor fixes in module doc. --- kivy_garden/hover/__init__.py | 44 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/kivy_garden/hover/__init__.py b/kivy_garden/hover/__init__.py index 1baf257..a24322e 100644 --- a/kivy_garden/hover/__init__.py +++ b/kivy_garden/hover/__init__.py @@ -22,10 +22,10 @@ class with its :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to ------------ Manager is responsible for dispatching of hover events to widgets in -the :attr:`~kivy.core.window.WindowBase.children` list. Widgets must register -for hover events using +the `Window`'s :attr:`~kivy.core.window.WindowBase.children` list. Widgets must +register for hover events using :meth:`~kivy.uix.widget.Widget.register_for_motion_event` to be able to receive -them in the :meth:`~kivy.uix.widget.Widget.on_motion` method. +those events in the :meth:`~kivy.uix.widget.Widget.on_motion` method. For your app to use a hover manager, you must register it with :meth:`~kivy.core.window.WindowBase.register_event_manager` when app starts @@ -51,7 +51,7 @@ def on_stop(self): super().on_stop() self.root_window.unregister_event_manager(self.hover_manager) -Manager expects every widget to always grab the event if they want to receive +Manager expects every widget to always grab the event, if they want to receive event type "end" for that same event while the event is in the grabbed state. To grab an event use :meth:`~kivy.input.motionevent.MotionEvent.grab` and to ungrab it use :meth:`~kivy.input.motionevent.MotionEvent.ungrab`. Manager @@ -76,9 +76,10 @@ def on_stop(self): `grab_list`. This way is ensured that widgets can handle their state if they didn't receive "update" or "begin" event type in the second time dispatch. 3. If a hover event is static (its position doesn't change) and - :attr:`HoverManager.min_wait_time` is greater than 0, manager will dispatch - an event type "update" to all events stored in step 1. using - :attr:`HoverManager.min_wait_time` as timeout between the static events. + :attr:`HoverManager.event_repeat_timeout` is greater than 0, manager will + dispatch an event type "update" to all events stored in step 1. using + :attr:`HoverManager.event_repeat_timeout` as timeout between the static + events. 4. On the event type "end", data stored in the step 1. is removed from the manager's internal storage. @@ -86,7 +87,7 @@ def on_stop(self): ------------- :class:`HoverBehavior` is a `mixin `_ -class which handles hover events received in +class which handles hover events received in the :meth:`~kivy.uix.widget.Widget.on_motion` method. It depends on :class:`HoverManager` and its way of dispatching of hover events - events with :attr:`~kivy.input.motionevent.MotionEvent.type_id` set to "hover". @@ -100,7 +101,7 @@ class HoverWidget(HoverBehavior, Widget): pass Behavior supports multi-hover - if one or multiple hover events are hovering -over the widget, then its property :attr:`HoverBehavior.hovered` will be set to +over a widget, then its property :attr:`HoverBehavior.hovered` will be set to `True`. Example app showing a widget which when hovered with a mouse indicator will @@ -116,7 +117,7 @@ class HoverWidget(HoverBehavior, Widget): : canvas.before: Color: - rgba: [0, 1, 0, 1] if self.hovered else [0.5, 0.5, 0.5, 1] + rgba: [0, 0.5, 0, 1] if self.hovered else [0.5, 0.5, 0.5, 1] Rectangle: pos: self.pos size: self.size @@ -155,7 +156,7 @@ def on_stop(self): --------------------- :class:`MotionCollideBehavior` is a -`mixin `_ class which filters-out events +`mixin `_ class which filters events which do not collide with a widget or events for which currently grabbed widget is not the widget itself. @@ -197,7 +198,7 @@ class HoverManager(EventManagerBase): list. When registered, manager will receive all events with `type_id` set to - "hover", transform them to match :attr:`window` size and dispatch them + "hover", transform them to match :attr:`window` size and then dispatch them through the `window.children` list using the `on_motion` event. To handle a case when the hover event position did not change within @@ -340,13 +341,14 @@ class HoverBehavior(object): `on_hover_event`: `(etype, me)` Dispatched when this widget receives a hover event. `on_hover_enter`: `(me, )` - Dispatched at first time a hover event collides with this widget. + Dispatched when a hover event collides with this widget for the + first time. `on_hover_update`: `(me, )` - Dispatched when a hover event position changed, but it's still + Dispatched when a hover event position has changed, but it's still within this widget. `on_hover_leave`: `(me, )` - Dispatched when a hover event is no longer within with this widget - or on event end. + Dispatched when a hover event is no longer within this widget or + when an event type "end" is received. """ def _get_hovered(self): @@ -369,13 +371,13 @@ def _get_hovered(self): Options: - - ``'default'``: Dispatch to children first and if none of the child - widgets accepts the event (by returning `True`) dispatch `on_hover_event` - so that this widget can try to handle it. + - ``'default'``: Dispatch to `children` first and if none of the child + widgets accepted the event (by returning `True`), then dispatch + `on_hover_event` so that this widget can try to handle it. - - ``'all'``: Same as `default` but always dispatch `on_hover_event`. + - ``'all'``: Same as `default`, but always dispatch `on_hover_event`. - - ``'self'``: Don't dispatch to children, but dispatch `on_hover_event`. + - ``'self'``: Don't dispatch to `children`, but dispatch `on_hover_event`. """ __events__ = ('on_hover_event', 'on_hover_enter', 'on_hover_update',