DatumHueEnterprise v0.0.24datumhue.com
Contents

Messages, events and shared state

Send messages between apps, react to what happens on the workstation, and keep values that several apps read and watch.

Apps work together in three ways:

You want toUse
tell other apps something as it happensmessages, datumhue.messaging
hear about windows, apps and inputsystem events, datumhue.events
keep values other apps can read, change and watchdocuments, datumhue.documents

Send messages

messaging.publish sends a payload on a topic, and messaging.subscribe runs a callback for every message on that topic, with the payload in msg.payload. A payload is a plain Lua value: a table, a string, a number or a boolean. Each subscriber gets its own copy, in which a table the payload holds twice is two tables; a table that holds itself raises. A message reaches the apps on this workstation that subscribe to its topic, but never the app that sent it, even when it subscribes too.

Every app shares the same topic names, so give a private channel a name no other app would pick, such as one starting with your package's name.

This program starts a dice service, a second app with no window, and asks it for a roll five times a second:

dice.lualua
local messaging = datumhue.messaging

-- A service app, with no window, that answers every roll
-- request with a number from 1 to 6.
local roller = [[
local messaging = datumhue.messaging
messaging.subscribe({
    topic = "dice/roll",
    callback = function()
        messaging.publish({
            topic = "dice/result",
            payload = { value = math.random(1, 6) },
        })
    end,
})
]]
datumhue.app.spawn({ name = "roller", code = roller, service = true })

-- This app shows every result it hears.
local card = datumhue.ui.root:panel({ padding = 24, gap = 12 })
card:label({ text = "Dice", font_size = 24 })
local results = card:label({ text = "Rolling..." })
local rolls = {}
messaging.subscribe({
    topic = "dice/result",
    callback = function(msg)
        table.insert(rolls, msg.payload.value)
        results.text = "Rolled " .. table.concat(rolls, " ")
    end,
})

-- Ask for a roll every 0.2 seconds.
datumhue.time.every(0.2, function()
    messaging.publish({ topic = "dice/roll", payload = true })
end)

In this example: datumhue.messaging datumhue.app.spawn datumhue.ui.root UiElement:panel UiElement:label datumhue.messaging.subscribe UiElement.text datumhue.time.every datumhue.messaging.publish

The roller keeps running while its subscription is live, and ends with the app that started it. Launch other apps covers starting apps.

With scope = "network", a message reaches the apps of your @scope whose packages came from where yours did, on this workstation and on the others connected to the same deployment, including apps your app starts from Lua source, unless it starts them with storage = "own". Both sides need the network permission. An app under another @scope, or a copy of yours run from a folder, reaches a different topic under the same name, and messaging.presence keeps its groups apart the same way. To talk with the apps of other @scopes, both sides set shared = true: a shared topic, or presence group, is one for every app that names it with shared.

A network topic keeps the apps of other @scopes from mixing their messages by accident; it keeps out no one: anyone who can reach the deployment and runs a modified workstation can hear and send on any network topic. To pass something confidential to another creator's app, put it in a document from documents.create and send that app a grant over a shared topic.

Hear system events

events.on runs a callback each time a named event happens: the window resizes, an app starts, ends or takes focus, an app asks for a permission. An event about an app reaches only the apps that manage it: itself, the app that started it, and the apps above that. Its payload names the app it is about.

Some events report a value you would otherwise read every frame. They fire once as you subscribe, with the current value, then again whenever it changes:

EventFollows
input_sourceinput.last_source, the device last used
fullscreenscreen.is_fullscreen and screen.fullscreen_available
focusui.focused, the widget holding focus
densitytheme.density, the size of controls
themetheme.current(), the theme in effect

connectivity fires once as you subscribe, with whether this session is connected.

lua
local hint = datumhue.ui.root:label({ text = "" })
datumhue.events.on("input_source", function(e)
    hint.text = e.source == "gamepad" and "Press A" or "Click"
end)

events.on returns a Subscription; call Subscription:unsubscribe when you no longer want the event.

Share values in a document

A document holds keys and values that several apps read, change and watch. documents.open_named opens one by name, and it lasts until the workstation quits. Document:set writes a key, Document:get reads one, and Document:subscribe runs a callback for each change under a key prefix.

