Skip to content

Commit 6a9ef5f

Browse files
committed
fix(Search Bar): add keyboard support for search bar
- Update search bar to use LineEdit instead of TextEdit - Add ability to move text cursor with OSK - Switch to library state upon keyboard input
1 parent 411ad5e commit 6a9ef5f

File tree

6 files changed

+57
-33
lines changed

6 files changed

+57
-33
lines changed

core/global/keyboard_instance.gd

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ var context: KeyboardContext
1919
# keyboard inputs should go, and how to handle submits.
2020
func open(ctx: KeyboardContext) -> void:
2121
set_context(ctx)
22+
if context and context.target:
23+
# Show the caret
24+
if context.target is LineEdit:
25+
var line_edit := context.target as LineEdit
26+
line_edit.caret_force_displayed = true
27+
# Some nodes (like LineEdit), will grab focus when text is manipulated.
28+
# Don't allow the node to grab focus
29+
context.target.focus_mode = Control.FOCUS_NONE
2230
keyboard_opened.emit()
2331

2432

@@ -27,6 +35,11 @@ func close() -> void:
2735
# If the target is a control node, return focus back to it when the
2836
# keyboard closes
2937
if context and context.target:
38+
# Hide the caret
39+
if context.target is LineEdit:
40+
var line_edit := context.target as LineEdit
41+
line_edit.caret_force_displayed = false
42+
context.target.focus_mode = Control.FOCUS_ALL
3043
context.target.grab_focus.call_deferred()
3144
set_context(null)
3245
keyboard_closed.emit()
@@ -48,7 +61,6 @@ func set_context(ctx: KeyboardContext) -> void:
4861
text_edit.set_caret_line(lines-1)
4962
var current_line := text_edit.get_line(lines-1)
5063
text_edit.set_caret_column(current_line.length())
51-
#text_edit.clear()
5264

5365
# Update our internal keyboard context
5466
if context == ctx:

core/ui/card_ui/navigation/search_bar_menu.gd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ var default_size := Vector2(custom_minimum_size.x, custom_minimum_size.y)
77

88
@export var animate_time := 0.2
99

10-
@onready var tabs_container := $%LibraryTabsContainer
11-
@onready var search_bar := $%SearchBar
12-
@onready var search_button := $%SearchButton
10+
@onready var tabs_container := $%LibraryTabsContainer as TabsHeader
11+
@onready var search_bar := $%SearchBar as SearchBar
12+
@onready var search_button := $%SearchButton as CardIconButton
1313

1414

1515
# Called when the node enters the scene tree for the first time.

core/ui/card_ui/navigation/search_bar_menu.tscn

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
[gd_scene load_steps=12 format=3 uid="uid://d4bmkauhrlhq0"]
1+
[gd_scene load_steps=13 format=3 uid="uid://d4bmkauhrlhq0"]
22

33
[ext_resource type="Script" path="res://core/ui/card_ui/navigation/search_bar_menu.gd" id="1_518qs"]
4-
[ext_resource type="PackedScene" uid="uid://bx0fnuxd8mm51" path="res://core/ui/components/search_bar.tscn" id="2_gqstr"]
54
[ext_resource type="Resource" uid="uid://oaavalv0wcoa" path="res://assets/state/states/home.tres" id="2_kr4pi"]
65
[ext_resource type="PackedScene" uid="uid://bfiia7vnbfw3s" path="res://core/systems/state/states_watcher.tscn" id="2_nb2d7"]
76
[ext_resource type="Resource" uid="uid://boq501bigx8kl" path="res://assets/state/states/library.tres" id="3_sj5or"]
7+
[ext_resource type="Script" path="res://core/systems/state/state.gd" id="3_truj2"]
88
[ext_resource type="PackedScene" uid="uid://bw8113ocotx2r" path="res://core/systems/effects/fade_effect.tscn" id="4_1043g"]
99
[ext_resource type="Texture2D" uid="uid://8pmccsyfv3u7" path="res://assets/ui/icons/search.svg" id="5_pq07x"]
1010
[ext_resource type="PackedScene" uid="uid://cr83fmlociwko" path="res://core/ui/components/card_icon_button.tscn" id="6_dilc0"]
1111
[ext_resource type="PackedScene" uid="uid://cgmb4kr2ec4ha" path="res://core/ui/components/tabs_header.tscn" id="8_uixir"]
1212
[ext_resource type="Resource" uid="uid://cjda3nse6s3n1" path="res://core/ui/card_ui/library/library_tabs_state.tres" id="9_dlgkq"]
1313
[ext_resource type="Script" path="res://core/ui/components/input_icon.gd" id="9_qnoau"]
14+
[ext_resource type="Script" path="res://core/ui/components/search_bar.gd" id="9_smv7o"]
1415

1516
[node name="SearchBarMenu" type="PanelContainer"]
1617
z_index = 19
@@ -21,7 +22,7 @@ theme_type_variation = &"SearchBar"
2122
script = ExtResource("1_518qs")
2223

2324
[node name="StatesWatcher" parent="." instance=ExtResource("2_nb2d7")]
24-
states = Array[Resource("res://core/systems/state/state.gd")]([ExtResource("2_kr4pi"), ExtResource("3_sj5or")])
25+
states = Array[ExtResource("3_truj2")]([ExtResource("2_kr4pi"), ExtResource("3_sj5or")])
2526

