commit - 4010e238a0826aba0cbc42d3a0a175d1edb4c547
commit + e78dc838220282917888618e9c7be69df3cb3ccf
blob - f3eeaf4b50fe79efeb2540158e9b5c58b40e3a7c
blob + 6401176dab6442e465071e514cd02d4dc8f24d8b
--- tog/tog.c
+++ tog/tog.c
/*
* We implement two types of views: parent views and child views.
*
- * The 'Tab' key switches between a parent view and its child view.
+ * The 'Tab' key switches focus between a parent view and its child view.
* Child views are shown side-by-side to their parent view, provided
* there is enough screen estate.
*
PANEL *panel;
int nlines, ncols, begin_y, begin_x;
int lines, cols; /* copies of LINES and COLS */
- int focussed;
+ int focussed; /* Only set on one parent or child view at a time. */
int dying;
struct tog_view *parent;
struct tog_view *child;
+ /*
+ * This flag is initially set on parent views when a new child view
+ * is created. It gets toggled when the 'Tab' key switches focus
+ * between parent and child.
+ * The flag indicates whether focus should be passed on to our child
+ * view if this parent view gets picked for focus after another parent
+ * view was closed. This prevents child views from losing focus in such
+ * situations.
+ */
+ int focus_child;
+
/* type-specific state */
enum tog_view_type type;
union {
const struct got_error *(*show)(struct tog_view *);
const struct got_error *(*input)(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
const struct got_error *(*close)(struct tog_view *);
const struct got_error *(*search_start)(struct tog_view *);
struct got_repository *);
static const struct got_error *show_diff_view(struct tog_view *);
static const struct got_error *input_diff_view(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
static const struct got_error* close_diff_view(struct tog_view *);
static const struct got_error *search_start_diff_view(struct tog_view *);
static const struct got_error *search_next_diff_view(struct tog_view *);
const char *, const char *, int);
static const struct got_error * show_log_view(struct tog_view *);
static const struct got_error *input_log_view(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
static const struct got_error *close_log_view(struct tog_view *);
static const struct got_error *search_start_log_view(struct tog_view *);
static const struct got_error *search_next_log_view(struct tog_view *);
struct got_object_id *, struct got_repository *);
static const struct got_error *show_blame_view(struct tog_view *);
static const struct got_error *input_blame_view(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
static const struct got_error *close_blame_view(struct tog_view *);
static const struct got_error *search_start_blame_view(struct tog_view *);
static const struct got_error *search_next_blame_view(struct tog_view *);
struct got_tree_object *, struct got_object_id *, struct got_repository *);
static const struct got_error *show_tree_view(struct tog_view *);
static const struct got_error *input_tree_view(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
static const struct got_error *close_tree_view(struct tog_view *);
static const struct got_error *search_start_tree_view(struct tog_view *);
static const struct got_error *search_next_tree_view(struct tog_view *);
struct got_repository *);
static const struct got_error *show_ref_view(struct tog_view *);
static const struct got_error *input_ref_view(struct tog_view **,
- struct tog_view **, struct tog_view *, int);
+ struct tog_view *, int);
static const struct got_error *close_ref_view(struct tog_view *);
static const struct got_error *search_start_ref_view(struct tog_view *);
static const struct got_error *search_next_ref_view(struct tog_view *);
}
static const struct got_error *
-view_input(struct tog_view **new, struct tog_view **focus, int *done,
- struct tog_view *view, struct tog_view_list_head *views)
+view_input(struct tog_view **new, int *done, struct tog_view *view,
+ struct tog_view_list_head *views)
{
const struct got_error *err = NULL;
struct tog_view *v;
int ch, errcode;
*new = NULL;
- *focus = NULL;
/* Clear "no matches" indicator. */
if (view->search_next_done == TOG_SEARCH_NO_MORE ||
err = view_resize(v);
if (err)
return err;
- err = v->input(new, focus, v, KEY_RESIZE);
+ err = v->input(new, v, KEY_RESIZE);
if (err)
return err;
}
break;
case '\t':
if (view->child) {
- *focus = view->child;
+ view->focussed = 0;
+ view->child->focussed = 1;
+ view->focus_child = 1;
} else if (view->parent) {
- *focus = view->parent;
+ view->focussed = 0;
+ view->parent->focussed = 1;
+ view->parent->focus_child = 0;
}
break;
case 'q':
- err = view->input(new, focus, view, ch);
+ err = view->input(new, view, ch);
view->dying = 1;
break;
case 'Q':
if (view->child == NULL)
break;
if (view_is_splitscreen(view->child)) {
- *focus = view->child;
+ view->focussed = 0;
+ view->child->focussed = 1;
err = view_fullscreen(view->child);
} else
err = view_splitscreen(view->child);
if (err)
break;
- err = view->child->input(new, focus, view->child,
+ err = view->child->input(new, view->child,
KEY_RESIZE);
} else {
if (view_is_splitscreen(view)) {
- *focus = view;
+ view->parent->focussed = 0;
+ view->focussed = 1;
err = view_fullscreen(view);
} else {
err = view_splitscreen(view);
}
if (err)
break;
- err = view->input(new, focus, view, KEY_RESIZE);
+ err = view->input(new, view, KEY_RESIZE);
}
break;
case KEY_RESIZE:
if (view->search_start)
view_search_start(view);
else
- err = view->input(new, focus, view, ch);
+ err = view->input(new, view, ch);
break;
case 'N':
case 'n':
view->search_next_done = 0;
view->search_next(view);
} else
- err = view->input(new, focus, view, ch);
+ err = view->input(new, view, ch);
break;
default:
- err = view->input(new, focus, view, ch);
+ err = view->input(new, view, ch);
break;
}
{
const struct got_error *err = NULL;
struct tog_view_list_head views;
- struct tog_view *new_view, *focus_view, *main_view;
+ struct tog_view *new_view, *main_view;
int fast_refresh = 10;
int done = 0, errcode;
if (fast_refresh && fast_refresh-- == 0)
halfdelay(10); /* switch to once per second */
- err = view_input(&new_view, &focus_view, &done, view, &views);
+ err = view_input(&new_view, &done, view, &views);
if (err)
break;
if (view->dying) {
- struct tog_view *prev = NULL;
+ struct tog_view *v, *prev = NULL;
if (view_is_parent_view(view))
prev = TAILQ_PREV(view, tog_view_list_head,
entry);
- else if (view->parent != view)
+ else if (view->parent)
prev = view->parent;
- if (view->parent)
+ if (view->parent) {
view->parent->child = NULL;
- else
+ view->parent->focus_child = 0;
+ } else
TAILQ_REMOVE(&views, view, entry);
err = view_close(view);
if (err || (view == main_view && new_view == NULL))
goto done;
- if (focus_view)
- view = focus_view;
- else if (prev)
- view = prev;
- else if (!TAILQ_EMPTY(&views))
- view = TAILQ_LAST(&views,
- tog_view_list_head);
- else
- view = NULL;
- if (view) {
- if (view->child &&
- view->child->focussed)
- focus_view = view->child;
- else
- focus_view = view;
+ view = NULL;
+ TAILQ_FOREACH(v, &views, entry) {
+ if (v->focussed)
+ break;
}
+ if (view == NULL && new_view == NULL) {
+ /* No view has focus. Try to pick one. */
+ if (prev)
+ view = prev;
+ else if (!TAILQ_EMPTY(&views)) {
+ view = TAILQ_LAST(&views,
+ tog_view_list_head);
+ }
+ if (view) {
+ if (view->focus_child) {
+ view->child->focussed = 1;
+ view = view->child;
+ } else
+ view->focussed = 1;
+ }
+ }
}
if (new_view) {
struct tog_view *v, *t;
}
TAILQ_INSERT_TAIL(&views, new_view, entry);
view = new_view;
- if (focus_view == NULL)
- focus_view = new_view;
- }
- if (focus_view) {
- show_panel(focus_view->panel);
- if (view)
- view->focussed = 0;
- focus_view->focussed = 1;
- view = focus_view;
- if (new_view)
- show_panel(new_view->panel);
- if (view->child && view_is_splitscreen(view->child))
- show_panel(view->child->panel);
- }
+ }
if (view) {
- if (focus_view == NULL) {
- view->focussed = 1;
- show_panel(view->panel);
- if (view->child && view_is_splitscreen(view->child))
- show_panel(view->child->panel);
- focus_view = view;
+ if (view_is_parent_view(view)) {
+ if (view->child && view->child->focussed)
+ view = view->child;
+ } else {
+ if (view->parent && view->parent->focussed)
+ view = view->parent;
}
- if (view->parent) {
+ show_panel(view->panel);
+ if (view->child && view_is_splitscreen(view->child))
+ show_panel(view->child->panel);
+ if (view->parent && view_is_splitscreen(view)) {
err = view->parent->show(view->parent);
if (err)
goto done;
if (s->matched_entry) {
int cur = s->selected_entry->idx;
while (cur < s->matched_entry->idx) {
- err = input_log_view(NULL, NULL, view, KEY_DOWN);
+ err = input_log_view(NULL, view, KEY_DOWN);
if (err)
return err;
cur++;
}
while (cur > s->matched_entry->idx) {
- err = input_log_view(NULL, NULL, view, KEY_UP);
+ err = input_log_view(NULL, view, KEY_UP);
if (err)
return err;
cur--;
}
static const struct got_error *
-input_log_view(struct tog_view **new_view, struct tog_view **focus_view,
- struct tog_view *view, int ch)
+input_log_view(struct tog_view **new_view, struct tog_view *view, int ch)
{
const struct got_error *err = NULL;
struct tog_log_view_state *s = &view->state.log;
view, s->repo);
if (err)
break;
+ view->focussed = 0;
+ diff_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, diff_view);
- *focus_view = diff_view;
+ view->focus_child = 1;
} else
*new_view = diff_view;
break;
s->selected_entry, s->in_repo_path, s->repo);
if (err)
break;
+ view->focussed = 0;
+ tree_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, tree_view);
- *focus_view = tree_view;
+ view->focus_child = 1;
} else
*new_view = tree_view;
break;
free(parent_path);
if (err)
return err;;
+ view->focussed = 0;
+ lv->focussed = 1;
if (view_is_parent_view(view))
*new_view = lv;
- else {
+ else
view_set_child(view->parent, lv);
- *focus_view = lv;
- }
break;
case CTRL('l'):
err = stop_log_thread(s);
view_close(ref_view);
return err;
}
+ view->focussed = 0;
+ ref_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, ref_view);
- *focus_view = ref_view;
+ view->focus_child = 1;
} else
*new_view = ref_view;
break;
}
static const struct got_error *
-input_diff_view(struct tog_view **new_view, struct tog_view **focus_view,
- struct tog_view *view, int ch)
+input_diff_view(struct tog_view **new_view, struct tog_view *view, int ch)
{
const struct got_error *err = NULL;
struct tog_diff_view_state *s = &view->state.diff;
if (entry == NULL)
break;
- err = input_log_view(NULL, NULL, s->log_view, KEY_UP);
+ err = input_log_view(NULL, s->log_view, KEY_UP);
if (err)
break;
if (err)
break;
}
- err = input_log_view(NULL, NULL, s->log_view, KEY_DOWN);
+ err = input_log_view(NULL, s->log_view, KEY_DOWN);
if (err)
break;
}
static const struct got_error *
-input_blame_view(struct tog_view **new_view, struct tog_view **focus_view,
- struct tog_view *view, int ch)
+input_blame_view(struct tog_view **new_view, struct tog_view *view, int ch)
{
const struct got_error *err = NULL, *thread_err = NULL;
struct tog_view *diff_view;
view_close(diff_view);
break;
}
+ view->focussed = 0;
+ diff_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
break;
view_set_child(view, diff_view);
- *focus_view = diff_view;
+ view->focus_child = 1;
} else
*new_view = diff_view;
if (err)
}
static const struct got_error *
-input_tree_view(struct tog_view **new_view, struct tog_view **focus_view,
- struct tog_view *view, int ch)
+input_tree_view(struct tog_view **new_view, struct tog_view *view, int ch)
{
const struct got_error *err = NULL;
struct tog_tree_view_state *s = &view->state.tree;
begin_x = view_split_begin_x(view->begin_x);
err = log_tree_entry(&log_view, begin_x, s->selected_entry,
&s->parents, s->commit_id, s->repo);
+ view->focussed = 0;
+ log_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, log_view);
- *focus_view = log_view;
+ view->focus_child = 1;
} else
*new_view = log_view;
break;
view_close(ref_view);
return err;
}
+ view->focussed = 0;
+ ref_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, ref_view);
- *focus_view = ref_view;
+ view->focus_child = 1;
} else
*new_view = ref_view;
break;
s->commit_id, s->repo);
if (err)
break;
+ view->focussed = 0;
+ blame_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, blame_view);
- *focus_view = blame_view;
+ view->focus_child = 1;
} else
*new_view = blame_view;
}
return err;
}
static const struct got_error *
-input_ref_view(struct tog_view **new_view, struct tog_view **focus_view,
- struct tog_view *view, int ch)
+input_ref_view(struct tog_view **new_view, struct tog_view *view, int ch)
{
const struct got_error *err = NULL;
struct tog_ref_view_state *s = &view->state.ref;
begin_x = view_split_begin_x(view->begin_x);
err = log_ref_entry(&log_view, begin_x, s->selected_entry,
s->repo);
+ view->focussed = 0;
+ log_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, log_view);
- *focus_view = log_view;
+ view->focus_child = 1;
} else
*new_view = log_view;
break;
s->repo);
if (err || tree_view == NULL)
break;
+ view->focussed = 0;
+ tree_view->focussed = 1;
if (view_is_parent_view(view)) {
err = view_close_child(view);
if (err)
return err;
view_set_child(view, tree_view);
- *focus_view = tree_view;
+ view->focus_child = 1;
} else
*new_view = tree_view;
break;