Skip to content

Share the frontend code that does not depend on the toolkit - #50

Merged
ivanizag merged 2 commits into
masterfrom
worktree-share-frontend
Aug 12, 2026
Merged

Share the frontend code that does not depend on the toolkit#50
ivanizag merged 2 commits into
masterfrom
worktree-share-frontend

Conversation

@ivanizag

Copy link
Copy Markdown
Owner

The frontends were copies of each other. frontend/shared, created for the
drop targets, now holds everything they have in common that does not depend on
a toolkit.

What moved

File What it holds
view.go What is on screen, the help text, and the chain that picks the snapshot and the title of the window
keys.go shared.Key and the codes of the Apple II keyboard, one table for the five frontends
keyboard.go Typing, the commands of the function keys, and the paste typed in slowly
paddles.go The four paddles, the three buttons, the apple keys and the mouse used as a joystick
mouse.go The pointer as the mouse card reads it
mixer.go The mixer with every sound source of the machine attached

sdlMouse.go and sdl3Mouse.go are gone. Each frontend keeps its own
translation table (sdlKey, sdl3Key, ebitenKey, wasmKey, retroKey) and
what really belongs to its toolkit: the clipboard, the instance ids of the SDL3
joysticks, the file system Ebitengine hands the dropped files in.

966 lines removed, 463 added.

What is aligned

Following a2sdl, the frontend that gets the most use:

  • Ctrl with a letter was broken on a2ebiten and a2wasm. The key was already
    zero based and 97 was subtracted from it again, so Ctrl-A sent 160 instead of
    1. Both use the table of a2sdl now.
  • The libretro core gets Ctrl-Left, the Delete of the Base64A.
  • a2sdl3 marks the drive under the pointer when the areas of the drives are
    shown with F8, as a2sdl does.

Two fixes go the other way, from a2sdl3 to a2sdl, because they are bugs and not
differences between the libraries:

  • The apple keys are found by scancode, so they work on the layouts where the
    alt keys produce another symbol.
  • Losing the focus of the window releases them, so one held while changing
    windows does not stay pressed.

a2ebiten keeps Ctrl-F5 for the readout of the speed it draws on the corner of
the screen, the only key left that does something else anywhere. It is already
documented as such.

Tests

go test ./... passes and every frontend builds, the wasm and the libretro
core included. What needs no machine is covered: the codes of the keyboard, the
scaling of the axis and the buttons of the paddles, the mouse, and the drive
the drop targets mark while a file is dragged and after it is dropped.

The mouse now leaves the pointer where it was on a window without size, instead
of dividing by zero on a size SDL3 failed to report.

The frontends were copies of each other. The help was the same text three
times, the chain that picks the screen to show was the same branches three
times, and the SDL2 and SDL3 keyboards, joysticks and mice were the same files
twice with the constants of each toolkit.

frontend/shared holds them now: the view with what is on screen and the help,
the keyboard with the codes of the Apple II keyboard and the commands of the
emulator, the paddles with the four axis and the three buttons, the mouse, and
the mixer with every sound source of the machine already attached. The
frontends keep what belongs to their toolkit: the translation of their keys to
shared.Key, the clipboard, the instance ids of the SDL3 joysticks and the file
system Ebitengine hands the dropped files in. The drop targets take the drag
over the window too, so a frontend only tells which drive the pointer is on.

One implementation aligns what the frontends did differently, following a2sdl
where they disagreed:

- Ctrl with a letter was broken on a2ebiten and a2wasm. The key was already
  zero based and 97 was subtracted from it again, so Ctrl-A sent 160 and not 1.
- The libretro core gets Ctrl-Left, the Delete of the Base64A.
- a2sdl3 marks the drive under the pointer when the areas are shown with F8.
- a2sdl finds the apple keys by scancode, so they work on the layouts where the
  alt keys produce another symbol, and releases them when the window loses the
  focus. Both come from a2sdl3.

a2ebiten keeps Ctrl-F5 for the readout of the speed it draws on the corner of
the screen, the only key that does something else anywhere.

The mouse leaves the pointer where it was on a window without size instead of
dividing by zero, which SDL3 can report when asking for the size fails.

What needs no machine is tested: the codes of the keyboard, the paddles, the
mouse and the drive the drop targets mark.
Comment thread frontend/shared/mixer.go Outdated

// NewMixer creates the mixer of a machine with every sound source of it
// attached, ready for the frontend to send the samples to its audio device
func NewMixer(a *izapple2.Apple2) *audio.Mixer {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Rename to NewFrontMixer() to avoid collissions.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Renamed to NewFrontMixer(), along with the four call sites.

Comment thread frontend/shared/mouse.go Outdated
return m.x, m.y, m.pressed
}

// TODO: SDL_WarpMouseInWindow

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Why?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

No reason, it came along with the rest of the SDL2 mouse and I kept it. It means nothing in a package that knows nothing about SDL, so it is gone.

Comment thread frontend/shared/mouse.go
m.pressed = pressed
}

// ReadMouse returns the position of the pointer on the window and whether its

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Mark this block as the izapple2.Mouse interface implementation

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Marked with an izapple2.MouseProvider implementation line over ReadMouse.

p.mouseButtons[button] = pressed
}

// ReadButton returns whether a pushbutton is pressed, as the machine reads it

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Mark this and the following one as JoystickProvider interface implementation

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Marked with an izapple2.JoysticksProvider implementation line over both. I moved mouseToPaddle up next to SetMousePosition so that the helper does not sit under the mark.

@ivanizag

Copy link
Copy Markdown
Owner Author

And I would make sense now to add the mouse implementation for Ebiten

The mouse the frontends share is little more than a scale, so a2ebiten can have
one now. Ebitengine has no mouse events, the pointer is polled when the frame is
updated, and its position is taken on the picture instead of on the window, so
it lands on the same place whatever the size of the window is. The models with a
mouse, like desktop, are of some use there now.

A pointer outside the window stays on the edge instead of wrapping around, which
Ebitengine reports as soon as the pointer leaves the picture.

NewMixer is now NewFrontMixer, so that it does not look like the NewMixer of the
audio package. The methods that the machine calls are marked as the
implementations of izapple2.MouseProvider and izapple2.JoysticksProvider, and
the note about SDL_WarpMouseInWindow is gone: it came from the SDL2 mouse and
means nothing in a package that knows nothing about SDL.
@ivanizag

Copy link
Copy Markdown
Owner Author

Added it. Ebitengine has no mouse events, so the pointer is polled on every frame update, and its position is taken on the 1128x768 picture instead of on the window, so it lands on the same place whatever the size of the window is. desktop and the other models with a mouse work there now.

A pointer outside the window stays on the edge instead of wrapping around, which Ebitengine reports as soon as it leaves the picture. doc/frontend_ebiten.md moves the mouse from what is missing to a section of its own.

@ivanizag
ivanizag merged commit 1b563d7 into master Aug 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant