~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/trayappletui.c

  • Committer: Balint Reczey
  • Date: 2020-06-11 18:46:02 UTC
  • Revision ID: balint.reczey@canonical.com-20200611184602-2rv1zan3xu723x2u
Moved to git at https://git.launchpad.net/update-notifier

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <glib.h>
2
 
 
3
 
#include "update-notifier.h"
4
 
#include "trayappletui.h"
5
 
 
6
 
void tray_applet_ui_ensure(TrayApplet *ta)
7
 
{
8
 
   g_debug("tray_applet_ui_ensure: %s", ta->name);
9
 
#ifdef HAVE_APP_INDICATOR
10
 
   if (ta->indicator)
11
 
      return;
12
 
   ta->indicator = app_indicator_new (ta->name, ta->name,
13
 
                                      APP_INDICATOR_CATEGORY_SYSTEM_SERVICES);
14
 
#else
15
 
   if (ta->tray_icon)
16
 
      return;
17
 
   ta->tray_icon = gtk_status_icon_new_from_icon_name (ta->name);
18
 
   gtk_status_icon_set_visible (ta->tray_icon, FALSE);
19
 
#endif
20
 
}
21
 
 
22
 
void tray_applet_ui_set_icon(TrayApplet *ta, const char *icon_name)
23
 
{
24
 
#ifdef HAVE_APP_INDICATOR
25
 
   return app_indicator_set_icon(ta->indicator, icon_name);
26
 
#else
27
 
   return gtk_status_icon_set_from_icon_name(ta->tray_icon, icon_name);
28
 
#endif
29
 
}
30
 
 
31
 
// visible
32
 
gboolean tray_applet_ui_get_visible(TrayApplet *ta)
33
 
{
34
 
#ifdef HAVE_APP_INDICATOR
35
 
   if (!ta->indicator)
36
 
      return FALSE;
37
 
   return app_indicator_get_status(ta->indicator) != APP_INDICATOR_STATUS_PASSIVE;
38
 
#else
39
 
   if (!ta->tray_icon)
40
 
      return FALSE;
41
 
   return gtk_status_icon_get_visible(ta->tray_icon);
42
 
#endif
43
 
}
44
 
 
45
 
void tray_applet_ui_set_visible(TrayApplet *ta, gboolean visible)
46
 
{
47
 
#ifdef HAVE_APP_INDICATOR
48
 
   if (visible)
49
 
      app_indicator_set_status(ta->indicator, APP_INDICATOR_STATUS_ACTIVE);
50
 
   else
51
 
      app_indicator_set_status(ta->indicator, APP_INDICATOR_STATUS_PASSIVE);  
52
 
#else
53
 
   gtk_status_icon_set_visible(ta->tray_icon, visible);
54
 
#endif
55
 
}
56
 
 
57
 
// tooltips are only support for GtkStatusIcon, so with the indicator
58
 
// we need to simulate this with a menu
59
 
void tray_applet_ui_set_tooltip_text(TrayApplet *ta, const char *text)
60
 
{
61
 
#ifdef HAVE_APP_INDICATOR
62
 
   // there are no tooltips so we show them in the menu as inactive entries
63
 
   if (!ta->menu) {
64
 
      ta->menu = gtk_menu_new();
65
 
   }
66
 
   // clear out any previous fake tooltip
67
 
   GList *l = gtk_container_get_children(GTK_CONTAINER(ta->menu));
68
 
   if (l && l->data && g_object_get_data(G_OBJECT(l->data), "fake-tooltip")) {
69
 
      // the tooltip itself
70
 
      gtk_container_remove(GTK_CONTAINER(ta->menu), l->data);
71
 
      // and the seperator
72
 
      if (g_list_next(l))
73
 
         gtk_container_remove(GTK_CONTAINER(ta->menu), g_list_next(l)->data);
74
 
   }
75
 
   g_list_free(l);
76
 
 
77
 
   // when we simluate the tooltip we may get really long lines, those
78
 
   // need to be split up. in order to do that in a unicode friendly
79
 
   // way we ask pango to do the line wrap for us
80
 
   GtkWidget *label = gtk_label_new(text);
81
 
   g_object_ref_sink(label);
82
 
   gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
83
 
   PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(label));
84
 
   // use 300px max for a line by default
85
 
   static const gint MAX_LINE_SIZE_IN_PIXEL = 300;
86
 
   pango_layout_set_width(layout, 
87
 
                          pango_units_from_double(MAX_LINE_SIZE_IN_PIXEL));
88
 
 
89
 
   // now go over the lines that pango identified and manually add \n
90
 
   GSList *lines = pango_layout_get_lines_readonly(layout);
91
 
   GString *new_text = g_string_new("");
92
 
   while (lines != NULL) {
93
 
      new_text = g_string_append_len(new_text, 
94
 
                                     text+((PangoLayoutLine*)lines->data)->start_index,
95
 
                                     ((PangoLayoutLine*)lines->data)->length);
96
 
      lines = g_slist_next(lines);
97
 
      // avoid final newline
98
 
      if (lines != NULL)
99
 
         new_text = g_string_append(new_text, "\n");
100
 
   }
