Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/server/source/notification_mixin.py : 60%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2# This file is part of Xpra.
3# Copyright (C) 2010-2020 Antoine Martin <antoine@xpra.org>
4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
5# later version. See the file COPYING for details.
7from xpra.util import typedict
8from xpra.server.source.stub_source_mixin import StubSourceMixin
9from xpra.log import Logger
11log = Logger("notify")
14class NotificationMixin(StubSourceMixin):
16 @classmethod
17 def is_needed(cls, caps : typedict) -> bool:
18 return caps.boolget("notifications", False)
21 def init_state(self):
22 self.send_notifications = False
23 self.send_notifications_actions = False
24 self.notification_callbacks = {}
26 def parse_client_caps(self, c : typedict):
27 self.send_notifications = c.boolget("notifications")
28 self.send_notifications_actions = c.boolget("notifications.actions")
29 log("notifications=%s, actions=%s", self.send_notifications, self.send_notifications_actions)
31 def get_info(self) -> dict:
32 return {
33 "notifications" : self.send_notifications,
34 }
36 ######################################################################
37 # notifications:
38 # Utility functions for mixins (makes notifications optional)
39 def may_notify(self, nid=0, summary="", body="", actions=(), hints=None, expire_timeout=10*1000,
40 icon_name=None, user_callback=None):
41 try:
42 from xpra.platform.paths import get_icon_filename
43 from xpra.notifications.common import parse_image_path
44 except ImportError as e:
45 log("not sending notification: %s", e)
46 else:
47 icon_filename = get_icon_filename(icon_name)
48 icon = parse_image_path(icon_filename) or ""
49 self.notify("", nid, "Xpra", 0, "",
50 summary, body, actions, hints or {},
51 expire_timeout, icon, user_callback)
53 def notify(self, dbus_id, nid, app_name, replaces_nid, app_icon,
54 summary, body, actions, hints, expire_timeout, icon, user_callback=None):
55 args = (dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout, icon)
56 log("notify%s types=%s", args, tuple(type(x) for x in args))
57 if not self.send_notifications:
58 log("client %s does not support notifications", self)
59 return False
60 #"suspended" belongs in the WindowsMixin:
61 if getattr(self, "suspended", False):
62 log("client %s is suspended, notification not sent", self)
63 return False
64 if user_callback:
65 self.notification_callbacks[nid] = user_callback
66 #this is one of the few places where we actually do care about character encoding:
67 try:
68 summary = summary.encode("utf8")
69 except UnicodeEncodeError:
70 summary = str(summary)
71 try:
72 body = body.encode("utf8")
73 except UnicodeEncodeError:
74 body = str(body)
75 if self.hello_sent:
76 #Warning: actions and hints are send last because they were added later (in version 2.3)
77 self.send_async("notify_show", dbus_id, nid, app_name, replaces_nid, app_icon,
78 summary, body, expire_timeout, icon, actions, hints)
79 return True
81 def notify_close(self, nid : int):
82 if not self.send_notifications or self.suspended or not self.hello_sent:
83 return
84 self.send_more("notify_close", nid)