summaryrefslogtreecommitdiff
path: root/cpufreq/src/cpufreq-popup.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpufreq/src/cpufreq-popup.c')
-rw-r--r--cpufreq/src/cpufreq-popup.c509
1 files changed, 509 insertions, 0 deletions
diff --git a/cpufreq/src/cpufreq-popup.c b/cpufreq/src/cpufreq-popup.c
new file mode 100644
index 00000000..8486c2b3
--- /dev/null
+++ b/cpufreq/src/cpufreq-popup.c
@@ -0,0 +1,509 @@
+/*
+ * MATE CPUFreq Applet
+ * Copyright (C) 2004 Carlos Garcia Campos <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Carlos Garc�a Campos <[email protected]>
+ */
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpufreq-popup.h"
+#include "cpufreq-selector.h"
+#include "cpufreq-utils.h"
+
+struct _CPUFreqPopupPrivate {
+ GtkUIManager *ui_manager;
+ GSList *radio_group;
+
+ GtkActionGroup *freqs_group;
+ GSList *freqs_actions;
+
+ GtkActionGroup *govs_group;
+ GSList *govs_actions;
+
+ guint merge_id;
+ gboolean need_build;
+ gboolean show_freqs;
+
+ CPUFreqMonitor *monitor;
+ GtkWidget *parent;
+};
+
+#define CPUFREQ_POPUP_GET_PRIVATE(object) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((object), CPUFREQ_TYPE_POPUP, CPUFreqPopupPrivate))
+
+static void cpufreq_popup_init (CPUFreqPopup *popup);
+static void cpufreq_popup_class_init (CPUFreqPopupClass *klass);
+static void cpufreq_popup_finalize (GObject *object);
+
+G_DEFINE_TYPE (CPUFreqPopup, cpufreq_popup, G_TYPE_OBJECT)
+
+static const gchar *ui_popup =
+"<ui>"
+" <popup name=\"CPUFreqSelectorPopup\" action=\"PopupAction\">"
+" <placeholder name=\"FreqsItemsGroup\">"
+" </placeholder>"
+" <separator />"
+" <placeholder name=\"GovsItemsGroup\">"
+" </placeholder>"
+" </popup>"
+"</ui>";
+
+#define FREQS_PLACEHOLDER_PATH "/CPUFreqSelectorPopup/FreqsItemsGroup"
+#define GOVS_PLACEHOLDER_PATH "/CPUFreqSelectorPopup/GovsItemsGroup"
+
+static void
+cpufreq_popup_init (CPUFreqPopup *popup)
+{
+ popup->priv = CPUFREQ_POPUP_GET_PRIVATE (popup);
+
+ popup->priv->ui_manager = gtk_ui_manager_new ();
+ popup->priv->radio_group = NULL;
+
+ popup->priv->freqs_group = NULL;
+ popup->priv->freqs_actions = NULL;
+
+ popup->priv->govs_group = NULL;
+ popup->priv->govs_actions = NULL;
+
+ popup->priv->merge_id = 0;
+ popup->priv->need_build = TRUE;
+ popup->priv->show_freqs = FALSE;
+
+ gtk_ui_manager_add_ui_from_string (popup->priv->ui_manager,
+ ui_popup, -1, NULL);
+
+ popup->priv->monitor = NULL;
+}
+
+static void
+cpufreq_popup_class_init (CPUFreqPopupClass *klass)
+{
+ GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (g_object_class, sizeof (CPUFreqPopupPrivate));
+
+ g_object_class->finalize = cpufreq_popup_finalize;
+}
+
+static void
+cpufreq_popup_finalize (GObject *object)
+{
+ CPUFreqPopup *popup = CPUFREQ_POPUP (object);
+
+ if (popup->priv->ui_manager) {
+ g_object_unref (popup->priv->ui_manager);
+ popup->priv->ui_manager = NULL;
+ }
+
+ if (popup->priv->freqs_group) {
+ g_object_unref (popup->priv->freqs_group);
+ popup->priv->freqs_group = NULL;
+ }
+
+ if (popup->priv->freqs_actions) {
+ g_slist_free (popup->priv->freqs_actions);
+ popup->priv->freqs_actions = NULL;
+ }
+
+ if (popup->priv->govs_group) {
+ g_object_unref (popup->priv->govs_group);
+ popup->priv->govs_group = NULL;
+ }
+
+ if (popup->priv->govs_actions) {
+ g_slist_free (popup->priv->govs_actions);
+ popup->priv->govs_actions = NULL;
+ }
+
+ if (popup->priv->monitor) {
+ g_object_unref (popup->priv->monitor);
+ popup->priv->monitor = NULL;
+ }
+
+ G_OBJECT_CLASS (cpufreq_popup_parent_class)->finalize (object);
+}
+
+CPUFreqPopup *
+cpufreq_popup_new (void)
+{
+ CPUFreqPopup *popup;
+
+ popup = CPUFREQ_POPUP (g_object_new (CPUFREQ_TYPE_POPUP,
+ NULL));
+
+ return popup;
+}
+
+/* Public methods */
+void
+cpufreq_popup_set_monitor (CPUFreqPopup *popup,
+ CPUFreqMonitor *monitor)
+{
+ g_return_if_fail (CPUFREQ_IS_POPUP (popup));
+ g_return_if_fail (CPUFREQ_IS_MONITOR (monitor));
+
+ if (popup->priv->monitor == monitor)
+ return;
+
+ if (popup->priv->monitor)
+ g_object_unref (popup->priv->monitor);
+ popup->priv->monitor = g_object_ref (monitor);
+}
+
+void
+cpufreq_popup_set_parent (CPUFreqPopup *popup,
+ GtkWidget *parent)
+{
+ g_return_if_fail (CPUFREQ_IS_POPUP (popup));
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+
+ popup->priv->parent = parent;
+}
+
+static void
+cpufreq_popup_frequencies_menu_activate (GtkAction *action,
+ CPUFreqPopup *popup)
+{
+ CPUFreqSelector *selector;
+ const gchar *name;
+ guint cpu;
+ guint freq;
+ guint32 parent;
+
+ if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+ return;
+
+ selector = cpufreq_selector_get_default ();
+
+ cpu = cpufreq_monitor_get_cpu (popup->priv->monitor);
+ name = gtk_action_get_name (action);
+ freq = (guint) atoi (name + strlen ("Frequency"));
+ parent = GDK_WINDOW_XID (gtk_widget_get_window (popup->priv->parent));
+
+
+ cpufreq_selector_set_frequency_async (selector, cpu, freq, parent);
+}
+
+static void
+cpufreq_popup_governors_menu_activate (GtkAction *action,
+ CPUFreqPopup *popup)
+{
+ CPUFreqSelector *selector;
+ const gchar *name;
+ guint cpu;
+ const gchar *governor;
+ guint32 parent;
+
+ if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+ return;
+
+ selector = cpufreq_selector_get_default ();
+
+ cpu = cpufreq_monitor_get_cpu (popup->priv->monitor);
+ name = gtk_action_get_name (action);
+ governor = name + strlen ("Governor");
+ parent = GDK_WINDOW_XID (gtk_widget_get_window (popup->priv->parent));
+
+ cpufreq_selector_set_governor_async (selector, cpu, governor, parent);
+}
+
+static void
+cpufreq_popup_menu_add_action (CPUFreqPopup *popup,
+ const gchar *menu,
+ GtkActionGroup *action_group,
+ const gchar *action_name,
+ const gchar *label,
+ gboolean sensitive)
+{
+ GtkToggleAction *action;
+ gchar *name;
+
+ name = g_strdup_printf ("%s%s", menu, action_name);
+
+ action = g_object_new (GTK_TYPE_RADIO_ACTION,
+ "name", name,
+ "label", label,
+ NULL);
+
+ gtk_action_set_sensitive (GTK_ACTION (action), sensitive);
+
+ gtk_radio_action_set_group (GTK_RADIO_ACTION (action), popup->priv->radio_group);
+ popup->priv->radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
+
+ if (g_ascii_strcasecmp (menu, "Frequency") == 0) {
+ popup->priv->freqs_actions = g_slist_prepend (popup->priv->freqs_actions,
+ (gpointer) action);
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (cpufreq_popup_frequencies_menu_activate),
+ (gpointer) popup);
+ } else if (g_ascii_strcasecmp (menu, "Governor") == 0) {
+ popup->priv->govs_actions = g_slist_prepend (popup->priv->govs_actions,
+ (gpointer) action);
+
+ g_signal_connect (action, "activate",
+ G_CALLBACK (cpufreq_popup_governors_menu_activate),
+ (gpointer) popup);
+ }
+
+ gtk_action_group_add_action (action_group, GTK_ACTION (action));
+ g_object_unref (action);
+
+ g_free (name);
+}
+
+static void
+frequencies_menu_create_actions (CPUFreqPopup *popup)
+{
+ GList *available_freqs;
+
+ available_freqs = cpufreq_monitor_get_available_frequencies (popup->priv->monitor);
+
+ while (available_freqs) {
+ const gchar *text;
+ gchar *freq_text;
+ gchar *label;
+ gchar *unit;
+ gint freq;
+
+ text = (const gchar *) available_freqs->data;
+ freq = atoi (text);
+
+ freq_text = cpufreq_utils_get_frequency_label (freq);
+ unit = cpufreq_utils_get_frequency_unit (freq);
+
+ label = g_strdup_printf ("%s %s", freq_text, unit);
+ g_free (freq_text);
+ g_free (unit);
+
+ cpufreq_popup_menu_add_action (popup,
+ "Frequency",
+ popup->priv->freqs_group,
+ text, label, TRUE);
+ g_free (label);
+
+ available_freqs = g_list_next (available_freqs);
+ }
+}
+
+static void
+governors_menu_create_actions (CPUFreqPopup *popup)
+{
+ GList *available_govs;
+
+ available_govs = cpufreq_monitor_get_available_governors (popup->priv->monitor);
+ available_govs = g_list_sort (available_govs, (GCompareFunc)g_ascii_strcasecmp);
+
+ while (available_govs) {
+ const gchar *governor;
+ gchar *label;
+
+ governor = (const gchar *) available_govs->data;
+ if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ popup->priv->show_freqs = TRUE;
+ available_govs = g_list_next (available_govs);
+ continue;
+ }
+
+ label = g_strdup (governor);
+ label[0] = g_ascii_toupper (label[0]);
+
+ cpufreq_popup_menu_add_action (popup,
+ "Governor",
+ popup->priv->govs_group,
+ governor, label, TRUE);
+ g_free (label);
+
+ available_govs = g_list_next (available_govs);
+ }
+}
+
+static void
+cpufreq_popup_build_ui (CPUFreqPopup *popup,
+ GSList *actions,
+ const gchar *menu_path)
+{
+ GSList *l = NULL;
+
+ for (l = actions; l && l->data; l = g_slist_next (l)) {
+ GtkAction *action;
+ gchar *name = NULL;
+ gchar *label = NULL;
+
+ action = (GtkAction *) l->data;
+
+ g_object_get (G_OBJECT (action),
+ "name", &name,
+ "label", &label,
+ NULL);
+
+ gtk_ui_manager_add_ui (popup->priv->ui_manager,
+ popup->priv->merge_id,
+ menu_path,
+ label, name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+
+ g_free (name);
+ g_free (label);
+ }
+}
+
+static void
+cpufreq_popup_build_frequencies_menu (CPUFreqPopup *popup,
+ const gchar *path)
+{
+ if (!popup->priv->freqs_group) {
+ GtkActionGroup *action_group;
+
+ action_group = gtk_action_group_new ("FreqsActions");
+ popup->priv->freqs_group = action_group;
+ gtk_action_group_set_translation_domain (action_group, NULL);
+
+ frequencies_menu_create_actions (popup);
+ popup->priv->freqs_actions = g_slist_reverse (popup->priv->freqs_actions);
+ gtk_ui_manager_insert_action_group (popup->priv->ui_manager,
+ action_group, 0);
+ }
+
+ cpufreq_popup_build_ui (popup,
+ popup->priv->freqs_actions,
+ path);
+}
+
+static void
+cpufreq_popup_build_governors_menu (CPUFreqPopup *popup,
+ const gchar *path)
+{
+ if (!popup->priv->govs_group) {
+ GtkActionGroup *action_group;
+
+ action_group = gtk_action_group_new ("GovsActions");
+ popup->priv->govs_group = action_group;
+ gtk_action_group_set_translation_domain (action_group, NULL);
+
+ governors_menu_create_actions (popup);
+ popup->priv->govs_actions = g_slist_reverse (popup->priv->govs_actions);
+ gtk_ui_manager_insert_action_group (popup->priv->ui_manager,
+ action_group, 1);
+ }
+
+ cpufreq_popup_build_ui (popup,
+ popup->priv->govs_actions,
+ path);
+}
+
+static void
+cpufreq_popup_build_menu (CPUFreqPopup *popup)
+{
+ if (popup->priv->merge_id > 0) {
+ gtk_ui_manager_remove_ui (popup->priv->ui_manager,
+ popup->priv->merge_id);
+ gtk_ui_manager_ensure_update (popup->priv->ui_manager);
+ }
+
+ popup->priv->merge_id = gtk_ui_manager_new_merge_id (popup->priv->ui_manager);
+
+ cpufreq_popup_build_frequencies_menu (popup, FREQS_PLACEHOLDER_PATH);
+ cpufreq_popup_build_governors_menu (popup, GOVS_PLACEHOLDER_PATH);
+
+ gtk_action_group_set_visible (popup->priv->freqs_group,
+ popup->priv->show_freqs);
+}
+
+static void
+cpufreq_popup_menu_set_active_action (CPUFreqPopup *popup,
+ GtkActionGroup *action_group,
+ const gchar *prefix,
+ const gchar *item)
+{
+ gchar name[128];
+ GtkAction *action;
+
+ g_snprintf (name, sizeof (name), "%s%s", prefix, item);
+ action = gtk_action_group_get_action (action_group, name);
+
+ g_signal_handlers_block_by_func (action,
+ cpufreq_popup_frequencies_menu_activate,
+ popup);
+ g_signal_handlers_block_by_func (action,
+ cpufreq_popup_governors_menu_activate,
+ popup);
+
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+
+ g_signal_handlers_unblock_by_func (action,
+ cpufreq_popup_frequencies_menu_activate,
+ popup);
+ g_signal_handlers_unblock_by_func (action,
+ cpufreq_popup_governors_menu_activate,
+ popup);
+}
+
+static void
+cpufreq_popup_menu_set_active (CPUFreqPopup *popup)
+{
+ const gchar *governor;
+
+ governor = cpufreq_monitor_get_governor (popup->priv->monitor);
+
+ if (g_ascii_strcasecmp (governor, "userspace") == 0) {
+ gchar *active;
+ guint freq;
+
+ freq = cpufreq_monitor_get_frequency (popup->priv->monitor);
+ active = g_strdup_printf ("%d", freq);
+ cpufreq_popup_menu_set_active_action (popup,
+ popup->priv->freqs_group,
+ "Frequency", active);
+ g_free (active);
+ } else {
+ cpufreq_popup_menu_set_active_action (popup,
+ popup->priv->govs_group,
+ "Governor", governor);
+ }
+}
+
+GtkWidget *
+cpufreq_popup_get_menu (CPUFreqPopup *popup)
+{
+ GtkWidget *menu;
+
+ g_return_val_if_fail (CPUFREQ_IS_POPUP (popup), NULL);
+ g_return_val_if_fail (CPUFREQ_IS_MONITOR (popup->priv->monitor), NULL);
+
+ if (!cpufreq_utils_selector_is_available ())
+ return NULL;
+
+ if (popup->priv->need_build) {
+ cpufreq_popup_build_menu (popup);
+ popup->priv->need_build = FALSE;
+ }
+
+ cpufreq_popup_menu_set_active (popup);
+
+ menu = gtk_ui_manager_get_widget (popup->priv->ui_manager,
+ "/CPUFreqSelectorPopup");
+
+ return menu;
+}