class

Tryst::SDL::Viewport

Inherits Reference < Object

An SDL3 rendering surface living inside a Tk frame.

app = Tryst::App.new(title: "game")
app.show
viewport = Tryst::SDL::Viewport.new(app, width: 640, height: 480)

Drawing goes through SDL, not Tk, so the frame is a hole in the widget tree that SDL paints into rather than something Tk renders. Keyboard input, though, stays TK'S: the embedded SDL window is not in SDL's own event loop and receives nothing, so key state comes from Tk bindings on the frame - see #key_down?.

ON MACOS THE SURFACE COVERS THE WHOLE WINDOW. Tk on Aqua gives a native window to a toplevel and none to the frames inside it, so SDL is handed the toplevel and paints over every other widget in it, wherever the frame happens to sit. #covers_toplevel? says so at runtime. A viewport meant to share a window with Tk widgets needs its own toplevel there, or its overlays drawn in SDL.

Constructors

new(app : Tryst::App, parent : String | Nil = nil, width : Int32 = 640, height : Int32 = 480, vsync : Bool = true, name : String | Nil = nil)

Builds the Tk frame, adopts its native window and puts a renderer in it.

parent is a widget path to build inside; nil means the root. vsync ties presentation to the display refresh, which is what anything animating wants and what an emulator pacing its own frames does not.

Source

Class methods

ensure_video(app : Tryst::App) : Nil

SDL's video subsystem MUST come up after Tk, never before. Bringing it up first aborts on macOS, where both want to own the NSApplication - and it aborts before any Crystal of yours runs, so it looks like the program never started. Viewport takes care of the order by initialising video here, once a live App has necessarily already initialised Tk.

Source

Instance methods

covers_toplevel?

Whether SDL is painting over the whole toplevel rather than just this frame. True on macOS - see the note on the class.

Source
destroy

Tears down the renderer, the SDL window and the Tk frame, in that order. Idempotent.

Note this does NOT shut SDL down - that is process-wide and belongs to whatever owns the application. See Tryst::SDL.quit for the ordering constraint that comes with it.

Source
destroyed?
Source
height
Source
input_focus?

Whether this window has keyboard input focus right now - false once the user switches to another application, another Space, or another window of this one.

A POLL rather than a Tk <Deactivate>/<Activate> binding, which is the obvious-looking alternative and does not work here: Tk only generates those from its own NSWindow notifications, and for a toplevel SDL has adopted <Activate> arrives while <Deactivate> never does. SDL_GetWindowFlags reads window-manager state SDL already tracks, so this needs no event loop of its own - which an adopted window has never been part of anyway.

X11 gives SDL a child window of the frame rather than the toplevel, and a child never receives X input focus, so this is false there regardless of what the user is looking at.

Source
key_down?(key : String) : Bool

Whether a key is held right now, by lowercased Tk keysym - "left", "space", "a". For a game loop, which wants to ask rather than be told.

String#downcase allocates even for already-lowercase strings; in a game loop this runs once per key per frame, so avoid it.

Source
keys_down

Every key currently held.

Source
path

The Tk widget path of the frame SDL draws into.

Source
pixel_size

The drawable size in real pixels, which is not the frame's size in Tk units on a scaled display.

Source
render

Draws a frame: yields the renderer, then presents.

The presenting is the point. Nothing drawn appears until it happens, and forgetting it looks exactly like the renderer not working at all - a blank surface and no error anywhere.

Does NOT clear first. An incremental frame that redraws only what changed is a perfectly good thing to want, so wiping the surface is left to the caller and spelled r.clear.

Source
renderer

The drawing API for this viewport.

Source
renderer_name

Which renderer backend SDL chose - "metal", "opengl", "direct3d11" and so on. Worth logging when something draws wrong.

Source
width
Source