Commit graph

150 commits

Author SHA1 Message Date
Daniel Eklöf
7354b94f73
osc: restore configured alpha if OSC-11 has no alpha value
When parsing an OSC-11 without an alpha value (i.e. standard OSC-11,
not rxvt's extended variant), restore the alpha value from the
configuration, rather than keeping whatever the current alpha is.
2025-05-02 18:54:03 +02:00
Daniel Eklöf
624c383a1f
config: move cursor.color to colors.cursor 2025-04-26 10:46:39 +02:00
Daniel Eklöf
0f93766614
osc: text-size: disable optimization
The optimization prevents the forced-width to be set on the new
combining character, causing issues when followed by more zero-width
codepoints.
2025-02-06 14:02:38 +01:00
Daniel Eklöf
1260004330
osc: text-sizing: implement w=0, plus optimize single-codepoint cases
If there's a single codepoint in the text portion of the OSC sequence,
and its calculated width matches the forced width, print it directly
to the grid instead of emitting a combining character.

When w=0, we split up the text string "as we normally would". Since we
don't support any other text-sizing parameters, this means simply
printing each codepoint to the grid.
2025-02-06 07:45:58 +01:00
Daniel Eklöf
d3f692990e
term+vt: refactor: move "utf8" char processing to term_process_and_print_non_ascii()
This function "prints" any non-ascii character (i.e. any character
that ends up in the action_utf8_print() function in vt.c) to the
grid. This includes grapheme cluster processing etc.

action_utf8_print() now simply calls this function.

This allows us to re-use the same functionality from other
places (like the text-sizing protocol).
2025-02-06 07:45:20 +01:00
Daniel Eklöf
7a8d2b5e01
osc: wip: kitty text size protocol
This brings initial support for the new kitty text-sizing
protocol. Note hat only the width-parameter ('w') is supported. That
is, no font scaling, and no multi-line cells.

For now, only explicit widths are supported. That is, w=0 does not yet
work.

There are a couple of changes to the renderer, to handle e.g.

    OSC 66 ; w=6 ; foobar ST

There are two ways this can get rendered, depending on whether
grapheme shaping has been enabled. We either shape it, and get an
array of glyphs back that we render. Or, we rasterize each codepoint
ourselves, and render each resulting glyph.

The two cases ends up in two different renderer loops, that worked
somewhat different. In particular, the first case has probably never
been tested/used at all...

With this patch, both are changed, and now uses some heuristic to
differentiate between multi-cell text strings (like in the example
above), or single-cell combining characters. The difference is mainly
in which offset to use for the secondary glyphs.

In a multi-cell string, each glyph is mapped to its own cell, while in
the combining case, we try to map all glyphs to the same cell.
2025-02-06 07:42:38 +01:00
Daniel Eklöf
06a32d553e
osc: ignore 'OSC 176 ?' - report app ID
It's not widely used (don't know _any_ application that uses it), and
can be used to trick users to run unwanted commands.
2025-01-07 13:01:21 +01:00
Daniel Eklöf
9f5be55d1c
osc: disable debug logging 2025-01-02 09:12:11 +01:00
Daniel Eklöf
e38ec79be1
osc: add option to disable OSC-52, partially or fully
Closes #1867
2024-12-22 07:16:12 +01:00
Daniel Eklöf
f3e443ea47
osc: 9: ignore ConEmu/Windows Terminal sequences
OSC-9 sequences starting with "<number>;" are now ignored, as they are
ConEmu sequences, and not iTerm notifications.
2024-11-02 08:33:03 +01:00
Jack Wilsdon
689549bb1f
osc: notify: fix crash with no message
Closes #1866
2024-10-31 07:03:04 +01:00
Daniel Eklöf
7984f08925
osc: OSC-1 does not set the icon, it sets the icon _label_
In fact, there appears there *is* no escape sequence to set the icon.

Keep most of the logic in place, but in practice, we'll always set the
icon to the app-id. That is, at startup, we set it to the configured
app-id (either from config, or the command line).

OSC-176, which sets the app-id, also updates the icon (to the app-id).
2024-09-13 09:04:18 +02:00
Daniel Eklöf
97ec375c67
toplevel-icon: implement OSC-1, CSI 20/21/22/23 t
* The toplevel icon is now set to the app-id, unless "overridden" by
  OSC-1 or OSC-0.
