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 <stdlib.h>
21 #include <string.h>
22 #include <cairo-dock.h> // include before to have 'HAVE_X11'
23 #ifdef HAVE_X11
24 #ifdef HAVE_XRANDR
25 #include <X11/Xlib.h>
26 #include <X11/extensions/Xrandr.h>
27 #include <gdk/gdkx.h>
28 #endif
29 #endif
30
31 #include "applet-struct.h"
32 #include "applet-notifications.h"
33
34
_cd_allow_minimize(CairoDesklet * pDesklet,gpointer data)35 static gboolean _cd_allow_minimize (CairoDesklet *pDesklet, gpointer data)
36 {
37 pDesklet->bAllowMinimize = TRUE;
38 return FALSE;
39 }
40
_cd_show_hide_desktop(gboolean bShowDesklets)41 static void _cd_show_hide_desktop (gboolean bShowDesklets)
42 {
43 if (! myData.bDesktopVisible && ! bShowDesklets) // on autorise chaque desklet a etre minimise. l'autorisation est annulee lors de leur cachage, donc on n'a pas besoin de faire le contraire apres avoir montre le bureau.
44 {
45 gldi_desklets_foreach ((GldiDeskletForeachFunc) _cd_allow_minimize, NULL);
46 }
47
48 gldi_desktop_show_hide (! myData.bDesktopVisible);
49 }
50
_cd_show_hide_desklet(void)51 static void _cd_show_hide_desklet (void)
52 {
53 if (!myData.bDeskletsVisible)
54 {
55 myData.pLastActiveWindow = gldi_windows_get_active ();
56 gldi_object_ref (GLDI_OBJECT(myData.pLastActiveWindow));
57 gldi_desklets_set_visible (TRUE); // TRUE <=> les desklets de la couche widget aussi.
58 }
59 else
60 {
61 gldi_desklets_set_visibility_to_default ();
62 if (myData.pLastActiveWindow)
63 {
64 gldi_window_show (myData.pLastActiveWindow);
65 gldi_object_unref (GLDI_OBJECT(myData.pLastActiveWindow));
66 myData.pLastActiveWindow = NULL;
67 }
68 }
69 myData.bDeskletsVisible = ! myData.bDeskletsVisible;
70
71 if (myConfig.cVisibleImage)
72 {
73 if (myData.bDesktopVisible || myData.bDeskletsVisible)
74 CD_APPLET_SET_IMAGE_ON_MY_ICON (myConfig.cVisibleImage);
75 else
76 CD_APPLET_SET_IMAGE_ON_MY_ICON (myConfig.cHiddenImage);
77 }
78 }
79
80
_cd_show_widget_layer(void)81 static void _cd_show_widget_layer (void)
82 {
83 gldi_desktop_show_widget_layer ();
84 }
85
_cd_expose(void)86 static void _cd_expose (void)
87 {
88 gldi_desktop_present_desktops ();
89 }
_expose_delayed(G_GNUC_UNUSED gpointer data)90 static gboolean _expose_delayed (G_GNUC_UNUSED gpointer data)
91 {
92 _cd_expose ();
93 return FALSE;
94 }
_cd_action(CDActionOnClick iAction)95 static void _cd_action (CDActionOnClick iAction)
96 {
97 switch (iAction)
98 {
99 case CD_SHOW_DESKTOP :
100 _cd_show_hide_desktop (FALSE);
101 break ;
102 case CD_SHOW_DESKLETS :
103 _cd_show_hide_desklet ();
104 break ;
105 case CD_SHOW_DESKTOP_AND_DESKLETS :
106 _cd_show_hide_desktop (TRUE); // TRUE <=> show the desklets
107 break ;
108 case CD_SHOW_WIDGET_LAYER :
109 if (gldi_desktop_can_show_widget_layer ())
110 _cd_show_widget_layer ();
111 else
112 {
113 cd_warning ("It seems there is no widget layer, we show/hide the desktop");
114 _cd_show_hide_desktop (FALSE);
115 }
116 break ;
117 case CD_EXPOSE :
118 if (gldi_desktop_can_present_desktops ())
119 {
120 g_timeout_add (250, _expose_delayed, NULL); // Gnome-Shell bug here: it doesn't execute the Dbus command right after a click; I suspect the delay to be the interval of a double-click... anyway, it's stupid but it's barely noticeable, so it doesn't hurt that much even when not using GS.
121 }
122 else
123 {
124 cd_warning ("It seems we can't present desktops, we show/hide the desktop");
125 _cd_show_hide_desktop (FALSE);
126 }
127 break ;
128 default:
129 break;
130 }
131 }
132
133 //\___________ Define here the action to be taken when the user left-clicks on your icon or on its subdock or your desklet. The icon and the container that were clicked are available through the macros CD_APPLET_CLICKED_ICON and CD_APPLET_CLICKED_CONTAINER. CD_APPLET_CLICKED_ICON may be NULL if the user clicked in the container but out of icons.
134 CD_APPLET_ON_CLICK_BEGIN
135 _cd_action (myConfig.iActionOnLeftClick);
136 CD_APPLET_ON_CLICK_END
137
138
139 //\___________ Define here the entries you want to add to the menu when the user right-clicks on your icon or on its subdock or your desklet. The icon and the container that were clicked are available through the macros CD_APPLET_CLICKED_ICON and CD_APPLET_CLICKED_CONTAINER. CD_APPLET_CLICKED_ICON may be NULL if the user clicked in the container but out of icons. The menu where you can add your entries is available throught the macro CD_APPLET_MY_MENU; you can add sub-menu to it if you want.
140 #ifdef HAVE_X11
141 #ifdef HAVE_XRANDR
_on_select_resolution(GtkMenuItem * menu_item,gpointer data)142 static void _on_select_resolution (GtkMenuItem *menu_item, gpointer data) /// TODO: put that in the core...
143 {
144 CD_APPLET_ENTER;
145 int iNumRes = GPOINTER_TO_INT (data);
146 Display *dpy;
147 Window root;
148 XRRScreenConfiguration *conf;
149 short *rates;
150 int num_rates;
151 dpy = gdk_x11_get_default_xdisplay ();
152 root = RootWindow(dpy, 0);
153
154 conf = XRRGetScreenInfo(dpy, root);
155 CD_APPLET_LEAVE_IF_FAIL (conf != NULL);
156 //g_return_if_fail (conf != NULL);
157
158 rates = XRRRates(dpy, 0, iNumRes, &num_rates);
159 CD_APPLET_LEAVE_IF_FAIL (num_rates > 0);
160 //g_return_if_fail (num_rates > 0);
161 cd_debug ("available rates : from %d to %d Hz", rates[0], rates[num_rates-1]);
162
163 XRRSetScreenConfigAndRate(dpy, conf, root, iNumRes, RR_Rotate_0, rates[num_rates-1], CurrentTime);
164 XRRFreeScreenConfigInfo (conf);
165
166 // restore original conf : XRRSetScreenConfigAndRate(dpy, conf, root, original_size_id, original_rotation, original_rate, CurrentTime);
167 CD_APPLET_LEAVE();
168 }
169 #endif
170 #endif
_show_desktop(GtkMenuItem * menu_item,gpointer data)171 static void _show_desktop (GtkMenuItem *menu_item, gpointer data)
172 {
173 _cd_show_hide_desktop (FALSE);
174 }
175 CD_APPLET_ON_BUILD_MENU_BEGIN
176 gchar *cLabel;
177
178 if (myConfig.iActionOnLeftClick != CD_SHOW_DESKTOP) // action is not bound to left-click => put it in the menu
179 {
180 if (myConfig.iActionOnMiddleClick == CD_SHOW_DESKTOP)
181 cLabel = g_strdup_printf ("%s (%s)", D_("Show desktop"), D_("middle-click"));
182 else
183 cLabel = g_strdup (D_("Show desktop"));
184 CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel,
185 MY_APPLET_SHARE_DATA_DIR"/../shared-files/images/show-desktop.svg",
186 _show_desktop,
187 CD_APPLET_MY_MENU);
188 g_free (cLabel);
189 }
190 if (myConfig.iActionOnLeftClick != CD_EXPOSE && gldi_desktop_can_present_desktops ()) // action is not bound to left-click => put it in the menu
191 {
192 if (myConfig.iActionOnMiddleClick == CD_EXPOSE)
193 cLabel = g_strdup_printf ("%s (%s)", D_("Expose all the desktops"), D_("middle-click"));
194 else
195 cLabel = g_strdup (D_("Expose all the desktops"));
196 CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel,
197 MY_APPLET_SHARE_DATA_DIR"/../shared-files/images/expose-desktops.svg",
198 _cd_expose,
199 CD_APPLET_MY_MENU);
200 g_free (cLabel);
201 }
202 if (myConfig.iActionOnLeftClick != CD_SHOW_WIDGET_LAYER && gldi_desktop_can_show_widget_layer ()) // action is not bound to left-click => put it in the menu
203 {
204 if (myConfig.iActionOnMiddleClick == CD_SHOW_WIDGET_LAYER)
205 cLabel = g_strdup_printf ("%s (%s)", D_("Show the Widget Layer"), D_("middle-click"));
206 else
207 cLabel = g_strdup (D_("Show the Widget Layer"));
208 CD_APPLET_ADD_IN_MENU_WITH_STOCK (cLabel,
209 MY_APPLET_SHARE_DATA_DIR"/../shared-files/images/widget-layer.svg",
210 _cd_show_widget_layer,
211 CD_APPLET_MY_MENU);
212 g_free (cLabel);
213 } // on ne met pas les actions sur les desklets, surement assez peu utilisees.
214
215 // Main Menu
216 #ifdef HAVE_X11
217 #ifdef HAVE_XRANDR
218 if (cairo_dock_check_xrandr (1, 1))
219 {
220 GtkWidget *pResSubMenu = CD_APPLET_ADD_SUB_MENU_WITH_IMAGE (D_("Change screen resolution"), CD_APPLET_MY_MENU, GLDI_ICON_NAME_FULLSCREEN);
221
222 Display *dpy;
223 Window root;
224 XRRScreenConfiguration *conf;
225 Rotation original_rotation;
226 SizeID original_size_id;
227
228 dpy = gdk_x11_get_default_xdisplay ();
229 root = RootWindow(dpy, 0);
230
231 conf = XRRGetScreenInfo(dpy, root); // config courante.
232 if (conf != NULL)
233 {
234 //original_rate = XRRConfigCurrentRate(conf);
235 original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
236
237 // resolutions possibles.
238 int num_sizes = 0;
239 XRRScreenSize *xrrs = XRRSizes(dpy, 0, &num_sizes);
240 // add to the menu
241 GString *pResString = g_string_new ("");
242 int i;
243 for (i = 0; i < num_sizes; i ++)
244 {
245 g_string_printf (pResString, "%dx%d", xrrs[i].width, xrrs[i].height);
246 if (i == original_size_id)
247 CD_APPLET_ADD_IN_MENU_WITH_STOCK_AND_DATA (pResString->str, GLDI_ICON_NAME_GO_FORWARD, _on_select_resolution, pResSubMenu, GINT_TO_POINTER (i));
248 else
249 CD_APPLET_ADD_IN_MENU_WITH_DATA (pResString->str, _on_select_resolution, pResSubMenu, GINT_TO_POINTER (i));
250 /*short *rates;
251 int num_rates;
252 rates = XRRRates(dpy, 0, i, &num_rates);
253 for(int j = 0; j < num_rates; j ++) {
254 possible_frequencies[i][j] = rates[j];
255 printf("%4i ", rates[j]); }*/
256 }
257 g_string_free (pResString, TRUE);
258 XRRFreeScreenConfigInfo (conf);
259 }
260 }
261 else
262 cd_warning ("Xrandr extension not available.");
263 #endif
264 #endif
265 CD_APPLET_ON_BUILD_MENU_END
266
267
268 CD_APPLET_ON_MIDDLE_CLICK_BEGIN
269 _cd_action (myConfig.iActionOnMiddleClick);
270 CD_APPLET_ON_MIDDLE_CLICK_END
271
272
_get_desktop_path(void)273 static gchar *_get_desktop_path (void)
274 {
275 gchar *cDesktopDir = cairo_dock_launch_command_sync ("xdg-user-dir DESKTOP");
276 if (cDesktopDir == NULL)
277 cDesktopDir = g_strdup_printf ("%s/Desktop", g_getenv ("HOME"));
278 return cDesktopDir;
279 }
_move_to_desktop(GtkMenuItem * menu_item,GldiModuleInstance * myApplet)280 static void _move_to_desktop (GtkMenuItem *menu_item, GldiModuleInstance *myApplet)
281 {
282 gchar *cDesktopDir = _get_desktop_path ();
283 if (cDesktopDir != NULL)
284 {
285 cairo_dock_launch_command_printf ("mv \"%s\" \"%s\"", NULL, myData.cPendingFile, cDesktopDir);
286 g_free (cDesktopDir);
287 }
288 }
_copy_to_desktop(GtkMenuItem * menu_item,GldiModuleInstance * myApplet)289 static void _copy_to_desktop (GtkMenuItem *menu_item, GldiModuleInstance *myApplet)
290 {
291 gchar *cDesktopDir = _get_desktop_path ();
292 if (cDesktopDir != NULL)
293 {
294 cairo_dock_launch_command_printf ("cp -r \"%s\" \"%s\"", NULL, myData.cPendingFile, cDesktopDir);
295 g_free (cDesktopDir);
296 }
297 }
_link_to_desktop(GtkMenuItem * menu_item,GldiModuleInstance * myApplet)298 static void _link_to_desktop (GtkMenuItem *menu_item, GldiModuleInstance *myApplet)
299 {
300 gchar *cDesktopDir = _get_desktop_path ();
301 if (cDesktopDir != NULL)
302 {
303 cairo_dock_launch_command_printf ("ln -s \"%s\" \"%s\"", NULL, myData.cPendingFile, cDesktopDir);
304 g_free (cDesktopDir);
305 }
306 }
_make_link_to_desktop(GtkMenuItem * menu_item,GldiModuleInstance * myApplet)307 static void _make_link_to_desktop (GtkMenuItem *menu_item, GldiModuleInstance *myApplet)
308 {
309 gchar *cDesktopDir = _get_desktop_path ();
310 if (cDesktopDir != NULL)
311 {
312 gchar *cName = g_path_get_basename (myData.cPendingFile);
313 gchar *cContent = g_strdup_printf ("[Desktop Entry]\n"
314 "Encoding=UTF-8\n"
315 "Name=%s\n"
316 "URL=%s\n"
317 "Icon=file\n"
318 "Type=Link\n",
319 cName, myData.cPendingFile);
320
321 gchar *cLinkPath = g_strdup_printf ("%s/Link to %s", cDesktopDir, cName);
322 g_file_set_contents (cLinkPath,
323 cContent,
324 -1,
325 NULL);
326
327 g_free (cLinkPath);
328 g_free (cContent);
329 g_free (cName);
330 g_free (cDesktopDir);
331 }
332 }
_dl_finished(gpointer data)333 static void _dl_finished (gpointer data)
334 {
335 cd_debug ("DL IS FINISHED");
336 }
_download_to_desktop(GtkMenuItem * menu_item,GldiModuleInstance * myApplet)337 static void _download_to_desktop (GtkMenuItem *menu_item, GldiModuleInstance *myApplet)
338 {
339 gchar *cDesktopDir = _get_desktop_path ();
340 if (cDesktopDir != NULL)
341 {
342 cairo_dock_download_file_async (myData.cPendingFile, NULL, (GFunc)_dl_finished, myApplet);
343 g_free (cDesktopDir);
344 }
345 }
346
347 CD_APPLET_ON_DROP_DATA_BEGIN
348 GtkWidget *pMenu = gldi_menu_new (myIcon);
349 g_free (myData.cPendingFile);
350 myData.cPendingFile = g_strdup (CD_APPLET_RECEIVED_DATA);
351
352 if (*CD_APPLET_RECEIVED_DATA == '/' || strncmp (CD_APPLET_RECEIVED_DATA, "file://", 7)) // fichier local
353 {
354 cairo_dock_add_in_menu_with_stock_and_data (("Move to the Desktop"), GLDI_ICON_NAME_CUT, G_CALLBACK (_move_to_desktop), pMenu, myApplet);
355 cairo_dock_add_in_menu_with_stock_and_data (("Copy to the Desktop"), GLDI_ICON_NAME_COPY, G_CALLBACK (_copy_to_desktop), pMenu, myApplet);
356 cairo_dock_add_in_menu_with_stock_and_data (("Link to the Desktop"), GLDI_ICON_NAME_JUMP_TO, G_CALLBACK (_link_to_desktop), pMenu, myApplet);
357 }
358 else // fichier a telecharger.
359 {
360 cairo_dock_add_in_menu_with_stock_and_data (("Link to the Desktop"), GLDI_ICON_NAME_JUMP_TO, G_CALLBACK (_make_link_to_desktop), pMenu, myApplet);
361 cairo_dock_add_in_menu_with_stock_and_data (("Download onto the Desktop"), GLDI_ICON_NAME_COPY, G_CALLBACK (_download_to_desktop), pMenu, myApplet);
362 }
363 CD_APPLET_POPUP_MENU_ON_MY_ICON (pMenu);
364
365
366 CD_APPLET_ON_DROP_DATA_END
367
368
on_keybinding_pull(const char * keystring,gpointer user_data)369 void on_keybinding_pull (const char *keystring, gpointer user_data)
370 {
371 CD_APPLET_ENTER;
372 _cd_action (myConfig.iActionOnMiddleClick);
373 CD_APPLET_LEAVE();
374 }
375
376
on_show_desktop(GldiModuleInstance * myApplet)377 gboolean on_show_desktop (GldiModuleInstance *myApplet)
378 {
379 CD_APPLET_ENTER;
380 myData.bDesktopVisible = gldi_desktop_is_visible ();
381 cd_debug ("bDesktopVisible <- %d", myData.bDesktopVisible);
382
383 if (myConfig.cVisibleImage)
384 {
385 if (myData.bDesktopVisible || myData.bDeskletsVisible)
386 CD_APPLET_SET_IMAGE_ON_MY_ICON (myConfig.cVisibleImage);
387 else
388 CD_APPLET_SET_IMAGE_ON_MY_ICON (myConfig.cHiddenImage);
389 CD_APPLET_REDRAW_MY_ICON;
390 }
391 CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
392 }
393