X Tutup
Skip to content

Add switch on hover to TabBar#103478

Merged
Repiteo merged 1 commit intogodotengine:masterfrom
KoBeWi:hover_witch
Oct 22, 2025
Merged

Add switch on hover to TabBar#103478
Repiteo merged 1 commit intogodotengine:masterfrom
KoBeWi:hover_witch

Conversation

@KoBeWi
Copy link
Member

@KoBeWi KoBeWi commented Mar 2, 2025

Docks will open when hovered during dragging.

ayOjP0dLwt.mp4

Same behavior exists in bottom panel.

EDIT:
Reworked to add switch_on_hover to TabBar. Now it works everywhere.

godot.windows.editor.dev.x86_64_8V0QtGUsXA.mp4

(pretty sure there was an issue for switch on hover for scenes)

@KoBeWi KoBeWi added this to the 4.x milestone Mar 2, 2025
@KoBeWi KoBeWi requested a review from a team March 2, 2025 20:34
@KoBeWi KoBeWi requested review from a team as code owners March 4, 2025 13:11
@KoBeWi KoBeWi changed the title Add switch on hover to dock tabs Add switch on hover to TabBar Mar 4, 2025
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, it works as expected.

Note that there's no delay after hovering a tab before it switches, which feels inconsistent with other actions like dragging items on top of inspector sections (which uses a delay configured in some project/editor setting). The delay avoids accidentally switching tabs when quickly dragging an item on top of unrelated tabs.

See KDE's Dolphin for comparison:

kde_dolphin_drag_and_drop_onto_tabs.mp4

@KoBeWi
Copy link
Member Author

KoBeWi commented Mar 4, 2025

The bottom panel also doesn't have delay. It can be improved later I think.

Copy link
Contributor

