Imported Upstream version 3.1.2
Youhei SASAKI
10 years ago
10 | 10 | ########### project ############### |
11 | 11 | |
12 | 12 | project ("cairo-dock-plugins") |
13 | set (VERSION "3.1.1") | |
13 | set (VERSION "3.1.2") | |
14 | 14 | |
15 | 15 | add_definitions (-std=c99 -Wall) # -Wextra -Wwrite-strings -Wuninitialized -Werror-implicit-function-declaration -Wstrict-prototypes -Wreturn-type -Wparentheses -Warray-bounds) # removed for stable versions: -Wstrict-prototypes #-Wunreachable-code -Wno-unused-parameter -Wall |
16 | 16 | if (NOT ${CMAKE_BUILD_TYPE}) |
145 | 145 | ############# INDICATOR-APPLET ################# |
146 | 146 | message (STATUS "> Indicator-Applet:") |
147 | 147 | # Note: the names of dbusmenu-glib, dbusmenu-gtk and indicator have changed... |
148 | ## DBusMenu Glib | |
148 | 149 | set (DBUSMENU_MODULE dbusmenu-glib-0.4) |
149 | 150 | pkg_check_modules (DBUSMENU ${DBUSMENU_MODULE}) |
150 | 151 | if (NOT "${DBUSMENU_FOUND}") |
155 | 156 | set (INDICATOR_APPLICATIONADDED_HAS_HINT 1) # now the ApplicationAdded signal (Status-Notifier) has a new parameter (hint) => https://code.launchpad.net/~ted/indicator-application/name-hints/+merge/67213 |
156 | 157 | endif() |
157 | 158 | |
159 | ## DBusMenu Gtk | |
158 | 160 | if ("${gtkversion}" STREQUAL "2") |
159 | 161 | set (DBUSMENU_GTK_MODULE dbusmenu-gtk-0.4) |
160 | 162 | else() |
170 | 172 | pkg_check_modules (DBUSMENU_GTK ${DBUSMENU_GTK_MODULE}) |
171 | 173 | endif() |
172 | 174 | |
175 | ## Indicator | |
173 | 176 | if ("${gtkversion}" STREQUAL "2") |
174 | 177 | set (INDICATOR_APPLET_MODULE indicator-0.4) |
175 | 178 | else() |
187 | 190 | pkg_check_modules (INDICATOR_APPLET ${INDICATOR_APPLET_MODULE}) |
188 | 191 | endif() |
189 | 192 | |
193 | ## libido | |
190 | 194 | if ("${gtkversion}" STREQUAL "2") |
191 | 195 | set (IDO_MODULE libido-0.1) |
192 | 196 | else() |
194 | 198 | endif() |
195 | 199 | pkg_check_modules (IDO ${IDO_MODULE}) |
196 | 200 | |
201 | ## Extract versions of DBusMenu | |
197 | 202 | if ("${DBUSMENU_FOUND}" STREQUAL "1" AND "${DBUSMENU_GTK_FOUND}" STREQUAL "1") |
198 | 203 | STRING (REGEX REPLACE "\\..*" "" DBUSMENU_MAJOR "${DBUSMENU_VERSION}") |
199 | 204 | STRING (REGEX REPLACE "[0-9]*\\.([^ ]+)" "\\1" DBUSMENU_MINOR "${DBUSMENU_VERSION}") # 0.1.7 => 1.7 |
216 | 221 | endif() |
217 | 222 | endif() |
218 | 223 | |
224 | ## Extract version of indicator | |
219 | 225 | if ("${INDICATOR_APPLET_FOUND}" STREQUAL "1") |
220 | 226 | STRING (REGEX REPLACE "\\..*" "" INDICATOR_MAJOR "${INDICATOR_APPLET_VERSION}") |
221 | 227 | STRING (REGEX REPLACE "[0-9]*\\.([^ ]+)" "\\1" INDICATOR_MINOR "${INDICATOR_APPLET_VERSION}") # 0.1.7 => 1.7 |
263 | 269 | if ("${with_indicator3}" STREQUAL "yes") |
264 | 270 | add_subdirectory (Indicator-applet3) |
265 | 271 | endif() |
266 | add_subdirectory (Indicator-applet) | |
267 | set (with_indicator "yes") | |
272 | ## DBusMenu is needed for Indicator-applet | |
273 | if ("${DBUSMENU_FOUND}" STREQUAL "1" AND "${DBUSMENU_GTK_FOUND}" STREQUAL "1") | |
274 | add_subdirectory (Indicator-applet) | |
275 | set (with_indicator "yes") | |
276 | endif() | |
268 | 277 | endif() |
269 | 278 | |
270 | 279 | if (NOT "${DBUSMENU_FOUND}" STREQUAL "1" OR NOT "${DBUSMENU_GTK_FOUND}" STREQUAL "1" OR NOT "${INDICATOR_APPLET_FOUND}" STREQUAL "1") |
343 | 352 | ############# ALSA_MIXER ################# |
344 | 353 | message (STATUS "> AlsaMixer:") |
345 | 354 | set (with_alsa "no") |
355 | set (with_soundmenu "no") | |
346 | 356 | if (NOT "${enable-alsa-mixer}" STREQUAL "no") |
347 | 357 | pkg_check_modules (ALSA_MIXER_PACKAGE alsa) |
348 | 358 | if ("${ALSA_MIXER_PACKAGE_FOUND}" STREQUAL "") |
76 | 76 | } |
77 | 77 | CD_APPLET_LEAVE(); |
78 | 78 | } |
79 | ||
80 | static gboolean _cd_check_edit_menu_cmd (const gchar *cWhich) | |
81 | { | |
82 | gchar *cResult = cairo_dock_launch_command_sync (cWhich); // Gnome (2 + 3(?)) + XFCE(?) | |
83 | gboolean bResult = (cResult != NULL && *cResult == '/'); | |
84 | g_free (cResult); | |
85 | return bResult; | |
86 | } | |
87 | ||
79 | 88 | CD_APPLET_ON_BUILD_MENU_BEGIN |
80 | 89 | gchar *cLabel = g_strdup_printf ("%s (%s)", D_("Quick launch"), D_("middle-click")); |
81 | 90 | CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel, GTK_STOCK_EXECUTE, cd_menu_show_hide_quick_launch, CD_APPLET_MY_MENU); |
86 | 95 | if (!myConfig.cConfigureMenuCommand && !bEditMenuCmdChecked) |
87 | 96 | { |
88 | 97 | bEditMenuCmdChecked = TRUE; |
89 | gchar *cResult = cairo_dock_launch_command_sync ("which alacarte"); // Gnome (2 + 3(?)) + XFCE(?) | |
90 | if (cResult != NULL && *cResult == '/') | |
91 | { | |
98 | if (_cd_check_edit_menu_cmd ("which alacarte")) | |
92 | 99 | s_cEditMenuCmd = "alacarte"; |
93 | } | |
94 | else | |
95 | { | |
96 | g_free (cResult); | |
97 | cResult = cairo_dock_launch_command_sync ("which kmenuedit"); // KDE | |
98 | if (cResult != NULL && *cResult == '/') | |
99 | s_cEditMenuCmd = "kmenuedit"; | |
100 | } /// TODO: handle other DE ... | |
101 | g_free (cResult); | |
100 | else if (_cd_check_edit_menu_cmd ("which kmenuedit")) | |
101 | s_cEditMenuCmd = "kmenuedit"; | |
102 | else if (_cd_check_edit_menu_cmd ("which menulibre")) | |
103 | s_cEditMenuCmd = "menulibre"; | |
102 | 104 | } |
103 | 105 | if (myConfig.cConfigureMenuCommand || s_cEditMenuCmd) |
104 | 106 | CD_APPLET_ADD_IN_MENU_WITH_STOCK (D_("Configure menu"), GTK_STOCK_PREFERENCES, _cd_menu_configure_menu, CD_APPLET_MY_MENU); |
720 | 720 | cLine = g_strdup (pItem->cDescription); |
721 | 721 | cd_rssreader_cut_line (cLine, pLayout, w); |
722 | 722 | pLinkButton = gtk_label_new (cLine); |
723 | gtk_label_set_selectable (GTK_LABEL (pLinkButton), TRUE); | |
723 | 724 | g_free (cLine); |
724 | 725 | |
725 | 726 | pAlign = gtk_alignment_new (0., 0.5, 0., 0.); |
774 | 775 | cairo_dock_show_temporary_dialog_with_icon (D_("No URL is defined\nYou can define one by copying the URL in the clipboard,\n and selecting \"Paste the URL\" in the menu."), |
775 | 776 | myIcon, |
776 | 777 | myContainer, |
777 | myConfig.iNotificationDuration, | |
778 | 1000*myConfig.iNotificationDuration, | |
778 | 779 | myDock ? "same icon" : MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE); |
779 | 780 | else |
780 | 781 | cairo_dock_show_temporary_dialog_with_icon (D_("No data\nDid you set a valid RSS feed?\nIs your connection alive?"), |
781 | 782 | myIcon, |
782 | 783 | myContainer, |
783 | myConfig.iNotificationDuration, | |
784 | 1000*myConfig.iNotificationDuration, | |
784 | 785 | myDock ? "same icon" : MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE); |
785 | 786 | } |
786 | 787 | } |
187 | 187 | } |
188 | 188 | #endif |
189 | 189 | |
190 | static void _cd_cclosure_marshal_VOID__INT_STRING_STRING (GClosure *closure, | |
191 | GValue *return_value G_GNUC_UNUSED, | |
192 | guint n_param_values, | |
193 | const GValue *param_values, | |
194 | gpointer invocation_hint G_GNUC_UNUSED, | |
195 | gpointer marshal_data) | |
196 | { | |
197 | //cd_debug ("=== %s ()", __func__); | |
198 | typedef void (*GMarshalFunc_VOID__INT_STRING_STRING) ( | |
199 | gpointer data1, | |
200 | gint arg_1, | |
201 | gchar *arg_2, | |
202 | gchar *arg_3, | |
203 | gpointer data2); | |
204 | register GMarshalFunc_VOID__INT_STRING_STRING callback; | |
205 | register GCClosure *cc = (GCClosure*) closure; | |
206 | register gpointer data1, data2; | |
207 | g_return_if_fail (n_param_values == 4); // return_value est NULL ici, car la callback ne renvoit rien. | |
208 | ||
209 | if (G_CCLOSURE_SWAP_DATA (closure)) | |
210 | { | |
211 | data1 = closure->data; | |
212 | data2 = g_value_peek_pointer (param_values + 0); | |
213 | } | |
214 | else | |
215 | { | |
216 | data1 = g_value_peek_pointer (param_values + 0); | |
217 | data2 = closure->data; | |
218 | } | |
219 | callback = (GMarshalFunc_VOID__INT_STRING_STRING) (marshal_data ? marshal_data : cc->callback); | |
220 | ||
221 | callback (data1, | |
222 | g_value_get_int (param_values + 1), | |
223 | (char*) g_value_get_string (param_values + 2), | |
224 | (char*) g_value_get_string (param_values + 3), | |
225 | data2); | |
226 | } | |
227 | ||
228 | static void _cd_cclosure_marshal_VOID__INT_STRING (GClosure *closure, | |
229 | GValue *return_value G_GNUC_UNUSED, | |
230 | guint n_param_values, | |
231 | const GValue *param_values, | |
232 | gpointer invocation_hint G_GNUC_UNUSED, | |
233 | gpointer marshal_data) | |
234 | { | |
235 | //cd_debug ("=== %s ()", __func__); | |
236 | typedef void (*GMarshalFunc_VOID__INT_STRING) ( | |
237 | gpointer data1, | |
238 | gint arg_1, | |
239 | gchar *arg_2, | |
240 | gpointer data2); | |
241 | register GMarshalFunc_VOID__INT_STRING callback; | |
242 | register GCClosure *cc = (GCClosure*) closure; | |
243 | register gpointer data1, data2; | |
244 | g_return_if_fail (n_param_values == 3); // return_value est NULL ici, car la callback ne renvoit rien. | |
245 | ||
246 | if (G_CCLOSURE_SWAP_DATA (closure)) | |
247 | { | |
248 | data1 = closure->data; | |
249 | data2 = g_value_peek_pointer (param_values + 0); | |
250 | } | |
251 | else | |
252 | { | |
253 | data1 = g_value_peek_pointer (param_values + 0); | |
254 | data2 = closure->data; | |
255 | } | |
256 | callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback); | |
257 | ||
258 | callback (data1, | |
259 | g_value_get_int (param_values + 1), | |
260 | (char*) g_value_get_string (param_values + 2), | |
261 | data2); | |
262 | } | |
263 | ||
190 | 264 | /////////////// |
191 | 265 | /// Signals /// |
192 | 266 | /////////////// |
270 | 344 | CD_APPLET_LEAVE (); |
271 | 345 | } |
272 | 346 | |
347 | static void on_application_icon_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconName, const gchar *cIconDesc, CairoDockModuleInstance *myApplet) | |
348 | { | |
349 | CD_APPLET_ENTER; | |
350 | cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cIconName, cIconDesc); | |
351 | ||
352 | CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition); | |
353 | g_return_if_fail (pItem != NULL); | |
354 | ||
355 | if (g_strcmp0 (pItem->cIconName, cIconName) == 0) // discard useless updates (skype...) | |
356 | return; | |
357 | g_free (pItem->cIconName); | |
358 | pItem->cIconName = g_strdup (cIconName); | |
359 | g_free (pItem->cAccessibleDesc); | |
360 | pItem->cAccessibleDesc = g_strdup (cIconDesc); | |
361 | ||
362 | if (pItem->iStatus != CD_STATUS_NEEDS_ATTENTION) | |
363 | { | |
364 | cd_satus_notifier_update_item_image (pItem); | |
365 | } | |
366 | ||
367 | CD_APPLET_LEAVE (); | |
368 | } | |
369 | ||
370 | static void on_application_icon_theme_path_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cIconThemePath, CairoDockModuleInstance *myApplet) | |
371 | { | |
372 | CD_APPLET_ENTER; | |
373 | cd_debug ("=== %s (%d, %s)", __func__, iPosition, cIconThemePath); | |
374 | ||
375 | CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition); | |
376 | g_return_if_fail (pItem != NULL); | |
377 | ||
378 | if (g_strcmp0 (cIconThemePath, pItem->cIconThemePath) != 0) | |
379 | { | |
380 | if (pItem->cIconThemePath != NULL) // if the item previously provided a theme, remove it first. | |
381 | cd_satus_notifier_remove_theme_path (pItem->cIconThemePath); | |
382 | g_free (pItem->cIconThemePath); | |
383 | pItem->cIconThemePath = g_strdup (cIconThemePath); | |
384 | ||
385 | cd_satus_notifier_add_theme_path (cIconThemePath); // and add the new one. | |
386 | ||
387 | if (pItem->cIconName != NULL) | |
388 | { | |
389 | cd_satus_notifier_update_item_image (pItem); | |
390 | } | |
391 | } | |
392 | CD_APPLET_LEAVE (); | |
393 | } | |
394 | ||
395 | static void on_application_label_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cLabel, const gchar *cLabelGuide, CairoDockModuleInstance *myApplet) | |
396 | { | |
397 | CD_APPLET_ENTER; | |
398 | cd_debug ("=== %s (%d, %s, %s)", __func__, iPosition, cLabel, cLabelGuide); | |
399 | ||
400 | CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition); | |
401 | g_return_if_fail (pItem != NULL); | |
402 | ||
403 | g_free (pItem->cLabel); | |
404 | pItem->cLabel = g_strdup (cLabel); | |
405 | g_free (pItem->cLabelGuide); | |
406 | pItem->cLabelGuide = g_strdup (cLabelGuide); | |
407 | ||
408 | CD_APPLET_LEAVE (); | |
409 | } | |
410 | ||
411 | static void on_application_title_changed (DBusGProxy *proxy_watcher, gint iPosition, const gchar *cTitle, CairoDockModuleInstance *myApplet) | |
412 | { | |
413 | CD_APPLET_ENTER; | |
414 | cd_debug ("=== %s (%d, %s)", __func__, iPosition, cTitle); | |
415 | ||
416 | CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_position (iPosition); | |
417 | g_return_if_fail (pItem != NULL); | |
418 | ||
419 | if (cTitle != NULL) | |
420 | { | |
421 | g_free (pItem->cTitle); | |
422 | pItem->cTitle = g_strdup (cTitle); | |
423 | } | |
424 | ||
425 | CD_APPLET_LEAVE (); | |
426 | } | |
273 | 427 | |
274 | 428 | ///////////////// |
275 | 429 | /// Get Items /// |
522 | 676 | G_TYPE_INVALID); |
523 | 677 | dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationRemoved", |
524 | 678 | G_CALLBACK(on_removed_application), myApplet, NULL); |
525 | // TODO? ApplicationIconChanged, ApplicationIconThemePathChanged, ApplicationLabelChanged, ApplicationTitleChanged | |
679 | ||
680 | // we add the following signals because some program don't support the StatusNotifier API (skype, once again...) but only the IAS one. | |
681 | dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING_STRING, | |
682 | G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); | |
683 | dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged", | |
684 | G_TYPE_INT, // position | |
685 | G_TYPE_STRING, // icon name | |
686 | G_TYPE_STRING, // icon desc (?) | |
687 | G_TYPE_INVALID); | |
688 | dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconChanged", | |
689 | G_CALLBACK(on_application_icon_changed), myApplet, NULL); | |
690 | ||
691 | dbus_g_object_register_marshaller(_cd_cclosure_marshal_VOID__INT_STRING, | |
692 | G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID); | |
693 | dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged", | |
694 | G_TYPE_INT, // position | |
695 | G_TYPE_STRING, // icon name | |
696 | G_TYPE_STRING, // icon desc (Note: I'm quite sure they will eventually remove it ...) | |
697 | G_TYPE_INVALID); | |
698 | dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationIconThemePathChanged", | |
699 | G_CALLBACK(on_application_icon_theme_path_changed), myApplet, NULL); | |
700 | ||
701 | dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged", | |
702 | G_TYPE_INT, // position | |
703 | G_TYPE_STRING, // label | |
704 | G_TYPE_STRING, // guide | |
705 | G_TYPE_INVALID); | |
706 | dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationLabelChanged", | |
707 | G_CALLBACK(on_application_label_changed), myApplet, NULL); | |
708 | ||
709 | dbus_g_proxy_add_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged", | |
710 | G_TYPE_INT, // position | |
711 | G_TYPE_STRING, // title | |
712 | G_TYPE_INVALID); | |
713 | dbus_g_proxy_connect_signal(myData.pProxyIndicatorApplicationService, "ApplicationTitleChanged", | |
714 | G_CALLBACK(on_application_title_changed), myApplet, NULL); | |
526 | 715 | } |
527 | 716 | |
528 | 717 | ////////////////// |
116 | 116 | CDStatusNotifierItem *pItem; |
117 | 117 | for (i = 0; pApplications[i] != NULL; i ++) |
118 | 118 | { |
119 | g_print (" + '%s'\n", pApplications[i]); // service + path | |
119 | cd_message (" + '%s'", pApplications[i]); // service + path | |
120 | 120 | if (*pApplications[i] == '\0') |
121 | 121 | continue; |
122 | 122 | |
135 | 135 | g_free (cService); |
136 | 136 | if (! pItem) |
137 | 137 | continue; |
138 | cd_debug ("=== => + %s", pItem->cTitle); | |
138 | cd_debug ("=== => + %s", pItem->cTitle?pItem->cTitle:pItem->cLabel); | |
139 | 139 | myData.pItems = g_list_prepend (myData.pItems, pItem); |
140 | 140 | } |
141 | 141 |
32 | 32 | #define CD_STATUS_NOTIFIER_HOST_ADDR "org.kde.StatusNotifierHost" |
33 | 33 | |
34 | 34 | |
35 | static CDStatusNotifierItem * _cd_satus_notifier_find_item_from_service (const gchar *cService) | |
35 | CDStatusNotifierItem * cd_satus_notifier_find_item_from_service (const gchar *cService) | |
36 | 36 | { |
37 | 37 | g_return_val_if_fail (cService != NULL, NULL); |
38 | 38 | CDStatusNotifierItem *pItem; |
46 | 46 | return NULL; |
47 | 47 | } |
48 | 48 | |
49 | static CDStatusNotifierItem * _cd_satus_notifier_find_item_from_position (int iPosition) | |
49 | CDStatusNotifierItem * cd_satus_notifier_find_item_from_position (int iPosition) | |
50 | 50 | { |
51 | 51 | CDStatusNotifierItem *pItem; |
52 | 52 | GList *it; |
66 | 66 | |
67 | 67 | void cd_satus_notifier_add_new_item_with_default (const gchar *cService, const gchar *cObjectPath, int iPosition, const gchar *cIconName, const gchar *cIconThemePath, const gchar *cLabel) |
68 | 68 | { |
69 | CDStatusNotifierItem *pItem = _cd_satus_notifier_find_item_from_service (cService); | |
69 | CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_service (cService); | |
70 | 70 | g_return_if_fail (pItem == NULL); // on evite d'ajouter 2 fois le meme service. |
71 | 71 | |
72 | 72 | pItem = cd_satus_notifier_create_item (cService, cObjectPath); |
88 | 88 | if (pItem->cLabel == NULL) |
89 | 89 | pItem->cLabel = g_strdup (cLabel); |
90 | 90 | |
91 | if (pItem->cMenuPath == NULL) | |
91 | if (pItem->cMenuPath == NULL) /// this is questionnable ... if the item doesn't provide a menu, this could be that it really doesn't use a dbusmenu (but rather relies on the ContextMenu). | |
92 | { | |
93 | cd_debug ("No menu defined for '%s', using '%s' as the menu path", cService, cObjectPath); | |
92 | 94 | pItem->cMenuPath = g_strdup (cObjectPath); |
95 | } | |
96 | // build the dbusmenu right now, so that the menu is complete when the user first click on the item (otherwise, the menu is not placed correctly). | |
97 | cd_satus_notifier_build_item_dbusmenu (pItem); | |
93 | 98 | |
94 | 99 | pItem->iPosition = iPosition; |
95 | 100 | if (pItem->cLabel == NULL && pItem->cTitle == NULL) |
112 | 117 | |
113 | 118 | void cd_satus_notifier_remove_item (const gchar *cService, int iPosition) |
114 | 119 | { |
115 | CDStatusNotifierItem *pItem = (cService ? _cd_satus_notifier_find_item_from_service (cService) : _cd_satus_notifier_find_item_from_position (iPosition)); | |
120 | CDStatusNotifierItem *pItem = (cService ? cd_satus_notifier_find_item_from_service (cService) : cd_satus_notifier_find_item_from_position (iPosition)); | |
116 | 121 | g_return_if_fail (pItem != NULL); |
117 | 122 | |
118 | 123 | myData.pItems = g_list_remove (myData.pItems, pItem); |
218 | 223 | g_hash_table_remove (myData.pThemePaths, cThemePath); // on le supprime de la table. |
219 | 224 | |
220 | 225 | cairo_dock_remove_path_from_icon_theme (cThemePath); |
221 | /**GtkIconTheme *pIconTheme = gtk_icon_theme_get_default(); // et du theme. | |
222 | gchar **paths = NULL; | |
223 | gint iNbPaths = 0; | |
224 | gtk_icon_theme_get_search_path (pIconTheme, &paths, &iNbPaths); | |
225 | ||
226 | int i; | |
227 | for (i = 0; i < iNbPaths; i++) // on cherche sa position dans le tableau. | |
228 | { | |
229 | if (strcmp (paths[i], cThemePath)) | |
230 | break; | |
231 | } | |
232 | if (i < iNbPaths) // trouve | |
233 | { | |
234 | g_free (paths[i]); | |
235 | for (i = i+1; i < iNbPaths; i++) // on decale tous les suivants vers l'arriere. | |
236 | { | |
237 | paths[i-1] = paths[i]; | |
238 | } | |
239 | paths[i-1] = NULL; | |
240 | gtk_icon_theme_set_search_path (pIconTheme, (const gchar **)paths, iNbPaths - 1); | |
241 | } | |
242 | ||
243 | g_strfreev (paths);*/ | |
244 | 226 | } |
245 | 227 | else // on decremente la reference. |
246 | 228 | { |
22 | 22 | #include <cairo-dock.h> |
23 | 23 | |
24 | 24 | |
25 | CDStatusNotifierItem * cd_satus_notifier_find_item_from_service (const gchar *cService); | |
26 | ||
27 | CDStatusNotifierItem * cd_satus_notifier_find_item_from_position (int iPosition); | |
28 | ||
29 | ||
25 | 30 | void cd_satus_notifier_add_new_item_with_default (const gchar *cService, const gchar *cObjectPath, int iPosition, const gchar *cIconName, const gchar *cIconThemePath, const gchar *cLabel); |
26 | 31 | |
27 | 32 | #define cd_satus_notifier_add_new_item(cService, cObjectPath, iPosition) cd_satus_notifier_add_new_item_with_default (cService, cObjectPath, iPosition, NULL, NULL, NULL) |
24 | 24 | #include "applet-struct.h" |
25 | 25 | #include "applet-host.h" |
26 | 26 | #include "applet-draw.h" |
27 | #include "applet-notifications.h" | |
27 | 28 | #include "applet-item.h" |
28 | 29 | |
29 | 30 | #define CD_STATUS_NOTIFIER_ITEM_IFACE "org.kde.StatusNotifierItem" |
140 | 141 | static void on_new_item_icon (DBusGProxy *proxy_item, CDStatusNotifierItem *pItem) |
141 | 142 | { |
142 | 143 | CD_APPLET_ENTER; |
143 | //g_print ("=== %s ()\n", __func__); | |
144 | cd_debug ("=== %s ()", __func__); | |
144 | 145 | |
145 | 146 | g_free (pItem->cIconName); |
146 | 147 | pItem->cIconName = cairo_dock_dbus_get_property_as_string (pItem->pProxyProps, CD_STATUS_NOTIFIER_ITEM_IFACE, "IconName"); |
147 | 148 | g_free (pItem->cAccessibleDesc); |
148 | 149 | pItem->cAccessibleDesc = cairo_dock_dbus_get_property_as_string (pItem->pProxyProps, CD_STATUS_NOTIFIER_ITEM_IFACE, "IconAccessibleDesc"); |
149 | //g_print ("=== new icon : %s\n", pItem->cIconName); | |
150 | cd_debug ("=== new icon : %s", pItem->cIconName); | |
150 | 151 | |
151 | 152 | if (pItem->iStatus != CD_STATUS_NEEDS_ATTENTION) |
152 | 153 | { |
158 | 159 | static void on_new_item_attention_icon (DBusGProxy *proxy_item, CDStatusNotifierItem *pItem) |
159 | 160 | { |
160 | 161 | CD_APPLET_ENTER; |
161 | //g_print ("=== %s ()\n", __func__); | |
162 | cd_debug ("=== %s ()", __func__); | |
162 | 163 | |
163 | 164 | g_free (pItem->cAttentionIconName); |
164 | 165 | pItem->cAttentionIconName = cairo_dock_dbus_get_property_as_string (pItem->pProxyProps, CD_STATUS_NOTIFIER_ITEM_IFACE, "AttentionIconName"); |
165 | //g_print ("=== new attention icon : %s\n", pItem->cAttentionIconName); | |
166 | cd_debug ("=== new attention icon : %s", pItem->cAttentionIconName); | |
166 | 167 | |
167 | 168 | if (pItem->iStatus == CD_STATUS_NEEDS_ATTENTION) |
168 | 169 | { |
223 | 224 | g_free (pItem->cLabelGuide); |
224 | 225 | pItem->cLabelGuide = g_strdup (cLabelGuide); |
225 | 226 | |
226 | ||
227 | 227 | CD_APPLET_LEAVE (); |
228 | 228 | } |
229 | 229 | |
232 | 232 | CD_APPLET_ENTER; |
233 | 233 | //g_print ("=== %s (%s)\n", __func__, cNewThemePath); |
234 | 234 | |
235 | g_free (pItem->cIconThemePath); | |
236 | pItem->cIconThemePath = g_strdup (cNewThemePath); | |
237 | ||
238 | cd_satus_notifier_update_item_image (pItem); | |
235 | if (g_strcmp0 (cNewThemePath, pItem->cIconThemePath) != 0) | |
236 | { | |
237 | if (pItem->cIconThemePath != NULL) // if the item previously provided a theme, remove it first. | |
238 | cd_satus_notifier_remove_theme_path (pItem->cIconThemePath); | |
239 | g_free (pItem->cIconThemePath); | |
240 | pItem->cIconThemePath = g_strdup (cNewThemePath); | |
241 | ||
242 | cd_satus_notifier_update_item_image (pItem); | |
243 | } | |
239 | 244 | |
240 | 245 | CD_APPLET_LEAVE (); |
241 | 246 | } |
329 | 334 | CD_APPLET_LEAVE (); |
330 | 335 | } |
331 | 336 | |
337 | static gboolean _update_icon_delayed (CDStatusNotifierItem *pItem) | |
338 | { | |
339 | cd_debug (""); | |
340 | if (pItem->cIconName != NULL) | |
341 | { | |
342 | cd_satus_notifier_update_item_image (pItem); | |
343 | } | |
344 | pItem->iSidUpdateIcon = 0; | |
345 | return FALSE; | |
346 | } | |
332 | 347 | gchar *cd_satus_notifier_search_item_icon_s_path (CDStatusNotifierItem *pItem, gint iSize) |
333 | 348 | { |
334 | 349 | g_return_val_if_fail (pItem != NULL, NULL); |
351 | 366 | if (cIconPath == NULL) // in case we have a buggy app, try some heuristic |
352 | 367 | { |
353 | 368 | cIconPath = cairo_dock_search_icon_s_path (pItem->cId, iSize); |
354 | if (cIconPath == NULL) | |
369 | if (cIconPath == NULL && pItem->pSurface == NULL) // only use the fallback icon if the item is still empty (to not have an invisible item). | |
370 | { | |
355 | 371 | cIconPath = g_strdup (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE); |
372 | } | |
373 | ||
374 | // skype strikes again ! on startup, it indicates its icon theme path (a temporary folder in /tmp); BUT it copies the icons after, so for a few seconds, the icons it tells us don't exist. | |
375 | // so we trigger an update in a few seconds. | |
376 | if (pItem->iSidUpdateIcon == 0) | |
377 | pItem->iSidUpdateIcon = g_timeout_add_seconds (7, (GSourceFunc)_update_icon_delayed, pItem); | |
356 | 378 | } |
379 | } | |
380 | else if (pItem->iSidUpdateIcon != 0) // we found an icon, discard any pending update. | |
381 | { | |
382 | g_source_remove (pItem->iSidUpdateIcon); | |
383 | pItem->iSidUpdateIcon = 0; | |
357 | 384 | } |
358 | 385 | |
359 | 386 | return cIconPath; |
402 | 429 | { |
403 | 430 | g_return_val_if_fail (cService != NULL, NULL); |
404 | 431 | cd_debug ("=== %s (%s, %s)", __func__, cService, cObjectPath); |
432 | ||
433 | // avoid creating an item that already exists. This can happen in the following case (skype): | |
434 | // watcher starts -> dock registers to it -> dock asks the items - - - - - - - - - - - - - - - - - -> dock receives the items -> skype item is already here ! | |
435 | // -> skype creates its item -> 'new-item' is emitted -> dock receives the signal -> creates the item | |
436 | if (cd_satus_notifier_find_item_from_service (cService) != NULL) | |
437 | { | |
438 | cd_debug ("The service %s / %s is already listed, skip it", cService, cObjectPath); | |
439 | return NULL; | |
440 | } | |
405 | 441 | |
406 | 442 | gchar *str = strchr (cService, '/'); // just to be sure. |
407 | 443 | if (str) |
618 | 654 | cd_satus_notifier_add_theme_path (pItem->cIconThemePath); |
619 | 655 | } |
620 | 656 | |
621 | if (pItem->cMenuPath != NULL) | |
622 | pItem->pMenu = dbusmenu_gtkmenu_new ((gchar *)pItem->cService, (gchar *)pItem->cMenuPath); | |
657 | // build the dbusmenu right now, so that the menu is complete when the user first click on the item (otherwise, the menu is not placed correctly). | |
658 | cd_satus_notifier_build_item_dbusmenu (pItem); | |
623 | 659 | |
624 | 660 | //\_________________ track any changes in the item. |
625 | 661 | // signals supported by both. |
674 | 710 | return pItem; |
675 | 711 | } |
676 | 712 | |
713 | static gboolean _on_draw_menu_reposition (GtkWidget *pWidget, G_GNUC_UNUSED gpointer useless, CDStatusNotifierItem *pItem); | |
714 | ||
677 | 715 | void cd_free_item (CDStatusNotifierItem *pItem) |
678 | 716 | { |
679 | 717 | if (pItem == NULL) |
681 | 719 | pItem->bInvalid = TRUE; |
682 | 720 | if (pItem->iSidPopupTooltip != 0) |
683 | 721 | g_source_remove (pItem->iSidPopupTooltip); |
722 | if (pItem->iSidUpdateIcon != 0) | |
723 | g_source_remove (pItem->iSidUpdateIcon); | |
684 | 724 | if (pItem->cIconThemePath) |
685 | 725 | cd_satus_notifier_remove_theme_path (pItem->cIconThemePath); |
726 | if (pItem->pMenu != NULL) | |
727 | g_object_unref (pItem->pMenu); // will remove the 'reposition' callback too. | |
686 | 728 | g_object_unref (pItem->pProxy); |
687 | 729 | g_object_unref (pItem->pProxyProps); |
688 | 730 | g_free (pItem->cService); |
756 | 798 | } |
757 | 799 | return NULL; |
758 | 800 | } |
801 | ||
802 | ||
803 | static gboolean _on_draw_menu_reposition (GtkWidget *pWidget, G_GNUC_UNUSED gpointer useless, CDStatusNotifierItem *pItem) | |
804 | { | |
805 | g_return_val_if_fail (pItem != NULL, FALSE); | |
806 | ||
807 | int iMenuWidth = gtk_widget_get_allocated_width (pWidget); | |
808 | ||
809 | if (pItem->iMenuWidth != iMenuWidth) // if the width has changed, reposition the menu to be sure it won't out of the screen. | |
810 | { | |
811 | pItem->iMenuWidth = iMenuWidth; | |
812 | gtk_menu_reposition (GTK_MENU (pWidget)); | |
813 | } | |
814 | ||
815 | return FALSE; // FALSE to propagate the event further. | |
816 | } | |
817 | void cd_satus_notifier_build_item_dbusmenu (CDStatusNotifierItem *pItem) | |
818 | { | |
819 | if (pItem->pMenu == NULL) // menu not yet built | |
820 | { | |
821 | if (pItem->cMenuPath != NULL && *pItem->cMenuPath != '\0' && strcmp (pItem->cMenuPath, "/NO_DBUSMENU") != 0) // hopefully, if the item doesn't provide a dbusmenu, it will not set something different as these 2 choices (ex.: Klipper). | |
822 | { | |
823 | pItem->pMenu = dbusmenu_gtkmenu_new ((gchar *)pItem->cService, (gchar *)pItem->cMenuPath); | |
824 | if (g_object_is_floating (pItem->pMenu)) // claim ownership on the menu. | |
825 | g_object_ref_sink (pItem->pMenu); | |
826 | /* Position of the menu: GTK doesn't do its job :-/ | |
827 | * e.g. with Dropbox: the menu is out of the screen every time | |
828 | * something has changed in this menu (it displays 'connecting', | |
829 | * free space available, etc.) -> we need to reposition it. | |
830 | * (maybe it's due to a delay because Python and DBus are slower...) | |
831 | * We can't watch the 'configure' event (which should be triggered | |
832 | * each time the menu is resized) because it seems this notification | |
833 | * is not send... | |
834 | * This is why we need to watch the 'draw' event... | |
835 | */ | |
836 | g_signal_connect (G_OBJECT (pItem->pMenu), | |
837 | #if (GTK_MAJOR_VERSION < 3) | |
838 | "expose-event", | |
839 | #else | |
840 | "draw", | |
841 | #endif | |
842 | G_CALLBACK (_on_draw_menu_reposition), | |
843 | pItem); | |
844 | } | |
845 | } | |
846 | } |
39 | 39 | #define _item_is_visible(item) ((item)->iStatus != CD_STATUS_PASSIVE || ! myConfig.bHideInactive) |
40 | 40 | |
41 | 41 | |
42 | void cd_satus_notifier_build_item_dbusmenu (CDStatusNotifierItem *pItem); | |
43 | ||
44 | ||
42 | 45 | #endif |
83 | 83 | } |
84 | 84 | |
85 | 85 | |
86 | static inline gboolean _popup_menu (CDStatusNotifierItem *pItem, Icon *pIcon, CairoContainer *pContainer) | |
86 | static gboolean _popup_menu (CDStatusNotifierItem *pItem, Icon *pIcon, CairoContainer *pContainer) | |
87 | 87 | { |
88 | 88 | gboolean r = FALSE; |
89 | if (pItem->cMenuPath != NULL && *pItem->cMenuPath != '\0' && strcmp (pItem->cMenuPath, "/NO_DBUSMENU") != 0) // hopefully, if the item doesn't have a dbusmenu, it will not set something different as these 2 choices. | |
90 | { | |
91 | if (pItem->pMenu == NULL) | |
92 | pItem->pMenu = dbusmenu_gtkmenu_new ((gchar *)pItem->cService, (gchar *)pItem->cMenuPath); | |
93 | if (pItem->pMenu != NULL) | |
94 | { | |
95 | cairo_dock_popup_menu_on_icon (GTK_WIDGET (pItem->pMenu), pIcon, pContainer); | |
96 | r = TRUE; | |
97 | } | |
89 | ||
90 | cd_satus_notifier_build_item_dbusmenu (pItem); | |
91 | if (pItem->pMenu != NULL) | |
92 | { | |
93 | cairo_dock_popup_menu_on_icon (GTK_WIDGET (pItem->pMenu), pIcon, pContainer); | |
94 | r = TRUE; | |
98 | 95 | } |
99 | 96 | |
100 | 97 | if (!r) // no menu available, send the corresponding action |
35 | 35 | gboolean cd_status_notifier_on_enter_icon (CairoDockModuleInstance *myApplet, Icon *pIcon, CairoDock *pDock, gboolean *bStartAnimation); |
36 | 36 | |
37 | 37 | |
38 | gboolean on_draw_menu_reposition (GtkWidget *pWidget, G_GNUC_UNUSED gpointer useless, gpointer data); | |
39 | ||
38 | 40 | gboolean on_mouse_moved (CairoDockModuleInstance *myApplet, CairoContainer *pContainer, gboolean *bStartAnimation); |
39 | 41 | |
40 | 42 | gboolean on_update_desklet (CairoDockModuleInstance *myApplet, CairoContainer *pContainer, gboolean *bContinueAnimation); |
98 | 98 | gboolean bInvalid; // item deja en cours de destruction |
99 | 99 | DbusmenuGtkMenu *pMenu; |
100 | 100 | cairo_surface_t *pSurface; |
101 | guint iSidUpdateIcon; | |
102 | // menu redraw | |
103 | int iMenuWidth; | |
101 | 104 | } CDStatusNotifierItem; |
102 | 105 | |
103 | 106 |
30 | 30 | bus_iface_str = 'org.kde.StatusNotifierWatcher' |
31 | 31 | items_list = [] # array of service+path |
32 | 32 | hosts_list = [] # array of services |
33 | ||
34 | def _emit_host_registered (self): | |
35 | self.StatusNotifierHostRegistered() | |
36 | return False | |
33 | 37 | |
34 | 38 | def __init__(self): |
35 | 39 | DBusGMainLoop(set_as_default=True) |
73 | 77 | for it in to_be_removed: |
74 | 78 | self.hosts_list.remove (it) |
75 | 79 | self.StatusNotifierHostUnregistered() |
80 | elif (service == 'com.Skype.API'): # this stupid proprietary software only creates its item when the host appears ! | |
81 | glib.timeout_add_seconds(2, self._emit_host_registered) | |
76 | 82 | |
77 | 83 | ### methods ### |
78 | 84 | |
111 | 117 | return self.items_list |
112 | 118 | else: # too bad! dbus-python can't encode the GValue if 'items_list' is None or []. |
113 | 119 | return [''] # so we return a empty string; hopefuly the host will skip this invalid value. |
114 | elif property == 'HasStatusNotifierHostRegistered': | |
120 | elif property == 'IsStatusNotifierHostRegistered': | |
121 | return (len (self.hosts_list) != 0) | |
122 | elif property == 'HasStatusNotifierHostRegistered': # deprecated | |
115 | 123 | return (len (self.hosts_list) != 0) |
116 | 124 | elif property == 'ProtocolVersion': |
117 | 125 | return 0 |
48 | 48 | pInterface->save_custom_widget = cd_clock_save_custom_widget; |
49 | 49 | CD_APPLET_DEFINE_END |
50 | 50 | |
51 | static gboolean _cd_check_new_minute (CairoDockModuleInstance *myApplet) | |
52 | { | |
53 | myData.iSidUpdateClock = g_timeout_add_seconds (60, | |
54 | (GSourceFunc) cd_clock_update_with_time, | |
55 | (gpointer) myApplet); // this new g_timeout should start approximately at 00" (between 00" and 01" ; better than between [00-60]) | |
56 | cd_clock_update_with_time (myApplet); // update the time right now and not after 60sec | |
57 | return FALSE; | |
58 | } | |
59 | ||
60 | static void _cd_launch_timer (CairoDockModuleInstance *myApplet) | |
61 | { | |
62 | cd_clock_update_with_time (myApplet); // should update myData.currentTime | |
63 | ||
64 | if (! myConfig.bShowSeconds) // can be interesting to show the correct minute... Start the new timer with a delay | |
65 | { | |
66 | guint iWaitSeconds = 60 - myData.currentTime.tm_sec; | |
67 | cd_debug ("Waiting for a new minute during %d sec", iWaitSeconds); | |
68 | ||
69 | myData.iSidUpdateClock = g_timeout_add_seconds (iWaitSeconds, | |
70 | (GSourceFunc) _cd_check_new_minute, | |
71 | (gpointer) myApplet); | |
72 | } | |
73 | else | |
74 | myData.iSidUpdateClock = g_timeout_add_seconds (1, (GSourceFunc) cd_clock_update_with_time, (gpointer) myApplet); | |
75 | } | |
51 | 76 | |
52 | 77 | CD_APPLET_INIT_BEGIN |
53 | 78 | if (myDesklet) |
95 | 120 | cd_clock_list_tasks (myApplet); |
96 | 121 | |
97 | 122 | //\_______________ On lance le timer. |
98 | if (! myConfig.bShowSeconds) // pour ne pas attendre 1 mn avant d'avoir le dessin. | |
99 | cd_clock_update_with_time (myApplet); | |
100 | myData.iSidUpdateClock = g_timeout_add_seconds ((myConfig.bShowSeconds ? 1: 60), (GSourceFunc) cd_clock_update_with_time, (gpointer) myApplet); | |
123 | _cd_launch_timer (myApplet); | |
101 | 124 | CD_APPLET_INIT_END |
102 | 125 | |
103 | 126 | |
165 | 188 | myData.iLastCheckedDay = -1; |
166 | 189 | myData.iLastCheckedMonth = -1; |
167 | 190 | myData.iLastCheckedYear = -1; |
168 | cd_clock_update_with_time (myApplet); | |
169 | myData.iSidUpdateClock = g_timeout_add_seconds ((myConfig.bShowSeconds ? 1: 60), (GSourceFunc) cd_clock_update_with_time, (gpointer) myApplet); | |
191 | _cd_launch_timer (myApplet); | |
170 | 192 | } |
171 | 193 | else |
172 | 194 | { |
53 | 53 | static inline void _fill_handler_properties (const gchar *cDesktopFileName, gchar *cAppClass) |
54 | 54 | { |
55 | 55 | g_free ((gchar*)myData.pCurrentHandler->appclass); |
56 | if (cAppClass == NULL) // cAppClass: this parameter is optional | |
57 | myData.pCurrentHandler->appclass = cairo_dock_register_class (cDesktopFileName); | |
58 | else | |
59 | myData.pCurrentHandler->appclass = cAppClass; | |
56 | myData.pCurrentHandler->appclass = cAppClass; | |
60 | 57 | g_free ((gchar*)myData.pCurrentHandler->launch); |
61 | 58 | myData.pCurrentHandler->launch = g_strdup (cairo_dock_get_class_command (myData.pCurrentHandler->appclass)); |
62 | 59 | if (myData.pCurrentHandler->launch == NULL) // we really need a command to launch it on click, so insist a little |
63 | { | |
64 | 60 | myData.pCurrentHandler->launch = g_strdup (cDesktopFileName); |
65 | } | |
66 | 61 | g_free ((gchar*)myData.pCurrentHandler->cDisplayedName); |
67 | 62 | myData.pCurrentHandler->cDisplayedName = g_strdup (cairo_dock_get_class_name (myData.pCurrentHandler->appclass)); |
63 | } | |
64 | ||
65 | static inline void _get_right_class_and_desktop_file (const gchar *cName, gchar **cDesktopFileName, gchar **cAppClass) | |
66 | { | |
67 | if (myConfig.cLastKnownDesktopFile) | |
68 | { | |
69 | *cDesktopFileName = myConfig.cLastKnownDesktopFile; | |
70 | *cAppClass = cairo_dock_register_class (*cDesktopFileName); // no need to be freed here | |
71 | } | |
72 | if (*cAppClass == NULL && cName) // myConfig.cLastKnownDesktopFile is NULL when transitionning from an old version of the applet where we didn't use the "Desktop Entry" property yet -> use some heuristic as a fallback. | |
73 | { | |
74 | *cAppClass = cairo_dock_register_class (cName); // no need to be freed here | |
75 | if (*cAppClass == NULL && | |
76 | (*cDesktopFileName = strrchr (cName, '.')) != NULL) // if cName = org.mpris.MediaPlayer2.amarok => amarok | |
77 | *cAppClass = cairo_dock_register_class (*cDesktopFileName+1); // no need to be freed here | |
78 | else | |
79 | *cDesktopFileName = (gchar *)cName; | |
80 | } | |
81 | cd_debug ("%s (%s - %s) => (%s - %s)", __func__, myConfig.cLastKnownDesktopFile, cName, *cDesktopFileName, *cAppClass); | |
68 | 82 | } |
69 | 83 | |
70 | 84 | MusicPlayerHandler *cd_musicplayer_get_handler_by_name (const gchar *cName) |
361 | 375 | myData.pCurrentHandler = cd_musicplayer_get_handler_by_name ("Mpris2"); // no need to watch it, it was already done (that's why we are here !) |
362 | 376 | |
363 | 377 | // fill its properties |
364 | myData.pCurrentHandler->appclass = cairo_dock_register_class (myConfig.cLastKnownDesktopFile ? myConfig.cLastKnownDesktopFile : cName); // myConfig.cLastKnownDesktopFile is NULL when transitionning from an old version of the applet where we didn't use the "Desktop Entry" property yet -> use some heuristic as a fallback. | |
365 | myData.pCurrentHandler->launch = g_strdup (cairo_dock_get_class_command (myData.pCurrentHandler->appclass)); | |
366 | myData.pCurrentHandler->cDisplayedName = g_strdup (cairo_dock_get_class_name (myData.pCurrentHandler->appclass)); | |
367 | if (myData.pCurrentHandler->launch == NULL) // we really need a command to launch it on click, so insist a little | |
368 | { | |
369 | myData.pCurrentHandler->launch = g_strdup (cName); | |
370 | } | |
371 | ||
378 | gchar *cAppClass = NULL, *cDesktopFileName = NULL; | |
379 | _get_right_class_and_desktop_file (cName, &cDesktopFileName, &cAppClass); | |
380 | if (cAppClass) // better to not use any class than a wrong class | |
381 | _fill_handler_properties (cDesktopFileName, cAppClass); | |
382 | ||
372 | 383 | g_free ((gchar*)myData.pCurrentHandler->cMprisService); |
373 | 384 | myData.pCurrentHandler->cMprisService = g_strdup (cName); |
374 | 385 | } |
487 | 498 | // get the MPRIS2 handler |
488 | 499 | myData.pCurrentHandler = cd_musicplayer_get_handler_by_name ("Mpris2"); |
489 | 500 | |
490 | // fill its properties | |
491 | /* myConfig.cLastKnownDesktopFile is NULL when transitionning from an | |
492 | * old version of the applet where we didn't use the "Desktop Entry" | |
493 | * property yet -> use some heuristic as a fallback. | |
494 | */ | |
495 | _fill_handler_properties (myConfig.cLastKnownDesktopFile ? myConfig.cLastKnownDesktopFile : cName, NULL); | |
501 | gchar *cAppClass = NULL, *cDesktopFileName = NULL; | |
502 | _get_right_class_and_desktop_file (cName, &cDesktopFileName, &cAppClass); | |
503 | if (cAppClass) // better to not use any class than a wrong class | |
504 | _fill_handler_properties (cDesktopFileName, cAppClass); | |
496 | 505 | |
497 | 506 | myData.pCurrentHandler->cMprisService = g_strdup_printf (CD_MPRIS2_SERVICE_BASE".%s", cName); |
498 | 507 | myData.cMpris2Service = NULL; |