2016-09-14 3 views
2

Я программирую простой индикатор, который должен показывать значок для каждого ядра процессора на панели Unity, что изменит цвет в зависимости от температурного диапазона.C и libappindicator - Создание нескольких индикаторов

Это потребует, чтобы у меня было более одного AppIndicator в той же программе, так как я думаю, что нет никакого способа иметь один AppIndicator с несколькими значками или использовать gtk_container для их хранения и добавления в AppIndicator. Я на самом деле пытаюсь использовать 1 AppIndicator для меню (с опцией «Выход») и 1 AppIndicator для каждого ядра процессора.

В программе не было предупреждений Gtk только с одним AppIndicator (основным), но после того, как я добавил код для создания других 2 приложений для каждого ядра процессора (оба с разными уникальными идентификаторами), Gtk начал бросать некоторые предупреждения и критические Сообщения. Индикаторы отображаются на панели, как и предполагалось, но я не хочу просто игнорировать эти сообщения, поскольку они могут скрывать некоторые реальные проблемы под шторами.

Проверка кода, единственное, что я думаю, может быть запуск этих предупреждений и критических сообщений app_indicator_new() вызывается более чем один раз, я на самом деле удалены все меню и menu_item в функции создания для этих дополнительных показателей, оставив только app_indicator_new() вызов и Я все еще получаю эти сообщения (по одному для каждого дополнительного app_indicator_new() вызова после первого):

(process:8040): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8040): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8040): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

Когда я добавить код в меню создается и связанный с некоторыми дополнительными ошибками лишних AppIndicator показывают вверх:

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8681): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed 

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_icon_theme_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(process:8681): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed 

(process:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(process:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(process:8681): Gtk-CRITICAL **: IA__gtk_settings_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed 

(TempI:8681): Gtk-WARNING **: Screen for GtkWindow not set; you must always set 
a screen for a GtkWindow before using the window 

(TempI:8681): Gdk-CRITICAL **: IA__gdk_screen_get_display: assertion 'GDK_IS_SCREEN (screen)' failed 

(TempI:8681): Gdk-CRITICAL **: IA__gdk_keymap_get_for_display: assertion 'GDK_IS_DISPLAY (display)' failed 

(TempI:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(TempI:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

(TempI:8681): Gtk-WARNING **: Screen for GtkWindow not set; you must always set 
a screen for a GtkWindow before using the window 

(TempI:8681): Gdk-CRITICAL **: IA__gdk_screen_get_display: assertion 'GDK_IS_SCREEN (screen)' failed 

(TempI:8681): Gdk-CRITICAL **: IA__gdk_keymap_get_for_display: assertion 'GDK_IS_DISPLAY (display)' failed 

(TempI:8681): GLib-GObject-WARNING **: invalid (NULL) pointer instance 

(TempI:8681): GLib-GObject-CRITICAL **: g_signal_connect_data: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed 

При необходимости я могу выслать код программы, просто не сделал этого, потому что это поставило бы вопрос еще больше. Это блок, где я создаю дополнительные AppIndicators хотя:

for(int i=0; i<TempI_Main.Cores_Counter; i++){ 
    TempI_Main.Core[i].Gtk_Menu_Root=gtk_menu_new(); 

    //The core name ("Core " + number) 
    char IndicatorName[TEMPI_MAX_CHARS]; 
    snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i); 

    TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(IndicatorName); 
    gtk_menu_append(GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root),TempI_Main.Core[i].Gtk_Menu_Root_Description); 
    gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[i].Gtk_Menu_Root_Description),FALSE); 
    gtk_widget_show(TempI_Main.Core[i].Gtk_Menu_Root_Description); 

    TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(IndicatorName,"indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS); 
    app_indicator_set_status(TempI_Main.Core[i].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE); 
    //Need to set icon 
    //Need to set attention icon 

    app_indicator_set_menu(TempI_Main.Core[i].Gtk_Indicator,GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root)); 
} 

Любые подсказки, что может быть причиной? Являются ли несколько индексов приложений для каждой программы не поддерживаемыми?

EDIT:

Исправленный код после @ Жан-Франсуа Фабр ответ.

