From 96c4d399463165cbd2f395b0db46f989778d9ce0 Mon Sep 17 00:00:00 2001 From: Eric Smith <5d@fifthdread.com> Date: Thu, 21 May 2026 08:58:04 -0400 Subject: [PATCH] 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 --- autoload/layout_manager.gd | 6 ++-- config/default.cfg | 6 ---- config/layouts/default.cfg | 32 ++++++++++++++++++ scripts/dashboard_grid.gd | 69 +++++++++++++++++++++++++++++++++----- 4 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 config/layouts/default.cfg diff --git a/autoload/layout_manager.gd b/autoload/layout_manager.gd index 2d38a90..b7b7a6b 100644 --- a/autoload/layout_manager.gd +++ b/autoload/layout_manager.gd @@ -12,8 +12,8 @@ signal layout_loaded(layout_name: String) const LAYOUT_DIR: String = "res://config/layouts/" -## Current layout name (e.g. "default"). -var current_layout_name: String = "default" +## Current layout name (e.g. "Main"). +var current_layout_name: String = "Main" ## The active layout data: tile_id -> {col, row, w, h} var _layout: Dictionary = {} @@ -28,7 +28,7 @@ func _ready() -> void: current_layout_name = configured_name if not load_layout(current_layout_name): - current_layout_name = "default" + current_layout_name = "Main" _layout.clear() diff --git a/config/default.cfg b/config/default.cfg index 61b4e84..56197c1 100644 --- a/config/default.cfg +++ b/config/default.cfg @@ -9,9 +9,3 @@ show_disk=true [performance] refresh_interval=1.0 - -[general] -theme=default - -[layout] -current="default" diff --git a/config/layouts/default.cfg b/config/layouts/default.cfg new file mode 100644 index 0000000..5273b64 --- /dev/null +++ b/config/layouts/default.cfg @@ -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 diff --git a/scripts/dashboard_grid.gd b/scripts/dashboard_grid.gd index 538fa48..b9ecf37 100644 --- a/scripts/dashboard_grid.gd +++ b/scripts/dashboard_grid.gd @@ -56,6 +56,14 @@ const EDGE_RIGHT: int = 2 const EDGE_TOP: int = 4 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: mouse_filter = Control.MOUSE_FILTER_STOP @@ -66,6 +74,8 @@ func _ready() -> void: func _on_mouse_exited() -> void: + if _long_press_active: + _cancel_long_press() if _is_dragging: if _drag_module != null: _drag_module.modulate = Color(1, 1, 1, 1) @@ -81,23 +91,33 @@ func _on_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton: var mb: InputEventMouseButton = event 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) elif mb.button_index == MOUSE_BUTTON_LEFT and not mb.double_click: if mb.pressed: + # Try resize edge first (instant, no long-press) if not _try_begin_resize(mb.position): - _begin_drag(mb.position) - elif _is_resizing: - _end_resize(mb.position) - elif _is_dragging: - _end_drag(mb.position) + # Not on an edge — start long-press gesture + _start_long_press(mb.position) + else: + _cancel_long_press() + if _is_resizing: + _end_resize(mb.position) + elif _is_dragging: + _end_drag(mb.position) elif event is InputEventMouseMotion: + var mm: InputEventMouseMotion = event if _is_resizing: - _update_resize(event.position) + _update_resize(mm.position) 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: - _update_hover_cursor(event.position) + _update_hover_cursor(mm.position) 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) +# -------------------------------------------------------------------------- +# 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 # -------------------------------------------------------------------------- @@ -603,6 +654,8 @@ func _highlight_cell(col: int, row: int, highlighted: bool) -> void: # -------------------------------------------------------------------------- func _rebuild_grid() -> void: + if _long_press_active: + _cancel_long_press() if _is_dragging: _cancel_drag() if _is_resizing: