Skip to content

Commit c23e64f

Browse files
committed
Add api to customize input modes for RenderView
1 parent 2f27f3c commit c23e64f

7 files changed

Lines changed: 289 additions & 42 deletions

File tree

config/test_plugin.nim

Lines changed: 73 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,41 @@ var renderCommandEncoder: BinaryEncoder
1111
var num = 1
1212

1313
converter toWitString(s: string): WitString = ws(s)
14+
var target = getSetting("test.num-squares", 50)
1415

15-
defineCommand(ws"test-command-1",
16-
active = false,
17-
docs = ws"test command",
18-
params = wl[(WitString, WitString)](nil, 0),
19-
returnType = ws"",
20-
context = ws"",
21-
data = 123):
22-
proc(data: uint32, args: WitString): WitString {.cdecl.} =
23-
try:
24-
echo &"[guest] test-command-1 {data} '{args}'"
25-
except CatchableError as e:
26-
echo &"[guest] err: {e.msg}"
27-
return ws""
16+
proc handleViewRender(id: int32, data: uint32) {.cdecl.}
2817

29-
defineCommand(ws"test-command-2",
30-
active = false,
31-
docs = ws"test command",
32-
params = wl[(WitString, WitString)](nil, 0),
33-
returnType = ws"",
34-
context = ws"",
35-
data = 123):
36-
proc(data: uint32, args: WitString): WitString {.cdecl.} =
37-
try:
38-
echo &"[guest] test-command-2 {data} '{args}'"
39-
except CatchableError as e:
40-
echo &"[guest] err: {e.msg}"
41-
return ws""
18+
proc openCustomView() =
19+
var renderView = renderViewFromUserId(ws"test_plugin_view")
20+
if renderView.isNone:
21+
echo "[guest] Create new RenderView"
22+
renderView = newRenderView().some
23+
else:
24+
echo "[guest] Reusing existing RenderView"
25+
renderView.get.setUserId(ws"test_plugin_view")
26+
renderView.get.setRenderWhenInactive(true)
27+
renderView.get.setPreventThrottling(true)
28+
renderView.get.setRenderCallback(cast[uint32](handleViewRender), views.len.uint32)
29+
renderView.get.addMode(ws"test-plugin")
30+
renderView.get.markDirty()
31+
show(renderView.get.view, ws"#new-tab", true, true)
32+
views.add(renderView.take)
4233

4334
proc handleViewRender(id: int32, data: uint32) {.cdecl.} =
44-
let view {.cursor.} = views[0]
35+
let index = data.int
36+
if index notin 0..views.high:
37+
echo "handleViewRender: index out of bounds {index} notin 0..<{views.len}"
38+
return
39+
40+
let view {.cursor.} = views[index]
4541

4642
try:
4743
let version = apiVersion()
48-
let target = getSetting("test.num-squares", 50)
4944
inc num
5045
if num > target:
5146
num = 1
5247

53-
# num = target
48+
num = target
5449

5550
proc vec2(v: Vec2f): Vec2 = vec2(v.x, v.y)
5651

@@ -82,19 +77,57 @@ proc init() =
8277

8378
let s = getTime()
8479
var renderView = renderViewFromUserId(ws"test_plugin_view")
85-
if renderView.isNone:
86-
echo "[guest] Create new RenderView"
87-
renderView = newRenderView().some
88-
else:
80+
if renderView.isSome:
8981
echo "[guest] Reusing existing RenderView"
90-
renderView.get.setUserId(ws"test_plugin_view")
91-
renderView.get.setRenderWhenInactive(true)
92-
renderView.get.setPreventThrottling(true)
93-
renderView.get.setRenderCallback(cast[uint32](handleViewRender), 123)
94-
renderView.get.markDirty()
95-
show(renderView.get.view, ws"#new-tab", true, true)
96-
views.add(renderView.take)
82+
renderView.get.setRenderWhenInactive(true)
83+
renderView.get.setPreventThrottling(true)
84+
renderView.get.setRenderCallback(cast[uint32](handleViewRender), views.len.uint32)
85+
renderView.get.addMode(ws"test-plugin")
86+
renderView.get.markDirty()
87+
show(renderView.get.view, ws"#new-tab", true, true)
88+
views.add(renderView.take)
9789

9890
echo &"[guest] init test_plugin took {getTime() - s} ms"
9991

10092
init()
93+
94+
defineCommand(ws"test-command-1",
95+
active = false,
96+
docs = ws"test command",
97+
params = wl[(WitString, WitString)](nil, 0),
98+
returnType = ws"",
99+
context = ws"",
100+
data = 123):
101+
proc(data: uint32, args: WitString): WitString {.cdecl.} =
102+
try:
103+
echo &"[guest] test-command-1 {data} '{args}'"
104+
inc target
105+
except CatchableError as e:
106+
echo &"[guest] err: {e.msg}"
107+
return ws""
108+
109+
defineCommand(ws"test-command-2",
110+
active = false,
111+
docs = ws"test command",
112+
params = wl[(WitString, WitString)](nil, 0),
113+
returnType = ws"",
114+
context = ws"",
115+
data = 123):
116+
proc(data: uint32, args: WitString): WitString {.cdecl.} =
117+
try:
118+
echo &"[guest] test-command-2 {data} '{args}'"
119+
dec target
120+
except CatchableError as e:
121+
echo &"[guest] err: {e.msg}"
122+
return ws""
123+
124+
defineCommand(ws"open-custom-view",
125+
active = false,
126+
docs = ws"docs",
127+
params = wl[(WitString, WitString)](nil, 0),
128+
returnType = ws"",
129+
context = ws"",
130+
data = 0):
131+
proc(data: uint32, args: WitString): WitString {.cdecl.} =
132+
openCustomView()
133+
return ws""

