Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ports/headless.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,6 @@ bool iui_headless_save_screenshot(iui_port_ctx *ctx, const char *path)
/* Adler-32 checksum */
uint32_t adler = adler32(raw_data, raw_size);
write_be32(zlib_data + zlib_pos, adler);
zlib_pos += 4;

free(raw_data);

Expand Down
12 changes: 6 additions & 6 deletions src/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,10 +688,10 @@ void iui_tooltip(iui_context *ctx, const char *text)
x = win.x + win.width - width;

/* Smart vertical positioning: check available space above and below */
float space_below =
(win.y + win.height) - (ctx->layout.y + ctx->row_height);
float space_above = ctx->layout.y - win.y;
if (y + height > win.y + win.height) {
float space_below =
(win.y + win.height) - (ctx->layout.y + ctx->row_height);
float space_above = ctx->layout.y - win.y;
/* Would overflow bottom - try flipping above if more space there */
if (space_above > space_below && space_above >= height)
y = ctx->layout.y - height - IUI_TOOLTIP_OFFSET;
Expand Down Expand Up @@ -759,10 +759,10 @@ bool iui_tooltip_rich(iui_context *ctx,
x = win.x + win.width - width;

/* Smart vertical positioning: check available space above and below */
float space_below =
(win.y + win.height) - (ctx->layout.y + ctx->row_height);
float space_above = ctx->layout.y - win.y;
if (y + height > win.y + win.height) {
float space_below =
(win.y + win.height) - (ctx->layout.y + ctx->row_height);
float space_above = ctx->layout.y - win.y;
/* Would overflow bottom - try flipping above if more space there */
if (space_above > space_below && space_above >= height)
y = ctx->layout.y - height - IUI_TOOLTIP_OFFSET;
Expand Down
3 changes: 2 additions & 1 deletion src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ bool iui_has_focus(const iui_context *ctx, const char *id)
}

/* Internal: Check if widget with given ID is focused */
bool iui_widget_is_focused(iui_context *ctx, uint32_t id)
bool iui_widget_is_focused(const iui_context *ctx, uint32_t id)
{
return ctx->focused_widget_id == id && id != 0;
}
Expand Down Expand Up @@ -1340,6 +1340,7 @@ const char *iui_a11y_state_description(uint32_t state)
APPEND_STATE(IUI_A11Y_STATE_HASPOPUP, "has popup")

#undef APPEND_STATE
(void) count; /* suppress unused-after-final-increment warning */
return buf;
}

Expand Down
7 changes: 3 additions & 4 deletions src/dialog.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,13 @@ int iui_dialog(iui_context *ctx,
iui_state_t state = iui_get_component_state(ctx, btn_rect, false);

/* Draw button based on position (rightmost:filled, others:text) */
uint32_t bg_color = 0;
uint32_t text_color = ctx->colors.primary;
/* MD3 button corner radius (full rounded) */
float btn_corner = IUI_SHAPE_FULL;

if (i == btn_count - 1) {
/* Primary button (rightmost) - filled style */
bg_color = ctx->colors.primary;
uint32_t bg_color = ctx->colors.primary;
text_color = ctx->colors.on_primary;
ctx->renderer.draw_box(btn_rect, btn_corner, bg_color,
ctx->renderer.user);
Expand Down Expand Up @@ -376,9 +375,9 @@ bool iui_fullscreen_dialog_begin(iui_context *ctx,
}

/* Draw title after close icon */
float title_x = padding + touch_target + padding * 0.5f;
float title_y = (header_h - ctx->font_height) * 0.5f;
if (dialog->title) {
float title_x = padding + touch_target + padding * 0.5f;
float title_y = (header_h - ctx->font_height) * 0.5f;
iui_internal_draw_text(ctx, title_x, title_y, dialog->title,
ctx->colors.on_surface);
}
Expand Down
6 changes: 3 additions & 3 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,11 @@ static void iui_divider_internal(iui_context *ctx, float left_inset)
ctx->layout.y += 8.f;

/* MD3: 1dp height, outline_variant color */
float x = ctx->layout.x + left_inset, w = ctx->layout.width - left_inset;
float w = ctx->layout.width - left_inset;

/* Guard against negative width in narrow containers */
if (w > 0.f) {
float x = ctx->layout.x + left_inset;
ctx->renderer.draw_box((iui_rect_t) {x, ctx->layout.y, w, 1.f}, 0.f,
ctx->colors.outline_variant, ctx->renderer.user);
}
Expand Down Expand Up @@ -537,10 +538,9 @@ iui_state_t iui_get_component_state(iui_context *ctx,

if (ctx->mouse_pressed & IUI_MOUSE_LEFT)
return IUI_STATE_PRESSED;
}

if (hovered)
return IUI_STATE_HOVERED;
}

return IUI_STATE_DEFAULT;
}
Expand Down
3 changes: 1 addition & 2 deletions src/fab.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,11 @@ static bool iui_fab_internal(iui_context *ctx,
iui_draw_state_layer(ctx, fab_rect, corner_radius, content_color, state);

/* Calculate content position */
float content_x = x;
float center_y = y + fab_h * 0.5f;

if (label) {
/* Extended FAB: icon (optional) + label */
content_x = x + IUI_FAB_EXTENDED_PADDING;
float content_x = x + IUI_FAB_EXTENDED_PADDING;

if (icon) {
float icon_cx = content_x + icon_size * 0.5f;
Expand Down
5 changes: 1 addition & 4 deletions src/icons.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,11 +331,8 @@ void iui_draw_fab_icon(iui_context *ctx,
cx + half * 0.3f, cy, stroke, color);
iui_draw_line_soft(ctx, cx + half * 0.3f, cy, cx - half * 0.2f,
cy + half * 0.4f, stroke, color);
} else if (!strcmp(icon_name, "dot")) {
/* Filled dot */
iui_draw_circle_soft(ctx, cx, cy, size * 0.15f, color, 0, 0);
} else {
/* Default: draw a simple dot/circle for unknown icons */
/* Default / "dot": draw a simple filled circle */
iui_draw_circle_soft(ctx, cx, cy, size * 0.15f, color, 0, 0);
}
}
30 changes: 12 additions & 18 deletions src/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,17 +751,16 @@ bool iui_edit_with_selection(iui_context *ctx,
state->is_dragging = false;
}

/* Handle keyboard input when focused */
/* Handle keyboard input when focused and auto-scroll to keep cursor visible
*/
if (has_focus) {
modified =
iui_process_text_input_selection(ctx, buffer, buffer_size, state);
/* Reset cursor blink on any key activity */
if (ctx->key_pressed != IUI_KEY_NONE || ctx->char_input != 0)
ctx->cursor_blink = 0.f;
}

/* Auto-scroll to keep cursor visible */
if (has_focus) {
/* Auto-scroll to keep cursor visible */
float cursor_x_in_text =
textfield_get_width_to_pos(ctx, buffer, state->cursor, false);
if (cursor_x_in_text < state->scroll_offset)
Expand Down Expand Up @@ -990,7 +989,8 @@ iui_textfield_result iui_textfield_with_selection(
has_focus = false;
state->is_dragging = false;
}
} else if (opts.disabled && has_focus) {
} else if (has_focus) {
/* Widget is disabled but still has focus - clear it */
ctx->focused_edit = NULL;
has_focus = false;
}
Expand Down Expand Up @@ -1217,15 +1217,11 @@ bool iui_switch(iui_context *ctx,
}
}

/* Apply focus state layer */
/* Apply focus state layer and draw focus ring when focused */
if (is_focused) {
uint32_t focus_layer =
iui_state_layer(ctx->colors.primary, IUI_STATE_FOCUS_ALPHA);
track_color = iui_blend_color(track_color, focus_layer);
}

/* Draw focus ring when focused */
if (is_focused) {
iui_draw_focus_ring(ctx, track_rect, corner);
}

Expand Down Expand Up @@ -1525,16 +1521,14 @@ bool iui_dropdown(iui_context *ctx, const iui_dropdown_options *options)
}

