summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-06-11 10:13:08 -0400
committerAndrew Opalach <andrew@akon.city> 2025-06-11 10:18:57 -0400
commitdd5f84bee046fdb62f7ae5f31e3a4bd698de5c4b (patch)
treeedd1552ce242b12a2e6fcfd7c2574d61d2212e53
parent6e8fa1f2c625b8326065b8f0a6b67e048ba812b5 (diff)
downloadmauri-dd5f84bee046fdb62f7ae5f31e3a4bd698de5c4b.tar.gz
mauri-dd5f84bee046fdb62f7ae5f31e3a4bd698de5c4b.tar.bz2
mauri-dd5f84bee046fdb62f7ae5f31e3a4bd698de5c4b.zip
Default color(4) to white, TUI improvements
- Add some default uniforms. - Fix depth usage. - Add new shader hack for HLSL compat. - Update deps. Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--flake.lock6
-rw-r--r--src/context.h4
-rw-r--r--src/engine.cc1
-rw-r--r--src/engine.h1
-rw-r--r--src/gl.cc11
-rw-r--r--src/gl.h1
-rw-r--r--src/mauri.cc2
-rw-r--r--src/objects/effect.cc2
-rw-r--r--src/objects/object.cc2
-rw-r--r--src/objects/pass.cc18
-rw-r--r--src/objects/pass.h4
-rw-r--r--src/shader.cc27
-rw-r--r--subprojects/libalabaster.wrap2
-rw-r--r--subprojects/libnaunet.wrap2
-rw-r--r--subprojects/stela.wrap2
-rw-r--r--taro/daemon.c2
-rw-r--r--taro/tests/notcurses_ffmpeg.c2
-rw-r--r--taro/ui.c276
18 files changed, 213 insertions, 152 deletions
diff --git a/flake.lock b/flake.lock
index f2a579f..68074f7 100644
--- a/flake.lock
+++ b/flake.lock
@@ -19,11 +19,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1748693115,
- "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=",
+ "lastModified": 1749285348,
+ "narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc",
+ "rev": "3e3afe5174c561dee0df6f2c2b2236990146329f",
"type": "github"
},
"original": {
diff --git a/src/context.h b/src/context.h
index ab27cb2..dce9d5e 100644
--- a/src/context.h
+++ b/src/context.h
@@ -35,7 +35,8 @@ class Context
this->window->pointer_pos_callback = pointer_pos_callback;
this->window->should_close_callback = should_close_callback;
this->window->userdata = this;
- s32 flags = STELA_WINDOW_VSYNC | (monitor.empty() ? 0 : STELA_WINDOW_WALLPAPER);
+ s32 flags = STELA_WINDOW_VSYNC;
+ if (!monitor.empty()) flags |= STELA_WINDOW_WALLPAPER;
if (!this->window->create_window(this->window, width, height, monitor.c_str(), name.c_str(), flags)) {
return false;
}
@@ -44,7 +45,6 @@ class Context
return false;
}
glEnable(GL_BLEND);
- glEnable(GL_MULTISAMPLE);
return true;
}
diff --git a/src/engine.cc b/src/engine.cc
index 1943357..d4424a7 100644
--- a/src/engine.cc
+++ b/src/engine.cc
@@ -66,6 +66,7 @@ Engine::Engine(Scene *scene, f32 rate, bool audio)
this->default_mat = glm::ortho(-1.f, 1.f, -1.f, 1.f, -3.f, 1.f);
this->default_mat = glm::scale(this->default_mat, vec3{1.f, 1.f, 0.001f});
+ this->default_mat_inverse = glm::inverse(this->default_mat);
this->default_object = new RenderObject(DEFAULT);
this->flipped_object = new RenderObject(DEFAULT_FLIPPED);
diff --git a/src/engine.h b/src/engine.h
index 991c226..4b90dbf 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -53,6 +53,7 @@ class Engine
View view;
mat4x4 default_mat;
+ mat4x4 default_mat_inverse;
RenderObject *default_object;
RenderObject *flipped_object;
diff --git a/src/gl.cc b/src/gl.cc
index 9cf1b2d..2570c61 100644
--- a/src/gl.cc
+++ b/src/gl.cc
@@ -496,7 +496,9 @@ auto RenderFramebuffer::clear(vec4 color) -> void
{
if (!context()->is_draw_enabled()) return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->id);
- glClearBufferfv(GL_COLOR | GL_DEPTH, 0, glm::value_ptr(color));
+ glClearBufferfv(GL_COLOR, 0, glm::value_ptr(color));
+ GLfloat depth = 0.f;
+ glClearBufferfv(GL_DEPTH, 0, &depth);
}
RenderFramebuffer::~RenderFramebuffer()
@@ -518,6 +520,13 @@ auto Render::color_mask(f32 r, f32 g, f32 b, f32 a) -> void
glColorMask(r, g, b, a);
}
+auto Render::depth_test(bool enabled) -> void
+{
+ if (!context()->is_draw_enabled()) return;
+ if (enabled) glEnable(GL_DEPTH_TEST);
+ else glDisable(GL_DEPTH_TEST);
+}
+
auto Render::bind_framebuffer(s32 id) -> void
{
if (!context()->is_draw_enabled()) return;
diff --git a/src/gl.h b/src/gl.h
index 47c5f8a..0c6450b 100644
--- a/src/gl.h
+++ b/src/gl.h
@@ -126,6 +126,7 @@ class Render
public:
static auto blend_func(s32 sfactor, s32 dfactor) -> void;
static auto color_mask(f32 r, f32 g, f32 b, f32 a) -> void;
+ static auto depth_test(bool enabled) -> void;
static auto bind_framebuffer(s32 id) -> void;
static auto set_viewport(s32 x, s32 y, s32 width, s32 height) -> void;
};
diff --git a/src/mauri.cc b/src/mauri.cc
index 6e0bcbf..7cb1476 100644
--- a/src/mauri.cc
+++ b/src/mauri.cc
@@ -138,7 +138,7 @@ auto main(s32 argc, char *argv[]) -> s32
auto wmain(s32 argc, wchar_t **argv) -> s32
#endif
{
- if (!nn_common_init()) return EXIT_FAILURE;
+ if (!nn_common_init(NULL)) return EXIT_FAILURE;
janus::ArgParser args(HELP_TEXT, "0.13");
args.newString("package p", "");
diff --git a/src/objects/effect.cc b/src/objects/effect.cc
index 2a6960f..75b7187 100644
--- a/src/objects/effect.cc
+++ b/src/objects/effect.cc
@@ -1,3 +1,5 @@
+#include "../log.h"
+
#include "effect.h"
#include "pass.h"
diff --git a/src/objects/object.cc b/src/objects/object.cc
index 6240c30..4e710ee 100644
--- a/src/objects/object.cc
+++ b/src/objects/object.cc
@@ -51,7 +51,7 @@ auto Object::parse(Parser &pr, const json &root) -> Object *
warn("non 0 origin[2]");
object->origin[2] = 0.f;
}
- pr.map_value<vec3>(root, "color", &object->color, vec3(0.f));
+ pr.map_value<vec3>(root, "color", &object->color, vec3(1.f));
pr.map_value<f32>(root, "alpha", &object->alpha, 1.f);
pr.map_value<s32>(root, "colorBlendMode", &object->color_blend_mode, 0);
diff --git a/src/objects/pass.cc b/src/objects/pass.cc
index e2dc02d..b07e98f 100644
--- a/src/objects/pass.cc
+++ b/src/objects/pass.cc
@@ -1,6 +1,7 @@
#include "../gl.h"
//#define AL_LOG_ENABLE_TRACE
#include "../log.h"
+#include "../context.h"
#include "pass.h"
@@ -45,6 +46,8 @@ auto Pass::parse(Parser &pr, const json &root, PassStage stage) -> Pass *
if (pass->shader == "genericimage4") {
pass->shader = "genericimage2";
}
+ pass->depthtest = root["depthtest"] != "disabled";
+ pass->depthwrite = root["depthwrite"] != "disabled";
break;
}
@@ -130,6 +133,8 @@ auto Pass::load(Engine *engine, PassStage stage, Pass *pass) -> void
case MATERIAL_ONLY_PASS:
case MATERIAL_PASS:
pass->shader = this->shader;
+ pass->depthtest = this->depthtest;
+ pass->depthwrite = this->depthwrite;
break;
}
}
@@ -163,6 +168,11 @@ RenderPass::RenderPass(Engine *engine, Pass *pass)
this->model = pass->model;
this->combine = pass->combine;
+ this->depth = pass->depthtest;
+ if (pass->depthtest || pass->depthwrite)
+ {
+ warn("depth test support incomplete");
+ }
this->shader = get_shader(pass->shader);
@@ -213,6 +223,10 @@ RenderPass::RenderPass(Engine *engine, Pass *pass)
for (Uniform *uniform : this->shader->uniforms)
{
+ if (uniform->uname == "g_Color4")
+ {
+ uniform->value = &this->object->color4;
+ }
for (UniformOverride *uniform_override : pass->uniforms)
{
if (uniform->name.empty()) continue;
@@ -334,6 +348,8 @@ auto RenderPass::draw(Engine *engine) -> void
if (!this->target) this->object->swap_buffers();
+ if (this->depth) Render::depth_test(true);
+
if (this->combine) Render::blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else Render::blend_func(GL_ONE, GL_ZERO);
@@ -344,6 +360,8 @@ auto RenderPass::draw(Engine *engine) -> void
this->render_object->draw();
+ if (this->depth) Render::depth_test(false);
+
#ifdef FRAME_STEP
adjusted_target->buffer->blit(0, context()->width(), context()->height());
context()->swap_buffers();
diff --git a/src/objects/pass.h b/src/objects/pass.h
index fdec680..6d91a03 100644
--- a/src/objects/pass.h
+++ b/src/objects/pass.h
@@ -50,6 +50,9 @@ class Pass
Object *object;
Effect *effect;
+ bool depthtest;
+ bool depthwrite;
+
std::string shader;
std::array<std::string, MAX_TEXTURES> binds = {};
@@ -77,6 +80,7 @@ class RenderPass
bool model;
bool combine;
+ bool depth;
Shader *shader = nullptr;
diff --git a/src/shader.cc b/src/shader.cc
index 71597da..878f5b2 100644
--- a/src/shader.cc
+++ b/src/shader.cc
@@ -126,10 +126,30 @@ static auto bokeh_blur_hack(std::string_view &line) -> const std::string_view
return line;
}
+static auto hlsl_hack(std::string_view &line) -> const std::string_view
+{
+ // https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math#the-vector-type
+ // HLSL would take the first components in these situations (I think).
+ if (line == " float pointer = g_PointerPosition.xy * u_pointerSpeed;\r\n")
+ {
+ return " float pointer = g_PointerPosition.x * u_pointerSpeed;\r\n";
+ }
+ if (line == "vec3 albedo = texSample2D(g_Texture0, v_TexCoord.xy);\r\n")
+ {
+ return "vec3 albedo = texSample2D(g_Texture0, v_TexCoord.xy).xyz;\r\n";
+ }
+ if (line == "float scale = pow(length(abs(v_TexCoord - CAST2(u_offset)) * 1.0), 3.0) * u_scale;\r\n")
+ {
+ return "float scale = pow(length(abs(v_TexCoord.xy - CAST2(u_offset)) * 1.0), 3.0) * u_scale;\r\n";
+ }
+ return line;
+}
+
static auto apply_hacks(std::string_view line) -> const std::string_view
{
line = simple_audio_bars_hack(line);
line = bokeh_blur_hack(line);
+ line = hlsl_hack(line);
return line;
}
@@ -421,6 +441,10 @@ auto Shader::bind(RenderShader *shader, Engine *engine, Object *object, mat4x4 *
shader->set_uniform("g_ModelViewProjectionMatrix", TYPE_MAT4, glm::value_ptr(*model));
shader->set_uniform("g_ModelViewProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(inverse));
shader->set_uniform("g_EffectModelViewProjectionMatrix", TYPE_MAT4, glm::value_ptr(engine->default_mat));
+ shader->set_uniform("g_EffectModelViewProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(engine->default_mat_inverse));
+ shader->set_uniform("g_EffectTextureProjectionMatrix", TYPE_MAT4, glm::value_ptr(engine->default_mat));
+ shader->set_uniform("g_EffectTextureProjectionMatrixInverse", TYPE_MAT4, glm::value_ptr(engine->default_mat_inverse));
+
shader->set_uniform("g_ModelMatrix", TYPE_MAT4, glm::value_ptr(engine->default_mat));
}
@@ -434,10 +458,11 @@ auto Shader::bind(RenderShader *shader, Engine *engine, Object *object, mat4x4 *
}
cursor_pos[0] /= engine->view.width;
cursor_pos[1] /= engine->view.height;
+ //cursor_pos[1] = -cursor_pos[1];
shader->set_uniform("g_PointerPosition", TYPE_VEC2, glm::value_ptr(cursor_pos));
shader->set_uniform("g_Alpha", TYPE_FLOAT, &object->alpha);
shader->set_uniform("g_Color", TYPE_VEC3, glm::value_ptr(object->color));
- shader->set_uniform("g_Color4", TYPE_VEC4, glm::value_ptr(object->color4));
+ //shader->set_uniform("g_Color4", TYPE_VEC4, glm::value_ptr(object->color4));
}
static const std::array<f32, 64> empty_bars = {};
diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap
index 243dff8..e3aedee 100644
--- a/subprojects/libalabaster.wrap
+++ b/subprojects/libalabaster.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libalabaster
-revision = ec99011aca3a9b92964c653d74d693e693ac052f
+revision = 93f664a69a3c688d196bdc228d572b45a65e7991
depth = 1
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index 3f43502..8388a93 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libnaunet
-revision = 6993b9814769668fb03b4d282734f20f63b16f9c
+revision = 393e266f6bfceb25a97cd1cf28dfc72cac9e9f81
depth = 1
diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap
index 4d0add3..444d851 100644
--- a/subprojects/stela.wrap
+++ b/subprojects/stela.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/stela
-revision = a2e04b98512e9db93d5457ecc52ac385b9a9e0aa
+revision = 658e476c3d43718a2c9eb2884f16ac37cc3f1da2
depth = 1
diff --git a/taro/daemon.c b/taro/daemon.c
index a26de8b..6ceba90 100644
--- a/taro/daemon.c
+++ b/taro/daemon.c
@@ -482,7 +482,7 @@ static void sigint_handler(s32 signum)
s32 main(void)
{
- if (!nn_common_init() || !open_config(&dmon.conf, true)) {
+ if (!nn_common_init(NULL) || !open_config(&dmon.conf, true)) {
return EXIT_FAILURE;
}
diff --git a/taro/tests/notcurses_ffmpeg.c b/taro/tests/notcurses_ffmpeg.c
index adf9689..342d115 100644
--- a/taro/tests/notcurses_ffmpeg.c
+++ b/taro/tests/notcurses_ffmpeg.c
@@ -5,7 +5,7 @@
s32 main(void)
{
- if (!nn_common_init()) return EXIT_FAILURE;
+ if (!nn_common_init(NULL)) return EXIT_FAILURE;
struct notcurses *nc = notcurses_init(NULL, stdin);
diff --git a/taro/ui.c b/taro/ui.c
index d8a2054..1162196 100644
--- a/taro/ui.c
+++ b/taro/ui.c
@@ -15,6 +15,7 @@
#define PIXEL_BLIT 1
#define TIMER_UPDATE_BASE 1.f
+#define TIMER_TICK(delay) MAX(TIMER_UPDATE_BASE * (delay / 1000000.f), 0.001f)
#define TEXT_UPDATE_RATE 0.4f
#define FLASH_DURATION 0.4f
@@ -75,7 +76,6 @@ struct monitors {
array(char *) monitors;
s32 selected_monitor;
s32 set_monitor;
- f32 flash;
str selection_path;
};
@@ -83,12 +83,13 @@ struct grid {
struct ncplane *p;
s32 tiles_x;
s32 tiles_y;
+ u32 tiles_per_page;
+ s32 previous_index;
s32 min_index;
s32 max_index;
s32 selected_index;
s32 set_index;
f32 flash;
- u32 tiles_per_page;
array(struct tile) tiles;
};
@@ -100,12 +101,11 @@ struct info_prop {
struct info {
struct ncplane *ip;
struct entry *e;
- f32 flash;
bool blitted;
struct scrolling_text text;
u32 max_props;
- s32 selected_prop;
array(struct info_prop) props;
+ s32 selected_prop;
};
enum {
@@ -125,6 +125,7 @@ struct ui {
u32 term_rows;
u32 term_cols;
u8 selected_menu;
+ u8 previous_menu;
struct ncplane *p, *mp, *gp, *ip;
struct monitors m;
struct grid g;
@@ -134,9 +135,9 @@ struct ui {
struct config conf;
};
-// ---------
+// -------
// Client
-// ---------
+// -------
static s32 get_entry_from_config(struct ui *u)
{
@@ -183,11 +184,7 @@ static void write_selected_entry_to_config(struct ui *u)
al_str_from(&config, "||");
} else {
al_str_clone(&config, &u->n.e->id);
- if (u->n.e->has_package) {
- al_str_cat(&config, &al_str_c("_p"));
- } else {
- al_str_cat(&config, &al_str_c("_d"));
- }
+ al_str_cat(&config, u->n.e->has_package ? &al_str_c("_p") : &al_str_c("_d"));
al_str_cat(&config, &al_str_c("|false,100|"));
struct prop *p;
al_array_foreach_ptr(u->n.e->props, i, p) {
@@ -200,16 +197,14 @@ static void write_selected_entry_to_config(struct ui *u)
}
al_str_cat(&config, &al_str_c(","));
}
- if (al_str_at(&config, config.length - 1) == ',') {
- config.length--;
- }
+ if (al_str_atr(&config, 1) == ',') config.length--;
}
nn_file_open_and_replace(&u->m.selection_path, &config, true);
}
-// ---------
-// Interface
-// ---------
+// ---------------
+// User Interface
+// ---------------
static bool init_info(struct info *n)
{
@@ -305,14 +300,14 @@ static bool init_ui(struct ui *u)
struct image *get_image_from_pool(struct image_pool *pool, str *path)
{
u32 hash = al_str_hash(path);
- struct image *rimg;
- al_array_foreach_ptr(pool->images, i, rimg) {
- if (rimg->hash == hash) {
- return rimg;
- }
+
+ struct image *cached;
+ al_array_foreach_ptr(pool->images, i, cached) {
+ if (cached->hash == hash) return cached;
}
if (pool->images.count >= pool->max) {
+ // This should at least be based on LRU.
for (u32 i = 0; i < pool->chunk_size; i++) {
ncvisual_destroy(al_array_at(pool->images, i).v);
}
@@ -320,19 +315,13 @@ struct image *get_image_from_pool(struct image_pool *pool, str *path)
}
u32 index = al_str_rfind(path, '.');
- bool gif = index != AL_STR_NPOS && al_str_cmp(path, &al_str_c(".gif"), index, 4) == 0;
-
+ bool is_gif = index != AL_STR_NPOS && al_str_cmp(path, &al_str_c(".gif"), index, 4) == 0;
char *c_str = al_str_to_c_str(path);
- struct image img = {
- .hash = hash,
- .gif = gif,
- .errored = false,
- .v = ncvisual_from_file(c_str)
- };
+ struct ncvisual *v = ncvisual_from_file(c_str);
al_free(c_str);
- if (!img.v) return NULL;
- al_array_push(pool->images, img);
+ if (!v) return NULL;
+ al_array_push(pool->images, ((struct image){ hash, is_gif, false, v }));
return &al_array_last(pool->images);
}
@@ -358,8 +347,7 @@ static s32 resize_cb(struct ncplane *p)
}
u->n.blitted = false;
ncplane_erase(u->n.ip);
- // To not break images we need to erase them
- // then render them in 2 steps.
+ // To not break images we need to erase then render them in 2 steps.
notcurses_refresh(u->nc, NULL, NULL);
notcurses_render(u->nc);
draw_monitors(u, &u->m);
@@ -421,14 +409,15 @@ static void maybe_destroy_info(struct info *n)
static void set_info_entry(struct ui *u, struct info *n)
{
- n->e = &al_array_at(u->db.entries, u->g.selected_index);
+ struct entry *e = &al_array_at(u->db.entries, u->g.selected_index);
+ if (e == n->e) return;
+ n->e = e;
n->blitted = false;
s32 width = al_wstr_width(&u->n.e->title);
s32 tx = 2 + ((width < INFO_TEXT_WIDTH) ? (INFO_TEXT_WIDTH - width) / 2 : 0);
set_scrolling_text(&n->text, &u->n.e->title, INFO_IMG_HEIGHT + 1, tx, INFO_TEXT_WIDTH);
- n->selected_prop = 0;
n->props.count = 0;
struct prop *p;
struct info_prop *ip;
@@ -439,6 +428,7 @@ static void set_info_entry(struct ui *u, struct info *n)
s32 ty = INFO_IMG_HEIGHT + 3 + ((i % n->max_props) * 2);
set_scrolling_text(&ip->text, &p->title, ty, 0, PROP_TEXT_WIDTH);
}
+ n->selected_prop = 0;
}
static bool layout_info(struct ui *u, struct info *n, struct ncplane *parent, s32 height)
@@ -449,14 +439,11 @@ static bool layout_info(struct ui *u, struct info *n, struct ncplane *parent, s3
if (!n->max_props) return false;
struct ncplane_options nopts = { 0 };
-
nopts.cols = INFO_IMG_WIDTH;
nopts.rows = INFO_IMG_HEIGHT;
nopts.x = 0;
nopts.y = 1;
-
- n->ip = ncplane_create(parent, &nopts);
- if (!n->ip) {
+ if (!(n->ip = ncplane_create(parent, &nopts))) {
maybe_destroy_info(n);
return false;
}
@@ -486,7 +473,11 @@ static void maybe_destroy_grid(struct grid *g)
static void set_grid_tiles(struct ui *u, struct grid *g)
{
u32 selected = (g->selected_index >= 0) ? g->selected_index : g->set_index;
- u32 index = (selected - (selected % g->tiles_per_page));
+ u32 index = selected - (selected % g->tiles_per_page);
+ if (g->previous_index >= 0 && index == (u32)g->previous_index) {
+ return;
+ }
+ g->previous_index = index;
g->min_index = index;
g->max_index = index;
@@ -552,19 +543,16 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3
{
maybe_destroy_grid(g);
- s32 inner_width = width;
- s32 inner_height = height;
-
g->tiles_x = width / GRID_TILE_WIDTH;
g->tiles_y = height / GRID_TILE_HEIGHT;
-
if (!g->tiles_x || !g->tiles_y) {
// Window is too small.
return false;
}
-
g->tiles_per_page = g->tiles_x * g->tiles_y;
+ g->previous_index = -1;
+
// Reserve space for 4 pages, but never shrink.
if (u->pool.chunk_size < g->tiles_per_page) {
u->pool.chunk_size = g->tiles_per_page;
@@ -572,35 +560,28 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3
al_array_reserve(u->pool.images, u->pool.max);
}
- while (inner_width && inner_width % g->tiles_x != 0) {
- inner_width--;
- }
-
- while (inner_height && inner_height % g->tiles_y != 0) {
- inner_height--;
- }
+ s32 inner_width = width;
+ s32 inner_height = height;
+ while (inner_width && inner_width % g->tiles_x != 0) inner_width--;
+ while (inner_height && inner_height % g->tiles_y != 0) inner_height--;
struct ncplane_options nopts = { 0 };
-
nopts.cols = inner_width;
nopts.rows = inner_height;
nopts.x = (width - (g->tiles_x * GRID_TILE_WIDTH)) / 2;
nopts.y = (height - (g->tiles_y * GRID_TILE_HEIGHT)) / 2;
+ if (!(g->p = ncplane_create(parent, &nopts))) {
+ return false;
+ }
- g->p = ncplane_create(parent, &nopts);
- if (!g->p) return false;
-
+ struct tile t = { 0 };
for (s32 y = 0; y < g->tiles_y; y++) {
for (s32 x = 0; x < g->tiles_x; x++) {
- struct tile t = { 0 };
-
nopts.cols = GRID_TILE_WIDTH;
nopts.rows = GRID_TILE_HEIGHT;
nopts.x = x * GRID_TILE_WIDTH;
nopts.y = y * GRID_TILE_HEIGHT;
-
- t.p = ncplane_create(g->p, &nopts);
- if (!t.p) {
+ if (!(t.p = ncplane_create(g->p, &nopts))) {
maybe_destroy_grid(g);
return false;
}
@@ -609,9 +590,7 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3
nopts.rows = GRID_TILE_HEIGHT - 2;
nopts.x = 1;
nopts.y = 1;
-
- t.ip = ncplane_create(t.p, &nopts);
- if (!t.ip) {
+ if (!(t.ip = ncplane_create(t.p, &nopts))) {
maybe_destroy_grid(g);
return false;
}
@@ -655,7 +634,6 @@ bool layout_ui(struct ui *u)
u32 rwidth = even ? UI_RESERVE_WIDTH + 1 : UI_RESERVE_WIDTH;
u32 rheight = even ? UI_RESERVE_HEIGHT + 1 : UI_RESERVE_HEIGHT;
-
if (u->term_cols < GRID_TILE_WIDTH + rwidth || u->term_rows < GRID_TILE_HEIGHT + rheight) {
return false;
}
@@ -663,18 +641,14 @@ bool layout_ui(struct ui *u)
maybe_destroy_ui(u);
struct ncplane_options nopts = { 0 };
-
nopts.rows = u->term_rows;
nopts.cols = u->term_cols;
-
- u->p = ncplane_create(notcurses_stdplane(u->nc), &nopts);
- if (!u->p) {
+ if (!(u->p = ncplane_create(notcurses_stdplane(u->nc), &nopts))) {
return false;
}
s32 cols = (s32)u->term_cols - rwidth;
s32 rows = (s32)u->term_rows - rheight;
-
if (cols < 0 || rows < 0) {
maybe_destroy_ui(u);
return false;
@@ -684,9 +658,7 @@ bool layout_ui(struct ui *u)
nopts.y = 1;
nopts.cols = cols - 1;
nopts.rows = 1;
-
- u->mp = ncplane_create(u->p, &nopts);
- if (!u->mp) {
+ if (!(u->mp = ncplane_create(u->p, &nopts))) {
maybe_destroy_ui(u);
return false;
}
@@ -695,9 +667,7 @@ bool layout_ui(struct ui *u)
nopts.y = 2;
nopts.cols = cols - 1;
nopts.rows = rows - 2;
-
- u->gp = ncplane_create(u->p, &nopts);
- if (!u->gp) {
+ if (!(u->gp = ncplane_create(u->p, &nopts))) {
maybe_destroy_ui(u);
return false;
}
@@ -711,9 +681,7 @@ bool layout_ui(struct ui *u)
nopts.y = INFO_Y_OFFSET;
nopts.cols = INFO_WIDTH;
nopts.rows = u->term_rows - rheight;
-
- u->ip = ncplane_create(u->p, &nopts);
- if (!u->ip) {
+ if (!(u->ip = ncplane_create(u->p, &nopts))) {
maybe_destroy_ui(u);
return false;
}
@@ -743,8 +711,7 @@ void draw_monitors(struct ui *u, struct monitors *m)
}
ncplane_set_styles(u->mp, NCSTYLE_BOLD);
- s32 w = ncplane_dim_x(u->mp);
- s32 x = ((w - 1) - width) / 2;
+ s32 x = ((ncplane_dim_x(u->mp) - 1) - width) / 2;
ncplane_cursor_move_yx(u->mp, 0, x);
if (u->m.selected_monitor == -1) {
@@ -758,13 +725,12 @@ void draw_monitors(struct ui *u, struct monitors *m)
ncplane_putstr(u->mp, no_monitors);
} else {
al_array_foreach(m->monitors, i, monitor) {
- if (m->flash <= 0.f && u->selected_menu == MENU_MONITORS && i == (u32)m->selected_monitor) {
+ if (u->selected_menu == MENU_MONITORS && i == (u32)m->selected_monitor) {
ncplane_set_bg_palindex(u->mp, 8);
ncplane_set_fg_palindex(u->mp, 0);
} else if (i == (u32)m->set_monitor) {
ncplane_set_bg_palindex(u->mp, 7);
ncplane_set_fg_palindex(u->mp, 0);
- m->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f);
} else {
ncplane_set_fg_default(u->mp);
ncplane_set_bg_default(u->mp);
@@ -781,7 +747,6 @@ void draw_info(struct ui *u, struct info *n, bool update_text)
ncplane_erase(u->ip);
-
struct ncvisual_options vopts = { 0 };
vopts.scaling = PIXEL_BLIT ? NCSCALE_SCALE_HIRES : NCSCALE_STRETCH;
vopts.blitter = PIXEL_BLIT ? NCBLIT_PIXEL : NCBLIT_2x1;
@@ -806,9 +771,8 @@ void draw_info(struct ui *u, struct info *n, bool update_text)
ncplane_set_fg_default(u->ip);
draw_scrolling_text(u->ip, &n->text, update_text);
- u32 selected_index = n->selected_prop - (n->selected_prop % n->max_props);
+ u32 i, index, selected_index = n->selected_prop - (n->selected_prop % n->max_props);
struct info_prop *ip = NULL;
- u32 i, index;
for (i = 0; i < n->max_props; i++) {
index = i + selected_index;
if (index >= n->props.count) {
@@ -816,24 +780,17 @@ void draw_info(struct ui *u, struct info *n, bool update_text)
}
ip = &al_array_at(n->props, index);
if (u->selected_menu == MENU_INFO && index == (u32)n->selected_prop) {
- if (n->flash > 0.f) {
- ncplane_set_fg_palindex(u->ip, 0);
- ncplane_set_bg_palindex(u->ip, 7);
- n->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f);
- } else {
- ncplane_set_fg_palindex(u->ip, 8);
- ncplane_set_bg_default(u->ip);
- }
+ ncplane_set_fg_palindex(u->ip, 8);
} else {
ncplane_set_fg_default(u->ip);
- ncplane_set_bg_default(u->ip);
}
draw_scrolling_text(u->ip, &ip->text, update_text);
switch (ip->p->type) {
- case PROP_TYPE_BOOL:
- ncplane_putstr_yx(u->ip, ip->text.y, ip->text.width + 2,
- *((bool *)ip->p->value) ? "[x]" : "[ ]");
+ case PROP_TYPE_BOOL: {
+ char *c = *((bool *)ip->p->value) ? "[x]" : "[ ]";
+ ncplane_putstr_yx(u->ip, ip->text.y, ip->text.width + 2, c);
break;
+ }
case PROP_TYPE_SLIDER: {
char c[16];
al_snprintf(c, sizeof(c), "%.2f", ((struct slider_value *)ip->p->value)->value);
@@ -847,21 +804,27 @@ void draw_info(struct ui *u, struct info *n, bool update_text)
}
}
-static void set_tile_highlight(struct tile *t, s32 bindex, s32 findex)
+static void set_tile_highlight(struct tile *t, s32 findex, s32 bindex)
{
- ncplane_set_bg_alpha(t->p, NCALPHA_TRANSPARENT);
struct nccell ncl;
nccell_init(&ncl);
nccell_load(t->p, &ncl, " ");
nccell_set_bg_palindex(&ncl, bindex);
+ nccell_set_fg_default(&ncl);
ncplane_polyfill_yx(t->p, 1, 0, &ncl);
+ nccell_release(t->p, &ncl);
+ ncplane_set_bg_default(t->p);
ncplane_set_fg_palindex(t->p, bindex);
for (s32 i = 0; i < GRID_TILE_WIDTH; i++) {
ncplane_putwc_yx(t->p, 0, i, L'▃');
}
- ncplane_set_fg_palindex(t->p, findex);
+ (void)findex;
+ //ncplane_set_fg_palindex(t->p, findex);
+ // If we set both fg and bg palindex here, the fg color
+ // will carry over to the info prop list for a split second.
+ // This might be a notcurses bug, I need to look more carefully.
+ ncplane_set_fg_rgb8(t->p, 0, 0, 0);
ncplane_set_bg_palindex(t->p, bindex);
- ncplane_set_bg_alpha(t->p, NCALPHA_OPAQUE);
ncplane_set_styles(t->p, NCSTYLE_BOLD);
}
@@ -873,12 +836,9 @@ void draw_grid_tiles(struct ui *u, struct grid *g, bool update_text)
vopts.scaling = PIXEL_BLIT ? NCSCALE_SCALE_HIRES : NCSCALE_STRETCH;
vopts.blitter = PIXEL_BLIT ? NCBLIT_PIXEL : NCBLIT_2x1;
- s32 index = (g->selected_index - (g->selected_index % g->tiles_per_page));
struct tile *t;
al_array_foreach_ptr(g->tiles, i, t) {
- ncplane_erase(t->p);
- if (!t->e) continue;
- if (t->e->has_preview) {
+ if (t->e && t->e->has_preview) {
struct image *img = get_image_from_pool(&u->pool, &t->e->preview_path);
if (img && !t->blitted && !img->errored) {
vopts.n = t->ip;
@@ -886,15 +846,19 @@ void draw_grid_tiles(struct ui *u, struct grid *g, bool update_text)
t->blitted = true;
}
}
+ }
+ s32 index = g->selected_index - (g->selected_index % g->tiles_per_page);
+ al_array_foreach_ptr(g->tiles, i, t) {
+ ncplane_erase(t->p);
+ if (!t->e) continue;
if (index == g->selected_index && g->flash <= 0.f && u->selected_menu == MENU_GRID) {
- set_tile_highlight(t, 8, 0);
+ set_tile_highlight(t, 0, 8);
} else if (index == g->set_index && g->set_index >= 0) {
- set_tile_highlight(t, 7, 0);
- g->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f);
+ set_tile_highlight(t, 0, 7);
+ g->flash -= TIMER_TICK(u->delay);
} else {
ncplane_set_fg_default(t->p);
ncplane_set_bg_default(t->p);
- ncplane_set_bg_alpha(t->p, NCALPHA_TRANSPARENT);
ncplane_set_styles(t->p, NCSTYLE_NONE);
}
if (t->text.s && !al_wstr_is_empty(t->text.s)) {
@@ -928,10 +892,17 @@ static bool handle_input_monitors(struct ui *u, struct monitors *m, struct ncinp
should_redraw_monitors = true;
break;
}
+ case NCKEY_DOWN:
+ case 'j': {
+ u->selected_menu = MENU_GRID;
+ should_redraw_monitors = true;
+ should_redraw_grid = true;
+ break;
+ }
case NCKEY_RETURN:
case NCKEY_SPACE: {
select_monitor(u);
- m->flash = FLASH_DURATION;
+ u->selected_menu = MENU_GRID;
should_redraw_monitors = true;
should_redraw_grid = true;
should_redraw_info = true;
@@ -1055,6 +1026,7 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu
bool should_update_grid = false;
bool should_redraw_grid = false;
bool should_redraw_info = false;
+ bool should_redraw_monitors = false;
switch (input->id) {
case NCKEY_LEFT:
case 'h': {
@@ -1087,10 +1059,12 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu
case NCKEY_UP:
case 'k': {
if (g->selected_index - g->tiles_x < g->min_index) {
- return false;
+ u->selected_menu = MENU_MONITORS;
+ should_redraw_monitors = true;
+ } else {
+ g->selected_index -= g->tiles_x;
+ should_redraw_info = true;
}
- g->selected_index -= g->tiles_x;
- should_redraw_info = true;
should_redraw_grid = true;
break;
}
@@ -1104,6 +1078,18 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu
should_redraw_grid = true;
break;
}
+ case '0': {
+ g->selected_index -= g->selected_index % g->tiles_x;
+ should_redraw_info = true;
+ should_redraw_grid = true;
+ break;
+ }
+ case '4': { // '$' in vim.
+ g->selected_index += g->tiles_x - (g->selected_index % g->tiles_x) - 1;
+ should_redraw_info = true;
+ should_redraw_grid = true;
+ break;
+ }
case 'f': {
if (grid_next_page(u, &u->g, 0)) {
should_update_grid = true;
@@ -1160,6 +1146,9 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu
set_info_entry(u, &u->n);
draw_info(u, &u->n, false);
}
+ if (should_redraw_monitors) {
+ draw_monitors(u, &u->m);
+ }
return should_redraw_grid || should_redraw_info;
}
@@ -1172,44 +1161,55 @@ static void input_poll_callback(void *userdata, s32 revents)
u32 ret;
while (1) {
ret = notcurses_get_nblock(u->nc, &input);
- if (ret == (u32)-1 || ret == 0) {
- break;
- }
+ if (ret == (u32)-1 || ret == 0) break;
if (input.evtype == NCTYPE_PRESS || input.evtype == NCTYPE_UNKNOWN) {
if (input.id == NCKEY_TAB) {
switch (u->selected_menu) {
+ case MENU_MONITORS:
+ break;
case MENU_GRID:
if (u->n.props.count > 0) {
u->selected_menu = MENU_INFO;
- u->n.flash = FLASH_DURATION;
- } else {
- u->selected_menu = MENU_MONITORS;
}
break;
case MENU_INFO:
- u->selected_menu = MENU_MONITORS;
- break;
- case MENU_MONITORS:
u->selected_menu = MENU_GRID;
break;
}
draw_info(u, &u->n, false);
- draw_monitors(u, &u->m);
draw_grid_tiles(u, &u->g, false);
should_render = true;
+ } else if (input.id == 'm') {
+ if (u->selected_menu != MENU_MONITORS) {
+ u->previous_menu = u->selected_menu;
+ u->selected_menu = MENU_MONITORS;
+ } else {
+ u->selected_menu = u->previous_menu;
+ }
+ draw_monitors(u, &u->m);
+ switch (u->previous_menu) {
+ case MENU_GRID:
+ draw_grid_tiles(u, &u->g, false);
+ break;
+ case MENU_INFO:
+ draw_info(u, &u->n, false);
+ break;
+ }
+ should_render = true;
} else if (input.id == 'q') {
nn_event_loop_break(&u->loop);
- }
- switch (u->selected_menu) {
- case MENU_GRID:
- should_render |= handle_input_grid(u, &u->g, &input);
- break;
- case MENU_INFO:
- should_render |= handle_input_info(u, &u->n, &input);
- break;
- case MENU_MONITORS:
- should_render |= handle_input_monitors(u, &u->m, &input);
- break;
+ } else {
+ switch (u->selected_menu) {
+ case MENU_GRID:
+ should_render |= handle_input_grid(u, &u->g, &input);
+ break;
+ case MENU_INFO:
+ should_render |= handle_input_info(u, &u->n, &input);
+ break;
+ case MENU_MONITORS:
+ should_render |= handle_input_monitors(u, &u->m, &input);
+ break;
+ }
}
}
}
@@ -1231,7 +1231,7 @@ static void timer_callback(void *userdata, struct nn_timer *timer)
draw_grid_tiles(u, &u->g, true);
draw_info(u, &u->n, true);
} else {
- u->text_update -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f);
+ u->text_update -= TIMER_TICK(u->delay);
draw_grid_tiles(u, &u->g, false);
draw_info(u, &u->n, false);
}
@@ -1248,7 +1248,7 @@ static struct ui u = { 0 };
s32 main(void)
{
- if (!nn_common_init()) return EXIT_FAILURE;
+ if (!nn_common_init(NULL)) return EXIT_FAILURE;
if (!open_config(&u.conf, false)) {
log_error("failed to open config, run `tarod` at least once to generate needed config");