@kitbdev kitbdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to get #103601 in first for the drag and drop tests.

}
}
} else if (switch_on_hover && hover > -1 && hover != current) {
const_cast<TabBar *>(this)->set_current_tab(hover);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like how we do this in a const method, but it happens a lot in can_drop_data and the current alternatives aren't great. So its fine for now.

@KoBeWi KoBeWi force-pushed the hover_witch branch 2 times, most recently from 6c9dd11 to bf5d7fa Compare May 15, 2025 19:45
@KoBeWi
Copy link
Member Author

KoBeWi commented May 16, 2025

Well, turns out there were quite a few issues with what I did (including TabContainer rearranging not working at all, though not sure if it was from the beginning or after my latest changes). I modified my approach a bit and it should be all working now.

Copy link
Contributor

@kitbdev kitbdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes errors when dragging a node from the scene dock, switching to another scene by hovering over the scene tab bar, and trying to drop to the scene dock. It seems to sometimes crash, not sure how exactly to reproduce yet.
So the scene tree dock dragging logic will need some tweaks.

ERROR: Node not found: "/root/@EditorNode@21408/@Panel@14/@VBoxContainer@15/DockHSplitLeftL/DockHSplitLeftR/DockHSplitMain/@VBoxContainer@26/DockVSplitCenter/@VSplitContainer@54/@VBoxContainer@55/@EditorMainScreen@102/MainScreen/@CanvasItemEditor@11646/@VSplitContainer@11298/@HSplitContainer@11300/@HSplitContainer@11302/@Control@11303/@SubViewportContainer@11304/@SubViewport@11305/Control2/Control" (absolute path attempted from "/root/@EditorNode@21408/@Panel@14/@VBoxContainer@15/DockHSplitLeftL/DockHSplitLeftR/DockVSplitLeftR/DockSlotLeftUR/Scene/@SceneTreeEditor@5127").

There is also issues when trying to drag text between text edits in a similar way, when dragging between scenes changes the inspector and creates TextEdits. I guess this is because it never receives NOTIFICATION_DRAG_BEGIN since the dragging started before it existed.
ERROR: The main caret should not be removed. ERROR: scene\gui\tree.cpp:1509 - Index p_column = 0 is out of bounds (cells.size() = 0).
This seems like a larger dragging issue, and NOTIFICATION_DRAG_BEGIN should be sent to all new nodes while dragging is ongoing.

Comment on lines -1412 to +1416
drag_data["type"] = p_type;
drag_data["type"] = "tab";
drag_data["tab_type"] = p_type;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that changing this means that some users may need to update it as well, see gilzoide/godot-dockable-container#24
Maybe instead we could keep the type the same and add a drag_data["is_rearrange_tab"] = true or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk, consistent type makes more sense.
Technically this is not part of the API, so compatibility is not a concern here.

@kitbdev
Copy link
Contributor

kitbdev commented May 16, 2025

I reproduced the crash with a call stack.
I was dragging a scene tree dock node around for a while, hovering over another scene tree dock item after switching scenes and waiting a while.
It looks like the crash happens here:

Details

Exception has occurred: W32/0xC0000005
Unhandled exception thrown: read access violation.
p_item-> was 0x7FF700000102.

godot.windows.editor.dev.x86_64.exe!_restore_treeitem_custom_color(TreeItem * p_item) Line 82 (c:\Projects\godotsrc\godot\editor\scene_tree_dock.cpp:82)
godot.windows.editor.dev.x86_64.exe!SceneTreeDock::_inspect_hovered_node() Line 100 (c:\Projects\godotsrc\godot\editor\scene_tree_dock.cpp:100)
godot.windows.editor.dev.x86_64.exe!call_with_variant_args_helper<SceneTreeDock>(SceneTreeDock * p_instance, void(SceneTreeDock::*)() p_method, const Variant * * p_args, Callable::CallError & r_error, IndexSequence<> __formal) Line 223 (c:\Projects\godotsrc\godot\core\variant\binder_common.h:223)
godot.windows.editor.dev.x86_64.exe!call_with_variant_args<SceneTreeDock>(SceneTreeDock * p_instance, void(SceneTreeDock::*)() p_method, const Variant * * p_args, int p_argcount, Callable::CallError & r_error) Line 337 (c:\Projects\godotsrc\godot\core\variant\binder_common.h:337)
godot.windows.editor.dev.x86_64.exe!CallableCustomMethodPointer<SceneTreeDock,void>::call(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 103 (c:\Projects\godotsrc\godot\core\object\callable_method_pointer.h:103)
godot.windows.editor.dev.x86_64.exe!Callable::callp(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 57 (c:\Projects\godotsrc\godot\core\variant\callable.cpp:57)
godot.windows.editor.dev.x86_64.exe!Object::emit_signalp(const StringName & p_name, const Variant * * p_args, int p_argcount) Line 1288 (c:\Projects\godotsrc\godot\core\object\object.cpp:1288)
godot.windows.editor.dev.x86_64.exe!Node::emit_signalp(const StringName & p_name, const Variant * * p_args, int p_argcount) Line 4292 (c:\Projects\godotsrc\godot\scene\main\node.cpp:4292)
godot.windows.editor.dev.x86_64.exe!Object::emit_signal<>(const StringName & p_name) Line 930 (c:\Projects\godotsrc\godot\core\object\object.h:930)
godot.windows.editor.dev.x86_64.exe!Timer::_notification(int p_what) Line 64 (c:\Projects\godotsrc\godot\scene\main\timer.cpp:64)
godot.windows.editor.dev.x86_64.exe!Timer::_notification_forwardv(int p_notification) Line 36 (c:\Projects\godotsrc\godot\scene\main\timer.h:36)
godot.windows.editor.dev.x86_64.exe!Object::_notification_forward(int p_notification) Line 931 (c:\Projects\godotsrc\godot\core\object\object.cpp:931)
godot.windows.editor.dev.x86_64.exe!Object::notification(int p_notification, bool p_reversed) Line 879 (c:\Projects\godotsrc\godot\core\object\object.h:879)
godot.windows.editor.dev.x86_64.exe!SceneTree::_process_group(SceneTree::ProcessGroup * p_group, bool p_physics) Line 1183 (c:\Projects\godotsrc\godot\scene\main\scene_tree.cpp:1183)
godot.windows.editor.dev.x86_64.exe!SceneTree::_process(bool p_physics) Line 1263 (c:\Projects\godotsrc\godot\scene\main\scene_tree.cpp:1263)
godot.windows.editor.dev.x86_64.exe!SceneTree::process(double p_time) Line 697 (c:\Projects\godotsrc\godot\scene\main\scene_tree.cpp:697)
godot.windows.editor.dev.x86_64.exe!Main::iteration() Line 4747 (c:\Projects\godotsrc\godot\main\main.cpp:4747)
godot.windows.editor.dev.x86_64.exe!OS_Windows::run() Line 2278 (c:\Projects\godotsrc\godot\platform\windows\os_windows.cpp:2278)
godot.windows.editor.dev.x86_64.exe!widechar_main(int argc, wchar_t * * argv) Line 96 (c:\Projects\godotsrc\godot\platform\windows\godot_windows.cpp:96)
godot.windows.editor.dev.x86_64.exe!_main() Line 122 (c:\Projects\godotsrc\godot\platform\windows\godot_windows.cpp:122)

@KoBeWi KoBeWi requested a review from a team as a code owner May 17, 2025 21:28
@KoBeWi
Copy link
Member Author

KoBeWi commented May 17, 2025

The errors should be fixed now.

@YeldhamDev
Copy link
Member

I don't think the switch should be instantaneous. In other places in the editor with the same mechanism, there's a brief pause before it happens.

@KoBeWi
Copy link
Member Author

KoBeWi commented Sep 18, 2025

Which other place involves switching tabs and has a delay?

@YeldhamDev
Copy link
Member

Not tabs specifically, but in the inspector for example, dragging something to a folded category will only unfold it after a few milliseconds:

Screencast_20250918_111256.webm

@KoBeWi
Copy link
Member Author

KoBeWi commented Sep 18, 2025

As I already mentioned, the bottom panel (which is the closest to a tab bar with switch on hover) does not have delay:

godot.windows.editor.dev.x86_64_vUT2lrkHKM.mp4

If this PR adds a delay and #106164 gets merged, bottom panel will have the delay too. I can add it if this behavior change is ok (at least it will be consistent).

@YeldhamDev
Copy link
Member

I would be in favor of the delay, as this behavior is what I see when using other software.

@KoBeWi
Copy link
Member Author

KoBeWi commented Sep 18, 2025

Added the delay.

Copy link
Member

@YeldhamDev YeldhamDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows warnings should be fixed, but overall looks good. Would be nice if the delay time would be centralized and shared by multiple UI elements, but that's for another PR.

@kitbdev kitbdev modified the milestones: 4.x, 4.6 Sep 24, 2025
@kitbdev kitbdev mentioned this pull request Sep 26, 2025
@kitbdev

This comment was marked as resolved.

Copy link
Contributor

@Repiteo Repiteo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scene/main/timer.h is no longer a transitive include

@Repiteo Repiteo merged commit 8191042 into godotengine:master Oct 22, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Oct 22, 2025

Thanks!

@KoBeWi KoBeWi deleted the hover_witch branch October 22, 2025 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

X Tutup