Skip to content

Fix erroneous scroll when using X/Y offsets in images - #10256

Merged
kovidgoyal merged 1 commit into
kovidgoyal:masterfrom
jquast:jq/bugfix-img-xyoff-scrolling
Jul 13, 2026
Merged

kovidgoyal merged 1 commit into
kovidgoyal:masterfrom
jquast:jq/bugfix-img-xyoff-scrolling

Conversation

@jquast

@jquast jquast commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

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 add cell_x_offset a second time.

The cursor then is placed too far down, often causing erroneous scrolling when displaying images near the center of the screen when also using X= and Y= offsets, as demonstrated by this demo script:

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()

Before

Before, second rectangle causes erroneous scroll:

kitty-img-before-scrollbug.mp4

After, cursor positioned correctly

kitty-img-after-scrollbug.mp4

Solution

Add auto_cols and auto_rows to remember the original read-only values before exercising their auto-calculated size.

note that 'auto_rows isn't technically necessary given the logic branching, but it describes in code better.

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.
@kovidgoyal
kovidgoyal merged commit 2b7ac11 into kovidgoyal:master Jul 13, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants