blob: 0fa322875acba6ad029dfe5873cb456ffd9dc1ea (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
// Source: https://gist.githubusercontent.com/s-ilent/067d4e477041d52d2f8eabd78927d1a4/raw/568c222044a8ce3c33426c495cccbfe7c3a0c733/LinuxTabFix.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
/// <summary>
/// Linux Editor Tab Navigation Patch for Unity (2022.3+, Unity 6).
/// Restores missing ASCII '\t' character codes stripped by Linux window backend
/// and manages focus handshakes between IMGUIContainers in UI Toolkit windows.
/// </summary>
[InitializeOnLoad]
public static class LinuxTabFix
{
private static readonly ConditionalWeakTable<IMGUIContainer, object> patchedContainers
= new ConditionalWeakTable<IMGUIContainer, object>();
static LinuxTabFix()
{
// Ensure idempotent event subscription across domain reloads
EditorApplication.update -= ApplyTabPatchToFocusedWindow;
EditorApplication.update += ApplyTabPatchToFocusedWindow;
}
private static void ApplyTabPatchToFocusedWindow()
{
EditorWindow focusedWindow = EditorWindow.focusedWindow;
if (focusedWindow == null) return;
VisualElement root = focusedWindow.rootVisualElement;
if (root == null) return;
List<IMGUIContainer> containers = root.Query<IMGUIContainer>().ToList();
int count = containers.Count;
for (int i = 0; i < count; i++)
{
IMGUIContainer container = containers[i];
if (container == null) continue;
int currentIndex = i;
// Patch unhandled containers without modifying container properties
if (!patchedContainers.TryGetValue(container, out _))
{
patchedContainers.Add(container, null);
Action originalHandler = container.onGUIHandler;
container.onGUIHandler = () =>
{
Event e = Event.current;
if (e != null && e.type == EventType.KeyDown && e.keyCode == KeyCode.Tab)
{
// Restore character code stripped by Linux native window backend
if (e.character == 0)
{
e.character = '\t';
}
bool isShift = e.shift;
// Execute original IMGUI pass
originalHandler?.Invoke();
// When boundary is reached, transfer focus to adjacent container
if (GUIUtility.keyboardControl == 0)
{
int targetIndex = isShift ? currentIndex - 1 : currentIndex + 1;
if (targetIndex >= 0 && targetIndex < count && targetIndex < containers.Count)
{
IMGUIContainer targetContainer = containers[targetIndex];
if (targetContainer != null)
{
targetContainer.Focus();
focusedWindow.Repaint();
}
}
}
return;
}
originalHandler?.Invoke();
};
}
}
}
}
#endif
|