Skip to content
Open
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
2 changes: 1 addition & 1 deletion clib.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuklear",
"version": "4.12.8",
"version": "4.13.0",
"repo": "Immediate-Mode-UI/Nuklear",
"description": "A small ANSI C gui toolkit",
"keywords": ["gl", "ui", "toolkit"],
Expand Down
57 changes: 53 additions & 4 deletions nuklear.h
Original file line number Diff line number Diff line change
Expand Up @@ -4917,6 +4917,11 @@ struct nk_keyboard {
struct nk_key keys[NK_KEY_MAX];
char text[NK_INPUT_MAX];
int text_len;

/*Text keyboard request system*/
nk_bool text_want; /*When true, text input is actively requested*/
struct nk_rect text_area; /*Input area (valid only when text_want == true)*/
struct nk_rect text_cursor; /*Cursor position (valid only when text_want == true)*/
};

struct nk_input {
Expand All @@ -4941,6 +4946,10 @@ NK_API nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_button
NK_API nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
NK_API nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys);
NK_API nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys);
/* This is a utility function that should be called inside a widget
* to mark text keyboard for opening.
* Returns true only on the first request each frame */
NK_API nk_bool nk_input_want_text_keyboard(struct nk_input*);

/* ===============================================================
*
Expand Down Expand Up @@ -18199,6 +18208,10 @@ nk_input_begin(struct nk_context *ctx)
for (i = 0; i < NK_BUTTON_MAX; ++i)
in->mouse.buttons[i].clicked = 0;

in->keyboard.text_want = nk_false;
in->keyboard.text_area = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);
in->keyboard.text_cursor = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);

in->keyboard.text_len = 0;
in->mouse.scroll_delta = nk_vec2(0,0);
in->mouse.prev.x = in->mouse.pos.x;
Expand Down Expand Up @@ -18469,7 +18482,15 @@ nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
if (k->down) return nk_true;
return nk_false;
}

NK_API nk_bool
nk_input_want_text_keyboard(struct nk_input* i)
{
nk_bool ret;
NK_ASSERT(i);
ret = !i->keyboard.text_want;
i->keyboard.text_want = nk_true;
return ret;
}



Expand Down Expand Up @@ -27997,6 +28018,9 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
char cursor_follow = 0;
struct nk_rect old_clip;
struct nk_rect clip;
/*Variables for text keyboard(kb) support*/
nk_bool kb_text_want = nk_false;
struct nk_rect kb_text_cursor = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);

NK_ASSERT(state);
NK_ASSERT(out);
Expand Down Expand Up @@ -28082,13 +28106,17 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
cursor_follow = nk_true;
}
}
if (old_mode != edit->mode) {
/* If mode changes and text keys are pressed in the same frame,
* mode change takes priority (may transition to VIEW mode) */
if (old_mode != edit->mode)
in->keyboard.text_len = 0;
}}
else if (edit->mode == NK_TEXT_EDIT_MODE_INSERT || edit->mode == NK_TEXT_EDIT_MODE_REPLACE)
kb_text_want = nk_input_want_text_keyboard(in);
}

/* text input */
edit->filter = filter;
if (in->keyboard.text_len) {
if (kb_text_want && in->keyboard.text_len) {
nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
cursor_follow = nk_true;
in->keyboard.text_len = 0;
Expand Down Expand Up @@ -28407,12 +28435,23 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
row_height, font, background_color, text_color, nk_false);
}
if (edit->select_start != edit->select_end) {
int glyph_len;
nk_rune unicode;

/* draw selected text */
NK_ASSERT(select_begin_ptr);
if (!select_end_ptr) {
const char *begin = nk_str_get_const(&edit->string);
select_end_ptr = begin + nk_str_len_char(&edit->string);
}

glyph_len = nk_utf_decode(select_begin_ptr, &unicode, (int)(select_end_ptr - select_begin_ptr));
/* In this case, we set the cursor to the first selected character */
kb_text_cursor = nk_rect(
area.x + selection_offset_start.x - edit->scrollbar.x,
area.y + selection_offset_start.y - edit->scrollbar.y,
font->width(font->userdata, font->height, select_begin_ptr, glyph_len), row_height);

nk_edit_draw_text(out, style,
area.x - edit->scrollbar.x,
area.y + selection_offset_start.y - edit->scrollbar.y,
Expand Down Expand Up @@ -28449,6 +28488,7 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
cursor.y -= edit->scrollbar.y;
kb_text_cursor = cursor;
nk_fill_rect(out, cursor, 0, cursor_color);
} else {
/* draw cursor inside text */
Expand All @@ -28468,6 +28508,7 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
txt.padding = nk_vec2(0,0);
txt.background = cursor_color;;
txt.text = cursor_text_color;
kb_text_cursor = label;
nk_fill_rect(out, label, 0, cursor_color);
nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
}
Expand Down Expand Up @@ -28504,6 +28545,11 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
background_color, text_color, nk_false);
}
nk_push_scissor(out, old_clip);}
if (kb_text_want) {
NK_ASSERT(in);
in->keyboard.text_cursor = kb_text_cursor;
in->keyboard.text_area = clip;
}
return ret;
}
NK_API void
Expand Down Expand Up @@ -30729,6 +30775,9 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args)
/// - [y]: Minor version with non-breaking API and library changes
/// - [z]: Patch version with no direct changes to the API
///
/// - 2025/11/13 (4.13.0) - Introduced minimal text keyboard request API (nk_input_want_text_keyboard)
/// with support for text input area and cursor position.
/// This functionality is required for SDL_SetTextInputRect
/// - 2025/10/08 (4.12.8) - Fix nk_widget_text to use NK_TEXT_ALIGN_LEFT by default,
/// instead of silently failing when no x-axis alignment is provided,
/// and refactor this function to keep the code style consistent
Expand Down
3 changes: 3 additions & 0 deletions src/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/// - [y]: Minor version with non-breaking API and library changes
/// - [z]: Patch version with no direct changes to the API
///
/// - 2025/11/13 (4.13.0) - Introduced minimal text keyboard request API (nk_input_want_text_keyboard)
/// with support for text input area and cursor position.
/// This functionality is required for SDL_SetTextInputRect
/// - 2025/10/08 (4.12.8) - Fix nk_widget_text to use NK_TEXT_ALIGN_LEFT by default,
/// instead of silently failing when no x-axis alignment is provided,
/// and refactor this function to keep the code style consistent
Expand Down
9 changes: 9 additions & 0 deletions src/nuklear.h
Original file line number Diff line number Diff line change
Expand Up @@ -4694,6 +4694,11 @@ struct nk_keyboard {
struct nk_key keys[NK_KEY_MAX];
char text[NK_INPUT_MAX];
int text_len;

/*Text keyboard request system*/
nk_bool text_want; /*When true, text input is actively requested*/
struct nk_rect text_area; /*Input area (valid only when text_want == true)*/
struct nk_rect text_cursor; /*Cursor position (valid only when text_want == true)*/
};

