aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2025-10-26 20:59:05 -0400
committerJack Jamison <jackqjamison@gmail.com>2025-10-26 21:04:55 -0400
commit77c11183c22d640939cd8a6a7588329a5879c64c (patch)
tree88d79731cb0563e1986280fa282618de1e121b23
parent7557fb423436f21e485e27ffd7f10e2c15232135 (diff)
refactor to layout
-rw-r--r--config.h2
-rw-r--r--graphics.c101
-rw-r--r--input_field.c15
-rw-r--r--input_field.h1
-rw-r--r--keybind.c2
-rw-r--r--layout.c96
-rw-r--r--layout.h5
-rw-r--r--state.h6
8 files changed, 129 insertions, 99 deletions
diff --git a/config.h b/config.h
index 8deca15..27cac24 100644
--- a/config.h
+++ b/config.h
@@ -8,7 +8,7 @@ typedef struct {
float r,g,b,a;
} color_t;
-static const bool fancy_scroll = false;
+static const bool fancy_scroll = true;
static const uint32_t min_width = 500;
static const uint32_t font_size = 16;
static const color_t text_color = {0.85, 0.85, 0.85, 1.0};
diff --git a/graphics.c b/graphics.c
index 638c6a7..9f66702 100644
--- a/graphics.c
+++ b/graphics.c
@@ -177,30 +177,27 @@ void render_frame(client_state *state) {
glClearColor(background_color.r,background_color.g,background_color.b,background_color.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // bind shader and texture
- glUseProgram(state->text_shader);
- glUniform2f(state->t_screen_size_uniform, state->width, state->height);
- glUniform4f(state->t_color_uniform, text_color.r,text_color.g,text_color.b,text_color.a);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, state->atlas.texture);
-
// calculate input buffer size
- Rect input = { .x = 0, .y = state->line_height * state->lines, .dx = state->width, .dy = state->line_height };
- if (state->lines == 0 && array_size(state->filtered_items) != 0) {
- input.dx = state->width / 3.0f;
- }
+ rect_t input, options;
+ calculate_layout(state, &input, &options, false);
// draw input buffer
+ glUseProgram(state->text_shader);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, state->atlas.texture);
glScissor(input.x, input.y, input.dx - state->horizontal_spacing / 2.0f, input.dy);
glBindVertexArray(state->input_buffer_grafix.vao);
+ glUniform2f(state->t_screen_size_uniform, state->width, state->height);
+ glUniform4f(state->t_color_uniform, text_color.r,text_color.g,text_color.b,text_color.a);
glUniform2f(state->t_offset_uniform, input.x + state->horizontal_spacing / 2.0f, input.y - state->atlas.vert_shift);
glDrawElements(GL_TRIANGLES, state->input_buffer_grafix.num_elements, GL_UNSIGNED_INT, 0);
- // draw cursor box
+ // calculate cursor size
float cursor_size = state->atlas.metrics['M'].bitmap_width;
if (state->cursor_index != array_size(state->input_buffer)) {
cursor_size = state->atlas.metrics[(int)state->input_buffer[state->cursor_index]].advance_x;
}
+ // draw cursor
glUseProgram(state->box_shader);
glUniform4f(state->b_color_uniform, cursor_color.r,cursor_color.g,cursor_color.b,cursor_color.a);
glUniform2f(state->b_screen_size_uniform, state->width, state->height);
@@ -208,80 +205,18 @@ void render_frame(client_state *state) {
glUniform2f(state->b_size_uniform, cursor_size, input.dy);
glDrawArrays(GL_TRIANGLES, 0, 6);
- Rect options = {0};
- float start;
- // set up starting pen and scissor for options
- if (state->lines) {
- options.dx = state->width;
- options.dy = input.y;
-
- start = input.y - state->line_height + state->scroll;
-
- if (array_size(state->filtered_items) != 0) {
- // calc scroll
- float selected_bot = start - state->filtered_items[state->selected_filtered_item].offset;
- float selected_top = selected_bot + state->line_height;
- if (selected_bot < 0) {
- state->scroll -= selected_bot;
- start -= selected_bot;
- }
- float diff = selected_top - input.y;
- if (diff > 0) {
- state->scroll -= diff;
- start -= diff;
- }
- }
- } else {
- options.x = input.x + input.dx;
- options.dx = state->width - options.x;
- options.dy = state->line_height;
-
- start = input.dx + state->scroll;
-
- if (array_size(state->filtered_items) != 0) {
- // calc scroll
- item_display_t* selected = &state->filtered_items[state->selected_filtered_item];
- float selected_len = selected->item->pixel_len + state->horizontal_spacing;
- float selected_left = start + selected->offset;
- float selected_right = selected_left + selected_len;
- float right_diff = selected_right - state->width;
- float left_diff = selected_left - input.dx;
- if (selected_len > state->width - input.dx) {
- state->scroll -= left_diff;
- start -= left_diff;
- }
- else if (right_diff > 0) {
- state->scroll -= right_diff;
- start -= right_diff;
- }
- else if (left_diff < 0) {
- state->scroll -= left_diff;
- start -= left_diff;
- }
- }
- }
+ // scissor options
glScissor(options.x, options.y, options.dx, options.dy);
// draw highlighted option box
if (state->selected_filtered_item != -1) {
item_display_t* display = &state->filtered_items[state->selected_filtered_item];
- item_t* item = display->item;
-
- float x,y;
- if (state->lines) {
- x = 0;
- y = start - display->offset;
- }
- else {
- x = start + display->offset;
- y = 0;
- }
glUseProgram(state->box_shader);
glUniform4f(state->b_color_uniform, highlight_color.r,highlight_color.g,highlight_color.b,highlight_color.a);
glUniform2f(state->b_screen_size_uniform, state->width, state->height);
- glUniform2f(state->b_start_uniform, x, y);
- glUniform2f(state->b_size_uniform, (state->lines) ? state->width : item->pixel_len + state->horizontal_spacing, state->line_height);
+ glUniform2f(state->b_start_uniform, display->r.x, display->r.y);
+ glUniform2f(state->b_size_uniform, display->r.dx, display->r.dy);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
@@ -295,18 +230,8 @@ void render_frame(client_state *state) {
item_display_t* display = &state->filtered_items[i];
item_t* item = display->item;
- float x,y;
- if (state->lines) {
- x = 0;
- y = start - display->offset;
- }
- else {
- x = start + display->offset;
- y = 0;
- }
-
glBindVertexArray(item->text_buffer.vao);
- glUniform2f(state->t_offset_uniform, x + state->horizontal_spacing / 2.0f, y - state->atlas.vert_shift);
+ glUniform2f(state->t_offset_uniform, display->r.x + state->horizontal_spacing / 2.0f, display->r.y - state->atlas.vert_shift);
glDrawElements(GL_TRIANGLES, item->text_buffer.num_elements, GL_UNSIGNED_INT, 0);
}
diff --git a/input_field.c b/input_field.c
index 69ddf62..dc62503 100644
--- a/input_field.c
+++ b/input_field.c
@@ -3,11 +3,17 @@
#include "input_field.h"
#include "array.h"
#include "graphics.h"
+#include "layout.h"
int compare(const void *a, const void *b) {
return strlen(((item_display_t*)a)->item->text) > strlen(((item_display_t*)b)->item->text);
}
+void update_layout(client_state* state) {
+ rect_t input, options;
+ calculate_layout(state, &input, &options, true);
+}
+
void filter_items(client_state* state) {
if (!state->items) return;
@@ -30,13 +36,8 @@ void filter_items(client_state* state) {
if (array_size(state->filtered_items) > 0) state->selected_filtered_item = 0;
else state->selected_filtered_item = -1;
- // lay out items
- float offset = 0;
- array_for_all(item_display_t, display, state->filtered_items) {
- display->offset = offset;
- if (state->lines) offset += state->line_height;
- else offset += display->item->pixel_len + state->horizontal_spacing;
- }
+ // update layout
+ update_layout(state);
}
void update_text_buffer(client_state* state) {
diff --git a/input_field.h b/input_field.h
index 6ec588e..b338b1f 100644
--- a/input_field.h
+++ b/input_field.h
@@ -8,5 +8,6 @@
key_repeat_t type_key(client_state* state, xkb_keysym_t keysym);
void filter_items(client_state* state);
void update_text_buffer(client_state* state);
+void update_layout(client_state* state);
#endif
diff --git a/keybind.c b/keybind.c
index 986ec4c..a24e00c 100644
--- a/keybind.c
+++ b/keybind.c
@@ -40,6 +40,7 @@ key_repeat_t insert_selected(client_state* state) {
key_repeat_t select_next(client_state* state) {
if (state->selected_filtered_item != -1) {
state->selected_filtered_item = MIN(state->selected_filtered_item + 1, (int)array_size(state->filtered_items) - 1);
+ update_layout(state);
}
return KEY_REPEAT;
}
@@ -47,6 +48,7 @@ key_repeat_t select_next(client_state* state) {
key_repeat_t select_previous(client_state* state) {
if (state->selected_filtered_item != -1) {
state->selected_filtered_item = MAX(state->selected_filtered_item - 1, 0);
+ update_layout(state);
}
return KEY_REPEAT;
}
diff --git a/layout.c b/layout.c
index fb3ff4c..981210c 100644
--- a/layout.c
+++ b/layout.c
@@ -1,2 +1,98 @@
#include "layout.h"
+#include "array.h"
+#include "config.h"
+void init_layout(client_state* state) {
+
+}
+
+void calculate_layout(client_state* state, rect_t* input, rect_t* options, bool recalc_options) {
+
+ // calculate input rect
+ *input = (rect_t){ .x = 0, .y = state->line_height * state->lines, .dx = state->width, .dy = state->line_height };
+ if (state->lines == 0 && array_size(state->filtered_items) != 0) {
+ input->dx = state->width / 3.0f;
+ }
+
+ // calculate options rect
+ *options = (rect_t){0};
+ if (state->lines) {
+ options->dx = state->width;
+ options->dy = input->y;
+ } else {
+ options->x = input->x + input->dx;
+ options->dx = state->width - options->x;
+ options->dy = state->line_height;
+ }
+
+ if (recalc_options) {
+
+ // calculate starting conditions
+ rect_t cur;
+ if (state->lines) {
+ cur = (rect_t){ .x = options->x, .y = input->y - state->line_height, .dx = options->dx, .dy = state->line_height };
+ } else {
+ cur = (rect_t){ .x = options->x, .y = options->y, .dx = 0.0f, .dy = state->line_height };
+ }
+
+ // calculate base filtered item rects
+ array_for_all(item_display_t, display, state->filtered_items) {
+ if (!state->lines) {
+ cur.dx = display->item->pixel_len + state->horizontal_spacing;
+ }
+
+ display->r = cur;
+
+ if (state->lines) {
+ cur.y -= state->line_height;
+ } else {
+ cur.x += cur.dx;
+ }
+ }
+
+ // calculate fancy scroll
+ if (fancy_scroll && array_size(state->filtered_items) != 0) {
+
+ // calculate if we should adjust scrolling
+ if (state->lines) {
+ // calc vertical scroll
+ float selected_bot = state->fancy_scroll + state->filtered_items[state->selected_filtered_item].r.y;
+ float selected_top = selected_bot + state->filtered_items[state->selected_filtered_item].r.dy;
+ if (selected_bot < options->y) {
+ state->fancy_scroll -= selected_bot;
+ }
+ float diff = selected_top - (options->y + options->dy);
+ if (diff > 0) {
+ state->fancy_scroll -= diff;
+ }
+ } else {
+ // calc horizontal scroll
+ item_display_t* selected = &state->filtered_items[state->selected_filtered_item];
+ float selected_left = state->fancy_scroll + selected->r.x;
+ float selected_right = selected_left + selected->r.dx;
+ float right_diff = selected_right - (options->x + options->dx);
+ float left_diff = selected_left - options->x;
+
+ if (selected->r.dx > options->dx) {
+ state->fancy_scroll -= left_diff;
+ }
+ else if (right_diff > 0) {
+ state->fancy_scroll -= right_diff;
+ }
+ else if (left_diff < 0) {
+ state->fancy_scroll -= left_diff;
+ }
+ }
+
+ // apply scroll offset
+ array_for_all(item_display_t, display, state->filtered_items) {
+ if (state->lines) {
+ display->r.y += state->fancy_scroll;
+ } else {
+ display->r.x += state->fancy_scroll;
+ }
+ }
+
+ }
+ }
+}
diff --git a/layout.h b/layout.h
index cd1240d..8a4dd75 100644
--- a/layout.h
+++ b/layout.h
@@ -1,4 +1,9 @@
#ifndef LAYOUT_H_
#define LAYOUT_H_
+#include "state.h"
+
+void init_layout(client_state* state);
+void calculate_layout(client_state* state, rect_t* input, rect_t* options, bool recalc_options);
+
#endif
diff --git a/state.h b/state.h
index be55a11..6811c41 100644
--- a/state.h
+++ b/state.h
@@ -21,7 +21,7 @@
typedef struct {
float x, y, dx, dy;
-} Rect;
+} rect_t;
typedef struct {
GLuint vbo, ebo, vao;
@@ -52,7 +52,7 @@ typedef struct {
typedef struct {
item_t* item;
- float offset;
+ rect_t r;
} item_display_t;
typedef struct {
@@ -129,7 +129,7 @@ typedef struct {
int selected_filtered_item;
char* input_buffer;
size_t cursor_index;
- float scroll;
+ float fancy_scroll;
} client_state;