Skip to content

Commit 867bdea

Browse files
committed
Ensure that the widget in focus is visible
Signed-off-by: Alexey Gladkov <legion@kernel.org>
1 parent 74b900d commit 867bdea

3 files changed

Lines changed: 62 additions & 15 deletions

File tree

src/plainmouthd.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,20 @@ static void free_instances(void)
207207
release_instance(TAILQ_FIRST(&instances));
208208
}
209209

210+
static void widget_ensure_visible(struct widget *w)
211+
{
212+
struct widget *child = w;
213+
struct widget *cur = w->parent;
214+
215+
while (cur) {
216+
if (cur->ensure_visible)
217+
cur->ensure_visible(cur, child);
218+
219+
child = cur;
220+
cur = cur->parent;
221+
}
222+
}
223+
210224
static inline void ui_wakeup(void)
211225
{
212226
uint64_t one = 1;
@@ -317,21 +331,23 @@ static void ui_focused(bool state)
317331
if (!focused)
318332
return;
319333

320-
if (state)
334+
if (state) {
321335
focused->flags |= FLAG_INFOCUS;
322-
else
323-
focused->flags &= ~FLAG_INFOCUS;
324336

325-
widget_render_tree(focused);
337+
widget_ensure_visible(focused);
326338

327-
if (state) {
328339
/*
329340
* This is necessary to ensure that the panel with the widget
330341
* in focus is on top of everything else.
331342
*/
332343
struct instance *ins = find_instance(focused->instance_id);
333-
top_panel(ins->panel);
344+
if (ins)
345+
top_panel(ins->panel);
346+
} else {
347+
focused->flags &= ~FLAG_INFOCUS;
334348
}
349+
350+
widget_render_tree(focused);
335351
}
336352

337353
static void ui_next_focused(void)

src/widget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ struct widget {
184184
void (*free_data)(struct widget *); /* Free widget-specific data */
185185
int (*input)(const struct widget *, wchar_t); /* Handle keyboard input */
186186

187+
void (*ensure_visible)(struct widget *, struct widget *);
188+
187189
bool (*setter)(struct widget *, enum widget_property, const void *);
188190
bool (*getter)(struct widget *, enum widget_property, void *);
189191
bool (*getter_index)(struct widget *, enum widget_property, int, void *);

src/widget_scroll_vbox.c

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,34 @@ static int scroll_vbox_input(const struct widget *w, wchar_t key)
165165
return 1;
166166
}
167167

168+
static void scroll_vbox_ensure_visible(struct widget *container, struct widget *child)
169+
{
170+
struct widget_svbox *state = container->state.svbox;
171+
172+
if (!state)
173+
return;
174+
175+
int child_y = child->ly;
176+
int child_h = child->h;
177+
178+
int view_top = state->scroll;
179+
int view_bot = state->scroll + container->h;
180+
181+
if (child_y < view_top) {
182+
state->scroll = child_y;
183+
} else if (child_y + child_h > view_bot) {
184+
state->scroll = child_y + child_h - container->h;
185+
}
186+
187+
if (state->scroll < 0)
188+
state->scroll = 0;
189+
190+
int max_scroll = state->content_h - container->h;
191+
192+
if (state->scroll > max_scroll)
193+
state->scroll = max_scroll;
194+
}
195+
168196
static void scroll_vbox_freedata(struct widget *w)
169197
{
170198
struct widget_svbox *state = w->state.svbox;
@@ -187,15 +215,16 @@ struct widget *make_scroll_vbox(void)
187215
return NULL;
188216
}
189217

190-
w->state.svbox = state;
191-
w->measure = scroll_vbox_measure;
192-
w->layout = scroll_vbox_layout;
193-
w->render = scroll_vbox_render;
194-
w->create_win = scroll_vbox_createwin;
195-
w->noutrefresh = scroll_vbox_refresh;
196-
w->input = scroll_vbox_input;
197-
w->free_data = scroll_vbox_freedata;
198-
w->color_pair = COLOR_PAIR_WINDOW;
218+
w->state.svbox = state;
219+
w->measure = scroll_vbox_measure;
220+
w->layout = scroll_vbox_layout;
221+
w->render = scroll_vbox_render;
222+
w->create_win = scroll_vbox_createwin;
223+
w->noutrefresh = scroll_vbox_refresh;
224+
w->input = scroll_vbox_input;
225+
w->free_data = scroll_vbox_freedata;
226+
w->ensure_visible = scroll_vbox_ensure_visible;
227+
w->color_pair = COLOR_PAIR_WINDOW;
199228

200229
w->stretch_w = true;
201230
w->stretch_h = true;

0 commit comments

Comments
 (0)