* Implemented OSC-1
* OSC-0 extended to also set the icon
* Implemented CSI 20 t - report window icon
* Implemented CSI 21 t - report window title
* Implemented CSI 22 ; 1 t - push window icon
* Implemented CS 23 ; 1 t - pop window icon
* Extended CSI 22/23 ; 0 t to also push/pop the icon
* Verify app-id set by OSC-176 is valid UTF-8
* Verify icon set by OSC-0/1 is valid UTF-8
2024-09-13 09:04:17 +02:00
Craig Barnes
d4a1283797
xsnprintf: various improvements related to xvsnprintf() and xsnprintf()
Summary of changes:

* Make xvsnprintf() static
* restrict-qualify pointer arguments (as done by the libc equivalents)
* Make comments and spec references more thorough
* Remove pointless `n <= INT_MAX` assertion (see comment)
* Use FATAL_ERROR() instead of xassert() (since the assertion is inside
  a shared util function but the caller is responsible for ensuring the
  condition holds true)
* Change some callers to use size_t instead of int for the return value
  (negative returns are impossible and all subsequent uses are size_t)

The updated comments and code were taken (and adapted) from:

49260bb154/src/util/xsnprintf.c (L6-50)

This work was entirely authored by me and I hereby license this
contribution under the MIT license (stated explicitly, so that
there's no ambiguity w.r.t. the original license).
2024-09-13 09:01:15 +02:00
Daniel Eklöf
c5bb1fb2ed
notifications: BEL and OSC-777 now focuses the window on notification activation
Or put more propertly; if the notification daemon, and the
notification helper used by foot has been configured
properly (i.e. they both support XDG activation tokens), notifications
generated by BEL and OSC-777 will now raise/focus the window when the
default action of the notification is activated - typically by
clicking the notification.

Closes #1822
2024-09-05 07:16:15 +02:00
Daniel Eklöf
7dd204fd31
osc: notify: fix bad check for invalid UTF-8
mbsntoc32() returns (size_t)-1 on failure, not (char32_t)-1.
2024-08-20 07:14:53 +02:00
Daniel Eklöf
2896c18981
osc: regression: fix OSC-111 handling of alpha changes
When the background alpha changes from fully opaque, to transparent,
or vice versa, we need to do more than just repaint the affected
cells.

For example, we need to create new surfaces with the correct pixel
format.

OSC-11 (set background color) already does this, but the same alpha
checking logic was missing in OSC-111 (reset background color).

Fixes #1801
2024-08-14 08:53:45 +02:00
Daniel Eklöf
ee9c76ded0
osc: kitty: update 's' to the latest spec
* The spec now defines a couple of "standard" names. Translate these
  to the freedesktop compliant names.
* The query response no longer contains 'xdg-names', but instead list
  the supported standard names.
2024-08-09 08:25:36 +02:00
Daniel Eklöf
84d36606cb
osc: kitty notifications: add support for XDG sound names 2024-08-04 15:23:31 +02:00
Daniel Eklöf
6349262491
osc: kitty notifications: implement s=silent
This implements part of the new 's' (sound) parameter; the 'silent'
value. When s=silent, we set the ${muted} template argument to
"true". It is intended to set the 'suppress-sound' hint:

    notify-send --hint BOOLEAN:suppress-sound:${muted}
2024-08-04 14:20:35 +02:00
Craig Barnes
b27841e1b5 Merge branch 'xstrjoin3' 2024-08-03 10:42:37 +01:00
Daniel Eklöf
6b72108ee2
osc: kitty notifications: ignore invalid IDs
Notification IDs must only use characters from [a-zA-Z0-9_-+.]

    Terminals **must** sanitize ids received from client programs
    before sending them back in responses, to mitigate input injection
    based attacks. That is, they must either reject ids containing
    characters not from the above set, or remove bad characters when
    reading ids sent to them.

Foot implements the first: reject IDs containing characters not from
the above set.
2024-08-03 11:05:58 +02:00
Craig Barnes
f87c9bb9f7 xmalloc: remove delim param from xstrjoin() and add separate xstrjoin3()
This avoids the need for an unused third argument for most xstrjoin()
calls and replaces the cases where it's needed with a more flexible
function. Code generation is the same in both cases, when there are 2
string params and a compile-time known delimiter.

This commit also converts 4 uses of xasprintf() to use xstrjoin*().

See also: https://godbolt.org/z/xsjrhv9b6
2024-08-03 08:51:06 +01:00
Daniel Eklöf
ea2f0e7c3f
osc: kitty notifications: cleanup and update to latest version of spec
* Don't store a list of unfinished notifications. Use a single one. If
  the notification ID of the 'current' notification doesn't match the
  previous, unfinished one, the 'current' notification replaces the
  previous one, instead of updating it.

* Update xstrjoin() to take an optional delimiter (for example ','),
  and use that when joining categories and 'alive IDs'.

* Rename ${action-arg} to ${action-argument}

* Update handling of the 'n' parameter (symbolic icon name); the spec
  allows it to be used multiple times, and the terminal is supposed to
  pick the first one it can resolve. Foot can't resolve icons at all,
  neither can 'notify-send' or 'fyi' (which is what foot typically
  executes to display a notification); it's the notification daemon that
  resolves icons.

  The spec _could_ be interpreted to mean the terminal should lookup
  .desktop files, and use the value of the 'Icon' key from the first
  matching .desktop files. But foot doesn't read .desktop files, and I
  don't intend to implement XDG directory scanning and parsing of
  .desktop files just to figure out which icon to use.

  Instead, use a simple heuristics; use the *shortest* symbolic
  names. The idea is pretty simple: plain icon names are typically
  shorter than .desktop file IDs.
2024-08-02 08:07:13 +02:00
Daniel Eklöf
76ac910b11
osc: kitty notifications: buttons, icons, app-name, categories etc
First, icons have been finalized in the specification. There were only
three things we needed to adjust:

* symbolic names are base64 encoded
* there are a couple of OSC-99 defined symbolic names that need to be
  translated to the corresponding XDG icon name.
* allow in-band icons without a cache ID (that is, allow applications
  to use p=icon without having to cache the icon first).

Second, add support for the following new additions to the protocol:

* 'f': custom app-name, overrides the terminal's app-id
* 't': categories
* 'p=alive': lets applications poll for currently active notifications
* 'id' is now 'unset' by default, rather than "0"
* 'w': expire time (i.e. notification timeout)
* "buttons": aka actions. This lets applications add additional (to
  the terminal defined "default" action) actions. The 'activated' event
  has been updated to report which button/action was used to activate
  the notification.

To support button/actions, desktop-notifications.command had to be
reworked a bit.

There's now a new config option:
desktop-notifications.command-action-arg. It has two template
arguments ${action-name} and ${action-label}.

command-action-arg gets expanded for *each* action.

${action-name} and ${action-label} has been replaced by ${action-arg}
in command. This is a somewhat special template, in that it gets
replaced by *all* instances of the expanded actions.
2024-07-31 16:22:17 +02:00
Daniel Eklöf
9cf99ea4bf
notify: close notification by sending SIGINT to helper
If the user hasn't configured a custom 'desktop-notifications.close'
command, try to close the notification by sending SIGINT to the
notification helper.

This is best-effort:

* If there's no helper running, we do nothing (except warn)
* We don't verify, in any way, the notification is actually closed
* We don't send any other signals, under any circumstances. That is,
  no SIGTERM, no SIGKILL. Ever.
2024-07-26 16:28:47 +02:00
Daniel Eklöf
c4d9f8a8ff
osc: kitty notifications: implement the 'close' request
Add a new config option, desktop-notifications.close, defining what to
execute to close a notification. It has a single template parameter,
${id}, that is expanded to the external notification ID foot may have
picked up from the notification helper.

notify-send does not support closing notifications, and it appears
impossible to pass an *unsigned* integer as argument to gdbus. Hence
no default value for the new 'close' option.

Example:

    printf '\e]99;i=123;this is a notification\e\\'
    printf '\e]99;i=123:p=close;\e\\'
2024-07-25 19:24:28 +02:00
Daniel Eklöf
c797222930
osc: kitty notification: implement 'close' events
Application can now request to receive a 'close' event when the
notification is closed (but not necessarily activated), by adding
'c=1' to the notification request.
2024-07-25 18:47:23 +02:00
Daniel Eklöf
d53f0aea75
notify: rename 'report' -> 'report_activated' 2024-07-25 18:45:58 +02:00
Daniel Eklöf
a6bc9cafaf
osc+notify: strcmp() -> streq() 2024-07-24 16:04:14 +02:00
Daniel Eklöf
24168ed86e
osc: kitty notifications: don't include '?' in the query reply
No need to say we support queries, in the query reply...
2024-07-24 15:58:19 +02:00
Daniel Eklöf
70b4638a75
osc: kitty notifications: implement query 2024-07-23 18:32:23 +02:00
Daniel Eklöf
e59efb1233
osc: remove unused includes 2024-07-23 15:28:47 +02:00
Daniel Eklöf
efa5b9cea6
osc: cleanup 2024-07-23 12:12:38 +02:00
Daniel Eklöf
b3108e1ad2
notify: separate active notifications from unfinished kitty notifications
This fixes an issue where it wasn't possible to trigger multiple
notifications with the same kitty notification ID. This is something
that works in kitty, and there's no reason why it shouldn't work.

The issue was that we track stdout, and the notification helper's PID
in the notification struct. Thus, when a notification is being
displayed, we can't re-use the same notification struct instance for
another notification.

This patch fixes this by adding a new notification list,
'active_notifications'. Whenever we detect that we need to track the
helper (notification want's to either focus the window on activation,
or send an event to the application), we add a copy of the
notification to the 'active' list.

The notification can then be removed from the 'kitty' list, allowing
kitty notifications to re-use the same ID over and over again, even if
old notifications are still being displayed.
2024-07-23 11:53:30 +02:00
Daniel Eklöf
ccb184ae64
osc: kitty notifications: updated support for icons
This implements the suggested protocol discussed in
https://github.com/kovidgoyal/kitty/issues/7657.

Icons are handled by loading a cache. Both in-band PNG data, and
symbolic names are allowed.

Applications use a graphical ID to reference the icon both when
loading the cache, and when showing a notification.

* 'g' is the graphical ID
* 'n' is optional, and assigns a symbolic name to the icon
* 'p=icon' - the payload is icon PNG data. It needs to be base64
  encoded, but this is *not* implied. I.e. the application *must* use
  e=1 explicitly.

To load an icon (in-band PNG data):

    printf '\e]99;g=123:p=icon;<base64-encoded-png-data>\e\\'

or (symbolic name)

    printf '\e]99;g=123:n=firefox:p=icon;\e\\'

Of course, we can combine the two, assigning *both* a symbolic
name, *and* PNG data:

    printf '\e]99;g=123:n=firefox:p=icon;<base64-encoded-png>\e\\'

Then, to use the icon in a notification:

    printf '\e]99;g=123;this is a notification\e\\'

Foot also allows a *symbolic* icon to be defined and used at the same
time:

    printf '\e]99;g=123:n=firefox;this is a notification\e\\'

This obviously won't work with PNG data, since it uses the payload
portion of the escape sequence.
2024-07-23 11:29:05 +02:00
Daniel Eklöf
e52d6e3fb8
osc: kitty notifications: use xstrjoin() instead of xasprintf() 2024-07-23 08:05:19 +02:00
Daniel Eklöf
5905ea0d84
osc: kitty notifications: implement focus|report
This patch adds support for window focusing, and sending events back
to the client application when a notification is closed.

* Refactor notification related configuration options:
    - add desktop-notifications sub-section
    - deprecate 'notify' in favor of 'desktop-notifications.command'
    - deprecate 'notify-focus-inhibit' in favor of
      'desktop-notifications.inhibit-when-focused'
* Refactor: rename 'struct kitty_notification' to 'struct
  notification'
* Pass a 'struct notification' to notify_notify(), instead of many
  arguments.
* notify_notify() now registers a reaper callback. When the notifier
  process has terminated, the notification is considered closed, and we
  either try to focus (activate) the window, or send an event to the
  client application, depending on the notification setting.
* For the window activation, we need an XDG activation token. For now,
  assume *everything* written on stdout is part of the token.
* Refactor: remove much of the warnings from OSC-99; we don't
  typically log anything when an OSC/CSI has invalid values.
* Add icon support to OSC-99. This isn't part of the upstream
  spec. Foot's implementation:
    - uses the 'I' parameter
    - the value is expected to be a symbolic icon name
    - a quick check for absolute paths is done, and such icon requests
      are ignored.
* Added ${icon} to the 'desktop-notifications.command' template. Uses
  the icon specified in the notification, or ${app-id} if not set.
2024-07-23 07:17:21 +02:00
Daniel Eklöf
57af75f988
osc: kitty notifications: use body as title, if no title is set
This mirrors kitty's behavior; if the user didn't set a title, but did
set the body/text, use the body as title instead.
2024-07-23 07:17:21 +02:00
Daniel Eklöf
b0bf8ca5f7
osc/notify: add support for OSC-99, kitty desktop notifications
This adds limited support for OSC-99, kitty desktop notifications[^1]. We
support everything defined by the "protocol", except:

* 'a': action to perform on notification activation. Since we don't
  trigger the notification ourselves (over D-Bus), we don't know a)
  which ID the notification got, or b) when it is clicked.
