start of input logger

This commit is contained in:
2025-10-19 22:59:42 +01:00
parent 87a3d4b43b
commit fd470a7f7a
2 changed files with 179 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# Input Logger Example
This example demonstrates how to capture and log all pointer and key events in a Gio application.
## Features
- Captures all pointer events (press, release, move, drag, scroll)
- Captures all key events (press, release) with modifiers
- Logs event details including:
- Key name and state (press/release)
- Pointer position and button states
- Scroll amounts
- Modifier keys (Ctrl, Shift, Alt, etc.)
- Simple flex layout with a gray background area for interaction
## Usage
```bash
cd examples/inputlog
go run .
```
Move your mouse around the window and press keys to see the events logged to the console.
## Event Details
The application logs:
- **Key Events**: Name, State (Press/Release), Modifiers
- **Pointer Events**: Kind, Source (Mouse/Touch), Position, Buttons, Scroll, Modifiers
- **Focus Events**: When the window gains/loses focus
## Implementation Notes
- Uses `event.Op()` to register event handlers
- Uses `gtx.Source.Event()` to retrieve events
- Implements proper event filtering for both key and pointer events
- Uses material theme for consistent styling

142
examples/inputlog/main.go Normal file
View File

@@ -0,0 +1,142 @@
// SPDX-License-Identifier: Unlicense OR MIT
package main
import (
"fmt"
"image/color"
"os"
"github.com/mleku/fromage/app"
"github.com/mleku/fromage/io/event"
"github.com/mleku/fromage/io/key"
"github.com/mleku/fromage/io/pointer"
"github.com/mleku/fromage/layout"
"github.com/mleku/fromage/op"
"github.com/mleku/fromage/op/clip"
"github.com/mleku/fromage/op/paint"
"github.com/mleku/fromage/unit"
"github.com/mleku/fromage/widget/material"
)
func main() {
go func() {
w := &app.Window{}
if err := run(w); err != nil {
fmt.Printf("Error: %v\n", err)
}
os.Exit(0)
}()
app.Main()
}
func run(w *app.Window) error {
var ops op.Ops
var th = material.NewTheme()
var inputHandler = &InputHandler{}
for {
switch e := w.Event().(type) {
case app.DestroyEvent:
return e.Err
case app.FrameEvent:
gtx := app.NewContext(&ops, e)
inputHandler.Layout(gtx, th)
e.Frame(&ops)
}
}
}
type InputHandler struct {
keyTag event.Tag
pointerTag event.Tag
}
func (h *InputHandler) Layout(gtx layout.Context, th *material.Theme) {
// Initialize tags if not set
if h.keyTag == nil {
h.keyTag = &h.keyTag
}
if h.pointerTag == nil {
h.pointerTag = &h.pointerTag
}
// Create a flex layout that fills the entire window
flex := layout.Flex{
Axis: layout.Vertical,
}
// Create a simple box that captures all input events
box := layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
// Draw a background rectangle
paint.FillShape(gtx.Ops, color.NRGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xFF},
clip.Rect{Max: gtx.Constraints.Max}.Op())
// Set up event handlers
h.setupEventHandlers(gtx)
return layout.Dimensions{Size: gtx.Constraints.Max}
})
// Add some text at the top
label := layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return material.Label(th, unit.Sp(16),
"Input Logger - Move mouse and press keys to see events logged").Layout(gtx)
})
flex.Layout(gtx, label, box)
// Handle events after layout
h.handleEvents(gtx)
}
func (h *InputHandler) setupEventHandlers(gtx layout.Context) {
// Set up a hit area for pointer events
area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
// Set up pointer event handler
event.Op(gtx.Ops, h.pointerTag)
// Set up key event handler
event.Op(gtx.Ops, h.keyTag)
// Request focus for key events
gtx.Execute(key.FocusCmd{Tag: h.keyTag})
area.Pop()
}
func (h *InputHandler) handleEvents(gtx layout.Context) {
// Handle key events
keyFilter := key.Filter{Focus: h.keyTag}
for {
ev, ok := gtx.Event(keyFilter)
if !ok {
break
}
switch ev := ev.(type) {
case key.Event:
fmt.Printf("Key Event: Name=%s, State=%s, Modifiers=%s\n",
ev.Name, ev.State, ev.Modifiers)
case key.FocusEvent:
fmt.Printf("Focus Event: Focus=%t\n", ev.Focus)
}
}
// Handle pointer events
pointerFilter := pointer.Filter{
Target: h.pointerTag,
Kinds: pointer.Press | pointer.Release | pointer.Move | pointer.Drag | pointer.Scroll,
}
for {
ev, ok := gtx.Event(pointerFilter)
if !ok {
break
}
switch ev := ev.(type) {
case pointer.Event:
fmt.Printf("Pointer Event: Kind=%s, Source=%s, PointerID=%d, Position=(%.1f,%.1f), Buttons=%s, Scroll=(%.1f,%.1f), Modifiers=%s\n",
ev.Kind, ev.Source, ev.PointerID, ev.Position.X, ev.Position.Y, ev.Buttons, ev.Scroll.X, ev.Scroll.Y, ev.Modifiers)
}
}
}