Every app of your @scope on this workstation that opens the same name gets the same document, including apps your app starts from Lua source, unless it starts them with storage = "own". An app under another @scope, or a copy of yours run from a folder, gets a different document under the same name. With shared = true, every app that opens the name with shared gets one document, whatever its @scope.

This program opens a board, listens for notes, and starts a second app that writes one:

board.lualua
local documents = datumhue.documents

-- Every app of this @scope on this workstation that opens
-- "board" gets the same document, until the workstation quits.
local board = documents.open_named({ name = "board" })
board:subscribe("notes/", function(key, value)
    print(key .. " = " .. tostring(value))
end)

-- Another app writes to the board; this one hears it.
datumhue.app.spawn({
    name = "writer",
    service = true,
    code = [[
local board = datumhue.documents.open_named({ name = "board" })
board:set("notes/greeting", "hello from the writer"):ready()
]],
})

In this example: datumhue.documents datumhue.documents.open_named Document:subscribe datumhue.app.spawn

It prints notes/greeting = hello from the writer. Opening a document and reading a key wait for their result; Waiting: suspending calls and handles explains how. For data only your app keeps from one run to the next, use Save data between runs instead.

Hand a document to another app

documents.create makes a document with no name, which other apps can open only through a grant. Document:grant makes a DocumentGrant for any document, to read or to write as well. DocumentGrant:encode turns it into a string that travels over any channel, a message included, and documents.open opens the document from it.

With scope = "network", a document is shared with other workstations connected to the same deployment, and needs the network permission. A workstation syncs it while a handle or a subscription on it is open there, and an app's handles close when the app ends. When two of them write the same key, the newest write wins. Each workstation turns away a write stamped more than ten minutes ahead of its own clock, so a workstation whose clock is off by more than that loses writes; keep clocks set automatically. Keys are /-separated paths. Writing a key replaces what its author wrote under it, and Document:delete_prefix removes what its author wrote under the prefix; keys other authors wrote there stay.

A document opened by name keeps the apps of other @scopes from mixing their data by accident; it keeps out no one: anyone who can reach the deployment and runs a modified workstation can read and change it, under any author. Keep anything private in a document from documents.create, shared through grants; to give one to another creator's app, send it the grant over a shared topic.

Each signed-in person also has a communal document, opened with documents.communal: their own section is always theirs to write, and reading another person's section takes a grant from them.

A grant to a network document can cover one key prefix, and lasts for the days valid_days sets. It reads the document's history and the changes stamped until it runs out, never one stamped later; once it runs out, DatumHue starts no new sync of the document to its holder. A grant cannot be taken back: whoever holds it keeps that access until it runs out. Whoever holds a grant can DocumentGrant:delegate a narrower one, but never a wider one.

A write grant's holder can add writes stamped from an hour before the grant was made until it runs out, and can still add such writes after it runs out; they lose to any newer write of the same key.

See also

Reference used on this page: datumhue.messaging datumhue.events datumhue.documents datumhue.app.spawn datumhue.ui.root UiElement:panel UiElement:label datumhue.messaging.subscribe UiElement.text datumhue.time.every datumhue.messaging.publish datumhue.input.last_source datumhue.screen.is_fullscreen datumhue.screen.fullscreen_available datumhue.ui.focused datumhue.theme.density datumhue.theme.current datumhue.events.on datumhue.documents.open_named Document:subscribe datumhue.messaging.presence datumhue.documents.create Subscription:unsubscribe Document:set Document:get Document:grant DocumentGrant:encode datumhue.documents.open Document:delete_prefix datumhue.documents.communal DocumentGrant:delegate

datumhue.com

(c) 2026 Shuusei AB. Quote excerpts of this manual, with attribution to DatumHue, in your own documentation, tutorials, course materials, reviews, and other writing or video. Republishing it in whole or in substantial part needs written permission: support@datumhue.com.

Victor Mono is licensed under the SIL Open Font License 1.1
Copyright (c) 2024, Rune Bjørnerås (https://github.com/rubjo)

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL


-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Try

    ↑↓ selectEnter openTab filter

    Settings

    Theme
    Text
    Print

    Keyboard shortcuts

    / or Ctrl KSearch
    ↑ ↓ EnterPick a result
    TabNext result filter
    j kNext or previous entry
    [ ]Previous or next page
    yCopy a link to the current entry
    ?These shortcuts
    EscClose

    On this page