/* Draw floating label */
float label_y;
uint32_t label_color =
options->disabled
? iui_state_layer(ctx->colors.on_surface_variant,
IUI_STATE_DISABLE_ALPHA)
: (is_open ? ctx->colors.primary : ctx->colors.on_surface_variant);

if (options->label) {
uint32_t label_color =
options->disabled ? iui_state_layer(ctx->colors.on_surface_variant,
IUI_STATE_DISABLE_ALPHA)
: (is_open ? ctx->colors.primary
: ctx->colors.on_surface_variant);
/* Label floats above when there's a selection */
label_y = field_rect.y + 8.f;
float label_y = field_rect.y + 8.f;
iui_internal_draw_text(ctx, field_rect.x + padding, label_y,
options->label, label_color);
}
Expand Down
4 changes: 2 additions & 2 deletions src/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ void iui_draw_fab_icon(iui_context *ctx,
float cx,
float cy,
float size,
const char *icon,
const char *icon_name,
uint32_t color);

/* Vector font rendering (implemented in core.c) */
Expand Down Expand Up @@ -1079,7 +1079,7 @@ bool iui_register_focusable(iui_context *ctx,
iui_rect_t bounds,
float corner);
void iui_process_focus_navigation(iui_context *ctx);
bool iui_widget_is_focused(iui_context *ctx, uint32_t id);
bool iui_widget_is_focused(const iui_context *ctx, uint32_t id);

