xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #1735: notifications-actions.patch

File notifications-actions.patch, 15.4 KB (added by Antoine Martin, 4 years ago)

work in progress

  • xpra/client/gtk3/gtk3_notifier.py

     
    1414
    1515class GTK3_Notifier(NotifierBase):
    1616
    17     def show_notify(self, dbus_id, tray, nid, app_id, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     17    def show_notify(self, dbus_id, tray, nid, app_id, app_name, replaces_nid, app_icon, summary, body, action, hints, expire_timeout, icon):
    1818        if not self.dbus_check(dbus_id):
    1919            return
    2020        icon_string = self.get_icon_string(nid, app_icon, icon)
  • xpra/client/gtk_base/gtk_notifier.py

     
    104104    def get_origin_y(self):
    105105        return    self.y
    106106
    107     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     107    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    108108        self.new_popup(summary, body, icon)
    109109
    110110    def new_popup(self, summary, body, icon):
  • xpra/client/notifications/dbus_notifier.py

     
    55
    66import os
    77
    8 from xpra.util import repr_ellipsized
     8from xpra.util import repr_ellipsized, csv
    99from xpra.client.notifications.notifier_base import NotifierBase, log
    1010try:
    1111    #new recommended way of using the glib main loop:
     
    4646        self.org_fd_notifications = self.dbus_session.get_object(FD_NOTIFICATIONS, '/org/freedesktop/Notifications')
    4747        self.dbusnotify = dbus.Interface(self.org_fd_notifications, FD_NOTIFICATIONS)
    4848        log("using dbusnotify: %s(%s)", type(self.dbusnotify), FD_NOTIFICATIONS)
     49        log("capabilities=%s", csv(str(x) for x in self.dbusnotify.GetCapabilities()))
    4950
    50     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     51    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    5152        if not self.dbus_check(dbus_id):
    5253            return
    5354        self.may_retry = True
     
    6465            except:
    6566                app_str = app_name or "Xpra"
    6667            self.last_notification = (dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon)
    67             self.dbusnotify.Notify(app_str, 0, icon_string, summary, body, [], [], expire_timeout,
     68            self.dbusnotify.Notify(app_str, 0, icon_string, summary, body, actions, hints, expire_timeout,
    6869                 reply_handler = self.cbReply,
    6970                 error_handler = self.cbError)
    7071        except:
  • xpra/client/notifications/notifier_base.py

     
    2525            for nid in self.temp_files.keys():
    2626                self.clean_notification(nid)
    2727
    28     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     28    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    2929        pass
    3030
    3131    def get_icon_string(self, nid, app_icon, icon):
  • xpra/client/notifications/pynotify_notifier.py

     
    1010
    1111class PyNotify_Notifier(NotifierBase):
    1212
    13     def show_notify(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     13    def show_notify(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    1414        if not self.dbus_check(dbus_id):
    1515            return
    1616        icon_string = self.get_icon_string(nid, app_icon, icon)
     
    2323        n = pynotify.Notification(summary, body, icon_string)
    2424        n.set_urgency(pynotify.URGENCY_LOW)
    2525        n.set_timeout(expire_timeout)
     26        if actions and False:
     27            while len(actions)>=2:
     28               
    2629        n.show()
    2730
     31    def add_action(self, n, action_id, action_label):
     32        #n.add_action("foo", "Foo!", foo_action)
     33        def callback(*args):
     34            pass
     35        n.add_action(action_id, action_label, callback)
     36
    2837    def close_notify(self, nid):
    2938        pass
    3039
     
    3443    import gtk
    3544    def show():
    3645        n = PyNotify_Notifier()
    37         n.show_notify("", 0, "Test", 0, "", "Summary", "Body...", 0)
     46        n.show_notify("", 0, "Test", 0, "", "Summary", "Body...", [], {}, 0, "")
    3847        return False
    3948    glib.idle_add(show)
    4049    glib.timeout_add(20000, gtk.main_quit)
  • xpra/client/ui_client_base.py

     
    34303430            return
    34313431        self._ui_event()
    34323432        dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout = packet[1:9]
     3433        icon, actions, hints = None, [], {}
    34333434        if len(packet)>=10:
    34343435            icon = packet[9]
    3435         else:
    3436             icon = None
     3436        if len(packet)>=12:
     3437            actions, hints = packet[10], packet[11]
    34373438        #note: if the server doesn't support notification forwarding,
    34383439        #it can still send us the messages (via xpra control or the dbus interface)
    34393440        notifylog("_process_notify_show(%s) notifier=%s, server_notifications=%s", repr_ellipsized(str(packet)), self.notifier, self.server_notifications)
     3441        notifylog.info("actions=%s, hints=%s", actions, hints)
    34403442        assert self.notifier
    3441         #TODO: choose more appropriate tray if we have more than one shown?
    34423443        #this one of the few places where we actually do care about character encoding:
    34433444        try:
    34443445            summary = summary.decode("utf8")
     
    34493450        except:
    34503451            body = bytestostr(body)
    34513452        app_name = bytestostr(app_name)
    3452         tray = self.get_tray_window(app_name)
     3453        tray = self.get_tray_window(app_name, hints)
    34533454        traylog("get_tray_window(%s)=%s", app_name, tray)
    3454         self.notifier.show_notify(dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon)
     3455        self.notifier.show_notify(dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon)
    34553456
    34563457    def _process_notify_close(self, packet):
    34573458        if not self.notifications_enabled:
     
    34613462        log("_process_notify_close(%s)", nid)
    34623463        self.notifier.close_notify(nid)
    34633464
    3464     def get_tray_window(self, app_name):
     3465    def get_tray_window(self, app_name, hints):
    34653466        #try to identify the application tray that generated this notification,
    34663467        #so we can show it as coming from the correct systray icon
    34673468        #on platforms that support it (ie: win32)
     3469        try:
     3470            pid = int(hints.get("pid") or 0)
     3471        except (TypeError, ValueError):
     3472            pass
     3473        else:
     3474            #TODO: try to find a tray with this pid?
     3475            if pid:
     3476                notifylog("tray window: match pid=%i", pid)
    34683477        if app_name and app_name.lower()!="xpra":
    34693478            #exact match:
    34703479            for window in self._id_to_window.values():
  • xpra/dbus/notifications_forwarder.py

     
    44# later version. See the file COPYING for details.
    55
    66import os
    7 import gtk
    87import dbus.service
    98
     9from xpra.dbus.helper import dbus_to_native
    1010from xpra.log import Logger
    1111log = Logger("dbus", "notify")
    1212
     
    4444            nid = replaces_nid
    4545        log("Notify%s counter=%i, callback=%s", (app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout), self.counter, self.notify_callback)
    4646        if self.notify_callback:
    47             self.notify_callback(self.dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout)
     47            try:
     48                actions = tuple(str(x) for x in actions)
     49                hints = dbus_to_native(hints)
     50                args = self.dbus_id, int(nid), str(app_name), int(replaces_nid), str(app_icon), str(summary), str(body), actions, hints, int(expire_timeout)
     51            except Exception as e:
     52                log.error("Error: failed to parse Notify arguments:")
     53                log.error(" %s", e)
     54            try:
     55                self.notify_callback(*args)
     56            except Exception as e:
     57                log.error("Error calling notification handler", exc_info=True)
    4858        log("Notify returning %s", nid)
    4959        return nid
    5060
     
    8898
    8999def main():
    90100    register()
     101    import gtk
    91102    gtk.main()
    92103
    93104if __name__ == "__main__":
  • xpra/platform/darwin/gui.py

     
    110110        self.notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
    111111        assert self.notification_center
    112112
    113     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     113    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    114114        notification = NSUserNotification.alloc().init()
    115115        notification.setTitle_(summary)
    116116        notification.setInformativeText_(body)
     
    133133
    134134
    135135class OSX_Subprocess_Notifier(NotifierBase):
    136     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     136    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    137137        from xpra.platform.darwin import osx_notifier
    138138        osx_notifier_file = osx_notifier.__file__
    139139        if osx_notifier_file.endswith("pyc"):
  • xpra/platform/win32/win32_notifier.py

     
    88
    99class Win32_Notifier(NotifierBase):
    1010
    11     def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
     11    def show_notify(self, dbus_id, tray, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
    1212        if tray is None:
    1313            log.warn("Warning: no system tray - cannot show notification!")
    1414            return
  • xpra/server/server_base.py

     
    11151115    def idle_grace_timeout_cb(self, source):
    11161116        log("idle_grace_timeout_cb(%s)", source)
    11171117        timeout_nid = 2**16 + 2**8 + 1
    1118         source.notify(0, timeout_nid, "xpra", 0, "", "This Xpra session will timeout soon", "Activate one of the windows to avoid this timeout", 10)
     1118        source.notify(0, timeout_nid, "xpra", 0, "", "This Xpra session will timeout soon", "Activate one of the windows to avoid this timeout", [], {}, 10, "")
    11191119        source.go_idle()
    11201120
    11211121    def _log_disconnect(self, proto, *args):
     
    17841784        notifylog("control_command_send_notification(%i, %s, %s, %s) will send to sources %s (matching %s)", nid, title, message, client_uuids, sources, client_uuids)
    17851785        count = 0
    17861786        for source in sources:
    1787             if source.notify(0, nid, "control channel", 0, "", title, message, 10, ()):
     1787            if source.notify(0, nid, "control channel", 0, "", title, message, [], {}, 10, ""):
    17881788                count += 1
    17891789        msg = "notification id %i: message sent to %i clients" % (nid, count)
    17901790        notifylog(msg)
     
    26152615        if self._clipboard_client:
    26162616            self._clipboard_client.send_clipboard(parts)
    26172617
    2618     def notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout):
     2618    def notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout):
    26192619        try:
    26202620            assert self.notifications_forwarder and self.notifications
    26212621            icon = self.get_notification_icon(str(app_icon))
    26222622            if os.path.isabs(str(app_icon)):
    26232623                app_icon = ""
    2624             notifylog("notify_callback%s icon=%s", (dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout), repr_ellipsized(str(icon)))
     2624            notifylog("notify_callback%s icon=%s", (dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout), repr_ellipsized(str(icon)))
    26252625            for ss in self._server_sources.values():
    2626                 ss.notify(dbus_id, int(nid), str(app_name), int(replaces_nid), str(app_icon), str(summary), str(body), int(expire_timeout), icon)
     2626                ss.notify(dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon)
    26272627        except Exception as e:
    26282628            notifylog("notify_callback failed", exc_info=True)
    26292629            notifylog.error("Error processing notification:")
  • xpra/server/source.py

     
    19621962            return
    19631963        self.send_async("bell", wid, device, percent, pitch, duration, bell_class, bell_id, bell_name)
    19641964
    1965     def notify(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon):
    1966         args = (dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon)
     1965    def notify(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon):
     1966        args = (dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon)
    19671967        notifylog("notify%s types=%s", args, tuple(type(x) for x in args))
    19681968        if not self.send_notifications:
    19691969            notifylog("client %s does not support notifications", self)
     
    19811981        except:
    19821982            body = str(body)
    19831983        if self.hello_sent:
    1984             self.send_async("notify_show", dbus_id, int(nid), str(app_name), int(replaces_nid), str(app_icon), summary, body, int(expire_timeout), icon)
     1984            #Warning: actions and hints are send last because they were added later (in version 2.3)
     1985            self.send_async("notify_show", dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, expire_timeout, icon, actions, hints)
    19851986        return True
    19861987
    19871988    def notify_close(self, nid):