diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/web-view-schemes/local.mk | 3 | ||||
-rw-r--r-- | src/web-view-schemes/schemes.h | 13 | ||||
-rw-r--r-- | src/web-view-schemes/view-source.c | 191 |
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, +}; |