Added command for scrolling.
authorDaniel Carl <danielcarl@gmx.de>
Wed, 3 Oct 2012 17:37:34 +0000 (19:37 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Wed, 3 Oct 2012 20:07:19 +0000 (22:07 +0200)
src/command.c
src/config.h
src/keybind.c
src/main.c
src/main.h

index 3cc923e..4293dba 100644 (file)
@@ -5,11 +5,23 @@ static CommandInfo cmd_list[] = {
     /* command          function          arg */
     {"quit",            vp_close_browser, {0}},
     {"source",          vp_view_source,   {0}},
-    {"back",            vp_navigate,      {NAVIG_BACK}},
-    {"forward",         vp_navigate,      {NAVIG_FORWARD}},
-    {"reload",          vp_navigate,      {NAVIG_RELOAD}},
-    {"reload!",         vp_navigate,      {NAVIG_RELOAD_FORCE}},
-    {"stop",            vp_navigate,      {NAVIG_STOP_LOADING}},
+    {"back",            vp_navigate,      {VP_NAVIG_BACK}},
+    {"forward",         vp_navigate,      {VP_NAVIG_FORWARD}},
+    {"reload",          vp_navigate,      {VP_NAVIG_RELOAD}},
+    {"reload!",         vp_navigate,      {VP_NAVIG_RELOAD_FORCE}},
+    {"stop",            vp_navigate,      {VP_NAVIG_STOP_LOADING}},
+    {"jumpleft",        vp_scroll,        {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_LEFT}},
+    {"jumpright",       vp_scroll,        {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_RIGHT}},
+    {"jumptop",         vp_scroll,        {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_TOP}},
+    {"jumpbottom",      vp_scroll,        {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_DOWN}},
+    {"pageup",          vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_PAGE}},
+    {"pagedown",        vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_PAGE}},
+    {"halfpageup",      vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_HALFPAGE}},
+    {"halfpagedown",    vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_HALFPAGE}},
+    {"scrollleft",      vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_LEFT | VP_SCROLL_UNIT_LINE}},
+    {"scrollright",     vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_RIGHT | VP_SCROLL_UNIT_LINE}},
+    {"scrollup",        vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_LINE}},
+    {"scrolldown",      vp_scroll,        {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_LINE}},
 };
 
 void command_init()
index 42e6b51..5af42f6 100644 (file)
@@ -8,4 +8,6 @@
 #define STATUS_BAR_FONT "monospace bold 8"
 #define URL_BOX_FONT    "monospace 8"
 
+#define SCROLLSTEP (40) /* cursor difference in pixel for scrolling */
+
 #endif /* end of include guard: CONFIG_H */
index 4ed31a9..884f725 100644 (file)
@@ -53,8 +53,7 @@ static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* e
             /* switch to normal mode */
             vp.state.mode = VP_MODE_NORMAL;
             /* remove current modkey and set count back to 0 */
-            vp.state.modkey = 0;
-            vp.state.count  = 0;
+            vp.state.modkey = vp.state.count  = 0;
             vp_update_statusbar();
 
             return TRUE;