* ... and that's it. Everything else is supported

To be explicit, we *do* support:

* Chunked notifications (d=0|1), allowing the application to append
  data to a notification in chunks, before it's finally displayed.
* Plain UTF-8, or base64-encoded UTF-8 payload (e=0|1).
* Notification identifier (i=xyz).
* Payload type (p=title|body).
* When to honor the notification (o=always|unfocused|invisible), with
  the following quirks:
    - we don't know when the window is invisible, thus it's treated as
      'unfocused'.
    - the foot option 'notify-focus-inhibit' overrides 'always'
* Urgency (u=0|1|2)

[^1]: https://sw.kovidgoyal.net/kitty/desktop-notifications/
2024-07-23 07:17:21 +02:00
Daniel Eklöf
22c8637610
osc: extend damage-cells-by-color to default fg/bg as well
When changing part of the color palette, through either OSC-4, or
OSC-10 and OSC-11 (and the corresponding reset OSCs: 104, 110 and
111), only dirty affected cells.

We've always done this, but only for OSC-4.

This patch breaks out that logic, and extends it to handle default
fg/bg too.

It also fixes a bug where cells with colored underlines were not
dirtied if the underline was the only part of the cell that was
affected by a OSC-4 change.
2024-07-03 10:53:33 +02:00
Daniel Eklöf
d440d5aa2c
osc: 10/11/12/17/19: don't apply overly much damage 2024-07-03 09:47:51 +02:00
Daniel Eklöf
5d4a002413
osc: merge OSC 10/11/12/17/19 handling
10/11/17/19 were already merged, so this patch just stops special
casing 12 (cursor color).

