Report if close events are supported in the query response

This commit is contained in:
Kovid Goyal
2024-07-25 18:59:31 +05:30
parent 9c772915fb
commit 0813a3daff
3 changed files with 32 additions and 8 deletions

View File

@@ -99,6 +99,9 @@ to display it based on what it does understand.
Being informed when a notification is closed
------------------------------------------------
.. versionadded:: 0.36.0
Notifications of close events were added in kitty version 0.36.0
If you wish to be informed when a notification is closed, you can specify
``c=1`` when sending the notification. For example::
@@ -113,6 +116,12 @@ If no notification id was specified ``i=0`` will be used.
If ``a=report`` is specified and the notification is activated/clicked on
then both the activation report and close notification are sent.
.. note::
Close events are best effort, some platforms such as macOS do not have
events when notifications are closed. Applications can use the
:ref:`notifications_query` to check if close events are supported
by the current terminal emulator.
Closing an existing notification
----------------------------------
@@ -128,6 +137,8 @@ This will close a previous notification with the specified id. If no such
notification exists (perhaps because it was already closed or it was activated)
then the request is ignored.
.. _notifications_query:
Querying for support
-------------------------
@@ -167,6 +178,9 @@ Key Value
``p`` Comma spearated list of supported payload types (i.e. values of the
``p`` key that the terminal implements). These must contain at least
``title`` and ``body``.
``c`` ``c=1`` if the terminal supports close events, otherwise the ``c``
must be omitted.
======= ================================================================================
In the future, if this protocol expands, more keys might be added. Clients must

View File

@@ -249,6 +249,8 @@ class NotificationCommand:
class DesktopIntegration:
supports_close_events: bool = True
def __init__(self, notification_manager: 'NotificationManager'):
self.notification_manager = notification_manager
self.initialize()
@@ -274,9 +276,20 @@ class DesktopIntegration:
from .update_check import notification_activated
notification_activated()
def query_response(self, identifier: str) -> str:
actions = ','.join(x.value for x in Action)
when = ','.join(x.value for x in OnlyWhen if x.value)
urgency = ','.join(str(x.value) for x in Urgency)
i = f'i={identifier or "0"}:'
p = ','.join(x.value for x in PayloadType if x.value)
c = ':c=1' if self.supports_close_events else ''
return f'99;{i}p=?;a={actions}:o={when}:u={urgency}:p={p}{c}'
class MacOSIntegration(DesktopIntegration):
supports_close_events: bool = False
def initialize(self) -> None:
from .fast_data_types import cocoa_set_notification_activated_callback
self.id_counter = count(start=1)
@@ -543,7 +556,9 @@ class NotificationManager:
_, cmd = self.in_progress_notification_commands.popitem(False)
self.in_progress_notification_commands_by_client_id.pop(cmd.identifier, None)
def parse_notification_cmd(self, prev_cmd: NotificationCommand, channel_id: int, raw: str) -> Optional[NotificationCommand]:
def parse_notification_cmd(
self, prev_cmd: NotificationCommand, channel_id: int, raw: str
) -> Optional[NotificationCommand]:
metadata, payload = raw.partition(';')[::2]
cmd = NotificationCommand()
try:
@@ -552,12 +567,7 @@ class NotificationManager:
self.log('Malformed metadata section in OSC 99: ' + metadata)
return None
if payload_type is PayloadType.query:
actions = ','.join(x.value for x in Action)
when = ','.join(x.value for x in OnlyWhen if x.value)
urgency = ','.join(str(x.value) for x in Urgency)
i = f'i={cmd.identifier or "0"}:'
p = ','.join(x.value for x in PayloadType if x.value)
self.channel.send(channel_id, f'99;{i}p=?;a={actions}:o={when}:u={urgency}:p={p}')
self.channel.send(channel_id, self.desktop_integration.query_response(cmd.identifier))
return None
if payload_type is PayloadType.close:
if cmd.identifier:

View File

@@ -204,7 +204,7 @@ def do_test(self: 'TestNotifications') -> None:
# Test querying
h('i=xyz:p=?')
self.assertFalse(di.notifications)
qr = 'a=focus,report:o=always,unfocused,invisible:u=0,1,2:p=title,body,?,close'
qr = 'a=focus,report:o=always,unfocused,invisible:u=0,1,2:p=title,body,?,close:c=1'
self.ae(ch.responses, [f'99;i=xyz:p=?;{qr}'])
reset()
h('p=?')