From 989801d717ca29b735cc8f61b5ae558851899d1b Mon Sep 17 00:00:00 2001 From: MrMelon Date: Fri, 30 Apr 2021 13:48:45 +0100 Subject: [PATCH] Add support for the appindicator in the GUI package --- src/impl/cli/main.c | 19 +++---- src/impl/gui/main.c | 56 +++++++++++++------- src/impl/gui/statusicon.c | 78 ++++++++++++++++++++-------- src/impl/shared/unix_socket_client.c | 2 +- src/impl/shared/unix_socket_server.c | 9 ++-- src/intf/statusicon.h | 2 + 6 files changed, 110 insertions(+), 56 deletions(-) diff --git a/src/impl/cli/main.c b/src/impl/cli/main.c index 15d4c69..40e93ab 100644 --- a/src/impl/cli/main.c +++ b/src/impl/cli/main.c @@ -23,6 +23,7 @@ char *version = PROJ_VERSION; bool is_gui = false; thrd_t listenthr; atomic_bool listenserverready = false; +bool is_debug = false; int send_to_daemon(char*, ssize_t); int refresh_vpn(); @@ -82,12 +83,12 @@ int is_arg(int ac, char **argv, char *arg) { return 0; // arg not present } -void display_version(bool is_debug) { +void display_version() { if(is_debug) printf("v%s-beta\n", version); else printf("v%s\n", version); } -void display_about(bool is_debug) { +void display_about() { printf("%s\n", about_name); display_version(is_debug); printf("%s\n", about_copyright); @@ -97,7 +98,7 @@ void display_about(bool is_debug) { printf("Artist: %s\n", about_artist); } -void display_help(bool is_debug) { +void display_help() { printf("Melon VPN Help\n"); printf("-h, --help Display this help message\n"); printf("--about About this program\n"); @@ -111,20 +112,20 @@ int main (int argc, char **argv) { int status; currentstate = DISCONNECTED; - bool is_debug = is_arg(argc, argv, "--debug"); + is_debug = is_arg(argc, argv, "--debug"); if(is_arg(argc, argv, "--help") || is_arg(argc, argv, "-h")) { - display_help(is_debug); + display_help(); return 0; } if(is_arg(argc, argv, "--version") || is_arg(argc, argv, "-v")) { - display_version(is_debug); + display_version(); return 0; } if(is_arg(argc, argv, "--about")) { - display_about(is_debug); + display_about(); return 0; } @@ -184,7 +185,7 @@ int send_to_daemon(char *buf, ssize_t n) { write(sfd, buf, n); close(sfd); - fprintf(stderr, "Closed connection to socket\n"); + if(is_debug) fprintf(stderr, "Closed connection to socket\n"); return 0; } @@ -213,7 +214,7 @@ int start_client_server() { msg[MAX_PEERS_LEN-1]=0; } - fprintf(stderr, "Incoming request: %s\n",msg); + if(is_debug) fprintf(stderr, "Incoming request: %s\n",msg); char *a = strtok(msg,"\1"); if(strcmp(a,"client")==0) { diff --git a/src/impl/gui/main.c b/src/impl/gui/main.c index e817215..1d62362 100644 --- a/src/impl/gui/main.c +++ b/src/impl/gui/main.c @@ -35,18 +35,14 @@ int (*cli_stop_vpn)(); int (*cli_refresh_vpn)(); int (*cli_restart_conf_vpn)(bool); -void update_state(States state) { - currentstate = state; - if(currentstate == CONNECTED) { - status_icon_set_state(APP_INDICATOR_STATUS_ATTENTION); - } else if(currentstate == DISCONNECTED) { - status_icon_set_state(APP_INDICATOR_STATUS_PASSIVE); - } else { - status_icon_set_state(APP_INDICATOR_STATUS_ACTIVE); - } +int quit_app() { + // Stops 'g_application_run' + g_application_quit(G_APPLICATION(app)); + return 0; } void open_about(GtkApplication* app) { + // Setup and display about window GtkWidget *about = gtk_about_dialog_new(); gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),about_name); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),"v1.0.0"); @@ -73,55 +69,73 @@ void open_stop_btn(GtkButton *button) { (*cli_stop_vpn)(); } -void open_restart_toggle_btn(GtkButton *button) { - restarttoggle = !restarttoggle; - (*cli_restart_conf_vpn)(restarttoggle); - update_restart_toggle_btn_label(); -} - void update_restart_toggle_btn_label() { char restartbtnlabel[] = "Restart [ ]"; if(restarttoggle) restartbtnlabel[9] = '#'; gtk_button_set_label(GTK_BUTTON(button3), restartbtnlabel); } +void open_restart_toggle_btn(GtkButton *button) { + restarttoggle = !restarttoggle; + (*cli_restart_conf_vpn)(restarttoggle); + update_restart_toggle_btn_label(); +} + void open_about_btn(GtkButton *button) { open_about(app); } +gboolean on_window_deleted(GtkWidget *widget, GdkEvent *event, gpointer data) { + gtk_widget_hide(widget); + return true; +} + void activate(GtkApplication* app) { window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window),"Melon VPN"); gtk_window_set_default_size(GTK_WINDOW(window),300,300); + gtk_window_set_resizable(GTK_WINDOW(window),false); + gtk_window_set_type_hint(GTK_WINDOW(window),GDK_WINDOW_TYPE_HINT_DIALOG); + g_signal_connect(G_OBJECT(window),"delete-event",G_CALLBACK(on_window_deleted),NULL); // Setup status icon now window is available status_icon_create(window,statusiconoff,statusiconon); - status_icon_set_state(APP_INDICATOR_STATUS_PASSIVE); + status_icon_set_state(APP_INDICATOR_STATUS_ACTIVE); + status_icon_set_quit_callback(quit_app); + status_icon_set_connect_callback(cli_start_vpn); + status_icon_set_disconnect_callback(cli_stop_vpn); gtk_container_set_border_width(GTK_CONTAINER(window),8); + // Setup a monospace font PangoFontDescription *font = pango_font_description_new(); pango_font_description_set_family(font,"Monospace"); + // Create start button button = gtk_button_new_with_label("Start"); gtk_widget_modify_font(GTK_WIDGET(button), font); g_signal_connect(button,"clicked",G_CALLBACK(open_start_btn),NULL); + // Create stop button button2 = gtk_button_new_with_label("Stop"); gtk_widget_modify_font(GTK_WIDGET(button2), font); g_signal_connect(button2,"clicked",G_CALLBACK(open_stop_btn),NULL); + // Create restart button button3 = gtk_button_new_with_label("Restart [ ]"); gtk_widget_modify_font(GTK_WIDGET(button3), font); g_signal_connect(button3,"clicked",G_CALLBACK(open_restart_toggle_btn),NULL); + // Create about button button4 = gtk_button_new_with_label("About"); gtk_widget_modify_font(GTK_WIDGET(button4), font); g_signal_connect(button4,"clicked",G_CALLBACK(open_about_btn),NULL); + // Create label for status text statustxt = gtk_label_new(""); gtk_widget_modify_font(GTK_WIDGET(statustxt), font); + // Fixed box used to position the widgets box = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window),box); @@ -221,10 +235,16 @@ int run_gui(int argc, char **argv, bool is_debug, int (*start_vpn)(), int (*stop void mod_trigger_state(States state) { currentstate = state; + if(cli_is_debug) fprintf(stderr, "update_state(%s);\n",string_state(currentstate)); + if(currentstate == CONNECTED) { + status_icon_set_state(APP_INDICATOR_STATUS_ATTENTION); + } else if(currentstate == DISCONNECTED) { + status_icon_set_state(APP_INDICATOR_STATUS_ACTIVE); + } else { + status_icon_set_state(APP_INDICATOR_STATUS_PASSIVE); + } char *statelbl = string_state_upper(state); - fprintf(stderr, "hi: %s\n", statelbl); - gtk_label_set_text(GTK_LABEL(statustxt), statelbl); } diff --git a/src/impl/gui/statusicon.c b/src/impl/gui/statusicon.c index 61a2aec..127e336 100644 --- a/src/impl/gui/statusicon.c +++ b/src/impl/gui/statusicon.c @@ -1,19 +1,29 @@ #include #include +#include + #include "states.h" #include "statusicon.h" GtkWidget *mainwindow; AppIndicator *indicator; +GtkWidget *indicator_menu; States status_icon_currentstate; +bool isquitcallback = false; +bool isconnectcallback = false; +bool isdisconnectcallback = false; +int (*quit_callback)(); +int (*connect_callback)(); +int (*disconnect_callback)(); + static void activate_action (GtkAction *action); static GtkActionEntry entries[] = { {"FileMenu",NULL,"_File"}, - {"New","document-new","_New","N","Create a new file",G_CALLBACK(activate_action)}, - {"Open","document-open","_Open","O","Open a file",G_CALLBACK(activate_action)}, - {"Save","document-save","_Save","S","Save file",G_CALLBACK(activate_action)}, + {"Connect","vpn-connect","_Connect","C","Connect to VPN",G_CALLBACK(activate_action)}, + {"Disconnect","vpn-disconnect","_Disconnect","D","Disconnect from VPN",G_CALLBACK(activate_action)}, + {"Open","window-open","_Open","O","Open the window",G_CALLBACK(activate_action)}, {"Close","window-close","_Close","W","Close the window",G_CALLBACK(activate_action)}, {"Quit","application-exit","_Quit","Q","Exit the application",G_CALLBACK(activate_action)}, }; @@ -21,20 +31,11 @@ static guint n_entries = G_N_ELEMENTS (entries); static const gchar *ui_info = "" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " " " -" " +" " +" " +" " " " -" " " " " " " " @@ -42,12 +43,28 @@ static const gchar *ui_info = static void activate_action(GtkAction *action) { const gchar *name = gtk_action_get_name(action); - if(strcmp(name,"Quit") == 0 || strcmp(name,"Close") == 0) { - if(mainwindow != NULL) { - gtk_window_close(GTK_WINDOW(mainwindow)); - return; - } + if(strcmp(name,"Quit") == 0) { + // A custom callback is used as closing the window triggers gtk_widget_hide + if(isquitcallback) (*quit_callback)(); + return; + } else if(strcmp(name,"Close") == 0) { + // Hide the main window + if(mainwindow != NULL) gtk_widget_hide(GTK_WIDGET(mainwindow)); + return; + } else if(strcmp(name,"Open") == 0) { + // Open the main window + if(mainwindow != NULL) gtk_widget_show(GTK_WIDGET(mainwindow)); + return; + } else if(strcmp(name,"Connect") == 0) { + // Trigger connect to VPN callback + if(isconnectcallback) (*connect_callback)(); + return; + } else if(strcmp(name,"Disconnect") == 0) { + // Trigger disconnect from VPN callback + if(isdisconnectcallback) (*disconnect_callback)(); + return; } + GtkWidget *dialog; dialog = gtk_message_dialog_new(NULL,GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_INFO,GTK_BUTTONS_CLOSE,"You activated action: \"%s\"",name); g_signal_connect(dialog,"response",G_CALLBACK(gtk_widget_destroy),NULL); @@ -59,7 +76,6 @@ void status_icon_create(GtkWidget *window, char *statusoff, char *statuson) { mainwindow = window; GtkUIManager *uim; GError *error = NULL; - GtkWidget *indicator_menu; GtkActionGroup *action_group; action_group = gtk_action_group_new("AppActions"); @@ -84,6 +100,22 @@ void status_icon_create(GtkWidget *window, char *statusoff, char *statuson) { } } -void status_icon_set_state(AppIndicatorStatus status) { - app_indicator_set_status(APP_INDICATOR(indicator),status); +void status_icon_set_quit_callback(int (*func)()) { + quit_callback = func; + isquitcallback = true; +} + +void status_icon_set_connect_callback(int (*func)()) { + connect_callback = func; + isconnectcallback = true; +} + +void status_icon_set_disconnect_callback(int (*func)()) { + disconnect_callback = func; + isdisconnectcallback = true; +} + +void status_icon_set_state(AppIndicatorStatus status) { + app_indicator_set_status(indicator,status); + app_indicator_set_menu(indicator,GTK_MENU(indicator_menu)); } diff --git a/src/impl/shared/unix_socket_client.c b/src/impl/shared/unix_socket_client.c index 5f76d2b..31b04c6 100644 --- a/src/impl/shared/unix_socket_client.c +++ b/src/impl/shared/unix_socket_client.c @@ -28,7 +28,7 @@ int unix_socket_client_start(char *sock_path) { // Connects the active socket referred to be sfd to the listening socket // whose address is specified by addr. if (connect(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) { - fprintf(stderr,"Failed to connect\n"); + fprintf(stderr,"ERROR: Failed to connect to socket\n"); return -1; } diff --git a/src/impl/shared/unix_socket_server.c b/src/impl/shared/unix_socket_server.c index 371e76f..ca90506 100644 --- a/src/impl/shared/unix_socket_server.c +++ b/src/impl/shared/unix_socket_server.c @@ -11,7 +11,6 @@ int unix_socket_server_start(char *sock_path) { // Create a new server socket with domain: AF_UNIX, type: SOCK_STREAM, protocol: 0 int sfd = socket(AF_UNIX, SOCK_STREAM, 0); - printf("Server socket fd = %d\n", sfd); // Make sure socket's file descriptor is legit. if (sfd == -1) { @@ -21,14 +20,14 @@ int unix_socket_server_start(char *sock_path) { // Make sure the address we're planning to use isn't too long. if (strlen(sock_path) > sizeof(addr.sun_path) - 1) { - fprintf(stderr,"Server socket path too long: %s\n",sock_path); + fprintf(stderr,"ERROR: Server socket path too long: %s\n",sock_path); return -1; } // Delete any file that already exists at the address. Make sure the deletion // succeeds. If the error is just that the file/directory doesn't exist, it's fine. if (remove(sock_path) == -1 && errno != ENOENT) { - fprintf(stderr,"remove-%s\n",sock_path); + fprintf(stderr,"ERROR: Failed to remove old socket file: %s\n",sock_path); return -1; } @@ -40,7 +39,7 @@ int unix_socket_server_start(char *sock_path) { // Bind the socket to the address. Note that we're binding the server socket // to a well-known address so that clients know where to connect. if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) { - fprintf(stderr,"Failed to bind\n"); + fprintf(stderr,"ERROR: Failed to bind to socket address\n"); return -1; } @@ -49,7 +48,7 @@ int unix_socket_server_start(char *sock_path) { // listen cannot be called on a connected socket (a socket on which a connect() // has been succesfully performed or a socket returned by a call to accept()). if (listen(sfd, BACKLOG) == -1) { - fprintf(stderr,"Failed to listen\n"); + fprintf(stderr,"ERROR: Failed to listen to socket\n"); return -1; } diff --git a/src/intf/statusicon.h b/src/intf/statusicon.h index e543d02..838a095 100644 --- a/src/intf/statusicon.h +++ b/src/intf/statusicon.h @@ -6,3 +6,5 @@ void status_icon_create(GtkWidget *window, char *off, char *on); void status_icon_set_state(AppIndicatorStatus state); +void status_icon_set_connect_callback(int (*func)()); +void status_icon_set_disconnect_callback(int (*func)());