Forgot about supporting multiplexers in the desktop notification query protocol

This commit is contained in:
Kovid Goyal
2024-07-23 20:35:26 +05:30
parent 3cf6db445b
commit c4baed73a2
3 changed files with 19 additions and 11 deletions

View File

@@ -102,11 +102,15 @@ Querying for support
An application can query the terminal emulator for support of this protocol, by
sending the following escape code::
<OSC> 99 ; ? ; <terminator>
<OSC> 99 ; i=<some identifier> : p=? ; <terminator>
A conforming terminal must respond with an escape code of the form::
<OSC> 99 ; ? ; key=value : key=value <terminator>
<OSC> 99 ; i=<some identifier> : p=? ; key=value : key=value <terminator>
The identifier must be some globally unique identifier string like an UUID. It
is present to support terminal multiplexers, so that they know which window to
redirect the query response too.
Here, the ``key=value`` parts specify details about what the terminal
implementation supports. Currently, the following keys are defined:
@@ -150,8 +154,8 @@ Key Value Default Description
``i`` ``[a-zA-Z0-9-_+.]`` ``0`` Identifier for the notification
``p`` One of ``title`` or ``title`` Whether the payload is the notification title or body. If a
``body``. notification has no title, the body will be used as title.
``p`` One of ``title``, ``title`` Whether the payload is the notification title or body or query. If a
``body`` or ``?`` notification has no title, the body will be used as title.
``o`` One of ``always``, ``always`` When to honor the notification request. ``unfocused`` means when the window
``unfocused`` or the notification is sent on does not have keyboard focus. ``invisible``

View File

@@ -140,11 +140,6 @@ class QueryResponse(Exception):
def parse_osc_99(raw: str) -> NotificationCommand:
cmd = NotificationCommand()
metadata, payload = raw.partition(';')[::2]
if metadata == '?':
actions = ','.join(x.name for x in Action)
when = ','.join(x.name for x in OnlyWhen if x.value)
urgency = ','.join(str(x.value) for x in Urgency)
raise QueryResponse(f'99;?;a={actions}:o={when}:u={urgency}')
payload_is_encoded = False
payload_type = 'title'
if metadata:
@@ -181,6 +176,15 @@ def parse_osc_99(raw: str) -> NotificationCommand:
elif k == 'u':
with suppress(Exception):
cmd.urgency = Urgency(int(v))
if payload_type == '?':
actions = ','.join(x.name for x in Action)
when = ','.join(x.name for x in OnlyWhen if x.value)
urgency = ','.join(str(x.value) for x in Urgency)
i = ''
if cmd.identifier:
i = f'i={sanitize_id(cmd.identifier)}:'
raise QueryResponse(f'99;{i}p=?;a={actions}:o={when}:u={urgency}')
if payload_type not in ('body', 'title'):
log_error(f'Malformed OSC 99: unknown payload type: {payload_type}')
return NotificationCommand()

View File

@@ -588,9 +588,9 @@ class TestParser(BaseTest):
notification_activated(notifications[-1][-2], activated)
self.ae(activations, [('0', 1, True, False)])
reset()
h('?')
h('i=xyz:p=?')
self.assertFalse(notifications)
self.ae(query_responses, ['99;?;a=focus,report:o=always,unfocused,invisible:u=0,1,2'])
self.ae(query_responses, ['99;i=xyz:p=?;a=focus,report:o=always,unfocused,invisible:u=0,1,2'])
def test_dcs_codes(self):
s = self.create_screen()