#include "tray.h" #include "getcore.h" #include "getfreq.h" #include "getgov.h" #include "bat_tray.h" #include "defaults.h" #include "paramano_set_interface.h" #include #include #include #include #include static GtkStatusIcon* tray; static char tooltip_text[1024]; static GtkWidget* menu; static GSList* menu_items; static GtkWidget* checked_menu_item; /*********************************************************************** * Handler for when freq is chosen **********************************************************************/ static void freq_menu_item_toggled(GtkCheckMenuItem* item, gpointer data) { if (gtk_check_menu_item_get_active(item)) { checked_menu_item = GTK_WIDGET(item); gint freq = GPOINTER_TO_INT(data); unsigned int i = 0; for (i = 0; i < gc_number(); i++) si_freq(freq, i); } } /*********************************************************************** * Handler for when governor is chosen **********************************************************************/ static void gov_menu_item_toggled(GtkCheckMenuItem* item, gpointer data) { if (gtk_check_menu_item_get_active(item)) { checked_menu_item = GTK_WIDGET(item); char* gov = (char*)data; unsigned int i = 0; for (i = 0; i < gc_number(); i++) si_gov(gov, i); } } /*********************************************************************** * Destroy a menu item **********************************************************************/ static void remove_menu_item(GtkWidget* menu_item, gpointer data) { gtk_widget_destroy(menu_item); } /*********************************************************************** * Remove all items in menu **********************************************************************/ static void tray_clear_menu() { GtkContainer* cont = GTK_CONTAINER(menu); gtk_container_foreach(cont, remove_menu_item, NULL); menu_items = NULL; } /*********************************************************************** * Create new instance of gtk_tray_new for gov/freq tray **********************************************************************/ static void tray_init_menu() { menu = gtk_menu_new(); } /*********************************************************************** * Populate gtk menu object with all the entries **********************************************************************/ static void tray_generate_menu() { tray_clear_menu(); gg_init(); char label[1024]; unsigned int i = 0; char current_governor[20]; memset(current_governor, '\0', sizeof(current_governor) ); gg_current(0, current_governor, sizeof(current_governor) ); gint current_frequency = gf_current(0); /* Add available frequencies */ for (i = 0; i < gf_number(); i++) { gf_get_frequency_label(label, sizeof(label), gf_freqi(0, i)); GtkWidget* item = gtk_radio_menu_item_new_with_label(menu_items, label); menu_items = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); if (g_strcmp0(current_governor, "userspace") == 0 && gf_freqi(0, i) == current_frequency) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(freq_menu_item_toggled), GINT_TO_POINTER(gf_freqi(0, i))); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); } /* Add a seperator */ GtkWidget* seperator = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), seperator); /* Add available governors */ for (i = 0; i < gg_number(); i++) { if (g_strcmp0(gg_gov(0, i), "userspace") == 0) continue; GtkWidget* item = gtk_radio_menu_item_new_with_label(menu_items, gg_gov(0, i)); menu_items = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); if (g_strcmp0(gg_gov(0, i), current_governor) == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(gov_menu_item_toggled), gg_gov(0, i)); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); } gtk_widget_show_all(menu); } /*********************************************************************** * Tell gtk what the tooltip message should be **********************************************************************/ static gboolean show_tooltip(GtkStatusIcon* status_icon, gint x, gint y, gboolean keyboard_mode,GtkTooltip* tooltip, gpointer data) { gtk_tooltip_set_text(tooltip, tooltip_text); return true; } /*********************************************************************** * Work out what the tooltip message would be now, store it away **********************************************************************/ static void update_tooltip_cache() { char msg[10240], label[1024]; char current_governor[20]; /* FIXME magic */ unsigned int i = 0; unsigned int offset = 0; memset(current_governor, '\0', sizeof(current_governor) ); gg_current(0, current_governor, sizeof(current_governor) ); offset = snprintf(msg, sizeof(msg), _("Governor: %s\n"), current_governor); for (i = 0; i < gc_number(); i++) { gf_get_frequency_label(label, sizeof(label), gf_current(i)); offset += snprintf(msg+offset, sizeof(msg)-offset, _("CPU%d: %s%s"), i, label, i == gc_number()-1 ? "" : "\n"); } strncpy(tooltip_text, msg, sizeof(tooltip_text)); tooltip_text[sizeof(tooltip_text)-1] = '\0'; } /*********************************************************************** * Handler for spawning the popup/context menu **********************************************************************/ static void popup_menu(GtkStatusIcon* statuc_icon,guint button,guint activate_time,gpointer data) { tray_generate_menu(); gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,tray,button,activate_time); } /********************************************************************** * Set icon based on current freq/governor **********************************************************************/ static void update_icon() { char file[1024]; int max_frequency = gf_freqi(0, 0); int adjusted_percent, percent; /* If max_frequency is 0, we don't want to divide by it, * so give up, call it a day, and have a simple icon */ if (max_frequency == 0) { adjusted_percent = 0; } else { /* Percentages need to be {25,50,75,100}. Round to one of these numbers. * TO DO: round/truncate instead of lots of ifs */ percent = (gf_current(0) * 100)/max_frequency; if (percent == 100) { adjusted_percent = 100; } else if (percent >= 65.5) { adjusted_percent = 75; } else if (percent >= 37.5) { adjusted_percent = 50; } else if (percent >= 12.5) { adjusted_percent = 25; } else { adjusted_percent = 0; } } snprintf(file, sizeof(file), "%s/cpu-%d.png", DEFAULT_THEME,adjusted_percent); gtk_status_icon_set_from_file(tray, file); } /*********************************************************************** * Update the freq/gov tray icon * Also updates the cached tooltip text **********************************************************************/ static gboolean update() { static int last_bat_state = -1; int now_bat_state = STATE_UNKNOWN; unsigned int i; update_tooltip_cache(); update_icon(); now_bat_state = get_battery_state(); if (now_bat_state == last_bat_state) return true; last_bat_state = now_bat_state; switch ( now_bat_state ) { case STATE_DISCHARGING: fprintf(stderr, "discharging\n"); if (DEFAULT_BAT_GOV) { for (i = 0; i < gc_number(); i++) si_gov(DEFAULT_BAT_GOV, i); } break; case STATE_CHARGING: case STATE_FULL: fprintf(stderr, "ac power\n"); if (DEFAULT_AC_GOV) { for (i = 0; i < gc_number(); i++) si_gov(DEFAULT_AC_GOV, i); } break; } return true; } /*********************************************************************** * Apply default gov/freq for current situation **********************************************************************/ void tray_set_defaults() { unsigned int i = 0; if (DEFAULT_GOV) { for (i = 0; i < gc_number(); i++) si_gov(DEFAULT_GOV, i); } else { for (i = 0; i < gc_number(); i++) si_gov("ondemand", i); } if (DEFAULT_FREQ) { for (i = 0; i < gc_number(); i++) si_freq(atoi(DEFAULT_FREQ), i); } } /*********************************************************************** * Start the tray icon thingy **********************************************************************/ void tray_init() { tray_set_defaults(); tray = gtk_status_icon_new(); char* icon_file = g_strconcat(DEFAULT_THEME, "/cpu-0.png", NULL); /* Force something useful to be in the cached tooltip text */ update_tooltip_cache(); gtk_status_icon_set_from_file(tray, icon_file); gtk_status_icon_set_has_tooltip(tray, TRUE); g_signal_connect(G_OBJECT(tray), "query-tooltip", G_CALLBACK(show_tooltip), NULL); g_signal_connect(G_OBJECT(tray), "popup-menu", G_CALLBACK(popup_menu), NULL); g_timeout_add(1000, update, NULL); /* Force meaningful tooltip cached text and force meaningful icon */ update(); tray_init_menu(); } /*********************************************************************** * Show the tray **********************************************************************/ void tray_show() { gtk_status_icon_set_visible(tray, TRUE); } /*********************************************************************** * Hide the tray **********************************************************************/ void tray_hide() { gtk_status_icon_set_visible(tray, FALSE); } /*********************************************************************** * Return bool for visiblity of tray **********************************************************************/ bool tray_visible() { return gtk_status_icon_get_visible(tray); } /*********************************************************************** * Return bool for embeddedness of tray **********************************************************************/ bool tray_embedded() { return gtk_status_icon_is_embedded(tray); }