Hi,
modal browsing hasn't been first class citizen in surf. but given the
recent activity in adding features and webkit2 may be there is a
slightly better chance now.
attached is another rewrite of the modal browsing patch.
I find particularly appealing the fact that when implemented in the
browser code, it is independent of the JS loading policy. (AFAIR there
are alternative implementations as plug-ins which can be adapted and used
in .surf/script.js.)
what the patch provides:
- command line switch to enable modes
- the default behaviour is unchanged
- when enabled, modes resemble 2 vi inspired modes: "insert mode" and "normal
mode"
- insert mode is equivalent to the default behaviour
- in normal mode, the MODKEY is assumed pressed, i.e. the bindings are
active without pressing MODKEY.
in addition:
- the patch shifts around some default bindings in config.def.h to make
the new functionality more consistent.
cheers
--s
>From 043bdf0730f9acc6044b1876155a4b42563852e6 Mon Sep 17 00:00:00 2001
From: ssd <[email protected]>
Date: Sun, 3 Sep 2017 01:30:18 +0200
Subject: [surf] optional modal browsing
To: [email protected]
---
config.def.h | 14 +++++++----
surf.c | 76 ++++++++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/config.def.h b/config.def.h
index 2e735bf..51c09a0 100644
--- a/config.def.h
+++ b/config.def.h
@@ -6,6 +6,8 @@ static char *styledir = "~/.surf/styles/";
static char *certdir = "~/.surf/certificates/";
static char *cachedir = "~/.surf/cache/";
static char *cookiefile = "~/.surf/cookies.txt";
+static int modal = 0;
+static int insert_mode = 1;
/* Webkit default features */
/* Highest priority value will be used.
@@ -129,18 +131,20 @@ static SiteSpecific certs[] = {
*/
static Key keys[] = {
/* modifier keyval function arg */
+ { 0, GDK_KEY_i, insertmode, { .b = 1 } },
+ { 0, GDK_KEY_Escape, insertmode, { .b = 0 } },
{ MODKEY, GDK_KEY_g, spawn, SETPROP("_SURF_URI", "_SURF_GO", PROMPT_GO) },
{ MODKEY, GDK_KEY_f, spawn, SETPROP("_SURF_FIND", "_SURF_FIND", PROMPT_FIND) },
{ MODKEY, GDK_KEY_slash, spawn, SETPROP("_SURF_FIND", "_SURF_FIND", PROMPT_FIND) },
- { 0, GDK_KEY_Escape, stop, { 0 } },
+ { 0|GDK_SHIFT_MASK, GDK_KEY_Escape, stop, { 0 } },
{ MODKEY, GDK_KEY_c, stop, { 0 } },
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_r, reload, { .i = 1 } },
{ MODKEY, GDK_KEY_r, reload, { .i = 0 } },
- { MODKEY, GDK_KEY_l, navigate, { .i = +1 } },
- { MODKEY, GDK_KEY_h, navigate, { .i = -1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_l, navigate, { .i = +1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_h, navigate, { .i = -1 } },
/* Currently we have to use scrolling steps that WebKit2GTK+ gives us
* d: step down, u: step up, r: step right, l:step left
@@ -149,8 +153,8 @@ static Key keys[] = {
{ MODKEY, GDK_KEY_k, scroll, { .i = 'u' } },
{ MODKEY, GDK_KEY_b, scroll, { .i = 'U' } },
{ MODKEY, GDK_KEY_space, scroll, { .i = 'D' } },
- { MODKEY, GDK_KEY_i, scroll, { .i = 'r' } },
- { MODKEY, GDK_KEY_u, scroll, { .i = 'l' } },
+ { MODKEY, GDK_KEY_l, scroll, { .i = 'r' } },
+ { MODKEY, GDK_KEY_h, scroll, { .i = 'l' } },
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_j, zoom, { .i = -1 } },
diff --git a/surf.c b/surf.c
index 0f8b9c9..201d91f 100644
--- a/surf.c
+++ b/surf.c
@@ -222,6 +222,7 @@ static void togglefullscreen(Client *c, const Arg *a);
static void togglecookiepolicy(Client *c, const Arg *a);
static void toggleinspector(Client *c, const Arg *a);
static void find(Client *c, const Arg *a);
+static void insertmode(Client *c, const Arg *a);
/* Buttons */
static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h);
@@ -294,7 +295,7 @@ static ParamName loadfinished[] = {
void
usage(void)
{
- die("usage: surf [-bBdDfFgGiIkKmMnNpPsStTvwxX]\n"
+ die("usage: surf [-bBdDfFgGiIkKmMnNpPsStTvVwxX]\n"
"[-a cookiepolicies ] [-c cookiefile] [-C stylefile] [-e xid]\n"
"[-r scriptfile] [-u useragent] [-z zoomlevel] [uri]\n");
}
@@ -597,17 +598,18 @@ updatetitle(Client *c)
char *title;
const char *name = c->overtitle ? c->overtitle :
c->title ? c->title : "";
+ const char *mode = modal ? (insert_mode ? "+" : "_") : " ";
if (curconfig[ShowIndicators].val.i) {
gettogglestats(c);
getpagestats(c);
if (c->progress != 100)
- title = g_strdup_printf("[%i%%] %s:%s | %s",
- c->progress, togglestats, pagestats, name);
+ title = g_strdup_printf("[%i%%] %s%s:%s | %s",
+ c->progress, mode, togglestats, pagestats, name);
else
- title = g_strdup_printf("%s:%s | %s",
- togglestats, pagestats, name);
+ title = g_strdup_printf("%s%s:%s | %s",
+ mode, togglestats, pagestats, name);
gtk_window_set_title(GTK_WINDOW(c->win), title);
g_free(title);
@@ -903,9 +905,9 @@ setstyle(Client *c, const char *file)
webkit_user_content_manager_add_style_sheet(
webkit_web_view_get_user_content_manager(c->view),
webkit_user_style_sheet_new(style,
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
- WEBKIT_USER_STYLE_LEVEL_USER,
- NULL, NULL));
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
+ WEBKIT_USER_STYLE_LEVEL_USER,
+ NULL, NULL));
g_free(style);
}
@@ -1249,6 +1251,45 @@ processx(GdkXEvent *e, GdkEvent *event, gpointer d)
return GDK_FILTER_CONTINUE;
}
+void
+insertmode(Client *c, const Arg *a)
+{
+ if (modal) {
+ insert_mode = (a->i);
+ updatetitle(c);
+ }
+}
+
+gboolean
+processkeypress(GdkEvent *e, Client *c)
+{
+ int i, statematches, isstartinsert, keymatches;
+ guint simulatemod, ismodbinding;
+
+ for (i = 0; i < LENGTH(keys); ++i) {
+ /* if not in insert mode, pretend MODKEY was pressed */
+ ismodbinding = (MODKEY & keys[i].mod);
+ simulatemod = (!insert_mode && ismodbinding) ? MODKEY : 0;
+ statematches = keys[i].mod == (e->key.state | simulatemod);
+
+ keymatches = gdk_keyval_to_lower(e->key.keyval)
+ == gdk_keyval_to_lower(keys[i].keyval);
+
+ if (keymatches && statematches && keys[i].func) {
+ updatewinid(c);
+
+ /* ignore starting insert mode if already in */
+ isstartinsert = (keys[i].func == insertmode)
+ && (keys[i].arg.i == 1);
+ if (insert_mode && isstartinsert) return FALSE;
+
+ keys[i].func(c, &(keys[i].arg));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
gboolean
winevent(GtkWidget *w, GdkEvent *e, Client *c)
{
@@ -1260,18 +1301,9 @@ winevent(GtkWidget *w, GdkEvent *e, Client *c)
updatetitle(c);
break;
case GDK_KEY_PRESS:
- if (!curconfig[KioskMode].val.i) {
- for (i = 0; i < LENGTH(keys); ++i) {
- if (gdk_keyval_to_lower(e->key.keyval) ==
- keys[i].keyval &&
- CLEANMASK(e->key.state) == keys[i].mod &&
- keys[i].func) {
- updatewinid(c);
- keys[i].func(c, &(keys[i].arg));
- return TRUE;
- }
- }
- }
+ if (!curconfig[KioskMode].val.i)
+ if (processkeypress(e, c)) return TRUE;
+ break;
case GDK_LEAVE_NOTIFY:
c->overtitle = NULL;
updatetitle(c);
@@ -2012,6 +2044,10 @@ main(int argc, char *argv[])
break;
case 'v':
die("surf-"VERSION", see LICENSE for © details\n");
+ case 'V':
+ modal = 1;
+ insert_mode = 0;
+ break;
case 'w':
showxid = 1;
break;
--
2.13.2