mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
api/ui: allow popupmenu to be drawn by external ui
This commit is contained in:
parent
97c6d80ca7
commit
999af47be8
@ -10,6 +10,7 @@
|
|||||||
#include "nvim/msgpack_rpc/channel.h"
|
#include "nvim/msgpack_rpc/channel.h"
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
|
#include "nvim/popupmnu.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "api/ui.c.generated.h"
|
# include "api/ui.c.generated.h"
|
||||||
@ -88,6 +89,7 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
|
|||||||
ui->suspend = remote_ui_suspend;
|
ui->suspend = remote_ui_suspend;
|
||||||
ui->set_title = remote_ui_set_title;
|
ui->set_title = remote_ui_set_title;
|
||||||
ui->set_icon = remote_ui_set_icon;
|
ui->set_icon = remote_ui_set_icon;
|
||||||
|
ui->event = remote_ui_event;
|
||||||
pmap_put(uint64_t)(connected_uis, channel_id, ui);
|
pmap_put(uint64_t)(connected_uis, channel_id, ui);
|
||||||
ui_attach_impl(ui);
|
ui_attach_impl(ui);
|
||||||
return;
|
return;
|
||||||
@ -121,6 +123,20 @@ Object ui_try_resize(uint64_t channel_id, Integer width,
|
|||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui_set_popupmenu_external(uint64_t channel_id, Boolean external,
|
||||||
|
Error *error)
|
||||||
|
{
|
||||||
|
// Technically this is not needed right now,
|
||||||
|
// but futher on we might implement smarter behavior when multiple
|
||||||
|
// ui:s are attached with different draw modes
|
||||||
|
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
|
||||||
|
api_set_error(error, Exception, _("UI is not attached for channel"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pum_set_external(external);
|
||||||
|
}
|
||||||
|
|
||||||
static void push_call(UI *ui, char *name, Array args)
|
static void push_call(UI *ui, char *name, Array args)
|
||||||
{
|
{
|
||||||
Array call = ARRAY_DICT_INIT;
|
Array call = ARRAY_DICT_INIT;
|
||||||
@ -341,3 +357,19 @@ static void remote_ui_set_icon(UI *ui, char *icon)
|
|||||||
ADD(args, STRING_OBJ(cstr_to_string(icon)));
|
ADD(args, STRING_OBJ(cstr_to_string(icon)));
|
||||||
push_call(ui, "set_icon", args);
|
push_call(ui, "set_icon", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
|
||||||
|
{
|
||||||
|
Array my_args = ARRAY_DICT_INIT;
|
||||||
|
// Objects are currently single-reference
|
||||||
|
// make a copy, but only if necessary
|
||||||
|
if (*args_consumed) {
|
||||||
|
for (size_t i = 0; i < args.size; i++) {
|
||||||
|
ADD(my_args, copy_object(args.items[i]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
my_args = args;
|
||||||
|
*args_consumed = true;
|
||||||
|
}
|
||||||
|
push_call(ui, name, my_args);
|
||||||
|
}
|
||||||
|
@ -2472,6 +2472,7 @@ void ins_compl_show_pum(void)
|
|||||||
int cur = -1;
|
int cur = -1;
|
||||||
colnr_T col;
|
colnr_T col;
|
||||||
int lead_len = 0;
|
int lead_len = 0;
|
||||||
|
bool array_changed = false;
|
||||||
|
|
||||||
if (!pum_wanted() || !pum_enough_matches())
|
if (!pum_wanted() || !pum_enough_matches())
|
||||||
return;
|
return;
|
||||||
@ -2483,7 +2484,8 @@ void ins_compl_show_pum(void)
|
|||||||
update_screen(0);
|
update_screen(0);
|
||||||
|
|
||||||
if (compl_match_array == NULL) {
|
if (compl_match_array == NULL) {
|
||||||
/* Need to build the popup menu list. */
|
array_changed = true;
|
||||||
|
// Need to build the popup menu list.
|
||||||
compl_match_arraysize = 0;
|
compl_match_arraysize = 0;
|
||||||
compl = compl_first_match;
|
compl = compl_first_match;
|
||||||
/*
|
/*
|
||||||
@ -2586,7 +2588,7 @@ void ins_compl_show_pum(void)
|
|||||||
// Use the cursor to get all wrapping and other settings right.
|
// Use the cursor to get all wrapping and other settings right.
|
||||||
col = curwin->w_cursor.col;
|
col = curwin->w_cursor.col;
|
||||||
curwin->w_cursor.col = compl_col;
|
curwin->w_cursor.col = compl_col;
|
||||||
pum_display(compl_match_array, compl_match_arraysize, cur);
|
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed);
|
||||||
curwin->w_cursor.col = col;
|
curwin->w_cursor.col = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/popupmnu.h"
|
#include "nvim/popupmnu.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
@ -21,6 +22,7 @@
|
|||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#include "nvim/edit.h"
|
#include "nvim/edit.h"
|
||||||
|
#include "nvim/ui.h"
|
||||||
|
|
||||||
static pumitem_T *pum_array = NULL; // items of displayed pum
|
static pumitem_T *pum_array = NULL; // items of displayed pum
|
||||||
static int pum_size; // nr of items in "pum_array"
|
static int pum_size; // nr of items in "pum_array"
|
||||||
@ -36,8 +38,10 @@ static int pum_scrollbar; // TRUE when scrollbar present
|
|||||||
static int pum_row; // top row of pum
|
static int pum_row; // top row of pum
|
||||||
static int pum_col; // left column of pum
|
static int pum_col; // left column of pum
|
||||||
|
|
||||||
static int pum_do_redraw = FALSE; // do redraw anyway
|
static bool pum_is_visible = false;
|
||||||
|
|
||||||
|
static bool pum_external = false;
|
||||||
|
static bool pum_wants_external = false;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "popupmnu.c.generated.h"
|
# include "popupmnu.c.generated.h"
|
||||||
@ -53,7 +57,10 @@ static int pum_do_redraw = FALSE; // do redraw anyway
|
|||||||
/// @param array
|
/// @param array
|
||||||
/// @param size
|
/// @param size
|
||||||
/// @param selected index of initially selected item, none if out of range
|
/// @param selected index of initially selected item, none if out of range
|
||||||
void pum_display(pumitem_T *array, int size, int selected)
|
/// @param array_changed if true, array contains different items since last call
|
||||||
|
/// if false, a new item is selected, but the array
|
||||||
|
/// is the same
|
||||||
|
void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
|
||||||
{
|
{
|
||||||
int w;
|
int w;
|
||||||
int def_width;
|
int def_width;
|
||||||
@ -68,20 +75,55 @@ void pum_display(pumitem_T *array, int size, int selected)
|
|||||||
int above_row = cmdline_row;
|
int above_row = cmdline_row;
|
||||||
int redo_count = 0;
|
int redo_count = 0;
|
||||||
|
|
||||||
|
if (!pum_is_visible) {
|
||||||
|
// To keep the code simple, we only allow changing the
|
||||||
|
// draw mode when the popup menu is not being displayed
|
||||||
|
pum_external = pum_wants_external;
|
||||||
|
}
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
|
// Mark the pum as visible already here,
|
||||||
|
// to avoid that must_redraw is set when 'cursorcolumn' is on.
|
||||||
|
pum_is_visible = true;
|
||||||
|
validate_cursor_col();
|
||||||
|
|
||||||
|
// anchor position: the start of the completed word
|
||||||
|
row = curwin->w_wrow + curwin->w_winrow;
|
||||||
|
if (curwin->w_p_rl) {
|
||||||
|
col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
|
||||||
|
} else {
|
||||||
|
col = curwin->w_wincol + curwin->w_wcol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pum_external) {
|
||||||
|
Array args = ARRAY_DICT_INIT;
|
||||||
|
if (array_changed) {
|
||||||
|
Array arr = ARRAY_DICT_INIT;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
Array item = ARRAY_DICT_INIT;
|
||||||
|
ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_text)));
|
||||||
|
ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_kind)));
|
||||||
|
ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_extra)));
|
||||||
|
ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info)));
|
||||||
|
ADD(arr, ARRAY_OBJ(item));
|
||||||
|
}
|
||||||
|
ADD(args, ARRAY_OBJ(arr));
|
||||||
|
ADD(args, INTEGER_OBJ(selected));
|
||||||
|
ADD(args, INTEGER_OBJ(row));
|
||||||
|
ADD(args, INTEGER_OBJ(col));
|
||||||
|
ui_event("popupmenu_show", args);
|
||||||
|
} else {
|
||||||
|
ADD(args, INTEGER_OBJ(selected));
|
||||||
|
ui_event("popupmenu_select", args);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
def_width = PUM_DEF_WIDTH;
|
def_width = PUM_DEF_WIDTH;
|
||||||
max_width = 0;
|
max_width = 0;
|
||||||
kind_width = 0;
|
kind_width = 0;
|
||||||
extra_width = 0;
|
extra_width = 0;
|
||||||
|
|
||||||
// Pretend the pum is already there to avoid that must_redraw is set when
|
|
||||||
// 'cuc' is on.
|
|
||||||
pum_array = (pumitem_T *)1;
|
|
||||||
validate_cursor_col();
|
|
||||||
pum_array = NULL;
|
|
||||||
|
|
||||||
row = curwin->w_wrow + curwin->w_winrow;
|
|
||||||
|
|
||||||
if (firstwin->w_p_pvw) {
|
if (firstwin->w_p_pvw) {
|
||||||
top_clear = firstwin->w_height;
|
top_clear = firstwin->w_height;
|
||||||
} else {
|
} else {
|
||||||
@ -194,13 +236,6 @@ redo:
|
|||||||
pum_base_width = max_width;
|
pum_base_width = max_width;
|
||||||
pum_kind_width = kind_width;
|
pum_kind_width = kind_width;
|
||||||
|
|
||||||
// Calculate column
|
|
||||||
if (curwin->w_p_rl) {
|
|
||||||
col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
|
|
||||||
} else {
|
|
||||||
col = curwin->w_wincol + curwin->w_wcol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there are more items than room we need a scrollbar
|
// if there are more items than room we need a scrollbar
|
||||||
if (pum_height < size) {
|
if (pum_height < size) {
|
||||||
pum_scrollbar = 1;
|
pum_scrollbar = 1;
|
||||||
@ -641,9 +676,9 @@ static int pum_set_selected(int n, int repeat)
|
|||||||
|
|
||||||
// Update the screen before drawing the popup menu.
|
// Update the screen before drawing the popup menu.
|
||||||
// Enable updating the status lines.
|
// Enable updating the status lines.
|
||||||
pum_do_redraw = TRUE;
|
pum_is_visible = false;
|
||||||
update_screen(0);
|
update_screen(0);
|
||||||
pum_do_redraw = FALSE;
|
pum_is_visible = true;
|
||||||
|
|
||||||
if (!resized && win_valid(curwin_save)) {
|
if (!resized && win_valid(curwin_save)) {
|
||||||
no_u_sync++;
|
no_u_sync++;
|
||||||
@ -653,9 +688,9 @@ static int pum_set_selected(int n, int repeat)
|
|||||||
|
|
||||||
// May need to update the screen again when there are
|
// May need to update the screen again when there are
|
||||||
// autocommands involved.
|
// autocommands involved.
|
||||||
pum_do_redraw = TRUE;
|
pum_is_visible = false;
|
||||||
update_screen(0);
|
update_screen(0);
|
||||||
pum_do_redraw = FALSE;
|
pum_is_visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -672,10 +707,17 @@ static int pum_set_selected(int n, int repeat)
|
|||||||
/// Undisplay the popup menu (later).
|
/// Undisplay the popup menu (later).
|
||||||
void pum_undisplay(void)
|
void pum_undisplay(void)
|
||||||
{
|
{
|
||||||
|
pum_is_visible = false;
|
||||||
pum_array = NULL;
|
pum_array = NULL;
|
||||||
redraw_all_later(SOME_VALID);
|
|
||||||
redraw_tabline = TRUE;
|
if (pum_external) {
|
||||||
status_redraw_all();
|
Array args = ARRAY_DICT_INIT;
|
||||||
|
ui_event("popupmenu_hide", args);
|
||||||
|
} else {
|
||||||
|
redraw_all_later(SOME_VALID);
|
||||||
|
redraw_tabline = true;
|
||||||
|
status_redraw_all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the popup menu. Currently only resets the offset to the first
|
/// Clear the popup menu. Currently only resets the offset to the first
|
||||||
@ -685,12 +727,16 @@ void pum_clear(void)
|
|||||||
pum_first = 0;
|
pum_first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overruled when "pum_do_redraw" is set, used to redraw the status lines.
|
/// @return true if the popup menu is displayed.
|
||||||
///
|
bool pum_visible(void)
|
||||||
/// @return TRUE if the popup menu is displayed.
|
|
||||||
int pum_visible(void)
|
|
||||||
{
|
{
|
||||||
return !pum_do_redraw && pum_array != NULL;
|
return pum_is_visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return true if the popup menu is displayed and drawn on the grid.
|
||||||
|
bool pum_drawn(void)
|
||||||
|
{
|
||||||
|
return pum_visible() && !pum_external;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the height of the menu.
|
/// Gets the height of the menu.
|
||||||
@ -701,3 +747,8 @@ int pum_get_height(void)
|
|||||||
{
|
{
|
||||||
return pum_height;
|
return pum_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pum_set_external(bool external)
|
||||||
|
{
|
||||||
|
pum_wants_external = external;
|
||||||
|
}
|
||||||
|
@ -420,9 +420,10 @@ void update_screen(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end_search_hl();
|
end_search_hl();
|
||||||
/* May need to redraw the popup menu. */
|
// May need to redraw the popup menu.
|
||||||
if (pum_visible())
|
if (pum_drawn()) {
|
||||||
pum_redraw();
|
pum_redraw();
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset b_mod_set flags. Going through all windows is probably faster
|
/* Reset b_mod_set flags. Going through all windows is probably faster
|
||||||
* than going through all buffers (there could be many buffers). */
|
* than going through all buffers (there could be many buffers). */
|
||||||
@ -4827,15 +4828,12 @@ void win_redr_status(win_T *wp)
|
|||||||
|
|
||||||
wp->w_redr_status = FALSE;
|
wp->w_redr_status = FALSE;
|
||||||
if (wp->w_status_height == 0) {
|
if (wp->w_status_height == 0) {
|
||||||
/* no status line, can only be last window */
|
// no status line, can only be last window
|
||||||
redraw_cmdline = TRUE;
|
redraw_cmdline = true;
|
||||||
} else if (!redrawing()
|
} else if (!redrawing() || pum_drawn()) {
|
||||||
/* don't update status line when popup menu is visible and may be
|
// Don't redraw right now, do it later. Don't update status line when
|
||||||
* drawn over it */
|
// popup menu is visible and may be drawn over it
|
||||||
|| pum_visible()
|
wp->w_redr_status = true;
|
||||||
) {
|
|
||||||
/* Don't redraw right now, do it later. */
|
|
||||||
wp->w_redr_status = TRUE;
|
|
||||||
} else if (*p_stl != NUL || *wp->w_p_stl != NUL) {
|
} else if (*p_stl != NUL || *wp->w_p_stl != NUL) {
|
||||||
/* redraw custom status line */
|
/* redraw custom status line */
|
||||||
redraw_custom_statusline(wp);
|
redraw_custom_statusline(wp);
|
||||||
@ -7081,9 +7079,9 @@ void showruler(int always)
|
|||||||
{
|
{
|
||||||
if (!always && !redrawing())
|
if (!always && !redrawing())
|
||||||
return;
|
return;
|
||||||
if (pum_visible()) {
|
if (pum_drawn()) {
|
||||||
/* Don't redraw right now, do it later. */
|
// Don't redraw right now, do it later.
|
||||||
curwin->w_redr_status = TRUE;
|
curwin->w_redr_status = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
|
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
|
||||||
@ -7119,9 +7117,10 @@ static void win_redr_ruler(win_T *wp, int always)
|
|||||||
if (wp == lastwin && lastwin->w_status_height == 0)
|
if (wp == lastwin && lastwin->w_status_height == 0)
|
||||||
if (edit_submode != NULL)
|
if (edit_submode != NULL)
|
||||||
return;
|
return;
|
||||||
/* Don't draw the ruler when the popup menu is visible, it may overlap. */
|
// Don't draw the ruler when the popup menu is visible, it may overlap.
|
||||||
if (pum_visible())
|
if (pum_drawn()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (*p_ruf) {
|
if (*p_ruf) {
|
||||||
int save_called_emsg = called_emsg;
|
int save_called_emsg = called_emsg;
|
||||||
@ -7371,7 +7370,7 @@ void screen_resize(int width, int height)
|
|||||||
redrawcmdline();
|
redrawcmdline();
|
||||||
} else {
|
} else {
|
||||||
update_topline();
|
update_topline();
|
||||||
if (pum_visible()) {
|
if (pum_drawn()) {
|
||||||
redraw_later(NOT_VALID);
|
redraw_later(NOT_VALID);
|
||||||
ins_compl_show_pum(); /* This includes the redraw. */
|
ins_compl_show_pum(); /* This includes the redraw. */
|
||||||
} else
|
} else
|
||||||
|
@ -106,6 +106,7 @@ UI *tui_start(void)
|
|||||||
ui->suspend = tui_suspend;
|
ui->suspend = tui_suspend;
|
||||||
ui->set_title = tui_set_title;
|
ui->set_title = tui_set_title;
|
||||||
ui->set_icon = tui_set_icon;
|
ui->set_icon = tui_set_icon;
|
||||||
|
ui->event = tui_event;
|
||||||
return ui_bridge_attach(ui, tui_main, tui_scheduler);
|
return ui_bridge_attach(ui, tui_main, tui_scheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,6 +651,12 @@ static void tui_set_icon(UI *ui, char *icon)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB: if we start to use this, the ui_bridge must be updated
|
||||||
|
// to make a copy for the tui thread
|
||||||
|
static void tui_event(UI *ui, char *name, Array args, bool *args_consumed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void invalidate(UI *ui, int top, int bot, int left, int right)
|
static void invalidate(UI *ui, int top, int bot, int left, int right)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#else
|
#else
|
||||||
# include "nvim/msgpack_rpc/server.h"
|
# include "nvim/msgpack_rpc/server.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "nvim/api/private/helpers.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "ui.c.generated.h"
|
# include "ui.c.generated.h"
|
||||||
@ -143,6 +144,15 @@ void ui_set_icon(char *icon)
|
|||||||
UI_CALL(flush);
|
UI_CALL(flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui_event(char *name, Array args)
|
||||||
|
{
|
||||||
|
bool args_consumed = false;
|
||||||
|
UI_CALL(event, name, args, &args_consumed);
|
||||||
|
if (!args_consumed) {
|
||||||
|
api_free_array(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// May update the shape of the cursor.
|
// May update the shape of the cursor.
|
||||||
void ui_cursor_shape(void)
|
void ui_cursor_shape(void)
|
||||||
{
|
{
|
||||||
@ -519,3 +529,4 @@ static void ui_mode_change(void)
|
|||||||
UI_CALL(mode_change, mode);
|
UI_CALL(mode_change, mode);
|
||||||
conceal_check_cursur_line();
|
conceal_check_cursur_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "api/private/defs.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool bold, underline, undercurl, italic, reverse;
|
bool bold, underline, undercurl, italic, reverse;
|
||||||
int foreground, background, special;
|
int foreground, background, special;
|
||||||
@ -39,6 +41,7 @@ struct ui_t {
|
|||||||
void (*suspend)(UI *ui);
|
void (*suspend)(UI *ui);
|
||||||
void (*set_title)(UI *ui, char *title);
|
void (*set_title)(UI *ui, char *title);
|
||||||
void (*set_icon)(UI *ui, char *icon);
|
void (*set_icon)(UI *ui, char *icon);
|
||||||
|
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
|
||||||
void (*stop)(UI *ui);
|
void (*stop)(UI *ui);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user