When split horizontally, selecting multiple lines at the top of the left
pane could paint a horizontal selection line all the way across the rest
of the terminal to the right hand edge.
Removes the dependency on knowing where the pane top/left position
is so that the line render routine could be used in more places.
Adjusts the tab bar and scroll bar positioning so that the tab bar
ignores window padding and is always flush with the top/bottom window
edge (full width as well), and that the scroll bar top/bottom respects
the tab bar position and height.
More of a "fix"; we use some heuristics based on the bearing
and glyph width to figure out if a sequence looks like a funky
ligature that moves left to render the glyph.
This may be prone to false positives, but the consequences are low:
when we think a glyph is part of a ligature, then rather than using
the cursor_fg color (which is typically black, or close to invisible),
we retain the normal text fg color.
This way the portion of the glyph outside of the cursor retains its
foreground color, and just the cell containing the cursor may have
a slightly funky fg color in the case where the heuristic was bad.
closes: #478
`use_fancy_tab_bar` switches to an alternate rendering of the tab
bar that uses the window_frame config to get a proportional
title font to use to render tabs, as well as rendering a few
additional elements to space out and make the tabs feel more
like tabs.
Computing the number of tabs doesn't respect the alternate font
at this time.
Formatted tab item foreground and background colors are also
not respected at this time.
refs: #1180
We now compute the cap-height from the rasterized glyph data.
Moved the scaling action of use_cap_height_to_scale_fallback_fonts from
glyphcache into the font resolver: when enabled, and we have data
about the baseline font and the font being resolved, then the resolving
font will be scaled such that the cap-height of both fonts has the same
pixel size.
The effect of this is that `I` glyphs from both fonts should appear to
have the same height.
Added a row of `I`'s in differing styles at the bottom of styles.txt
to make this easier to visualize.
refs: #1189
This is to handle situations such as some versions of the Terminus
bitmap font, where the individual bitmap strike sizes are broken
out across multiple individual files.
Font matching now passes down the nominal pixel height based on
the current DPI and font scale factor, and will use that to select
the font file that has the closest pixel size.
Previously, it would be potentially undefined which of the Terminus
font files would be selected.
refs: https://github.com/wez/wezterm/issues/1189
This commit adjusts the the window event routing/queuing so that
a queued event can capture a pane_id other than the focused pane.
Since we only allow one queued instance of a given named event in a
window, a consequence of this is that multiple bell events coming
from different panes at the same time may race and the loser's
event will be dropped. We log a warning in that case.
refs: #3
This commit introduces a mechanism for specifying resize increments
for a window, and then arranges for the termwindow to set those
to match the current font cell metrics.
This should help to avoid cases where there is excess padding pixels
resulting from the window being slightly larger than computed number
of cells and the font metrics.
Fast-clicking users generally expect to be able to rapidly do regular selections
or otherwise cancel double/triple/quad clicks, so significant mouse movement should end the streak.
Allowing tiny pixel movements to account for touchpads is necessary.
Fortunately, the position here is already in character grid cells, which provides enough margin for this.
Other code editors like gedit also seem to do this based on the character grid.
It appears as though kakoune hides the terminal cursor and renders
its own version of the cursor.
The hidden state was being picked up by the copymode overlay,
making it awkward to use.
This commit forces the cursor to be visible (and a block) when
copy mode is active.
closes: #1113
I think this is a hangover from the older logic to figure out
the initial sizing, and I suspect that it is what is causing
refs: 1074
So this is a speculative change to see if it helps!
This splits rendering into 3 passes:
* background pass for z-index < 0. This is for solid background colors,
background images, and image attachments with z-index < 0.
Rendered with regular alpha blending.
* glyph pass: for glyphs at z-index==0. This is rendered with dual
source blending enabled to facilitate subpixel aa appearance.
* top layer pass for z-index >= 0 graphics. This is rendered with
regular alpha blending.
This avoids weird effects, like images with alpha shining through
the back of the window when the window itself isn't transparent.
refs: #544
transparent images weren't always blending correctly, and were
instead shining through.
This might also have affected cursors.
It may also be a factor in a couple of recent reports of excessive
boldness which looked like funky over-alpha multiplication.
Let's see what people say about this.
This makes the comparison in https://github.com/wez/wezterm/issues/544
work for me on mac, linux (x11, wayland) and also on Windows but
only using WGL.
It looks like we can use the proper colorspace on all targets
except for ANGLE EGL. For whatever reason, the combination of
glium and ANGLE EGL on windows over-gamma corrects.
AFAICT, the framebuffer and perhaps the surfaces it creates
don't indicate srgb support, and whatever combination of status
they return tickles glium's srgb stuff the wrong way.
I think the "solution" is just to directly use WGL by default.
EGL was on by default because it tended to be more survivable
when graphics card drivers were updated, but the last couple
of times I updated mine it still killed wezterm anyway.
refs: #544
Add a more general dragging thingy and use that to know when we
are dragging splits or the scroll thumb.
Fixup scrollbar math, which didn't account for whether the tabbar
was shown and which might cause the scroll thumb to jump around
on first drag (resolves#568)
The idea here is to make it a bit easier to do hit detection for UI
elements; today we've been duplicating position math between the render
and the mouse movement handlers, with both pieces of code knowing the
location of the UI element.
UIItem allows the render phase to record the position, which allows
the mouse phase to be a more independent lookup against the registered
elements.
This makes it easier to add more UI elements in the future.
If a cell contained a ligature, the math used to track where the
next quad was going to be placed could lose consistency with
the cluster/shaping information and result in offset glyphs.
This was most noticeable to me in tab titles in the tab bar;
my shell dotfiles append `-- something` to the title when a
command is launched, and the `--` is a ligature in my font.
I think I've also seen this mess up positioning in the notcurses
demo as well.
The solution is to take the cluster initial cell index rather
than trying to reverse engineer it from incomplete info.
This commit annotates fonts with a boolean that indicates whether
we think it contains glyphs with emoji presentation, and then
passes the cluster.presentation field down to the shaper.
If the presentation doesn't match the current font in the fallback,
then it will be skipped until we exhaust its options.
`wezterm ls-fonts` also shows whether we think a font has emoji
presentation.
refs: #997
This replaces the slightly gnarly subpixel enabled blending in the
shader with Dual Source Blending, which is a technique where the
fragment shader can specify both the primary color (RGBA) as well
as an additional per-channel mask that can be used to alpha blend
with the destination.
This enables artifact-free alpha blending when used together
with a transparent window background.
refs: https://github.com/wez/wezterm/issues/932
Terminal now maintains a sequence number that increments
for each Action that is applied to it.
Changes to lines are tagged with the current sequence number.
This makes it a bit easier to reason about when an individual
line has changed relative to some point in "time"; the consumer
of the terminal can sample the current sequence number and then
can later determine which lines have changed since that point
in time.
refs: https://github.com/wez/wezterm/issues/867
Use the newer logical line method in pane rather than going
via the hyperlink function, so that we can better reason
about physical vs. logical line breaks, and get the results
very slightly faster too.
refs: #874
We were previously only remembering the most recently pressed
button, but that's a lossy thing to do.
This commit remembers the button presses so that we can correctly
report all press/release events.
refs: #973
I think this is the heart of the initial size issues:
during creation, if the dpi or size is different, we generate
a resize event, but because it is dispatched before we've
assigned self.window, we weren't able to resize the window
to fit.
This commit passes the Window object down to the resize
handler so that it can do that; the diff is conceptually
small but there is corresponding fanout around ensuring
that the Window is passed down through all the resize
related codepaths that need it.
refs: #1002
refs: #695
It seems like this is making things worse on X11/Wayland.
Let's try simply skipping it--that seems fine on X11/Wayland,
but needs to be verified on macOS and Windows.
refs: #1002
refs: #695
The intent is to avoid weirdness with Wayland where we need to wait for
a configure event before we try to set the window size programmatically.
refs: #1002
WindowState is a bitfield that can represent maximized, full screen
and hidden window states.
WindowState is passed along with resize events, improving on the
prior basic is_full_screen boolean by representing the other states.
Notably, WindowState::MAXIMIZED is used to represent a state where
the window's size is constrained by some window environment function;
it could be due to the window being maximized in either or both the
vertical or horizontal directions, or by the window being in a tiled
state on any edge.
When the window is MAXIMIZED, wezterm will behave as though
`adjust_window_size_when_changing_font_size = false` because it knows
that it cannot adjust the window size in that state.
This potentially helps with #695, depending on whether the window
manager propagates this state information to wezterm. Gnome/mutter
does a good job at this with both X11 and Wayland, but I couldn't get
sway to report these states and I don't know of any other tiling wm
that I can easily install and use on fedora, so there's a question
mark around that.
This commit changes the full surface fill to be fully transparent,
and adds a separate quad to fill with the configured window background
color.
The thesis is that this should avoid the apparent weird rgb/srgb
mismatch that seems to occur with the window background on Intel macs
(those have a different OpenGL implementation than M1 based macs which
don't appear to have this issue).
refs: https://github.com/wez/wezterm/issues/1000
refs: https://github.com/wez/wezterm/issues/653
I noticed that on macos, the initial terminal size didn't
match the 80x24 default; it was a few columns short.
I think I broke this with recent changes in window
event dispatching.
This commit passes the terminal size down to apply_dimensions
just after we've set up the GL context to preserve the
terminal size.
Possibly related to https://github.com/wez/wezterm/issues/1002
This should help to avoid artifacts in the case where glyphs
render outside their nominal terminal cell (happens when the
shaper tweaks positioning, and/or when ligatures are involved).
Previously we'd render the layers in z-index order for cell N
before the layers in z-index order for cell N+1.
If N had an image that overlayed the text (nominally z-index 0.5!)
and the glyph in N+1 (z-index 0) was slightly to the left of its
border, then it could layer incorrectly over the cell to the left.
The underlying types in termwiz support 10-bit color, but in our
conversion to the data we pass to the vertex, we were forcing it
into 8-bit and then converting to float.
Simplify this by skipping the intermediate 8-bit representation
and just go directly to float.
I'm not sure if this is needed now that we have a single draw call, but
based on the history and the nuance of different gl/driver/os quirks it
feels like a good idea to keep this option in the back pocket.
Since we can now mutate individual frames, we need to avoid
falsely caching across a change; switch from using (image_id, frame_idx)
to frame_hash.
refs: #986
Adds a use_image feature to termwiz that enables an optional
dep on the image crate. This in turn allows decoding of animation
formats (gif, apng) from file data, but more crucially, allows
modeling animation frames at the termwiz layer, which is a pre-req
for enabling kitty img protocol animation support.
refs: #986
Rather than leaving the frame un-rendered, this commit arranges
to make one last pass but with all image quad assignments skipped.
This should at least make a reasonable effort at displaying text
on the screen.
refs: https://github.com/wez/wezterm/issues/879
I noticed when running the notcurses demo that we're spending a
decent amount of time decoding png data whenever we need to
re-do the texture atlas.
Let's avoid that by allowing for ImageData at the termwiz layer
to represent both the image file format and decoded rgba8 data.
This commit is a bit muddy and also includes some stuff to try
to delete placements from the model. It's not perfect by any
means--more expensive than I want, and there's something funky
that causes a large number of images to build up during some
phases of the demo.
refs: #986
OpenGL will silently let us allocate a texture larger than the GPU can
bind to a sampler, reporting the error status out of band and leaving
the display in a perma-broken state.
This commit deliberately checks against the max texture size and raises
an error in that case.
The recovery story isn't perfect, but at least the texture remains
usable, so the user can clear the screen and still be able to see glyphs
afterwards.
refs: https://github.com/wez/wezterm/issues/879
Taking further advantage of dynamic quad allocation, we can now
remove the multiple render passes in favor of allocating the quads
and painting them from back to front.
In turn, this means that we can reduce the amount of data that we
store in the vertex, which simplifies the shaders a bit, at the
expense of making the render code in rust a bit more complex.
However, we can take advantage of stretching runs of cells with
background colors in to a single quad.
refs: #986
This was added in 365a68dfb8 to free the
orca from its cage. With the recent dynamic quad allocation changes, we
don't need a distinct 4th pass any more and can simply layer a separate
quad on top of the glyph quad.
refs: #986
This removes the pre-allocated (at resize) number of quads
and replaces it with a dynamic mechanism that tracks how many
quads are needed for a frame and then will re-allocate and
re-render when there weren't enough.
We start with 1024 quads and try to allocate in multiples
of 1024 quads.
refs: #986
This commit removes the `Quads` struct which maintained pre-defined quad
indices for each of the cells, the background image and scrollbar thumb.
In its place, we now "dynamically" hand out quads to meet the needs of
what is being rendered. There are some efficiency gains here with
things like the selection (which can now be a single stretched quad,
rather than `n` quads in width).
This isn't a fully dynamic allocation scheme, as we still allocate the
current worst case number of quads when resizing.
A following commit will adjust that so that we allocate a ballpark and
then employ a mechanism similar to OutOfTextureSpace to grow and retry a
render pass when we need more quads.
Futhermore, this dynamic approach may allow reducing the amount of stuff
we have in the Vertex and "simply" render some quads before others so
that we don't have to have so many draw() passes to build up the
complete scene.
refs: #986