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 An application can query the terminal emulator for support of this protocol, by
sending the following escape code:: 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:: 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 Here, the ``key=value`` parts specify details about what the terminal
implementation supports. Currently, the following keys are defined: 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 ``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 ``p`` One of ``title``, ``title`` Whether the payload is the notification title or body or query. If a
``body``. notification has no title, the body will be used as title. ``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 ``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`` ``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: def parse_osc_99(raw: str) -> NotificationCommand:
cmd = NotificationCommand() cmd = NotificationCommand()
metadata, payload = raw.partition(';')[::2] 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_is_encoded = False
payload_type = 'title' payload_type = 'title'
if metadata: if metadata:
@@ -181,6 +176,15 @@ def parse_osc_99(raw: str) -> NotificationCommand:
elif k == 'u': elif k == 'u':
with suppress(Exception): with suppress(Exception):
cmd.urgency = Urgency(int(v)) 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'): if payload_type not in ('body', 'title'):
log_error(f'Malformed OSC 99: unknown payload type: {payload_type}') log_error(f'Malformed OSC 99: unknown payload type: {payload_type}')
return NotificationCommand() return NotificationCommand()

View File

@@ -588,9 +588,9 @@ class TestParser(BaseTest):
notification_activated(notifications[-1][-2], activated) notification_activated(notifications[-1][-2], activated)
self.ae(activations, [('0', 1, True, False)]) self.ae(activations, [('0', 1, True, False)])
reset() reset()
h('?') h('i=xyz:p=?')
self.assertFalse(notifications) 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): def test_dcs_codes(self):
s = self.create_screen() s = self.create_screen()