Ticket #3700: fix segfault after switch left panel to info mode.

(widget_replace): if new widget cannot take focus, move focus to other widget
before widget replacement.

In our case, the focused file panel is replaced by Info one. Info panel
a) isn't selectable (it never takes focus) and b) uses CWD of current
panel. Therefore focus must be moved to other file panel to make it
current and correctly set up it's CWD before first draw of Info panel.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2016-10-11 10:42:44 +03:00
parent 755447b96e
commit 716479ba4f

View File

@ -419,6 +419,7 @@ widget_replace (Widget * old_w, Widget * new_w)
{ {
WDialog *h = old_w->owner; WDialog *h = old_w->owner;
gboolean should_focus = FALSE; gboolean should_focus = FALSE;
GList *holder;
if (h->widgets == NULL) if (h->widgets == NULL)
return; return;
@ -426,25 +427,43 @@ widget_replace (Widget * old_w, Widget * new_w)
if (h->current == NULL) if (h->current == NULL)
h->current = h->widgets; h->current = h->widgets;
/* locate widget position in the list */
if (old_w == h->current->data) if (old_w == h->current->data)
should_focus = TRUE; holder = h->current;
else
holder = g_list_find (h->widgets, old_w);
/* if old widget is focused, we should focus the new one... */
if (widget_get_state (old_w, WST_FOCUSED))
should_focus = TRUE;
/* ...but if new widget isn't selectable, we cannot focus it */
if (!widget_get_options (new_w, WOP_SELECTABLE))
should_focus = FALSE;
/* if new widget isn't selectable, select other widget before replace */
if (!should_focus)
{
GList *l;
for (l = dlg_get_widget_next_of (holder);
!widget_get_options (WIDGET (l->data), WOP_SELECTABLE)
&& !widget_get_state (WIDGET (l->data), WST_DISABLED); l = dlg_get_widget_next_of (l))
;
widget_select (WIDGET (l->data));
}
/* replace widget */
new_w->owner = h; new_w->owner = h;
new_w->id = old_w->id; new_w->id = old_w->id;
holder->data = new_w;
if (should_focus)
h->current->data = new_w;
else
g_list_find (h->widgets, old_w)->data = new_w;
send_message (old_w, NULL, MSG_DESTROY, 0, NULL); send_message (old_w, NULL, MSG_DESTROY, 0, NULL);
send_message (new_w, NULL, MSG_INIT, 0, NULL); send_message (new_w, NULL, MSG_INIT, 0, NULL);
if (should_focus) if (should_focus)
widget_select (new_w); widget_select (new_w);
else
/* draw inactive widget */
if (!widget_get_state (new_w, WST_FOCUSED))
widget_redraw (new_w); widget_redraw (new_w);
} }