mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-26 18:22:09 +02:00
Report if close events are supported in the query response
This commit is contained in:
@@ -99,6 +99,9 @@ to display it based on what it does understand.
|
|||||||
Being informed when a notification is closed
|
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
|
If you wish to be informed when a notification is closed, you can specify
|
||||||
``c=1`` when sending the notification. For example::
|
``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
|
If ``a=report`` is specified and the notification is activated/clicked on
|
||||||
then both the activation report and close notification are sent.
|
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
|
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)
|
notification exists (perhaps because it was already closed or it was activated)
|
||||||
then the request is ignored.
|
then the request is ignored.
|
||||||
|
|
||||||
|
.. _notifications_query:
|
||||||
|
|
||||||
Querying for support
|
Querying for support
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
@@ -167,6 +178,9 @@ Key Value
|
|||||||
``p`` Comma spearated list of supported payload types (i.e. values of the
|
``p`` Comma spearated list of supported payload types (i.e. values of the
|
||||||
``p`` key that the terminal implements). These must contain at least
|
``p`` key that the terminal implements). These must contain at least
|
||||||
``title`` and ``body``.
|
``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
|
In the future, if this protocol expands, more keys might be added. Clients must
|
||||||
|
|||||||
@@ -249,6 +249,8 @@ class NotificationCommand:
|
|||||||
|
|
||||||
class DesktopIntegration:
|
class DesktopIntegration:
|
||||||
|
|
||||||
|
supports_close_events: bool = True
|
||||||
|
|
||||||
def __init__(self, notification_manager: 'NotificationManager'):
|
def __init__(self, notification_manager: 'NotificationManager'):
|
||||||
self.notification_manager = notification_manager
|
self.notification_manager = notification_manager
|
||||||
self.initialize()
|
self.initialize()
|
||||||
@@ -274,9 +276,20 @@ class DesktopIntegration:
|
|||||||
from .update_check import notification_activated
|
from .update_check import notification_activated
|
||||||
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):
|
class MacOSIntegration(DesktopIntegration):
|
||||||
|
|
||||||
|
supports_close_events: bool = False
|
||||||
|
|
||||||
def initialize(self) -> None:
|
def initialize(self) -> None:
|
||||||
from .fast_data_types import cocoa_set_notification_activated_callback
|
from .fast_data_types import cocoa_set_notification_activated_callback
|
||||||
self.id_counter = count(start=1)
|
self.id_counter = count(start=1)
|
||||||
@@ -543,7 +556,9 @@ class NotificationManager:
|
|||||||
_, cmd = self.in_progress_notification_commands.popitem(False)
|
_, cmd = self.in_progress_notification_commands.popitem(False)
|
||||||
self.in_progress_notification_commands_by_client_id.pop(cmd.identifier, None)
|
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]
|
metadata, payload = raw.partition(';')[::2]
|
||||||
cmd = NotificationCommand()
|
cmd = NotificationCommand()
|
||||||
try:
|
try:
|
||||||
@@ -552,12 +567,7 @@ class NotificationManager:
|
|||||||
self.log('Malformed metadata section in OSC 99: ' + metadata)
|
self.log('Malformed metadata section in OSC 99: ' + metadata)
|
||||||
return None
|
return None
|
||||||
if payload_type is PayloadType.query:
|
if payload_type is PayloadType.query:
|
||||||
actions = ','.join(x.value for x in Action)
|
self.channel.send(channel_id, self.desktop_integration.query_response(cmd.identifier))
|
||||||
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}')
|
|
||||||
return None
|
return None
|
||||||
if payload_type is PayloadType.close:
|
if payload_type is PayloadType.close:
|
||||||
if cmd.identifier:
|
if cmd.identifier:
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ def do_test(self: 'TestNotifications') -> None:
|
|||||||
# Test querying
|
# Test querying
|
||||||
h('i=xyz:p=?')
|
h('i=xyz:p=?')
|
||||||
self.assertFalse(di.notifications)
|
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}'])
|
self.ae(ch.responses, [f'99;i=xyz:p=?;{qr}'])
|
||||||
reset()
|
reset()
|
||||||
h('p=?')
|
h('p=?')
|
||||||
|
|||||||
Reference in New Issue
Block a user