Navigation: review r3 fix
This commit is contained in:
4 files changed
+48
-1
No files matched your search
@@ -74,3 +74,4 @@ if id, ok := res.Chosen(); ok && id == "wrap" {
|
|||||||
- 菜单打开期间,焦点保持在标题上,高亮项由组件管理。驱动菜单的按键注册在标题上,而 MyGo 的 active descendant 不公开,因此高亮变化时用 `c.Announce` 朗读当前项,并把它写入标题的 `Description`。
|
- 菜单打开期间,焦点保持在标题上,高亮项由组件管理。驱动菜单的按键注册在标题上,而 MyGo 的 active descendant 不公开,因此高亮变化时用 `c.Announce` 朗读当前项,并把它写入标题的 `Description`。
|
||||||
- 弹层打开时在 160 ms 内淡入,减少动画时直接显示。关闭时立即消失:弹层关闭后 MyGo 不再构建其元素,公开接口无法为已移除的浮层做淡出。
|
- 弹层打开时在 160 ms 内淡入,减少动画时直接显示。关闭时立即消失:弹层关闭后 MyGo 不再构建其元素,公开接口无法为已移除的浮层做淡出。
|
||||||
- 点击菜单内任意位置(包括禁用项)或用指针打开子菜单后,焦点回到所属标题,方向键、Enter、Escape 继续有效。
|
- 点击菜单内任意位置(包括禁用项)或用指针打开子菜单后,焦点回到所属标题,方向键、Enter、Escape 继续有效。
|
||||||
|
- 菜单打开时用 Tab 或 Shift+Tab 离开菜单栏,菜单关闭,焦点留在 Tab 目标上;焦点在菜单栏内任意位置时 Escape 关闭菜单。
|
||||||
@@ -105,9 +105,17 @@ func Menubar(c *ui.Context, menus []MenubarMenu, opts MenubarOptions) MenubarRes
|
|||||||
titles[i] = t.Bounds()
|
titles[i] = t.Bounds()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if m.st.open >= 0 && bar.Shortcut(0, ui.KeyEscape) {
|
||||||
|
m.close()
|
||||||
|
}
|
||||||
if m.st.open >= 0 {
|
if m.st.open >= 0 {
|
||||||
m.overlay(titles)
|
m.overlay(titles)
|
||||||
}
|
}
|
||||||
|
// Presses in the menu refocus the title, so lost focus means Tab left the menubar.
|
||||||
|
if m.st.open >= 0 && m.st.focusTo < 0 && !bar.FocusWithin() {
|
||||||
|
slog.Debug("mujica: menubar close on focus out")
|
||||||
|
m.st.open, m.st.hl = -1, nil
|
||||||
|
}
|
||||||
// Focus stays on the title, so the highlighted item is read out.
|
// Focus stays on the title, so the highlighted item is read out.
|
||||||
if name := m.current(); m.moved && name != "" {
|
if name := m.current(); m.moved && name != "" {
|
||||||
c.Announce(name)
|
c.Announce(name)
|
||||||
|
|||||||
+7
-1
@@ -20,6 +20,9 @@ func (m *menubarRun) overlay(titles []ui.Rect) {
|
|||||||
m.close()
|
m.close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if back.Pressed() {
|
||||||
|
m.focus(st.open)
|
||||||
|
}
|
||||||
// Title hotspots above the backdrop switch menus as the pointer moves.
|
// Title hotspots above the backdrop switch menus as the pointer moves.
|
||||||
for i, r := range titles {
|
for i, r := range titles {
|
||||||
hot := ui.Box(c).Absolute().Left(r.X).Top(r.Y).Size(r.W, r.H).Cursor(ui.CursorPointer)
|
hot := ui.Box(c).Absolute().Left(r.X).Top(r.Y).Size(r.W, r.H).Cursor(ui.CursorPointer)
|
||||||
@@ -31,6 +34,9 @@ func (m *menubarRun) overlay(titles []ui.Rect) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if hot.Pressed() {
|
||||||
|
m.focus(st.open)
|
||||||
|
}
|
||||||
if hot.Hovered() && i != st.open {
|
if hot.Hovered() && i != st.open {
|
||||||
m.openMenu(i, false)
|
m.openMenu(i, false)
|
||||||
}
|
}
|
||||||
@@ -76,7 +82,7 @@ func (m *menubarRun) panel(l int, x, y float32, parent ui.Rect) (*ui.Element, *u
|
|||||||
y = max(4, wh-4-pb.H)
|
y = max(4, wh-4-pb.H)
|
||||||
}
|
}
|
||||||
panel.Left(max(4, x)).Top(y)
|
panel.Left(max(4, x)).Top(y)
|
||||||
if panel.Clicked() {
|
if panel.Clicked() || panel.Pressed() {
|
||||||
m.focus(st.open)
|
m.focus(st.open)
|
||||||
}
|
}
|
||||||
var anchor *ui.Element
|
var anchor *ui.Element
|
||||||
|
|||||||
@@ -178,6 +178,38 @@ func TestMenubarKeysAfterClickInMenu(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMenubarTabOutClosesMenu(t *testing.T) {
|
||||||
|
for _, back := range []bool{false, true} {
|
||||||
|
a := &menubarApp{}
|
||||||
|
tt := ui.NewTester(func(c *ui.Context) {
|
||||||
|
Use(c, Settings{})
|
||||||
|
ui.Column(c).Fill().Children(func() {
|
||||||
|
Button(c, "Before", ButtonOptions{})
|
||||||
|
Menubar(c, a.menus(), MenubarOptions{})
|
||||||
|
Button(c, "After", ButtonOptions{})
|
||||||
|
})
|
||||||
|
}, 700, 500)
|
||||||
|
tt.Key(0, ui.KeyTab)
|
||||||
|
tt.Key(0, ui.KeyTab)
|
||||||
|
tt.Key(0, ui.KeyDown)
|
||||||
|
if !tt.HasText("Quit") {
|
||||||
|
t.Fatal("menu did not open")
|
||||||
|
}
|
||||||
|
mods, want := ui.Modifiers(0), "After"
|
||||||
|
if back {
|
||||||
|
mods, want = ui.Shift, "Before"
|
||||||
|
}
|
||||||
|
tt.Key(mods, ui.KeyTab)
|
||||||
|
if tt.HasText("Quit") || !tt.Focused(want) {
|
||||||
|
t.Fatalf("shift=%v: menu open %v, focus on %s %v", back, tt.HasText("Quit"), want, tt.Focused(want))
|
||||||
|
}
|
||||||
|
tt.Key(0, ui.KeyEscape)
|
||||||
|
if !tt.Focused(want) {
|
||||||
|
t.Fatalf("shift=%v: Escape moved focus off %s", back, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMenubarLongMenuScrolls(t *testing.T) {
|
func TestMenubarLongMenuScrolls(t *testing.T) {
|
||||||
var items []MenubarItem
|
var items []MenubarItem
|
||||||
for i := range 30 {
|
for i := range 30 {
|
||||||
|
|||||||
Reference in new issue
Block a user