From 387bb88ac8a4d5f5005f50ca0912617a97656af9 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 10 Aug 2026 20:10:42 +0300 Subject: [PATCH] feat: add event stringers --- doc.go | 7 ++++- event_stringers.go | 60 +++++++++++++++++++++++++++++++++++++++ event_stringers_test.go | 63 +++++++++++++++++++++++++++++++++++++++++ events.go | 4 +-- pointer.go | 6 ++-- 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 event_stringers.go create mode 100644 event_stringers_test.go diff --git a/doc.go b/doc.go index f6eeb86..2857c6b 100644 --- a/doc.go +++ b/doc.go @@ -52,4 +52,9 @@ // Reference: https://github.com/gogpu/gpucontext package gpucontext -const stringNone = "None" +const ( + stringNone = "None" + stringLeft = "Left" + stringRight = "Right" + stringMiddle = "Middle" +) diff --git a/event_stringers.go b/event_stringers.go new file mode 100644 index 0000000..d64e533 --- /dev/null +++ b/event_stringers.go @@ -0,0 +1,60 @@ +// Copyright 2026 The gogpu Authors +// SPDX-License-Identifier: MIT + +package gpucontext + +import "strings" + +// String returns the mouse button name for debugging. +// +// The names for the extra buttons match [Button.String]: X1 and X2. Values +// outside the defined buttons are reported as Unknown. +func (b MouseButton) String() string { + switch b { + case MouseButtonLeft: + return stringLeft + case MouseButtonRight: + return stringRight + case MouseButtonMiddle: + return stringMiddle + case MouseButton4: + return "X1" + case MouseButton5: + return "X2" + default: + return "Unknown" + } +} + +// String returns a human-readable representation of the modifier keys. +// +// Combined modifiers are ordered as Ctrl, Alt, Shift, Super, CapsLock, and +// NumLock, matching the gogpu/ui event convention. Unknown bits are ignored, +// also matching the gogpu/ui event convention; a value containing only unknown +// bits therefore produces an empty string. +func (m Modifiers) String() string { + if m == 0 { + return stringNone + } + + parts := make([]string, 0, 6) + if m&ModControl != 0 { + parts = append(parts, "Ctrl") + } + if m&ModAlt != 0 { + parts = append(parts, "Alt") + } + if m&ModShift != 0 { + parts = append(parts, "Shift") + } + if m&ModSuper != 0 { + parts = append(parts, "Super") + } + if m&ModCapsLock != 0 { + parts = append(parts, "CapsLock") + } + if m&ModNumLock != 0 { + parts = append(parts, "NumLock") + } + return strings.Join(parts, "+") +} diff --git a/event_stringers_test.go b/event_stringers_test.go new file mode 100644 index 0000000..d5f6c15 --- /dev/null +++ b/event_stringers_test.go @@ -0,0 +1,63 @@ +// Copyright 2026 The gogpu Authors +// SPDX-License-Identifier: MIT + +package gpucontext + +import "testing" + +func TestMouseButtonString(t *testing.T) { + tests := []struct { + name string + button MouseButton + want string + }{ + {name: "left", button: MouseButtonLeft, want: "Left"}, + {name: "right", button: MouseButtonRight, want: "Right"}, + {name: "middle", button: MouseButtonMiddle, want: "Middle"}, + {name: "button four", button: MouseButton4, want: "X1"}, + {name: "button five", button: MouseButton5, want: "X2"}, + {name: "invalid", button: MouseButton(255), want: "Unknown"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.button.String(); got != tt.want { + t.Errorf("MouseButton(%d).String() = %q, want %q", tt.button, got, tt.want) + } + }) + } +} + +func TestModifiersString(t *testing.T) { + const unknown Modifiers = 1 << 6 + + tests := []struct { + name string + mods Modifiers + want string + }{ + {name: "zero", mods: 0, want: "None"}, + {name: "control", mods: ModControl, want: "Ctrl"}, + {name: "alt", mods: ModAlt, want: "Alt"}, + {name: "shift", mods: ModShift, want: "Shift"}, + {name: "super", mods: ModSuper, want: "Super"}, + {name: "caps lock", mods: ModCapsLock, want: "CapsLock"}, + {name: "num lock", mods: ModNumLock, want: "NumLock"}, + {name: "control and shift", mods: ModControl | ModShift, want: "Ctrl+Shift"}, + {name: "control alt shift", mods: ModControl | ModAlt | ModShift, want: "Ctrl+Alt+Shift"}, + {name: "all known", mods: ModControl | ModAlt | ModShift | ModSuper | ModCapsLock | ModNumLock, want: "Ctrl+Alt+Shift+Super+CapsLock+NumLock"}, + // Unknown bits are ignored to stay compatible with gogpu/ui's + // event.Modifiers.String implementation. + {name: "unknown only", mods: unknown, want: ""}, + {name: "unknown mixed", mods: ModControl | unknown, want: "Ctrl"}, + {name: "unknown and all known", mods: ModControl | ModAlt | ModShift | ModSuper | ModCapsLock | ModNumLock | unknown, want: "Ctrl+Alt+Shift+Super+CapsLock+NumLock"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.mods.String(); got != tt.want { + t.Errorf("Modifiers(%d).String() = %q, want %q", tt.mods, got, tt.want) + } + }) + } +} diff --git a/events.go b/events.go index 62603d7..ea8de60 100644 --- a/events.go +++ b/events.go @@ -491,9 +491,9 @@ func (k Key) String() string { case KeyPageDown: return "PageDown" case KeyLeft: - return "Left" + return stringLeft case KeyRight: - return "Right" + return stringRight case KeyUp: return "Up" case KeyDown: diff --git a/pointer.go b/pointer.go index 1a4f502..c2e127a 100644 --- a/pointer.go +++ b/pointer.go @@ -248,11 +248,11 @@ func (b Button) String() string { case ButtonNone: return stringNone case ButtonLeft: - return "Left" + return stringLeft case ButtonMiddle: - return "Middle" + return stringMiddle case ButtonRight: - return "Right" + return stringRight case ButtonX1: return "X1" case ButtonX2: