@@ -20,6 +20,8 @@ class DialogResult(IntEnum):
2020
2121
2222class Widget (abc .ABC ):
23+ LONG_PRESS_TIME = 0.5
24+
2325 def __init__ (self ):
2426 self ._rect : rl .Rectangle = rl .Rectangle (0 , 0 , 0 , 0 )
2527 self ._parent_rect : rl .Rectangle | None = None
@@ -33,6 +35,10 @@ def __init__(self):
3335 self ._multi_touch = False
3436 self .__was_awake = True
3537
38+ # Long press state (single touch only, slot 0)
39+ self ._long_press_start_t : float | None = None
40+ self ._long_press_fired : bool = False
41+
3642 @property
3743 def rect (self ) -> rl .Rectangle :
3844 return self ._rect
@@ -127,19 +133,28 @@ def _process_mouse_events(self) -> None:
127133 self ._handle_mouse_press (mouse_event .pos )
128134 self .__is_pressed [mouse_event .slot ] = True
129135 self .__tracking_is_pressed [mouse_event .slot ] = True
136+ if mouse_event .slot == 0 :
137+ self ._long_press_start_t = rl .get_time ()
138+ self ._long_press_fired = False
130139 self ._handle_mouse_event (mouse_event )
131140
132141 # Callback such as scroll panel signifies user is scrolling
133142 elif not touch_valid :
134143 self .__is_pressed [mouse_event .slot ] = False
135144 self .__tracking_is_pressed [mouse_event .slot ] = False
145+ if mouse_event .slot == 0 :
146+ self ._long_press_start_t = None
147+ self ._long_press_fired = False
136148
137149 elif mouse_event .left_released :
138150 self ._handle_mouse_event (mouse_event )
139- if self .__is_pressed [mouse_event .slot ] and mouse_in_rect :
151+ if self .__is_pressed [mouse_event .slot ] and mouse_in_rect and not ( mouse_event . slot == 0 and self . _long_press_fired ) :
140152 self ._handle_mouse_release (mouse_event .pos )
141153 self .__is_pressed [mouse_event .slot ] = False
142154 self .__tracking_is_pressed [mouse_event .slot ] = False
155+ if mouse_event .slot == 0 :
156+ self ._long_press_start_t = None
157+ self ._long_press_fired = False
143158
144159 # Mouse/touch is still within our rect
145160 elif mouse_in_rect :
@@ -150,8 +165,17 @@ def _process_mouse_events(self) -> None:
150165 # Mouse/touch left our rect but may come back into focus later
151166 elif not mouse_in_rect :
152167 self .__is_pressed [mouse_event .slot ] = False
168+ if mouse_event .slot == 0 :
169+ self ._long_press_start_t = None
170+ self ._long_press_fired = False
153171 self ._handle_mouse_event (mouse_event )
154172
173+ # Long press detection
174+ if self ._long_press_start_t is not None and not self ._long_press_fired :
175+ if (rl .get_time () - self ._long_press_start_t ) >= self .LONG_PRESS_TIME :
176+ self ._long_press_fired = True
177+ self ._handle_long_press (gui_app .last_mouse_event .pos )
178+
155179 def _layout (self ) -> None :
156180 """Optionally lay out child widgets separately. This is called before rendering."""
157181
@@ -175,9 +199,11 @@ def _handle_mouse_release(self, mouse_pos: MousePos) -> bool:
175199 self ._click_callback ()
176200 return False
177201
202+ def _handle_long_press (self , mouse_pos : MousePos ) -> None :
203+ """Optionally handle a long-press gesture."""
204+
178205 def _handle_mouse_event (self , mouse_event : MouseEvent ) -> None :
179206 """Optionally handle mouse events. This is called before rendering."""
180- # Default implementation does nothing, can be overridden by subclasses
181207
182208 def show_event (self ):
183209 """Optionally handle show event. Parent must manually call this"""
0 commit comments