for(int i=0; i<TempI_Main.Cores_Counter; i++){ 
    TempI_Main.Core[i].Gtk_Menu_Root=gtk_menu_new(); 

    //The core name ("Core " + number) 
    char IndicatorName[TEMPI_MAX_CHARS]; 
    //MAX_CHARS - 6 ("Core "+'\0') is the limit for appending 
    snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i); 

    TempI_Main.Core[i].Gtk_Indicator_Name=strdup(IndicatorName); 

    TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(TempI_Main.Core[i].Gtk_Indicator_Name); 
    gtk_menu_append(GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root),TempI_Main.Core[i].Gtk_Menu_Root_Description); 
    gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[i].Gtk_Menu_Root_Description),FALSE); 
    gtk_widget_show(TempI_Main.Core[i].Gtk_Menu_Root_Description); 

    TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(TempI_Main.Core[i].Gtk_Indicator_Name,"indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS); 
    app_indicator_set_status(TempI_Main.Core[i].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE); 
    //Need to set icon 
    //Need to set attention icon 

    app_indicator_set_menu(TempI_Main.Core[i].Gtk_Indicator,GTK_MENU(TempI_Main.Core[i].Gtk_Menu_Root)); 
} 

EDIT2:

Код для создания единого основного показателя явно. Тем не менее метание предупреждение и критические сообщения:

TempI_Main.Core[0].Gtk_Menu_Root=gtk_menu_new(); 

TempI_Main.Core[0].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label("Core1"); 
gtk_menu_append(GTK_MENU(TempI_Main.Core[0].Gtk_Menu_Root),TempI_Main.Core[0].Gtk_Menu_Root_Description); 
gtk_widget_set_sensitive(GTK_WIDGET(TempI_Main.Core[0].Gtk_Menu_Root_Description),FALSE); 
gtk_widget_show(TempI_Main.Core[0].Gtk_Menu_Root_Description); 

TempI_Main.Core[0].Gtk_Indicator=app_indicator_new("Core1","indicator-messages",APP_INDICATOR_CATEGORY_APPLICATION_STATUS); 
app_indicator_set_status(TempI_Main.Core[0].Gtk_Indicator, APP_INDICATOR_STATUS_ACTIVE); 
//Need to set icon 
//Need to set attention icon 

app_indicator_set_menu(TempI_Main.Core[0].Gtk_Indicator,GTK_MENU(TempI_Main.Core[0].Gtk_Menu_Root)); 

ответ

0

Я нашел корень проблемы, и это смущает сказать, но я просто упустил функцию, которая создала AppIndicator. Он был вызван доgtk_init(), так что откуда все эти ошибки исходили. Во-первых, я имел:

TempI_Set_Core_Indicator(); 

//Starts gtk 
gtk_init(&argc,&argv); 

TempI_Set_Main_Indicator(); 

и просто заменив его:

//Starts gtk 
gtk_init(&argc,&argv); 

TempI_Set_Main_Indicator(); 
TempI_Set_Core_Indicator(); 

было достаточно, чтобы решить эту проблему. Я так много фокусировался на самой функции, что не переставал смотреть, куда ее зовут.

1

что в цикле является просто плохо:

char IndicatorName[TEMPI_MAX_CHARS]; 
snprintf(IndicatorName, TEMPI_MAX_CHARS,"TempI_Core %u",i); 
TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(IndicatorName); 
... 
TempI_Main.Core[i].Gtk_Indicator=app_indicator_new(IndicatorName, ... 

Вы объявляете IndicatorName как автоматические переменные в цикле, но передать его gtk_menu_item_new_with_label, который ожидает const char *, означает: он просто сохранит адрес строки.

Не только память будет использоваться повторно для дальнейших итераций, и все меню будут иметь одно и то же имя индикатора в цикле, но, выходя из цикла, память будет выделена для какой-либо другой переменной, а имена будут уничтожены => неопределенное поведение

Вы должны сделать копию строки, как это:

TempI_Main.Core[i].Gtk_Menu_Root_Description=gtk_menu_item_new_with_label(strdup(IndicatorName)); 

(конечно, лучше было бы хранить скопированный строку, чтобы иметь возможность освободить их, если это необходимо)

+0

Человек, что я наделал?!? : o Спасибо, что указали это! Я создал дополнительное поле для имени «TempI_Main.Core [i] .Gtk_Indicator_Name» и использовал его вместо этого. Тем не менее, я все еще получаю предупреждения и критические сообщения. Я поставлю новый код цикла в вопросе как Редактировать! – IanC

+0

Может ли проблема состоять в том, что куча является динамической, и строка может меняться во время выполнения программы? У libappindicator все еще был бы старый адрес и результат в том же неопределенном поведении? Я попробую использовать строковые литералы и посмотреть, каков результат. – IanC

+0

с strdup, все должно быть в порядке. Вы уверены, что 'TEMPI_MAX_CHARS' достаточно большой? Я бы уменьшил цикл до 1 итерации: легко сделать, может пролить некоторый свет ... –

Смежные вопросы