godotengine / godotengine/godot

FileSystemDock scrolls to top when ResourceSaver.save() is called from an editor plugin

Open
#118,482 1 comment 0 reactions 0 assignees View on GitHub
bug topic:editor usability
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

Tested versions:
- Reproducible in: 4.6.stable (89cea1439)
- Not tested in earlier versions, but likely present since the FileSystemDock scroll fix in #101078 only addressed scene saves, not ResourceSaver.save()

### System information

Godot v4.6.stable - macOS Tahoe (26.4.0) - Multi-window, 1 monitor - OpenGL 3 (Compatibility) - Apple M1 Pro - Apple M1 Pro (8 threads) - 16.00 GiB memory

### Issue description

When an editor plugin calls `ResourceSaver.save()` to update a `.res` file in the project directory, the FileSystemDock briefly scrolls/jumps — the scroll position resets and then returns. This creates a visible flicker every time a resource is saved programmatically.

This is similar to #101065, which was fixed for scene saves in #101078 by preserving scroll position in `_update_tree()`. However, `ResourceSaver.save()` triggers the same `_fs_changed() → update_all() → _update_tree()` path without preserving the scroll position.

**Expected behavior:** FileSystemDock scroll position should remain stable when resources are saved from a plugin.

**Actual behavior:** FileSystemDock briefly flickers/scrolls on every `ResourceSaver.save()` call.

### Steps to reproduce

1. Create an editor plugin with a Timer that calls `ResourceSaver.save()` on a `.res` file every few seconds
2. Open any project, scroll down in the FileSystem dock
3. Observe the scroll position jumping briefly each time the resource is saved

Minimal plugin code:

```gdscript
@tool
extends EditorPlugin

var _timer: Timer

func _enter_tree() -> void:
_timer = Timer.new()
_timer.wait_time = 3.0
_timer.timeout.connect(_on_timeout)
add_child(_timer)
_timer.start()

func _exit_tree() -> void:
_timer.queue_free()

func _on_timeout() -> void:
var image := Image.create(16, 16, false, Image.FORMAT_RGBA8)
var texture := ImageTexture.create_from_image(image)
ResourceSaver.save(texture, "res://test_texture.res")
```

### Minimal reproduction project (MRP)

N/A — reproducible with the plugin code above in any project.

Contributor guide

Open the contributing guide

Research direction

Start by tracing FileSystemDock's _fs_changed() → update_all() → _update_tree() path, comparing it with the scroll-preserving behavior added for scene saves in #101078. Reproduce the flicker using the Timer-based editor plugin and verify that saving a .res resource with ResourceSaver.save() leaves the FileSystemDock scroll position stable.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.