From ae1c76ff830d146d41e88d6fba724c0a54bce868 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:45:20 +0200 Subject: Adding upstream version 1:43.6. Signed-off-by: Daniel Baumann --- search-provider/cc-search-provider.c | 377 +++++++++++++++++++++ search-provider/cc-search-provider.h | 43 +++ search-provider/control-center-search-provider.c | 151 +++++++++ search-provider/control-center-search-provider.h | 52 +++ search-provider/meson.build | 47 +++ .../org.gnome.Settings.SearchProvider.service.in | 3 + .../org.gnome.Settings.search-provider.ini | 5 + search-provider/org.gnome.ShellSearchProvider2.xml | 87 +++++ 8 files changed, 765 insertions(+) create mode 100644 search-provider/cc-search-provider.c create mode 100644 search-provider/cc-search-provider.h create mode 100644 search-provider/control-center-search-provider.c create mode 100644 search-provider/control-center-search-provider.h create mode 100644 search-provider/meson.build create mode 100644 search-provider/org.gnome.Settings.SearchProvider.service.in create mode 100644 search-provider/org.gnome.Settings.search-provider.ini create mode 100644 search-provider/org.gnome.ShellSearchProvider2.xml (limited to 'search-provider') diff --git a/search-provider/cc-search-provider.c b/search-provider/cc-search-provider.c new file mode 100644 index 0000000..8a8981a --- /dev/null +++ b/search-provider/cc-search-provider.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2012 Giovanni Campagna + * + * The Control Center 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 2 of the License, or (at your + * option) any later version. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cc-util.h" + +#include "control-center-search-provider.h" +#include "cc-search-provider.h" + +struct _CcSearchProvider +{ + GObject parent; + + CcShellSearchProvider2 *skeleton; + + GHashTable *iter_table; /* COL_ID -> GtkTreeIter */ +}; + +typedef enum { + MATCH_NONE, + MATCH_PREFIX, + MATCH_SUBSTRING +} PanelSearchMatch; + +G_DEFINE_TYPE (CcSearchProvider, cc_search_provider, G_TYPE_OBJECT) + +static char ** +get_casefolded_terms (char **terms) +{ + char **casefolded_terms; + int i, n; + + n = g_strv_length ((char**) terms); + casefolded_terms = g_new (char*, n + 1); + + for (i = 0; i < n; i++) + casefolded_terms[i] = cc_util_normalize_casefold_and_unaccent (terms[i]); + casefolded_terms[n] = NULL; + + return casefolded_terms; +} + +static gboolean +matches_all_terms (GtkTreeModel *model, + GtkTreeIter *iter, + char **terms) +{ + int i; + + for (i = 0; terms[i]; i++) + { + if (!cc_shell_model_iter_matches_search (CC_SHELL_MODEL (model), + iter, + terms[i])) + return FALSE; + } + + return TRUE; +} + +static GtkTreeModel * +get_model (void) +{ + CcSearchProviderApp *app; + + app = cc_search_provider_app_get (); + return GTK_TREE_MODEL (cc_search_provider_app_get_model (app)); +} + +static gchar ** +get_results (gchar **terms) +{ + g_auto(GStrv) casefolded_terms = NULL; + GtkTreeModel *model = get_model (); + GtkTreeIter iter; + GPtrArray *results; + gboolean ok; + + casefolded_terms = get_casefolded_terms (terms); + results = g_ptr_array_new (); + + cc_shell_model_set_sort_terms (CC_SHELL_MODEL (model), casefolded_terms); + + ok = gtk_tree_model_get_iter_first (model, &iter); + while (ok) + { + if (matches_all_terms (model, &iter, casefolded_terms)) + { + gchar *id; + gtk_tree_model_get (model, &iter, COL_ID, &id, -1); + g_ptr_array_add (results, id); + } + + ok = gtk_tree_model_iter_next (model, &iter); + } + + g_ptr_array_add (results, NULL); + + return (char**) g_ptr_array_free (results, FALSE); +} + +static gboolean +handle_get_initial_result_set (CcShellSearchProvider2 *skeleton, + GDBusMethodInvocation *invocation, + char **terms, + CcSearchProvider *self) +{ + g_auto(GStrv) results = get_results (terms); + cc_shell_search_provider2_complete_get_initial_result_set (skeleton, + invocation, + (const char* const*) results); + return TRUE; +} + +static gboolean +handle_get_subsearch_result_set (CcShellSearchProvider2 *skeleton, + GDBusMethodInvocation *invocation, + char **previous_results, + char **terms, + CcSearchProvider *self) +{ + /* We ignore the previous results here since the model re-sorts for + * the new terms. This means that we're not really doing a subsearch + * but, on the other hand, the results are consistent with the + * control center's own search. In any case, the number of elements + * in the model is always small enough that we don't need to worry + * about this taking too long. + */ + g_auto(GStrv) results = get_results (terms); + cc_shell_search_provider2_complete_get_subsearch_result_set (skeleton, + invocation, + (const char* const*) results); + return TRUE; +} + +static GtkTreeIter * +get_iter_for_result (CcSearchProvider *self, + const gchar *result) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean ok; + gchar *id; + + /* Caching GtkTreeIters in this way is only OK because the model is + * a GtkListStore which guarantees that while a row exists, the iter + * is persistent. + */ + if (self->iter_table) + goto lookup; + + self->iter_table = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) gtk_tree_iter_free); + + model = get_model (); + ok = gtk_tree_model_get_iter_first (model, &iter); + while (ok) + { + gtk_tree_model_get (model, &iter, COL_ID, &id, -1); + + g_hash_table_replace (self->iter_table, id, gtk_tree_iter_copy (&iter)); + + ok = gtk_tree_model_iter_next (model, &iter); + } + + lookup: + return g_hash_table_lookup (self->iter_table, result); +} + +static gboolean +handle_get_result_metas (CcShellSearchProvider2 *skeleton, + GDBusMethodInvocation *invocation, + char **results, + CcSearchProvider *self) +{ + GtkTreeModel *model = get_model (); + GtkTreeIter *iter; + int i; + GVariantBuilder builder; + const char *id; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); + + for (i = 0; results[i]; i++) + { + g_autofree gchar *description = NULL; + g_autofree gchar *name = NULL; + g_autoptr(GAppInfo) app = NULL; + g_autoptr(GIcon) icon = NULL; + + iter = get_iter_for_result (self, results[i]); + if (!iter) + continue; + + gtk_tree_model_get (model, iter, + COL_APP, &app, + COL_NAME, &name, + COL_GICON, &icon, + COL_DESCRIPTION, &description, + -1); + id = g_app_info_get_id (app); + + g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&builder, "{sv}", + "id", g_variant_new_string (id)); + g_variant_builder_add (&builder, "{sv}", + "name", g_variant_new_string (name)); + g_variant_builder_add (&builder, "{sv}", + "icon", g_icon_serialize (icon)); + g_variant_builder_add (&builder, "{sv}", + "description", g_variant_new_string (description)); + g_variant_builder_close (&builder); + } + + cc_shell_search_provider2_complete_get_result_metas (skeleton, + invocation, + g_variant_builder_end (&builder)); + return TRUE; +} + +static gboolean +handle_activate_result (CcShellSearchProvider2 *skeleton, + GDBusMethodInvocation *invocation, + char *identifier, + char **results, + guint timestamp, + CcSearchProvider *self) +{ + GdkAppLaunchContext *launch_context; + g_autoptr(GError) error = NULL; + GAppInfo *app; + + launch_context = gdk_display_get_app_launch_context (gdk_display_get_default ()); + gdk_app_launch_context_set_timestamp (launch_context, timestamp); + + app = G_APP_INFO (g_desktop_app_info_new (identifier)); + + if (!g_app_info_launch (app, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error)) + g_dbus_method_invocation_return_gerror (invocation, error); + else + cc_shell_search_provider2_complete_activate_result (skeleton, invocation); + + return TRUE; +} + +static gboolean +handle_launch_search (CcShellSearchProvider2 *skeleton, + GDBusMethodInvocation *invocation, + char **terms, + guint timestamp, + CcSearchProvider *self) +{ + GdkAppLaunchContext *launch_context; + g_autoptr(GError) error = NULL; + char *joined_terms, *command_line; + GAppInfo *app; + + launch_context = gdk_display_get_app_launch_context (gdk_display_get_default ()); + gdk_app_launch_context_set_timestamp (launch_context, timestamp); + + joined_terms = g_strjoinv (" ", terms); + command_line = g_strdup_printf ("gnome-control-center -s '%s'", joined_terms); + app = g_app_info_create_from_commandline (command_line, + "gnome-control-center.desktop", + G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION, + &error); + if (!app) + { + g_dbus_method_invocation_return_gerror (invocation, error); + return TRUE; + } + + if (!g_app_info_launch (app, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error)) + g_dbus_method_invocation_return_gerror (invocation, error); + else + cc_shell_search_provider2_complete_launch_search (skeleton, invocation); + + return TRUE; +} + +static void +cc_search_provider_init (CcSearchProvider *self) +{ + self->skeleton = cc_shell_search_provider2_skeleton_new (); + + g_signal_connect (self->skeleton, "handle-get-initial-result-set", + G_CALLBACK (handle_get_initial_result_set), self); + g_signal_connect (self->skeleton, "handle-get-subsearch-result-set", + G_CALLBACK (handle_get_subsearch_result_set), self); + g_signal_connect (self->skeleton, "handle-get-result-metas", + G_CALLBACK (handle_get_result_metas), self); + g_signal_connect (self->skeleton, "handle-activate-result", + G_CALLBACK (handle_activate_result), self); + g_signal_connect (self->skeleton, "handle-launch-search", + G_CALLBACK (handle_launch_search), self); +} + +gboolean +cc_search_provider_dbus_register (CcSearchProvider *self, + GDBusConnection *connection, + const gchar *object_path, + GError **error) +{ + GDBusInterfaceSkeleton *skeleton; + + skeleton = G_DBUS_INTERFACE_SKELETON (self->skeleton); + + return g_dbus_interface_skeleton_export (skeleton, connection, object_path, error); +} + +void +cc_search_provider_dbus_unregister (CcSearchProvider *self, + GDBusConnection *connection, + const gchar *object_path) +{ + GDBusInterfaceSkeleton *skeleton; + + skeleton = G_DBUS_INTERFACE_SKELETON (self->skeleton); + + if (g_dbus_interface_skeleton_has_connection (skeleton, connection)) + g_dbus_interface_skeleton_unexport_from_connection (skeleton, connection); +} + +static void +cc_search_provider_dispose (GObject *object) +{ + CcSearchProvider *self; + + self = CC_SEARCH_PROVIDER (object); + + g_clear_object (&self->skeleton); + g_clear_pointer (&self->iter_table, g_hash_table_destroy); + + G_OBJECT_CLASS (cc_search_provider_parent_class)->dispose (object); +} + +static void +cc_search_provider_class_init (CcSearchProviderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = cc_search_provider_dispose; +} + +CcSearchProvider * +cc_search_provider_new (void) +{ + return g_object_new (CC_TYPE_SEARCH_PROVIDER, NULL); +} + diff --git a/search-provider/cc-search-provider.h b/search-provider/cc-search-provider.h new file mode 100644 index 0000000..0eb05b9 --- /dev/null +++ b/search-provider/cc-search-provider.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012 Giovanni Campagna + * + * The Control Center 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 2 of the License, or (at your + * option) any later version. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#pragma once + +#include +#include +#include "cc-shell-search-provider-generated.h" +#include + +G_BEGIN_DECLS + +#define CC_TYPE_SEARCH_PROVIDER (cc_search_provider_get_type()) + +G_DECLARE_FINAL_TYPE (CcSearchProvider, cc_search_provider, CC, SEARCH_PROVIDER, GObject) + +CcSearchProvider *cc_search_provider_new (void); + +gboolean cc_search_provider_dbus_register (CcSearchProvider *provider, + GDBusConnection *connection, + const char *object_path, + GError **error); +void cc_search_provider_dbus_unregister (CcSearchProvider *provider, + GDBusConnection *connection, + const char *object_path); + +G_END_DECLS diff --git a/search-provider/control-center-search-provider.c b/search-provider/control-center-search-provider.c new file mode 100644 index 0000000..c49cd9a --- /dev/null +++ b/search-provider/control-center-search-provider.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2012 Giovanni Campagna + * + * The Control Center 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 2 of the License, or (at your + * option) any later version. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" + +#include +#include + +#include + +#include +#include +#include "cc-search-provider.h" +#include "control-center-search-provider.h" + +G_DEFINE_TYPE (CcSearchProviderApp, cc_search_provider_app, GTK_TYPE_APPLICATION); + +#define INACTIVITY_TIMEOUT 60 * 1000 /* One minute, in milliseconds */ + +static gboolean +cc_search_provider_app_dbus_register (GApplication *application, + GDBusConnection *connection, + const gchar *object_path, + GError **error) +{ + CcSearchProviderApp *self; + + if (!G_APPLICATION_CLASS (cc_search_provider_app_parent_class)->dbus_register (application, + connection, + object_path, + error)) + return FALSE; + + self = CC_SEARCH_PROVIDER_APP (application); + + return cc_search_provider_dbus_register (self->search_provider, connection, + object_path, error); +} + +static void +cc_search_provider_app_dbus_unregister (GApplication *application, + GDBusConnection *connection, + const gchar *object_path) +{ + CcSearchProviderApp *self; + + self = CC_SEARCH_PROVIDER_APP (application); + if (self->search_provider) + cc_search_provider_dbus_unregister (self->search_provider, connection, object_path); + + G_APPLICATION_CLASS (cc_search_provider_app_parent_class)->dbus_unregister (application, + connection, + object_path); +} + +static void +cc_search_provider_app_dispose (GObject *object) +{ + CcSearchProviderApp *self; + + self = CC_SEARCH_PROVIDER_APP (object); + + g_clear_object (&self->model); + g_clear_object (&self->search_provider); + + G_OBJECT_CLASS (cc_search_provider_app_parent_class)->dispose (object); +} + +static void +cc_search_provider_app_init (CcSearchProviderApp *self) +{ + self->search_provider = cc_search_provider_new (); + g_application_set_inactivity_timeout (G_APPLICATION (self), + INACTIVITY_TIMEOUT); + + /* HACK: get the inactivity timeout started */ + g_application_hold (G_APPLICATION (self)); + g_application_release (G_APPLICATION (self)); +} + +static void +cc_search_provider_app_startup (GApplication *application) +{ + CcSearchProviderApp *self; + + self = CC_SEARCH_PROVIDER_APP (application); + + G_APPLICATION_CLASS (cc_search_provider_app_parent_class)->startup (application); + + self->model = cc_shell_model_new (); + cc_panel_loader_fill_model (self->model); +} + +static void +cc_search_provider_app_class_init (CcSearchProviderAppClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GApplicationClass *app_class = G_APPLICATION_CLASS (klass); + + object_class->dispose = cc_search_provider_app_dispose; + + app_class->dbus_register = cc_search_provider_app_dbus_register; + app_class->dbus_unregister = cc_search_provider_app_dbus_unregister; + app_class->startup = cc_search_provider_app_startup; +} + +CcShellModel * +cc_search_provider_app_get_model (CcSearchProviderApp *application) +{ + return application->model; +} + +CcSearchProviderApp * +cc_search_provider_app_get () +{ + static CcSearchProviderApp *singleton; + + if (singleton) + return singleton; + + singleton = g_object_new (CC_TYPE_SEARCH_PROVIDER_APP, + "application-id", "org.gnome.Settings.SearchProvider", + "flags", G_APPLICATION_IS_SERVICE, + NULL); + + return singleton; +} + +int main (int argc, char **argv) +{ + GApplication *app; + + app = G_APPLICATION (cc_search_provider_app_get ()); + return g_application_run (app, argc, argv); +} diff --git a/search-provider/control-center-search-provider.h b/search-provider/control-center-search-provider.h new file mode 100644 index 0000000..3dc058f --- /dev/null +++ b/search-provider/control-center-search-provider.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 Giovanni Campagna + * + * The Control Center 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 2 of the License, or (at your + * option) any later version. + * + * The Control Center 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 the Control Center; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#pragma once + +#include + +#include +#include "cc-search-provider.h" + +G_BEGIN_DECLS + +typedef struct { + GtkApplication parent; + + CcShellModel *model; + CcSearchProvider *search_provider; +} CcSearchProviderApp; + +typedef struct { + GtkApplicationClass parent_class; +} CcSearchProviderAppClass; + +#define CC_TYPE_SEARCH_PROVIDER_APP cc_search_provider_app_get_type () + +#define CC_SEARCH_PROVIDER_APP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CC_TYPE_SEARCH_PROVIDER_APP, CcSearchProviderApp)) + +GType cc_search_provider_app_get_type (void) G_GNUC_CONST; + +CcSearchProviderApp *cc_search_provider_app_get (void); + +CcShellModel *cc_search_provider_app_get_model (CcSearchProviderApp *application); + +G_END_DECLS diff --git a/search-provider/meson.build b/search-provider/meson.build new file mode 100644 index 0000000..624641a --- /dev/null +++ b/search-provider/meson.build @@ -0,0 +1,47 @@ +service_conf = configuration_data() +service_conf.set('libexecdir', control_center_libexecdir) + +service = 'org.gnome.Settings.SearchProvider.service' + +configure_file( + input : service + '.in', + output : service, + install : true, + install_dir : join_paths(control_center_datadir, 'dbus-1', 'services'), + configuration : service_conf +) + +install_data( + 'org.gnome.Settings.search-provider.ini', + install_dir: join_paths(control_center_datadir, 'gnome-shell', 'search-providers') +) + +sources = files( + 'cc-search-provider.c', + 'control-center-search-provider.c' +) + +# The upstream for the DBus interface definition is +# at http://git.gnome.org/browse/gnome-shell/plain/data/org.gnome.ShellSearchProvider2.xml +sources += gnome.gdbus_codegen( + 'cc-shell-search-provider-generated', + 'org.gnome.ShellSearchProvider2.xml', + interface_prefix : 'org.gnome.', + namespace : 'Cc' +) + +libs = [ + libpanel_loader, + libshell +] + +executable( + 'gnome-control-center-search-provider', + sources, + include_directories : top_inc, + dependencies : shell_deps, + c_args : cflags, + link_with : libs, + install : true, + install_dir : control_center_libexecdir +) diff --git a/search-provider/org.gnome.Settings.SearchProvider.service.in b/search-provider/org.gnome.Settings.SearchProvider.service.in new file mode 100644 index 0000000..7cc98a3 --- /dev/null +++ b/search-provider/org.gnome.Settings.SearchProvider.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.gnome.Settings.SearchProvider +Exec=@libexecdir@/gnome-control-center-search-provider diff --git a/search-provider/org.gnome.Settings.search-provider.ini b/search-provider/org.gnome.Settings.search-provider.ini new file mode 100644 index 0000000..89dd949 --- /dev/null +++ b/search-provider/org.gnome.Settings.search-provider.ini @@ -0,0 +1,5 @@ +[Shell Search Provider] +DesktopId=org.gnome.Settings.desktop +BusName=org.gnome.Settings.SearchProvider +ObjectPath=/org/gnome/Settings/SearchProvider +Version=2 diff --git a/search-provider/org.gnome.ShellSearchProvider2.xml b/search-provider/org.gnome.ShellSearchProvider2.xml new file mode 100644 index 0000000..26b213d --- /dev/null +++ b/search-provider/org.gnome.ShellSearchProvider2.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3