/* Layout internal functions (iui_layout.c) */

Expand Down
4 changes: 1 addition & 3 deletions src/layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,8 @@ void iui_row(iui_context *ctx, int items, const float *widths, float height)
return;

/* End previous row if any */
if (ctx->in_row) {
if (ctx->in_row)
ctx->layout.y = ctx->row.next_row_y;
ctx->in_row = false;
}

ctx->in_row = true;
ctx->row.item_count = items;
Expand Down
2 changes: 1 addition & 1 deletion src/searchbar.c
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,10 @@ bool iui_search_view_suggestion(iui_context *ctx,

/* Draw icon if provided */
float content_x = padding;
float icon_cy = item_y + item_h * 0.5f;

if (icon) {
float icon_cx = padding + icon_size * 0.5f;
float icon_cy = item_y + item_h * 0.5f;
iui_draw_fab_icon(ctx, icon_cx, icon_cy, icon_size, icon,
ctx->colors.on_surface_variant);
content_x += icon_size + padding;
Expand Down
2 changes: 1 addition & 1 deletion src/tabs.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ static int iui_tabs_internal(iui_context *ctx,
is_selected ? ctx->colors.primary : ctx->colors.on_surface_variant;

/* Calculate content position (centered) */
float content_y = tabs_y + tab_height * 0.5f;
float text_width = iui_get_text_width(ctx, labels[i]);

if (icons && icons[i]) {
Expand All @@ -122,6 +121,7 @@ static int iui_tabs_internal(iui_context *ctx,
content_color);
} else {
/* Label only (centered vertically) */
float content_y = tabs_y + tab_height * 0.5f;
float label_x = tab_x + (tab_width - text_width) * 0.5f,
label_y = content_y - ctx->font_height * 0.5f;
iui_internal_draw_text(ctx, label_x, label_y, labels[i],
Expand Down
10 changes: 5 additions & 5 deletions tests/test-overflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ static void test_large_coord_clip(void)
bool success = iui_push_clip(ctx, large_clip);
ASSERT_TRUE(success);

/* Verify coordinates were clamped to uint16 range */
ASSERT_TRUE(g_last_clip_max_x <= UINT16_MAX);
ASSERT_TRUE(g_last_clip_max_y <= UINT16_MAX);
/* Verify coordinates were clamped to uint16 max (150000 -> 65535) */
ASSERT_EQ(g_last_clip_max_x, UINT16_MAX);
ASSERT_EQ(g_last_clip_max_y, UINT16_MAX);

iui_pop_clip(ctx);

Expand Down Expand Up @@ -249,10 +249,10 @@ static void test_slider_tracking_overflow(void)
float values[IUI_MAX_TRACKED_SLIDERS + 10];

for (int i = 0; i < IUI_MAX_TRACKED_SLIDERS + 10; i++) {
values[i] = 50.f;
values[i] = iui_slider_ex(ctx, values[i], 0.f, 100.f, 1.f, NULL);
values[i] = iui_slider_ex(ctx, 50.f, 0.f, 100.f, 1.f, NULL);
iui_newline(ctx);
}
(void) values; /* suppress unused warning - test only checks for crashes */

/* Should not crash - overflow handled gracefully */

Expand Down
Loading