GTK: Add a location focus state machine

Because the initial navigation process on new browser window
creation is somewhat complex, we need a small state machine in
the GTK UI to ensure that we handle the correct combination
of focussing needed to maintain selection through initial tab
opening.

Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
This commit is contained in:
Daniel Silverstone 2020-02-22 15:33:17 +00:00
parent 5239163f4d
commit a016445a82
No known key found for this signature in database
GPG Key ID: C30DF439F2987D74
3 changed files with 73 additions and 3 deletions

View File

@ -144,6 +144,25 @@ struct nsgtk_toolbar_item {
void *dataminus;
};
/**
* Location focus state machine
*
* 1. If we don't care, we're in LFS_IDLE
* 2. When we create a new toolbar, we can put it into
* LFS_WANT which means that we want the url bar to focus
* 3. When we start throbbing if we're in LFS_WANT we move to LFS_THROB
* 4. When we stop throbbing, if we're in LFS_THROB we move to LFS_LAST
*
* While not in LFS_IDLE, if the url bar is updated and we previously had it
* fully selected then we reselect it all. If we're in LFS_LAST we move to
* LFS_IDLE at that point.
*/
typedef enum {
LFS_IDLE, /**< Nothing to do */
LFS_WANT, /**< Want focus, will apply */
LFS_THROB, /**< Want focus, we have started throbbing */
LFS_LAST, /**< Last chance for a focus update */
} nsgtk_toolbar_location_focus_state;
/**
* control toolbar context
@ -182,6 +201,11 @@ struct nsgtk_toolbar {
* context passed to get_bw function
*/
void *get_ctx;
/**
* Location focus state machine, current state
*/
nsgtk_toolbar_location_focus_state loc_focus;
};
@ -3416,6 +3440,7 @@ nserror
nsgtk_toolbar_create(GtkBuilder *builder,
struct browser_window *(*get_bw)(void *ctx),
void *get_ctx,
bool want_location_focus,
struct nsgtk_toolbar **tb_out)
{
nserror res;
@ -3431,6 +3456,11 @@ nsgtk_toolbar_create(GtkBuilder *builder,
tb->get_ctx = get_ctx;
/* set the throbber start frame. */
tb->throb_frame = 0;
if (want_location_focus) {
tb->loc_focus = LFS_WANT;
} else {
tb->loc_focus = LFS_IDLE;
}
tb->widget = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
gtk_toolbar_set_show_arrow(tb->widget, TRUE);
@ -3515,6 +3545,24 @@ nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active)
nserror res;
struct browser_window *bw;
/* Manage the location focus state */
switch (tb->loc_focus) {
case LFS_IDLE:
break;
case LFS_WANT:
if (active) {
tb->loc_focus = LFS_THROB;
}
break;
case LFS_THROB:
if (!active) {
tb->loc_focus = LFS_LAST;
}
break;
case LFS_LAST:
break;
}
/* when activating the throbber simply schedule the next frame update */
if (active) {
nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, tb);
@ -3627,7 +3675,23 @@ nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url)
url_text = nsurl_access(url);
}
gtk_entry_set_text(url_entry, url_text);
if (strcmp(url_text, gtk_entry_get_text(url_entry)) != 0) {
/* The URL bar content has changed, we need to update it */
gint startpos, endpos;
bool was_selected;
gtk_editable_get_selection_bounds(GTK_EDITABLE(url_entry),
&startpos, &endpos);
was_selected = gtk_widget_is_focus(GTK_WIDGET(url_entry)) &&
startpos == 0 &&
endpos == gtk_entry_get_text_length(url_entry);
gtk_entry_set_text(url_entry, url_text);
if (was_selected && tb->loc_focus != LFS_IDLE) {
gtk_widget_grab_focus(GTK_WIDGET(url_entry));
if (tb->loc_focus == LFS_LAST) {
tb->loc_focus = LFS_IDLE;
}
}
}
if (idn_url_s != NULL) {
free(idn_url_s);

View File

@ -32,7 +32,11 @@ struct nsgtk_scaffolding;
* \param[out] toolbar a pointer to receive the result.
* \return NSERROR_OK and toolbar updated on success else error code
*/
nserror nsgtk_toolbar_create(GtkBuilder *builder, struct browser_window *(*get_bw)(void *ctx), void *get_bw_ctx,struct nsgtk_toolbar **toolbar);
nserror nsgtk_toolbar_create(GtkBuilder *builder,
struct browser_window *(*get_bw)(void *ctx),
void *get_bw_ctx,
bool want_location_focus,
struct nsgtk_toolbar **toolbar);
/**

View File

@ -862,7 +862,9 @@ gui_window_create(struct browser_window *bw,
/* create toolbar */
res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g, &g->toolbar);
res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g,
!!(flags & GW_CREATE_FOCUS_LOCATION),
&g->toolbar);
if (res != NSERROR_OK) {
free(g);
g_object_unref(tab_builder);