From b278d4cfd5c1708198ae4519c222863b6cd6cb8b Mon Sep 17 00:00:00 2001 From: vanadiae Date: Sun, 1 Aug 2021 19:45:55 +0200 Subject: [PATCH 1/6] ls: Add session saving support --- src/plugins/ls/gbp-ls-session-addin.c | 166 ++++++++++++++++++++++++++ src/plugins/ls/gbp-ls-session-addin.h | 32 +++++ src/plugins/ls/ls-plugin.c | 4 + src/plugins/ls/meson.build | 1 + 4 files changed, 203 insertions(+) create mode 100644 src/plugins/ls/gbp-ls-session-addin.c create mode 100644 src/plugins/ls/gbp-ls-session-addin.h diff --git a/src/plugins/ls/gbp-ls-session-addin.c b/src/plugins/ls/gbp-ls-session-addin.c new file mode 100644 index 000000000..d66b78c30 --- /dev/null +++ b/src/plugins/ls/gbp-ls-session-addin.c @@ -0,0 +1,166 @@ +/* gbp-ls-session-addin.c + * + * Copyright 2021 vanadiae + * + * This program 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. + * + * This program 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 this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + + +#define G_LOG_DOMAIN "gbp-ls-session-addin" + +#include "config.h" + +#include + +#include "gbp-ls-session-addin.h" + +#include "gbp-ls-page.h" + +struct _GbpLsSessionAddin +{ + IdeObject parent_instance; +}; + +static void +gbp_ls_session_addin_save_page_async (IdeSessionAddin *addin, + IdePage *page, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(IdeTask) task = NULL; + GVariantDict state_dict; + GFile *directory; + + IDE_ENTRY; + + g_assert (IDE_IS_MAIN_THREAD ()); + g_assert (GBP_IS_LS_SESSION_ADDIN (addin)); + g_assert (GBP_IS_LS_PAGE (page)); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + task = ide_task_new (addin, cancellable, callback, user_data); + ide_task_set_source_tag (task, gbp_ls_session_addin_save_page_async); + + directory = gbp_ls_page_get_directory (GBP_LS_PAGE (page)); + g_variant_dict_init (&state_dict, NULL); + g_variant_dict_insert (&state_dict, "directory", "s", directory ? g_file_peek_path (directory) : ""); + + IDE_TRACE_MSG ("Saving ls page with directory \"%s\"", g_file_peek_path (directory)); + + ide_task_return_pointer (task, g_variant_take_ref (g_variant_dict_end (&state_dict)), g_variant_unref); + + IDE_EXIT; +} + +static GVariant * +gbp_ls_session_addin_save_page_finish (IdeSessionAddin *self, + GAsyncResult *result, + GError **error) +{ + g_assert (GBP_IS_LS_SESSION_ADDIN (self)); + g_assert (IDE_IS_TASK (result)); + + return ide_task_propagate_pointer (IDE_TASK (result), error); +} + +static void +gbp_ls_session_addin_restore_page_async (IdeSessionAddin *addin, + GVariant *state, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(IdeTask) task = NULL; + GVariantDict state_dict; + const char *directory_path; + g_autoptr(GFile) directory = NULL; + + g_assert (GBP_IS_LS_SESSION_ADDIN (addin)); + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + g_assert (g_variant_is_of_type (state, G_VARIANT_TYPE_VARDICT)); + + task = ide_task_new (addin, cancellable, callback, user_data); + ide_task_set_source_tag (task, gbp_ls_session_addin_restore_page_async); + + g_variant_dict_init (&state_dict, state); + g_variant_dict_lookup (&state_dict, "directory", "&s", &directory_path); + g_assert (directory_path != NULL); + + IDE_TRACE_MSG ("Restoring ls page at directory \"%s\"", directory_path); + + directory = g_file_new_for_path (directory_path); + ide_task_return_pointer (task, + g_object_new (GBP_TYPE_LS_PAGE, + "directory", directory, + "visible", TRUE, + NULL), + g_object_unref); +} + +static IdePage * +gbp_ls_session_addin_restore_page_finish (IdeSessionAddin *self, + GAsyncResult *result, + GError **error) +{ + g_assert (GBP_IS_LS_SESSION_ADDIN (self)); + g_assert (IDE_IS_TASK (result)); + + return ide_task_propagate_pointer (IDE_TASK (result), error); +} + +static gboolean +gbp_ls_session_addin_can_save_page (IdeSessionAddin *addin, + IdePage *page) +{ + return GBP_IS_LS_PAGE (page); +} + +static char ** +gbp_ls_session_addin_get_autosave_properties (IdeSessionAddin *addin) +{ + GStrvBuilder *builder = NULL; + + g_assert (GBP_IS_LS_SESSION_ADDIN (addin)); + + builder = g_strv_builder_new (); + g_strv_builder_add (builder, "directory"); + return g_strv_builder_end (builder); +} + +static void +session_addin_iface_init (IdeSessionAddinInterface *iface) +{ + iface->save_page_async = gbp_ls_session_addin_save_page_async; + iface->save_page_finish = gbp_ls_session_addin_save_page_finish; + iface->restore_page_async = gbp_ls_session_addin_restore_page_async; + iface->restore_page_finish = gbp_ls_session_addin_restore_page_finish; + iface->can_save_page = gbp_ls_session_addin_can_save_page; + iface->get_autosave_properties = gbp_ls_session_addin_get_autosave_properties; +} + +G_DEFINE_TYPE_WITH_CODE (GbpLsSessionAddin, gbp_ls_session_addin, IDE_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (IDE_TYPE_SESSION_ADDIN, session_addin_iface_init)) + +static void +gbp_ls_session_addin_class_init (GbpLsSessionAddinClass *klass) +{ +} + +static void +gbp_ls_session_addin_init (GbpLsSessionAddin *self) +{ +} diff --git a/src/plugins/ls/gbp-ls-session-addin.h b/src/plugins/ls/gbp-ls-session-addin.h new file mode 100644 index 000000000..0dfb0ad77 --- /dev/null +++ b/src/plugins/ls/gbp-ls-session-addin.h @@ -0,0 +1,32 @@ +/* gbp-ls-session-addin.h + * + * Copyright 2021 vanadiae + * + * This program 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. + * + * This program 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 this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + + +#pragma once + +#include + +G_BEGIN_DECLS + +#define GBP_TYPE_LS_SESSION_ADDIN (gbp_ls_session_addin_get_type()) + +G_DECLARE_FINAL_TYPE (GbpLsSessionAddin, gbp_ls_session_addin, GBP, LS_SESSION_ADDIN, IdeObject) + +G_END_DECLS diff --git a/src/plugins/ls/ls-plugin.c b/src/plugins/ls/ls-plugin.c index 1117ed0ba..d7fa4c538 100644 --- a/src/plugins/ls/ls-plugin.c +++ b/src/plugins/ls/ls-plugin.c @@ -25,6 +25,7 @@ #include #include "gbp-ls-editor-page-addin.h" +#include "gbp-ls-session-addin.h" #include "gbp-ls-workbench-addin.h" _IDE_EXTERN void @@ -33,6 +34,9 @@ _gbp_ls_register_types (PeasObjectModule *module) peas_object_module_register_extension_type (module, IDE_TYPE_EDITOR_PAGE_ADDIN, GBP_TYPE_LS_EDITOR_PAGE_ADDIN); + peas_object_module_register_extension_type (module, + IDE_TYPE_SESSION_ADDIN, + GBP_TYPE_LS_SESSION_ADDIN); peas_object_module_register_extension_type (module, IDE_TYPE_WORKBENCH_ADDIN, GBP_TYPE_LS_WORKBENCH_ADDIN); diff --git a/src/plugins/ls/meson.build b/src/plugins/ls/meson.build index e74df7ebe..d3be22e4a 100644 --- a/src/plugins/ls/meson.build +++ b/src/plugins/ls/meson.build @@ -2,6 +2,7 @@ plugins_sources += files([ 'gbp-ls-model.c', 'gbp-ls-page.c', 'gbp-ls-editor-page-addin.c', + 'gbp-ls-session-addin.c', 'gbp-ls-workbench-addin.c', 'gbp-ls-tree-view.c', 'ls-plugin.c', -- GitLab From 84f8c00fa17a959a1cb3f76f7431c5d937468b6b Mon Sep 17 00:00:00 2001 From: vanadiae Date: Sun, 1 Aug 2021 19:46:26 +0200 Subject: [PATCH 2/6] libide-io: Make sure we never use our overridden icons for folders --- src/libide/io/ide-content-type.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libide/io/ide-content-type.c b/src/libide/io/ide-content-type.c index a3ed67220..0c024c7f0 100644 --- a/src/libide/io/ide-content-type.c +++ b/src/libide/io/ide-content-type.c @@ -134,6 +134,16 @@ ide_g_content_type_get_symbolic_icon (const gchar *content_type, icon = g_content_type_get_symbolic_icon (content_type); + /* Special case folders to never even try to use an overridden icon. For + * example in the case of the LICENSES folder required by the REUSE licensing + * helpers, the icon would be the copyright icon. Even if in this particular + * case it might make sense to keep the copyright icon, it's just really + * confusing to have a folder without a folder icon, especially since it becomes + * an expanded folder icon when opening it in the project tree. + */ + if (g_strcmp0 (content_type, "inode/directory") == 0) + return g_steal_pointer (&icon); + if (G_IS_THEMED_ICON (icon)) { const gchar * const *names; -- GitLab From aa4e56d47d3e665a2bce3b3f78f4ccb80d496eb7 Mon Sep 17 00:00:00 2001 From: vanadiae Date: Sun, 1 Aug 2021 19:48:45 +0200 Subject: [PATCH 3/6] devhelp: Redirect any non local link to the user's browser And block any remote page resource (e.g. javascript, CSS). The point here is to make sure that opening a project's homepage will open the web browser. Since it's easy to block the rest of the possible URI requests (remote resources), then do that too since we don't expect to have any remote things since it's supposed to be entirely offline documentation. --- src/plugins/devhelp/gbp-devhelp-page.c | 77 +++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/plugins/devhelp/gbp-devhelp-page.c b/src/plugins/devhelp/gbp-devhelp-page.c index fbb499c0f..8d74b6a1f 100644 --- a/src/plugins/devhelp/gbp-devhelp-page.c +++ b/src/plugins/devhelp/gbp-devhelp-page.c @@ -228,21 +228,84 @@ gbp_devhelp_page_class_init (GbpDevhelpPageClass *klass) g_type_ensure (WEBKIT_TYPE_WEB_VIEW); } +static gboolean +webview_decide_policy_cb (WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType decision_type, + gpointer user_data) +{ + WebKitURIRequest *request = NULL; + g_autoptr(GUri) uri = NULL; + gboolean launch_in_browser; + + g_assert (WEBKIT_IS_WEB_VIEW (web_view)); + + switch (decision_type) { + case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: + case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: + { + WebKitNavigationAction *navigation_action = + webkit_navigation_policy_decision_get_navigation_action (WEBKIT_NAVIGATION_POLICY_DECISION (decision)); + request = webkit_navigation_action_get_request (navigation_action); + launch_in_browser = TRUE; + } + break; + case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: + request = webkit_response_policy_decision_get_request (WEBKIT_RESPONSE_POLICY_DECISION (decision)); + launch_in_browser = FALSE; + break; + default: + return FALSE; + } + + uri = g_uri_parse (webkit_uri_request_get_uri (request), G_URI_FLAGS_NONE, NULL); + if (!uri) + /* Don't let invalid URIs go through the firewall. */ + { + webkit_policy_decision_ignore (decision); + return TRUE; + } + else + { + /* Allow the integrated devhelp web view to handle local documentation links, + * but open any non-local ones with the user's web browser (e.g. library's homepage), + * and deny any other remote resource. + */ + if (g_strcmp0 (g_uri_get_scheme (uri), "file") == 0) + return FALSE; + else + { + if (launch_in_browser) + { + GAppLaunchContext *launch_ctx = G_APP_LAUNCH_CONTEXT (gdk_display_get_app_launch_context (gdk_display_get_default ())); + g_app_info_launch_default_for_uri (webkit_uri_request_get_uri (request), + launch_ctx, + NULL); + } + webkit_policy_decision_ignore (decision); + return TRUE; + } + } +} + static void -setup_webview_styling (WebKitWebView *web_view) +setup_webview (WebKitWebView *web_view) { + g_autoptr(WebKitUserStyleSheet) stylesheet = NULL; + /* Both gi-docgen and gtk-doc use the devhelp-hidden style class to give indications of what * elements should be hidden for use by devhelp. Generally it's for the sidebar but it allows * to hide really anything not useful for devhelp (e.g. the TOC which already has native GTK * widgets in Builder/Devhelp. So follow Devhelp here and hide them. */ - g_autoptr(WebKitUserStyleSheet) stylesheet = - webkit_user_style_sheet_new (".devhelp-hidden { display: none; }", - WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, - WEBKIT_USER_STYLE_LEVEL_USER, - NULL, NULL); + stylesheet = webkit_user_style_sheet_new (".devhelp-hidden { display: none; }", + WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, + WEBKIT_USER_STYLE_LEVEL_USER, + NULL, NULL); webkit_user_content_manager_add_style_sheet (webkit_web_view_get_user_content_manager (web_view), stylesheet); + + g_signal_connect (web_view, "decide-policy", G_CALLBACK (webview_decide_policy_cb), NULL); } static const GActionEntry actions[] = { @@ -266,7 +329,7 @@ gbp_devhelp_page_init (GbpDevhelpPage *self) self->clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); self->web_controller = webkit_web_view_get_find_controller (self->web_view); - setup_webview_styling (self->web_view); + setup_webview (self->web_view); gtk_overlay_add_overlay (self->devhelp_overlay, GTK_WIDGET (self->search_revealer)); -- GitLab From feca93463e63e0cb9eb397e0b5fe4b646879a6a5 Mon Sep 17 00:00:00 2001 From: vanadiae Date: Sun, 1 Aug 2021 20:48:00 +0200 Subject: [PATCH 4/6] devhelp: Fix Ctrl+F shortcut by using an action shortcut We can't use gtk_binding_entry_add_signal() because it requires us to have the end focus (like an entry or button has) with can-focus=True, which we can't have because we're just a container and not a "primitive" widget. I'm not sure if that shortcut ever worked, and how though. So instead use an action shortcut, and get back the search bar ;) --- src/plugins/devhelp/gbp-devhelp-page.c | 48 +++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/plugins/devhelp/gbp-devhelp-page.c b/src/plugins/devhelp/gbp-devhelp-page.c index 8d74b6a1f..20f035118 100644 --- a/src/plugins/devhelp/gbp-devhelp-page.c +++ b/src/plugins/devhelp/gbp-devhelp-page.c @@ -18,6 +18,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#define I_ g_intern_string + #include #include #include @@ -44,15 +46,9 @@ enum { LAST_PROP }; -enum { - SEARCH_REVEAL, - LAST_SIGNAL -}; - G_DEFINE_TYPE (GbpDevhelpPage, gbp_devhelp_page, IDE_TYPE_PAGE) static GParamSpec *properties [LAST_PROP]; -static guint signals [LAST_SIGNAL]; void gbp_devhelp_page_set_uri (GbpDevhelpPage *self, @@ -169,12 +165,17 @@ gbp_devhelp_page_get_property (GObject *object, } static void -gbp_devhelp_search_reveal (GbpDevhelpPage *self) +gbp_devhelp_page_actions_reveal_search (GSimpleAction *action, + GVariant *param, + gpointer user_data) { + GbpDevhelpPage *self = (GbpDevhelpPage *)user_data; + g_assert (GBP_IS_DEVHELP_PAGE (self)); webkit_web_view_can_execute_editing_command (self->web_view, WEBKIT_EDITING_COMMAND_COPY, NULL, NULL, NULL); gtk_revealer_set_reveal_child (self->search_revealer, TRUE); + gtk_widget_grab_focus (GTK_WIDGET (self->search)); } static void @@ -187,6 +188,16 @@ gbp_devhelp_focus_in_event (GbpDevhelpPage *self, gtk_revealer_set_reveal_child (self->search_revealer, FALSE); } +static void +gbp_devhelp_page_finalize (GObject *object) +{ + GbpDevhelpPage *self = (GbpDevhelpPage *)object; + + g_assert (GBP_IS_DEVHELP_PAGE (self)); + + gtk_widget_insert_action_group (GTK_WIDGET (self), "devhelp-view", NULL); +} + static void gbp_devhelp_page_class_init (GbpDevhelpPageClass *klass) { @@ -196,6 +207,7 @@ gbp_devhelp_page_class_init (GbpDevhelpPageClass *klass) object_class->set_property = gbp_devhelp_page_set_property; object_class->get_property = gbp_devhelp_page_get_property; + object_class->finalize = gbp_devhelp_page_finalize; view_class->create_split = gbp_devhelp_page_create_split; @@ -206,19 +218,6 @@ gbp_devhelp_page_class_init (GbpDevhelpPageClass *klass) NULL, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY)); - signals [SEARCH_REVEAL] = - g_signal_new_class_handler ("search-reveal", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_CALLBACK (gbp_devhelp_search_reveal), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - gtk_binding_entry_add_signal (gtk_binding_set_by_class (klass), - GDK_KEY_f, - GDK_CONTROL_MASK, - "search-reveal", 0); - g_object_class_install_properties (object_class, LAST_PROP, properties); gtk_widget_class_set_template_from_resource (widget_class, "/plugins/devhelp/gbp-devhelp-page.ui"); @@ -310,12 +309,14 @@ setup_webview (WebKitWebView *web_view) static const GActionEntry actions[] = { { "print", gbp_devhelp_page_actions_print }, + { "reveal-search", gbp_devhelp_page_actions_reveal_search }, }; static void gbp_devhelp_page_init (GbpDevhelpPage *self) { g_autoptr(GSimpleActionGroup) group = NULL; + DzlShortcutController *controller; gtk_widget_init_template (GTK_WIDGET (self)); @@ -357,4 +358,11 @@ gbp_devhelp_page_init (GbpDevhelpPage *self) gtk_widget_insert_action_group (GTK_WIDGET (self), "devhelp-view", G_ACTION_GROUP (group)); + + controller = dzl_shortcut_controller_find (GTK_WIDGET (self)); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-view.reveal-search"), + "f", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-view.reveal-search")); } -- GitLab From 8c298f6fa418e66b8ccde72a9f5aeadc82dc9c1b Mon Sep 17 00:00:00 2001 From: vanadiae Date: Mon, 2 Aug 2021 15:54:16 +0200 Subject: [PATCH 5/6] devhelp: Add previous/next history page shortcuts The same as what we have in nautilus/epiphany. --- src/plugins/devhelp/gbp-devhelp-page.c | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/plugins/devhelp/gbp-devhelp-page.c b/src/plugins/devhelp/gbp-devhelp-page.c index 20f035118..1d19c6dc8 100644 --- a/src/plugins/devhelp/gbp-devhelp-page.c +++ b/src/plugins/devhelp/gbp-devhelp-page.c @@ -164,6 +164,30 @@ gbp_devhelp_page_get_property (GObject *object, } } +static void +gbp_devhelp_page_actions_history_next (GSimpleAction *action, + GVariant *param, + gpointer user_data) +{ + GbpDevhelpPage *self = (GbpDevhelpPage *)user_data; + + g_assert (GBP_IS_DEVHELP_PAGE (self)); + + webkit_web_view_go_forward (self->web_view); +} + +static void +gbp_devhelp_page_actions_history_previous (GSimpleAction *action, + GVariant *param, + gpointer user_data) +{ + GbpDevhelpPage *self = (GbpDevhelpPage *)user_data; + + g_assert (GBP_IS_DEVHELP_PAGE (self)); + + webkit_web_view_go_back (self->web_view); +} + static void gbp_devhelp_page_actions_reveal_search (GSimpleAction *action, GVariant *param, @@ -310,6 +334,8 @@ setup_webview (WebKitWebView *web_view) static const GActionEntry actions[] = { { "print", gbp_devhelp_page_actions_print }, { "reveal-search", gbp_devhelp_page_actions_reveal_search }, + { "history-next", gbp_devhelp_page_actions_history_next }, + { "history-previous", gbp_devhelp_page_actions_history_previous }, }; static void @@ -365,4 +391,24 @@ gbp_devhelp_page_init (GbpDevhelpPage *self) "f", DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, I_("devhelp-view.reveal-search")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-view.history-next"), + "Right", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-view.history-next")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-view.history-previous"), + "Left", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-view.history-previous")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-view.history-next"), + "KP_Right", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-view.history-next")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-view.history-previous"), + "KP_Left", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-view.history-previous")); } -- GitLab From 09d97a379a55328456dddd973b344bde8270d6b3 Mon Sep 17 00:00:00 2001 From: vanadiae Date: Mon, 2 Aug 2021 15:57:24 +0200 Subject: [PATCH 6/6] devhelp: Add close search bar and find next/prev keyboard shortcuts I had to clean up things a bit to make it work. --- src/plugins/devhelp/gbp-devhelp-page.c | 4 +- src/plugins/devhelp/gbp-devhelp-search.c | 128 +++++++++++++---- src/plugins/devhelp/gbp-devhelp-search.ui | 160 +++++++++++----------- 3 files changed, 186 insertions(+), 106 deletions(-) diff --git a/src/plugins/devhelp/gbp-devhelp-page.c b/src/plugins/devhelp/gbp-devhelp-page.c index 1d19c6dc8..ae32fbaba 100644 --- a/src/plugins/devhelp/gbp-devhelp-page.c +++ b/src/plugins/devhelp/gbp-devhelp-page.c @@ -358,8 +358,8 @@ gbp_devhelp_page_init (GbpDevhelpPage *self) setup_webview (self->web_view); - gtk_overlay_add_overlay (self->devhelp_overlay, - GTK_WIDGET (self->search_revealer)); + gtk_widget_show (GTK_WIDGET (self->search)); + gtk_overlay_add_overlay (self->devhelp_overlay, GTK_WIDGET (self->search)); gbp_devhelp_search_set_devhelp (self->search, self->web_controller, diff --git a/src/plugins/devhelp/gbp-devhelp-search.c b/src/plugins/devhelp/gbp-devhelp-search.c index 4391122a6..fd884ba62 100644 --- a/src/plugins/devhelp/gbp-devhelp-search.c +++ b/src/plugins/devhelp/gbp-devhelp-search.c @@ -18,10 +18,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#define I_ g_intern_string + #define G_LOG_DOMAIN "gbp-devhelp-search" #define MAX_SEARCH 100 -#include #include #include #include @@ -31,28 +32,6 @@ G_DEFINE_TYPE (GbpDevhelpSearch, gbp_devhelp_search, GTK_TYPE_BIN) -static void -close_clicked_cb (GtkButton *button, - GbpDevhelpSearch *self) -{ - g_assert (GBP_IS_DEVHELP_SEARCH (self)); - - webkit_find_controller_search_finish (self->web_controller); - gtk_revealer_set_reveal_child (self->search_revealer, FALSE); -} - -static void -search_button_clicked_cb (GtkButton *button, - GbpDevhelpSearch *self) -{ - g_assert (GBP_IS_DEVHELP_SEARCH (self)); - - if (button == self->search_prev_button) - webkit_find_controller_search_previous (self->web_controller); - else - webkit_find_controller_search_next (self->web_controller); -} - static void search_text_changed_cb (IdeTaggedEntry *search_entry, GbpDevhelpSearch *self) @@ -90,11 +69,77 @@ search_revealer_cb (GtkRevealer *search_revealer, gtk_revealer_set_reveal_child (self->search_revealer, FALSE); } +static void +gbp_devhelp_search_actions_close (GSimpleAction *action, + GVariant *param, + gpointer user_data) +{ + GbpDevhelpSearch *self = (GbpDevhelpSearch *)user_data; + + g_assert (GBP_IS_DEVHELP_SEARCH (self)); + + webkit_find_controller_search_finish (self->web_controller); + gtk_revealer_set_reveal_child (self->search_revealer, FALSE); +} + +static void +gbp_devhelp_search_actions_find_next (GSimpleAction *action, + GVariant *param, + gpointer user_data) +{ + GbpDevhelpSearch *self = (GbpDevhelpSearch *)user_data; + + g_assert (GBP_IS_DEVHELP_SEARCH (self)); + + if (gtk_revealer_get_reveal_child (self->search_revealer) && + webkit_find_controller_get_search_text (self->web_controller)) + webkit_find_controller_search_next (self->web_controller); +} + +static void +gbp_devhelp_search_actions_find_previous (GSimpleAction *action, + GVariant *param, + gpointer user_data) +{ + GbpDevhelpSearch *self = (GbpDevhelpSearch *)user_data; + + g_assert (GBP_IS_DEVHELP_SEARCH (self)); + + if (gtk_revealer_get_reveal_child (self->search_revealer) && + webkit_find_controller_get_search_text (self->web_controller)) + webkit_find_controller_search_previous (self->web_controller); +} + +static void +gbp_devhelp_search_grab_focus (GtkWidget *widget) +{ + GbpDevhelpSearch *self = (GbpDevhelpSearch *)widget; + + g_assert (GBP_IS_DEVHELP_SEARCH (self)); + + gtk_widget_grab_focus (GTK_WIDGET (self->search_entry)); +} + +static void +gbp_devhelp_search_finalize (GObject *object) +{ + GbpDevhelpSearch *self = (GbpDevhelpSearch *)object; + + g_assert (GBP_IS_DEVHELP_SEARCH (self)); + + gtk_widget_insert_action_group (GTK_WIDGET (self), "devhelp-search", NULL); +} + static void gbp_devhelp_search_class_init (GbpDevhelpSearchClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + object_class->finalize = gbp_devhelp_search_finalize; + + widget_class->grab_focus = gbp_devhelp_search_grab_focus; + gtk_widget_class_set_template_from_resource (widget_class, "/plugins/devhelp/gbp-devhelp-search.ui"); gtk_widget_class_bind_template_child (widget_class, GbpDevhelpSearch, search_prev_button); @@ -104,17 +149,48 @@ gbp_devhelp_search_class_init (GbpDevhelpSearchClass *klass) gtk_widget_class_bind_template_child (widget_class, GbpDevhelpSearch, search_revealer); } +static const GActionEntry actions[] = { + { "close", gbp_devhelp_search_actions_close }, + { "find-next", gbp_devhelp_search_actions_find_next }, + { "find-previous", gbp_devhelp_search_actions_find_previous }, +}; + static void gbp_devhelp_search_init (GbpDevhelpSearch *self) { + g_autoptr(GSimpleActionGroup) group = NULL; + DzlShortcutController *controller; gtk_widget_init_template (GTK_WIDGET (self)); - g_signal_connect (self->search_prev_button, "clicked", G_CALLBACK (search_button_clicked_cb), self); - g_signal_connect (self->search_next_button, "clicked", G_CALLBACK (search_button_clicked_cb), self); - g_signal_connect (self->close_button, "clicked", G_CALLBACK (close_clicked_cb), self); g_signal_connect (self->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), self); g_signal_connect (self->search_revealer, "notify::child-revealed", G_CALLBACK (search_revealer_cb), self); + + group = g_simple_action_group_new (); + g_action_map_add_action_entries (G_ACTION_MAP (group), + actions, + G_N_ELEMENTS (actions), + self); + gtk_widget_insert_action_group (GTK_WIDGET (self), + "devhelp-search", + G_ACTION_GROUP (group)); + + controller = dzl_shortcut_controller_find (GTK_WIDGET (self)); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-search.close"), + "Escape", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-search.close")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-search.find-next"), + "g", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-search.find-next")); + dzl_shortcut_controller_add_command_action (controller, + I_("org.gnome.builder.devhelp-search.find-previous"), + "g", + DZL_SHORTCUT_PHASE_CAPTURE | DZL_SHORTCUT_PHASE_GLOBAL, + I_("devhelp-search.find-previous")); } void diff --git a/src/plugins/devhelp/gbp-devhelp-search.ui b/src/plugins/devhelp/gbp-devhelp-search.ui index 5f690fd7a..bf5112925 100644 --- a/src/plugins/devhelp/gbp-devhelp-search.ui +++ b/src/plugins/devhelp/gbp-devhelp-search.ui @@ -1,116 +1,120 @@ - + -- GitLab