Merge branch 'main' of git.sr.ht:~jacqueline/tangara-fw

custom
jacqueline 1 year ago
commit beb1f65495
  1. 62
      lua/browser.lua
  2. 13
      lua/licenses.lua
  3. 17
      lua/main.lua
  4. 19
      lua/main_menu.lua
  5. 33
      lua/playing.lua
  6. 139
      lua/settings.lua
  7. 1
      src/lua/CMakeLists.txt
  8. 2
      src/lua/bridge.cpp
  9. 15
      src/lua/include/lua_screen.hpp
  10. 75
      src/lua/lua_screen.cpp
  11. 3
      src/ui/include/screen.hpp
  12. 3
      src/ui/include/screen_lua.hpp
  13. 1
      src/ui/include/ui_fsm.hpp
  14. 36
      src/ui/screen_lua.cpp
  15. 38
      src/ui/ui_fsm.cpp

@ -6,12 +6,11 @@ local queue = require("queue")
local playing = require("playing")
local theme = require("theme")
local playback = require("playback")
local screen = require("screen")
local browser = {}
function browser.create(opts)
local screen = {}
screen.root = lvgl.Object(nil, {
return screen:new {
createUi = function(self)
self.root = lvgl.Object(nil, {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
@ -22,14 +21,14 @@ function browser.create(opts)
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
})
screen.root:center()
self.root:center()
screen.status_bar = widgets.StatusBar(screen.root, {
title = opts.title,
self.status_bar = widgets.StatusBar(self.root, {
title = self.title,
})
if opts.breadcrumb then
local header = screen.root:Object {
if self.breadcrumb then
local header = self.root:Object {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
@ -48,7 +47,7 @@ function browser.create(opts)
}
header:Label {
text = opts.breadcrumb,
text = self.breadcrumb,
text_font = font.fusion_10,
}
@ -64,7 +63,7 @@ function browser.create(opts)
h = lvgl.SIZE_CONTENT,
pad_column = 4,
})
local original_iterator = opts.iterator:clone()
local original_iterator = self.iterator:clone()
local enqueue = widgets.IconBtn(buttons, "//lua/img/enqueue.png", "Enqueue")
enqueue:onClicked(function()
queue.add(original_iterator)
@ -81,57 +80,52 @@ function browser.create(opts)
)
end
screen.list = lvgl.List(screen.root, {
self.list = lvgl.List(self.root, {
w = lvgl.PCT(100),
h = lvgl.PCT(100),
flex_grow = 1,
scrollbar_mode = lvgl.SCROLLBAR_MODE.OFF,
})
local back = screen.list:add_btn(nil, "< Back")
local back = self.list:add_btn(nil, "< Back")
back:onClicked(backstack.pop)
back:add_style(theme.list_item)
screen.focused_item = 0
screen.last_item = 0
screen.add_item = function(item)
self.focused_item = 0
self.last_item = 0
self.add_item = function(item)
if not item then return end
screen.last_item = screen.last_item + 1
local this_item = screen.last_item
local btn = screen.list:add_btn(nil, tostring(item))
self.last_item = self.last_item + 1
local this_item = self.last_item
local btn = self.list:add_btn(nil, tostring(item))
btn:onClicked(function()
local contents = item:contents()
if type(contents) == "userdata" then
backstack.push(function()
return browser.create({
title = opts.title,
backstack.push(require("browser"):new {
title = self.title,
iterator = contents,
breadcrumb = tostring(item),
})
end)
else
queue.clear()
queue.add(contents)
playback.playing:set(true)
backstack.push(playing)
backstack.push(playing:new())
end
end)
btn:onevent(lvgl.EVENT.FOCUSED, function()
screen.focused_item = this_item
if screen.last_item - 5 < this_item then
screen.add_item(opts.iterator())
self.focused_item = this_item
if self.last_item - 5 < this_item then
self.add_item(self.iterator())
end
end)
btn:add_style(theme.list_item)
end
for _ = 1, 8 do
local val = opts.iterator()
local val = self.iterator()
if not val then break end
screen.add_item(val)
self.add_item(val)
end
return screen
end
return browser.create
}

@ -2,20 +2,23 @@ local backstack = require("backstack")
local widgets = require("widgets")
local font = require("font")
local theme = require("theme")
local screen = require("screen")
local function show_license(text)
backstack.push(function()
local screen = widgets.MenuScreen {
backstack.push(screen:new {
createUi = function(self)
self.menu = widgets.MenuScreen {
show_back = true,
title = "Licenses",
}
screen.root:Label {
self.menu.root:Label {
w = lvgl.PCT(100),
h = lvgl.SIZE_CONTENT,
text_font = font.fusion_10,
text = text,
}
end)
end
})
end
local function gpl(copyright)
@ -175,4 +178,6 @@ return function()
library("tremor", "bsd", function()
xiphbsd("Copyright (c) 2002, Xiph.org Foundation")
end)
return menu
end

@ -1,8 +1,13 @@
local font = require("font")
local vol = require("volume")
local controls = require("controls")
local time = require("time")
local lock_time = time.ticks()
-- Set up property bindings that are used across every screen.
GLOBAL_BINDINGS = {
-- Show an alert with the current volume whenver the volume changes.
vol.current_pct:bind(function(pct)
require("alerts").show(function()
local container = lvgl.Object(nil, {
@ -32,6 +37,18 @@ GLOBAL_BINDINGS = {
container:center()
end)
end),
-- When the device has been locked for a while, default to showing the now
-- playing screen after unlocking.
controls.lock_switch:bind(function(locked)
if locked then
lock_time = time.ticks()
elseif time.ticks() - lock_time > 8000 then
local queue = require("queue")
if queue.size:get() > 0 then
require("playing"):pushIfNotShown()
end
end
end),
}
local backstack = require("backstack")

@ -5,8 +5,10 @@ local backstack = require("backstack")
local browser = require("browser")
local playing = require("playing")
local theme = require("theme")
local screen = require("screen")
return function()
return screen:new {
createUi = function()
local menu = widgets.MenuScreen({})
menu.list = lvgl.List(menu.root, {
@ -17,7 +19,7 @@ return function()
local now_playing = menu.list:add_btn(nil, "Now Playing")
now_playing:onClicked(function()
backstack.push(playing)
backstack.push(playing:new())
end)
now_playing:add_style(theme.list_item)
@ -25,21 +27,20 @@ return function()
for _, idx in ipairs(indexes) do
local btn = menu.list:add_btn(nil, tostring(idx))
btn:onClicked(function()
backstack.push(function()
return browser {
backstack.push(browser:new {
title = tostring(idx),
iterator = idx:iter()
}
end)
iterator = idx:iter(),
})
end)
btn:add_style(theme.list_item)
end
local settings = menu.list:add_btn(nil, "Settings")
settings:onClicked(function()
backstack.push(require("settings").root)
backstack.push(require("settings"):new())
end)
settings:add_style(theme.list_item)
return menu
end
end,
}

@ -4,6 +4,7 @@ local backstack = require("backstack")
local font = require("font")
local playback = require("playback")
local queue = require("queue")
local screen = require("screen")
local img = {
play = "//lua/img/play.png",
@ -18,9 +19,11 @@ local img = {
repeat_disabled = "//lua/img/repeat_disabled.png",
}
return function(opts)
local screen = {}
screen.root = lvgl.Object(nil, {
local is_now_playing_shown = false
return screen:new {
createUi = function(self)
self.root = lvgl.Object(nil, {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
@ -31,14 +34,14 @@ return function(opts)
w = lvgl.HOR_RES(),
h = lvgl.VER_RES(),
})
screen.root:center()
self.root:center()
screen.status_bar = widgets.StatusBar(screen.root, {
self.status_bar = widgets.StatusBar(self.root, {
back_cb = backstack.pop,
transparent_bg = true,
})
local info = screen.root:Object {
local info = self.root:Object {
flex = {
flex_direction = "column",
flex_wrap = "wrap",
@ -66,7 +69,7 @@ return function(opts)
text_align = 2,
}
local playlist = screen.root:Object {
local playlist = self.root:Object {
flex = {
flex_direction = "row",
justify_content = "center",
@ -112,7 +115,7 @@ return function(opts)
}
playlist:Object({ w = 3, h = 1 }) -- spacer
local scrubber = screen.root:Slider {
local scrubber = self.root:Slider {
w = lvgl.PCT(100),
h = 5,
range = { min = 0, max = 100 },
@ -123,7 +126,7 @@ return function(opts)
playback.position:set(scrubber:value())
end)
local controls = screen.root:Object {
local controls = self.root:Object {
flex = {
flex_direction = "row",
justify_content = "center",
@ -173,7 +176,7 @@ return function(opts)
return string.format("%d:%02d", time // 60, time % 60)
end
screen.bindings = {
self.bindings = {
playback.playing:bind(function(playing)
if playing then
play_pause_img:set_src(img.pause)
@ -231,6 +234,12 @@ return function(opts)
playlist_total:set { text = tostring(num) }
end),
}
return screen
end,
onShown = function() is_now_playing_shown = true end,
onHidden = function() is_now_playing_shown = false end,
pushIfNotShown = function(self)
if not is_now_playing_shown then
backstack.push(self:new())
end
end
}

@ -7,8 +7,7 @@ local display = require("display")
local controls = require("controls")
local bluetooth = require("bluetooth")
local database = require("database")
local settings = {}
local screen = require("screen")
local function SettingsScreen(title)
local menu = widgets.MenuScreen {
@ -31,10 +30,11 @@ local function SettingsScreen(title)
return menu
end
function settings.bluetooth()
local menu = SettingsScreen("Bluetooth")
local BluetoothSettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Bluetooth")
local enable_container = menu.content:Object {
local enable_container = self.menu.content:Object {
flex = {
flex_direction = "row",
justify_content = "flex-start",
@ -52,12 +52,12 @@ function settings.bluetooth()
bluetooth.enabled:set(enabled)
end)
menu.content:Label {
self.menu.content:Label {
text = "Paired Device",
pad_bottom = 1,
}:add_style(theme.settings_title)
local paired_container = menu.content:Object {
local paired_container = self.menu.content:Object {
flex = {
flex_direction = "row",
justify_content = "flex-start",
@ -78,17 +78,17 @@ function settings.bluetooth()
bluetooth.paired_device:set()
end)
menu.content:Label {
self.menu.content:Label {
text = "Nearby Devices",
pad_bottom = 1,
}:add_style(theme.settings_title)
local devices = menu.content:List {
local devices = self.menu.content:List {
w = lvgl.PCT(100),
h = lvgl.SIZE_CONTENT,
}
menu.bindings = {
self.bindings = {
bluetooth.enabled:bind(function(en)
if en then
enable_sw:add_state(lvgl.STATE.CHECKED)
@ -115,15 +115,17 @@ function settings.bluetooth()
end)
}
end
}
function settings.headphones()
local menu = SettingsScreen("Headphones")
local HeadphonesSettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Headphones")
menu.content:Label {
self.menu.content:Label {
text = "Maximum volume limit",
}:add_style(theme.settings_title)
local volume_chooser = menu.content:Dropdown {
local volume_chooser = self.menu.content:Dropdown {
options = "Line Level (-10 dB)\nCD Level (+6 dB)\nMaximum (+10dB)",
selected = 1,
}
@ -134,11 +136,11 @@ function settings.headphones()
volume.limit_db:set(limits[selection])
end)
menu.content:Label {
self.menu.content:Label {
text = "Left/Right balance",
}:add_style(theme.settings_title)
local balance = menu.content:Slider {
local balance = self.menu.content:Slider {
w = lvgl.PCT(100),
h = 5,
range = { min = -100, max = 100 },
@ -148,9 +150,9 @@ function settings.headphones()
volume.left_bias:set(balance:value())
end)
local balance_label = menu.content:Label {}
local balance_label = self.menu.content:Label {}
menu.bindings = {
self.bindings = {
volume.limit_db:bind(function(limit)
for i = 1, #limits do
if limits[i] == limit then
@ -175,14 +177,14 @@ function settings.headphones()
end
end),
}
return menu
end
}
function settings.display()
local menu = SettingsScreen("Display")
local DisplaySettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Display")
local brightness_title = menu.content:Object {
local brightness_title = self.menu.content:Object {
flex = {
flex_direction = "row",
justify_content = "flex-start",
@ -196,7 +198,7 @@ function settings.display()
local brightness_pct = brightness_title:Label {}
brightness_pct:add_style(theme.settings_title)
local brightness = menu.content:Slider {
local brightness = self.menu.content:Slider {
w = lvgl.PCT(100),
h = 5,
range = { min = 0, max = 100 },
@ -206,19 +208,19 @@ function settings.display()
display.brightness:set(brightness:value())
end)
menu.bindings = {
self.bindings = {
display.brightness:bind(function(b)
brightness_pct:set { text = tostring(b) .. "%" }
end)
}
return menu
end
}
function settings.input()
local menu = SettingsScreen("Input Method")
local InputSettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Input Method")
menu.content:Label {
self.menu.content:Label {
text = "Control scheme",
}:add_style(theme.settings_title)
@ -239,11 +241,11 @@ function settings.input()
option_idx = option_idx + 1
end
local controls_chooser = menu.content:Dropdown {
local controls_chooser = self.menu.content:Dropdown {
options = options,
}
menu.bindings = {
self.bindings = {
controls.scheme:bind(function(s)
local option = scheme_to_option[s]
controls_chooser:set({ selected = option })
@ -256,12 +258,12 @@ function settings.input()
controls.scheme:set(scheme)
end)
menu.content:Label {
self.menu.content:Label {
text = "Scroll Sensitivity",
}:add_style(theme.settings_title)
local slider_scale = 4; -- Power steering
local sensitivity = menu.content:Slider {
local sensitivity = self.menu.content:Slider {
w = lvgl.PCT(90),
h = 5,
range = { min = 0, max = 255 / slider_scale },
@ -270,17 +272,17 @@ function settings.input()
sensitivity:onevent(lvgl.EVENT.VALUE_CHANGED, function()
controls.scroll_sensitivity:set(sensitivity:value() * slider_scale)
end)
return menu
end
}
function settings.database()
local menu = SettingsScreen("Database")
local DatabaseSettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Database")
local db = require("database")
widgets.Row(menu.content, "Schema version", db.version())
widgets.Row(menu.content, "Size on disk", string.format("%.1f KiB", db.size() / 1024))
widgets.Row(self.menu.content, "Schema version", db.version())
widgets.Row(self.menu.content, "Size on disk", string.format("%.1f KiB", db.size() / 1024))
local actions_container = menu.content:Object {
local actions_container = self.menu.content:Object {
w = lvgl.PCT(100),
h = lvgl.SIZE_CONTENT,
flex = {
@ -300,54 +302,59 @@ function settings.database()
database.update()
end)
end
}
function settings.firmware()
local menu = SettingsScreen("Firmware")
local FirmwareSettings = screen:new {
createUi = function(self)
self.menu = SettingsScreen("Firmware")
local version = require("version")
widgets.Row(menu.content, "ESP32", version.esp())
widgets.Row(menu.content, "SAMD21", version.samd())
widgets.Row(menu.content, "Collator", version.collator())
widgets.Row(self.menu.content, "ESP32", version.esp())
widgets.Row(self.menu.content, "SAMD21", version.samd())
widgets.Row(self.menu.content, "Collator", version.collator())
end
}
function settings.root()
local menu = widgets.MenuScreen {
local LicensesScreen = screen:new {
createUi = function(self)
self.root = require("licenses")()
end
}
return screen:new {
createUi = function(self)
self.menu = widgets.MenuScreen {
show_back = true,
title = "Settings",
}
menu.list = menu.root:List {
self.list = self.menu.root:List {
w = lvgl.PCT(100),
h = lvgl.PCT(100),
flex_grow = 1,
}
local function section(name)
menu.list:add_text(name):add_style(theme.list_heading)
self.list:add_text(name):add_style(theme.list_heading)
end
local function submenu(name, fn)
local item = menu.list:add_btn(nil, name)
local function submenu(name, class)
local item = self.list:add_btn(nil, name)
item:onClicked(function()
backstack.push(fn)
backstack.push(class:new())
end)
item:add_style(theme.list_item)
end
section("Audio")
submenu("Bluetooth", settings.bluetooth)
submenu("Headphones", settings.headphones)
submenu("Bluetooth", BluetoothSettings)
submenu("Headphones", HeadphonesSettings)
section("Interface")
submenu("Display", settings.display)
submenu("Input Method", settings.input)
submenu("Display", DisplaySettings)
submenu("Input Method", InputSettings)
section("System")
submenu("Database", settings.database)
submenu("Firmware", settings.firmware)
submenu("Licenses", function()
return require("licenses")()
end)
return menu
submenu("Database", DatabaseSettings)
submenu("Firmware", FirmwareSettings)
submenu("Licenses", LicensesScreen)
end
return settings
}

@ -5,6 +5,7 @@
idf_component_register(
SRCS "lua_thread.cpp" "bridge.cpp" "property.cpp" "lua_database.cpp"
"lua_queue.cpp" "lua_version.cpp" "lua_controls.cpp" "registry.cpp"
"lua_screen.cpp"
INCLUDE_DIRS "include"
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database"
"esp_timer" "battery" "esp-idf-lua" "luavgl" "lua-linenoise" "lua-term"

@ -19,6 +19,7 @@
#include "lua_controls.hpp"
#include "lua_database.hpp"
#include "lua_queue.hpp"
#include "lua_screen.hpp"
#include "lua_version.hpp"
#include "lvgl.h"
@ -84,6 +85,7 @@ auto Bridge::installBaseModules(lua_State* L) -> void {
RegisterDatabaseModule(L);
RegisterQueueModule(L);
RegisterVersionModule(L);
RegisterScreenModule(L);
}
auto Bridge::installLvgl(lua_State* L) -> void {

@ -0,0 +1,15 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#pragma once
#include "lua.hpp"
namespace lua {
auto RegisterScreenModule(lua_State*) -> void;
} // namespace lua

@ -0,0 +1,75 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "lua_screen.hpp"
#include <memory>
#include <string>
#include "lua.hpp"
#include "esp_log.h"
#include "lauxlib.h"
#include "lua.h"
#include "lvgl.h"
#include "bridge.hpp"
#include "database.hpp"
#include "event_queue.hpp"
#include "index.hpp"
#include "property.hpp"
#include "service_locator.hpp"
#include "track.hpp"
#include "track_queue.hpp"
#include "ui_events.hpp"
namespace lua {
static auto screen_new(lua_State* L) -> int {
// o = o or {}
if (lua_gettop(L) != 2) {
lua_settop(L, 1);
lua_newtable(L);
}
// Swap o and self on the stack.
lua_insert(L, 1);
lua_pushliteral(L, "__index");
lua_pushvalue(L, 1);
lua_settable(L, 1); // self.__index = self
lua_setmetatable(L, 1); // setmetatable(o, self)
return 1; // return o
}
static auto screen_noop(lua_State* state) -> int {
return 0;
}
static const struct luaL_Reg kScreenFuncs[] = {{"new", screen_new},
{"createUi", screen_noop},
{"onShown", screen_noop},
{"onHidden", screen_noop},
{NULL, NULL}};
static auto lua_screen(lua_State* state) -> int {
luaL_newlib(state, kScreenFuncs);
lua_pushliteral(state, "__index");
lua_pushvalue(state, -2);
lua_rawset(state, -3);
return 1;
}
auto RegisterScreenModule(lua_State* s) -> void {
luaL_requiref(s, "screen", lua_screen, true);
lua_pop(s, 1);
}
} // namespace lua

@ -27,6 +27,9 @@ class Screen {
Screen();
virtual ~Screen();
virtual auto onShown() -> void {}
virtual auto onHidden() -> void {}
auto root() -> lv_obj_t* { return root_; }
auto content() -> lv_obj_t* { return content_; }
auto alert() -> lv_obj_t* { return alert_; }

@ -18,6 +18,9 @@ class Lua : public Screen {
Lua();
~Lua();
auto onShown() -> void override;
auto onHidden() -> void override;
auto SetObjRef(lua_State*) -> void;
private:

@ -129,6 +129,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
static lua::Property sControlsScheme;
static lua::Property sScrollSensitivity;
static lua::Property sLockSwitch;
static lua::Property sDatabaseUpdating;
};

@ -7,8 +7,10 @@
#include "screen_lua.hpp"
#include "core/lv_obj_tree.h"
#include "lua.h"
#include "lua.hpp"
#include "lua_thread.hpp"
#include "luavgl.h"
namespace ui {
@ -22,6 +24,40 @@ Lua::~Lua() {
}
}
auto Lua::onShown() -> void {
if (!s_ || !obj_ref_) {
return;
}
lua_rawgeti(s_, LUA_REGISTRYINDEX, *obj_ref_);
lua_pushliteral(s_, "onShown");
if (lua_gettable(s_, -2) == LUA_TFUNCTION) {
lua_pushvalue(s_, -2);
lua::CallProtected(s_, 1, 0);
} else {
lua_pop(s_, 1);
}
lua_pop(s_, 1);
}
auto Lua::onHidden() -> void {
if (!s_ || !obj_ref_) {
return;
}
lua_rawgeti(s_, LUA_REGISTRYINDEX, *obj_ref_);
lua_pushliteral(s_, "onHidden");
if (lua_gettable(s_, -2) == LUA_TFUNCTION) {
lua_pushvalue(s_, -2);
lua::CallProtected(s_, 1, 0);
} else {
lua_pop(s_, 1);
}
lua_pop(s_, 1);
}
auto Lua::SetObjRef(lua_State* s) -> void {
assert(s_ == nullptr);
s_ = s;

@ -125,7 +125,8 @@ lua::Property UiState::sPlaybackPlaying{
}};
lua::Property UiState::sPlaybackTrack{};
lua::Property UiState::sPlaybackPosition{0, [](const lua::LuaValue& val) {
lua::Property UiState::sPlaybackPosition{
0, [](const lua::LuaValue& val) {
int current_val = std::get<int>(sPlaybackPosition.Get());
if (!std::holds_alternative<int>(val)) {
return false;
@ -136,7 +137,9 @@ lua::Property UiState::sPlaybackPosition{0, [](const lua::LuaValue& val) {
if (!std::holds_alternative<audio::Track>(track)) {
return false;
}
events::Audio().Dispatch(audio::SeekFile{.offset = (uint32_t)new_val, .filename = std::get<audio::Track>(track).filepath});
events::Audio().Dispatch(audio::SeekFile{
.offset = (uint32_t)new_val,
.filename = std::get<audio::Track>(track).filepath});
}
return true;
}};
@ -277,6 +280,8 @@ lua::Property UiState::sScrollSensitivity{
return true;
}};
lua::Property UiState::sLockSwitch{false};
lua::Property UiState::sDatabaseUpdating{false};
auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool {
@ -294,27 +299,36 @@ auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool {
}
void UiState::PushScreen(std::shared_ptr<Screen> screen) {
lv_obj_set_parent(sAlertContainer, screen->alert());
if (sCurrentScreen) {
sCurrentScreen->onHidden();
sScreens.push(sCurrentScreen);
}
sCurrentScreen = screen;
lv_obj_set_parent(sAlertContainer, sCurrentScreen->alert());
sCurrentScreen->onShown();
}
int UiState::PopScreen() {
if (sScreens.empty()) {
return 0;
}
sCurrentScreen = sScreens.top();
lv_obj_set_parent(sAlertContainer, sCurrentScreen->alert());
lv_obj_set_parent(sAlertContainer, sScreens.top()->alert());
sCurrentScreen->onHidden();
sCurrentScreen = sScreens.top();
sScreens.pop();
sCurrentScreen->onShown();
return sScreens.size();
}
void UiState::react(const system_fsm::KeyLockChanged& ev) {
sDisplay->SetDisplayOn(!ev.locking);
sInput->lock(ev.locking);
sLockSwitch.Update(ev.locking);
}
void UiState::react(const internal::ControlSchemeChanged&) {
@ -505,6 +519,7 @@ void Lua::entry() {
{
{"scheme", &sControlsScheme},
{"scroll_sensitivity", &sScrollSensitivity},
{"lock_switch", &sLockSwitch},
});
registry.AddPropertyModule(
@ -539,7 +554,7 @@ void Lua::entry() {
auto Lua::PushLuaScreen(lua_State* s) -> int {
// Ensure the arg looks right before continuing.
luaL_checktype(s, 1, LUA_TFUNCTION);
luaL_checktype(s, 1, LUA_TTABLE);
// First, create a new plain old Screen object. We will use its root and
// group for the Lua screen. Allocate it in external ram so that arbitrarily
@ -554,10 +569,15 @@ auto Lua::PushLuaScreen(lua_State* s) -> int {
lv_group_set_default(new_screen->group());
// Call the constructor for this screen.
lua_settop(s, 1); // Make sure the function is actually at top of stack
lua::CallProtected(s, 0, 1);
// lua_settop(s, 1); // Make sure the screen is actually at top of stack
lua_pushliteral(s, "createUi");
if (lua_gettable(s, 1) == LUA_TFUNCTION) {
lua_pushvalue(s, 1);
lua::CallProtected(s, 1, 0);
}
// Store the reference for the table the constructor returned.
// Store the reference for this screen's table.
lua_settop(s, 1);
new_screen->SetObjRef(s);
// Finally, push the now-initialised screen as if it were a regular C++

Loading…
Cancel
Save