mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-24 10:20:24 +01:00
Add process_mode property to PTY
Adds process_mode property to PTY which can be set to IDLE or PHYSICS. Determines whether the PTY will be updated in the `_process()` or `_physics_process()` step. Defaults to PHYSICS.
This commit is contained in:
parent
2acb93f8ff
commit
3378e6ff8f
7 changed files with 55 additions and 28 deletions
|
@ -4,7 +4,6 @@ extends "../../terminal.gd"
|
||||||
signal exited(exit_code, signum)
|
signal exited(exit_code, signum)
|
||||||
|
|
||||||
var editor_settings: EditorSettings
|
var editor_settings: EditorSettings
|
||||||
var timer := Timer.new()
|
|
||||||
|
|
||||||
onready var pty = $PTY
|
onready var pty = $PTY
|
||||||
|
|
||||||
|
@ -51,20 +50,6 @@ func _ready():
|
||||||
)
|
)
|
||||||
_native_terminal._update_theme()
|
_native_terminal._update_theme()
|
||||||
|
|
||||||
# In editor _process is not called continuously unless the "Update Continuously"
|
|
||||||
# editor setting is enabled. This setting is disabled by default and uses 100%
|
|
||||||
# of one core when enabled, so best to leave it off and use a timer instead.
|
|
||||||
add_child(timer)
|
|
||||||
timer.wait_time = 0.025
|
|
||||||
timer.connect("timeout", self, "_poll")
|
|
||||||
timer.start()
|
|
||||||
|
|
||||||
|
|
||||||
func _poll():
|
|
||||||
if pty and pty.has_method("get_master"):
|
|
||||||
pty.get_master().poll()
|
|
||||||
update()
|
|
||||||
|
|
||||||
|
|
||||||
func _input(event):
|
func _input(event):
|
||||||
if has_focus() and event is InputEventKey and event.is_pressed():
|
if has_focus() and event is InputEventKey and event.is_pressed():
|
||||||
|
|
|
@ -9,6 +9,10 @@ func open(cols: int, rows: int):
|
||||||
return _not_implemented()
|
return _not_implemented()
|
||||||
|
|
||||||
|
|
||||||
|
func run_process(delta: float):
|
||||||
|
return _not_implemented()
|
||||||
|
|
||||||
|
|
||||||
func resize(cols: int, rows: int):
|
func resize(cols: int, rows: int):
|
||||||
return _not_implemented()
|
return _not_implemented()
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,11 @@ func write(data) -> void:
|
||||||
_pipe.write(data)
|
_pipe.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
func run_process(_delta):
|
||||||
|
if _pipe:
|
||||||
|
_pipe.poll()
|
||||||
|
|
||||||
|
|
||||||
func resize(cols: int, rows: int) -> void:
|
func resize(cols: int, rows: int) -> void:
|
||||||
if cols <= 0 or rows <= 0 or cols == NAN or rows == NAN or cols == INF or rows == INF:
|
if cols <= 0 or rows <= 0 or cols == NAN or rows == NAN or cols == INF or rows == INF:
|
||||||
push_error("Resizing must be done using positive cols and rows.")
|
push_error("Resizing must be done using positive cols and rows.")
|
||||||
|
@ -126,11 +131,6 @@ func _parse_env(env: Dictionary = {}) -> PoolStringArray:
|
||||||
return pairs
|
return pairs
|
||||||
|
|
||||||
|
|
||||||
func _process(_delta):
|
|
||||||
if _pipe:
|
|
||||||
_pipe.poll()
|
|
||||||
|
|
||||||
|
|
||||||
func fork(
|
func fork(
|
||||||
file: String = OS.get_environment("SHELL"),
|
file: String = OS.get_environment("SHELL"),
|
||||||
args: PoolStringArray = PoolStringArray(),
|
args: PoolStringArray = PoolStringArray(),
|
||||||
|
|
|
@ -23,6 +23,13 @@ const Signal = _PTYUnix.Signal
|
||||||
signal data_received(data)
|
signal data_received(data)
|
||||||
signal exited(exit_code, signum)
|
signal exited(exit_code, signum)
|
||||||
|
|
||||||
|
enum ProcessMode {
|
||||||
|
IDLE,
|
||||||
|
PHYSICS,
|
||||||
|
}
|
||||||
|
|
||||||
|
export(ProcessMode) var process_mode := ProcessMode.IDLE
|
||||||
|
|
||||||
export(NodePath) var terminal_path := NodePath() setget set_terminal_path
|
export(NodePath) var terminal_path := NodePath() setget set_terminal_path
|
||||||
|
|
||||||
var _terminal: _Terminal = null setget _set_terminal
|
var _terminal: _Terminal = null setget _set_terminal
|
||||||
|
@ -150,6 +157,16 @@ func get_master():
|
||||||
return _pty_native.get_master()
|
return _pty_native.get_master()
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta: float):
|
||||||
|
if process_mode == ProcessMode.IDLE:
|
||||||
|
_pty_native.run_process(delta)
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta: float):
|
||||||
|
if process_mode == ProcessMode.PHYSICS:
|
||||||
|
_pty_native.run_process(delta)
|
||||||
|
|
||||||
|
|
||||||
func _on_pty_native_data_received(data):
|
func _on_pty_native_data_received(data):
|
||||||
emit_signal("data_received", data)
|
emit_signal("data_received", data)
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ func write(data) -> void:
|
||||||
|
|
||||||
# Will be cleared when _flush() is called after VisualServer emits the "frame_pre_draw" signal.
|
# Will be cleared when _flush() is called after VisualServer emits the "frame_pre_draw" signal.
|
||||||
_buffer.push_back(data)
|
_buffer.push_back(data)
|
||||||
|
update() # Queue the CanvasItem for updates. Ensures VisualServer will draw a frame, otherwise it might not.
|
||||||
|
|
||||||
|
|
||||||
func _flush():
|
func _flush():
|
||||||
|
|
9
test/mocks/mock_pty_native.gd
Normal file
9
test/mocks/mock_pty_native.gd
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
extends "res://addons/godot_xterm/nodes/pty/pty_native.gd"
|
||||||
|
|
||||||
|
|
||||||
|
func write(data):
|
||||||
|
emit_signal("data_received", data)
|
||||||
|
|
||||||
|
|
||||||
|
func run_process(_delta: float):
|
||||||
|
pass
|
|
@ -1,27 +1,38 @@
|
||||||
extends "res://addons/gut/test.gd"
|
extends "res://addons/gut/test.gd"
|
||||||
|
|
||||||
|
|
||||||
class MockPTY:
|
|
||||||
extends "res://addons/godot_xterm/nodes/pty/pty_native.gd"
|
|
||||||
|
|
||||||
func write(data):
|
|
||||||
emit_signal("data_received", data)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseTest:
|
class BaseTest:
|
||||||
extends "res://addons/gut/test.gd"
|
extends "res://addons/gut/test.gd"
|
||||||
const PTY := preload("res://addons/godot_xterm/pty.gd")
|
const PTY := preload("res://addons/godot_xterm/pty.gd")
|
||||||
|
const MockPTYPath := "res://test/mocks/mock_pty_native.gd"
|
||||||
|
const MockPTY := preload(MockPTYPath)
|
||||||
|
|
||||||
var pty: PTY
|
var pty: PTY
|
||||||
var mock_pty_native: MockPTY
|
var mock_pty_native: MockPTY
|
||||||
|
|
||||||
func before_each():
|
func before_each():
|
||||||
pty = add_child_autofree(PTY.new())
|
pty = add_child_autofree(PTY.new())
|
||||||
mock_pty_native = autofree(MockPTY.new())
|
mock_pty_native = autofree(double(MockPTYPath).new())
|
||||||
pty._pty_native = mock_pty_native
|
pty._pty_native = mock_pty_native
|
||||||
watch_signals(mock_pty_native)
|
watch_signals(mock_pty_native)
|
||||||
|
|
||||||
|
|
||||||
|
class TestProcessMode:
|
||||||
|
extends BaseTest
|
||||||
|
|
||||||
|
func test_updates_only_during_idle_time():
|
||||||
|
pty.process_mode = PTY.ProcessMode.IDLE
|
||||||
|
for _i in range(4):
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
assert_between(get_call_count(mock_pty_native, "run_process"), 3, 4)
|
||||||
|
|
||||||
|
func test_updates_only_during_physics_step():
|
||||||
|
pty.process_mode = PTY.ProcessMode.PHYSICS
|
||||||
|
for _i in range(4):
|
||||||
|
yield(get_tree(), "physics_frame")
|
||||||
|
assert_between(get_call_count(mock_pty_native, "run_process"), 3, 4)
|
||||||
|
|
||||||
|
|
||||||
class TestPTYInterfaceGodotXterm2_0_0:
|
class TestPTYInterfaceGodotXterm2_0_0:
|
||||||
extends BaseTest
|
extends BaseTest
|
||||||
# Test that PTY class conforms to the GodotXterm 2.0.0 specification published at:
|
# Test that PTY class conforms to the GodotXterm 2.0.0 specification published at:
|
||||||
|
|
Loading…
Reference in a new issue