In preparation for XTPUSHCOLORS/XTPOPCOLORS, the cursor colors are
moved from their own struct, into the 'colors' struct.

Also fix a bug where OSC 17/19 queries returned OSC-11 data.
2024-07-03 09:47:30 +02:00
Daniel Eklöf
f3d848da01
osc: 52: treat OSC-52 replies as paste data (after all, they are)
This fixes an issue where other data (such as replies to other
requests) being interleaved with the OSC-52 reply.

The patch piggy backs on the already existing mechanism for handling
regular pastes, where other data is queued up until the paste is done.

There's one corner case that won't work; if the user *just* did a
normal paste (i.e. at virtually the same time the application
requested OSC-52 data), the OSC-52 request will return an empty reply.

Likewise, if there are multiple OSC-52 requests at the same time, only
the first will return data.

Closes #1734
2024-06-09 10:14:57 +02:00
Daniel Eklöf
23ada09d14
osc: reject notifications with invalid UTF-8 strings 2024-04-15 16:02:54 +02:00
Daniel Eklöf
4b075bb075
osc: 176 (app-id): implement query+reply
Applications can now query for the current app-id with:

    \E] 176 ; ? \E\\

The reply is

    \E] 176 ; <title> \E\\
2024-02-06 13:55:30 +01:00
delthas
6c56b04b3f
osc: add support for osc 176 (app ID)
This adds support for a new OSC escape sequence: OSC 176, that lets
terminal programs tell the terminal the name of the app that is
running. foot then sets the app ID of the toplevel to that ID,
which lets the compositor know which app is running, and typically
sets the appropriate icon, window grouping, ...

See: https://gist.github.com/delthas/d451e2cc1573bb2364839849c7117239
2024-02-06 13:50:09 +01:00
Daniel Eklöf
7999975016
Don't use fancy Unicode quotes, stick to ASCII 2024-02-06 12:36:45 +01:00
Daniel Eklöf
e9607de5ae
osc: store column of FTCS_COMMAND_{EXECUTED,FINISHED} in row struct 2024-02-06 12:12:57 +01:00
Daniel Eklöf
f8e875a7cd
term: move row->prompt_marker into new struct, row->shell_integration 2024-02-06 12:12:56 +01:00