2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
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.
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/>.
24
#include "applet-struct.h"
25
#include "applet-item.h"
26
#include "applet-draw.h"
27
#include "applet-notifications.h"
29
//\___________ 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.
31
static void _get_x_y (Icon *pIcon, GldiContainer *pContainer, int *x, int *y)
33
if (pContainer->bIsHorizontal)
35
*x = pContainer->iWindowPositionX + pIcon->fDrawX + pIcon->fWidth * pIcon->fScale/2;
36
*y = pContainer->iWindowPositionY + (pContainer->bDirectionUp ? 0 : pContainer->iHeight);
40
*x = pContainer->iWindowPositionY + (pContainer->bDirectionUp ? 0 : pContainer->iHeight);
41
*y = pContainer->iWindowPositionX + pIcon->fDrawX + pIcon->fWidth * pIcon->fScale/2;
43
//g_print ("click position : %d;%d\n", *x, *y);
45
static inline gboolean _emit_click (CDStatusNotifierItem *pItem, Icon *pIcon, GldiContainer *pContainer, const gchar *cSignal)
48
_get_x_y (pIcon, pContainer, &x, &y);
50
GError *erreur = NULL;
51
dbus_g_proxy_call (pItem->pProxy, cSignal, &erreur,
58
//g_print ("method %s failed (%s)\n", cSignal, erreur->message);
59
g_error_free (erreur);
65
static inline CDStatusNotifierItem *_get_item (Icon *pClickedIcon, GldiContainer *pClickedContainer)
67
CDStatusNotifierItem *pItem = NULL;
68
if (myConfig.bCompactMode)
70
if (pClickedIcon == myIcon) // clic sur la bonne icone.
72
pItem = cd_satus_notifier_find_item_from_coord ();
77
if ((myIcon->pSubDock != NULL && pClickedContainer == CAIRO_CONTAINER (myIcon->pSubDock)) ||
78
(myDesklet && pClickedContainer == myContainer)) // clic sur le bon container.
80
pItem = cd_satus_notifier_get_item_from_icon (pClickedIcon);
87
static gboolean _popup_menu (CDStatusNotifierItem *pItem, Icon *pIcon, GldiContainer *pContainer)
91
cd_satus_notifier_build_item_dbusmenu (pItem);
92
if (pItem->pMenu != NULL)
94
gldi_menu_popup (GTK_WIDGET (pItem->pMenu));
98
if (!r) // no menu available, send the corresponding action
100
r = _emit_click (pItem, pIcon, pContainer, "ContextMenu");
103
if (!r) // no luck, try to fallback on 'activate()'
105
r = _emit_click (pItem, pIcon, pContainer, "Activate");
111
CD_APPLET_ON_CLICK_BEGIN
112
CDStatusNotifierItem *pItem = _get_item (CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER);
113
//g_print ("click on item '%s'\n", pItem?pItem->cService:"none");
116
// Ubuntu-like: show the menu on left click as the sole action (right-click = usual Cairo-Dock menu).
117
if (myConfig.bMenuOnLeftClick || pItem->bItemIsMenu) // if bItemIsMenu: "The item only support the context menu, the visualization should prefer sending ContextMenu() instead of Activate()"
119
_popup_menu (pItem, CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER);
121
else // KDE-like: activate the item on left click, and show its menu on right-click.
124
r = _emit_click (pItem, CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER, "Activate");
128
if (pItem->cId != NULL)
130
/// TODO: try to get the icon in the taskbar, because launch the command doesn't raise the window if it was already visible (but it does pop up it if it was hidden, usually).
131
cairo_dock_launch_command (pItem->cId); // try to launch the application because generally this click shows its item's window.
136
CD_APPLET_ON_CLICK_END
139
CD_APPLET_ON_MIDDLE_CLICK_BEGIN
140
CDStatusNotifierItem *pItem = _get_item (CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER);
143
_emit_click (pItem, CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER, "SecondaryActivate");
145
CD_APPLET_ON_MIDDLE_CLICK_END
148
CD_APPLET_ON_SCROLL_BEGIN
149
CDStatusNotifierItem *pItem = _get_item (CD_APPLET_CLICKED_ICON, CD_APPLET_CLICKED_CONTAINER);
152
GError *erreur = NULL;
153
dbus_g_proxy_call (pItem->pProxy, "Scroll", &erreur,
154
G_TYPE_INT, CD_APPLET_SCROLL_UP ? +1 : -1,
155
G_TYPE_STRING, "vertical",
160
//g_print ("method %s failed (%s)\n", "Scroll", erreur->message);
161
g_error_free (erreur);
164
CD_APPLET_ON_SCROLL_END
167
//\___________ 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.
168
/*CD_APPLET_ON_BUILD_MENU_BEGIN
170
CD_APPLET_ON_BUILD_MENU_END*/
173
gboolean cd_status_notifier_on_right_click (GldiModuleInstance *myApplet, Icon *pClickedIcon, GldiContainer *pClickedContainer, GtkWidget *pAppletMenu, gboolean *bDiscardMenu)
175
if (pClickedIcon == NULL || myConfig.bMenuOnLeftClick)
176
return GLDI_NOTIFICATION_LET_PASS;
179
CDStatusNotifierItem *pItem = _get_item (pClickedIcon, pClickedContainer);
182
_popup_menu (pItem, pClickedIcon, pClickedContainer);
184
*bDiscardMenu = TRUE;
185
CD_APPLET_LEAVE (GLDI_NOTIFICATION_INTERCEPT);
187
CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
191
/*static gboolean _popup_tooltip (Icon *pIcon)
193
CDStatusNotifierItem *pItemData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
194
if (pItemData != NULL && pItemData->pToolTip != NULL)
196
myDialogsParam.dialogTextDescription.bUseMarkup = TRUE;
197
//g_print ("pItemData->pToolTip->cMessage : %s\n", pItemData->pToolTip->cMessage);
198
gchar *cText = g_strdup_printf ("<b>%s</b>\n%s", pItemData->pToolTip->cTitle, pItemData->pToolTip->cMessage);
199
gchar *cIconPath = NULL;
200
if (pItemData->pToolTip->cIconName)
202
cIconPath = cairo_dock_search_icon_s_path (pItemData->pToolTip->cIconName, cairo_dock_search_icon_size (GTK_ICON_SIZE_DND)); // dialog
205
gldi_dialog_show_temporary_with_icon (cText, pIcon, CAIRO_CONTAINER (myIcon->pSubDock), 3000, cIconPath ? cIconPath : "same icon");
207
myDialogsParam.dialogTextDescription.bUseMarkup = FALSE;
208
pItemData->iSidPopupTooltip = 0;
212
gboolean cd_status_notifier_on_enter_icon (GldiModuleInstance *myApplet, Icon *pIcon, CairoDock *pDock, gboolean *bStartAnimation)
214
if (pDock == myIcon->pSubDock && myIcon->pSubDock != NULL)
218
for (ic = myData.pIcons; ic != NULL; ic = ic->next)
221
CDStatusNotifierItem *pItemData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
222
if (pItemData && pItemData->iSidPopupTooltip != 0)
224
g_source_remove (pItemData->iSidPopupTooltip);
225
pItemData->iSidPopupTooltip = 0;
227
gldi_dialogs_remove_on_icon (icon);
232
CDStatusNotifierItem *pItemData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
233
pItemData->iSidPopupTooltip = g_timeout_add (600, (GSourceFunc) _popup_tooltip, pIcon);
236
return GLDI_NOTIFICATION_LET_PASS;
241
gboolean on_mouse_moved (GldiModuleInstance *myApplet, GldiContainer *pContainer, gboolean *bStartAnimation)
244
if (! myIcon->bPointed || ! pContainer->bInside)
245
CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
247
CDStatusNotifierItem *pItem = cd_satus_notifier_find_item_from_coord ();
249
if (pItem != myData.pCurrentlyHoveredItem)
251
myData.pCurrentlyHoveredItem = pItem;
252
myData.fDesktopNameAlpha = 0.;
254
CD_APPLET_SET_NAME_FOR_MY_ICON (NULL);
257
GString *sTitle = g_string_new ("");
258
if (pItem->cTitle && *pItem->cTitle != '\0')
260
gunichar wc = g_utf8_get_char (pItem->cTitle);
261
g_string_append_unichar (sTitle, g_unichar_toupper (wc)); // force the first char to upper
262
g_string_append (sTitle, g_utf8_next_char (pItem->cTitle));
264
if (pItem->cLabel && *pItem->cLabel != '\0')
265
g_string_append_printf (sTitle, "%s%s", sTitle->len == 0 ? "" : " | ", pItem->cLabel);
266
if (pItem->cAccessibleDesc && *pItem->cAccessibleDesc != '\0')
267
g_string_append_printf (sTitle, "%s%s", sTitle->len == 0 ? "" : " | ", pItem->cAccessibleDesc);
268
if (sTitle->len == 0) // don't display an empty label
271
* Let's display the ID if we really have nothing, just to avoid
272
* having a gap (no label), inconsistency (only on some items),
273
* and an item that you can't guess until you click on it.
274
* This is a workaround for applications that don't provide a
275
* label yet, which should hopefully become rare!
276
* Since the ID is sometimes too ugly (e.g: dropbox-xxxx,
277
* emesene-xxxxxxxxx, etc.), we cut the string.
279
gchar *cName = cairo_dock_cut_string (pItem->cId, 12);
280
CD_APPLET_SET_NAME_FOR_MY_ICON (cName);
284
CD_APPLET_SET_NAME_FOR_MY_ICON (sTitle->str);
285
g_string_free (sTitle, TRUE);
288
CAIRO_DOCK_REDRAW_MY_CONTAINER;
290
*bStartAnimation = TRUE;
292
CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
295
gboolean on_update_desklet (GldiModuleInstance *myApplet, GldiContainer *pContainer, gboolean *bContinueAnimation)
298
if (! myIcon->bPointed || ! pContainer->bInside)
300
myData.fDesktopNameAlpha -= .07;
301
if (myData.fDesktopNameAlpha < .01)
302
myData.fDesktopNameAlpha = 0;
303
if (myData.fDesktopNameAlpha != 0)
304
*bContinueAnimation = TRUE;
308
myData.fDesktopNameAlpha += .07;
309
if (myData.fDesktopNameAlpha > .99)
310
myData.fDesktopNameAlpha = 1;
311
if (myData.fDesktopNameAlpha != 1)
312
*bContinueAnimation = TRUE;
314
CAIRO_DOCK_REDRAW_MY_CONTAINER;
315
CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
318
gboolean on_render_desklet (GldiModuleInstance *myApplet, GldiContainer *pContainer, cairo_t *pCairoContext)
321
int x, y; // text center (middle of the icon).
322
x = myIcon->fDrawX + myIcon->fWidth * myIcon->fScale / 2;
323
y = myIcon->fDrawY + myIcon->fHeight * myIcon->fScale / 2;
324
if (x - myIcon->label.iWidth/2 < 0)
326
x -= myIcon->label.iWidth/2;
328
if (pCairoContext != NULL)
330
if (myIcon->label.pSurface != NULL)
332
/**cairo_save (pCairoContext);
333
cairo_translate (pCairoContext, x, y);
334
cairo_set_source_surface (pCairoContext, myIcon->pTextBuffer, - myIcon->iTextWidth/2, - myIcon->iTextHeight/2);
335
cairo_paint_with_alpha (pCairoContext, myData.fDesktopNameAlpha);
336
cairo_restore (pCairoContext);*/
337
cairo_dock_apply_image_buffer_surface_with_offset (&myIcon->label, pCairoContext,
338
- myIcon->label.iWidth/2, - myIcon->label.iHeight/2, myData.fDesktopNameAlpha);
343
if (myIcon->label.iTexture != 0)
346
glTranslatef (-myContainer->iWidth/2, -myContainer->iHeight/2, -myContainer->iHeight*(sqrt(3)/2));
347
/**glTranslatef (x - ((myIcon->iTextWidth & 1) ? 0.5 : 0.),
348
y - ((myIcon->iTextHeight & 1) ? 0.5 : 0.),
350
cairo_dock_draw_texture_with_alpha (myIcon->iLabelTexture, myIcon->iTextWidth, myIcon->iTextHeight, myData.fDesktopNameAlpha);*/
351
_cairo_dock_enable_texture ();
352
_cairo_dock_set_blend_alpha ();
353
_cairo_dock_set_alpha (myData.fDesktopNameAlpha);
354
cairo_dock_apply_image_buffer_texture_with_offset (&myIcon->label,
355
x - ((myIcon->label.iWidth & 1) ? 0.5 : 0.),
356
y - ((myIcon->label.iHeight & 1) ? 0.5 : 0.));
357
_cairo_dock_disable_texture ();
361
CD_APPLET_LEAVE (GLDI_NOTIFICATION_LET_PASS);
364
gboolean on_leave_desklet (GldiModuleInstance *myApplet, GldiContainer *pContainer, gboolean *bStartAnimation)
366
*bStartAnimation = TRUE;
367
myData.pCurrentlyHoveredItem = NULL;
368
return GLDI_NOTIFICATION_LET_PASS;