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 #define __USE_POSIX 1
24 #include <time.h>
25 #include <glib.h>
26 #include <glib/gi18n.h>
27 #include <cairo.h>
28 #include <gtk/gtk.h>
29 #include <glib/gstdio.h> // g_mkdir/g_remove
30
31 #include "config.h"
32 #include "gldi-icon-names.h"
33 #include "cairo-dock-animations.h" // cairo_dock_trigger_icon_removal_from_dock
34 #include "cairo-dock-icon-facility.h"
35 #include "cairo-dock-applications-manager.h"
36 #include "cairo-dock-stack-icon-manager.h"
37 #include "cairo-dock-separator-manager.h"
38 #include "cairo-dock-applet-manager.h"
39 #include "cairo-dock-class-icon-manager.h"
40 #include "cairo-dock-launcher-manager.h"
41 #include "cairo-dock-module-manager.h"
42 #include "cairo-dock-module-instance-manager.h"
43 #include "cairo-dock-dock-factory.h"
44 #include "cairo-dock-dock-facility.h"
45 #include "cairo-dock-themes-manager.h" // cairo_dock_update_conf_file
46 #include "cairo-dock-file-manager.h" // cairo_dock_copy_file
47 #include "cairo-dock-log.h"
48 #include "cairo-dock-utils.h" // cairo_dock_launch_command_sync
49 #include "cairo-dock-desklet-manager.h"
50 #include "cairo-dock-dock-manager.h"
51 #include "cairo-dock-class-manager.h"
52 #include "cairo-dock-container.h"
53 #include "cairo-dock-dialog-factory.h" // gldi_dialog_show_*
54 #include "cairo-dock-desktop-manager.h"
55 #include "cairo-dock-windows-manager.h"
56 #include "cairo-dock-user-interaction.h" // set_custom_icon_on_appli
57 #include "cairo-dock-gui-backend.h"
58 #include "cairo-dock-gui-commons.h"
59 #include "cairo-dock-applet-facility.h" // cairo_dock_pop_up_about_applet
60 #include "cairo-dock-menu.h"
61 #include "cairo-dock-user-menu.h"
62
63 #define CAIRO_DOCK_CONF_PANEL_WIDTH 1000
64 #define CAIRO_DOCK_CONF_PANEL_HEIGHT 600
65 #define CAIRO_DOCK_ABOUT_WIDTH 400
66 #define CAIRO_DOCK_ABOUT_HEIGHT 500
67 #define CAIRO_DOCK_FILE_HOST_URL "https://launchpad.net/cairo-dock" // https://developer.berlios.de/project/showfiles.php?group_id=8724
68 #define CAIRO_DOCK_SITE_URL "http://glx-dock.org" // http://cairo-dock.vef.fr
69 #define CAIRO_DOCK_FORUM_URL "http://forum.glx-dock.org" // http://cairo-dock.vef.fr/bg_forumlist.php
70 #define CAIRO_DOCK_PAYPAL_URL "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=UWQ3VVRB2ZTZS&lc=GB&item_name=Support%20Cairo%2dDock¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted"
71 #define CAIRO_DOCK_FLATTR_URL "http://flattr.com/thing/370779/Support-Cairo-Dock-development"
72
73 extern CairoDock *g_pMainDock;
74 extern GldiDesktopGeometry g_desktopGeometry;
75
76 extern gchar *g_cConfFile;
77 extern gchar *g_cCurrentLaunchersPath;
78 extern gchar *g_cCurrentThemePath;
79 extern gchar *g_cCurrentIconsPath;
80
81 extern gboolean g_bLocked;
82 extern gboolean g_bForceCairo;
83 extern gboolean g_bEasterEggs;
84
85 #define cairo_dock_icons_are_locked(...) (myDocksParam.bLockIcons || myDocksParam.bLockAll || g_bLocked)
86 #define cairo_dock_is_locked(...) (myDocksParam.bLockAll || g_bLocked)
87
88 #define _add_entry_in_menu(cLabel, gtkStock, pCallBack, pSubMenu) cairo_dock_add_in_menu_with_stock_and_data (cLabel, gtkStock, G_CALLBACK (pCallBack), pSubMenu, data)
89
90
91 //////////////////////////////////////////////
92 /////////// CAIRO-DOCK SUB-MENU //////////////
93 //////////////////////////////////////////////
94
_cairo_dock_edit_and_reload_conf(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)95 static void _cairo_dock_edit_and_reload_conf (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
96 {
97 cairo_dock_show_main_gui ();
98 }
99
_cairo_dock_configure_root_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,CairoDock * pDock)100 static void _cairo_dock_configure_root_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, CairoDock *pDock)
101 {
102 g_return_if_fail (pDock->iRefCount == 0 && ! pDock->bIsMainDock);
103
104 cairo_dock_show_items_gui (NULL, CAIRO_CONTAINER (pDock), NULL, 0);
105 }
_on_answer_delete_dock(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,CairoDock * pDock,G_GNUC_UNUSED CairoDialog * pDialog)106 static void _on_answer_delete_dock (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, CairoDock *pDock, G_GNUC_UNUSED CairoDialog *pDialog)
107 {
108 if (iClickedButton == 0 || iClickedButton == -1) // ok button or Enter.
109 {
110 gldi_object_delete (GLDI_OBJECT(pDock));
111 }
112 }
_cairo_dock_delete_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,CairoDock * pDock)113 static void _cairo_dock_delete_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, CairoDock *pDock)
114 {
115 g_return_if_fail (pDock->iRefCount == 0 && ! pDock->bIsMainDock);
116
117 Icon *pIcon = cairo_dock_get_pointed_icon (pDock->icons);
118
119 gldi_dialog_show_with_question (_("Delete this dock?"),
120 pIcon, CAIRO_CONTAINER (pDock),
121 CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
122 (CairoDockActionOnAnswerFunc)_on_answer_delete_dock, pDock, (GFreeFunc)NULL);
123 }
_cairo_dock_initiate_theme_management(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)124 static void _cairo_dock_initiate_theme_management (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
125 {
126 cairo_dock_show_themes ();
127 }
128
_cairo_dock_add_about_page(GtkWidget * pNoteBook,const gchar * cPageLabel,const gchar * cAboutText)129 static void _cairo_dock_add_about_page (GtkWidget *pNoteBook, const gchar *cPageLabel, const gchar *cAboutText)
130 {
131 GtkWidget *pVBox, *pScrolledWindow;
132 GtkWidget *pPageLabel, *pAboutLabel;
133
134 pPageLabel = gtk_label_new (cPageLabel);
135 pVBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
136 pScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
137 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
138 #if GTK_CHECK_VERSION (3, 8, 0)
139 gtk_container_add (GTK_CONTAINER (pScrolledWindow), pVBox);
140 #else
141 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pScrolledWindow), pVBox);
142 #endif
143 gtk_notebook_append_page (GTK_NOTEBOOK (pNoteBook), pScrolledWindow, pPageLabel);
144
145 pAboutLabel = gtk_label_new (NULL);
146 gtk_label_set_use_markup (GTK_LABEL (pAboutLabel), TRUE);
147 gtk_misc_set_alignment (GTK_MISC (pAboutLabel), 0.0, 0.0);
148 gtk_misc_set_padding (GTK_MISC (pAboutLabel), 30, 0);
149 gtk_box_pack_start (GTK_BOX (pVBox),
150 pAboutLabel,
151 FALSE,
152 FALSE,
153 15);
154 gtk_label_set_markup (GTK_LABEL (pAboutLabel), cAboutText);
155 }
_cairo_dock_lock_icons(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)156 static void _cairo_dock_lock_icons (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
157 {
158 myDocksParam.bLockIcons = ! myDocksParam.bLockIcons;
159 cairo_dock_update_conf_file (g_cConfFile,
160 G_TYPE_BOOLEAN, "Accessibility", "lock icons", myDocksParam.bLockIcons,
161 G_TYPE_INVALID);
162 }
163
164 /* Not used
165 static void _cairo_dock_lock_all (GtkMenuItem *pMenuItem, gpointer data)
166 {
167 myDocksParam.bLockAll = ! myDocksParam.bLockAll;
168 cairo_dock_update_conf_file (g_cConfFile,
169 G_TYPE_BOOLEAN, "Accessibility", "lock all", myDocksParam.bLockAll,
170 G_TYPE_INVALID);
171 }
172 */
_cairo_dock_about(G_GNUC_UNUSED GtkMenuItem * pMenuItem,GldiContainer * pContainer)173 static void _cairo_dock_about (G_GNUC_UNUSED GtkMenuItem *pMenuItem, GldiContainer *pContainer)
174 {
175 // build dialog
176 GtkWidget *pDialog = gtk_dialog_new_with_buttons (_("About Cairo-Dock"),
177 GTK_WINDOW (pContainer->pWidget),
178 GTK_DIALOG_DESTROY_WITH_PARENT,
179 GLDI_ICON_NAME_CLOSE,
180 GTK_RESPONSE_CLOSE,
181 NULL);
182
183 // the dialog box is destroyed when the user responds
184 g_signal_connect_swapped (pDialog,
185 "response",
186 G_CALLBACK (gtk_widget_destroy),
187 pDialog);
188
189 GtkWidget *pContentBox = gtk_dialog_get_content_area (GTK_DIALOG(pDialog));
190
191 // logo + links
192 GtkWidget *pHBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
193 gtk_box_pack_start (GTK_BOX (pContentBox), pHBox, FALSE, FALSE, 0);
194
195 const gchar *cImagePath = CAIRO_DOCK_SHARE_DATA_DIR"/images/"CAIRO_DOCK_LOGO;
196 GtkWidget *pImage = gtk_image_new_from_file (cImagePath);
197 gtk_box_pack_start (GTK_BOX (pHBox), pImage, FALSE, FALSE, 0);
198
199 GtkWidget *pVBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
200 gtk_box_pack_start (GTK_BOX (pHBox), pVBox, FALSE, FALSE, 0);
201
202 GtkWidget *pLink = gtk_link_button_new_with_label (CAIRO_DOCK_SITE_URL, "Cairo-Dock (2007-2014)\n version "CAIRO_DOCK_VERSION);
203 gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
204
205 //~ pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FORUM_URL, _("Community site"));
206 //~ gtk_widget_set_tooltip_text (pLink, _("Problems? Suggestions? Just want to talk to us? Come on over!"));
207 //~ gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
208
209 pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FILE_HOST_URL, _("Development site"));
210 gtk_widget_set_tooltip_text (pLink, _("Find the latest version of Cairo-Dock here !"));
211 gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
212
213 gchar *cLink = cairo_dock_get_third_party_applets_link ();
214 pLink = gtk_link_button_new_with_label (cLink, _("Get more applets!"));
215 g_free (cLink);
216 gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
217
218 gchar *cLabel = g_strdup_printf ("%s (Flattr)", _("Donate"));
219 pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FLATTR_URL, cLabel);
220 g_free (cLabel);
221 gtk_widget_set_tooltip_text (pLink, _("Support the people who spend countless hours to bring you the best dock ever."));
222 gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
223
224 cLabel = g_strdup_printf ("%s (Paypal)", _("Donate"));
225 pLink = gtk_link_button_new_with_label (CAIRO_DOCK_PAYPAL_URL, cLabel);
226 g_free (cLabel);
227 gtk_widget_set_tooltip_text (pLink, _("Support the people who spend countless hours to bring you the best dock ever."));
228 gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
229
230
231 // notebook
232 GtkWidget *pNoteBook = gtk_notebook_new ();
233 gtk_notebook_set_scrollable (GTK_NOTEBOOK (pNoteBook), TRUE);
234 gtk_notebook_popup_enable (GTK_NOTEBOOK (pNoteBook));
235 gtk_box_pack_start (GTK_BOX (pContentBox), pNoteBook, TRUE, TRUE, 0);
236
237 // About
238 /* gchar *text = g_strdup_printf ("\n\n<b>%s</b>\n\n\n"
239 "<a href=\"http://glx-dock.org\">http://glx-dock.org</a>",
240 _("<b>Cairo-Dock is a pretty, light and convenient interface\n"
241 " to your desktop, able to replace advantageously your system panel!</b>"));
242 _cairo_dock_add_about_page (pNoteBook,
243 _("About"),
244 text);*/
245 // Development
246 gchar *text = g_strdup_printf ("%s\n\n"
247 "<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
248 " Fabounet (Fabrice Rey)\n"
249 "\t<span size=\"smaller\">%s</span>\n\n"
250 " Matttbe (Matthieu Baerts)\n"
251 "\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
252 " Eduardo Mucelli\n"
253 " Jesuisbenjamin\n"
254 " SQP\n",
255 _("Here is a list of the current developers and contributors"),
256 _("Developers"),
257 _("Main developer and project leader"),
258 _("Contributors / Hackers"));
259 _cairo_dock_add_about_page (pNoteBook,
260 _("Development"),
261 text);
262 // Support
263 text = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
264 " Matttbe\n"
265 " Mav\n"
266 " Necropotame\n"
267 "\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
268 " BobH\n"
269 " Franksuse64\n"
270 " Lylambda\n"
271 " Ppmt\n"
272 " Taiebot65\n"
273 "\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
274 "%s",
275 _("Website"),
276 _("Beta-testing / Suggestions / Forum animation"),
277 _("Translators for this language"),
278 _("translator-credits"));
279 _cairo_dock_add_about_page (pNoteBook,
280 _("Support"),
281 text);
282 // Thanks
283 text = g_strdup_printf ("%s\n"
284 "<a href=\"http://glx-dock.org/ww_page.php?p=How to help us\">%s</a>: %s\n\n"
285 "\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
286 " Augur\n"
287 " ChAnGFu\n"
288 " Ctaf\n"
289 " Mav\n"
290 " Necropotame\n"
291 " Nochka85\n"
292 " Paradoxxx_Zero\n"
293 " Rom1\n"
294 " Tofe\n"
295 " Mac Slow (original idea)\n"
296 "\t<span size=\"smaller\">%s</span>\n"
297 "\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
298 "\t<a href=\"http://glx-dock.org/userlist_messages.php\">%s</a>\n"
299 "\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
300 " Benoit2600\n"
301 " Coz\n"
302 " Fabounet\n"
303 " Lord Northam\n"
304 " Lylambda\n"
305 " MastroPino\n"
306 " Matttbe\n"
307 " Nochka85\n"
308 " Paradoxxx_Zero\n"
309 " Taiebot65\n",
310 _("Thanks to all people that help us to improve the Cairo-Dock project.\n"
311 "Thanks to all current, former and future contributors."),
312 _("How to help us?"),
313 _("Don't hesitate to join the project, we need you ;)"),
314 _("Former contributors"),
315 _("For a complete list, please have a look to BZR logs"),
316 _("Users of our forum"),
317 _("List of our forum's members"),
318 _("Artwork"));
319 _cairo_dock_add_about_page (pNoteBook,
320 _("Thanks"),
321 text);
322 g_free (text);
323
324 gtk_window_resize (GTK_WINDOW (pDialog),
325 MIN (CAIRO_DOCK_ABOUT_WIDTH, gldi_desktop_get_width()),
326 MIN (CAIRO_DOCK_ABOUT_HEIGHT, gldi_desktop_get_height() - (g_pMainDock && g_pMainDock->container.bIsHorizontal ? g_pMainDock->iMaxDockHeight : 0)));
327
328 gtk_widget_show_all (pDialog);
329
330 gtk_window_set_keep_above (GTK_WINDOW (pDialog), TRUE);
331 //don't use gtk_dialog_run(), as we don't want to block the dock
332 }
333
_launch_url(const gchar * cURL)334 static void _launch_url (const gchar *cURL)
335 {
336 if (! cairo_dock_fm_launch_uri (cURL))
337 {
338 gchar *cCommand = g_strdup_printf ("\
339 which xdg-open > /dev/null && xdg-open %s || \
340 which firefox > /dev/null && firefox %s || \
341 which konqueror > /dev/null && konqueror %s || \
342 which iceweasel > /dev/null && konqueror %s || \
343 which opera > /dev/null && opera %s ",
344 cURL,
345 cURL,
346 cURL,
347 cURL,
348 cURL); // pas super beau mais efficace ^_^
349 int r = system (cCommand);
350 if (r < 0)
351 cd_warning ("Not able to launch this command: %s", cCommand);
352 g_free (cCommand);
353 }
354 }
_cairo_dock_show_third_party_applets(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)355 static void _cairo_dock_show_third_party_applets (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
356 {
357 gchar *cLink = cairo_dock_get_third_party_applets_link ();
358 _launch_url (cLink);
359 g_free (cLink);
360 }
361
_cairo_dock_present_help(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)362 static void _cairo_dock_present_help (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
363 {
364 int iMode = cairo_dock_gui_backend_get_mode ();
365 if (iMode == 0)
366 cairo_dock_load_user_gui_backend (1); // load the advanced mode (it seems it's currently not possible to open the Help with the Simple mode)
367 cairo_dock_show_module_gui ("Help");
368 if (iMode == 0)
369 cairo_dock_load_user_gui_backend (0);
370 }
371
_cairo_dock_quick_hide(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED CairoDock * pDock)372 static void _cairo_dock_quick_hide (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED CairoDock *pDock)
373 {
374 //g_print ("%s ()\n", __func__);
375 ///pDock->bHasModalWindow = FALSE;
376 cairo_dock_quick_hide_all_docks ();
377 }
378
_cairo_dock_add_autostart(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)379 static void _cairo_dock_add_autostart (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
380 {
381 gchar *cCairoAutoStartDirPath = g_strdup_printf ("%s/.config/autostart", g_getenv ("HOME"));
382 if (! g_file_test (cCairoAutoStartDirPath, G_FILE_TEST_IS_DIR))
383 {
384 if (g_mkdir (cCairoAutoStartDirPath, 7*8*8+5*8+5) != 0)
385 {
386 cd_warning ("couldn't create directory %s", cCairoAutoStartDirPath);
387 g_free (cCairoAutoStartDirPath);
388 return ;
389 }
390 }
391 cairo_dock_copy_file ("/usr/local/share/applications/cairo-dock.desktop", cCairoAutoStartDirPath);
392 g_free (cCairoAutoStartDirPath);
393 }
394
_on_answer_quit(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,G_GNUC_UNUSED gpointer data,G_GNUC_UNUSED CairoDialog * pDialog)395 static void _on_answer_quit (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, G_GNUC_UNUSED gpointer data, G_GNUC_UNUSED CairoDialog *pDialog)
396 {
397 if (iClickedButton == 0 || iClickedButton == -1) // ok button or Enter.
398 {
399 gtk_main_quit ();
400 }
401 }
_cairo_dock_quit(G_GNUC_UNUSED GtkMenuItem * pMenuItem,GldiContainer * pContainer)402 static void _cairo_dock_quit (G_GNUC_UNUSED GtkMenuItem *pMenuItem, GldiContainer *pContainer)
403 {
404 Icon *pIcon = NULL;
405 if (CAIRO_DOCK_IS_DOCK (pContainer))
406 pIcon = cairo_dock_get_pointed_icon (CAIRO_DOCK (pContainer)->icons);
407 else if (CAIRO_DOCK_IS_DESKLET (pContainer))
408 pIcon = CAIRO_DESKLET (pContainer)->pIcon;
409
410 gldi_dialog_show_with_question (_("Quit Cairo-Dock?"),
411 pIcon, pContainer,
412 CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
413 (CairoDockActionOnAnswerFunc) _on_answer_quit, NULL, (GFreeFunc)NULL);
414 }
415
416
417 ////////////////////////////////////////
418 /////////// ITEM SUB-MENU //////////////
419 ////////////////////////////////////////
420
_add_item_sub_menu(Icon * icon,GtkWidget * pMenu)421 GtkWidget *_add_item_sub_menu (Icon *icon, GtkWidget *pMenu)
422 {
423 const gchar *cName = NULL;
424 if (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (icon) || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (icon))
425 {
426 cName = (icon->cInitialName ? icon->cInitialName : icon->cName);
427 }
428 else if (CAIRO_DOCK_ICON_TYPE_IS_APPLI (icon) || CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (icon))
429 {
430 cName = cairo_dock_get_class_name (icon->cClass); // better than the current window title.
431 if (cName == NULL)
432 cName = icon->cClass;
433 }
434 else if (CAIRO_DOCK_IS_APPLET (icon))
435 {
436 cName = icon->pModuleInstance->pModule->pVisitCard->cTitle;
437 }
438 else if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
439 {
440 cName = _("Separator");
441 }
442 else
443 cName = icon->cName;
444
445 gchar *cIconFile = NULL;
446 if (CAIRO_DOCK_IS_APPLET (icon))
447 {
448 if (icon->cFileName != NULL) // if possible, use the actual icon
449 cIconFile = cairo_dock_search_icon_s_path (icon->cFileName, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
450 if (!cIconFile) // else, use the default applet's icon.
451 cIconFile = cairo_dock_search_icon_s_path (icon->pModuleInstance->pModule->pVisitCard->cIconFilePath, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
452 }
453 else if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
454 {
455 if (myIconsParam.cSeparatorImage)
456 cIconFile = cairo_dock_search_image_s_path (myIconsParam.cSeparatorImage);
457 }
458 else if (icon->cFileName != NULL)
459 {
460 cIconFile = cairo_dock_search_icon_s_path (icon->cFileName, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
461 }
462 if (cIconFile == NULL && icon->cClass != NULL)
463 {
464 const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
465 if (cClassIcon)
466 cIconFile = cairo_dock_search_icon_s_path (cClassIcon, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
467 }
468
469 GtkWidget *pItemSubMenu;
470 GdkPixbuf *pixbuf = NULL;
471
472 if (!cIconFile) // no icon file (for instance a class that has no icon defined in its desktop file, like gnome-setting-daemon) => use its buffer directly.
473 {
474 pixbuf = cairo_dock_icon_buffer_to_pixbuf (icon);
475 }
476
477 if (pixbuf)
478 {
479 GtkWidget *pMenuItem = NULL;
480 pItemSubMenu = gldi_menu_add_sub_menu_full (pMenu, cName, "", &pMenuItem);
481
482 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
483 gldi_menu_item_set_image (pMenuItem, image);
484 g_object_unref (pixbuf);
485 }
486 else
487 {
488 pItemSubMenu = cairo_dock_create_sub_menu (cName, pMenu, cIconFile);
489 }
490
491 g_free (cIconFile);
492 return pItemSubMenu;
493 }
494
495
_get_next_order(Icon * icon,CairoDock * pDock)496 static double _get_next_order (Icon *icon, CairoDock *pDock)
497 {
498 double fOrder;
499 if (icon != NULL)
500 {
501 if (pDock->container.iMouseX < icon->fDrawX + icon->fWidth * icon->fScale / 2) // a gauche.
502 {
503 Icon *prev_icon = cairo_dock_get_previous_icon (pDock->icons, icon);
504 fOrder = (prev_icon != NULL ? (icon->fOrder + prev_icon->fOrder) / 2 : icon->fOrder - 1);
505 }
506 else
507 {
508 Icon *next_icon = cairo_dock_get_next_icon (pDock->icons, icon);
509 fOrder = (next_icon != NULL ? (icon->fOrder + next_icon->fOrder) / 2 : icon->fOrder + 1);
510 }
511 }
512 else
513 fOrder = CAIRO_DOCK_LAST_ORDER;
514 return fOrder;
515 }
516
cairo_dock_add_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)517 static void cairo_dock_add_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
518 {
519 Icon *icon = data[0];
520 CairoDock *pDock = data[1];
521 double fOrder = _get_next_order (icon, pDock);
522 Icon *pNewIcon = gldi_launcher_add_new (NULL, pDock, fOrder);
523 if (pNewIcon == NULL)
524 cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
525 else
526 cairo_dock_show_items_gui (pNewIcon, NULL, NULL, -1); // open the config so that the user can complete its fields
527 }
528
cairo_dock_add_sub_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)529 static void cairo_dock_add_sub_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
530 {
531 Icon *icon = data[0];
532 CairoDock *pDock = data[1];
533 double fOrder = _get_next_order (icon, pDock);
534 Icon *pNewIcon = gldi_stack_icon_add_new (pDock, fOrder);
535 if (pNewIcon == NULL)
536 cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
537 }
538
_show_new_dock_msg(gchar * cDockName)539 static gboolean _show_new_dock_msg (gchar *cDockName)
540 {
541 CairoDock *pDock = gldi_dock_get (cDockName);
542 if (pDock)
543 gldi_dialog_show_temporary_with_default_icon (_("The new dock has been created.\nNow move some launchers or applets into it by right-clicking on the icon -> move to another dock"), NULL, CAIRO_CONTAINER (pDock), 10000);
544 g_free (cDockName);
545 return FALSE;
546 }
cairo_dock_add_main_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer * data)547 static void cairo_dock_add_main_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer *data)
548 {
549 gchar *cDockName = gldi_dock_add_conf_file ();
550 gldi_dock_new (cDockName);
551
552 cairo_dock_gui_trigger_reload_items (); // we could also connect to the signal "new-object" on docks...
553
554 g_timeout_add_seconds (1, (GSourceFunc)_show_new_dock_msg, cDockName); // delai, car sa fenetre n'est pas encore bien placee (0,0).
555 }
556
cairo_dock_add_separator(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)557 static void cairo_dock_add_separator (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
558 {
559 Icon *icon = data[0];
560 CairoDock *pDock = data[1];
561 double fOrder = _get_next_order (icon, pDock);
562 Icon *pNewIcon = gldi_separator_icon_add_new (pDock, fOrder);
563 if (pNewIcon == NULL)
564 cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
565 }
566
cairo_dock_add_applet(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer * data)567 static void cairo_dock_add_applet (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer *data)
568 {
569 cairo_dock_show_addons ();
570 }
571
_add_add_entry(GtkWidget * pMenu,gpointer * data)572 static void _add_add_entry (GtkWidget *pMenu, gpointer *data)
573 {
574 GtkWidget *pSubMenuAdd = cairo_dock_create_sub_menu (_("Add"), pMenu, GLDI_ICON_NAME_ADD);
575
576 _add_entry_in_menu (_("Sub-dock"), GLDI_ICON_NAME_ADD, cairo_dock_add_sub_dock, pSubMenuAdd);
577
578 _add_entry_in_menu (_("Main dock"), GLDI_ICON_NAME_ADD, cairo_dock_add_main_dock, pSubMenuAdd);
579
580 _add_entry_in_menu (_("Separator"), GLDI_ICON_NAME_ADD, cairo_dock_add_separator, pSubMenuAdd);
581
582 GtkWidget *pMenuItem = _add_entry_in_menu (_("Custom launcher"), GLDI_ICON_NAME_ADD, cairo_dock_add_launcher, pSubMenuAdd);
583 gtk_widget_set_tooltip_text (pMenuItem, _("Usually you would drag a launcher from the menu and drop it on the dock."));
584
585 _add_entry_in_menu (_("Applet"), GLDI_ICON_NAME_ADD, cairo_dock_add_applet, pSubMenuAdd);
586 }
587
588
589 ///////////////////////////////////////////
590 /////////// LAUNCHER ACTIONS //////////////
591 ///////////////////////////////////////////
592
_on_answer_remove_icon(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,Icon * icon,G_GNUC_UNUSED CairoDialog * pDialog)593 static void _on_answer_remove_icon (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, Icon *icon, G_GNUC_UNUSED CairoDialog *pDialog)
594 {
595 if (iClickedButton == 0 || iClickedButton == -1) // ok button or Enter.
596 {
597 if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (icon)
598 && icon->pSubDock != NULL) // remove the sub-dock's content from the theme or dispatch it in the main dock.
599 {
600 if (icon->pSubDock->icons != NULL) // on propose de repartir les icones de son sous-dock dans le dock principal.
601 {
602 int iClickedButton = gldi_dialog_show_and_wait (_("Do you want to re-dispatch the icons contained inside this container into the dock?\n(otherwise they will be destroyed)"),
603 icon, CAIRO_CONTAINER (icon->pContainer),
604 CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, NULL);
605 if (iClickedButton == 0 || iClickedButton == -1) // ok button or Enter.
606 {
607 CairoDock *pDock = CAIRO_DOCK (icon->pContainer);
608 cairo_dock_remove_icons_from_dock (icon->pSubDock, pDock);
609 }
610 }
611 }
612 cairo_dock_trigger_icon_removal_from_dock (icon);
613 }
614 }
_cairo_dock_remove_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)615 static void _cairo_dock_remove_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
616 {
617 Icon *icon = data[0];
618 CairoDock *pDock = data[1];
619
620 const gchar *cName = (icon->cInitialName != NULL ? icon->cInitialName : icon->cName);
621 if (cName == NULL)
622 {
623 if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
624 cName = _("separator");
625 else
626 cName = "no name";
627 }
628 gchar *question = g_strdup_printf (_("You're about to remove this icon (%s) from the dock. Are you sure?"), cName);
629 gldi_dialog_show_with_question (question,
630 icon, CAIRO_CONTAINER (pDock),
631 "same icon",
632 (CairoDockActionOnAnswerFunc) _on_answer_remove_icon, icon, (GFreeFunc)NULL);
633 g_free (question);
634 }
635
_cairo_dock_modify_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)636 static void _cairo_dock_modify_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
637 {
638 Icon *icon = data[0];
639 CairoDock *pDock = data[1];
640
641 if (icon->cDesktopFileName == NULL || strcmp (icon->cDesktopFileName, "none") == 0)
642 {
643 gldi_dialog_show_temporary_with_icon (_("Sorry, this icon doesn't have a configuration file."), icon, CAIRO_CONTAINER (pDock), 4000, "same icon");
644 return ;
645 }
646
647 cairo_dock_show_items_gui (icon, NULL, NULL, -1);
648 }
649
_cairo_dock_move_launcher_to_dock(GtkMenuItem * pMenuItem,const gchar * cDockName)650 static void _cairo_dock_move_launcher_to_dock (GtkMenuItem *pMenuItem, const gchar *cDockName)
651 {
652 Icon *pIcon = g_object_get_data (G_OBJECT (pMenuItem), "icon-item");
653
654 //\_________________________ on cree si besoin le fichier de conf d'un nouveau dock racine.
655 gchar *cValidDockName;
656 if (cDockName == NULL) // nouveau dock
657 {
658 cValidDockName = gldi_dock_add_conf_file ();
659 }
660 else
661 {
662 cValidDockName = g_strdup (cDockName);
663 }
664
665 //\_________________________ on met a jour le fichier de conf de l'icone.
666 gldi_theme_icon_write_container_name_in_conf_file (pIcon, cValidDockName);
667
668 //\_________________________ on recharge l'icone, ce qui va creer le dock.
669 if ((CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
670 || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
671 || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
672 && pIcon->cDesktopFileName != NULL) // user icon.
673 {
674 gldi_object_reload (GLDI_OBJECT(pIcon), TRUE); // TRUE <=> reload config.
675 }
676 else if (CAIRO_DOCK_IS_APPLET (pIcon))
677 {
678 gldi_object_reload (GLDI_OBJECT(pIcon->pModuleInstance), TRUE); // TRUE <=> reload config.
679 }
680
681 CairoDock *pNewDock = gldi_dock_get (cValidDockName);
682 if (pNewDock && pNewDock->iRefCount == 0 && pNewDock->icons && pNewDock->icons->next == NULL) // le dock vient d'etre cree avec cette icone.
683 gldi_dialog_show_general_message (_("The new dock has been created.\nYou can customize it by right-clicking on it -> cairo-dock -> configure this dock."), 8000); // on le place pas sur le nouveau dock, car sa fenetre n'est pas encore bien placee (0,0).
684 g_free (cValidDockName);
685 }
686
_cairo_dock_add_docks_sub_menu(GtkWidget * pMenu,Icon * pIcon)687 static void _cairo_dock_add_docks_sub_menu (GtkWidget *pMenu, Icon *pIcon)
688 {
689 GtkWidget *pSubMenuDocks = cairo_dock_create_sub_menu (_("Move to another dock"), pMenu, GLDI_ICON_NAME_JUMP_TO);
690 g_object_set_data (G_OBJECT (pSubMenuDocks), "icon-item", pIcon);
691 GtkWidget *pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("New main dock"), GLDI_ICON_NAME_NEW, G_CALLBACK (_cairo_dock_move_launcher_to_dock), pSubMenuDocks, NULL);
692 g_object_set_data (G_OBJECT (pMenuItem), "icon-item", pIcon);
693
694 GList *pDocks = cairo_dock_get_available_docks_for_icon (pIcon);
695 const gchar *cName;
696 gchar *cUserName;
697 CairoDock *pDock;
698 GList *d;
699 for (d = pDocks; d != NULL; d = d->next)
700 {
701 pDock = d->data;
702 cName = gldi_dock_get_name (pDock);
703 cUserName = gldi_dock_get_readable_name (pDock);
704
705 GtkWidget *pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (cUserName ? cUserName : cName, NULL, G_CALLBACK (_cairo_dock_move_launcher_to_dock), pSubMenuDocks, (gpointer)cName);
706 g_object_set_data (G_OBJECT (pMenuItem), "icon-item", pIcon);
707 g_free (cUserName);
708 }
709 g_list_free (pDocks);
710 }
711
_cairo_dock_make_launcher_from_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)712 static void _cairo_dock_make_launcher_from_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
713 {
714 Icon *icon = data[0];
715 CairoDock *pDock = data[1];
716 g_return_if_fail (icon->cClass != NULL);
717
718 // look for the .desktop file of the program
719 cd_debug ("%s (%s)", __func__, icon->cClass);
720 gchar *cDesktopFilePath = g_strdup (cairo_dock_get_class_desktop_file (icon->cClass));
721 if (cDesktopFilePath == NULL) // empty class
722 {
723 gchar *cCommand = g_strdup_printf ("find /usr/local/share/applications /usr/local/share/applications -iname \"*%s*.desktop\"", icon->cClass); // look for a desktop file from their file name
724 gchar *cResult = cairo_dock_launch_command_sync (cCommand);
725 if (cResult == NULL || *cResult == '\0') // no luck, search harder
726 {
727 g_free (cCommand);
728 cCommand = g_strdup_printf ("find /usr/local/share/applications /usr/local/share/applications -name \"*.desktop\" -exec grep -qi '%s' {} \\; -print", icon->cClass); // look for a desktop file from their content
729 cResult = cairo_dock_launch_command_sync (cCommand);
730 }
731 if (cResult != NULL && *cResult != '\0')
732 {
733 gchar *str = strchr (cResult, '\n'); // remove the trailing linefeed, and only take the first result
734 if (str)
735 *str = '\0';
736 cDesktopFilePath = cResult;
737 }
738 g_free (cCommand);
739 }
740
741 // make a new launcher from this desktop file
742 if (cDesktopFilePath != NULL)
743 {
744 cd_message ("found desktop file : %s", cDesktopFilePath);
745 // place it after the last launcher, since the user will probably want to move this new launcher amongst the already existing ones.
746 double fOrder = CAIRO_DOCK_LAST_ORDER;
747 Icon *pIcon;
748 GList *ic, *last_launcher_ic = NULL;
749 for (ic = g_pMainDock->icons; ic != NULL; ic = ic->next)
750 {
751 pIcon = ic->data;
752 if (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
753 || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon))
754 {
755 last_launcher_ic = ic;
756 }
757 }
758 if (last_launcher_ic != NULL)
759 {
760 ic = last_launcher_ic;
761 pIcon = ic->data;
762 Icon *next_icon = (ic->next ? ic->next->data : NULL);
763 if (next_icon != NULL && cairo_dock_get_icon_order (next_icon) == cairo_dock_get_icon_order (pIcon))
764 fOrder = (pIcon->fOrder + next_icon->fOrder) / 2;
765 else
766 fOrder = pIcon->fOrder + 1;
767 }
768 gldi_launcher_add_new (cDesktopFilePath, g_pMainDock, fOrder); // add in the main dock
769 }
770 else
771 {
772 gldi_dialog_show_temporary_with_default_icon (_("Sorry, couldn't find the corresponding description file.\nConsider dragging and dropping the launcher from the Applications Menu."), icon, CAIRO_CONTAINER (pDock), 8000);
773 }
774 g_free (cDesktopFilePath);
775 }
776
777 //////////////////////////////////////////////////////////////////
778 /////////// LES OPERATIONS SUR LES APPLETS ///////////////////////
779 //////////////////////////////////////////////////////////////////
780
_cairo_dock_initiate_config_module(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)781 static void _cairo_dock_initiate_config_module (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
782 {
783 cd_debug ("%s ()", __func__);
784 Icon *icon = data[0];
785 GldiContainer *pContainer= data[1];
786 if (CAIRO_DOCK_IS_DESKLET (pContainer))
787 icon = (CAIRO_DESKLET (pContainer))->pIcon; // l'icone cliquee du desklet n'est pas forcement celle qui contient le module.
788 g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
789
790 cairo_dock_show_items_gui (icon, NULL, NULL, -1);
791 }
792
_cairo_dock_detach_module(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)793 static void _cairo_dock_detach_module (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
794 {
795 Icon *icon = data[0];
796 GldiContainer *pContainer= data[1];
797 if (CAIRO_DOCK_IS_DESKLET (pContainer))
798 icon = (CAIRO_DESKLET (pContainer))->pIcon; // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
799 g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
800
801 gldi_module_instance_detach (icon->pModuleInstance);
802 }
803
_on_answer_remove_module_instance(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,Icon * icon,G_GNUC_UNUSED CairoDialog * pDialog)804 static void _on_answer_remove_module_instance (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, Icon *icon, G_GNUC_UNUSED CairoDialog *pDialog)
805 {
806 if (iClickedButton == 0 || iClickedButton == -1) // ok button or Enter.
807 {
808 gldi_object_delete (GLDI_OBJECT(icon->pModuleInstance));
809 }
810 }
_cairo_dock_remove_module_instance(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)811 static void _cairo_dock_remove_module_instance (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
812 {
813 Icon *icon = data[0];
814 GldiContainer *pContainer= data[1];
815 if (CAIRO_DOCK_IS_DESKLET (pContainer))
816 icon = (CAIRO_DESKLET (pContainer))->pIcon; // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
817 g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
818
819 gchar *question = g_strdup_printf (_("You're about to remove this applet (%s) from the dock. Are you sure?"), icon->pModuleInstance->pModule->pVisitCard->cTitle);
820 gldi_dialog_show_with_question (question,
821 icon, CAIRO_CONTAINER (pContainer),
822 "same icon",
823 (CairoDockActionOnAnswerFunc) _on_answer_remove_module_instance, icon, (GFreeFunc)NULL);
824 g_free (question);
825 }
826
_cairo_dock_add_module_instance(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)827 static void _cairo_dock_add_module_instance (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
828 {
829 Icon *icon = data[0];
830 GldiContainer *pContainer= data[1];
831 if (CAIRO_DOCK_IS_DESKLET (pContainer))
832 icon = (CAIRO_DESKLET (pContainer))->pIcon; // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
833 g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
834
835 gldi_module_add_instance (icon->pModuleInstance->pModule);
836 }
837
_cairo_dock_set_sensitive_quit_menu(G_GNUC_UNUSED GtkWidget * pMenuItem,GdkEventKey * pKey,GtkWidget * pQuitEntry)838 static void _cairo_dock_set_sensitive_quit_menu (G_GNUC_UNUSED GtkWidget *pMenuItem, GdkEventKey *pKey, GtkWidget *pQuitEntry)
839 {
840 // pMenuItem not used because we want to only modify one entry
841 if (pKey->type == GDK_KEY_PRESS &&
842 (pKey->keyval == GDK_KEY_Shift_L ||
843 pKey->keyval == GDK_KEY_Shift_R)) // pressed
844 gtk_widget_set_sensitive (pQuitEntry, TRUE); // unlocked
845 else if (pKey->state & GDK_SHIFT_MASK) // released
846 gtk_widget_set_sensitive (pQuitEntry, FALSE); // locked)
847 }
848
_cairo_dock_launch_new(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)849 static void _cairo_dock_launch_new (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
850 {
851 Icon *icon = data[0];
852 CairoDock *pDock = data[1];
853 if (icon->cCommand != NULL)
854 {
855 gldi_object_notify (CAIRO_CONTAINER (pDock), NOTIFICATION_CLICK_ICON, icon, pDock, GDK_SHIFT_MASK); // on emule un shift+clic gauche .
856 }
857 }
858
859
860 /////////////////////////////////////////
861 /// BUILD CONTAINER MENU NOTIFICATION ///
862 /////////////////////////////////////////
863
_show_image_preview(GtkFileChooser * pFileChooser,GtkImage * pPreviewImage)864 static void _show_image_preview (GtkFileChooser *pFileChooser, GtkImage *pPreviewImage)
865 {
866 gchar *cFileName = gtk_file_chooser_get_preview_filename (pFileChooser);
867 if (cFileName == NULL)
868 return ;
869 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cFileName, 64, 64, NULL);
870 g_free (cFileName);
871 if (pixbuf != NULL)
872 {
873 gtk_image_set_from_pixbuf (pPreviewImage, pixbuf);
874 g_object_unref (pixbuf);
875 gtk_file_chooser_set_preview_widget_active (pFileChooser, TRUE);
876 }
877 else
878 gtk_file_chooser_set_preview_widget_active (pFileChooser, FALSE);
879 }
_cairo_dock_set_custom_appli_icon(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)880 static void _cairo_dock_set_custom_appli_icon (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
881 {
882 Icon *icon = data[0];
883 CairoDock *pDock = data[1];
884 if (! CAIRO_DOCK_IS_APPLI (icon))
885 return;
886
887 GtkWidget* pFileChooserDialog = gtk_file_chooser_dialog_new (
888 _("Pick up an image"),
889 GTK_WINDOW (pDock->container.pWidget),
890 GTK_FILE_CHOOSER_ACTION_OPEN,
891 _("Ok"),
892 GTK_RESPONSE_OK,
893 _("Cancel"),
894 GTK_RESPONSE_CANCEL,
895 NULL);
896 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (pFileChooserDialog), "/usr/local/share/icons"); // we could also use 'xdg-user-dir PICTURES' or /usr/local/share/icons or ~/.icons, but actually we have no idea where the user will want to pick the image, so let's not try to be smart.
897 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (pFileChooserDialog), FALSE);
898
899 GtkWidget *pPreviewImage = gtk_image_new ();
900 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (pFileChooserDialog), pPreviewImage);
901 g_signal_connect (GTK_FILE_CHOOSER (pFileChooserDialog), "update-preview", G_CALLBACK (_show_image_preview), pPreviewImage);
902
903 // a filter
904 GtkFileFilter *pFilter = gtk_file_filter_new ();
905 gtk_file_filter_set_name (pFilter, _("Image"));
906 gtk_file_filter_add_pixbuf_formats (pFilter);
907 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (pFileChooserDialog), pFilter);
908
909 gtk_widget_show (pFileChooserDialog);
910 int answer = gtk_dialog_run (GTK_DIALOG (pFileChooserDialog));
911 if (answer == GTK_RESPONSE_OK)
912 {
913 if (myTaskbarParam.cOverwriteException != NULL && icon->cClass != NULL) // si cette classe etait definie pour ne pas ecraser l'icone X, on le change, sinon l'action utilisateur n'aura aucun impact, ce sera troublant.
914 {
915 gchar **pExceptions = g_strsplit (myTaskbarParam.cOverwriteException, ";", -1);
916
917 int i, j = -1;
918 for (i = 0; pExceptions[i] != NULL; i ++)
919 {
920 if (j == -1 && strcmp (pExceptions[i], icon->cClass) == 0)
921 {
922 g_free (pExceptions[i]);
923 pExceptions[i] = NULL;
924 j = i;
925 }
926 } // apres la boucle, i = nbre d'elements, j = l'element qui a ete enleve.
927 if (j != -1) // un element a ete enleve.
928 {
929 cd_warning ("The class '%s' was explicitely set up to use the X icon, we'll change this behavior automatically.", icon->cClass);
930 if (j < i - 1) // ce n'est pas le dernier
931 {
932 pExceptions[j] = pExceptions[i-1];
933 pExceptions[i-1] = NULL;
934 }
935
936 myTaskbarParam.cOverwriteException = g_strjoinv (";", pExceptions);
937 cairo_dock_set_overwrite_exceptions (myTaskbarParam.cOverwriteException);
938
939 cairo_dock_update_conf_file (g_cConfFile,
940 G_TYPE_STRING, "TaskBar", "overwrite exception", myTaskbarParam.cOverwriteException,
941 G_TYPE_INVALID);
942 }
943 g_strfreev (pExceptions);
944 }
945
946 gchar *cFilePath = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pFileChooserDialog));
947 cairo_dock_set_custom_icon_on_appli (cFilePath, icon, CAIRO_CONTAINER (pDock));
948 g_free (cFilePath);
949 }
950 gtk_widget_destroy (pFileChooserDialog);
951 }
_cairo_dock_remove_custom_appli_icon(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)952 static void _cairo_dock_remove_custom_appli_icon (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
953 {
954 Icon *icon = data[0];
955 CairoDock *pDock = data[1];
956 if (! CAIRO_DOCK_IS_APPLI (icon))
957 return;
958
959 const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
960 if (cClassIcon == NULL)
961 cClassIcon = icon->cClass;
962
963 gchar *cCustomIcon = g_strdup_printf ("%s/%s.png", g_cCurrentIconsPath, cClassIcon);
964 if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
965 {
966 g_free (cCustomIcon);
967 cCustomIcon = g_strdup_printf ("%s/%s.svg", g_cCurrentIconsPath, cClassIcon);
968 if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
969 {
970 g_free (cCustomIcon);
971 cCustomIcon = NULL;
972 }
973 }
974 if (cCustomIcon != NULL)
975 {
976 g_remove (cCustomIcon);
977 cairo_dock_reload_icon_image (icon, CAIRO_CONTAINER (pDock));
978 cairo_dock_redraw_icon (icon);
979 }
980 }
981
cairo_dock_notification_build_container_menu(G_GNUC_UNUSED gpointer * pUserData,Icon * icon,GldiContainer * pContainer,GtkWidget * menu,G_GNUC_UNUSED gboolean * bDiscardMenu)982 gboolean cairo_dock_notification_build_container_menu (G_GNUC_UNUSED gpointer *pUserData, Icon *icon, GldiContainer *pContainer, GtkWidget *menu, G_GNUC_UNUSED gboolean *bDiscardMenu)
983 {
984 static gpointer data[3];
985
986 if (CAIRO_DOCK_IS_DESKLET (pContainer) && icon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // not on the icons of a desklet, except the applet icon (on a desklet, it's easy to click out of any icon).
987 return GLDI_NOTIFICATION_LET_PASS;
988
989 if (CAIRO_DOCK_IS_DOCK (pContainer) && CAIRO_DOCK (pContainer)->iRefCount > 0) // not on the sub-docks, except user sub-docks.
990 {
991 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (CAIRO_DOCK (pContainer), NULL);
992 if (pPointingIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pPointingIcon))
993 return GLDI_NOTIFICATION_LET_PASS;
994 }
995
996 GtkWidget *pMenuItem;
997
998 //\_________________________ First item is the Cairo-Dock sub-menu.
999 GtkWidget *pSubMenu = cairo_dock_create_sub_menu ("Cairo-Dock", menu, CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON);
1000
1001 // theme settings
1002 if (! cairo_dock_is_locked ())
1003 {
1004 // global settings
1005 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Configure"),
1006 GLDI_ICON_NAME_PREFERENCES,
1007 G_CALLBACK (_cairo_dock_edit_and_reload_conf),
1008 pSubMenu,
1009 NULL);
1010 gtk_widget_set_tooltip_text (pMenuItem, _("Configure behaviour, appearance, and applets."));
1011
1012 // root dock settings
1013 if (CAIRO_DOCK_IS_DOCK (pContainer) && ! CAIRO_DOCK (pContainer)->bIsMainDock && CAIRO_DOCK (pContainer)->iRefCount == 0)
1014 {
1015 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Configure this dock"),
1016 GLDI_ICON_NAME_EXECUTE,
1017 G_CALLBACK (_cairo_dock_configure_root_dock),
1018 pSubMenu,
1019 CAIRO_DOCK (pContainer));
1020 gtk_widget_set_tooltip_text (pMenuItem, _("Customize the position, visibility and appearance of this main dock."));
1021
1022 cairo_dock_add_in_menu_with_stock_and_data (_("Delete this dock"),
1023 GLDI_ICON_NAME_DELETE,
1024 G_CALLBACK (_cairo_dock_delete_dock),
1025 pSubMenu,
1026 CAIRO_DOCK (pContainer));
1027 }
1028
1029 // themes
1030 if (cairo_dock_can_manage_themes ())
1031 {
1032 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Manage themes"),
1033 CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-appearance.svg",
1034 G_CALLBACK (_cairo_dock_initiate_theme_management),
1035 pSubMenu,
1036 NULL);
1037 gtk_widget_set_tooltip_text (pMenuItem, _("Choose from amongst many themes on the server or save your current theme."));
1038 }
1039
1040 // add new item
1041 if (CAIRO_DOCK_IS_DOCK (pContainer))
1042 {
1043 _add_add_entry (pSubMenu, data);
1044 }
1045
1046 gldi_menu_add_separator (pSubMenu);
1047
1048 // lock icons position
1049 pMenuItem = gtk_check_menu_item_new_with_label (_("Lock icons position"));
1050 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (pMenuItem), myDocksParam.bLockIcons);
1051 gtk_menu_shell_append (GTK_MENU_SHELL (pSubMenu), pMenuItem);
1052 g_signal_connect (G_OBJECT (pMenuItem), "toggled", G_CALLBACK (_cairo_dock_lock_icons), NULL);
1053 gtk_widget_set_tooltip_text (pMenuItem, _("This will (un)lock the position of the icons."));
1054 }
1055
1056 // quick-hide
1057 if (CAIRO_DOCK_IS_DOCK (pContainer) && ! CAIRO_DOCK (pContainer)->bAutoHide)
1058 {
1059 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Quick-Hide"),
1060 GLDI_ICON_NAME_GOTO_BOTTOM,
1061 G_CALLBACK (_cairo_dock_quick_hide),
1062 pSubMenu,
1063 CAIRO_DOCK (pContainer));
1064 gtk_widget_set_tooltip_text (pMenuItem, _("This will hide the dock until you hover over it with the mouse."));
1065 }
1066
1067 const gchar *cDesktopSession = g_getenv ("DESKTOP_SESSION");
1068 gboolean bIsCairoDockSession = cDesktopSession && g_str_has_prefix (cDesktopSession, "cairo-dock");
1069 if (! g_bLocked)
1070 {
1071 // auto-start
1072 gchar *cCairoAutoStartDirPath = g_strdup_printf ("%s/.config/autostart", g_getenv ("HOME"));
1073 gchar *cCairoAutoStartEntryPath = g_strdup_printf ("%s/cairo-dock.desktop", cCairoAutoStartDirPath);
1074 gchar *cCairoAutoStartEntryPath2 = g_strdup_printf ("%s/cairo-dock-cairo.desktop", cCairoAutoStartDirPath);
1075 if (! bIsCairoDockSession && ! g_file_test (cCairoAutoStartEntryPath, G_FILE_TEST_EXISTS) && ! g_file_test (cCairoAutoStartEntryPath2, G_FILE_TEST_EXISTS))
1076 {
1077 cairo_dock_add_in_menu_with_stock_and_data (_("Launch Cairo-Dock on startup"),
1078 GLDI_ICON_NAME_ADD,
1079 G_CALLBACK (_cairo_dock_add_autostart),
1080 pSubMenu,
1081 NULL);
1082 }
1083 g_free (cCairoAutoStartEntryPath);
1084 g_free (cCairoAutoStartEntryPath2);
1085 g_free (cCairoAutoStartDirPath);
1086
1087 // third-party applets (are here to give them more visibility).
1088 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Get more applets!"),
1089 GLDI_ICON_NAME_ADD,
1090 G_CALLBACK (_cairo_dock_show_third_party_applets),
1091 pSubMenu,
1092 NULL);
1093 gtk_widget_set_tooltip_text (pMenuItem, _("Third-party applets provide integration with many programs, like Pidgin"));
1094
1095 // Help (we don't present the help if locked, because it would open the configuration window).
1096 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Help"),
1097 GLDI_ICON_NAME_HELP,
1098 G_CALLBACK (_cairo_dock_present_help),
1099 pSubMenu,
1100 NULL);
1101 gtk_widget_set_tooltip_text (pMenuItem, _("There are no problems, only solutions (and a lot of useful hints!)"));
1102 }
1103
1104 // About
1105 cairo_dock_add_in_menu_with_stock_and_data (_("About"),
1106 GLDI_ICON_NAME_ABOUT,
1107 G_CALLBACK (_cairo_dock_about),
1108 pSubMenu,
1109 pContainer);
1110
1111 // quit
1112 if (! g_bLocked)
1113 {
1114 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Quit"),
1115 GLDI_ICON_NAME_QUIT,
1116 G_CALLBACK (_cairo_dock_quit),
1117 pSubMenu,
1118 pContainer);
1119 // if we're using a Cairo-Dock session and we quit the dock we have... nothing to relaunch it!
1120 if (bIsCairoDockSession)
1121 {
1122 gtk_widget_set_sensitive (pMenuItem, FALSE); // locked
1123 gtk_widget_set_tooltip_text (pMenuItem, _("You're using a Cairo-Dock Session!\nIt's not advised to quit the dock but you can press Shift to unlock this menu entry."));
1124 // signal to unlock the entry (signal monitored only in the submenu)
1125 g_signal_connect (pSubMenu, "key-press-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
1126 g_signal_connect (pSubMenu, "key-release-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
1127 }
1128 }
1129
1130 //\_________________________ Second item is the Icon sub-menu.
1131 Icon *pIcon = icon;
1132 if (pIcon == NULL && CAIRO_DOCK_IS_DESKLET (pContainer)) // on a desklet, the main applet icon may not be drawn; therefore we add the applet sub-menu if we clicked outside of an icon.
1133 {
1134 pIcon = CAIRO_DESKLET (pContainer)->pIcon;
1135 }
1136 data[0] = pIcon;
1137 data[1] = pContainer;
1138 data[2] = menu;
1139
1140 if (pIcon != NULL && ! CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (pIcon))
1141 {
1142 GtkWidget *pItemSubMenu = _add_item_sub_menu (pIcon, menu);
1143
1144 if (cairo_dock_is_locked ())
1145 {
1146 gboolean bSensitive = FALSE;
1147 if (CAIRO_DOCK_IS_APPLI (icon) && icon->cCommand != NULL)
1148 {
1149 _add_entry_in_menu (_("Launch a new (Shift+clic)"), GLDI_ICON_NAME_ADD, _cairo_dock_launch_new, pItemSubMenu);
1150 bSensitive = TRUE;
1151 }
1152 if (CAIRO_DOCK_IS_APPLET (pIcon))
1153 {
1154 cairo_dock_add_in_menu_with_stock_and_data (_("Applet's handbook"), GLDI_ICON_NAME_ABOUT, G_CALLBACK (cairo_dock_pop_up_about_applet), pItemSubMenu, pIcon->pModuleInstance);
1155 bSensitive = TRUE;
1156 }
1157 gtk_widget_set_sensitive (pItemSubMenu, bSensitive);
1158 }
1159 else
1160 {
1161 if (CAIRO_DOCK_IS_APPLI (icon) && icon->cCommand != NULL)
1162 _add_entry_in_menu (_("Launch a new (Shift+clic)"), GLDI_ICON_NAME_ADD, _cairo_dock_launch_new, pItemSubMenu);
1163
1164 if ((CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
1165 || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
1166 || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
1167 && icon->cDesktopFileName != NULL) // user icon
1168 {
1169 _add_entry_in_menu (_("Edit"), GLDI_ICON_NAME_EDIT, _cairo_dock_modify_launcher, pItemSubMenu);
1170
1171 pMenuItem = _add_entry_in_menu (_("Remove"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_launcher, pItemSubMenu);
1172 gtk_widget_set_tooltip_text (pMenuItem, _("You can remove a launcher by dragging it out of the dock with the mouse ."));
1173
1174 _cairo_dock_add_docks_sub_menu (pItemSubMenu, pIcon);
1175 }
1176 else if (CAIRO_DOCK_ICON_TYPE_IS_APPLI (pIcon)
1177 || CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (pIcon)) // appli with no launcher
1178 {
1179 if (! cairo_dock_class_is_inhibited (pIcon->cClass)) // if the class doesn't already have an inhibator somewhere.
1180 {
1181 _add_entry_in_menu (_("Make it a launcher"), GLDI_ICON_NAME_NEW, _cairo_dock_make_launcher_from_appli, pItemSubMenu);
1182
1183 if (!myDocksParam.bLockAll && CAIRO_DOCK_ICON_TYPE_IS_APPLI (icon))
1184 {
1185 if (myTaskbarParam.bOverWriteXIcons)
1186 {
1187 const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
1188 if (cClassIcon == NULL)
1189 cClassIcon = icon->cClass;
1190
1191 gchar *cCustomIcon = g_strdup_printf ("%s/%s.png", g_cCurrentIconsPath, cClassIcon);
1192 if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
1193 {
1194 g_free (cCustomIcon);
1195 cCustomIcon = g_strdup_printf ("%s/%s.svg", g_cCurrentIconsPath, cClassIcon);
1196 if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
1197 {
1198 g_free (cCustomIcon);
1199 cCustomIcon = NULL;
1200 }
1201 }
1202 if (cCustomIcon != NULL)
1203 {
1204 _add_entry_in_menu (_("Remove custom icon"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_custom_appli_icon, pItemSubMenu);
1205 }
1206 }
1207
1208 _add_entry_in_menu (_("Set a custom icon"), GLDI_ICON_NAME_SELECT_COLOR, _cairo_dock_set_custom_appli_icon, pItemSubMenu);
1209 }
1210 }
1211 }
1212 else if (CAIRO_DOCK_IS_APPLET (pIcon)) // applet (icon or desklet) (the sub-icons have been filtered before and won't have this menu).
1213 {
1214 _add_entry_in_menu (_("Edit"), GLDI_ICON_NAME_EDIT, _cairo_dock_initiate_config_module, pItemSubMenu);
1215
1216 if (CAIRO_DOCK_IS_DETACHABLE_APPLET (pIcon))
1217 {
1218 _add_entry_in_menu (CAIRO_DOCK_IS_DOCK (pContainer) ? _("Detach") : _("Return to the dock"), CAIRO_DOCK_IS_DOCK (pContainer) ? GLDI_ICON_NAME_GOTO_TOP : GLDI_ICON_NAME_GOTO_BOTTOM, _cairo_dock_detach_module, pItemSubMenu);
1219 }
1220
1221 _add_entry_in_menu (_("Remove"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_module_instance, pItemSubMenu);
1222
1223 if (pIcon->pModuleInstance->pModule->pVisitCard->bMultiInstance)
1224 {
1225 _add_entry_in_menu (_("Duplicate"), GLDI_ICON_NAME_ADD, _cairo_dock_add_module_instance, pItemSubMenu); // Launch another instance of this applet
1226 }
1227
1228 if (CAIRO_DOCK_IS_DOCK (pContainer) && cairo_dock_get_icon_container(pIcon) != NULL) // sinon bien sur ca n'est pas la peine de presenter l'option (Cairo-Penguin par exemple)
1229 {
1230 _cairo_dock_add_docks_sub_menu (pItemSubMenu, pIcon);
1231 }
1232
1233 gldi_menu_add_separator (pItemSubMenu);
1234
1235 cairo_dock_add_in_menu_with_stock_and_data (_("Applet's handbook"), GLDI_ICON_NAME_ABOUT, G_CALLBACK (cairo_dock_pop_up_about_applet), pItemSubMenu, pIcon->pModuleInstance);
1236 }
1237 }
1238 }
1239
1240 return GLDI_NOTIFICATION_LET_PASS;
1241 }
1242
1243
1244
1245 /////////////////////////////////////////////////////////////////
1246 /////////// LES OPERATIONS SUR LES APPLIS ///////////////////////
1247 /////////////////////////////////////////////////////////////////
1248
_cairo_dock_close_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1249 static void _cairo_dock_close_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1250 {
1251 Icon *icon = data[0];
1252 // CairoDock *pDock = data[1];
1253 if (CAIRO_DOCK_IS_APPLI (icon))
1254 gldi_window_close (icon->pAppli);
1255 }
_cairo_dock_kill_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1256 static void _cairo_dock_kill_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1257 {
1258 Icon *icon = data[0];
1259 // CairoDock *pDock = data[1];
1260 if (CAIRO_DOCK_IS_APPLI (icon))
1261 gldi_window_kill (icon->pAppli);
1262 }
_cairo_dock_minimize_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1263 static void _cairo_dock_minimize_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1264 {
1265 Icon *icon = data[0];
1266 // CairoDock *pDock = data[1];
1267 if (CAIRO_DOCK_IS_APPLI (icon))
1268 {
1269 gldi_window_minimize (icon->pAppli);
1270 }
1271 }
_cairo_dock_lower_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1272 static void _cairo_dock_lower_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1273 {
1274 Icon *icon = data[0];
1275 // CairoDock *pDock = data[1];
1276 if (CAIRO_DOCK_IS_APPLI (icon))
1277 {
1278 gldi_window_lower (icon->pAppli);
1279 }
1280 }
1281
_cairo_dock_show_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1282 static void _cairo_dock_show_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1283 {
1284 Icon *icon = data[0];
1285 // CairoDock *pDock = data[1];
1286 if (CAIRO_DOCK_IS_APPLI (icon))
1287 {
1288 gldi_window_show (icon->pAppli);
1289 }
1290 }
1291
_cairo_dock_maximize_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1292 static void _cairo_dock_maximize_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1293 {
1294 Icon *icon = data[0];
1295 // CairoDock *pDock = data[1];
1296 if (CAIRO_DOCK_IS_APPLI (icon))
1297 {
1298 gldi_window_maximize (icon->pAppli, ! icon->pAppli->bIsMaximized);
1299 }
1300 }
1301
_cairo_dock_set_appli_fullscreen(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1302 static void _cairo_dock_set_appli_fullscreen (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1303 {
1304 Icon *icon = data[0];
1305 // CairoDock *pDock = data[1];
1306 if (CAIRO_DOCK_IS_APPLI (icon))
1307 {
1308 gldi_window_set_fullscreen (icon->pAppli, ! icon->pAppli->bIsFullScreen);
1309 }
1310 }
1311
_cairo_dock_move_appli_to_current_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1312 static void _cairo_dock_move_appli_to_current_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1313 {
1314 Icon *icon = data[0];
1315 // CairoDock *pDock = data[1];
1316 if (CAIRO_DOCK_IS_APPLI (icon))
1317 {
1318 gldi_window_move_to_current_desktop (icon->pAppli);
1319 if (!icon->pAppli->bIsHidden)
1320 gldi_window_show (icon->pAppli);
1321 }
1322 }
1323
_cairo_dock_move_appli_to_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * user_data)1324 static void _cairo_dock_move_appli_to_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *user_data)
1325 {
1326 gpointer *data = user_data[0];
1327 Icon *icon = data[0];
1328 // CairoDock *pDock = data[1];
1329 int iDesktopNumber = GPOINTER_TO_INT (user_data[1]);
1330 int iViewPortNumberY = GPOINTER_TO_INT (user_data[2]);
1331 int iViewPortNumberX = GPOINTER_TO_INT (user_data[3]);
1332 cd_message ("%s (%d;%d;%d)", __func__, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1333 if (CAIRO_DOCK_IS_APPLI (icon))
1334 {
1335 gldi_window_move_to_desktop (icon->pAppli, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1336 }
1337 }
1338
_cairo_dock_change_window_above(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1339 static void _cairo_dock_change_window_above (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1340 {
1341 Icon *icon = data[0];
1342 // CairoDock *pDock = data[1];
1343 if (CAIRO_DOCK_IS_APPLI (icon))
1344 {
1345 gboolean bIsAbove=FALSE, bIsBelow=FALSE;
1346 gldi_window_is_above_or_below (icon->pAppli, &bIsAbove, &bIsBelow);
1347 gldi_window_set_above (icon->pAppli, ! bIsAbove);
1348 }
1349 }
1350
_cairo_dock_change_window_sticky(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1351 static void _cairo_dock_change_window_sticky (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1352 {
1353 Icon *icon = data[0];
1354 // CairoDock *pDock = data[1];
1355 if (CAIRO_DOCK_IS_APPLI (icon))
1356 {
1357 gboolean bIsSticky = gldi_window_is_sticky (icon->pAppli);
1358 gldi_window_set_sticky (icon->pAppli, ! bIsSticky);
1359 }
1360 }
1361
_cairo_dock_move_class_to_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * user_data)1362 static void _cairo_dock_move_class_to_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *user_data)
1363 {
1364 gpointer *data = user_data[0];
1365 Icon *icon = data[0];
1366 // CairoDock *pDock = data[1];
1367 g_return_if_fail (icon->pSubDock != NULL);
1368 int iDesktopNumber = GPOINTER_TO_INT (user_data[1]);
1369 int iViewPortNumberY = GPOINTER_TO_INT (user_data[2]);
1370 int iViewPortNumberX = GPOINTER_TO_INT (user_data[3]);
1371 cd_message ("%s (%d;%d;%d)", __func__, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1372
1373 Icon *pIcon;
1374 GList *ic;
1375 for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1376 {
1377 pIcon = ic->data;
1378 if (CAIRO_DOCK_IS_APPLI (pIcon))
1379 {
1380 gldi_window_move_to_desktop (pIcon->pAppli, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1381 }
1382 }
1383 }
1384
_add_desktops_entry(GtkWidget * pMenu,gboolean bAll,gpointer * data)1385 static void _add_desktops_entry (GtkWidget *pMenu, gboolean bAll, gpointer *data)
1386 {
1387 static gpointer *s_pDesktopData = NULL;
1388 GtkWidget *pMenuItem;
1389
1390 if (g_desktopGeometry.iNbDesktops > 1 || g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1)
1391 {
1392 // add separator
1393 pMenuItem = gtk_separator_menu_item_new ();
1394 gtk_menu_shell_append (GTK_MENU_SHELL (pMenu), pMenuItem);
1395
1396 int i, j, k, iDesktopCode;
1397 const gchar *cLabel;
1398 if (g_desktopGeometry.iNbDesktops > 1 && (g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1))
1399 cLabel = bAll ? _("Move all to desktop %d - face %d") : _("Move to desktop %d - face %d");
1400 else if (g_desktopGeometry.iNbDesktops > 1)
1401 cLabel = bAll ? _("Move all to desktop %d") : _("Move to desktop %d");
1402 else
1403 cLabel = bAll ? _("Move all to face %d") : _("Move to face %d");
1404 GString *sDesktop = g_string_new ("");
1405 g_free (s_pDesktopData);
1406 s_pDesktopData = g_new0 (gpointer, 4 * g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY);
1407 gpointer *user_data;
1408 Icon *icon = data[0];
1409 GldiWindowActor *pAppli = icon->pAppli;
1410
1411 for (i = 0; i < g_desktopGeometry.iNbDesktops; i ++) // on range par bureau.
1412 {
1413 for (j = 0; j < g_desktopGeometry.iNbViewportY; j ++) // puis par rangee.
1414 {
1415 for (k = 0; k < g_desktopGeometry.iNbViewportX; k ++)
1416 {
1417 if (g_desktopGeometry.iNbDesktops > 1 && (g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1))
1418 g_string_printf (sDesktop, cLabel, i+1, j*g_desktopGeometry.iNbViewportX+k+1);
1419 else if (g_desktopGeometry.iNbDesktops > 1)
1420 g_string_printf (sDesktop, cLabel, i+1);
1421 else
1422 g_string_printf (sDesktop, cLabel, j*g_desktopGeometry.iNbViewportX+k+1);
1423 iDesktopCode = i * g_desktopGeometry.iNbViewportY * g_desktopGeometry.iNbViewportX + j * g_desktopGeometry.iNbViewportX + k;
1424 user_data = &s_pDesktopData[4*iDesktopCode];
1425 user_data[0] = data;
1426 user_data[1] = GINT_TO_POINTER (i);
1427 user_data[2] = GINT_TO_POINTER (j);
1428 user_data[3] = GINT_TO_POINTER (k);
1429
1430 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (sDesktop->str, NULL, G_CALLBACK (bAll ? _cairo_dock_move_class_to_desktop : _cairo_dock_move_appli_to_desktop), pMenu, user_data);
1431 if (pAppli && gldi_window_is_on_desktop (pAppli, i, k, j))
1432 gtk_widget_set_sensitive (pMenuItem, FALSE);
1433 }
1434 }
1435 }
1436 g_string_free (sDesktop, TRUE);
1437 }
1438 }
1439
1440
1441 ///////////////////////////////////////////////////////////////
1442 ///////////// LES OPERATIONS SUR LES CLASSES //////////////////
1443 ///////////////////////////////////////////////////////////////
1444
_cairo_dock_launch_class_action(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gchar * cCommand)1445 static void _cairo_dock_launch_class_action (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gchar *cCommand)
1446 {
1447 cairo_dock_launch_command (cCommand);
1448 }
1449
_cairo_dock_show_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1450 static void _cairo_dock_show_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1451 {
1452 Icon *icon = data[0];
1453 // CairoDock *pDock = data[1];
1454 g_return_if_fail (icon->pSubDock != NULL);
1455
1456 Icon *pIcon;
1457 GList *ic;
1458 for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1459 {
1460 pIcon = ic->data;
1461 if (CAIRO_DOCK_IS_APPLI (pIcon))
1462 {
1463 gldi_window_show (pIcon->pAppli);
1464 }
1465 }
1466 }
1467
_cairo_dock_minimize_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1468 static void _cairo_dock_minimize_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1469 {
1470 Icon *icon = data[0];
1471 // CairoDock *pDock = data[1];
1472 g_return_if_fail (icon->pSubDock != NULL);
1473
1474 Icon *pIcon;
1475 GList *ic;
1476 for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1477 {
1478 pIcon = ic->data;
1479 if (CAIRO_DOCK_IS_APPLI (pIcon))
1480 {
1481 gldi_window_minimize (pIcon->pAppli);
1482 }
1483 }
1484 }
1485
_cairo_dock_close_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1486 static void _cairo_dock_close_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1487 {
1488 Icon *icon = data[0];
1489 // CairoDock *pDock = data[1];
1490 g_return_if_fail (icon->pSubDock != NULL);
1491
1492 Icon *pIcon;
1493 GList *ic;
1494 for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1495 {
1496 pIcon = ic->data;
1497 if (CAIRO_DOCK_IS_APPLI (pIcon))
1498 {
1499 gldi_window_close (pIcon->pAppli);
1500 }
1501 }
1502 }
1503
_cairo_dock_move_class_to_current_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1504 static void _cairo_dock_move_class_to_current_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1505 {
1506 Icon *icon = data[0];
1507 // CairoDock *pDock = data[1];
1508 g_return_if_fail (icon->pSubDock != NULL);
1509
1510 Icon *pIcon;
1511 GList *ic;
1512 for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1513 {
1514 pIcon = ic->data;
1515 if (CAIRO_DOCK_IS_APPLI (pIcon))
1516 {
1517 gldi_window_move_to_current_desktop (pIcon->pAppli);
1518 }
1519 }
1520 }
1521
1522 ///////////////////////////////////////////////////////////////////
1523 ///////////////// LES OPERATIONS SUR LES DESKLETS /////////////////
1524 ///////////////////////////////////////////////////////////////////
1525
_cairo_dock_set_desklet_accessibility(CairoDesklet * pDesklet,CairoDeskletVisibility iVisibility)1526 static inline void _cairo_dock_set_desklet_accessibility (CairoDesklet *pDesklet, CairoDeskletVisibility iVisibility)
1527 {
1528 gldi_desklet_set_accessibility (pDesklet, iVisibility, TRUE); // TRUE <=> save state in conf.
1529 cairo_dock_gui_update_desklet_visibility (pDesklet);
1530 }
_cairo_dock_keep_below(GtkCheckMenuItem * pMenuItem,gpointer * data)1531 static void _cairo_dock_keep_below (GtkCheckMenuItem *pMenuItem, gpointer *data)
1532 {
1533 CairoDesklet *pDesklet = data[1];
1534 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1535 _cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_KEEP_BELOW);
1536 }
1537
_cairo_dock_keep_normal(GtkCheckMenuItem * pMenuItem,gpointer * data)1538 static void _cairo_dock_keep_normal (GtkCheckMenuItem *pMenuItem, gpointer *data)
1539 {
1540 CairoDesklet *pDesklet = data[1];
1541 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1542 _cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_NORMAL);
1543 }
1544
_cairo_dock_keep_above(GtkCheckMenuItem * pMenuItem,gpointer * data)1545 static void _cairo_dock_keep_above (GtkCheckMenuItem *pMenuItem, gpointer *data)
1546 {
1547 CairoDesklet *pDesklet = data[1];
1548 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1549 _cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_KEEP_ABOVE);
1550 }
1551
_cairo_dock_keep_on_widget_layer(GtkMenuItem * pMenuItem,gpointer * data)1552 static void _cairo_dock_keep_on_widget_layer (GtkMenuItem *pMenuItem, gpointer *data)
1553 {
1554 CairoDesklet *pDesklet = data[1];
1555 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1556 _cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_ON_WIDGET_LAYER);
1557 }
1558
_cairo_dock_keep_space(GtkCheckMenuItem * pMenuItem,gpointer * data)1559 static void _cairo_dock_keep_space (GtkCheckMenuItem *pMenuItem, gpointer *data)
1560 {
1561 CairoDesklet *pDesklet = data[1];
1562 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1563 _cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_RESERVE_SPACE);
1564 }
1565
_cairo_dock_set_on_all_desktop(GtkCheckMenuItem * pMenuItem,gpointer * data)1566 static void _cairo_dock_set_on_all_desktop (GtkCheckMenuItem *pMenuItem, gpointer *data)
1567 {
1568 CairoDesklet *pDesklet = data[1];
1569 gboolean bSticky = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem));
1570 gldi_desklet_set_sticky (pDesklet, bSticky);
1571 cairo_dock_gui_update_desklet_visibility (pDesklet);
1572 }
1573
_cairo_dock_lock_position(GtkMenuItem * pMenuItem,gpointer * data)1574 static void _cairo_dock_lock_position (GtkMenuItem *pMenuItem, gpointer *data)
1575 {
1576 CairoDesklet *pDesklet = data[1];
1577 gboolean bLocked = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem));
1578 gldi_desklet_lock_position (pDesklet, bLocked);
1579 cairo_dock_gui_update_desklet_visibility (pDesklet);
1580 }
1581
1582
1583 ////////////////////////////////////
1584 /// BUILD ICON MENU NOTIFICATION ///
1585 ////////////////////////////////////
1586
1587 // stuff for the buttons inside a menu-item
_on_press_menu_item(GtkWidget * pWidget,GdkEventButton * pEvent,G_GNUC_UNUSED gpointer data)1588 static gboolean _on_press_menu_item (GtkWidget* pWidget, GdkEventButton *pEvent, G_GNUC_UNUSED gpointer data)
1589 {
1590 GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1591 GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1592 int x = pEvent->x, y = pEvent->y; // position of the mouse relatively to the menu-item
1593 int xb, yb; // position of the top-left corner of the button relatively to the menu-item
1594 GtkWidget* pButton;
1595 GList* c;
1596 for (c = children->next; c != NULL; c = c->next)
1597 {
1598 pButton = GTK_WIDGET(c->data);
1599 GtkAllocation alloc;
1600 gtk_widget_get_allocation (pButton, &alloc);
1601 gtk_widget_translate_coordinates (pButton, pWidget,
1602 0, 0, &xb, &yb);
1603 if (x >= xb && x < (xb + alloc.width)
1604 && y >= yb && y < (yb + alloc.height))
1605 {
1606 gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_ACTIVE, TRUE);
1607 gtk_widget_set_state_flags (
1608 gtk_bin_get_child(GTK_BIN(pButton)),
1609 GTK_STATE_FLAG_ACTIVE, TRUE);
1610 gtk_button_clicked (GTK_BUTTON (pButton));
1611 }
1612 else
1613 {
1614 gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1615 gtk_widget_set_state_flags (
1616 gtk_bin_get_child(GTK_BIN(pButton)),
1617 GTK_STATE_FLAG_NORMAL, TRUE);
1618 }
1619 }
1620 g_list_free (children);
1621 gtk_widget_queue_draw (pWidget);
1622 return TRUE;
1623 }
_draw_menu_item(GtkWidget * pWidget,cairo_t * cr)1624 static gboolean _draw_menu_item (GtkWidget* pWidget, cairo_t *cr)
1625 {
1626 gtk_container_propagate_draw (GTK_CONTAINER (pWidget),
1627 gtk_bin_get_child (GTK_BIN (pWidget)),
1628 cr); // skip the drawing of the menu-item, just propagate to its child; there is no need to make anything else, the child hbox will draw its child as usual.
1629 return TRUE; // intercept
1630 }
_on_motion_notify_menu_item(GtkWidget * pWidget,GdkEventMotion * pEvent,G_GNUC_UNUSED gpointer data)1631 gboolean _on_motion_notify_menu_item (GtkWidget* pWidget,
1632 GdkEventMotion* pEvent,
1633 G_GNUC_UNUSED gpointer data)
1634 {
1635 GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1636 GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1637 int x = pEvent->x, y = pEvent->y; // position of the mouse relatively to the menu-item
1638 int xb, yb; // position of the top-left corner of the button relatively to the menu-item
1639 GtkWidget* pButton;
1640 GList* c;
1641 for (c = children->next; c != NULL; c = c->next) // skip the label
1642 {
1643 pButton = GTK_WIDGET (c->data);
1644 GtkAllocation alloc;
1645 gtk_widget_get_allocation (pButton, &alloc);
1646 gtk_widget_translate_coordinates (pButton, pWidget,
1647 0, 0, &xb, &yb);
1648 if (x >= xb && x < (xb + alloc.width)
1649 && y >= yb && y < (yb + alloc.height)) // the mouse is inside the button -> select it
1650 {
1651 gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_PRELIGHT, TRUE);
1652 gtk_widget_set_state_flags (
1653 gtk_bin_get_child(GTK_BIN(pButton)),
1654 GTK_STATE_FLAG_PRELIGHT, TRUE);
1655 }
1656 else // else deselect it, in case it was selected
1657 {
1658 gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1659 gtk_widget_set_state_flags (
1660 gtk_bin_get_child(GTK_BIN(pButton)),
1661 GTK_STATE_FLAG_NORMAL, TRUE);
1662 }
1663 }
1664 GtkWidget *pLabel = children->data; // force the label to be in a normal state
1665 gtk_widget_set_state_flags (pLabel, GTK_STATE_FLAG_NORMAL, TRUE);
1666 g_list_free (children);
1667 gtk_widget_queue_draw (pWidget); // and redraw everything
1668 return FALSE;
1669 }
_on_leave_menu_item(GtkWidget * pWidget,G_GNUC_UNUSED GdkEventCrossing * pEvent,G_GNUC_UNUSED gpointer data)1670 static gboolean _on_leave_menu_item (GtkWidget* pWidget,
1671 G_GNUC_UNUSED GdkEventCrossing* pEvent,
1672 G_GNUC_UNUSED gpointer data)
1673 {
1674 GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1675 GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1676 GtkWidget* pButton;
1677 GList* c;
1678 for (c = children->next; c != NULL; c = c->next)
1679 {
1680 pButton = GTK_WIDGET(c->data);
1681 gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1682 gtk_widget_set_state_flags(
1683 gtk_bin_get_child (GTK_BIN(pButton)),
1684 GTK_STATE_FLAG_NORMAL, TRUE);
1685 }
1686 g_list_free (children);
1687 gtk_widget_queue_draw (pWidget);
1688 return FALSE;
1689 }
_on_enter_menu_item(GtkWidget * pWidget,G_GNUC_UNUSED GdkEventCrossing * pEvent,G_GNUC_UNUSED gpointer data)1690 static gboolean _on_enter_menu_item (GtkWidget* pWidget,
1691 G_GNUC_UNUSED GdkEventCrossing* pEvent,
1692 G_GNUC_UNUSED gpointer data)
1693 {
1694 GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1695 GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1696 GtkWidget* pLabel = children->data; // force the label to be in a normal state
1697 gtk_widget_set_state_flags (pLabel, GTK_STATE_FLAG_NORMAL, TRUE);
1698 g_list_free (children);
1699 gtk_widget_queue_draw (pWidget);
1700 return FALSE;
1701 }
_add_new_button_to_hbox(const gchar * gtkStock,const gchar * cTooltip,GCallback pFunction,GtkWidget * hbox,gpointer data)1702 static GtkWidget *_add_new_button_to_hbox (const gchar *gtkStock, const gchar *cTooltip, GCallback pFunction, GtkWidget *hbox, gpointer data)
1703 {
1704 GtkWidget *pButton = gtk_button_new ();
1705 /*
1706 GtkStyleContext *ctx = gtk_widget_get_style_context (pButton);
1707 // or we can just remove the style of a button but it's still a button :)
1708 gtk_style_context_remove_class (ctx, GTK_STYLE_CLASS_BUTTON);
1709 // a style like a menuitem but it's a button...
1710 gtk_style_context_add_class (ctx, GTK_STYLE_CLASS_MENUITEM);
1711 */
1712
1713 if (gtkStock)
1714 {
1715 GtkWidget *pImage = NULL;
1716 if (*gtkStock == '/')
1717 {
1718 int size = cairo_dock_search_icon_size (GTK_ICON_SIZE_MENU);
1719 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (gtkStock, size, size, NULL);
1720 pImage = gtk_image_new_from_pixbuf (pixbuf);
1721 g_object_unref (pixbuf);
1722 }
1723 else
1724 {
1725 pImage = gtk_image_new_from_icon_name (gtkStock, GTK_ICON_SIZE_MENU);
1726 }
1727 gtk_button_set_image (GTK_BUTTON (pButton), pImage); // don't unref the image
1728 }
1729 gtk_widget_set_tooltip_text (pButton, cTooltip);
1730 g_signal_connect (G_OBJECT (pButton), "clicked", G_CALLBACK(pFunction), data);
1731 gtk_box_pack_end (GTK_BOX (hbox), pButton, FALSE, FALSE, 0);
1732 return pButton;
1733 }
_add_menu_item_with_buttons(GtkWidget * menu)1734 static GtkWidget *_add_menu_item_with_buttons (GtkWidget *menu)
1735 {
1736 GtkWidget *pMenuItem = gtk_menu_item_new ();
1737 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1738
1739 g_signal_connect (G_OBJECT (pMenuItem), "button-press-event",
1740 G_CALLBACK(_on_press_menu_item),
1741 NULL); // the press event on the menu will close it, which is fine for us.
1742 g_signal_connect (G_OBJECT (pMenuItem), "motion-notify-event",
1743 G_CALLBACK(_on_motion_notify_menu_item),
1744 NULL); // we need to manually higlight the currently pointed button
1745 g_signal_connect (G_OBJECT (pMenuItem),
1746 "leave-notify-event",
1747 G_CALLBACK (_on_leave_menu_item),
1748 NULL); // to turn off the highlighted button when we leave the menu-item (if we leave it quickly, a motion event won't be generated)
1749 g_signal_connect (G_OBJECT (pMenuItem),
1750 "enter-notify-event",
1751 G_CALLBACK (_on_enter_menu_item),
1752 NULL); // to force the label to not highlight (it gets highlighted, even if we overwrite the motion_notify_event callback)
1753 g_signal_connect (G_OBJECT (pMenuItem),
1754 "draw",
1755 G_CALLBACK (_draw_menu_item),
1756 NULL); // we don't want the whole menu-item to be higlighted, but only the currently pointed button; so we draw the menu-item ourselves.
1757
1758 GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
1759 gtk_container_add (GTK_CONTAINER (pMenuItem), hbox);
1760 return hbox;
1761 }
1762
cairo_dock_notification_build_icon_menu(G_GNUC_UNUSED gpointer * pUserData,Icon * icon,GldiContainer * pContainer,GtkWidget * menu)1763 gboolean cairo_dock_notification_build_icon_menu (G_GNUC_UNUSED gpointer *pUserData, Icon *icon, GldiContainer *pContainer, GtkWidget *menu)
1764 {
1765 static gpointer data[3];
1766 data[0] = icon;
1767 data[1] = pContainer;
1768 data[2] = menu;
1769 GtkWidget *pMenuItem;
1770
1771 gchar *cLabel;
1772
1773 //\_________________________ Clic en-dehors d'une icone utile => on s'arrete la.
1774 if (CAIRO_DOCK_IS_DOCK (pContainer) && (icon == NULL || CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (icon)))
1775 {
1776 return GLDI_NOTIFICATION_LET_PASS;
1777 }
1778
1779 gboolean bAddSeparator = TRUE;
1780 if (CAIRO_DOCK_IS_DESKLET (pContainer) && icon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // not on the icons of a desklet, except the applet icon (on a desklet, it's easy to click out of any icon).
1781 bAddSeparator = FALSE;
1782
1783 if (CAIRO_DOCK_IS_DOCK (pContainer) && CAIRO_DOCK (pContainer)->iRefCount > 0) // not on the sub-docks, except user sub-docks.
1784 {
1785 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (CAIRO_DOCK (pContainer), NULL);
1786 if (pPointingIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pPointingIcon))
1787 bAddSeparator = FALSE;
1788 }
1789
1790 //\_________________________ class actions.
1791 if (icon && icon->cClass != NULL && ! icon->bIgnoreQuicklist)
1792 {
1793 const GList *pClassMenuItems = cairo_dock_get_class_menu_items (icon->cClass);
1794 if (pClassMenuItems != NULL)
1795 {
1796 if (bAddSeparator)
1797 {
1798 pMenuItem = gtk_separator_menu_item_new ();
1799 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1800 }
1801 bAddSeparator = TRUE;
1802 gchar **pClassItem;
1803 const GList *m;
1804 for (m = pClassMenuItems; m != NULL; m = m->next)
1805 {
1806 pClassItem = m->data;
1807 pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (pClassItem[0], pClassItem[2], G_CALLBACK (_cairo_dock_launch_class_action), menu, pClassItem[1]);
1808 }
1809 }
1810 }
1811
1812 //\_________________________ On rajoute les actions sur les applis.
1813 if (CAIRO_DOCK_IS_APPLI (icon))
1814 {
1815 if (bAddSeparator)
1816 {
1817 pMenuItem = gtk_separator_menu_item_new ();
1818 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1819 }
1820 bAddSeparator = TRUE;
1821
1822 GldiWindowActor *pAppli = icon->pAppli;
1823
1824 gboolean bCanMinimize, bCanMaximize, bCanClose;
1825 gldi_window_can_minimize_maximize_close (pAppli, &bCanMinimize, &bCanMaximize, &bCanClose);
1826
1827 //\_________________________ Window Management
1828 GtkWidget *hbox = _add_menu_item_with_buttons (menu);
1829
1830 GtkWidget *pLabel = gtk_label_new (_("Window"));
1831 gtk_box_pack_start (GTK_BOX (hbox), pLabel, FALSE, FALSE, 0);
1832
1833 if (bCanClose)
1834 {
1835 if (myTaskbarParam.iActionOnMiddleClick == 1 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // close
1836 cLabel = g_strdup_printf ("%s (%s)", _("Close"), _("middle-click"));
1837 else
1838 cLabel = g_strdup (_("Close"));
1839 _add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-close.svg",
1840 cLabel,
1841 G_CALLBACK(_cairo_dock_close_appli),
1842 hbox, data);
1843 g_free (cLabel);
1844 }
1845
1846 if (! pAppli->bIsHidden)
1847 {
1848 if (bCanMaximize)
1849 {
1850 _add_new_button_to_hbox (pAppli->bIsMaximized ? CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-restore.svg" : CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-maximize.svg",
1851 pAppli->bIsMaximized ? _("Unmaximise") : _("Maximise"),
1852 G_CALLBACK(_cairo_dock_maximize_appli),
1853 hbox, data);
1854 }
1855
1856 if (bCanMinimize)
1857 {
1858 if (myTaskbarParam.iActionOnMiddleClick == 2 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // minimize
1859 cLabel = g_strdup_printf ("%s (%s)", _("Minimise"), _("middle-click"));
1860 else
1861 cLabel = g_strdup (_("Minimise"));
1862 _add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-minimize.svg",
1863 cLabel,
1864 G_CALLBACK(_cairo_dock_minimize_appli),
1865 hbox, data);
1866 g_free (cLabel);
1867 }
1868 }
1869
1870 if (pAppli->bIsHidden
1871 || pAppli != gldi_windows_get_active ()
1872 || !gldi_window_is_on_current_desktop (pAppli))
1873 {
1874 _add_new_button_to_hbox (GLDI_ICON_NAME_FIND,
1875 _("Show"),
1876 G_CALLBACK(_cairo_dock_show_appli),
1877 hbox, data);
1878 }
1879
1880 //\_________________________ Other actions
1881 GtkWidget *pSubMenuOtherActions = cairo_dock_create_sub_menu (_("Other actions"), menu, NULL);
1882
1883 // Move
1884 pMenuItem = _add_entry_in_menu (_("Move to this desktop"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_move_appli_to_current_desktop, pSubMenuOtherActions);
1885 if (gldi_window_is_on_current_desktop (pAppli))
1886 gtk_widget_set_sensitive (pMenuItem, FALSE);
1887
1888 // Fullscreen
1889 _add_entry_in_menu (pAppli->bIsFullScreen ? _("Not Fullscreen") : _("Fullscreen"), pAppli->bIsFullScreen ? GLDI_ICON_NAME_LEAVE_FULLSCREEN : GLDI_ICON_NAME_FULLSCREEN, _cairo_dock_set_appli_fullscreen, pSubMenuOtherActions);
1890
1891 // Below
1892 if (! pAppli->bIsHidden) // this could be a button in the menu, if we find an icon that doesn't look too much like the "minimise" one
1893 {
1894 if (myTaskbarParam.iActionOnMiddleClick == 4 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // lower
1895 cLabel = g_strdup_printf ("%s (%s)", _("Below other windows"), _("middle-click"));
1896 else
1897 cLabel = g_strdup (_("Below other windows"));
1898 _add_entry_in_menu (cLabel, CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-lower.svg", _cairo_dock_lower_appli, pSubMenuOtherActions);
1899 g_free (cLabel);
1900 }
1901
1902 // Above
1903 gboolean bIsAbove=FALSE, bIsBelow=FALSE;
1904 gldi_window_is_above_or_below (pAppli, &bIsAbove, &bIsBelow);
1905 _add_entry_in_menu (bIsAbove ? _("Don't keep above") : _("Keep above"), bIsAbove ? GLDI_ICON_NAME_GOTO_BOTTOM : GLDI_ICON_NAME_GOTO_TOP, _cairo_dock_change_window_above, pSubMenuOtherActions);
1906
1907 // Sticky
1908 gboolean bIsSticky = gldi_window_is_sticky (pAppli);
1909 _add_entry_in_menu (bIsSticky ? _("Visible only on this desktop") : _("Visible on all desktops"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_change_window_sticky, pSubMenuOtherActions);
1910
1911 _add_desktops_entry (pSubMenuOtherActions, FALSE, data);
1912
1913 // add separator
1914 pMenuItem = gtk_separator_menu_item_new ();
1915 gtk_menu_shell_append (GTK_MENU_SHELL (pSubMenuOtherActions), pMenuItem);
1916
1917 _add_entry_in_menu (_("Kill"), GLDI_ICON_NAME_CLOSE, _cairo_dock_kill_appli, pSubMenuOtherActions);
1918 }
1919 else if (CAIRO_DOCK_IS_MULTI_APPLI (icon))
1920 {
1921 if (bAddSeparator)
1922 {
1923 pMenuItem = gtk_separator_menu_item_new ();
1924 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1925 }
1926 bAddSeparator = TRUE;
1927
1928 //\_________________________ Window Management
1929 GtkWidget *hbox = _add_menu_item_with_buttons (menu);
1930
1931 GtkWidget *pLabel = gtk_label_new (_("Windows"));
1932 gtk_box_pack_start (GTK_BOX (hbox), pLabel, FALSE, FALSE, 0);
1933
1934 if (myTaskbarParam.iActionOnMiddleClick == 1 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // close
1935 cLabel = g_strdup_printf ("%s (%s)", _("Close all"), _("middle-click"));
1936 else
1937 cLabel = g_strdup (_("Close all"));
1938 _add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-close.svg",
1939 cLabel,
1940 G_CALLBACK(_cairo_dock_close_class),
1941 hbox, data);
1942 g_free (cLabel);
1943
1944 if (myTaskbarParam.iActionOnMiddleClick == 2 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon)) // minimize
1945 cLabel = g_strdup_printf ("%s (%s)", _("Minimise all"), _("middle-click"));
1946 else
1947 cLabel = g_strdup (_("Minimise all"));
1948 _add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-minimize.svg",
1949 cLabel,
1950 G_CALLBACK(_cairo_dock_minimize_class),
1951 hbox, data);
1952 g_free (cLabel);
1953
1954 _add_new_button_to_hbox (GLDI_ICON_NAME_FIND,
1955 _("Show all"),
1956 G_CALLBACK(_cairo_dock_show_class),
1957 hbox, data);
1958
1959 //\_________________________ Other actions
1960 GtkWidget *pSubMenuOtherActions = cairo_dock_create_sub_menu (_("Other actions"), menu, NULL);
1961
1962 _add_entry_in_menu (_("Move all to this desktop"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_move_class_to_current_desktop, pSubMenuOtherActions);
1963
1964 _add_desktops_entry (pSubMenuOtherActions, TRUE, data);
1965 }
1966
1967 //\_________________________ On rajoute les actions de positionnement d'un desklet.
1968 if (! cairo_dock_is_locked () && CAIRO_DOCK_IS_DESKLET (pContainer))
1969 {
1970 if (bAddSeparator)
1971 {
1972 pMenuItem = gtk_separator_menu_item_new ();
1973 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1974 }
1975 bAddSeparator = TRUE;
1976
1977 GtkWidget *pSubMenuAccessibility = cairo_dock_create_sub_menu (_("Visibility"), menu, GLDI_ICON_NAME_FIND);
1978
1979 GSList *group = NULL;
1980
1981 gboolean bIsSticky = gldi_desklet_is_sticky (CAIRO_DESKLET (pContainer));
1982 CairoDesklet *pDesklet = CAIRO_DESKLET (pContainer);
1983 CairoDeskletVisibility iVisibility = pDesklet->iVisibility;
1984
1985 pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Normal"));
1986 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
1987 gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
1988 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), iVisibility == CAIRO_DESKLET_NORMAL/*bIsNormal*/); // on coche celui-ci par defaut, il sera decoche par les suivants eventuellement.
1989 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_normal), data);
1990
1991 pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Always on top"));
1992 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
1993 gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
1994 if (iVisibility == CAIRO_DESKLET_KEEP_ABOVE)
1995 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
1996 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_above), data);
1997
1998 pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Always below"));
1999 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2000 gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2001 if (iVisibility == CAIRO_DESKLET_KEEP_BELOW)
2002 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2003 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_below), data);
2004
2005 if (gldi_desktop_can_set_on_widget_layer ())
2006 {
2007 pMenuItem = gtk_radio_menu_item_new_with_label(group, "Widget Layer");
2008 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2009 gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2010 if (iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER)
2011 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2012 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_on_widget_layer), data);
2013 }
2014
2015 pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Reserve space"));
2016 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2017 gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2018 if (iVisibility == CAIRO_DESKLET_RESERVE_SPACE)
2019 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2020 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_space), data);
2021
2022 pMenuItem = gtk_check_menu_item_new_with_label(_("On all desktops"));
2023 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
2024 if (bIsSticky)
2025 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2026 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_set_on_all_desktop), data);
2027
2028 pMenuItem = gtk_check_menu_item_new_with_label(_("Lock position"));
2029 gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
2030 if (pDesklet->bPositionLocked)
2031 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2032 g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_lock_position), data);
2033 }
2034
2035 return GLDI_NOTIFICATION_LET_PASS;
2036 }
2037