@@ -77,15 +76,15 @@ static gboolean keybind_keypress_callback(WebKitWebView* webview, GdkEventKey* e
         struct _keybind_key* keybind = (struct _keybind_key*)tmp->data;
 
         /* handle key presses */
-        if (gdk_keyval_to_lower(event->keyval) == keybind->keyval
-            && (event->state & keybind->modmask) == keybind->modmask
+        if (keybind->modmask == (CLEAN(event->state) & ~irrelevant)
             && keybind->modkey == vp.state.modkey
+            && keybind->keyval == keyval
             && keybind->command
         ) {
             command_run(keybind->command);
 
             /* if key binding used, remove the modkey */
-            vp.state.modkey = 0;
+            vp.state.modkey = vp.state.count = 0;
             vp_update_statusbar();
 
             return TRUE;
index 01120b6..6c03424 100644 (file)
@@ -75,22 +75,56 @@ gboolean vp_load_uri(const Arg* arg)
     return TRUE;
 }
 
-void vp_navigate(const Arg *arg)
+void vp_navigate(const Argarg)
 {
-    if (arg->i <= NAVIG_FORWARD) {
+    if (arg->i <= VP_NAVIG_FORWARD) {
         /* TODO allow to set a count for the navigation */
         webkit_web_view_go_back_or_forward(
-            vp.gui.webview, (arg->i == NAVIG_BACK ? -1 : 1)
+            vp.gui.webview, (arg->i == VP_NAVIG_BACK ? -1 : 1)
         );
-    } else if (arg->i == NAVIG_RELOAD) {
+    } else if (arg->i == VP_NAVIG_RELOAD) {
         webkit_web_view_reload(vp.gui.webview);
-    } else if (arg->i == NAVIG_RELOAD_FORCE) {
+    } else if (arg->i == VP_NAVIG_RELOAD_FORCE) {
         webkit_web_view_reload_bypass_cache(vp.gui.webview);
     } else {
         webkit_web_view_stop_loading(vp.gui.webview);
     }
 }
 
+void vp_scroll(const Arg* arg)
+{
+    GtkAdjustment *adjust = (arg->i & VP_SCROLL_AXIS_H) ? vp.gui.adjust_h : vp.gui.adjust_v;
+
+    gint max        = gtk_adjustment_get_upper(adjust) - gtk_adjustment_get_page_size(adjust);
+    gdouble percent = gtk_adjustment_get_value(adjust) / max * 100;
+    gint direction  = (arg->i & (1 << 2)) ? 1 : -1;
+
+    /* skip if no further scrolling is possible */
+    if ((direction == 1 && percent == 100) || (direction == -1 && percent == 0)) {
+        return;
+    }
+    /* type scroll */
+    if (arg->i & VP_SCROLL_TYPE_SCROLL) {
+        gdouble value;
+        gint count = vp.state.count ? vp.state.count : 1;
+        if (arg->i & VP_SCROLL_UNIT_LINE) {
+            value = SCROLLSTEP;
+        } else if (arg->i & VP_SCROLL_UNIT_HALFPAGE) {
+            value = gtk_adjustment_get_page_size(adjust) / 2;
+        } else {
+            value = gtk_adjustment_get_page_size(adjust);
+        }
+
+        gtk_adjustment_set_value(adjust, gtk_adjustment_get_value(adjust) + direction * value * count);
+    } else if (direction == 1) {
+        /* jump to top */
+        gtk_adjustment_set_value(adjust, gtk_adjustment_get_upper(adjust));
+    } else {
+        /* jump to bottom */
+        gtk_adjustment_set_value(adjust, gtk_adjustment_get_lower(adjust));
+    }
+}
+
 void vp_close_browser(const Arg* arg)
 {
     if (vp.behave.commands) {
@@ -121,14 +155,27 @@ void vp_update_statusbar(void)
     GString* status = g_string_new("");
     gchar*   markup;
 
-    /* TODO show modekeys count */
-    /* at the moment we have only one modkey available */
-    /* http://current_uri.tld   34% */
+    /* show current count */
     g_string_append_printf(status, "%.0d", vp.state.count);
+    /* show current modkey */
     if (vp.state.modkey) {
         g_string_append_c(status, vp.state.modkey);
     }
-    g_string_append_printf(status, " %.0d%%", 46);
+
+    /* show the scroll status */
+    gint max = gtk_adjustment_get_upper(vp.gui.adjust_v) - gtk_adjustment_get_page_size(vp.gui.adjust_v);
+    gint val = (int)(gtk_adjustment_get_value(vp.gui.adjust_v) / max * 100);
+
+    if (max == 0) {
+        g_string_append(status, " All");
+    } else if (val == 0) {
+        g_string_append(status, " Top");
+    } else if (val >= 100) {
+        g_string_append(status, " Bot");
+    } else {
+        g_string_append_printf(status, " %d%%", val);
+    }
+
     markup = g_markup_printf_escaped("<span font=\"%s\">%s</span>", STATUS_BAR_FONT, status->str);
     gtk_label_set_markup(GTK_LABEL(vp.gui.statusbar.right), markup);
     g_free(markup);
@@ -148,13 +195,25 @@ static void vp_init(void)
     /* initialize the keybindings */
     keybind_init();
 
-    keybind_add(VP_MODE_NORMAL, GDK_g, 0,                GDK_f, "source");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_d, "quit");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_o, "back");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_i, "forward");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_r, "reload");
-    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_R, "reload!");
-    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_c, "stop");
+    keybind_add(VP_MODE_NORMAL, GDK_g, 0,                GDK_f,      "source");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_d,      "quit");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_o,      "back");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_i,      "forward");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_r,      "reload");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_R,      "reload!");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_c,      "stop");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_f,      "pagedown");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_b,      "pageup");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_d,      "halfpagedown");
+    keybind_add(VP_MODE_NORMAL, 0,     GDK_CONTROL_MASK, GDK_u,      "halfpageup");
+    keybind_add(VP_MODE_NORMAL, GDK_g, 0,                GDK_g,      "jumptop");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_G,      "jumpbottom");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_0,      "jumpleft");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_dollar, "jumpright");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_h,      "scrollleft");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_l,      "scrollright");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_k,      "scrollup");
+    keybind_add(VP_MODE_NORMAL, 0,     0,                GDK_j,      "scrolldown");
 }
 
 static void vp_init_gui(void)
