Package list xapp / ad85cb7
New upstream version 1.8.7 Norbert Preining 1 year, 3 months ago
15 changed file(s) with 270 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
0 xapp (1.8.7) ulyana; urgency=medium
1
2 [ Clement Lefebvre ]
3 * Update docs
4
5 [ Michael Webster ]
6 * xapp-status-icon.c: Get rid of the dead 'shadow' region around menus, as they can interfere with clicking on the icon to close the menu.
7 * xapp-status-icon: Add new properties for menu/button state handling and one for metadata (miscellaneous info to help define behavior in the status applets).
8 * xapp-sn-watcher: Set status icon metadata for appindicator icons, to inform the applet to highlight/toggle the panel icon with either button click when opening the menu.
9 * mate-xapp-status-applet.py: Use new properties to sync button toggle state with the menu state.
10 * test-scripts: Update some scripts to demonstrate new property use.
11 * sn-item: Remove support for XAyatanaLabel.
12 * xapp-sn-watcher: Update clear the registration list before freeing the table of registered items.
13
14 -- Clement Lefebvre <root@linuxmint.com> Sat, 06 Jun 2020 14:29:58 +0100
15
016 xapp (1.8.6) ulyana; urgency=medium
117
218 [ Clement Lefebvre ]
110110 <span class="returnvalue">void</span>
111111 </td>
112112 <td class="function_name">
113 <a class="link" href="XAppStatusIcon.html#xapp-status-icon-popup-menu" title="xapp_status_icon_popup_menu ()">xapp_status_icon_popup_menu</a> <span class="c_punctuation">()</span>
114 </td>
115 </tr>
116 <tr>
117 <td class="function_type">
118 <span class="returnvalue">void</span>
119 </td>
120 <td class="function_name">
113121 <a class="link" href="XAppStatusIcon.html#xapp-status-icon-set-primary-menu" title="xapp_status_icon_set_primary_menu ()">xapp_status_icon_set_primary_menu</a> <span class="c_punctuation">()</span>
114122 </td>
115123 </tr>
489497 <p> the current visibility state.</p>
490498 </div>
491499 <p class="since">Since: 1.8.5</p>
500 </div>
501 <hr>
502 <div class="refsect2">
503 <a name="xapp-status-icon-popup-menu"></a><h3>xapp_status_icon_popup_menu ()</h3>
504 <pre class="programlisting"><span class="returnvalue">void</span>
505 xapp_status_icon_popup_menu (<em class="parameter"><code><a class="link" href="XAppStatusIcon.html" title="XAppStatusIcon"><span class="type">XAppStatusIcon</span></a> *icon</code></em>,
506 <em class="parameter"><code><a href="../gtk3/GtkMenu.html#GtkMenu-struct"><span class="type">GtkMenu</span></a> *menu</code></em>,
507 <em class="parameter"><code><a href="../glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> x</code></em>,
508 <em class="parameter"><code><a href="../glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> y</code></em>,
509 <em class="parameter"><code><a href="../glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> button</code></em>,
510 <em class="parameter"><code><a href="../glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> _time</code></em>,
511 <em class="parameter"><code><a href="../glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> panel_position</code></em>);</pre>
512 <p>Pop up <em class="parameter"><code>menu</code></em>
513 using the positioning arguments. These arguments should be
514 those provided by a <a class="link" href="XAppStatusIcon.html#XAppStatusIcon-button-release-event" title="The “button-release-event” signal"><span class="type">“button-release-event”</span></a>.</p>
515 <div class="refsect3">
516 <a name="xapp-status-icon-popup-menu.parameters"></a><h4>Parameters</h4>
517 <div class="informaltable"><table class="informaltable" width="100%" border="0">
518 <colgroup>
519 <col width="150px" class="parameters_name">
520 <col class="parameters_description">
521 <col width="200px" class="parameters_annotations">
522 </colgroup>
523 <tbody>
524 <tr>
525 <td class="parameter_name"><p>icon</p></td>
526 <td class="parameter_description"><p>an <a class="link" href="XAppStatusIcon.html" title="XAppStatusIcon"><span class="type">XAppStatusIcon</span></a></p></td>
527 <td class="parameter_annotations"> </td>
528 </tr>
529 <tr>
530 <td class="parameter_name"><p>menu</p></td>
531 <td class="parameter_description"><p>A <a href="../gtk3/GtkMenu.html#GtkMenu-struct"><span class="type">GtkMenu</span></a> to display when the primary mouse button is released. </p></td>
532 <td class="parameter_annotations"><span class="annotation">[<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>]</span></td>
533 </tr>
534 <tr>
535 <td class="parameter_name"><p>x</p></td>
536 <td class="parameter_description"><p>The x anchor position for the menu.</p></td>
537 <td class="parameter_annotations"> </td>
538 </tr>
539 <tr>
540 <td class="parameter_name"><p>y</p></td>
541 <td class="parameter_description"><p>The y anchor position for the menu.</p></td>
542 <td class="parameter_annotations"> </td>
543 </tr>
544 <tr>
545 <td class="parameter_name"><p>button</p></td>
546 <td class="parameter_description"><p>The button used to initiate this action (or 0)</p></td>
547 <td class="parameter_annotations"> </td>
548 </tr>
549 <tr>
550 <td class="parameter_name"><p>_time</p></td>
551 <td class="parameter_description"><p>The event time (or 0)</p></td>
552 <td class="parameter_annotations"> </td>
553 </tr>
554 <tr>
555 <td class="parameter_name"><p>panel_position</p></td>
556 <td class="parameter_description"><p>The <a href="../gtk3/gtk3-Standard-Enumerations.html#GtkPositionType"><span class="type">GtkPositionType</span></a> for the position of the icon.</p></td>
557 <td class="parameter_annotations"> </td>
558 </tr>
559 </tbody>
560 </table></div>
561 </div>
562 <p class="since">Since: 1.8.6</p>
492563 </div>
493564 <hr>
494565 <div class="refsect2">
630630 </dt>
631631 <dd></dd>
632632 <dt>
633 <a class="link" href="XAppStatusIcon.html#xapp-status-icon-popup-menu" title="xapp_status_icon_popup_menu ()">xapp_status_icon_popup_menu</a>, function in <a class="link" href="XAppStatusIcon.html" title="XAppStatusIcon">XAppStatusIcon</a>
634 </dt>
635 <dd></dd>
636 <dt>
633637 <a class="link" href="XAppStatusIcon.html#xapp-status-icon-set-icon-name" title="xapp_status_icon_set_icon_name ()">xapp_status_icon_set_icon_name</a>, function in <a class="link" href="XAppStatusIcon.html" title="XAppStatusIcon">XAppStatusIcon</a>
634638 </dt>
635639 <dd></dd>
1414 <div>
1515 <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">XApp Reference Manual</p></th></tr></table></div>
1616 <div><p class="releaseinfo">
17 xapp 1.8.5
17 xapp 1.8.6
1818 </p></div>
1919 </div>
2020 <hr>
111111 <keyword type="function" name="xapp_status_icon_set_label ()" link="XAppStatusIcon.html#xapp-status-icon-set-label" since="1.6"/>
112112 <keyword type="function" name="xapp_status_icon_set_visible ()" link="XAppStatusIcon.html#xapp-status-icon-set-visible" since="1.6"/>
113113 <keyword type="function" name="xapp_status_icon_get_visible ()" link="XAppStatusIcon.html#xapp-status-icon-get-visible" since="1.8.5"/>
114 <keyword type="function" name="xapp_status_icon_popup_menu ()" link="XAppStatusIcon.html#xapp-status-icon-popup-menu" since="1.8.6"/>
114115 <keyword type="function" name="xapp_status_icon_set_primary_menu ()" link="XAppStatusIcon.html#xapp-status-icon-set-primary-menu" since="1.6"/>
115116 <keyword type="function" name="xapp_status_icon_get_primary_menu ()" link="XAppStatusIcon.html#xapp-status-icon-get-primary-menu" since="1.6"/>
116117 <keyword type="function" name="xapp_status_icon_set_secondary_menu ()" link="XAppStatusIcon.html#xapp-status-icon-set-secondary-menu" since="1.6"/>
2727 <property type='s' name='Label' access='read'/>
2828 <property type='b' name='Visible' access='read'/>
2929 <property type='i' name='IconSize' access='readwrite'/>
30 <property type='b' name='PrimaryMenuIsOpen' access='read'/>
31 <property type='b' name='SecondaryMenuIsOpen' access='read'/>
32 <property type='s' name='Metadata' access='read' />
3033 </interface>
3134 </node>
8383 gchar *label;
8484 gboolean visible;
8585 gint icon_size;
86 gchar *metadata;
8687
8788 guint owner_id;
8889 guint listener_id;
254255 }
255256
256257 static void
258 primary_menu_unmapped (GtkWidget *widget,
259 gpointer user_data)
260 {
261 g_return_if_fail (XAPP_IS_STATUS_ICON (user_data));
262 XAppStatusIcon *icon = XAPP_STATUS_ICON (user_data);
263
264 g_debug ("XAppStatusIcon: Primary menu unmapped");
265
266 if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
267 {
268 xapp_status_icon_interface_set_primary_menu_is_open (icon->priv->skeleton, FALSE);
269 }
270
271 g_signal_handlers_disconnect_by_func (widget, primary_menu_unmapped, icon);
272 }
273
274 static void
275 secondary_menu_unmapped (GtkWidget *widget,
276 gpointer user_data)
277 {
278 g_return_if_fail (XAPP_IS_STATUS_ICON (user_data));
279 XAppStatusIcon *icon = XAPP_STATUS_ICON (user_data);
280
281 g_debug ("XAppStatusIcon: Secondary menu unmapped");
282
283 if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
284 {
285 xapp_status_icon_interface_set_secondary_menu_is_open (icon->priv->skeleton, FALSE);
286 }
287
288 g_signal_handlers_disconnect_by_func (widget, secondary_menu_unmapped, icon);
289 }
290
291 static void
257292 popup_menu (XAppStatusIcon *self,
258293 GtkMenu *menu,
259294 gint x,
268303 GdkGravity rect_anchor, menu_anchor;
269304
270305 g_debug ("XAppStatusIcon: Popup menu on behalf of application");
306
307 if (!gtk_widget_get_realized (GTK_WIDGET (menu)))
308 {
309 GtkWidget *toplevel;
310 GtkStyleContext *context;
311
312 gtk_widget_realize (GTK_WIDGET (menu));
313 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu));
314 context = gtk_widget_get_style_context (toplevel);
315
316 /* GtkMenu uses a GtkWindow as its toplevel that is explicitly set to
317 * be client-decorated, and applies shadows outside the visible part of
318 * the menu. They interfere with clicks on the icon while the menu is open,
319 * as the invisible part takes the events instead (and this ends up doing
320 * nothing). It makes the menu a littly ugly, so here's a new class name we
321 * can use for themes to restore things bit if we want. Just avoid shadows. */
322 gtk_style_context_remove_class (context, "csd");
323 gtk_style_context_add_class (context, "xapp-status-icon-menu-window");
324 }
325
326 if (button == GDK_BUTTON_PRIMARY)
327 {
328 if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
329 {
330 xapp_status_icon_interface_set_primary_menu_is_open (self->priv->skeleton, TRUE);
331 }
332
333 g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)),
334 "unmap",
335 G_CALLBACK (primary_menu_unmapped),
336 self);
337 }
338 else
339 if (button == GDK_BUTTON_SECONDARY)
340 {
341 if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
342 {
343 xapp_status_icon_interface_set_secondary_menu_is_open (self->priv->skeleton, TRUE);
344 }
345
346 g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)),
347 "unmap",
348 G_CALLBACK (secondary_menu_unmapped),
349 self);
350 }
271351
272352 event = synthesize_event (self,
273353 x, y, button, _time, panel_position,
654734 "icon-name", priv->icon_name,
655735 "tooltip-text", priv->tooltip_text,
656736 "visible", priv->visible,
737 "metadata", priv->metadata,
657738 NULL);
658739
659740 g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (priv->skeleton));
17231804 }
17241805
17251806 /**
1807 * xapp_status_icon_set_metadata:
1808 * @icon: an #XAppStatusIcon
1809 * @metadata: (nullable): A json-formatted string of key:values.
1810 *
1811 * Sets metadata to pass to the icon proxy for an applet's use. Right now this is only so
1812 * xapp-sn-watcher can tell the applets when the icon is originating from appindicator so panel
1813 * button 'highlighting' can behave correctly.
1814 *
1815 * Since: 1.8.7
1816 */
1817 void
1818 xapp_status_icon_set_metadata (XAppStatusIcon *icon,
1819 const gchar *metadata)
1820 {
1821 g_return_if_fail (XAPP_IS_STATUS_ICON (icon));
1822 gchar *old_meta;
1823
1824 g_debug ("XAppStatusIcon set_metadata: '%s'", metadata);
1825
1826 if (g_strcmp0 (metadata, icon->priv->metadata) == 0)
1827 {
1828 return;
1829 }
1830
1831 old_meta = icon->priv->metadata;
1832 icon->priv->metadata = g_strdup (metadata);
1833 g_free (old_meta);
1834
1835 if (icon->priv->skeleton)
1836 {
1837 xapp_status_icon_interface_set_metadata (icon->priv->skeleton, metadata);
1838 }
1839 }
1840
1841 /**
17261842 * xapp_status_icon_any_monitors:
17271843 *
17281844 * Looks for the existence of any active #XAppStatusIconMonitors on the bus.
6565 void xapp_status_icon_set_secondary_menu (XAppStatusIcon *icon, GtkMenu *menu);
6666 GtkWidget *xapp_status_icon_get_secondary_menu (XAppStatusIcon *icon);
6767 XAppStatusIconState xapp_status_icon_get_state (XAppStatusIcon *icon);
68 void xapp_status_icon_set_metadata (XAppStatusIcon *icon,
69 const gchar *metadata);
6870
6971 /* static */
7072 gboolean xapp_status_icon_any_monitors (void);
00 project('xapp',
11 'c',
2 version : '1.8.6'
2 version : '1.8.7'
33 )
44
55 gnome = import('gnome')
11
22 import locale
33 import gettext
4 import json
45 import os
56 import sys
67 import setproctitle
5556
5657 class StatusWidget(Gtk.ToggleButton):
5758 def __init__(self, icon, orientation, size):
58 super(Gtk.Button, self).__init__()
59 super(Gtk.ToggleButton, self).__init__()
5960 self.theme = Gtk.IconTheme.get_default()
6061 self.orientation = orientation
6162 self.size = size
9293 self.proxy.bind_property("tooltip-text", self, "tooltip-markup", flags)
9394 self.proxy.bind_property("visible", self, "visible", flags)
9495
96 self.proxy.connect("notify::primary-menu-is-open", self.menu_state_changed)
97 self.proxy.connect("notify::secondary-menu-is-open", self.menu_state_changed)
98
99 self.highlight_both_menus = False
100
101 if self.proxy.props.metadata not in ("", None):
102 try:
103 meta = json.loads(self.proxy.props.metadata)
104 if meta["highlight-both-menus"]:
105 self.highlight_both_menus = True
106 except json.JSONDecodeError as e:
107 print("Could not read metadata: %s" % e)
108
95109 self.proxy.connect("notify::icon-name", self._on_icon_name_changed)
96110
97111 self.in_widget = False
98112 self.plain_surface = None
99113 self.saturated_surface = None
114
115 self.menu_opened = False
100116
101117 self.connect("button-press-event", self.on_button_press)
102118 self.connect("button-release-event", self.on_button_release)
174190 self.image.set_pixel_size(self.size - ICON_SIZE_REDUCTION)
175191 self.image.set_from_icon_name("image-missing", Gtk.IconSize.MENU)
176192
193 def menu_state_changed(self, proxy, pspec, data=None):
194 if pspec.name == "primary-menu-is-open":
195 prop = proxy.props.primary_menu_is_open
196 else:
197 prop = proxy.props.secondary_menu_is_open
198
199 if not self.menu_opened or prop == False:
200 self.set_active(False)
201 return
202
203 self.set_active(prop)
204 self.menu_opened = False
205
177206 # TODO?
178207 def on_enter_notify(self, widget, event):
179208 self.in_widget = True
186215 return Gdk.EVENT_PROPAGATE
187216 # /TODO
188217
189 def after_release_idle(self, data=None):
190 self.set_active(False)
191
192 return GLib.SOURCE_REMOVE
193
194218 def on_button_press(self, widget, event):
219 self.menu_opened = False
220
195221 # If the user does ctrl->right-click, open the applet's about menu
196222 # instead of sending to the app.
197223 if event.state & Gdk.ModifierType.CONTROL_MASK and event.button == Gdk.BUTTON_SECONDARY:
202228 x, y = self.calc_menu_origin(widget, orientation)
203229 self.proxy.call_button_press(x, y, event.button, event.time, orientation, None, None)
204230
205 if event.button != Gdk.BUTTON_PRIMARY:
206 self.set_active(True)
207
208231 if event.button in (Gdk.BUTTON_MIDDLE, Gdk.BUTTON_SECONDARY):
209232 # Block the 'remove from panel' menu, and the middle-click drag.
210233 # They can still accomplish these things along the edges of the applet
211234 return Gdk.EVENT_STOP
212235
213 return Gdk.EVENT_PROPAGATE
236 return Gdk.EVENT_STOP
214237
215238 def on_button_release(self, widget, event):
216239 orientation = translate_applet_orientation_to_xapp(self.orientation)
217240
241 if event.button == Gdk.BUTTON_PRIMARY:
242 self.menu_opened = True
243 elif event.button == Gdk.BUTTON_SECONDARY and self.highlight_both_menus:
244 self.menu_opened = True
245
218246 x, y = self.calc_menu_origin(widget, orientation)
219247 self.proxy.call_button_release(x, y, event.button, event.time, orientation, None, None)
220
221 GObject.timeout_add(200, self.after_release_idle)
222248
223249 return Gdk.EVENT_PROPAGATE
224250
44 from gi.repository import Gio, GLib, GObject, Gtk, XApp, Gdk
55 import os
66 import sys
7 import json
78
89 DBUS_NAME = "org.x.StatusIcon"
910 DBUS_PATH = "/org/x/StatusIcon"
1011
11 class StatusWidget(Gtk.Button):
12 class StatusWidget(Gtk.ToggleButton):
1213
1314 def __init__(self, icon):
14 super(Gtk.Button, self).__init__()
15 super(Gtk.ToggleButton, self).__init__()
1516
1617 self.proxy = icon
1718 self.name = self.proxy.get_name()
3536 self.proxy.bind_property("label", self.label, "label", flags)
3637 self.proxy.bind_property("tooltip-text", self, "tooltip-markup", flags)
3738 self.proxy.bind_property("visible", self, "visible", flags)
39
40 self.proxy.bind_property("primary-menu-is-open", self, "active", flags)
41 self.proxy.bind_property("secondary-menu-is-open", self, "active", flags)
3842
3943 self.proxy.connect("notify::icon-name", self.on_icon_name_changed)
4044
2121 self.status_icon.set_tooltip_text("Testing primary and secondary menus")
2222 self.status_icon.set_label("label 1")
2323 self.status_icon.set_visible(True)
24 self.status_icon.set_metadata(' { "highlight-both-menus": true } ')
25
2426 self.status_icon.connect("scroll-event", self.handle_scroll_event)
2527
2628 self.counter = 1
587587 {
588588 g_autoptr(GVariant) tt_var;
589589
590 if (item->is_ai)
591 {
592 gchar *text;
593
594 text = get_string_property (item, "XAyatanaLabel");
595
596 if (text)
597 {
598 xapp_status_icon_set_tooltip_text (item->status_icon, text);
599 g_debug ("Tooltip text from XAyatanaLabel: %s", text);
600
601 g_free (text);
602 return;
603 }
604 }
605
606590 tt_var = get_property (item, "ToolTip");
607591
608592 if (tt_var)
724708 update_menu (item);
725709 }
726710 else
727 if (g_strcmp0 (signal_name, "XAyatanaNewLabel") ||
728 g_strcmp0 (signal_name, "NewToolTip") ||
711 if (g_strcmp0 (signal_name, "NewToolTip") ||
729712 g_strcmp0 (signal_name, "NewTitle"))
730713 {
731714 update_tooltip (item);
855838 {
856839 SnItem *item = SN_ITEM (user_data);
857840 GError *error = NULL;
841 gchar *json = NULL;
858842
859843 item->prop_proxy = g_dbus_proxy_new_finish (res, &error);
860844
871855 item);
872856
873857 item->status_icon = xapp_status_icon_new ();
858
859 json = g_strdup_printf ("{ 'highlight-both-menus': %s }", item->is_ai ? "true" : "false");
860 xapp_status_icon_set_metadata (item->status_icon, json);
861 g_free (json);
874862
875863 g_signal_connect (item->status_icon, "activate", G_CALLBACK (xapp_icon_activated), item);
876864 g_signal_connect (item->status_icon, "button-press-event", G_CALLBACK (xapp_icon_button_press), item);
7070 <!-- These are commented out because GDBusProxy would otherwise require them,
7171 but they are not available for KDE indicators
7272 -->
73 <signal name="XAyatanaNewLabel">
73 <!-- <signal name="XAyatanaNewLabel">
7474 <arg type="s" name="label" direction="out" />
7575 <arg type="s" name="guide" direction="out" />
7676 </signal>
7777 <property name="XAyatanaLabel" type="s" access="read" />
7878 <property name="XAyatanaLabelGuide" type="s" access="read" />
7979
80
80 -->
8181 </interface>
8282 </node>
506506 watcher->name_listener_id = 0;
507507 }
508508
509 update_published_items (watcher);
509510 g_clear_pointer (&watcher->items, g_hash_table_unref);
510511
511512 sn_watcher_interface_set_is_status_notifier_host_registered (watcher->skeleton,
512513 FALSE);
513514 g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (watcher->skeleton));
514515 sn_watcher_interface_emit_status_notifier_host_registered (watcher->skeleton);
515
516 update_published_items (watcher);
517516
518517 if (watcher->owner_id > 0)
519518 {