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
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
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 @@ def __init__(self, response_string: str):
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 @@ def activated(identifier, window_id, focus, report):
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()