2627
[node name="FadeEffect" parent="StatesWatcher" node_paths=PackedStringArray("target") instance=ExtResource("4_1043g")]
2728
target = NodePath("../..")
@@ -47,13 +48,17 @@ texture = ExtResource("5_pq07x")
4748
layout_mode = 2
4849
theme_override_constants/separation = 1
4950

50-
[node name="SearchBar" parent="MarginContainer/HBoxContainer/HBoxContainer" groups=["global_search_bar"] instance=ExtResource("2_gqstr")]
51+
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/HBoxContainer/HBoxContainer"]
52+
layout_mode = 2
53+
theme_override_constants/margin_top = 5
54+
theme_override_constants/margin_bottom = 5
55+
56+
[node name="SearchBar" type="LineEdit" parent="MarginContainer/HBoxContainer/HBoxContainer/MarginContainer" groups=["global_search_bar", "search_bar"]]
5157
unique_name_in_owner = true
52-
custom_minimum_size = Vector2(250, 36)
58+
custom_minimum_size = Vector2(200, 0)
5359
layout_mode = 2
54-
theme_override_colors/background_color = Color(0, 0, 0, 0)
55-
theme_override_font_sizes/font_size = 15
5660
placeholder_text = "What should you play?"
61+
script = ExtResource("9_smv7o")
5762

5863
[node name="InputIcon" type="HBoxContainer" parent="MarginContainer/HBoxContainer/HBoxContainer"]
5964
layout_mode = 2

core/ui/common/osk/on_screen_keyboard.gd

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func open() -> void:
179179
break
180180

181181
# Try to scroll any scroll containers to the target node
182-
var target = instance.context.target
182+
var target := instance.context.target
183183
if target:
184184
# TODO: Find a better way to scroll to the focused element after grow
185185
# effect finishes
@@ -211,18 +211,20 @@ func open() -> void:
211211

212212
# Closes the OSK
213213
func close() -> void:
214+
# Remove the OSK state
214215
popup_state_machine.remove_state(osk_state)
215216

216217
# If the keyboard is configured to send input to the game, set gamescope accordinly
217218
var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
218-
var pid := OS.get_process_id()
219-
var ogui_windows := xwayland.get_windows_for_pid(pid)
220-
if not ogui_windows.is_empty():
221-
var overlay_window_id := ogui_windows[0]
222-
if state_machine.current_state() == in_game_state:
223-
xwayland.set_input_focus(overlay_window_id, 0)
224-
else:
225-
xwayland.set_input_focus(overlay_window_id, 1)
219+
if xwayland:
220+
var pid := OS.get_process_id()
221+
var ogui_windows := xwayland.get_windows_for_pid(pid)
222+
if not ogui_windows.is_empty():
223+
var overlay_window_id := ogui_windows[0]
224+
if state_machine.current_state() == in_game_state:
225+
xwayland.set_input_focus(overlay_window_id, 0)
226+
else:
227+
xwayland.set_input_focus(overlay_window_id, 1)
226228

227229
closed.emit()
228230

@@ -393,6 +395,7 @@ func _handle_native(key: KeyboardKeyConfig) -> void:
393395
if target is LineEdit:
394396
var line_edit := instance.context.target as LineEdit
395397
line_edit.insert_text_at_caret(character)
398+
line_edit.text_changed.emit(line_edit.text) # insert_text doesn't fire this signal
396399
return
397400

398401
logger.warn("Keyboard target is not a supported type. Can't send key input.")
@@ -404,6 +407,16 @@ func _handle_native_action(key: KeyboardKeyConfig) -> void:
404407
return
405408
var target = instance.context.target
406409
match key.input.keycode:
410+
KEY_LEFT:
411+
if target != null and target is LineEdit:
412+
var line_edit := target as LineEdit
413+
if line_edit.caret_column > 0:
414+
line_edit.caret_column -= 1
415+
KEY_RIGHT:
416+
if target != null and target is LineEdit:
417+
var line_edit := target as LineEdit
418+
if line_edit.caret_column < line_edit.text.length():
419+
line_edit.caret_column += 1
407420
KEY_SHIFT:
408421
if _mode_shift > MODE_SHIFT.OFF:
409422
set_mode_shift(MODE_SHIFT.OFF)
@@ -423,6 +436,7 @@ func _handle_native_action(key: KeyboardKeyConfig) -> void:
423436
if target != null and target is LineEdit:
424437
var line_edit := target as LineEdit
425438
line_edit.delete_char_at_caret()
439+
# Upon delete, the LineEdit grabs focus
426440
return
427441
KEY_ENTER:
428442
instance.context.submitted.emit()

core/ui/components/search_bar.gd

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
extends TextEdit
1+
extends LineEdit
22
class_name SearchBar
33

44
signal search_submitted(text: String)
55

66
var state_machine := load("res://assets/state/state_machines/menu_state_machine.tres") as StateMachine
7-
var library_state := load("res://assets/state/states/library.tres")
7+
var library_state := load("res://assets/state/states/library.tres") as State
88

99
var keyboard_context := KeyboardContext.new(KeyboardContext.TYPE.GODOT, self)
1010
@export var keyboard: KeyboardInstance = preload("res://core/global/keyboard_instance.tres")
@@ -16,7 +16,10 @@ func _ready() -> void:
1616
text_changed.connect(_on_text_changed)
1717

1818

19-
func _on_text_changed() -> void:
19+
func _on_text_changed(new_text: String) -> void:
20+
if state_machine.current_state() != library_state:
21+
state_machine.push_state(library_state)
22+
grab_focus.call_deferred()
2023
search_submitted.emit(text)
2124

2225

core/ui/components/search_bar.tscn

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)