plugin_api/v0/render.nim

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,48 @@ proc setRenderCallback*(self: RenderView; fun: uint32; data: uint32): void {.
194194
arg1 = fun
195195
arg2 = data
196196
renderSetRenderCallbackImported(arg0, arg1, arg2)
197+
198+
proc renderSetModesImported(a0: int32; a1: int32; a2: int32): void {.
199+
wasmimport("[method]render-view.set-modes", "nev:plugins/render").}
200+
proc setModes*(self: RenderView; modes: WitList[WitString]): void {.nodestroy.} =
201+
var
202+
arg0: int32
203+
arg1: int32
204+
arg2: int32
205+
arg0 = cast[int32](self.handle - 1)
206+
if modes.len > 0:
207+
arg1 = cast[int32](modes[0].addr)
208+
else:
209+
arg1 = 0.int32
210+
arg2 = cast[int32](modes.len)
211+
renderSetModesImported(arg0, arg1, arg2)
212+
213+
proc renderAddModeImported(a0: int32; a1: int32; a2: int32): void {.
214+
wasmimport("[method]render-view.add-mode", "nev:plugins/render").}
215+
proc addMode*(self: RenderView; mode: WitString): void {.nodestroy.} =
216+
var
217+
arg0: int32
218+
arg1: int32
219+
arg2: int32
220+
arg0 = cast[int32](self.handle - 1)
221+
if mode.len > 0:
222+
arg1 = cast[int32](mode[0].addr)
223+
else:
224+
arg1 = 0.int32
225+
arg2 = cast[int32](mode.len)
226+
renderAddModeImported(arg0, arg1, arg2)
227+
228+
proc renderRemoveModeImported(a0: int32; a1: int32; a2: int32): void {.
229+
wasmimport("[method]render-view.remove-mode", "nev:plugins/render").}
230+
proc removeMode*(self: RenderView; mode: WitString): void {.nodestroy.} =
231+
var
232+
arg0: int32
233+
arg1: int32
234+
arg2: int32
235+
arg0 = cast[int32](self.handle - 1)
236+
if mode.len > 0:
237+
arg1 = cast[int32](mode[0].addr)
238+
else:
239+
arg1 = 0.int32
240+
arg2 = cast[int32](mode.len)
241+
renderRemoveModeImported(arg0, arg1, arg2)

plugins/test_plugin/manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
"parameters": [{"name": "a", "type": "string"}],
2121
"returnType": "string",
2222
"description": "",
23+
},
24+
"open-custom-view": {
25+
"parameters": [],
26+
"returnType": "",
27+
"description": "",
2328
}
2429
},
2530
"permissions": {

src/generated/plugin_api_host.nim

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,12 @@ proc renderMarkDirty(host: HostContext; store: ptr ContextT;
282282
proc renderSetRenderCallback(host: HostContext; store: ptr ContextT;
283283
self: var RenderViewResource; fun: uint32;
284284
data: uint32): void
285+
proc renderSetModes(host: HostContext; store: ptr ContextT;
286+
self: var RenderViewResource; modes: sink seq[string]): void
287+
proc renderAddMode(host: HostContext; store: ptr ContextT;
288+
self: var RenderViewResource; mode: sink string): void
289+
proc renderRemoveMode(host: HostContext; store: ptr ContextT;
290+
self: var RenderViewResource; mode: sink string): void
285291
proc defineComponent*(linker: ptr LinkerT; host: HostContext): WasmtimeResult[
286292
void] =
287293
block:
@@ -1168,3 +1174,98 @@ proc defineComponent*(linker: ptr LinkerT; host: HostContext): WasmtimeResult[
11681174
renderSetRenderCallback(host, store, self[], fun, data)
11691175
if e.isErr:
11701176
return e
1177+
block:
1178+
let e = block:
1179+
var ty: ptr WasmFunctypeT = newFunctype(
1180+
[WasmValkind.I32, WasmValkind.I32, WasmValkind.I32], [])
1181+
linker.defineFuncUnchecked("nev:plugins/render",
1182+
"[method]render-view.set-modes", ty):
1183+
var mainMemory = caller.getExport("memory")
1184+
if mainMemory.isNone:
1185+
mainMemory = host.getMemoryFor(caller)
1186+
var memory: ptr UncheckedArray[uint8] = nil
1187+
if mainMemory.get.kind == WASMTIME_EXTERN_SHAREDMEMORY:
1188+
memory = cast[ptr UncheckedArray[uint8]](data(
1189+
mainMemory.get.of_field.sharedmemory))
1190+
elif mainMemory.get.kind == WASMTIME_EXTERN_MEMORY:
1191+
memory = cast[ptr UncheckedArray[uint8]](store.data(
1192+
mainMemory.get.of_field.memory.addr))
1193+
else:
1194+
assert false
1195+
var self: ptr RenderViewResource
1196+
var modes: seq[string]
1197+
self = host.resources.resourceHostData(parameters[0].i32,
1198+
RenderViewResource)
1199+
block:
1200+
let p0 = cast[ptr UncheckedArray[uint8]](memory[parameters[1].i32].addr)
1201+
modes = newSeq[typeof(modes[0])](parameters[2].i32)
1202+
for i0 in 0 ..< modes.len:
1203+
block:
1204+
let p1 = cast[ptr UncheckedArray[char]](memory[
1205+
cast[ptr int32](p0[i0 * 8 + 0].addr)[]].addr)
1206+
modes[i0] = newString(cast[ptr int32](p0[i0 * 8 + 4].addr)[])
1207+
for i1 in 0 ..< modes[i0].len:
1208+
modes[i0][i1] = p1[i1]
1209+
renderSetModes(host, store, self[], modes)
1210+
if e.isErr:
1211+
return e
1212+
block:
1213+
let e = block:
1214+
var ty: ptr WasmFunctypeT = newFunctype(
1215+
[WasmValkind.I32, WasmValkind.I32, WasmValkind.I32], [])
1216+
linker.defineFuncUnchecked("nev:plugins/render",
1217+
"[method]render-view.add-mode", ty):
1218+
var mainMemory = caller.getExport("memory")
1219+
if mainMemory.isNone:
1220+
mainMemory = host.getMemoryFor(caller)
1221+
var memory: ptr UncheckedArray[uint8] = nil
1222+
if mainMemory.get.kind == WASMTIME_EXTERN_SHAREDMEMORY:
1223+
memory = cast[ptr UncheckedArray[uint8]](data(
1224+
mainMemory.get.of_field.sharedmemory))
1225+
elif mainMemory.get.kind == WASMTIME_EXTERN_MEMORY:
1226+
memory = cast[ptr UncheckedArray[uint8]](store.data(
1227+
mainMemory.get.of_field.memory.addr))
1228+
else:
1229+
assert false
1230+
var self: ptr RenderViewResource
1231+
var mode: string
1232+
self = host.resources.resourceHostData(parameters[0].i32,
1233+
RenderViewResource)
1234+
block:
1235+
let p0 = cast[ptr UncheckedArray[char]](memory[parameters[1].i32].addr)
1236+
mode = newString(parameters[2].i32)
1237+
for i0 in 0 ..< mode.len:
1238+
mode[i0] = p0[i0]
1239+
renderAddMode(host, store, self[], mode)
1240+
if e.isErr:
1241+
return e
1242+
block:
1243+
let e = block:
1244+
var ty: ptr WasmFunctypeT = newFunctype(
1245+
[WasmValkind.I32, WasmValkind.I32, WasmValkind.I32], [])
1246+
linker.defineFuncUnchecked("nev:plugins/render",
1247+
"[method]render-view.remove-mode", ty):
1248+
var mainMemory = caller.getExport("memory")
1249+
if mainMemory.isNone:
1250+
mainMemory = host.getMemoryFor(caller)
1251+
var memory: ptr UncheckedArray[uint8] = nil
1252+
if mainMemory.get.kind == WASMTIME_EXTERN_SHAREDMEMORY:
1253+
memory = cast[ptr UncheckedArray[uint8]](data(
1254+
mainMemory.get.of_field.sharedmemory))
1255+
elif mainMemory.get.kind == WASMTIME_EXTERN_MEMORY:
1256+
memory = cast[ptr UncheckedArray[uint8]](store.data(
1257+
mainMemory.get.of_field.memory.addr))
1258+
else:
1259+
assert false
1260+
var self: ptr RenderViewResource
1261+
var mode: string
1262+
self = host.resources.resourceHostData(parameters[0].i32,
1263+
RenderViewResource)
1264+
block:
1265+
let p0 = cast[ptr UncheckedArray[char]](memory[parameters[1].i32].addr)
1266+
mode = newString(parameters[2].i32)
1267+
for i0 in 0 ..< mode.len:
1268+
mode[i0] = p0[i0]
1269+
renderRemoveMode(host, store, self[], mode)
1270+
if e.isErr:
1271+
return e

src/plugin_api/plugin_api.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,3 +358,13 @@ proc renderSetRenderCallback(host: HostContext; store: ptr ContextT; self: var R
358358
let instance = cast[ptr InstanceData](store.getData())
359359
instance[].funcs.handleViewRenderCallback(view.id2, fun, data).okOr(err):
360360
log lvlError, "Failed to call handleViewRenderCallback: " & $err
361+
362+
proc renderSetModes(host: HostContext; store: ptr ContextT; self: var RenderViewResource; modes: sink seq[string]): void =
363+
self.view.modes = modes
364+
365+
proc renderAddMode(host: HostContext; store: ptr ContextT; self: var RenderViewResource; mode: sink string): void =
366+
self.view.modes.add(mode)
367+
368+
proc renderRemoveMode(host: HostContext; store: ptr ContextT; self: var RenderViewResource; mode: sink string): void =
369+
self.view.modes.removeShift(mode)
370+

0 commit comments

Comments
 (0)