1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <math.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <cairo.h>
24
25 #include "cairo-dock-image-buffer.h"
26 #include "cairo-dock-draw.h"
27 #include "cairo-dock-utils.h" // cairo_dock_launch_command
28 #include "cairo-dock-launcher-manager.h"
29 #include "cairo-dock-surface-factory.h"
30 #include "cairo-dock-animations.h"
31 #include "cairo-dock-packages.h"
32 #include "cairo-dock-keyfile-utilities.h"
33 #include "cairo-dock-module-instance-manager.h" // GldiModuleInstance
34 #include "cairo-dock-module-manager.h" // GldiModuleInstance
35 #include "cairo-dock-log.h"
36 #include "cairo-dock-config.h"
37 #include "cairo-dock-dock-factory.h"
38 #include "cairo-dock-dock-manager.h"
39 #include "cairo-dock-draw-opengl.h"
40 #include "cairo-dock-icon-factory.h"
41 #include "cairo-dock-container.h"
42 #include "cairo-dock-gui-manager.h"
43 #include "cairo-dock-backends-manager.h"
44 #include "cairo-dock-dock-facility.h"
45 #include "cairo-dock-icon-facility.h"
46 #include "cairo-dock-applet-facility.h"
47
48 extern gchar *g_cExtrasDirPath;
49
50 extern gboolean g_bUseOpenGL;
51
52
cairo_dock_set_icon_surface_full(cairo_t * pIconContext,cairo_surface_t * pSurface,double fScale,double fAlpha,Icon * pIcon)53 void cairo_dock_set_icon_surface_full (cairo_t *pIconContext, cairo_surface_t *pSurface, double fScale, double fAlpha, Icon *pIcon)
54 {
55 //\________________ On efface l'ancienne image.
56 if (! cairo_dock_begin_draw_icon_cairo (pIcon, 0, pIconContext)) // 0 <=> erase
57 return;
58
59 //\________________ On applique la nouvelle image.
60 if (pSurface != NULL && fScale > 0)
61 {
62 cairo_save (pIconContext);
63 if (fScale != 1 && pIcon != NULL)
64 {
65 int iWidth, iHeight;
66 cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
67 cairo_translate (pIconContext, .5 * iWidth * (1 - fScale) , .5 * iHeight * (1 - fScale));
68 cairo_scale (pIconContext, fScale, fScale);
69 }
70
71 cairo_set_source_surface (
72 pIconContext,
73 pSurface,
74 0.,
75 0.);
76
77 if (fAlpha != 1)
78 cairo_paint_with_alpha (pIconContext, fAlpha);
79 else
80 cairo_paint (pIconContext);
81 cairo_restore (pIconContext);
82 }
83 cairo_dock_end_draw_icon_cairo (pIcon);
84 }
85
86
87 /// TODO: don't use 'cairo_dock_set_icon_surface' here...
cairo_dock_set_image_on_icon(cairo_t * pIconContext,const gchar * cIconName,Icon * pIcon,G_GNUC_UNUSED GldiContainer * pContainer)88 gboolean cairo_dock_set_image_on_icon (cairo_t *pIconContext, const gchar *cIconName, Icon *pIcon, G_GNUC_UNUSED GldiContainer *pContainer)
89 {
90 //g_print ("%s (%s)\n", __func__, cIconName);
91 // load the image in a surface.
92 int iWidth, iHeight;
93 cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
94 cairo_surface_t *pImageSurface = cairo_dock_create_surface_from_icon (cIconName,
95 iWidth,
96 iHeight);
97
98 // check that it's ok.
99 if (pImageSurface == NULL) // let the icon in its current state.
100 return FALSE;
101
102 // set the new image on the icon
103 cairo_dock_set_icon_surface (pIconContext, pImageSurface, pIcon);
104
105 cairo_surface_destroy (pImageSurface);
106
107 if (cIconName != pIcon->cFileName)
108 {
109 g_free (pIcon->cFileName);
110 pIcon->cFileName = g_strdup (cIconName);
111 }
112 return TRUE;
113 }
114
cairo_dock_set_image_on_icon_with_default(cairo_t * pIconContext,const gchar * cIconName,Icon * pIcon,GldiContainer * pContainer,const gchar * cDefaultImagePath)115 void cairo_dock_set_image_on_icon_with_default (cairo_t *pIconContext, const gchar *cIconName, Icon *pIcon, GldiContainer *pContainer, const gchar *cDefaultImagePath)
116 {
117 if (! cIconName || ! cairo_dock_set_image_on_icon (pIconContext, cIconName, pIcon, pContainer))
118 cairo_dock_set_image_on_icon (pIconContext, cDefaultImagePath, pIcon, pContainer);
119 }
120
121
cairo_dock_set_hours_minutes_as_quick_info(Icon * pIcon,int iTimeInSeconds)122 void cairo_dock_set_hours_minutes_as_quick_info (Icon *pIcon, int iTimeInSeconds)
123 {
124 int hours = iTimeInSeconds / 3600;
125 int minutes = (iTimeInSeconds % 3600) / 60;
126 if (hours != 0)
127 gldi_icon_set_quick_info_printf (pIcon, "%dh%02d", hours, abs (minutes));
128 else
129 gldi_icon_set_quick_info_printf (pIcon, "%dmn", minutes);
130 }
131
cairo_dock_set_minutes_secondes_as_quick_info(Icon * pIcon,int iTimeInSeconds)132 void cairo_dock_set_minutes_secondes_as_quick_info (Icon *pIcon, int iTimeInSeconds)
133 {
134 int minutes = iTimeInSeconds / 60;
135 int secondes = iTimeInSeconds % 60;
136 //cd_debug ("%s (%d:%d)", __func__, minutes, secondes);
137 if (minutes != 0)
138 gldi_icon_set_quick_info_printf (pIcon, "%d:%02d", minutes, abs (secondes));
139 else
140 gldi_icon_set_quick_info_printf (pIcon, "%s0:%02d", (secondes < 0 ? "-" : ""), abs (secondes));
141 }
142
cairo_dock_get_human_readable_size(long long int iSizeInBytes)143 gchar *cairo_dock_get_human_readable_size (long long int iSizeInBytes)
144 {
145 double fValue;
146 if (iSizeInBytes >> 10 == 0)
147 {
148 return g_strdup_printf ("%dB", (int) iSizeInBytes);
149 }
150 else if (iSizeInBytes >> 20 == 0)
151 {
152 fValue = (double) (iSizeInBytes) / 1024.;
153 return g_strdup_printf (fValue < 10 ? "%.1fK" : "%.0fK", fValue);
154 }
155 else if (iSizeInBytes >> 30 == 0)
156 {
157 fValue = (double) (iSizeInBytes >> 10) / 1024.;
158 return g_strdup_printf (fValue < 10 ? "%.1fM" : "%.0fM", fValue);
159 }
160 else if (iSizeInBytes >> 40 == 0)
161 {
162 fValue = (double) (iSizeInBytes >> 20) / 1024.;
163 return g_strdup_printf (fValue < 10 ? "%.1fG" : "%.0fG", fValue);
164 }
165 else
166 {
167 fValue = (double) (iSizeInBytes >> 30) / 1024.;
168 return g_strdup_printf (fValue < 10 ? "%.1fT" : "%.0fT", fValue);
169 }
170 }
171
cairo_dock_set_size_as_quick_info(Icon * pIcon,long long int iSizeInBytes)172 void cairo_dock_set_size_as_quick_info (Icon *pIcon, long long int iSizeInBytes)
173 {
174 gchar *cSize = cairo_dock_get_human_readable_size (iSizeInBytes);
175 gldi_icon_set_quick_info (pIcon, cSize);
176 g_free (cSize);
177 }
178
179
180
cairo_dock_get_theme_path_for_module(const gchar * cAppletConfFilePath,GKeyFile * pKeyFile,const gchar * cGroupName,const gchar * cKeyName,gboolean * bFlushConfFileNeeded,const gchar * cDefaultThemeName,const gchar * cShareThemesDir,const gchar * cExtraDirName)181 gchar *cairo_dock_get_theme_path_for_module (const gchar *cAppletConfFilePath, GKeyFile *pKeyFile, const gchar *cGroupName, const gchar *cKeyName, gboolean *bFlushConfFileNeeded, const gchar *cDefaultThemeName, const gchar *cShareThemesDir, const gchar *cExtraDirName)
182 {
183 gchar *cThemeName = cairo_dock_get_string_key_value (pKeyFile, cGroupName, cKeyName, bFlushConfFileNeeded, cDefaultThemeName, NULL, NULL);
184
185 gchar *cUserThemesDir = (cExtraDirName != NULL ? g_strdup_printf ("%s/%s", g_cExtrasDirPath, cExtraDirName) : NULL);
186 CairoDockPackageType iType = cairo_dock_extract_package_type_from_name (cThemeName);
187 gchar *cThemePath = cairo_dock_get_package_path (cThemeName, cShareThemesDir, cUserThemesDir, cExtraDirName, iType);
188
189 if (iType != CAIRO_DOCK_ANY_PACKAGE)
190 {
191 g_key_file_set_string (pKeyFile, cGroupName, cKeyName, cThemeName);
192 cairo_dock_write_keys_to_file (pKeyFile, cAppletConfFilePath);
193 }
194 g_free (cThemeName);
195 g_free (cUserThemesDir);
196 return cThemePath;
197 }
198
199
200 //Utile pour jouer des fichiers son depuis le dock.
201 //A utiliser avec l'Objet UI 'u' dans les .conf
cairo_dock_play_sound(const gchar * cSoundPath)202 void cairo_dock_play_sound (const gchar *cSoundPath)
203 {
204 cd_debug ("%s (%s)", __func__, cSoundPath);
205 if (cSoundPath == NULL)
206 {
207 cd_warning ("No sound to play, skip.");
208 return;
209 }
210
211 gchar *cSoundCommand = NULL;
212 if (g_file_test ("/usr/bin/paplay", G_FILE_TEST_EXISTS))
213 cSoundCommand = g_strdup_printf("paplay --client-name=cairo-dock \"%s\"", cSoundPath);
214
215 else if (g_file_test ("/usr/bin/aplay", G_FILE_TEST_EXISTS))
216 cSoundCommand = g_strdup_printf("aplay \"%s\"", cSoundPath);
217
218 else if (g_file_test ("/usr/bin/play", G_FILE_TEST_EXISTS))
219 cSoundCommand = g_strdup_printf("play \"%s\"", cSoundPath);
220
221
222 cairo_dock_launch_command (cSoundCommand);
223
224 g_free (cSoundCommand);
225 }
226
227 // should be in gnome-integration if needed...
228 /*void cairo_dock_get_gnome_version (int *iMajor, int *iMinor, int *iMicro) {
229 gchar *cContent = NULL;
230 gsize length = 0;
231 GError *erreur = NULL;
232 g_file_get_contents ("/usr/share/gnome-about/gnome-version.xml", &cContent, &length, &erreur);
233
234 if (erreur != NULL) {
235 cd_warning (erreur->message);
236 g_error_free (erreur);
237 erreur = NULL;
238 *iMajor = 0;
239 *iMinor = 0;
240 *iMicro = 0;
241 return;
242 }
243
244 gchar **cLineList = g_strsplit (cContent, "\n", -1);
245 gchar *cOneLine = NULL, *cMajor = NULL, *cMinor = NULL, *cMicro = NULL;
246 int i, iMaj = 0, iMin = 0, iMic = 0;
247 for (i = 0; cLineList[i] != NULL; i ++) {
248 cOneLine = cLineList[i];
249 if (*cOneLine == '\0')
250 continue;
251
252 //Seeking for Major
253 cMajor = g_strstr_len (cOneLine, -1, "<platform>"); //<platform>2</platform>
254 if (cMajor != NULL) {
255 cMajor += 10; //On saute <platform>
256 gchar *str = strchr (cMajor, '<');
257 if (str != NULL)
258 *str = '\0'; //On bloque a </platform>
259 iMaj = atoi (cMajor);
260 }
261 else { //Gutsy xml's doesn't have <platform> but <major>
262 cMajor = g_strstr_len (cOneLine, -1, "<major>"); //<major>2</major>
263 if (cMajor != NULL) {
264 cMajor += 7; //On saute <major>
265 gchar *str = strchr (cMajor, '<');
266 if (str != NULL)
267 *str = '\0'; //On bloque a </major>
268 iMaj = atoi (cMajor);
269 }
270 }
271
272 //Seeking for Minor
273 cMinor = g_strstr_len (cOneLine, -1, "<minor>"); //<minor>22</minor>
274 if (cMinor != NULL) {
275 cMinor += 7; //On saute <minor>
276 gchar *str = strchr (cMinor, '<');
277 if (str != NULL)
278 *str = '\0'; //On bloque a </minor>
279 iMin = atoi (cMinor);
280 }
281
282 //Seeking for Micro
283 cMicro = g_strstr_len (cOneLine, -1, "<micro>"); //<micro>3</micro>
284 if (cMicro != NULL) {
285 cMicro += 7; //On saute <micro>
286 gchar *str = strchr (cMicro, '<');
287 if (str != NULL)
288 *str = '\0'; //On bloque a </micro>
289 iMic = atoi (cMicro);
290 }
291
292 if (iMaj != 0 && iMin != 0 && iMic != 0)
293 break; //On s'enfou du reste
294 }
295
296 cd_debug ("Gnome Version %d.%d.%d", iMaj, iMin, iMic);
297
298 *iMajor = iMaj;
299 *iMinor = iMin;
300 *iMicro = iMic;
301
302 g_free (cContent);
303 g_strfreev (cLineList);
304 }*/
305
cairo_dock_pop_up_about_applet(G_GNUC_UNUSED GtkMenuItem * menu_item,GldiModuleInstance * pModuleInstance)306 void cairo_dock_pop_up_about_applet (G_GNUC_UNUSED GtkMenuItem *menu_item, GldiModuleInstance *pModuleInstance)
307 {
308 gldi_module_instance_popup_description (pModuleInstance);
309 }
310
311
cairo_dock_open_module_config_on_demand(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,GldiModuleInstance * pModuleInstance,G_GNUC_UNUSED CairoDialog * pDialog)312 void cairo_dock_open_module_config_on_demand (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, GldiModuleInstance *pModuleInstance, G_GNUC_UNUSED CairoDialog *pDialog)
313 {
314 if (iClickedButton == 0 || iClickedButton == -1) // bouton OK ou touche Entree.
315 {
316 cairo_dock_show_module_instance_gui (pModuleInstance, -1);
317 }
318 }
319
320
cairo_dock_insert_icons_in_applet(GldiModuleInstance * pInstance,GList * pIconsList,const gchar * cDockRenderer,const gchar * cDeskletRenderer,gpointer pDeskletRendererData)321 void cairo_dock_insert_icons_in_applet (GldiModuleInstance *pInstance, GList *pIconsList, const gchar *cDockRenderer, const gchar *cDeskletRenderer, gpointer pDeskletRendererData)
322 {
323 Icon *pIcon = pInstance->pIcon;
324 g_return_if_fail (pIcon != NULL);
325
326 GldiContainer *pContainer = pInstance->pContainer;
327 g_return_if_fail (pContainer != NULL);
328
329 if (pInstance->pDock)
330 {
331 if (pIcon->pSubDock == NULL)
332 {
333 if (pIcon->cName == NULL)
334 gldi_icon_set_name (pIcon, pInstance->pModule->pVisitCard->cModuleName);
335 if (cairo_dock_check_unique_subdock_name (pIcon))
336 gldi_icon_set_name (pIcon, pIcon->cName);
337 pIcon->pSubDock = gldi_subdock_new (pIcon->cName, cDockRenderer, pInstance->pDock, pIconsList);
338 if (pIcon->pSubDock)
339 pIcon->pSubDock->bPreventDraggingIcons = TRUE; // par defaut pour toutes les applets on empeche de pouvoir deplacer/supprimer les icones a la souris.
340 }
341 else
342 {
343 Icon *pOneIcon;
344 GList *ic;
345 for (ic = pIconsList; ic != NULL; ic = ic->next)
346 {
347 pOneIcon = ic->data;
348 gldi_icon_insert_in_container (pOneIcon, CAIRO_CONTAINER(pIcon->pSubDock), ! CAIRO_DOCK_ANIMATE_ICON);
349 }
350 g_list_free (pIconsList);
351
352 cairo_dock_set_renderer (pIcon->pSubDock, cDockRenderer);
353 cairo_dock_update_dock_size (pIcon->pSubDock);
354 }
355
356 if (pIcon->iSubdockViewType != 0) // trigger the redraw after the icons are loaded.
357 cairo_dock_trigger_redraw_subdock_content_on_icon (pIcon);
358 }
359 else if (pInstance->pDesklet)
360 {
361 Icon *pOneIcon;
362 GList *ic;
363 for (ic = pIconsList; ic != NULL; ic = ic->next)
364 {
365 pOneIcon = ic->data;
366 cairo_dock_set_icon_container (pOneIcon, pInstance->pDesklet);
367 }
368 pInstance->pDesklet->icons = g_list_concat (pInstance->pDesklet->icons, pIconsList); /// + sort icons and insert automatic separators...
369 cairo_dock_set_desklet_renderer_by_name (pInstance->pDesklet, cDeskletRenderer, (CairoDeskletRendererConfigPtr) pDeskletRendererData);
370 cairo_dock_redraw_container (pInstance->pContainer);
371 }
372 }
373
374
cairo_dock_insert_icon_in_applet(GldiModuleInstance * pInstance,Icon * pOneIcon)375 void cairo_dock_insert_icon_in_applet (GldiModuleInstance *pInstance, Icon *pOneIcon)
376 {
377 // get the container (create it if necessary)
378 GldiContainer *pContainer = NULL;
379 if (pInstance->pDock)
380 {
381 Icon *pIcon = pInstance->pIcon;
382 if (pIcon->pSubDock == NULL)
383 {
384 if (pIcon->cName == NULL)
385 gldi_icon_set_name (pIcon, pInstance->pModule->pVisitCard->cModuleName);
386 if (cairo_dock_check_unique_subdock_name (pIcon))
387 gldi_icon_set_name (pIcon, pIcon->cName);
388 pIcon->pSubDock = gldi_subdock_new (pIcon->cName, NULL, pInstance->pDock, NULL);
389 if (pIcon->pSubDock)
390 pIcon->pSubDock->bPreventDraggingIcons = TRUE; // par defaut pour toutes les applets on empeche de pouvoir deplacer/supprimer les icones a la souris.
391 }
392 pContainer = CAIRO_CONTAINER (pIcon->pSubDock);
393 }
394 else if (pInstance->pDesklet)
395 {
396 pContainer = CAIRO_CONTAINER (pInstance->pDesklet);
397 }
398 g_return_if_fail (pContainer != NULL);
399
400 // insert the icon inside
401 gldi_icon_insert_in_container (pOneIcon, pContainer, ! CAIRO_DOCK_ANIMATE_ICON);
402 }
403
404
cairo_dock_remove_all_icons_from_applet(GldiModuleInstance * pInstance)405 void cairo_dock_remove_all_icons_from_applet (GldiModuleInstance *pInstance)
406 {
407 Icon *pIcon = pInstance->pIcon;
408 g_return_if_fail (pIcon != NULL);
409
410 GldiContainer *pContainer = pInstance->pContainer;
411 g_return_if_fail (pContainer != NULL);
412
413 cd_debug ("%s (%s)", __func__, pInstance->pModule->pVisitCard->cModuleName);
414 if (pInstance->pDesklet && pInstance->pDesklet->icons != NULL)
415 {
416 cd_debug (" destroy desklet icons");
417 GList *icons = pInstance->pDesklet->icons;
418 pInstance->pDesklet->icons = NULL;
419 GList *ic;
420 Icon *icon;
421 for (ic = icons; ic != NULL; ic = ic->next)
422 {
423 icon = ic->data;
424 cairo_dock_set_icon_container (icon, NULL);
425 gldi_object_unref (GLDI_OBJECT(icon));
426 }
427 g_list_free (icons);
428 cairo_dock_redraw_container (pInstance->pContainer);
429 }
430 if (pIcon->pSubDock != NULL)
431 {
432 if (pInstance->pDock) // optimisation : on ne detruit pas le sous-dock.
433 {
434 cd_debug (" destroy sub-dock icons");
435 GList *icons = pIcon->pSubDock->icons;
436 pIcon->pSubDock->icons = NULL;
437 GList *ic;
438 Icon *icon;
439 for (ic = icons; ic != NULL; ic = ic->next)
440 {
441 icon = ic->data;
442 cairo_dock_set_icon_container (icon, NULL);
443 gldi_object_unref (GLDI_OBJECT(icon));
444 }
445 g_list_free (icons);
446 }
447 else // precaution pas chere
448 {
449 cd_debug (" destroy sub-dock");
450 gldi_object_unref (GLDI_OBJECT(pIcon->pSubDock));
451 pIcon->pSubDock = NULL;
452 }
453 }
454 }
455
456
cairo_dock_resize_applet(GldiModuleInstance * pInstance,int w,int h)457 void cairo_dock_resize_applet (GldiModuleInstance *pInstance, int w, int h)
458 {
459 Icon *pIcon = pInstance->pIcon;
460 g_return_if_fail (pIcon != NULL);
461
462 GldiContainer *pContainer = pInstance->pContainer;
463 g_return_if_fail (pContainer != NULL);
464
465 if (pInstance->pDock)
466 {
467 cairo_dock_icon_set_requested_size (pIcon, w, h);
468 cairo_dock_resize_icon_in_dock (pIcon, pInstance->pDock);
469 }
470 else // in desklet mode, just resize the desklet, it will trigger the reload of the applet when the 'configure' event is received.
471 {
472 gtk_window_resize (GTK_WINDOW (pContainer->pWidget),
473 w,
474 h); /// TODO: actually, the renderer should handle this, because except with the 'Simple' view, we can't know the actual size of the icon.
475 }
476 }
477
478