commit bf66a4d1443da01955d03629b6fd71ab6aa91cdf
parent 74268f92c68c98757c16a7bce3b253297567744c
Author: Jacki <jacki@thejackimonster.de>
Date: Thu, 18 Jan 2024 23:01:22 +0100
Use libportal for requesting background permission
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
13 files changed, 791 insertions(+), 395 deletions(-)
diff --git a/meson.build b/meson.build
@@ -40,6 +40,8 @@ messenger_gtk_deps = [
dependency('gtk+-3.0'),
dependency('libhandy-1'),
dependency('gstreamer-1.0'),
+ dependency('libportal'),
+ dependency('libportal-gtk3'),
dependency('libnotify'),
dependency('libqrencode'),
declare_dependency(link_args: '-lunistring'),
diff --git a/resources/ui/settings.ui b/resources/ui/settings.ui
@@ -105,9 +105,8 @@ Author: Tobias Frisch
</packing>
</child>
<child>
- <object class="GtkSwitch">
+ <object class="GtkSwitch" id="start_on_login_switch">
<property name="visible">True</property>
- <property name="sensitive">False</property>
<property name="can-focus">True</property>
</object>
<packing>
@@ -147,9 +146,8 @@ Author: Tobias Frisch
</packing>
</child>
<child>
- <object class="GtkSwitch">
+ <object class="GtkSwitch" id="run_in_background_switch">
<property name="visible">True</property>
- <property name="sensitive">False</property>
<property name="can-focus">True</property>
</object>
<packing>
diff --git a/src/application.c b/src/application.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2022 GNUnet e.V.
+ Copyright (C) 2021--2024 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -23,11 +23,13 @@
*/
#include "application.h"
+#include "request.h"
#include "resources.h"
#include <gstreamer-1.0/gst/gst.h>
#include <gtk-3.0/gtk/gtk.h>
#include <libhandy-1/handy.h>
+#include <libportal-gtk3/portal-gtk3.h>
#include <libnotify/notify.h>
static void
@@ -37,14 +39,14 @@ _load_ui_stylesheets(MESSENGER_Application *app)
GtkCssProvider* provider = gtk_css_provider_new();
gtk_css_provider_load_from_resource(
- provider,
- application_get_resource_path(app, "css/style.css")
+ provider,
+ application_get_resource_path(app, "css/style.css")
);
gtk_style_context_add_provider_for_screen(
- screen,
- GTK_STYLE_PROVIDER(provider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
+ screen,
+ GTK_STYLE_PROVIDER(provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
}
@@ -67,15 +69,18 @@ _application_init(MESSENGER_Application *app)
{
ui_messenger_init(app, &(app->ui.messenger));
+ if (app->portal)
+ app->parent = xdp_parent_new_gtk(GTK_WINDOW(app->ui.messenger.main_window));
+
if (app->chat.identity)
- gtk_widget_show(GTK_WIDGET(app->ui.messenger.main_window));
+ application_show_window(app);
else
app->init = g_idle_add(G_SOURCE_FUNC(_application_accounts), app);
}
static void
_application_activate(GApplication* application,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -88,10 +93,10 @@ _application_activate(GApplication* application,
static void
_application_open(GApplication* application,
- GFile **files,
- gint n_files,
- UNUSED gchar* hint,
- gpointer user_data)
+ GFile **files,
+ gint n_files,
+ UNUSED gchar* hint,
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -132,8 +137,8 @@ _application_open(GApplication* application,
void
application_init(MESSENGER_Application *app,
- int argc,
- char **argv)
+ int argc,
+ char **argv)
{
memset(app, 0, sizeof(*app));
@@ -145,15 +150,25 @@ application_init(MESSENGER_Application *app,
hdy_init();
app->application = gtk_application_new(
- MESSENGER_APPLICATION_ID,
- G_APPLICATION_HANDLES_OPEN |
- G_APPLICATION_NON_UNIQUE
+ MESSENGER_APPLICATION_ID,
+ G_APPLICATION_HANDLES_OPEN |
+ G_APPLICATION_NON_UNIQUE
);
resources_register();
+ GError *error = NULL;
+ app->portal = xdp_portal_initable_new(&error);
+
+ if (!app->portal)
+ {
+ g_printerr("ERROR: %s\n", error->message);
+ g_error_free(error);
+ }
+
notify_init(MESSENGER_APPLICATION_NAME);
app->notifications = NULL;
+ app->requests = NULL;
_load_ui_stylesheets(app);
@@ -168,48 +183,48 @@ application_init(MESSENGER_Application *app,
app->quarks.ui = g_quark_from_string("messenger_ui");
g_application_add_main_option(
- G_APPLICATION(app->application),
- "mobile",
- 'm',
- G_OPTION_FLAG_NONE,
- G_OPTION_ARG_NONE,
- "Optimize UI spacing for mobile devices",
- NULL
+ G_APPLICATION(app->application),
+ "mobile",
+ 'm',
+ G_OPTION_FLAG_NONE,
+ G_OPTION_ARG_NONE,
+ "Optimize UI spacing for mobile devices",
+ NULL
);
g_application_add_main_option(
- G_APPLICATION(app->application),
- "ego",
- 'e',
- G_OPTION_FLAG_NONE,
- G_OPTION_ARG_STRING,
- "Identity to select for messaging",
- "IDENTITY"
+ G_APPLICATION(app->application),
+ "ego",
+ 'e',
+ G_OPTION_FLAG_NONE,
+ G_OPTION_ARG_STRING,
+ "Identity to select for messaging",
+ "IDENTITY"
);
g_signal_connect(
- app->application,
- "activate",
- G_CALLBACK(_application_activate),
- app
+ app->application,
+ "activate",
+ G_CALLBACK(_application_activate),
+ app
);
g_signal_connect(
- app->application,
- "open",
- G_CALLBACK(_application_open),
- app
+ app->application,
+ "open",
+ G_CALLBACK(_application_open),
+ app
);
}
const gchar*
application_get_resource_path(MESSENGER_Application *app,
- const char *path)
+ const char *path)
{
static gchar resource_path [PATH_MAX];
const gchar *base_path = g_application_get_resource_base_path(
- G_APPLICATION(app->application)
+ G_APPLICATION(app->application)
);
snprintf(resource_path, PATH_MAX, "%s/%s", base_path, path);
@@ -222,30 +237,30 @@ _application_chat_thread(void *args)
MESSENGER_Application *app = (MESSENGER_Application*) args;
struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_option_flag (
- 'm',
- "mobile",
- "Optimize UI spacing for mobile devices",
- &(app->settings.mobile_design)
- ),
- GNUNET_GETOPT_option_string (
- 'e',
- "ego",
- "IDENTITY",
- "Identity to select for messaging",
- &(app->chat.identity)
- ),
- GNUNET_GETOPT_OPTION_END
+ GNUNET_GETOPT_option_flag (
+ 'm',
+ "mobile",
+ "Optimize UI spacing for mobile devices",
+ &(app->settings.mobile_design)
+ ),
+ GNUNET_GETOPT_option_string (
+'e',
+ "ego",
+"IDENTITY",
+"Identity to select for messaging",
+ &(app->chat.identity)
+ ),
+ GNUNET_GETOPT_OPTION_END
};
app->chat.status = (GNUNET_PROGRAM_run(
- app->argc,
- app->argv,
- MESSENGER_APPLICATION_BINARY,
- gettext_noop(MESSENGER_APPLICATION_DESCRIPTION),
- options,
- &chat_messenger_run,
- app
+ app->argc,
+ app->argv,
+ MESSENGER_APPLICATION_BINARY,
+ gettext_noop(MESSENGER_APPLICATION_DESCRIPTION),
+ options,
+ &chat_messenger_run,
+ app
) == GNUNET_OK? EXIT_SUCCESS : EXIT_FAILURE);
return NULL;
@@ -255,12 +270,17 @@ void
application_run(MESSENGER_Application *app)
{
// Start thread to run GNUnet scheduler
- pthread_create(&(app->chat.tid), NULL, _application_chat_thread, app);
+ pthread_create(
+ &(app->chat.tid),
+ NULL,
+ _application_chat_thread,
+ app
+ );
app->ui.status = g_application_run(
- G_APPLICATION(app->application),
- app->argc,
- app->argv
+ G_APPLICATION(app->application),
+ app->argc,
+ app->argv
);
if (app->ui.status != 0)
@@ -274,16 +294,36 @@ application_run(MESSENGER_Application *app)
pthread_mutex_destroy(&(app->chat.mutex));
+ GList *list;
+
+ // Get rid of open requests
+ list = app->requests;
+
+ while (list)
+ {
+ if (list->data)
+ {
+ request_cancel((MESSENGER_Request*) list->data);
+ request_delete((MESSENGER_Request*) list->data);
+ }
+
+ list = list->next;
+ }
+
// Get rid of open notifications
- GList *list = app->notifications;
+ list = app->notifications;
- while (list) {
+ while (list)
+ {
if (list->data)
notify_notification_close(NOTIFY_NOTIFICATION(list->data), NULL);
list = list->next;
}
+ if (app->requests)
+ g_list_free(app->requests);
+
if (app->notifications)
g_list_free(app->notifications);
@@ -294,6 +334,51 @@ application_run(MESSENGER_Application *app)
g_object_unref(app->application);
}
+static void
+_request_background_callback(GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ XdpPortal *portal = XDP_PORTAL(source_object);
+ MESSENGER_Request *request = (MESSENGER_Request*) user_data;
+
+ request_cleanup(request);
+
+ gboolean *setting = (gboolean*) (request->user_data);
+
+ GError *error = NULL;
+ gboolean success = xdp_portal_request_background_finish(
+ portal, result, &error
+ );
+
+ if (!success) {
+ g_printerr("ERROR: %s\n", error->message);
+ g_error_free(error);
+ }
+
+ *setting = success;
+}
+
+void
+application_show_window(MESSENGER_Application *app)
+{
+ gtk_widget_show(GTK_WIDGET(app->ui.messenger.main_window));
+
+ request_new_background(
+ app,
+ XDP_BACKGROUND_FLAG_AUTOSTART,
+ _request_background_callback,
+ &(app->settings.autostart)
+ );
+
+ request_new_background(
+ app,
+ XDP_BACKGROUND_FLAG_ACTIVATABLE,
+ _request_background_callback,
+ &(app->settings.background_task)
+ );
+}
+
typedef struct MESSENGER_ApplicationEventCall
{
MESSENGER_Application *app;
@@ -318,12 +403,12 @@ _application_event_call(gpointer user_data)
void
application_call_event(MESSENGER_Application *app,
- MESSENGER_ApplicationEvent event)
+ MESSENGER_ApplicationEvent event)
{
MESSENGER_ApplicationEventCall *call;
call = (MESSENGER_ApplicationEventCall*) GNUNET_malloc(
- sizeof(MESSENGER_ApplicationEventCall)
+ sizeof(MESSENGER_ApplicationEventCall)
);
call->app = app;
@@ -359,8 +444,8 @@ _application_message_event_call(gpointer user_data)
void
application_call_message_event(MESSENGER_Application *app,
- MESSENGER_ApplicationMessageEvent event,
- struct GNUNET_CHAT_Context *context,
+ MESSENGER_ApplicationMessageEvent event,
+ struct GNUNET_CHAT_Context *context,
const struct GNUNET_CHAT_Message *message)
{
MESSENGER_ApplicationMessageEventCall *call;
@@ -369,7 +454,7 @@ application_call_message_event(MESSENGER_Application *app,
return;
call = (MESSENGER_ApplicationMessageEventCall*) GNUNET_malloc(
- sizeof(MESSENGER_ApplicationMessageEventCall)
+ sizeof(MESSENGER_ApplicationMessageEventCall)
);
call->app = app;
@@ -383,11 +468,16 @@ application_call_message_event(MESSENGER_Application *app,
void
application_exit(MESSENGER_Application *app,
- MESSENGER_ApplicationSignal signal)
+ MESSENGER_ApplicationSignal signal)
{
// Forward a signal to the other thread causing it to shutdown the
// GNUnet handles of the application.
write(app->chat.pipe[1], &signal, sizeof(signal));
+
+ if (app->portal)
+ g_free(app->portal);
+
+ app->portal = NULL;
}
int
diff --git a/src/application.h b/src/application.h
@@ -25,6 +25,8 @@
#ifndef APPLICATION_H_
#define APPLICATION_H_
+#include <libportal/portal.h>
+
#include <pthread.h>
#include <gnunet/gnunet_chat_lib.h>
@@ -69,8 +71,12 @@ typedef struct MESSENGER_Application
GtkApplication *application;
GList *notifications;
+ GList *requests;
guint init;
+ XdpPortal *portal;
+ XdpParent *parent;
+
struct {
GQuark widget;
GQuark data;
@@ -115,6 +121,9 @@ typedef struct MESSENGER_Application
gboolean mobile_design;
gboolean hide_delete_dialog;
+ gboolean autostart;
+ gboolean background_task;
+
gboolean disable_notifications;
gboolean send_read_receipts;
@@ -168,6 +177,14 @@ application_get_resource_path(MESSENGER_Application *app,
void
application_run(MESSENGER_Application *app);
+/**
+ * Shows the messenger application main window.
+ *
+ * @param app Messenger application
+ */
+void
+application_show_window(MESSENGER_Application *app);
+
typedef void (*MESSENGER_ApplicationEvent) (
MESSENGER_Application *app
);
diff --git a/src/meson.build b/src/meson.build
@@ -1,6 +1,6 @@
#
# This file is part of GNUnet.
-# Copyright (C) 2023 GNUnet e.V.
+# Copyright (C) 2023--2024 GNUnet e.V.
#
# GNUnet is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
@@ -26,6 +26,7 @@ messenger_gtk_sources = files([
'contact.c', 'contact.h',
'event.c', 'event.h',
'file.c', 'file.h',
+ 'request.c', 'request.h',
'resources.c', 'resources.h',
'ui.c', 'ui.h',
'util.h',
diff --git a/src/request.c b/src/request.c
@@ -0,0 +1,99 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2024 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file request.c
+ */
+
+#include "request.h"
+
+MESSENGER_Request*
+request_new(MESSENGER_Application *application,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ MESSENGER_Request* request = g_malloc(sizeof(MESSENGER_Request));
+
+ request->application = application;
+ request->cancellable = cancellable;
+ request->user_data = user_data;
+
+ application->requests = g_list_append(
+ application->requests,
+ request
+ );
+
+ return request;
+}
+
+MESSENGER_Request*
+request_new_background(MESSENGER_Application *application,
+ XdpBackgroundFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GCancellable* cancellable = g_cancellable_new();
+
+ MESSENGER_Request* request = request_new(
+ application,
+ cancellable,
+ user_data
+ );
+
+ xdp_portal_request_background(
+ application->portal,
+ application->parent,
+ NULL,
+ NULL,
+ flags,
+ cancellable,
+ callback,
+ request
+ );
+
+ return request;
+}
+
+void
+request_cancel(MESSENGER_Request *request)
+{
+ if (!request->cancellable)
+ return;
+
+ if (!g_cancellable_is_cancelled(request->cancellable))
+ g_cancellable_cancel(request->cancellable);
+}
+
+void
+request_cleanup(MESSENGER_Request *request)
+{
+ if (!request->cancellable)
+ return;
+
+ g_object_unref(request->cancellable);
+ request->cancellable = NULL;
+}
+
+void
+request_delete(MESSENGER_Request *request)
+{
+ request_cleanup(request);
+ g_free(request);
+}
diff --git a/src/request.h b/src/request.h
@@ -0,0 +1,59 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2024 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file request.h
+ */
+
+#ifndef REQUEST_H_
+#define REQUEST_H_
+
+#include <gio/gio.h>
+#include <libportal/portal.h>
+
+#include "application.h"
+
+typedef struct MESSENGER_Request {
+ MESSENGER_Application *application;
+ GCancellable *cancellable;
+ gpointer user_data;
+} MESSENGER_Request;
+
+MESSENGER_Request*
+request_new(MESSENGER_Application *application,
+ GCancellable *cancellable,
+ gpointer user_data);
+
+MESSENGER_Request*
+request_new_background(MESSENGER_Application *application,
+ XdpBackgroundFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+void
+request_cancel(MESSENGER_Request *request);
+
+void
+request_cleanup(MESSENGER_Request *request);
+
+void
+request_delete(MESSENGER_Request *request);
+
+#endif /* REQUEST_H_ */
diff --git a/src/ui/accounts.c b/src/ui/accounts.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2022 GNUnet e.V.
+ Copyright (C) 2022--2024 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -29,7 +29,7 @@
static void
handle_close_button_click(UNUSED GtkButton *button,
- gpointer user_data)
+ gpointer user_data)
{
GtkDialog *dialog = GTK_DIALOG(user_data);
gtk_window_close(GTK_WINDOW(dialog));
@@ -54,14 +54,14 @@ _show_messenger_main_window(gpointer user_data)
// Refresh the account list
ui_messenger_refresh(app, &(app->ui.messenger));
- gtk_widget_show(GTK_WIDGET(app->ui.messenger.main_window));
+ application_show_window(app);
return FALSE;
}
static void
handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
- GtkListBoxRow* row,
- gpointer user_data)
+ GtkListBoxRow* row,
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -69,14 +69,14 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
if (!gtk_list_box_row_get_selectable(row))
{
app->ui.accounts.show_queued = g_idle_add(
- G_SOURCE_FUNC(_open_new_account_dialog), app
+ G_SOURCE_FUNC(_open_new_account_dialog), app
);
goto close_dialog;
}
struct GNUNET_CHAT_Account *account = (struct GNUNET_CHAT_Account*) (
- g_object_get_qdata(G_OBJECT(row), app->quarks.data)
+ g_object_get_qdata(G_OBJECT(row), app->quarks.data)
);
if (!account)
@@ -85,7 +85,7 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
// Handle the GUI swap asyncronously
if (!gtk_widget_is_visible(GTK_WIDGET(app->ui.messenger.main_window)))
app->ui.accounts.show_queued = g_idle_add(
- G_SOURCE_FUNC(_show_messenger_main_window), app
+ G_SOURCE_FUNC(_show_messenger_main_window), app
);
GNUNET_CHAT_connect(app->chat.messenger.handle, account);
@@ -96,7 +96,7 @@ close_dialog:
static void
handle_dialog_destroy(UNUSED GtkWidget *window,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -109,8 +109,8 @@ handle_dialog_destroy(UNUSED GtkWidget *window,
static int
_iterate_accounts(void *cls,
- UNUSED const struct GNUNET_CHAT_Handle *handle,
- struct GNUNET_CHAT_Account *account)
+ UNUSED const struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Account *account)
{
MESSENGER_Application *app = (MESSENGER_Application*) cls;
@@ -121,16 +121,16 @@ _iterate_accounts(void *cls,
gtk_list_box_prepend(app->ui.accounts.accounts_listbox, entry->entry_box);
GtkListBoxRow *row = GTK_LIST_BOX_ROW(
- gtk_widget_get_parent(entry->entry_box)
+ gtk_widget_get_parent(entry->entry_box)
);
g_object_set_qdata(G_OBJECT(row), app->quarks.data, account);
g_object_set_qdata_full(
- G_OBJECT(row),
- app->quarks.ui,
- entry,
- (GDestroyNotify) ui_account_entry_delete
+ G_OBJECT(row),
+ app->quarks.ui,
+ entry,
+ (GDestroyNotify) ui_account_entry_delete
);
return GNUNET_YES;
@@ -138,62 +138,62 @@ _iterate_accounts(void *cls,
void
ui_accounts_dialog_init(MESSENGER_Application *app,
- UI_ACCOUNTS_Handle *handle)
+ UI_ACCOUNTS_Handle *handle)
{
handle->show_queued = 0;
handle->builder = gtk_builder_new_from_resource(
- application_get_resource_path(app, "ui/accounts.ui")
+ application_get_resource_path(app, "ui/accounts.ui")
);
handle->dialog = GTK_DIALOG(
- gtk_builder_get_object(handle->builder, "accounts_dialog")
+ gtk_builder_get_object(handle->builder, "accounts_dialog")
);
gtk_window_set_transient_for(
- GTK_WINDOW(handle->dialog),
- GTK_WINDOW(app->ui.messenger.main_window)
+ GTK_WINDOW(handle->dialog),
+ GTK_WINDOW(app->ui.messenger.main_window)
);
handle->accounts_listbox = GTK_LIST_BOX(
- gtk_builder_get_object(handle->builder, "accounts_listbox")
+ gtk_builder_get_object(handle->builder, "accounts_listbox")
);
g_signal_connect(
- handle->accounts_listbox,
- "row-activated",
- G_CALLBACK(handle_accounts_listbox_row_activated),
- app
+ handle->accounts_listbox,
+ "row-activated",
+ G_CALLBACK(handle_accounts_listbox_row_activated),
+ app
);
handle->close_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "close_button")
+ gtk_builder_get_object(handle->builder, "close_button")
);
g_signal_connect(
- handle->close_button,
- "clicked",
- G_CALLBACK(handle_close_button_click),
- handle->dialog
+ handle->close_button,
+ "clicked",
+ G_CALLBACK(handle_close_button_click),
+ handle->dialog
);
g_signal_connect(
- handle->dialog,
- "destroy",
- G_CALLBACK(handle_dialog_destroy),
- app
+ handle->dialog,
+ "destroy",
+ G_CALLBACK(handle_dialog_destroy),
+ app
);
}
void
ui_accounts_dialog_refresh(MESSENGER_Application *app,
- UI_ACCOUNTS_Handle *handle)
+ UI_ACCOUNTS_Handle *handle)
{
if (!(handle->accounts_listbox))
return;
GList *list = gtk_container_get_children(
- GTK_CONTAINER(handle->accounts_listbox)
+ GTK_CONTAINER(handle->accounts_listbox)
);
while (list)
@@ -204,8 +204,8 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app,
goto skip_row;
gtk_container_remove(
- GTK_CONTAINER(handle->accounts_listbox),
- GTK_WIDGET(row)
+ GTK_CONTAINER(handle->accounts_listbox),
+ GTK_WIDGET(row)
);
skip_row:
@@ -213,9 +213,9 @@ ui_accounts_dialog_refresh(MESSENGER_Application *app,
}
GNUNET_CHAT_iterate_accounts(
- app->chat.messenger.handle,
- _iterate_accounts,
- app
+ app->chat.messenger.handle,
+ _iterate_accounts,
+ app
);
}
diff --git a/src/ui/accounts.h b/src/ui/accounts.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2022 GNUnet e.V.
+ Copyright (C) 2022--2024 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -48,7 +48,7 @@ typedef struct UI_ACCOUNTS_Handle
*/
void
ui_accounts_dialog_init(MESSENGER_Application *app,
- UI_ACCOUNTS_Handle *handle);
+ UI_ACCOUNTS_Handle *handle);
/**
* Refreshes a given accounts dialog handle with the
@@ -59,7 +59,7 @@ ui_accounts_dialog_init(MESSENGER_Application *app,
*/
void
ui_accounts_dialog_refresh(MESSENGER_Application *app,
- UI_ACCOUNTS_Handle *handle);
+ UI_ACCOUNTS_Handle *handle);
/**
* Cleans up the allocated resources and resets the
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2022 GNUnet e.V.
+ Copyright (C) 2021--2024 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -58,21 +58,21 @@ _flap_user_details_reveal_switch(gpointer user_data)
static void
handle_user_details_via_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
UI_MESSENGER_Handle *handle = (UI_MESSENGER_Handle*) user_data;
gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_search), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(handle->chats_listbox), FALSE);
g_idle_add(
- G_SOURCE_FUNC(_flap_user_details_reveal_switch),
- handle
+ G_SOURCE_FUNC(_flap_user_details_reveal_switch),
+ handle
);
}
static void
handle_lobby_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -85,24 +85,24 @@ handle_lobby_button_click(UNUSED GtkButton* button,
static void
_switch_details_revealer_visibility(UI_MESSENGER_Handle *handle,
- gboolean state)
+ gboolean state)
{
GtkRevealer *revealer = handle->account_details_revealer;
GtkImage *symbol = handle->account_details_symbol;
gtk_revealer_set_reveal_child(revealer, state);
gtk_image_set_from_icon_name(
- symbol,
- state?
- "go-up-symbolic" :
- "go-down-symbolic",
- GTK_ICON_SIZE_BUTTON
+ symbol,
+ state?
+ "go-up-symbolic" :
+ "go-down-symbolic",
+ GTK_ICON_SIZE_BUTTON
);
}
static void
handle_account_details_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
UI_MESSENGER_Handle *handle = (UI_MESSENGER_Handle*) user_data;
@@ -115,8 +115,8 @@ handle_account_details_button_click(UNUSED GtkButton* button,
static void
handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
- GtkListBoxRow* row,
- gpointer user_data)
+ GtkListBoxRow* row,
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -132,7 +132,7 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
}
struct GNUNET_CHAT_Account *account = (struct GNUNET_CHAT_Account*) (
- g_object_get_qdata(G_OBJECT(row), app->quarks.data)
+ g_object_get_qdata(G_OBJECT(row), app->quarks.data)
);
if (!account)
@@ -146,7 +146,7 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
static void
handle_new_contact_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -157,7 +157,7 @@ handle_new_contact_button_click(UNUSED GtkButton* button,
static void
handle_new_group_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -168,7 +168,7 @@ handle_new_group_button_click(UNUSED GtkButton* button,
static void
handle_new_platform_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -179,7 +179,7 @@ handle_new_platform_button_click(UNUSED GtkButton* button,
static void
handle_contacts_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -190,7 +190,7 @@ handle_contacts_button_click(UNUSED GtkButton* button,
static void
handle_settings_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -201,7 +201,7 @@ handle_settings_button_click(UNUSED GtkButton* button,
static void
handle_about_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -212,8 +212,8 @@ handle_about_button_click(UNUSED GtkButton* button,
static void
handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox,
- GtkListBoxRow* row,
- gpointer user_data)
+ GtkListBoxRow* row,
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -221,7 +221,7 @@ handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox,
return;
UI_CHAT_ENTRY_Handle *entry = (UI_CHAT_ENTRY_Handle*) (
- g_object_get_qdata(G_OBJECT(row), app->quarks.ui)
+ g_object_get_qdata(G_OBJECT(row), app->quarks.ui)
);
if ((!entry) || (!(entry->chat)) || (!(entry->chat->chat_box)))
@@ -241,8 +241,8 @@ handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox,
static gint
handle_chats_listbox_sort_func(GtkListBoxRow* row0,
- GtkListBoxRow* row1,
- gpointer user_data)
+ GtkListBoxRow* row1,
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -252,11 +252,11 @@ handle_chats_listbox_sort_func(GtkListBoxRow* row0,
return 0;
UI_CHAT_ENTRY_Handle *entry0 = (UI_CHAT_ENTRY_Handle*) (
- g_object_get_qdata(G_OBJECT(row0), app->quarks.ui)
+ g_object_get_qdata(G_OBJECT(row0), app->quarks.ui)
);
UI_CHAT_ENTRY_Handle *entry1 = (UI_CHAT_ENTRY_Handle*) (
- g_object_get_qdata(G_OBJECT(row1), app->quarks.ui)
+ g_object_get_qdata(G_OBJECT(row1), app->quarks.ui)
);
if ((!entry0) || (!entry1))
@@ -275,7 +275,7 @@ handle_chats_listbox_sort_func(GtkListBoxRow* row0,
static gboolean
handle_chats_listbox_filter_func(GtkListBoxRow *row,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
@@ -284,14 +284,14 @@ handle_chats_listbox_filter_func(GtkListBoxRow *row,
return TRUE;
const gchar *filter = gtk_entry_get_text(
- GTK_ENTRY(app->ui.messenger.chats_search)
+ GTK_ENTRY(app->ui.messenger.chats_search)
);
if (!filter)
return TRUE;
UI_CHAT_ENTRY_Handle *entry = (UI_CHAT_ENTRY_Handle*) (
- g_object_get_qdata(G_OBJECT(row), app->quarks.ui)
+ g_object_get_qdata(G_OBJECT(row), app->quarks.ui)
);
if ((!entry) || (!(entry->title_label)))
@@ -307,7 +307,7 @@ handle_chats_listbox_filter_func(GtkListBoxRow *row,
static void
handle_chats_search_changed(UNUSED GtkSearchEntry *search,
- gpointer user_data)
+ gpointer user_data)
{
GtkListBox *listbox = GTK_LIST_BOX(user_data);
@@ -316,10 +316,15 @@ handle_chats_search_changed(UNUSED GtkSearchEntry *search,
static void
handle_main_window_destroy(UNUSED GtkWidget *window,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
+ if (app->parent)
+ xdp_parent_free(app->parent);
+
+ app->parent = NULL;
+
ui_messenger_cleanup(&(app->ui.messenger));
ui_accounts_dialog_cleanup(&(app->ui.accounts));
@@ -328,85 +333,85 @@ handle_main_window_destroy(UNUSED GtkWidget *window,
void
ui_messenger_init(MESSENGER_Application *app,
- UI_MESSENGER_Handle *handle)
+ UI_MESSENGER_Handle *handle)
{
memset(handle, 0, sizeof(*handle));
handle->app = app;
handle->builder = gtk_builder_new_from_resource(
- application_get_resource_path(app, "ui/messenger.ui")
+ application_get_resource_path(app, "ui/messenger.ui")
);
handle->main_window = GTK_APPLICATION_WINDOW(
- gtk_builder_get_object(handle->builder, "main_window")
+ gtk_builder_get_object(handle->builder, "main_window")
);
gtk_window_set_startup_id(
- GTK_WINDOW(handle->main_window),
- MESSENGER_APPLICATION_ID
+ GTK_WINDOW(handle->main_window),
+ MESSENGER_APPLICATION_ID
);
gtk_window_set_icon_name(
- GTK_WINDOW(handle->main_window),
- MESSENGER_APPLICATION_ID
+ GTK_WINDOW(handle->main_window),
+ MESSENGER_APPLICATION_ID
);
gtk_application_add_window(
- app->application,
- GTK_WINDOW(handle->main_window)
+ app->application,
+ GTK_WINDOW(handle->main_window)
);
gtk_window_set_default_size(
- GTK_WINDOW(handle->main_window),
- 1100, 700
+ GTK_WINDOW(handle->main_window),
+ 1100, 700
);
handle->leaflet_chat = HDY_LEAFLET(
- gtk_builder_get_object(handle->builder, "leaflet_chat")
+ gtk_builder_get_object(handle->builder, "leaflet_chat")
);
handle->flap_user_details = HDY_FLAP(
- gtk_builder_get_object(handle->builder, "flap_user_details")
+ gtk_builder_get_object(handle->builder, "flap_user_details")
);
handle->title_bar = HDY_HEADER_BAR(
- gtk_builder_get_object(handle->builder, "title_bar")
+ gtk_builder_get_object(handle->builder, "title_bar")
);
GtkLabel* application_name_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "application-name-label")
+ gtk_builder_get_object(handle->builder, "application-name-label")
);
GtkLabel* application_version_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "application-version-label")
+ gtk_builder_get_object(handle->builder, "application-version-label")
);
hdy_header_bar_set_title(
- handle->title_bar,
- MESSENGER_APPLICATION_TITLE
+ handle->title_bar,
+ MESSENGER_APPLICATION_TITLE
);
hdy_header_bar_set_subtitle(
- handle->title_bar,
- MESSENGER_APPLICATION_SUBTITLE
+ handle->title_bar,
+ MESSENGER_APPLICATION_SUBTITLE
);
gtk_label_set_text(
- application_name_label,
- MESSENGER_APPLICATION_APPNAME
+ application_name_label,
+ MESSENGER_APPLICATION_APPNAME
);
gtk_label_set_text(
- application_version_label,
- MESSENGER_APPLICATION_VERSION
+ application_version_label,
+ MESSENGER_APPLICATION_VERSION
);
g_object_bind_property(
- handle->leaflet_chat,
- "folded",
- handle->title_bar,
- "show-close-button",
- G_BINDING_INVERT_BOOLEAN
+ handle->leaflet_chat,
+ "folded",
+ handle->title_bar,
+ "show-close-button",
+ G_BINDING_INVERT_BOOLEAN
);
if (app->settings.mobile_design)
@@ -420,206 +425,206 @@ ui_messenger_init(MESSENGER_Application *app,
);
handle->profile_avatar = HDY_AVATAR(
- gtk_builder_get_object(handle->builder, "profile_avatar")
+ gtk_builder_get_object(handle->builder, "profile_avatar")
);
handle->profile_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "profile_label")
+ gtk_builder_get_object(handle->builder, "profile_label")
);
handle->profile_key_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "profile_key_label")
+ gtk_builder_get_object(handle->builder, "profile_key_label")
);
handle->hide_user_details_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "hide_user_details_button")
+ gtk_builder_get_object(handle->builder, "hide_user_details_button")
);
g_signal_connect(
- handle->hide_user_details_button,
- "clicked",
- G_CALLBACK(handle_user_details_via_button_click),
- handle
+ handle->hide_user_details_button,
+ "clicked",
+ G_CALLBACK(handle_user_details_via_button_click),
+ handle
);
handle->lobby_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "lobby_button")
+ gtk_builder_get_object(handle->builder, "lobby_button")
);
g_signal_connect(
- handle->lobby_button,
- "clicked",
- G_CALLBACK(handle_lobby_button_click),
- app
+ handle->lobby_button,
+ "clicked",
+ G_CALLBACK(handle_lobby_button_click),
+ app
);
handle->account_details_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "account_details_button")
+ gtk_builder_get_object(handle->builder, "account_details_button")
);
handle->account_details_symbol = GTK_IMAGE(
- gtk_builder_get_object(handle->builder, "account_details_symbol")
+ gtk_builder_get_object(handle->builder, "account_details_symbol")
);
handle->account_details_revealer = GTK_REVEALER(
- gtk_builder_get_object(handle->builder, "account_details_revealer")
+ gtk_builder_get_object(handle->builder, "account_details_revealer")
);
g_signal_connect(
- handle->account_details_button,
- "clicked",
- G_CALLBACK(handle_account_details_button_click),
- handle
+ handle->account_details_button,
+ "clicked",
+ G_CALLBACK(handle_account_details_button_click),
+ handle
);
handle->accounts_listbox = GTK_LIST_BOX(
- gtk_builder_get_object(handle->builder, "accounts_listbox")
+ gtk_builder_get_object(handle->builder, "accounts_listbox")
);
handle->add_account_listbox_row = GTK_LIST_BOX_ROW(
- gtk_builder_get_object(handle->builder, "add_account_listbox_row")
+ gtk_builder_get_object(handle->builder, "add_account_listbox_row")
);
g_signal_connect(
- handle->accounts_listbox,
- "row-activated",
- G_CALLBACK(handle_accounts_listbox_row_activated),
- app
+ handle->accounts_listbox,
+ "row-activated",
+ G_CALLBACK(handle_accounts_listbox_row_activated),
+ app
);
handle->new_contact_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "new_contact_button")
+ gtk_builder_get_object(handle->builder, "new_contact_button")
);
handle->new_group_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "new_group_button")
+ gtk_builder_get_object(handle->builder, "new_group_button")
);
handle->new_platform_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "new_platform_button")
+ gtk_builder_get_object(handle->builder, "new_platform_button")
);
g_signal_connect(
- handle->new_contact_button,
- "clicked",
- G_CALLBACK(handle_new_contact_button_click),
- app
+ handle->new_contact_button,
+ "clicked",
+ G_CALLBACK(handle_new_contact_button_click),
+ app
);
g_signal_connect(
- handle->new_group_button,
- "clicked",
- G_CALLBACK(handle_new_group_button_click),
- app
+ handle->new_group_button,
+ "clicked",
+ G_CALLBACK(handle_new_group_button_click),
+ app
);
g_signal_connect(
- handle->new_platform_button,
- "clicked",
- G_CALLBACK(handle_new_platform_button_click),
- app
+ handle->new_platform_button,
+ "clicked",
+ G_CALLBACK(handle_new_platform_button_click),
+ app
);
handle->contacts_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "contacts_button")
+ gtk_builder_get_object(handle->builder, "contacts_button")
);
handle->settings_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "settings_button")
+ gtk_builder_get_object(handle->builder, "settings_button")
);
g_signal_connect(
- handle->contacts_button,
- "clicked",
- G_CALLBACK(handle_contacts_button_click),
- app
+ handle->contacts_button,
+ "clicked",
+ G_CALLBACK(handle_contacts_button_click),
+ app
);
g_signal_connect(
- handle->settings_button,
- "clicked",
- G_CALLBACK(handle_settings_button_click),
- app
+ handle->settings_button,
+ "clicked",
+ G_CALLBACK(handle_settings_button_click),
+ app
);
handle->about_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "about_button")
+ gtk_builder_get_object(handle->builder, "about_button")
);
g_signal_connect(
- handle->about_button,
- "clicked",
- G_CALLBACK(handle_about_button_click),
- app
+ handle->about_button,
+ "clicked",
+ G_CALLBACK(handle_about_button_click),
+ app
);
handle->user_details_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "user_details_button")
+ gtk_builder_get_object(handle->builder, "user_details_button")
);
g_signal_connect(
- handle->user_details_button,
- "clicked",
- G_CALLBACK(handle_user_details_via_button_click),
- handle
+ handle->user_details_button,
+ "clicked",
+ G_CALLBACK(handle_user_details_via_button_click),
+ handle
);
handle->chats_search = GTK_SEARCH_ENTRY(
- gtk_builder_get_object(handle->builder, "chats_search")
+ gtk_builder_get_object(handle->builder, "chats_search")
);
handle->chats_listbox = GTK_LIST_BOX(
- gtk_builder_get_object(handle->builder, "chats_listbox")
+ gtk_builder_get_object(handle->builder, "chats_listbox")
);
gtk_list_box_set_sort_func(
- handle->chats_listbox,
- handle_chats_listbox_sort_func,
- app,
- NULL
+ handle->chats_listbox,
+ handle_chats_listbox_sort_func,
+ app,
+ NULL
);
gtk_list_box_set_filter_func(
- handle->chats_listbox,
- handle_chats_listbox_filter_func,
- app,
- NULL
+ handle->chats_listbox,
+ handle_chats_listbox_filter_func,
+ app,
+ NULL
);
g_signal_connect(
- handle->chats_search,
- "search-changed",
- G_CALLBACK(handle_chats_search_changed),
- handle->chats_listbox
+ handle->chats_search,
+ "search-changed",
+ G_CALLBACK(handle_chats_search_changed),
+ handle->chats_listbox
);
g_signal_connect(
- handle->chats_listbox,
- "row-activated",
- G_CALLBACK(handle_chats_listbox_row_activated),
- app
+ handle->chats_listbox,
+ "row-activated",
+ G_CALLBACK(handle_chats_listbox_row_activated),
+ app
);
handle->chats_stack = GTK_STACK(
- gtk_builder_get_object(handle->builder, "chats_stack")
+ gtk_builder_get_object(handle->builder, "chats_stack")
);
handle->no_chat_box = GTK_WIDGET(
- gtk_builder_get_object(handle->builder, "no_chat_box")
+ gtk_builder_get_object(handle->builder, "no_chat_box")
);
g_signal_connect(
- handle->main_window,
- "destroy",
- G_CALLBACK(handle_main_window_destroy),
- app
+ handle->main_window,
+ "destroy",
+ G_CALLBACK(handle_main_window_destroy),
+ app
);
}
static int
_messenger_iterate_accounts(void *cls,
- const struct GNUNET_CHAT_Handle *handle,
- struct GNUNET_CHAT_Account *account)
+ const struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Account *account)
{
MESSENGER_Application *app = (MESSENGER_Application*) cls;
UI_MESSENGER_Handle *ui = &(app->ui.messenger);
@@ -647,7 +652,7 @@ _messenger_iterate_accounts(void *cls,
static void
_clear_accounts_listbox(GtkWidget *widget,
- gpointer data)
+ gpointer data)
{
GtkListBoxRow *row = GTK_LIST_BOX_ROW(widget);
GtkListBox *listbox = GTK_LIST_BOX(data);
@@ -656,34 +661,34 @@ _clear_accounts_listbox(GtkWidget *widget,
return;
gtk_container_remove(
- GTK_CONTAINER(listbox),
- widget
+ GTK_CONTAINER(listbox),
+ widget
);
}
void
ui_messenger_refresh(MESSENGER_Application *app,
- UI_MESSENGER_Handle *handle)
+ UI_MESSENGER_Handle *handle)
{
if (!(handle->accounts_listbox))
return;
gtk_container_foreach(
- GTK_CONTAINER(handle->accounts_listbox),
- _clear_accounts_listbox,
- handle->accounts_listbox
+ GTK_CONTAINER(handle->accounts_listbox),
+ _clear_accounts_listbox,
+ handle->accounts_listbox
);
GNUNET_CHAT_iterate_accounts(
- app->chat.messenger.handle,
- _messenger_iterate_accounts,
- app
+ app->chat.messenger.handle,
+ _messenger_iterate_accounts,
+ app
);
}
gboolean
ui_messenger_is_context_active(UI_MESSENGER_Handle *handle,
- struct GNUNET_CHAT_Context *context)
+ struct GNUNET_CHAT_Context *context)
{
if (!gtk_window_is_active(GTK_WINDOW(handle->main_window)))
return FALSE;
@@ -694,7 +699,7 @@ ui_messenger_is_context_active(UI_MESSENGER_Handle *handle,
return FALSE;
GtkListBoxRow *row = GTK_LIST_BOX_ROW(
- gtk_widget_get_parent(entry->entry_box)
+ gtk_widget_get_parent(entry->entry_box)
);
if (!row)
diff --git a/src/ui/picker.c b/src/ui/picker.c
@@ -209,7 +209,7 @@ handle_emoji_search_entry_search_changed(GtkSearchEntry *entry,
static void
handle_search_button_click(UNUSED GtkButton *button,
- gpointer user_data)
+ gpointer user_data)
{
UI_PICKER_Handle *handle = (UI_PICKER_Handle*) user_data;
@@ -222,17 +222,16 @@ handle_search_button_click(UNUSED GtkButton *button,
if (search_bar)
hdy_search_bar_set_search_mode(
- search_bar,
- !hdy_search_bar_get_search_mode(search_bar)
+ search_bar,
+ !hdy_search_bar_get_search_mode(search_bar)
);
}
static void
handle_settings_button_click(UNUSED GtkButton *button,
- gpointer user_data)
+ UNUSED gpointer user_data)
{
- MESSENGER_Application *app = (MESSENGER_Application*) user_data;
-
+ // MESSENGER_Application *app = (MESSENGER_Application*) user_data;
// TODO
}
diff --git a/src/ui/settings.c b/src/ui/settings.c
@@ -25,30 +25,99 @@
#include "settings.h"
#include "../application.h"
+#include "../request.h"
+
#include <gnunet/gnunet_chat_lib.h>
#include <gnunet/gnunet_common.h>
+#include <libportal/background.h>
static gboolean
handle_general_switch_state(UNUSED GtkSwitch *widget,
- gboolean state,
- gpointer user_data)
+ gboolean state,
+ gpointer user_data)
{
gboolean *setting = (gboolean*) user_data;
*setting = state;
return FALSE;
}
+static void
+_request_background_callback(GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ XdpPortal *portal = XDP_PORTAL(source_object);
+ MESSENGER_Request *request = (MESSENGER_Request*) user_data;
+
+ request_cleanup(request);
+
+ MESSENGER_Application *app = request->application;
+ GtkSwitch *widget = GTK_SWITCH(request->user_data);
+
+ GError *error = NULL;
+ gboolean success = xdp_portal_request_background_finish(
+ portal, result, &error
+ );
+
+ if (!success) {
+ g_printerr("ERROR: %s\n", error->message);
+ g_error_free(error);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE);
+ gtk_switch_set_active(widget, FALSE);
+ return;
+ }
+
+ gboolean *setting = (gboolean*) (
+ g_object_get_qdata(G_OBJECT(widget), app->quarks.data)
+ );
+
+ handle_general_switch_state(widget, success, setting);
+}
+
+static gboolean
+handle_background_switch_state(GtkSwitch *widget,
+ gboolean state,
+ gpointer user_data)
+{
+ MESSENGER_Application *app = (MESSENGER_Application*) user_data;
+
+ gboolean *setting = (gboolean*) (
+ g_object_get_qdata(G_OBJECT(widget), app->quarks.data)
+ );
+
+ if ((!state) || (!gtk_widget_is_sensitive(GTK_WIDGET(widget))))
+ return handle_general_switch_state(widget, state, setting);
+
+ XdpBackgroundFlags flags = XDP_BACKGROUND_FLAG_NONE;
+
+ if (&(app->settings.autostart) == setting)
+ flags |= XDP_BACKGROUND_FLAG_AUTOSTART;
+ if (&(app->settings.background_task) == setting)
+ flags |= XDP_BACKGROUND_FLAG_ACTIVATABLE;
+
+ request_new_background(
+ app,
+ flags,
+ _request_background_callback,
+ widget
+ );
+
+ gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE);
+ return FALSE;
+}
+
static gboolean
handle_inverted_switch_state(GtkSwitch *widget,
- gboolean state,
- gpointer user_data)
+ gboolean state,
+ gpointer user_data)
{
return handle_general_switch_state(widget, !state, user_data);
}
static void
handle_general_combo_box_change(GtkComboBox *widget,
- gpointer user_data)
+ gpointer user_data)
{
gulong *delay = (gulong*) user_data;
GtkTreeModel *model = gtk_combo_box_get_model(widget);
@@ -60,8 +129,8 @@ handle_general_combo_box_change(GtkComboBox *widget,
int
_leave_group_iteration(UNUSED void *cls,
- UNUSED struct GNUNET_CHAT_Handle *handle,
- struct GNUNET_CHAT_Group *group)
+ UNUSED struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Group *group)
{
GNUNET_CHAT_group_leave(group);
return GNUNET_YES;
@@ -69,8 +138,8 @@ _leave_group_iteration(UNUSED void *cls,
int
_delete_contact_iteration(UNUSED void *cls,
- UNUSED struct GNUNET_CHAT_Handle *handle,
- struct GNUNET_CHAT_Contact *contact)
+ UNUSED struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Contact *contact)
{
GNUNET_CHAT_contact_delete(contact);
return GNUNET_YES;
@@ -78,20 +147,20 @@ _delete_contact_iteration(UNUSED void *cls,
static void
handle_leave_chats_button_click(UNUSED GtkButton* button,
- gpointer user_data)
+ gpointer user_data)
{
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
GNUNET_CHAT_iterate_groups(
- app->chat.messenger.handle,
- _leave_group_iteration,
- NULL
+ app->chat.messenger.handle,
+ _leave_group_iteration,
+ NULL
);
GNUNET_CHAT_iterate_contacts(
- app->chat.messenger.handle,
- _delete_contact_iteration,
- NULL
+ app->chat.messenger.handle,
+ _delete_contact_iteration,
+ NULL
);
}
@@ -145,218 +214,272 @@ ui_settings_dialog_init(MESSENGER_Application *app,
UI_SETTINGS_Handle *handle)
{
handle->builder = gtk_builder_new_from_resource(
- application_get_resource_path(app, "ui/settings.ui")
+ application_get_resource_path(app, "ui/settings.ui")
);
handle->dialog = HDY_PREFERENCES_WINDOW(
- gtk_builder_get_object(handle->builder, "settings_dialog")
+ gtk_builder_get_object(handle->builder, "settings_dialog")
);
gtk_window_set_transient_for(
- GTK_WINDOW(handle->dialog),
- GTK_WINDOW(app->ui.messenger.main_window)
+ GTK_WINDOW(handle->dialog),
+ GTK_WINDOW(app->ui.messenger.main_window)
+ );
+
+ handle->start_on_login_switch = GTK_SWITCH(
+ gtk_builder_get_object(handle->builder, "start_on_login_switch")
+ );
+
+ gtk_switch_set_active(
+ handle->start_on_login_switch,
+ app->settings.autostart
+ );
+
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(handle->start_on_login_switch),
+ !(app->settings.autostart)
+ );
+
+ g_object_set_qdata(
+ G_OBJECT(handle->start_on_login_switch),
+ app->quarks.data,
+ &(app->settings.autostart)
+ );
+
+ g_signal_connect(
+ handle->start_on_login_switch,
+ "state-set",
+ G_CALLBACK(handle_background_switch_state),
+ app
+ );
+
+ handle->run_in_background_switch = GTK_SWITCH(
+ gtk_builder_get_object(handle->builder, "run_in_background_switch")
+ );
+
+ gtk_switch_set_active(
+ handle->run_in_background_switch,
+ app->settings.background_task
+ );
+
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(handle->run_in_background_switch),
+ !(app->settings.background_task)
+ );
+
+ g_object_set_qdata(
+ G_OBJECT(handle->run_in_background_switch),
+ app->quarks.data,
+ &(app->settings.background_task)
+ );
+
+ g_signal_connect(
+ handle->run_in_background_switch,
+ "state-set",
+ G_CALLBACK(handle_background_switch_state),
+ app
);
handle->enable_notifications_switch = GTK_SWITCH(
- gtk_builder_get_object(handle->builder, "enable_notifications_switch")
+ gtk_builder_get_object(handle->builder, "enable_notifications_switch")
);
gtk_switch_set_active(
- handle->enable_notifications_switch,
- !(app->settings.disable_notifications)
+ handle->enable_notifications_switch,
+ !(app->settings.disable_notifications)
);
g_signal_connect(
- handle->enable_notifications_switch,
- "state-set",
- G_CALLBACK(handle_inverted_switch_state),
- &(app->settings.disable_notifications)
+ handle->enable_notifications_switch,
+ "state-set",
+ G_CALLBACK(handle_inverted_switch_state),
+ &(app->settings.disable_notifications)
);
handle->blocked_label = GTK_LABEL(
- gtk_builder_get_object(handle->builder, "blocked_label")
+ gtk_builder_get_object(handle->builder, "blocked_label")
);
guint blocked_count = 0;
GNUNET_CHAT_iterate_contacts(
- app->chat.messenger.handle,
- _count_blocked_contacts,
- &blocked_count
+ app->chat.messenger.handle,
+ _count_blocked_contacts,
+ &blocked_count
);
GString *blocked_text = g_string_new(NULL);
if (blocked_text)
{
g_string_printf(
- blocked_text,
- "%u blocked contacts",
- blocked_count
+ blocked_text,
+ "%u blocked contacts",
+ blocked_count
);
gtk_label_set_text(
- handle->blocked_label,
- blocked_text->str
+ handle->blocked_label,
+ blocked_text->str
);
g_string_free(blocked_text, TRUE);
}
handle->read_receipts_switch = GTK_SWITCH(
- gtk_builder_get_object(handle->builder, "read_receipts_switch")
+ gtk_builder_get_object(handle->builder, "read_receipts_switch")
);
gtk_switch_set_active(
- handle->read_receipts_switch,
- app->settings.send_read_receipts
+ handle->read_receipts_switch,
+ app->settings.send_read_receipts
);
g_signal_connect(
- handle->read_receipts_switch,
- "state-set",
- G_CALLBACK(handle_general_switch_state),
- &(app->settings.send_read_receipts)
+ handle->read_receipts_switch,
+ "state-set",
+ G_CALLBACK(handle_general_switch_state),
+ &(app->settings.send_read_receipts)
);
handle->whispering_switch = GTK_SWITCH(
- gtk_builder_get_object(handle->builder, "whispering_switch")
+ gtk_builder_get_object(handle->builder, "whispering_switch")
);
gtk_switch_set_active(
- handle->whispering_switch,
- app->settings.show_whispering
+ handle->whispering_switch,
+ app->settings.show_whispering
);
g_signal_connect(
- handle->whispering_switch,
- "state-set",
- G_CALLBACK(handle_general_switch_state),
- &(app->settings.show_whispering)
+ handle->whispering_switch,
+ "state-set",
+ G_CALLBACK(handle_general_switch_state),
+ &(app->settings.show_whispering)
);
handle->auto_delete_combo_box = GTK_COMBO_BOX(
- gtk_builder_get_object(handle->builder, "auto_delete_combo_box")
+ gtk_builder_get_object(handle->builder, "auto_delete_combo_box")
);
_set_combobox_to_active_by_delay(
- handle->auto_delete_combo_box,
- app->settings.auto_delete_delay
+ handle->auto_delete_combo_box,
+ app->settings.auto_delete_delay
);
g_signal_connect(
- handle->auto_delete_combo_box,
- "changed",
- G_CALLBACK(handle_general_combo_box_change),
- &(app->settings.auto_delete_delay)
+ handle->auto_delete_combo_box,
+ "changed",
+ G_CALLBACK(handle_general_combo_box_change),
+ &(app->settings.auto_delete_delay)
);
handle->auto_accept_invitations_switch = GTK_SWITCH(
- gtk_builder_get_object(handle->builder, "auto_accept_invitations_switch")
+ gtk_builder_get_object(handle->builder, "auto_accept_invitations_switch")
);
gtk_switch_set_active(
- handle->auto_accept_invitations_switch,
- app->settings.accept_all_invitations
+ handle->auto_accept_invitations_switch,
+ app->settings.accept_all_invitations
);
g_signal_connect(
- handle->auto_accept_invitations_switch,
- "state-set",
- G_CALLBACK(handle_general_switch_state),
- &(app->settings.accept_all_invitations)
+ handle->auto_accept_invitations_switch,
+ "state-set",
+ G_CALLBACK(handle_general_switch_state),
+ &(app->settings.accept_all_invitations)
);
handle->delete_invitations_combo_box = GTK_COMBO_BOX(
- gtk_builder_get_object(handle->builder, "delete_invitations_combo_box")
+ gtk_builder_get_object(handle->builder, "delete_invitations_combo_box")
);
_set_combobox_to_active_by_delay(
- handle->delete_invitations_combo_box,
- app->settings.delete_invitations_delay
+ handle->delete_invitations_combo_box,
+ app->settings.delete_invitations_delay
);
g_signal_connect(
- handle->delete_invitations_combo_box,
- "changed",
- G_CALLBACK(handle_general_combo_box_change),
- &(app->settings.delete_invitations_delay)
+ handle->delete_invitations_combo_box,
+ "changed",
+ G_CALLBACK(handle_general_combo_box_change),
+ &(app->settings.delete_invitations_delay)
);
handle->delete_invitations_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "delete_invitations_button")
+ gtk_builder_get_object(handle->builder, "delete_invitations_button")
);
handle->auto_accept_files_switch = GTK_SWITCH(
- gtk_builder_get_object(handle->builder, "auto_accept_files_switch")
+ gtk_builder_get_object(handle->builder, "auto_accept_files_switch")
);
gtk_switch_set_active(
- handle->auto_accept_files_switch,
- app->settings.accept_all_files
+ handle->auto_accept_files_switch,
+ app->settings.accept_all_files
);
g_signal_connect(
- handle->auto_accept_files_switch,
- "state-set",
- G_CALLBACK(handle_general_switch_state),
- &(app->settings.accept_all_files)
+ handle->auto_accept_files_switch,
+ "state-set",
+ G_CALLBACK(handle_general_switch_state),
+ &(app->settings.accept_all_files)
);
handle->download_folder_button = GTK_FILE_CHOOSER_BUTTON(
- gtk_builder_get_object(handle->builder, "download_folder_button")
+ gtk_builder_get_object(handle->builder, "download_folder_button")
);
handle->delete_files_combo_box = GTK_COMBO_BOX(
- gtk_builder_get_object(handle->builder, "delete_files_combo_box")
+ gtk_builder_get_object(handle->builder, "delete_files_combo_box")
);
_set_combobox_to_active_by_delay(
- handle->delete_files_combo_box,
- app->settings.delete_files_delay
+ handle->delete_files_combo_box,
+ app->settings.delete_files_delay
);
g_signal_connect(
- handle->delete_files_combo_box,
- "changed",
- G_CALLBACK(handle_general_combo_box_change),
- &(app->settings.delete_files_delay)
+ handle->delete_files_combo_box,
+ "changed",
+ G_CALLBACK(handle_general_combo_box_change),
+ &(app->settings.delete_files_delay)
);
handle->delete_files_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "delete_files_button")
+ gtk_builder_get_object(handle->builder, "delete_files_button")
);
handle->leave_chats_combo_box = GTK_COMBO_BOX(
- gtk_builder_get_object(handle->builder, "leave_chats_combo_box")
+ gtk_builder_get_object(handle->builder, "leave_chats_combo_box")
);
_set_combobox_to_active_by_delay(
- handle->leave_chats_combo_box,
- app->settings.leave_chats_delay
+ handle->leave_chats_combo_box,
+ app->settings.leave_chats_delay
);
g_signal_connect(
- handle->leave_chats_combo_box,
- "changed",
- G_CALLBACK(handle_general_combo_box_change),
- &(app->settings.leave_chats_delay)
+ handle->leave_chats_combo_box,
+ "changed",
+ G_CALLBACK(handle_general_combo_box_change),
+ &(app->settings.leave_chats_delay)
);
handle->leave_chats_button = GTK_BUTTON(
- gtk_builder_get_object(handle->builder, "leave_chats_button")
+ gtk_builder_get_object(handle->builder, "leave_chats_button")
);
g_signal_connect(
- handle->leave_chats_button,
- "clicked",
- G_CALLBACK(handle_leave_chats_button_click),
- app
+ handle->leave_chats_button,
+ "clicked",
+ G_CALLBACK(handle_leave_chats_button_click),
+ app
);
g_signal_connect(
- handle->dialog,
- "destroy",
- G_CALLBACK(handle_dialog_destroy),
- handle
+ handle->dialog,
+ "destroy",
+ G_CALLBACK(handle_dialog_destroy),
+ handle
);
}
diff --git a/src/ui/settings.h b/src/ui/settings.h
@@ -32,6 +32,9 @@ typedef struct UI_SETTINGS_Handle
GtkBuilder *builder;
HdyPreferencesWindow *dialog;
+ GtkSwitch *start_on_login_switch;
+ GtkSwitch *run_in_background_switch;
+
GtkSwitch *enable_notifications_switch;
GtkLabel *blocked_label;