niri for some reason known only to itself does not send any pointer
leave/data device enter/data source events when it accepts a grab. The
only event it seems to send is surface enter on the drag icon surface,
and that too it sends that event much later.
Handle this bonkers behavior by retrying the sync multiple times to
detect if niri has accepted the drag or not.
Fixes#10271
The first OS window on Wayland is created at scale 1 because the
compositor only sends the fractional scale after the surface exists.
The initial size in cells is therefore computed with scale-1 cell
metrics and the window is mapped a few cells too small. The existing
post-map recompute calls glfwSetWindowSize(), but on Wayland that loses
to the compositor's authoritative configure, which re-asserts the size
it recorded at map time. So a window that receives focus (the normal
interactive case) stays too small; a background window that never gets
an activated configure happens to keep the resized value, which is why
it can look fixed.
Correct the size while the window is still unmapped instead. GLFW gains
a hook (glfwWaylandSetInitialWindowSizeCallback) that it invokes when
the fractional scale is applied during creation -- mutter, kwin and niri
send the scale before the first configure -- letting the embedder
recompute the cell-based logical size for the real scale before the
window is mapped. The compositor then records the correct size and its
activation configure agrees, so there is nothing to race.
The existing post-map recompute is kept as a fallback for compositors
that only send the scale after the first configure (sway, Hyprland).
Also add glfwCocoaSetWindowLevel to the glfw.py wrapper generator list:
it was present in the committed glfw-wrapper but missing from the
generator, so regenerating the wrapper (required to add the hook above)
would otherwise drop it and break the macOS build.
This escape code is largely undefined. There is no specification for how
it affects alternate screen mode, overriden colors, kitty keyboard
state, paused rendering, etc. Do what I feel is sensible in these cases.
Fixes#10263
Problem
-------
In update_dest_rect() when both num_cols and num_rows are 0
(auto-computed, ``a=T``), the first block computes num_cols with
cell_x_offset, but, then the second block mismatches num_cols, causing
it to compute width_px from num_cols and adds cell_x_offset a second
time. The returned value is large enough that it often causes scrolling,
depending on size and location of the screen.
A sample visual program:
```python
import zlib, base64, time
from functools import partial
echo = partial(print, end='', flush=True)
echo('\033[H\033[J')
base = bytes([0, 128, 0, 255]) * 640 * 576
k = zlib.compress(keyframe, 3)
echo(f'\033[8;60H\033_Ga=T,i=1,q=1,f=32,s=640,v=576,o=z,N=1;{base64.b64encode(k).decode()}\033\\')
time.sleep(1)
delta = bytes([200, 0, 0, 255]) * 32 * 512
d = zlib.compress(delta, 3)
echo(f'\033[9;67H\033_Ga=T,i=100,q=1,f=32,s=32,v=512,o=z,N=1,X=9,Y=25;{base64.b64encode(d).decode()}\033\\')
time.sleep(1)
print()
```
Solution
--------
Add 'auto_cols' and 'auto_rows' to remember the original read-only
values before exercising their auto-calculated size. 'auto_rows' isn't
technically necessary given the logic branching but it describes in code
better.
Before and After video
----------------------
A video will be attached shortly, here.
Add a benchmark stream containing 262,144 distinct base-plus-combining-mark cells per repetition so TextCache collection cost remains visible instead of collapsing into cache hits.
Co-Authored-By: Claude <noreply@anthropic.com>
Move the periodic collection check to PREPARE_FOR_DRAW_TEXT so ordinary and fixed-width text share one safe integration point, while tab handling no longer initiates collection.
Reset the additions counter only after the live-cell remap completes successfully.
Co-Authored-By: Claude <noreply@anthropic.com>
Programs that hide the cursor with DECTCEM but keep moving it causes
the trail to run a full animation after every cursor move, which is
unnecessary since the cursor is invisible.
When the cursor is hidden and the trail has fully faded out, snap the
trail corners to the cursor position instead of animating them. The
trail still tracks the hidden cursor, so switching focus to or away
from such a window still animates the trail.
glibc can raise its dynamic mmap threshold above these MB-scale allocations, routing later scrollback segments through brk. Closing windows then leaves the freed segments stranded in allocator bins and grows the long-lived kitty process.
Back the existing batched segment layout with anonymous mappings instead. This preserves zero-initialization and pointer layout while ensuring the memory is returned to the OS when a history buffer is cleared or destroyed.
Co-Authored-By: Claude <noreply@anthropic.com>
_glfwPlatformCreateWindow() ignored the return value of
attach_opengl_context_to_window(), so when EGL is unavailable (for
example libEGL cannot be loaded) it reported success with
window->context left zeroed. glfwCreateWindow() then proceeded to
_glfwRefreshContextAttribs() -> glfwMakeContextCurrent(), which calls
the NULL context.makeCurrent pointer: kitty crashes with SIGSEGV
instead of reporting "Failed to create GLFWwindow. This usually
happens because of old/broken OpenGL drivers." as intended. The X11
backend already propagates these failures.
Co-Authored-By: Claude <noreply@anthropic.com>
The TextCache interns every unique multi-codepoint cell text for the
lifetime of the window with no eviction, so a stream of unique texts
(for example random combining mark sequences) grows memory without
bound, several hundred MB/hour at moderate throughput.
Mirror the existing hyperlink pool garbage collection: every 8192
newly interned entries, steal the cache contents and have the Screen
remap the index in every live cell (history buffer, main and alt line
buffers, paused rendering snapshot and overlay line), re-interning
only entries still referenced by some cell. Entries whose last
reference scrolled out of the history buffer are freed.
See #10249
Co-Authored-By: Claude <noreply@anthropic.com>