Files
gen1recomp/src/render/DesktopCompanion.lua
T
2026-08-16 22:24:12 +02:00

126 lines
4.3 KiB
Lua

-- Minimal second-window process for src/render/DesktopScreen.lua.
local DesktopCompanion = {}
function DesktopCompanion.install(config)
local enet = require("enet")
local host = assert(enet.host_create())
local peer = assert(host:connect(("127.0.0.1:%d"):format(config.port), 2))
local image, sourceW, sourceH, preference
local background = { 0, 0, 0, 1 }
local connected, commandedQuit = false, false
local pointerDown = false
local started = love.timer.getTime()
local lastContact = started
local function send(kind, payload)
if not connected then return end
pcall(peer.send, peer, kind .. config.token .. (payload or ""), 1, "reliable")
end
local function receiveFrame(data)
local prefix = "F" .. config.token .. "\n"
if data:sub(1, #prefix) ~= prefix then return end
local split = data:find("\n", #prefix + 1, true)
if not split then return end
local w, h, rgb, mode = data:sub(#prefix + 1, split - 1)
:match("^(%d+),(%d+),(%d+),([%w_:.-]+)$")
w, h, rgb = tonumber(w), tonumber(h), tonumber(rgb)
if not w or not h or w < 1 or h < 1 or w > 4096 or h > 4096 then return end
local ok, raw = pcall(love.data.decompress, "string", "lz4",
data:sub(split + 1))
if not ok or type(raw) ~= "string" or #raw ~= w * h * 4 then return end
local made, pixels = pcall(love.image.newImageData, w, h, "rgba8", raw)
if not made then return end
if not image or sourceW ~= w or sourceH ~= h then
if image and image.release then image:release() end
image = love.graphics.newImage(pixels)
else
image:replacePixels(pixels)
end
sourceW, sourceH, preference = w, h, mode
image:setFilter(mode:find("cover", 1, true) and "linear" or "nearest",
mode:find("cover", 1, true) and "linear" or "nearest")
background = {
math.floor(rgb / 0x10000) % 0x100 / 255,
math.floor(rgb / 0x100) % 0x100 / 255,
rgb % 0x100 / 255, 1,
}
end
local function service()
while true do
local event = host:service(0)
if not event then break end
if event.type == "connect" then
connected, lastContact = true, love.timer.getTime()
send("H")
elseif event.type == "receive" then
lastContact = love.timer.getTime()
if event.data == "Q" .. config.token then
commandedQuit = true
love.event.quit()
elseif event.data ~= "P" .. config.token then
receiveFrame(event.data)
end
elseif event.type == "disconnect" then
love.event.quit()
end
end
end
local function placement()
if not image then return 0, 0, 1 end
local ww, wh = love.graphics.getDimensions()
local cover = preference and preference:find("cover", 1, true)
local scale = (cover and math.max or math.min)(ww / sourceW, wh / sourceH)
return (ww - sourceW * scale) / 2, (wh - sourceH * scale) / 2, scale
end
local function input(action, x, y)
if not image then return false end
local dx, dy, scale = placement()
local sx, sy = math.floor((x - dx) / scale), math.floor((y - dy) / scale)
if sx < 0 or sy < 0 or sx >= sourceW or sy >= sourceH then return false end
send("I", ("\n%s,%d,%d"):format(action, sx, sy))
return true
end
function love.update()
service()
local t = love.timer.getTime()
if (not connected and t - started > 5) or t - lastContact > 5 then
love.event.quit()
end
end
function love.draw()
love.graphics.clear(background[1], background[2], background[3], background[4])
if not image then return end
local x, y, scale = placement()
love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(image, x, y, 0, scale, scale)
end
function love.mousepressed(x, y, button)
if button == 1 then pointerDown = input("down", x, y) end
end
function love.mousereleased(x, y, button)
if button == 1 and pointerDown then
if not input("up", x, y) then send("I", "\ncancel,0,0") end
pointerDown = false
end
end
function love.touchpressed(_, x, y) input("down", x, y) end
function love.touchreleased(_, x, y) input("up", x, y) end
function love.keypressed(key)
if key == "escape" then love.event.quit() end
end
function love.quit()
if not commandedQuit then send("C") end
pcall(peer.disconnect_now, peer)
end
end
return DesktopCompanion