101
 
 
102
 
   // add a new one
103
 
   GtkWidget *menu_item = gtk_menu_item_new_with_label(new_text->str);
104
 
   gtk_menu_shell_insert(GTK_MENU_SHELL(ta->menu), menu_item, 0);
105
 
   g_object_set_data(G_OBJECT(menu_item), "fake-tooltip", "1");
106
 
   gtk_widget_set_sensitive(menu_item, FALSE);
107
 
   gtk_widget_show(menu_item);
108
 
   menu_item = gtk_separator_menu_item_new();
109
 
   gtk_menu_shell_insert(GTK_MENU_SHELL(ta->menu), menu_item, 1);
110
 
   gtk_widget_show(menu_item);
111
 
 
112
 
   // and free
113
 
   g_slist_free(lines);
114
 
   g_string_free(new_text, TRUE);
115
 
   g_object_unref(label);
116
 
#else
117
 
   gtk_status_icon_set_tooltip_text (ta->tray_icon,  text);
118
 
#endif
119
 
}
120
 
 
121
 
#ifndef HAVE_APP_INDICATOR
122
 
// internal helper for the tray_applet_ui_set_menu call
123
 
static gboolean
124
 
popup_menu_for_gtk_status_icon_cb (GtkStatusIcon *status_icon,
125
 
                                   guint          button,
126
 
                                   guint          activate_time,
127
 
                                   TrayApplet     *ta)
128
 
{
129
 
   gtk_menu_set_screen (GTK_MENU (ta->menu),
130
 
                        gtk_status_icon_get_screen(ta->tray_icon));
131
 
   gtk_menu_popup (GTK_MENU (ta->menu), NULL, NULL, 
132
 
                   gtk_status_icon_position_menu, ta->tray_icon,
133
 
                   button, activate_time);
134
 
   return TRUE;
135
 
}
136
 
#endif
137
 
 
138
 
// add a menu to the applet, on the indicators this is left-click,
139
 
// on the GtkStatusBar its right click
140
 
void tray_applet_ui_set_menu(TrayApplet *ta, GtkWidget *menu)
141
 
{
142
 
   ta->menu = menu;
143
 
#ifdef HAVE_APP_INDICATOR
144
 
   app_indicator_set_menu(ta->indicator, GTK_MENU(ta->menu));
145
 
#else
146
 
   g_signal_connect (G_OBJECT(ta->tray_icon),
147
 
                     "popup-menu",
148
 
                     G_CALLBACK (popup_menu_for_gtk_status_icon_cb),
149
 
                     ta);
150
 
#endif
151
 
   
152
 
 
153
 
}
154
 
 
155
 
 
156
 
void tray_applet_ui_set_single_action(TrayApplet *ta, 
157
 
                                      const char *label,
158
 
                                      GCallback callback,
159
 
                                      void *data)
160
 
{
161
 
#ifdef HAVE_APP_INDICATOR
162
 
   GtkWidget *menu = gtk_menu_new();
163
 
   GtkWidget *menu_item = gtk_menu_item_new_with_label(label);
164
 
      g_signal_connect (G_OBJECT(menu_item),
165
 
                        "activate",
166
 
                        G_CALLBACK(callback),
167
 
                        data);
168
 
   gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
169
 
   gtk_widget_show_all(menu);
170
 
   app_indicator_set_menu(ta->indicator, GTK_MENU(menu));
171
 
#else
172
 
   tray_applet_ui_set_tooltip_text (ta, label);
173
 
   g_signal_connect (G_OBJECT(ta->tray_icon),
174
 
                     "activate",
175
 
                     callback,
176
 
                     data);
177
 
#endif
178
 
}
179
 
 
180
 
void tray_applet_ui_set_data(TrayApplet *ta, const char *key, void *data)
181
 
{
182
 
#ifdef HAVE_APP_INDICATOR
183
 
   g_object_set_data(G_OBJECT(ta->indicator), key, data);
184
 
#else
185
 
   g_object_set_data(G_OBJECT(ta->tray_icon), key, data);
186
 
#endif
187
 
}
188
 
 
189
 
void* tray_applet_ui_get_data(TrayApplet *ta, const char *key)
190
 
{
191
 
#ifdef HAVE_APP_INDICATOR
192
 
   return g_object_get_data(G_OBJECT(ta->indicator), key);
193
 
#else
194
 
   return g_object_get_data(G_OBJECT(ta->tray_icon), key);
195
 
#endif
196
 
}
197
 
 
198
 
void tray_applet_ui_destroy(TrayApplet *ta)
199
 
{
200
 
   g_debug("tray_applet_ui_destroy: %s", ta->name);
201
 
#ifdef HAVE_APP_INDICATOR
202
 
   g_clear_object(&ta->indicator);
203
 
#else
204
 
   g_clear_object(&ta->tray_icon);
205
 
#endif
206
 
}