Compare commits
2 Commits
9cd511a2e2
...
5d5f73f22f
Author | SHA1 | Date | |
---|---|---|---|
5d5f73f22f | |||
4a9e621d92 |
193
nncmpp.c
193
nncmpp.c
@ -1182,9 +1182,6 @@ struct widget;
|
|||||||
/// Draw a widget on the window
|
/// Draw a widget on the window
|
||||||
typedef void (*widget_render_fn) (struct widget *self);
|
typedef void (*widget_render_fn) (struct widget *self);
|
||||||
|
|
||||||
/// Extract the contents of container widgets
|
|
||||||
typedef struct widget *(*widget_sublayout_fn) (struct widget *self);
|
|
||||||
|
|
||||||
/// A minimal abstraction appropriate for both TUI and GUI widgets.
|
/// A minimal abstraction appropriate for both TUI and GUI widgets.
|
||||||
/// Units for the widget's region are frontend-specific.
|
/// Units for the widget's region are frontend-specific.
|
||||||
/// Having this as a linked list simplifies layouting and memory management.
|
/// Having this as a linked list simplifies layouting and memory management.
|
||||||
@ -1198,7 +1195,7 @@ struct widget
|
|||||||
int height; ///< Height, initialized by UI methods
|
int height; ///< Height, initialized by UI methods
|
||||||
|
|
||||||
widget_render_fn on_render; ///< Render callback
|
widget_render_fn on_render; ///< Render callback
|
||||||
widget_sublayout_fn on_sublayout; ///< Optional sublayout callback
|
struct widget *children; ///< Child widgets of containers
|
||||||
chtype attrs; ///< Rendition, in Curses terms
|
chtype attrs; ///< Rendition, in Curses terms
|
||||||
|
|
||||||
short id; ///< Post-layouting identification
|
short id; ///< Post-layouting identification
|
||||||
@ -1231,6 +1228,23 @@ struct ui
|
|||||||
bool have_icons;
|
bool have_icons;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
widget_destroy (struct widget *self)
|
||||||
|
{
|
||||||
|
LIST_FOR_EACH (struct widget, w, self->children)
|
||||||
|
widget_destroy (w);
|
||||||
|
free (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
widget_move (struct widget *w, int dx, int dy)
|
||||||
|
{
|
||||||
|
w->x += dx;
|
||||||
|
w->y += dy;
|
||||||
|
LIST_FOR_EACH (struct widget, child, w->children)
|
||||||
|
widget_move (child, dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
/// Replaces negative widths amongst widgets in the sublist by redistributing
|
/// Replaces negative widths amongst widgets in the sublist by redistributing
|
||||||
/// any width remaining after all positive claims are satisfied from "width".
|
/// any width remaining after all positive claims are satisfied from "width".
|
||||||
/// Also unifies heights to the maximum value of the run, and returns it.
|
/// Also unifies heights to the maximum value of the run, and returns it.
|
||||||
@ -1265,7 +1279,7 @@ widget_redistribute (struct widget *head, int width)
|
|||||||
int x = 0;
|
int x = 0;
|
||||||
LIST_FOR_EACH (struct widget, w, head)
|
LIST_FOR_EACH (struct widget, w, head)
|
||||||
{
|
{
|
||||||
w->x = x;
|
widget_move (w, x - w->x, 0);
|
||||||
x += w->width;
|
x += w->width;
|
||||||
}
|
}
|
||||||
return max_height;
|
return max_height;
|
||||||
@ -1792,30 +1806,37 @@ app_invalidate (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_flush_layout_to (struct layout *l, int width, struct layout *dest)
|
app_append_layout (struct layout *l, struct layout *dest)
|
||||||
{
|
{
|
||||||
hard_assert (l != NULL && l->head != NULL);
|
|
||||||
widget_redistribute (l->head, width);
|
|
||||||
|
|
||||||
struct widget *last = dest->tail;
|
struct widget *last = dest->tail;
|
||||||
if (!last)
|
if (!last)
|
||||||
*dest = *l;
|
*dest = *l;
|
||||||
else
|
else if (l->head)
|
||||||
{
|
{
|
||||||
// Assuming there is no unclaimed vertical space.
|
// Assuming there is no unclaimed vertical space.
|
||||||
LIST_FOR_EACH (struct widget, w, l->head)
|
LIST_FOR_EACH (struct widget, w, l->head)
|
||||||
w->y = last->y + last->height;
|
widget_move (w, 0, last->y + last->height - w->y);
|
||||||
|
|
||||||
last->next = l->head;
|
last->next = l->head;
|
||||||
l->head->prev = last;
|
l->head->prev = last;
|
||||||
dest->tail = l->tail;
|
dest->tail = l->tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*l = (struct layout) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_flush_layout (struct layout *l)
|
app_flush_layout_full (struct layout *l, int width, struct layout *dest)
|
||||||
{
|
{
|
||||||
app_flush_layout_to (l, g.ui_width, &g.widgets);
|
hard_assert (l != NULL && l->head != NULL);
|
||||||
|
widget_redistribute (l->head, width);
|
||||||
|
app_append_layout (l, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
app_flush_layout (struct layout *l, struct layout *out)
|
||||||
|
{
|
||||||
|
app_flush_layout_full (l, g.ui_width, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct widget *
|
static struct widget *
|
||||||
@ -1836,19 +1857,19 @@ app_push_fill (struct layout *l, struct widget *w)
|
|||||||
/// Write the given UTF-8 string padded with spaces.
|
/// Write the given UTF-8 string padded with spaces.
|
||||||
/// @param[in] attrs Text attributes for the text, including padding.
|
/// @param[in] attrs Text attributes for the text, including padding.
|
||||||
static void
|
static void
|
||||||
app_layout_text (const char *str, chtype attrs)
|
app_layout_text (const char *str, chtype attrs, struct layout *out)
|
||||||
{
|
{
|
||||||
struct layout l = {};
|
struct layout l = {};
|
||||||
app_push (&l, g.ui->padding (attrs, 0.25, 1));
|
app_push (&l, g.ui->padding (attrs, 0.25, 1));
|
||||||
app_push_fill (&l, g.ui->label (attrs, str));
|
app_push_fill (&l, g.ui->label (attrs, str));
|
||||||
app_push (&l, g.ui->padding (attrs, 0.25, 1));
|
app_push (&l, g.ui->padding (attrs, 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_song_info (void)
|
app_layout_song_info (struct layout *out)
|
||||||
{
|
{
|
||||||
compact_map_t map;
|
compact_map_t map;
|
||||||
if (!(map = item_list_get (&g.playlist, g.song)))
|
if (!(map = item_list_get (&g.playlist, g.song)))
|
||||||
@ -1880,7 +1901,7 @@ app_layout_song_info (void)
|
|||||||
app_push (&l, g.ui->label (attrs[1], title));
|
app_push (&l, g.ui->label (attrs[1], title));
|
||||||
app_push_fill (&l, g.ui->padding (attrs[0], 0, 1));
|
app_push_fill (&l, g.ui->padding (attrs[0], 0, 1));
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Showing a blank line is better than having the controls jump around
|
// Showing a blank line is better than having the controls jump around
|
||||||
@ -1919,7 +1940,7 @@ app_layout_song_info (void)
|
|||||||
|
|
||||||
app_push_fill (&l, g.ui->padding (attrs[0], 0, 1));
|
app_push_fill (&l, g.ui->padding (attrs[0], 0, 1));
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@ -1939,11 +1960,11 @@ app_time_string (int seconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_status (void)
|
app_layout_status (struct layout *out)
|
||||||
{
|
{
|
||||||
bool stopped = g.state == PLAYER_STOPPED;
|
bool stopped = g.state == PLAYER_STOPPED;
|
||||||
if (!stopped)
|
if (!stopped)
|
||||||
app_layout_song_info ();
|
app_layout_song_info (out);
|
||||||
|
|
||||||
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
||||||
struct layout l = {};
|
struct layout l = {};
|
||||||
@ -2014,11 +2035,11 @@ app_layout_status (void)
|
|||||||
str_free (&volume);
|
str_free (&volume);
|
||||||
|
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_tabs (void)
|
app_layout_tabs (struct layout *out)
|
||||||
{
|
{
|
||||||
chtype attrs[2] = { APP_ATTR (TAB_BAR), APP_ATTR (TAB_ACTIVE) };
|
chtype attrs[2] = { APP_ATTR (TAB_BAR), APP_ATTR (TAB_ACTIVE) };
|
||||||
struct layout l = {};
|
struct layout l = {};
|
||||||
@ -2053,30 +2074,30 @@ app_layout_tabs (void)
|
|||||||
}
|
}
|
||||||
#endif // WITH_FFTW
|
#endif // WITH_FFTW
|
||||||
|
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_header (void)
|
app_layout_header (struct layout *out)
|
||||||
{
|
{
|
||||||
if (g.client.state == MPD_CONNECTED)
|
if (g.client.state == MPD_CONNECTED)
|
||||||
{
|
{
|
||||||
struct layout lt = {};
|
struct layout lt = {};
|
||||||
app_push_fill (<, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
app_push_fill (<, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
||||||
app_flush_layout (<);
|
app_flush_layout (<, out);
|
||||||
|
|
||||||
app_layout_status ();
|
app_layout_status (out);
|
||||||
|
|
||||||
struct layout lb = {};
|
struct layout lb = {};
|
||||||
app_push_fill (&lb, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
app_push_fill (&lb, g.ui->padding (APP_ATTR (NORMAL), 0, 0.125));
|
||||||
app_flush_layout (&lb);
|
app_flush_layout (&lb, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
app_layout_tabs ();
|
app_layout_tabs (out);
|
||||||
|
|
||||||
const char *header = g.active_tab->header;
|
const char *header = g.active_tab->header;
|
||||||
if (header)
|
if (header)
|
||||||
app_layout_text (header, APP_ATTR (HEADER));
|
app_layout_text (header, APP_ATTR (HEADER), out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct widget *
|
static struct widget *
|
||||||
@ -2169,50 +2190,37 @@ app_layout_row (struct tab *tab, int item_index)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: This isn't a very clean design, in that part of layouting
|
static void
|
||||||
// is done during the rendering stage.
|
app_layout_view (struct layout *out, int height)
|
||||||
static struct widget *
|
|
||||||
app_sublayout_list (struct widget *list)
|
|
||||||
{
|
{
|
||||||
|
struct layout l = {};
|
||||||
|
struct widget *list = app_push_fill (&l, g.ui->list ());
|
||||||
|
list->id = WIDGET_LIST;
|
||||||
|
list->height = height;
|
||||||
|
list->width = g.ui_width;
|
||||||
|
|
||||||
struct tab *tab = g.active_tab;
|
struct tab *tab = g.active_tab;
|
||||||
|
if ((int) tab->item_count * g.ui_vunit > list->height)
|
||||||
|
{
|
||||||
|
struct widget *scrollbar = g.ui->scrollbar (APP_ATTR (SCROLLBAR));
|
||||||
|
list->width -= scrollbar->width;
|
||||||
|
app_push (&l, scrollbar)->id = WIDGET_SCROLLBAR;
|
||||||
|
}
|
||||||
|
|
||||||
int to_show = MIN ((int) tab->item_count - tab->item_top,
|
int to_show = MIN ((int) tab->item_count - tab->item_top,
|
||||||
ceil ((double) list->height / g.ui_vunit));
|
ceil ((double) list->height / g.ui_vunit));
|
||||||
|
|
||||||
struct layout l = {};
|
struct layout children = {};
|
||||||
for (int row = 0; row < to_show; row++)
|
for (int row = 0; row < to_show; row++)
|
||||||
{
|
{
|
||||||
int item_index = tab->item_top + row;
|
int item_index = tab->item_top + row;
|
||||||
struct layout subl = app_layout_row (tab, item_index);
|
struct layout subl = app_layout_row (tab, item_index);
|
||||||
app_flush_layout_to (&subl, list->width, &l);
|
// TODO: Change layouting so that we don't need to know list->width.
|
||||||
|
app_flush_layout_full (&subl, list->width, &children);
|
||||||
}
|
}
|
||||||
LIST_FOR_EACH (struct widget, w, l.head)
|
list->children = children.head;
|
||||||
{
|
|
||||||
w->x += list->x;
|
|
||||||
w->y += list->y;
|
|
||||||
}
|
|
||||||
return l.head;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
app_flush_layout (&l, out);
|
||||||
app_layout_view (void)
|
|
||||||
{
|
|
||||||
// XXX: Expecting the status bar to always be there, one row tall.
|
|
||||||
struct widget *last = g.widgets.tail;
|
|
||||||
int unavailable_height = last->y + last->height + g.ui_vunit;
|
|
||||||
|
|
||||||
struct layout l = {};
|
|
||||||
struct widget *w = app_push_fill (&l, g.ui->list ());
|
|
||||||
w->id = WIDGET_LIST;
|
|
||||||
w->height = g.ui_height - unavailable_height;
|
|
||||||
|
|
||||||
struct tab *tab = g.active_tab;
|
|
||||||
if ((int) tab->item_count * g.ui_vunit > w->height)
|
|
||||||
{
|
|
||||||
app_push (&l, g.ui->scrollbar (APP_ATTR (SCROLLBAR)))
|
|
||||||
->id = WIDGET_SCROLLBAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_flush_layout (&l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2258,7 +2266,7 @@ app_layout_mpd_status_playlist (struct layout *l, chtype attrs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_mpd_status (void)
|
app_layout_mpd_status (struct layout *out)
|
||||||
{
|
{
|
||||||
struct layout l = {};
|
struct layout l = {};
|
||||||
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
||||||
@ -2311,11 +2319,11 @@ app_layout_mpd_status (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
app_layout_statusbar (void)
|
app_layout_statusbar (struct layout *out)
|
||||||
{
|
{
|
||||||
struct layout l = {};
|
struct layout l = {};
|
||||||
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
||||||
@ -2331,7 +2339,7 @@ app_layout_statusbar (void)
|
|||||||
}
|
}
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
|
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
LIST_FOR_EACH (struct widget, w, l.head)
|
LIST_FOR_EACH (struct widget, w, l.head)
|
||||||
w->id = WIDGET_MESSAGE;
|
w->id = WIDGET_MESSAGE;
|
||||||
}
|
}
|
||||||
@ -2340,14 +2348,14 @@ app_layout_statusbar (void)
|
|||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_push (&l, g.ui->editor (attrs[1]));
|
app_push (&l, g.ui->editor (attrs[1]));
|
||||||
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
app_push (&l, g.ui->padding (attrs[0], 0.25, 1));
|
||||||
app_flush_layout (&l);
|
app_flush_layout (&l, out);
|
||||||
}
|
}
|
||||||
else if (g.client.state == MPD_CONNECTED)
|
else if (g.client.state == MPD_CONNECTED)
|
||||||
app_layout_mpd_status ();
|
app_layout_mpd_status (out);
|
||||||
else if (g.client.state == MPD_CONNECTING)
|
else if (g.client.state == MPD_CONNECTING)
|
||||||
app_layout_text ("Connecting to MPD...", attrs[0]);
|
app_layout_text ("Connecting to MPD...", attrs[0], out);
|
||||||
else if (g.client.state == MPD_DISCONNECTED)
|
else if (g.client.state == MPD_DISCONNECTED)
|
||||||
app_layout_text ("Disconnected", attrs[0]);
|
app_layout_text ("Disconnected", attrs[0], out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
@ -2393,14 +2401,23 @@ app_on_refresh (void *user_data)
|
|||||||
(void) user_data;
|
(void) user_data;
|
||||||
poller_idle_reset (&g.refresh_event);
|
poller_idle_reset (&g.refresh_event);
|
||||||
|
|
||||||
|
struct layout top = {}, bottom = {};
|
||||||
|
app_layout_header (&top);
|
||||||
|
app_layout_statusbar (&bottom);
|
||||||
|
|
||||||
|
int available_height = g.ui_height;
|
||||||
|
if (top.tail)
|
||||||
|
available_height -= top.tail->y + top.tail->height;
|
||||||
|
if (bottom.tail)
|
||||||
|
available_height -= bottom.tail->y + bottom.tail->height;
|
||||||
|
|
||||||
LIST_FOR_EACH (struct widget, w, g.widgets.head)
|
LIST_FOR_EACH (struct widget, w, g.widgets.head)
|
||||||
free (w);
|
widget_destroy (w);
|
||||||
|
|
||||||
g.widgets = (struct layout) {};
|
g.widgets = (struct layout) {};
|
||||||
|
app_append_layout (&top, &g.widgets);
|
||||||
app_layout_header ();
|
app_layout_view (&g.widgets, available_height);
|
||||||
app_layout_view ();
|
app_append_layout (&bottom, &g.widgets);
|
||||||
app_layout_statusbar ();
|
|
||||||
|
|
||||||
app_fix_view_range();
|
app_fix_view_range();
|
||||||
|
|
||||||
@ -2633,7 +2650,7 @@ incremental_search_on_changed (void)
|
|||||||
LIST_FOR_EACH (struct widget, w, tab->on_item_layout (index).head)
|
LIST_FOR_EACH (struct widget, w, tab->on_item_layout (index).head)
|
||||||
{
|
{
|
||||||
str_append (&s, w->text);
|
str_append (&s, w->text);
|
||||||
free (w);
|
widget_destroy (w);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -5694,11 +5711,8 @@ tui_make_scrollbar (chtype attrs)
|
|||||||
static void
|
static void
|
||||||
tui_render_list (struct widget *self)
|
tui_render_list (struct widget *self)
|
||||||
{
|
{
|
||||||
LIST_FOR_EACH (struct widget, w, self->on_sublayout (self))
|
LIST_FOR_EACH (struct widget, w, self->children)
|
||||||
{
|
|
||||||
w->on_render (w);
|
w->on_render (w);
|
||||||
free (w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct widget *
|
static struct widget *
|
||||||
@ -5708,7 +5722,6 @@ tui_make_list (void)
|
|||||||
w->width = -1;
|
w->width = -1;
|
||||||
w->height = g.active_tab->item_count;
|
w->height = g.active_tab->item_count;
|
||||||
w->on_render = tui_render_list;
|
w->on_render = tui_render_list;
|
||||||
w->on_sublayout = app_sublayout_list;
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6478,11 +6491,8 @@ x11_render_list (struct widget *self)
|
|||||||
&(XRectangle) { self->x, self->y, self->width, self->height }, 1);
|
&(XRectangle) { self->x, self->y, self->width, self->height }, 1);
|
||||||
|
|
||||||
x11_render_padding (self);
|
x11_render_padding (self);
|
||||||
LIST_FOR_EACH (struct widget, w, self->on_sublayout (self))
|
LIST_FOR_EACH (struct widget, w, self->children)
|
||||||
{
|
|
||||||
w->on_render (w);
|
w->on_render (w);
|
||||||
free (w);
|
|
||||||
}
|
|
||||||
|
|
||||||
XftDrawSetClip (g.xft_draw, None);
|
XftDrawSetClip (g.xft_draw, None);
|
||||||
}
|
}
|
||||||
@ -6492,7 +6502,6 @@ x11_make_list (void)
|
|||||||
{
|
{
|
||||||
struct widget *w = xcalloc (1, sizeof *w + 1);
|
struct widget *w = xcalloc (1, sizeof *w + 1);
|
||||||
w->on_render = x11_render_list;
|
w->on_render = x11_render_list;
|
||||||
w->on_sublayout = app_sublayout_list;
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6770,15 +6779,9 @@ x11_find_text (struct widget *list, int x, int y)
|
|||||||
if (!target)
|
if (!target)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (target->on_sublayout)
|
char *result = x11_find_text (target->children, x, y);
|
||||||
{
|
if (result)
|
||||||
struct widget *sublist = target->on_sublayout (target);
|
return result;
|
||||||
char *result = x11_find_text (sublist, x, y);
|
|
||||||
LIST_FOR_EACH (struct widget, w, sublist)
|
|
||||||
free (w);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return xstrdup (target->text);
|
return xstrdup (target->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user