summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/web-view-schemes/local.mk3
-rw-r--r--src/web-view-schemes/schemes.h13
-rw-r--r--src/web-view-schemes/view-source.c191
3 files changed, 206 insertions, 1 deletions
diff --git a/src/web-view-schemes/local.mk b/src/web-view-schemes/local.mk
index 879ee6f..af53bc1 100644
--- a/src/web-view-schemes/local.mk
+++ b/src/web-view-schemes/local.mk
@@ -1,2 +1,3 @@
marquee_SOURCES += \
- %reldir%/normal.c
+ %reldir%/normal.c \
+ %reldir%/view-source.c
diff --git a/src/web-view-schemes/schemes.h b/src/web-view-schemes/schemes.h
index f3aa7af..7fa8a46 100644
--- a/src/web-view-schemes/schemes.h
+++ b/src/web-view-schemes/schemes.h
@@ -37,6 +37,12 @@ typedef struct {
GFile *save_file;
} MqWebViewNormalScheme;
+typedef struct {
+ gint64 origin_tab_id;
+ guchar *source;
+ gchar *uri;
+} MqWebViewViewSourceScheme;
+
union _MqWebViewScheme {
MqWebViewNormalScheme normal;
};
@@ -51,6 +57,7 @@ typedef struct {
} MqWebViewSchemeMethods;
extern MqWebViewSchemeMethods mq_web_view_normal_scheme_methods;
+extern MqWebViewSchemeMethods mq_web_view_view_source_scheme_methods;
void
mq_web_view_normal_scheme_init(MqWebViewNormalScheme *scheme);
@@ -58,6 +65,12 @@ mq_web_view_normal_scheme_init(MqWebViewNormalScheme *scheme);
void
mq_web_view_normal_scheme_fini(MqWebViewNormalScheme *scheme);
+void
+mq_web_view_view_source_scheme_init(MqWebViewViewSourceScheme *scheme);
+
+void
+mq_web_view_view_source_scheme_fini(MqWebViewViewSourceScheme *scheme);
+
G_END_DECLS
#endif /* MQ_WEB_VIEW_SCHEMES_H */
diff --git a/src/web-view-schemes/view-source.c b/src/web-view-schemes/view-source.c
new file mode 100644
index 0000000..e7a1ecb
--- /dev/null
+++ b/src/web-view-schemes/view-source.c
@@ -0,0 +1,191 @@
+/*
+ * Web view members and methods for "view-source" scheme
+ *
+ * Copyright (C) 2017 Patrick McDermott
+ *
+ * This file is part of Marquee.
+ *
+ * Marquee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Marquee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Marquee. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "schemes.h"
+
+#include <glib.h>
+#include <webkit2/webkit2.h>
+
+#include "../application.h"
+#include "../config.h"
+#include "../notebook.h"
+#include "../tab-page.h"
+#include "../web-view.h"
+
+static gchar *
+rewrite_uri(MqWebViewScheme G_GNUC_UNUSED *scheme, const gchar *uri)
+{
+ return g_strdup(uri);
+}
+
+static gchar *
+display_uri(MqWebViewScheme G_GNUC_UNUSED *scheme, const gchar *uri)
+{
+ return g_strdup(uri);
+}
+
+#define WKCMA(ACTION) \
+ WEBKIT_CONTEXT_MENU_ACTION_##ACTION
+
+#define ITEM_DECLS \
+ GtkAction *action; \
+ WebKitContextMenuItem *menu_item;
+#define ITEM_DECLS_NO_CUSTOM \
+ WebKitContextMenuItem *menu_item;
+#define NEW_CUSTOM_ITEM(NAME, LABEL) \
+ G_STMT_START { \
+ /* Don't blame me; blame WebKitGTK+ for using GtkAction. */ \
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+ action = gtk_action_new(#NAME, (LABEL), NULL, NULL); \
+ G_GNUC_END_IGNORE_DEPRECATIONS \
+ g_signal_connect(action, "activate", \
+ G_CALLBACK(menu_##NAME##_activate_cb), web_view); \
+ menu_item = webkit_context_menu_item_new(action); \
+ webkit_context_menu_append(context_menu, menu_item); \
+ } G_STMT_END
+#define NEW_STOCK_ITEM(STOCK) \
+ G_STMT_START { \
+ menu_item = webkit_context_menu_item_new_from_stock_action( \
+ WEBKIT_CONTEXT_MENU_ACTION_##STOCK); \
+ webkit_context_menu_append(context_menu, menu_item); \
+ } G_STMT_END
+#define NEW_SEPARATOR_ITEM() \
+ G_STMT_START { \
+ webkit_context_menu_append(context_menu, \
+ webkit_context_menu_item_new_separator()); \
+ } G_STMT_END
+#define RESTORE_ITEMS(ITEMS) \
+ G_STMT_START { \
+ for (; ITEMS; ITEMS = ITEMS->next) { \
+ webkit_context_menu_append(context_menu, ITEMS->data); \
+ g_object_unref(ITEMS->data); \
+ } \
+ } G_STMT_END
+
+static void
+context_menu_document_cb(WebKitContextMenu *context_menu, GList *nav_items,
+ MqWebView G_GNUC_UNUSED *web_view)
+{
+ ITEM_DECLS_NO_CUSTOM
+
+ RESTORE_ITEMS(nav_items); /* _Back, _Forward, _Stop, _Reload */
+ NEW_SEPARATOR_ITEM(); /* --- */
+ NEW_STOCK_ITEM(SELECT_ALL); /* Select _All */
+ NEW_SEPARATOR_ITEM(); /* --- */
+}
+
+#define PRESERVE_ITEM(ITEMS) \
+ G_STMT_START { \
+ g_object_ref(items->data); \
+ ITEMS = g_list_prepend(ITEMS, items->data); \
+ } G_STMT_END
+
+static gboolean
+context_menu(MqWebView *web_view, MqWebViewScheme G_GNUC_UNUSED *scheme,
+ WebKitContextMenu *context_menu, GdkEvent G_GNUC_UNUSED *event,
+ WebKitHitTestResult *hit_test_result)
+{
+ GList *items;
+ GList *nav_items;
+ GList *edit_items;
+ gboolean is_selection;
+ WebKitContextMenuAction stock_action;
+ WebKitHitTestResultContext context;
+ gboolean context_handled;
+ WebKitContextMenuItem *menu_item;
+
+ /* Get more hints about the context, since WebKit doesn't describe
+ * context very well in hit test results. Also, preserve menu items
+ * that aren't easy to reproduce (e.g. the Unicode menu and spelling
+ * guesses). */
+ items = webkit_context_menu_get_items(context_menu);
+ nav_items = NULL;
+ edit_items = NULL;
+ is_selection = FALSE;
+ for (; items; items = items->next) {
+ stock_action = webkit_context_menu_item_get_stock_action(
+ items->data);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+ switch (stock_action) {
+ case WKCMA(GO_BACK):
+ case WKCMA(GO_FORWARD):
+ case WKCMA(STOP):
+ case WKCMA(RELOAD):
+ PRESERVE_ITEM(nav_items);
+ break;
+ case WKCMA(COPY):
+ PRESERVE_ITEM(edit_items);
+ is_selection = TRUE;
+ break;
+ }
+#pragma GCC diagnostic pop
+ }
+ nav_items = g_list_reverse(nav_items);
+ edit_items = g_list_reverse(edit_items);
+
+ /* Clear the menu. */
+ webkit_context_menu_remove_all(context_menu);
+
+ /* Get the reported context (which isn't very descriptive) and save the
+ * hit test result for use by action callbacks. */
+ context = webkit_hit_test_result_get_context(hit_test_result);
+ if (scheme->normal.hit_test_result) {
+ g_object_unref(scheme->normal.hit_test_result);
+ }
+ scheme->normal.hit_test_result = hit_test_result;
+ g_object_ref(scheme->normal.hit_test_result);
+ context_handled = FALSE;
+
+ /* Build the context menu. */
+ if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT) {
+ if (is_selection) {
+ RESTORE_ITEMS(edit_items); /* _Copy */
+ context_handled = TRUE;
+ } else {
+ context_menu_document_cb(context_menu, nav_items,
+ web_view);
+ context_handled = TRUE;
+ }
+ if (context_handled) {
+ NEW_SEPARATOR_ITEM();
+ }
+ NEW_STOCK_ITEM(INSPECT_ELEMENT); /* Inspect Element */
+ }
+
+ /* Propagate the event further and show the context menu. */
+ return FALSE;
+}
+
+static void
+save_file(MqWebView *web_view, MqWebViewScheme *scheme)
+{
+ /* TODO: Stub */
+ mq_web_view_get_scheme(web_view);
+ *scheme = *scheme;
+}
+
+MqWebViewSchemeMethods mq_web_view_view_source_scheme_methods = {
+ .rewrite_uri = rewrite_uri,
+ .display_uri = display_uri,
+ .context_menu = context_menu,
+ .save_file = save_file,
+};