Add support for the appindicator in the GUI package

This commit is contained in:
Melon 2021-04-30 13:48:45 +01:00
parent d0e35bf602
commit 989801d717
6 changed files with 110 additions and 56 deletions

View File

@ -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) {

View File

@ -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);
}

View File

@ -1,19 +1,29 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libappindicator/app-indicator.h>
#include <stdbool.h>
#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","<control>N","Create a new file",G_CALLBACK(activate_action)},
{"Open","document-open","_Open","<control>O","Open a file",G_CALLBACK(activate_action)},
{"Save","document-save","_Save","<control>S","Save file",G_CALLBACK(activate_action)},
{"Connect","vpn-connect","_Connect","<control>C","Connect to VPN",G_CALLBACK(activate_action)},
{"Disconnect","vpn-disconnect","_Disconnect","<control>D","Disconnect from VPN",G_CALLBACK(activate_action)},
{"Open","window-open","_Open","<control>O","Open the window",G_CALLBACK(activate_action)},
{"Close","window-close","_Close","<control>W","Close the window",G_CALLBACK(activate_action)},
{"Quit","application-exit","_Quit","<control>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 =
"<ui>"
" <menubar name='MenuBar'>"
" <menu action='FileMenu'>"
" <menuitem action='New'/>"
" <menuitem action='Open'/>"
" <menuitem action='Save'/>"
" <separator/>"
" <menuitem action='Close'/>"
" <menuitem action='Quit'/>"
" </menu>"
" </menubar>"
" <popup name='IndicatorPopup'>"
" <menuitem action='New' />"
" <menuitem action='Connect' />"
" <menuitem action='Disconnect' />"
" <separator/>"
" <menuitem action='Open' />"
" <menuitem action='Save' />"
" <menuitem action='Close' />"
" <menuitem action='Quit' />"
" </popup>"
@ -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));
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)());