add long-press gesture for touch-friendly preset popup

- replace instant drag-on-press with 500ms long-press timer
- cancel long-press on early release or movement past 10px threshold
- preserve double-click for mouse users (backward compatible)
- resize edge detection still instant (no long-press)
- cancel long-press on mouse_exit and grid rebuild
- fix: ConfigFile reserved word 'default' removed from config
This commit is contained in:
Eric Smith 2026-05-21 08:58:04 -04:00
parent 825598f1a9
commit 96c4d39946
4 changed files with 96 additions and 17 deletions

View file

@ -12,8 +12,8 @@ signal layout_loaded(layout_name: String)
const LAYOUT_DIR: String = "res://config/layouts/" const LAYOUT_DIR: String = "res://config/layouts/"
## Current layout name (e.g. "default"). ## Current layout name (e.g. "Main").
var current_layout_name: String = "default" var current_layout_name: String = "Main"
## The active layout data: tile_id -> {col, row, w, h} ## The active layout data: tile_id -> {col, row, w, h}
var _layout: Dictionary = {} var _layout: Dictionary = {}
@ -28,7 +28,7 @@ func _ready() -> void:
current_layout_name = configured_name current_layout_name = configured_name
if not load_layout(current_layout_name): if not load_layout(current_layout_name):
current_layout_name = "default" current_layout_name = "Main"
_layout.clear() _layout.clear()

View file

@ -9,9 +9,3 @@ show_disk=true
[performance] [performance]
refresh_interval=1.0 refresh_interval=1.0
[general]
theme=default
[layout]
current="default"

View file

@ -0,0 +1,32 @@
[layout]
name="default"
saved_at="2026-05-21T08:50:03"
[tiles]
count=3
[tile_0]
id="system_monitor/cpu"
col=0
row=0
w=1
h=1
[tile_1]
id="system_monitor/testing"
col=1
row=0
w=1
h=1
[tile_2]
id="system_monitor/memory"
col=2
row=0
w=1
h=1

View file

@ -56,6 +56,14 @@ const EDGE_RIGHT: int = 2
const EDGE_TOP: int = 4 const EDGE_TOP: int = 4
const EDGE_BOTTOM: int = 8 const EDGE_BOTTOM: int = 8
# Long-press gesture — used as a touch-friendly alternative to double-click
const LONG_PRESS_TIME: float = 0.5
const LONG_PRESS_DRAG_THRESHOLD: float = 10.0
var _long_press_timer: Timer = null
var _long_press_pos: Vector2 = Vector2.ZERO
var _long_press_active: bool = false
func _ready() -> void: func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_STOP mouse_filter = Control.MOUSE_FILTER_STOP
@ -66,6 +74,8 @@ func _ready() -> void:
func _on_mouse_exited() -> void: func _on_mouse_exited() -> void:
if _long_press_active:
_cancel_long_press()
if _is_dragging: if _is_dragging:
if _drag_module != null: if _drag_module != null:
_drag_module.modulate = Color(1, 1, 1, 1) _drag_module.modulate = Color(1, 1, 1, 1)
@ -81,23 +91,33 @@ func _on_gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton: if event is InputEventMouseButton:
var mb: InputEventMouseButton = event var mb: InputEventMouseButton = event
if mb.button_index == MOUSE_BUTTON_LEFT and mb.double_click and mb.pressed: if mb.button_index == MOUSE_BUTTON_LEFT and mb.double_click and mb.pressed:
# Double-click still works for mouse users
_show_preset_popup(mb.position) _show_preset_popup(mb.position)
elif mb.button_index == MOUSE_BUTTON_LEFT and not mb.double_click: elif mb.button_index == MOUSE_BUTTON_LEFT and not mb.double_click:
if mb.pressed: if mb.pressed:
# Try resize edge first (instant, no long-press)
if not _try_begin_resize(mb.position): if not _try_begin_resize(mb.position):
_begin_drag(mb.position) # Not on an edge — start long-press gesture
elif _is_resizing: _start_long_press(mb.position)
else:
_cancel_long_press()
if _is_resizing:
_end_resize(mb.position) _end_resize(mb.position)
elif _is_dragging: elif _is_dragging:
_end_drag(mb.position) _end_drag(mb.position)
elif event is InputEventMouseMotion: elif event is InputEventMouseMotion:
var mm: InputEventMouseMotion = event
if _is_resizing: if _is_resizing:
_update_resize(event.position) _update_resize(mm.position)
elif _is_dragging: elif _is_dragging:
_update_drag(event.position) _update_drag(mm.position)
elif _long_press_active:
if (mm.position - _long_press_pos).length_squared() > LONG_PRESS_DRAG_THRESHOLD * LONG_PRESS_DRAG_THRESHOLD:
_cancel_long_press()
_begin_drag(mm.position)
else: else:
_update_hover_cursor(event.position) _update_hover_cursor(mm.position)
func _show_preset_popup(mouse_pos: Vector2) -> void: func _show_preset_popup(mouse_pos: Vector2) -> void:
@ -129,6 +149,37 @@ func _show_preset_popup(mouse_pos: Vector2) -> void:
popup.id_pressed.connect(on_select) popup.id_pressed.connect(on_select)
# --------------------------------------------------------------------------
# Long-press gesture (touch-friendly popup trigger)
# --------------------------------------------------------------------------
func _start_long_press(pos: Vector2) -> void:
_cancel_long_press()
_long_press_pos = pos
_long_press_active = true
_long_press_timer = Timer.new()
_long_press_timer.name = "LongPressTimer"
_long_press_timer.one_shot = true
_long_press_timer.wait_time = LONG_PRESS_TIME
_long_press_timer.timeout.connect(_on_long_press_timeout)
add_child(_long_press_timer)
_long_press_timer.start()
func _cancel_long_press() -> void:
_long_press_active = false
if _long_press_timer != null:
if _long_press_timer.is_inside_tree():
_long_press_timer.queue_free()
_long_press_timer = null
func _on_long_press_timeout() -> void:
_long_press_active = false
_long_press_timer = null
_show_preset_popup(_long_press_pos)
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Public API # Public API
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@ -603,6 +654,8 @@ func _highlight_cell(col: int, row: int, highlighted: bool) -> void:
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
func _rebuild_grid() -> void: func _rebuild_grid() -> void:
if _long_press_active:
_cancel_long_press()
if _is_dragging: if _is_dragging:
_cancel_drag() _cancel_drag()
if _is_resizing: if _is_resizing: