Skip to content

Commit

Permalink
(feat) complete overlay implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
xTrayambak committed Nov 22, 2024
1 parent f868c78 commit f0ef953
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 15 deletions.
1 change: 1 addition & 0 deletions nim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
--define:adwMinor=4
--define:nvgGLES3
--deepCopy:on
--panics:on
Binary file added src/IBMPlexSans-Regular.ttf
Binary file not shown.
10 changes: 9 additions & 1 deletion src/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,20 @@ type
DaemonConfig* = object
port*: uint = 9898

OverlayConfig* = object
width*: uint = 600
height*: uint = 200
headingSize*: float = 32f
descriptionSize*: float = 18f
font*: Option[string] = none(string)
anchors*: string = "top-right"

Config* = object
apk*: APKConfig
lucem*: LucemConfig
tweaks*: Tweaks
client*: ClientConfig

overlay*: OverlayConfig
daemon*: DaemonConfig

proc backend*(config: Config): WindowingBackend =
Expand Down
4 changes: 4 additions & 0 deletions src/internal_fonts.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## A fallback font baked into the Lucem binary (IBM Plex Sans)

const
IbmPlexSans* = staticRead("IBMPlexSans-Regular.ttf")
98 changes: 84 additions & 14 deletions src/lucem_overlay.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import std/[logging, strutils, importutils]
import ./[argparser, sugar]
## Lucem Overlay
## Copyright (C) 2024 Trayambak Rai

import std/[os, logging, strutils, importutils, times]
import ./[argparser, sugar, config, internal_fonts]
import pkg/[siwin, opengl, nanovg, colored_logger, vmath]
import pkg/siwin/platforms/wayland/[window, windowOpengl]

Expand All @@ -15,18 +18,46 @@ type
expireTime*: float
icon*: Option[string]
closed*: bool
config*: Config

vg*: NVGContext
wl*: WindowWaylandOpengl
size*: IVec2 = ivec2(600, 200)

lastEpoch*: float
timeSpent*: float

headingFont*: Font

proc draw*(overlay: var Overlay) =
debug "overlay: redrawing surface"
glClearColor(255, 255, 255, 255)
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glViewport(0, 0, overlay.size.x, overlay.size.y)
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT or
GL_DEPTH_BUFFER_BIT or
GL_STENCIL_BUFFER_BIT)

overlay.vg.beginFrame(overlay.size.x.cfloat, overlay.size.y.cfloat, 1f) # TODO: fractional scaling support
overlay.vg.roundedRect(0, 0, overlay.size.x.cfloat, overlay.size.y.cfloat, 16f)
overlay.vg.fillColor(rgba(0.1, 0.1, 0.1, 0.5))
overlay.vg.fillColor(rgba(0.3, 0.3, 0.3, 0.8))
overlay.vg.fill()

overlay.vg.fontFace("heading")
overlay.vg.textAlign(haLeft, vaTop)
overlay.vg.fontSize(overlay.config.overlay.headingSize)
overlay.vg.fillColor(white(255))
discard overlay.vg.text(16f, 16f, overlay.heading)

overlay.vg.fontFace("heading")
overlay.vg.textAlign(haLeft, vaTop)
overlay.vg.fontSize(overlay.config.overlay.descriptionSize)
overlay.vg.fillColor(white(255))
discard overlay.vg.text(16f, 64f, overlay.description)

# TODO: icon rendering, even though we don't use them yet
# but it'd be useful for the future

overlay.vg.endFrame()

proc initOverlay*(input: Input) {.noReturn.} =
var overlay: Overlay
Expand All @@ -46,34 +77,73 @@ proc initOverlay*(input: Input) {.noReturn.} =

if (let oIcon = input.flag("icon"); *oIcon):
overlay.icon = oIcon

debug "overlay: got all arguments, parsing config"
var config = parseConfig(input)

debug "overlay: creating surface"
overlay.size = ivec2(config.overlay.width.int32, config.overlay.height.int32)
overlay.wl = newOpenglWindowWayland(
kind = WindowWaylandKind.LayerSurface,
layer = Layer.Overlay,
size = overlay.size,
namespace = "lucem"
)
overlay.wl.setKeyboardInteractivity(LayerInteractivityMode.None)
overlay.wl.setAnchor(@[LayerEdge.Right, LayerEdge.Top])
overlay.wl.setExclusiveZone(1)
var anchors: seq[LayerEdge]
for value in config.overlay.anchors.split('-'):
debug "overlay: got anchor: " & value
case value.toLowerAscii()
of "left", "l": anchors &= LayerEdge.Left
of "right", "r": anchors &= LayerEdge.Right
of "top", "up", "u": anchors &= LayerEdge.Top
of "bottom", "down", "d": anchors &= LayerEdge.Bottom
else:
warn "overlay: unhandled anchor: " & value

overlay.wl.setAnchor(anchors)
overlay.wl.setExclusiveZone(10000)

#[debug "overlay: loading OpenGL"
overlay.config = move(config)

debug "overlay: loading OpenGL"
loadExtensions()

debug "overlay: creating NanoVG instance"
nvgInit(glGetProc)
overlay.vg = nvgCreateContext({
nifAntialias
})
overlay.wl.firstStep(makeVisible = true)
while not overlay.closed:
overlay.wl.step()
var data =
if (*config.overlay.font and fileExists(&config.overlay.font)):
cast[seq[byte]](readFile(&config.overlay.font))
else:
cast[seq[byte]](IbmPlexSans)

overlay.headingFont = overlay.vg.createFontMem(
"heading",
data
)
overlay.lastEpoch = epochTime()
overlay.timeSpent = 0f

overlay.wl.eventsHandler.onRender = proc(event: RenderEvent) =
overlay.draw()

overlay.wl.eventsHandler.onTick = proc(event: TickEvent) =
let epoch = epochTime()
let elapsed = epoch - overlay.lastEpoch

overlay.timeSpent += elapsed
overlay.lastEpoch = epoch

debug "overlay: " & $overlay.timeSpent & "s / " & $overlay.expireTime & 's'

if overlay.wl.redrawRequested:
overlay.draw()]#
if overlay.timeSpent >= overlay.expireTime:
info "overlay: Completed lifetime. Closing!"
overlay.wl.close()

overlay.wl.run()
quit(0)

proc main =
Expand Down

0 comments on commit f0ef953

Please sign in to comment.