struct nk_input {
Expand All @@ -4718,6 +4723,10 @@ NK_API nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_button
NK_API nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
NK_API nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys);
NK_API nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys);
/* This is a utility function that should be called inside a widget
* to mark text keyboard for opening.
* Returns true only on the first request each frame */
NK_API nk_bool nk_input_want_text_keyboard(struct nk_input*);

/* ===============================================================
*
Expand Down
31 changes: 28 additions & 3 deletions src/nuklear_edit.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
char cursor_follow = 0;
struct nk_rect old_clip;
struct nk_rect clip;
/*Variables for text keyboard(kb) support*/
nk_bool kb_text_want = nk_false;
struct nk_rect kb_text_cursor = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);

NK_ASSERT(state);
NK_ASSERT(out);
Expand Down Expand Up @@ -251,13 +254,17 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
cursor_follow = nk_true;
}
}
if (old_mode != edit->mode) {
/* If mode changes and text keys are pressed in the same frame,
* mode change takes priority (may transition to VIEW mode) */
if (old_mode != edit->mode)
in->keyboard.text_len = 0;
}}
else if (edit->mode == NK_TEXT_EDIT_MODE_INSERT || edit->mode == NK_TEXT_EDIT_MODE_REPLACE)
kb_text_want = nk_input_want_text_keyboard(in);
}

/* text input */
edit->filter = filter;
if (in->keyboard.text_len) {
if (kb_text_want && in->keyboard.text_len) {
nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
cursor_follow = nk_true;
in->keyboard.text_len = 0;
Expand Down Expand Up @@ -576,12 +583,23 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
row_height, font, background_color, text_color, nk_false);
}
if (edit->select_start != edit->select_end) {
int glyph_len;
nk_rune unicode;

/* draw selected text */
NK_ASSERT(select_begin_ptr);
if (!select_end_ptr) {
const char *begin = nk_str_get_const(&edit->string);
select_end_ptr = begin + nk_str_len_char(&edit->string);
}

glyph_len = nk_utf_decode(select_begin_ptr, &unicode, (int)(select_end_ptr - select_begin_ptr));
/* In this case, we set the cursor to the first selected character */
kb_text_cursor = nk_rect(
area.x + selection_offset_start.x - edit->scrollbar.x,
area.y + selection_offset_start.y - edit->scrollbar.y,
font->width(font->userdata, font->height, select_begin_ptr, glyph_len), row_height);

nk_edit_draw_text(out, style,
area.x - edit->scrollbar.x,
area.y + selection_offset_start.y - edit->scrollbar.y,
Expand Down Expand Up @@ -618,6 +636,7 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
cursor.y -= edit->scrollbar.y;
kb_text_cursor = cursor;
nk_fill_rect(out, cursor, 0, cursor_color);
} else {
/* draw cursor inside text */
Expand All @@ -637,6 +656,7 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
txt.padding = nk_vec2(0,0);
txt.background = cursor_color;;
txt.text = cursor_text_color;
kb_text_cursor = label;
nk_fill_rect(out, label, 0, cursor_color);
nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
}
Expand Down Expand Up @@ -673,6 +693,11 @@ nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
background_color, text_color, nk_false);
}
nk_push_scissor(out, old_clip);}
if (kb_text_want) {
NK_ASSERT(in);
in->keyboard.text_cursor = kb_text_cursor;
in->keyboard.text_area = clip;
}
return ret;
}
NK_API void
Expand Down
14 changes: 13 additions & 1 deletion src/nuklear_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ nk_input_begin(struct nk_context *ctx)
for (i = 0; i < NK_BUTTON_MAX; ++i)
in->mouse.buttons[i].clicked = 0;

in->keyboard.text_want = nk_false;
in->keyboard.text_area = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);
in->keyboard.text_cursor = nk_rect(0.0f, 0.0f, 0.0f, 0.0f);

in->keyboard.text_len = 0;
in->mouse.scroll_delta = nk_vec2(0,0);
in->mouse.prev.x = in->mouse.pos.x;
Expand Down Expand Up @@ -287,4 +291,12 @@ nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
if (k->down) return nk_true;
return nk_false;
}

NK_API nk_bool
nk_input_want_text_keyboard(struct nk_input* i)
{
nk_bool ret;
NK_ASSERT(i);
ret = !i->keyboard.text_want;
i->keyboard.text_want = nk_true;
return ret;
}