@@ -162,6 +221,11 @@ static void vp_init_gui(void)
     Gui* gui = &vp.gui;
     GdkColor bg, fg;
 
+    gui->sb_h = GTK_SCROLLBAR(gtk_hscrollbar_new(NULL));
+    gui->sb_v = GTK_SCROLLBAR(gtk_vscrollbar_new(NULL));
+    gui->adjust_h = gtk_range_get_adjustment(GTK_RANGE(gui->sb_h));
+    gui->adjust_v = gtk_range_get_adjustment(GTK_RANGE(gui->sb_v));
+
     GdkGeometry hints = {10, 10};
     gui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     gtk_window_set_wmclass(GTK_WINDOW(gui->window), PROJECT, PROJECT);
@@ -173,7 +237,7 @@ static void vp_init_gui(void)
     gui->webview = WEBKIT_WEB_VIEW(webkit_web_view_new());
 
     /* Create a scrollable area */
-    gui->viewport = gtk_scrolled_window_new(NULL, NULL);
+    gui->viewport = gtk_scrolled_window_new(gui->adjust_h, gui->adjust_v);
     gtk_scrolled_window_set_policy(
         GTK_SCROLLED_WINDOW(gui->viewport),
         GTK_POLICY_NEVER, GTK_POLICY_NEVER
index ed3a026..7ce8095 100644 (file)
@@ -32,11 +32,35 @@ typedef enum _vp_mode {
 } Mode;
 
 enum {
-    NAVIG_BACK,
-    NAVIG_FORWARD,
-    NAVIG_RELOAD,
-    NAVIG_RELOAD_FORCE,
-    NAVIG_STOP_LOADING
+    VP_NAVIG_BACK,
+    VP_NAVIG_FORWARD,
+    VP_NAVIG_RELOAD,
+    VP_NAVIG_RELOAD_FORCE,
+    VP_NAVIG_STOP_LOADING
+};
+
+/*
+1 << 0:  0 = jump,              1 = scroll
+1 << 1:  0 = vertical,          1 = horizontal
+1 << 2:  0 = top/left,          1 = down/right
+1 << 3:  0 = paging/halfpage,   1 = line
+1 << 4:  0 = paging,            1 = halfpage
+*/
+enum {VP_SCROLL_TYPE_JUMP, VP_SCROLL_TYPE_SCROLL};
+enum {
+    VP_SCROLL_AXIS_V,
+    VP_SCROLL_AXIS_H = (1 << 1)
+};
+enum {
+    VP_SCROLL_DIRECTION_TOP,
+    VP_SCROLL_DIRECTION_DOWN  = (1 << 2),
+    VP_SCROLL_DIRECTION_LEFT  = VP_SCROLL_AXIS_H,
+    VP_SCROLL_DIRECTION_RIGHT = VP_SCROLL_AXIS_H | (1 << 2)
+};
+enum {
+    VP_SCROLL_UNIT_PAGE,
+    VP_SCROLL_UNIT_LINE     = (1 << 3),
+    VP_SCROLL_UNIT_HALFPAGE = (1 << 4)
 };
 
 /* structs */
@@ -61,6 +85,10 @@ typedef struct {
     GtkWidget*     eventbox;
     GtkWidget*     inputbox;
     StatusBar      statusbar;
+    GtkScrollbar*  sb_h;
+    GtkScrollbar*  sb_v;
+    GtkAdjustment* adjust_h;
+    GtkAdjustment* adjust_v;
 } Gui;
 
 /* state */
@@ -97,6 +125,7 @@ void vp_update_statusbar(void);
 void vp_update_urlbar(const gchar* uri);
 gboolean vp_load_uri(const Arg* arg);
 void vp_navigate(const Arg* arg);
+void vp_scroll(const Arg* arg);
 void vp_close_browser(const Arg* arg);
 void vp_view_source(const Arg* arg);