messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit ee55ecb8712955fc1d982b3a271c909896eb0631
parent 7e0a36c3954f7a054a3a7acab1cdfb239a466917
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Sat, 30 Oct 2021 21:13:51 +0200

Separated gtk, gnunet and events using both

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>

Diffstat:
MMakefile | 2++
Mresources/ui/messenger.ui | 1+
Asrc/application.c | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/application.h | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/chat/messenger.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/chat/messenger.h | 12++++++++++--
Asrc/event.c | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/event.h | 33+++++++++++++++++++++++++++++++++
Msrc/messenger_gtk.c | 145+++----------------------------------------------------------------------------
Msrc/ui/messenger.c | 42+++++++++++++++++++++++++++++++-----------
Msrc/ui/messenger.h | 12++++++++----
Asrc/util.h | 30++++++++++++++++++++++++++++++
12 files changed, 452 insertions(+), 157 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,6 +4,8 @@ INSTALL_DIR ?= /usr/local/ BINARY = messenger-gtk SOURCES = messenger_gtk.c\ + application.c\ + event.c\ chat/messenger.c\ ui/messenger.c diff --git a/resources/ui/messenger.ui b/resources/ui/messenger.ui @@ -31,6 +31,7 @@ Author: Tobias Frisch <property name="can-focus">False</property> <property name="hhomogeneous-folded">False</property> <property name="vhomogeneous-folded">False</property> + <property name="can-swipe-back">True</property> <child> <object class="GtkBox"> <property name="visible">True</property> diff --git a/src/application.c b/src/application.c @@ -0,0 +1,147 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 application.c + */ + +#include "application.h" + +static void +_load_ui_stylesheets(void) +{ + GdkScreen* screen = gdk_screen_get_default(); + GtkCssProvider* provider = gtk_css_provider_new(); + gtk_css_provider_load_from_path( + provider, + "resources/css/style.css", + NULL + ); + + gtk_style_context_add_provider_for_screen( + screen, + GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + ); +} + +void +application_init(MESSENGER_Application *app, + int argc, + char **argv) +{ + app->argc = argc; + app->argv = argv; + + gtk_init(&argc, &argv); + + _load_ui_stylesheets(); + + app->chat.status = EXIT_FAILURE; + app->chat.tid = 0; + app->chat.signal = MESSENGER_NONE; + + ui_messenger_init(app, &(app->ui.messenger)); +} + +static void* +_application_chat_thread(void *args) +{ + MESSENGER_Application *app = (MESSENGER_Application*) args; + + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + app->chat.status = (GNUNET_PROGRAM_run( + app->argc, + app->argv, + "messenger-gtk", + gettext_noop("A GTK based GUI for the Messenger service of GNUnet."), + options, + &chat_messenger_run, + app + ) == GNUNET_OK? EXIT_SUCCESS : EXIT_FAILURE); + + return NULL; +} + +void +application_start(MESSENGER_Application *app) +{ + pthread_create(&(app->chat.tid), NULL, _application_chat_thread, app); + + gtk_main(); + + pthread_join(app->chat.tid, NULL); +} + +typedef struct MESSENGER_ApplicationEventCall +{ + MESSENGER_Application *app; + MESSENGER_ApplicationEvent event; +} MESSENGER_ApplicationEventCall; + +static gboolean +_application_event_call(gpointer user_data) +{ + //printf("_application_event_call\n"); + + MESSENGER_ApplicationEventCall *call; + + call = (MESSENGER_ApplicationEventCall*) user_data; + call->event(call->app); + + GNUNET_free(call); + return FALSE; +} + +void +application_call_event(MESSENGER_Application *app, + MESSENGER_ApplicationEvent event) +{ + //printf("application_call_event\n"); + + MESSENGER_ApplicationEventCall *call; + + call = (MESSENGER_ApplicationEventCall*) GNUNET_malloc( + sizeof(MESSENGER_ApplicationEventCall) + ); + + call->app = app; + call->event = event; + + g_idle_add(_application_event_call, call); +} + +void +application_exit(MESSENGER_Application *app, + MESSENGER_ApplicationSignal signal) +{ + app->chat.signal = signal; + + gtk_main_quit(); +} + +int +application_status(MESSENGER_Application *app) +{ + return app->chat.status; +} diff --git a/src/application.h b/src/application.h @@ -0,0 +1,83 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 application.h + */ + +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +#include <pthread.h> + +#include "chat/messenger.h" + +#include "ui/messenger.h" + +#include "util.h" + +typedef enum MESSENGER_ApplicationSignal +{ + MESSENGER_NONE = 0, + MESSENGER_QUIT = 1, + MESSENGER_FAIL = 2 +} MESSENGER_ApplicationSignal; + +typedef struct MESSENGER_Application +{ + char** argv; + int argc; + + struct { + int status; + pthread_t tid; + + MESSENGER_ApplicationSignal signal; + + CHAT_MESSENGER_Handle messenger; + } chat; + + struct { + UI_MESSENGER_Handle messenger; + } ui; +} MESSENGER_Application; + +void +application_init(MESSENGER_Application *app, + int argc, + char **argv); + +void +application_start(MESSENGER_Application *app); + +typedef void (*MESSENGER_ApplicationEvent) (MESSENGER_Application *app); + +void +application_call_event(MESSENGER_Application *app, + MESSENGER_ApplicationEvent event); + +void +application_exit(MESSENGER_Application *app, + MESSENGER_ApplicationSignal signal); + +int +application_status(MESSENGER_Application *app); + +#endif /* APPLICATION_H_ */ diff --git a/src/chat/messenger.c b/src/chat/messenger.c @@ -24,4 +24,65 @@ #include "messenger.h" +#include "../event.h" +static void +_chat_messenger_idle(void *cls) +{ + MESSENGER_Application *app = (MESSENGER_Application*) cls; + + if (MESSENGER_NONE == app->chat.signal) + { + app->chat.messenger.idle = GNUNET_SCHEDULER_add_delayed_with_priority( + GNUNET_TIME_relative_get_second_(), + GNUNET_SCHEDULER_PRIORITY_IDLE, + &_chat_messenger_idle, + app + ); + + return; + } + + GNUNET_CHAT_stop(app->chat.messenger.handle); + app->chat.messenger.handle = NULL; + + if (MESSENGER_QUIT != app->chat.signal) + GNUNET_SCHEDULER_shutdown(); +} + +static int +_chat_messenger_message(void *cls, + UNUSED struct GNUNET_CHAT_Context *context, + const struct GNUNET_CHAT_Message *message) +{ + MESSENGER_Application *app = (MESSENGER_Application*) cls; + + if (GNUNET_CHAT_KIND_LOGIN == GNUNET_CHAT_message_get_kind(message)) + application_call_event(app, event_update_profile); + + return GNUNET_YES; +} + +void +chat_messenger_run(void *cls, + UNUSED char *const *args, + UNUSED const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + MESSENGER_Application *app = (MESSENGER_Application*) cls; + + app->chat.messenger.handle = GNUNET_CHAT_start( + cfg, + "messenger-gtk", + "test", + &_chat_messenger_message, + app + ); + + app->chat.messenger.idle = GNUNET_SCHEDULER_add_delayed_with_priority( + GNUNET_TIME_relative_get_zero_(), + GNUNET_SCHEDULER_PRIORITY_IDLE, + &_chat_messenger_idle, + app + ); +} diff --git a/src/chat/messenger.h b/src/chat/messenger.h @@ -30,10 +30,18 @@ #include <gnunet/gnunet_common.h> #include <gnunet/gnunet_program_lib.h> -struct CHAT_MESSENGER_Handle +typedef struct MESSENGER_Application MESSENGER_Application; + +typedef struct CHAT_MESSENGER_Handle { struct GNUNET_CHAT_Handle *handle; struct GNUNET_SCHEDULER_Task *idle; -}; +} CHAT_MESSENGER_Handle; + +void +chat_messenger_run(void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg); #endif /* CHAT_MESSENGER_H_ */ diff --git a/src/event.c b/src/event.c @@ -0,0 +1,41 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 event.c + */ + +#include "event.h" + +void +event_update_profile(MESSENGER_Application *app) +{ + //printf("event_update_profile\n"); + + const char *name = GNUNET_CHAT_get_name(app->chat.messenger.handle); + + //printf("A: %s\n", name); + + if (name) + { + hdy_avatar_set_text(app->ui.messenger.profile_avatar, name); + gtk_label_set_text(app->ui.messenger.profile_label, name); + } +} diff --git a/src/event.h b/src/event.h @@ -0,0 +1,33 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 event.h + */ + +#ifndef EVENT_H_ +#define EVENT_H_ + +#include "application.h" + +void +event_update_profile(MESSENGER_Application *app); + +#endif /* EVENT_H_ */ diff --git a/src/messenger_gtk.c b/src/messenger_gtk.c @@ -22,148 +22,13 @@ * @file messenger_gtk.c */ -#include "chat/messenger.h" -#include "ui/messenger.h" - -#include <pthread.h> - -#define UNUSED __attribute__((unused)) - -struct main_program -{ - int argc; - char** argv; - - bool exit; - - struct CHAT_MESSENGER_Handle chat; - struct UI_MESSENGER_Handle ui; -}; - -gboolean gtk_set_profile_name(gpointer user_data) -{ - struct main_program *program = (struct main_program*) user_data; - - const char *name = GNUNET_CHAT_get_name(program->chat.handle); - - if (name) - { - hdy_avatar_set_text(program->ui.profile_avatar, name); - gtk_label_set_text(program->ui.profile_label, name); - } - - return FALSE; -} - -int gnunet_chat_message(void *cls, - UNUSED struct GNUNET_CHAT_Context *context, - const struct GNUNET_CHAT_Message *message) -{ - struct main_program *program = (struct main_program*) cls; - - if (GNUNET_CHAT_KIND_LOGIN == GNUNET_CHAT_message_get_kind(message)) - g_idle_add(gtk_set_profile_name, program); - - return GNUNET_YES; -} - -void gnunet_idle(void *cls) -{ - struct main_program *program = (struct main_program*) cls; - - if (program->exit) - { - GNUNET_CHAT_stop(program->chat.handle); - program->chat.handle = NULL; - - GNUNET_SCHEDULER_shutdown(); - return; - } - - program->chat.idle = GNUNET_SCHEDULER_add_delayed_with_priority( - GNUNET_TIME_relative_get_second_(), - GNUNET_SCHEDULER_PRIORITY_IDLE, - gnunet_idle, - program - ); -} - -void gnunet_task(void *cls, - UNUSED char *const *args, - UNUSED const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct main_program *program = (struct main_program*) cls; - - program->chat.handle = GNUNET_CHAT_start( - cfg, - "messenger-gtk", - "test", - &gnunet_chat_message, - program - ); - - program->chat.idle = GNUNET_SCHEDULER_add_delayed_with_priority( - GNUNET_TIME_relative_get_zero_(), - GNUNET_SCHEDULER_PRIORITY_IDLE, - gnunet_idle, - program - ); -} - -void *gnunet_thread(void *args) -{ - struct main_program *program = (struct main_program*) args; - - struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_PROGRAM_run( - program->argc, - program->argv, - "messenger-gtk", - gettext_noop("A GTK based GUI for the Messenger service of GNUnet."), - options, - &gnunet_task, - program - ); - - return NULL; -} +#include "application.h" int main(int argc, char **argv) { - struct main_program program; - program.argc = argc; - program.argv = argv; - - program.exit = FALSE; - - pthread_t gnunet_tid; - gtk_init(&argc, &argv); - - GdkScreen* screen = gdk_screen_get_default(); - GtkCssProvider* provider = gtk_css_provider_new(); - gtk_css_provider_load_from_path( - provider, - "resources/css/style.css", - NULL - ); - - gtk_style_context_add_provider_for_screen( - screen, - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - ui_messenger_init(&(program.ui)); - - pthread_create(&gnunet_tid, NULL, gnunet_thread, &program); - - gtk_main(); + MESSENGER_Application app; - program.exit = TRUE; + application_init(&app, argc, argv); + application_start(&app); - pthread_join(gnunet_tid, NULL); - return 0; + return application_status(&app); } diff --git a/src/ui/messenger.c b/src/ui/messenger.c @@ -24,8 +24,11 @@ #include "messenger.h" -void handle_flap_via_button_click(UI_UNUSED GtkButton* button, - gpointer user_data) +#include "../application.h" + +static void +handle_flap_via_button_click(UNUSED GtkButton* button, + gpointer user_data) { HdyFlap* flap = HDY_FLAP(user_data); @@ -36,8 +39,9 @@ void handle_flap_via_button_click(UI_UNUSED GtkButton* button, } } -void handle_account_details_button_click(UI_UNUSED GtkButton* button, - gpointer user_data) +static void +handle_account_details_button_click(UNUSED GtkButton* button, + gpointer user_data) { GtkRevealer* revealer = GTK_REVEALER(user_data); @@ -48,9 +52,10 @@ void handle_account_details_button_click(UI_UNUSED GtkButton* button, } } -void handle_chats_listbox_row_activated(UI_UNUSED GtkListBox* listbox, - UI_UNUSED GtkListBoxRow* row, - gpointer user_data) +static void +handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox, + UNUSED GtkListBoxRow* row, + gpointer user_data) { HdyLeaflet* leaflet = HDY_LEAFLET(user_data); @@ -61,8 +66,9 @@ void handle_chats_listbox_row_activated(UI_UNUSED GtkListBox* listbox, } } -void handle_back_button_click(UI_UNUSED GtkButton* button, - gpointer user_data) +static void +handle_back_button_click(UNUSED GtkButton* button, + gpointer user_data) { HdyLeaflet* leaflet = HDY_LEAFLET(user_data); @@ -73,8 +79,17 @@ void handle_back_button_click(UI_UNUSED GtkButton* button, } } +static void +handle_main_window_destroy(gpointer user_data) +{ + MESSENGER_Application *app = (MESSENGER_Application*) user_data; + + application_exit(app, MESSENGER_QUIT); +} + void -ui_messenger_init(struct UI_MESSENGER_Handle *handle) +ui_messenger_init(MESSENGER_Application *app, + UI_MESSENGER_Handle *handle) { GtkBuilder* builder = gtk_builder_new(); gtk_builder_add_from_file( @@ -220,5 +235,10 @@ ui_messenger_init(struct UI_MESSENGER_Handle *handle) gtk_widget_show(GTK_WIDGET(handle->main_window)); - g_signal_connect(handle->main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect( + handle->main_window, + "destroy", + G_CALLBACK(handle_main_window_destroy), + app + ); } diff --git a/src/ui/messenger.h b/src/ui/messenger.h @@ -28,9 +28,9 @@ #include <gtk-3.0/gtk/gtk.h> #include <libhandy-1/handy.h> -#define UI_UNUSED __attribute__((unused)) +typedef struct MESSENGER_Application MESSENGER_Application; -struct UI_MESSENGER_Handle +typedef struct UI_MESSENGER_Handle { GtkApplicationWindow *main_window; @@ -67,9 +67,13 @@ struct UI_MESSENGER_Handle GtkButton *chat_details_button; GtkButton *hide_chat_details_button; -}; +} UI_MESSENGER_Handle; void -ui_messenger_init(struct UI_MESSENGER_Handle *handle); +ui_messenger_init(MESSENGER_Application *app, + UI_MESSENGER_Handle *handle); + +void +ui_messenger_update_profile(MESSENGER_Application *app); #endif /* UI_MESSENGER_H_ */ diff --git a/src/util.h b/src/util.h @@ -0,0 +1,30 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 util.h + */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +#define UNUSED __attribute__((unused)) + +#endif /* UTIL_H_ */