Add support for the appindicator in the GUI package
This commit is contained in:
parent
d0e35bf602
commit
989801d717
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)());
|
||||
|
Loading…
Reference in New Issue
Block a user