mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Merge branch 'master' into releases/1.7
This commit is contained in:
commit
0d0ebebb64
21 changed files with 464 additions and 263 deletions
35
CHANGELOG.md
35
CHANGELOG.md
|
|
@ -1,5 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
* [Unreleased](#unreleased)
|
||||
* [1.7.0](#1-7-0)
|
||||
* [1.6.4](#1-6-4)
|
||||
* [1.6.3](#1-6-3)
|
||||
|
|
@ -23,6 +24,40 @@
|
|||
* [1.2.0](#1-2-0)
|
||||
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
### Changed
|
||||
|
||||
* Update PGO build instructions in `INSTALL.md`
|
||||
(https://codeberg.org/dnkl/foot/issues/418).
|
||||
* In scrollback search mode, empty cells can now be matched by spaces.
|
||||
|
||||
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Logic that repairs invalid key bindings ended up breaking valid key
|
||||
bindings instead (https://codeberg.org/dnkl/foot/issues/407).
|
||||
* Custom `line-height` settings now scale when increasing or
|
||||
decreasing the font size at run-time.
|
||||
* Newlines sometimes incorrectly inserted into copied text
|
||||
(https://codeberg.org/dnkl/foot/issues/410).
|
||||
* Crash when compositor send `text-input-v3::enter` events without
|
||||
first having sent a `keyboard::enter` event
|
||||
(https://codeberg.org/dnkl/foot/issues/411).
|
||||
* Deadlock when rendering sixel images.
|
||||
* URL labels, scrollback search box or scrollback position indicator
|
||||
sometimes not showing up, caused by invalidly sized surface buffers
|
||||
when output scaling was enabled
|
||||
(https://codeberg.org/dnkl/foot/issues/409).
|
||||
* Empty sixels resulted in non-empty images.
|
||||
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Added
|
||||
|
|
|
|||
29
INSTALL.md
29
INSTALL.md
|
|
@ -65,6 +65,7 @@ In addition to the dev variant of the packages above, you need:
|
|||
* wayland protocols
|
||||
* ncurses (needed to generate terminfo)
|
||||
* scdoc (for man page generation)
|
||||
* llvm (for PGO builds with Clang)
|
||||
* [tllist](https://codeberg.org/dnkl/tllist) [^1]
|
||||
|
||||
A note on compilers; in general, foot runs **much** faster when
|
||||
|
|
@ -184,21 +185,15 @@ slower!) binary.
|
|||
First, configure the build directory:
|
||||
|
||||
```sh
|
||||
export CFLAGS="$CFLAGS -O3 -Wno-missing-profile"
|
||||
export CFLAGS="$CFLAGS -O3"
|
||||
meson --buildtype=release --prefix=/usr -Db_lto=true ../..
|
||||
```
|
||||
|
||||
It is **very** important `-O3` is being used here, as GCC-10.1.x and
|
||||
later have a regression where PGO with `-O2` is **much** slower.
|
||||
|
||||
If you are using Clang instead of GCC, use the following `CFLAGS` instead:
|
||||
|
||||
```sh
|
||||
export CFLAGS="$CFLAGS -O3 \
|
||||
-Wno-ignored-optimization-argument \
|
||||
-Wno-profile-instr-out-of-date \
|
||||
-Wno-profile-instr-unprofiled"
|
||||
```
|
||||
Clang users **must** add `-Wno-ignored-optimization-argument` to
|
||||
`CFLAGS`.
|
||||
|
||||
Then, tell meson we want to _generate_ profiling data, and build:
|
||||
|
||||
|
|
@ -234,6 +229,8 @@ We will use the `pgo` binary along with input corpus generated by
|
|||
`scripts/generate-alt-random-writes.py`:
|
||||
|
||||
```sh
|
||||
./footclient --version
|
||||
./foot --version
|
||||
tmp_file=$(mktemp)
|
||||
../../scripts/generate-alt-random-writes \
|
||||
--rows=67 \
|
||||
|
|
@ -253,7 +250,12 @@ tmp_file=$(mktemp)
|
|||
rm ${tmp_file}
|
||||
```
|
||||
|
||||
The snippet above first creates an (empty) temporary file. Then, it
|
||||
The first step, running `./foot --version` and `./footclient
|
||||
--version` might seem unnecessary, but is needed to ensure we have
|
||||
_some_ profiling data for functions not covered by the PGO helper
|
||||
binary. Without this, the final link phase will fail.
|
||||
|
||||
The snippet above then creates an (empty) temporary file. Then, it
|
||||
runs a script that generates random escape sequences (if you cat
|
||||
`${tmp_file}` in a terminal, you’ll see random colored characters all
|
||||
over the screen). Finally, we feed the randomly generated escape
|
||||
|
|
@ -271,14 +273,19 @@ This method requires a running Wayland session.
|
|||
We will use the script `scripts/generate-alt-random-writes.py`:
|
||||
|
||||
```sh
|
||||
./footclient --version
|
||||
foot_tmp_file=$(mktemp)
|
||||
./foot --config=/dev/null --term=xterm sh -c "<path-to-generate-alt-random-writes.py> --scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline ${foot_tmp_file} && cat ${foot_tmp_file}"
|
||||
./foot --config=/dev/null --term=xterm sh -c "<path-to-generate-alt-random-writes.py> --scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel ${foot_tmp_file} && cat ${foot_tmp_file}"
|
||||
rm ${foot_tmp_file}
|
||||
```
|
||||
|
||||
You should see a foot window open up, with random colored text. The
|
||||
window should close after ~1-2s.
|
||||
|
||||
The first step, `./footclient --version` might seem unnecessary, but
|
||||
is needed to ensure we have _some_ profiling data for
|
||||
`footclient`. Without this, the final link phase will fail.
|
||||
|
||||
|
||||
##### Use the generated PGO data
|
||||
|
||||
|
|
|
|||
77
PKGBUILD
77
PKGBUILD
|
|
@ -14,37 +14,70 @@ pkgver() {
|
|||
}
|
||||
|
||||
build() {
|
||||
local compiler=other
|
||||
local do_pgo=no
|
||||
|
||||
# makepkg uses -O2 by default, but we *really* want -O3
|
||||
# -Wno-missing-profile since we're not exercising everything when doing PGO builds
|
||||
export CFLAGS+=" -O3 -Wno-missing-profile"
|
||||
CFLAGS+=" -O3"
|
||||
|
||||
# Figure out which compiler we're using, and whether or not to do PGO
|
||||
case $(${CC-cc} --version) in
|
||||
*GCC*)
|
||||
compiler=gcc
|
||||
do_pgo=yes
|
||||
;;
|
||||
|
||||
*clang*)
|
||||
compiler=clang
|
||||
|
||||
# We need llvm to be able to manage the profiling data
|
||||
if command -v llvm-profdata > /dev/null; then
|
||||
do_pgo=yes
|
||||
|
||||
# Meson adds -fprofile-correction, which Clang doesn't
|
||||
# understand
|
||||
CFLAGS+=" -Wno-ignored-optimization-argument"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
meson --prefix=/usr --buildtype=release --wrap-mode=nofallback -Db_lto=true ..
|
||||
|
||||
find -name "*.gcda" -delete
|
||||
meson configure -Db_pgo=generate
|
||||
ninja
|
||||
if [[ ${do_pgo} == yes ]]; then
|
||||
find -name "*.gcda" -delete
|
||||
meson configure -Db_pgo=generate
|
||||
ninja
|
||||
|
||||
script_options="--scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel"
|
||||
local script_options="--scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel"
|
||||
|
||||
tmp_file=$(mktemp)
|
||||
tmp_file=$(mktemp)
|
||||
|
||||
if [[ -v WAYLAND_DISPLAY ]]; then
|
||||
./foot \
|
||||
--config /dev/null \
|
||||
--term=xterm \
|
||||
sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}"
|
||||
else
|
||||
../scripts/generate-alt-random-writes.py \
|
||||
--rows=67 \
|
||||
--cols=135 \
|
||||
${script_options} \
|
||||
${tmp_file}
|
||||
./pgo ${tmp_file} ${tmp_file} ${tmp_file}
|
||||
if [[ -v WAYLAND_DISPLAY ]]; then
|
||||
./footclient --version
|
||||
./foot \
|
||||
--config /dev/null \
|
||||
--term=xterm \
|
||||
sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}"
|
||||
else
|
||||
./footclient --version
|
||||
./foot --version
|
||||
../scripts/generate-alt-random-writes.py \
|
||||
--rows=67 \
|
||||
--cols=135 \
|
||||
${script_options} \
|
||||
${tmp_file}
|
||||
./pgo ${tmp_file} ${tmp_file} ${tmp_file}
|
||||
fi
|
||||
|
||||
rm "${tmp_file}"
|
||||
|
||||
if [[ ${compiler} == clang ]]; then
|
||||
llvm-profdata merge default_*profraw --output=default.profdata
|
||||
fi
|
||||
|
||||
meson configure -Db_pgo=use
|
||||
fi
|
||||
|
||||
rm "${tmp_file}"
|
||||
|
||||
meson configure -Db_pgo=use
|
||||
ninja
|
||||
}
|
||||
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -345,22 +345,23 @@ This is not how it is meant to be. Fonts are measured in _point sizes_
|
|||
**for a reason**; a given point size should have the same height on
|
||||
all mediums, be it printers or monitors, regardless of their DPI.
|
||||
|
||||
Foot will always use the monitor's physical DPI value. Scale factors
|
||||
are irrelevant (well, they affect e.g. padding, but not the font
|
||||
size). This means the glyphs rendered by foot should always have the
|
||||
same physical height, regardless of monitor.
|
||||
Foot’s default behavior is to use the monitor’s DPI to size fonts when
|
||||
output scaling has been disabled. On monitors where output scaling has
|
||||
been enabled, fonts will instead be sized using the scaling
|
||||
factor.
|
||||
|
||||
Foot will re-size the fonts on-the-fly when the window is moved
|
||||
between screens with different DPIs values. If the window covers
|
||||
This can be changed to either **always** use the monitor’s DPI
|
||||
(regardless of scaling factor), or to **never** use it. See the
|
||||
`dpi-aware` option in `foot.ini`. See the man page, **foot.ini**(5)
|
||||
for more information.
|
||||
|
||||
When fonts are sized using the monitor’s DPI, glyphs should always
|
||||
have the same physical height, regardless of monitor.
|
||||
|
||||
Furthermore, foot will re-size the fonts on-the-fly when the window is
|
||||
moved between screens with different DPIs values. If the window covers
|
||||
multiple screens, with different DPIs, the highest DPI will be used.
|
||||
|
||||
Starting with foot-1.6, the _default_ behavior is to use the monitor’s
|
||||
DPI to size fonts when output scaling has been disabled. On monitors
|
||||
where output scaling has been enabled, fonts will instead be sized
|
||||
using the scaling factor. This can be changed with the `dpi-aware`
|
||||
option in `foot.ini`. See the man page, **foot.ini**(5) for more
|
||||
information.
|
||||
|
||||
_Note_: if you configure **pixelsize**, rather than **size**, then DPI
|
||||
changes will **not** change the font size. Pixels are always pixels.
|
||||
|
||||
|
|
|
|||
6
client.c
6
client.c
|
|
@ -35,8 +35,10 @@ static const char *
|
|||
version_and_features(void)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "version: %s %cime",
|
||||
FOOT_VERSION, feature_ime() ? '+' : '-');
|
||||
snprintf(buf, sizeof(buf), "version: %s %cime %cpgo",
|
||||
FOOT_VERSION,
|
||||
feature_ime() ? '+' : '-',
|
||||
feature_pgo() ? '+' : '-');
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
|||
6
config.h
6
config.h
|
|
@ -53,12 +53,6 @@ struct config_mouse_binding {
|
|||
struct config_binding_pipe pipe;
|
||||
};
|
||||
|
||||
/* If px != 0 then px is valid, otherwise pt is valid */
|
||||
struct pt_or_px {
|
||||
int16_t px;
|
||||
float pt;
|
||||
};
|
||||
|
||||
struct config_spawn_template {
|
||||
char *raw_cmd;
|
||||
char **argv;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ terminal. This is done **20** times for each test. Then it calculates
|
|||
the _mean_ and _standard deviation_ for each test.
|
||||
|
||||
|
||||
## 2020-10-09
|
||||
## 2021-03-20
|
||||
|
||||
### System
|
||||
|
||||
|
|
@ -41,16 +41,16 @@ Scrollback: 10000 lines
|
|||
### Results
|
||||
|
||||
|
||||
| Benchmark | Foot (GCC+PGO) 1.5.0.r90 | Foot 1.5.0.r90 | Alacritty 0.5.0 | URxvt 9.22 | XTerm 360 |
|
||||
|------------------------|-------------------------:|---------------:|-------------------:|---------------:|---------------:|
|
||||
| alt-random | 0.353s ±0.007 | 0.685s ±0.005 | 0.903s ±0.011 | 1.102s ±0.004 | 12.886s ±0.064 |
|
||||
| alt-random-colors | 0.354s ±0.019 | 0.665s ±0.004 | 0.933s ±0.004 | 1.149s ±0.013 | 11.739s ±0.093 |
|
||||
| scrolling | 1.387s ±0.077 | 1.257s ±0.032 | 1.048s ±0.011 | 1.001s ±0.023 | 38.187s ±0.192 |
|
||||
| scrolling-filled-lines | 0.607s ±0.008 | 0.834s ±0.038 | 1.246s ±0.020 | 1.224s ±0.008 | 6.619s ±0.166 |
|
||||
| unicode-random | 0.224s ±0.001 | 0.144s ±0.001 | 0.092s ±0.004 [^1] | 21.294s ±1.580 | 26.594s ±3.801 |
|
||||
| Benchmark | Foot (GCC+PGO) 1.7.0.r2 | Foot 1.7.0.r2 | Alacritty 0.7.2 | URxvt 9.22 | XTerm 366 |
|
||||
|------------------------|------------------------:|--------------:|-------------------:|---------------:|---------------:|
|
||||
| alt-random | 0.382s ±0.003 | 0.550s ±0.007 | 0.995s ±0.010 | 1.201s ±0.006 | 12.756s ±0.045 |
|
||||
| alt-random-colors | 0.380s ±0.002 | 0.543s ±0.003 | 1.017s ±0.013 | 1.399s ±0.018 | 11.591s ±0.141 |
|
||||
| scrolling | 1.302s ±0.019 | 1.284s ±0.052 | 1.107s ±0.028 | 1.097s ±0.015 | 37.537s ±0.121 |
|
||||
| scrolling-filled-lines | 0.646s ±0.016 | 0.610s ±0.003 | 1.290s ±0.012 | 1.325s ±0.037 | 6.817s ±0.084 |
|
||||
| unicode-random | 0.167s ±0.001 | 0.276s ±0.445 | 0.097s ±0.002 [^1] | 18.032s ±0.334 | 29.731s ±3.746 |
|
||||
|
||||
|
||||
## 2020-12-21
|
||||
## 2021-03-20
|
||||
|
||||
### System
|
||||
|
||||
|
|
@ -73,13 +73,13 @@ Scrollback=10000 lines
|
|||
### Results
|
||||
|
||||
|
||||
| Benchmark | Foot (GCC+PGO) 1.6.0.r30 | Foot (no PGO) 1.6.0.r30 | Alacritty 0.6.0 | URxvt 9.22 | St 0.8.4 | XTerm 362 |
|
||||
|------------------------|-------------------------:|------------------------:|-------------------:|-----------------:|--------------:|----------------:|
|
||||
| alt-random | 0.734s ±0.051 | 1.186s ±0.101 | 1.580s ±0.083 | 1.709s ±0.090 | 1.953s ±0.038 | 38.693s ±0.298 |
|
||||
| alt-random-colors | 0.728s ±0.047 | 1.267s ±0.090 | 1.579s ±0.073 | 2.108s ±0.121 | 2.185s ±0.099 | 34.123s ±0.194 |
|
||||
| scrolling | 1.639s ±0.040 | 1.641s ±0.053 | 1.397s ±0.048 | 1.389s ±0.046 | 3.599s ±0.124 | 136.514s ±0.534 |
|
||||
| scrolling-filled-lines | 1.328s ±0.050 | 1.640s ±0.052 | 2.108s ±0.068 | 2.032s ±0.121 | 2.718s ±0.088 | 21.383s ±0.072 |
|
||||
| unicode-random | 0.304s ±0.018 | 0.271s ±0.017 | 0.143s ±0.002 [^1] | 20.543s ±0.098 | crashed | 16.013s ±0.253 |
|
||||
| Benchmark | Foot (GCC+PGO) 1.7.0.r2 | Foot (no PGO) 1.7.0.r2 | Alacritty 0.7.2 | URxvt 9.22 | St 0.8.4 | XTerm 366 |
|
||||
|------------------------|------------------------:|-----------------------:|-------------------:|-----------------:|--------------:|----------------:|
|
||||
| alt-random | 0.714s ±0.047 | 0.900s ±0.041 | 1.586s ±0.045 | 1.684s ±0.034 | 2.054s ±0.121 | 37.205s ±0.252 |
|
||||
| alt-random-colors | 0.736s ±0.054 | 0.950s ±0.082 | 1.565s ±0.043 | 2.150s ±0.137 | 2.195s ±0.154 | 33.112s ±0.167 |
|
||||
| scrolling | 1.593s ±0.070 | 1.559s ±0.055 | 1.517s ±0.079 | 1.462s ±0.052 | 3.308s ±0.133 | 134.432s ±0.436 |
|
||||
| scrolling-filled-lines | 1.178s ±0.044 | 1.309s ±0.045 | 2.281s ±0.086 | 2.044s ±0.060 | 2.732s ±0.056 | 20.753s ±0.067 |
|
||||
| unicode-random | 0.349s ±0.009 | 0.352s ±0.007 | 0.148s ±0.010 [^1] | 19.090s ±0.363 | crashed | 15.579s ±0.093 |
|
||||
|
||||
[^1]: [Alacritty and "unicode-random"](#alacritty-and-unicode-random)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,12 @@ static inline bool feature_ime(void)
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool feature_pgo(void)
|
||||
{
|
||||
#if defined(FOOT_PGO_ENABLED) && FOOT_PGO_ENABLED
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
171
ime.c
171
ime.c
|
|
@ -37,10 +37,6 @@ leave(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
struct seat *seat = data;
|
||||
LOG_DBG("leave: seat=%s", seat->name);
|
||||
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
if (term != NULL)
|
||||
term_ime_reset(term);
|
||||
|
||||
ime_disable(seat);
|
||||
seat->ime.focused = false;
|
||||
}
|
||||
|
|
@ -53,7 +49,7 @@ preedit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
|
||||
struct seat *seat = data;
|
||||
|
||||
ime_reset_preedit(seat);
|
||||
ime_reset_pending_preedit(seat);
|
||||
|
||||
if (text != NULL) {
|
||||
seat->ime.preedit.pending.text = xstrdup(text);
|
||||
|
|
@ -70,7 +66,7 @@ commit_string(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
|
||||
struct seat *seat = data;
|
||||
|
||||
ime_reset_commit(seat);
|
||||
ime_reset_pending_commit(seat);
|
||||
|
||||
if (text != NULL)
|
||||
seat->ime.commit.pending.text = xstrdup(text);
|
||||
|
|
@ -107,6 +103,7 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
|
||||
LOG_DBG("done: serial=%u", serial);
|
||||
struct seat *seat = data;
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
|
||||
if (seat->ime.serial != serial) {
|
||||
LOG_DBG("IME serial mismatch: expected=0x%08x, got 0x%08x",
|
||||
|
|
@ -114,16 +111,26 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
return;
|
||||
}
|
||||
|
||||
xassert(seat->kbd_focus);
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
if (term == NULL) {
|
||||
static bool have_warned = false;
|
||||
if (!have_warned) {
|
||||
LOG_WARN(
|
||||
"%s: text-input::done() received on seat that isn't "
|
||||
"focusing a terminal window", seat->name);
|
||||
have_warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* 1. Delete existing pre-edit text */
|
||||
if (term->ime.preedit.cells != NULL) {
|
||||
term_ime_reset(term);
|
||||
if (term->is_searching)
|
||||
render_refresh_search(term);
|
||||
else
|
||||
render_refresh(term);
|
||||
if (seat->ime.preedit.cells != NULL) {
|
||||
ime_reset_preedit(seat);
|
||||
|
||||
if (term != NULL) {
|
||||
if (term->is_searching)
|
||||
render_refresh_search(term);
|
||||
else
|
||||
render_refresh(term);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -139,12 +146,14 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
const char *text = seat->ime.commit.pending.text;
|
||||
size_t len = strlen(text);
|
||||
|
||||
if (term->is_searching) {
|
||||
search_add_chars(term, text, len);
|
||||
render_refresh_search(term);
|
||||
} else
|
||||
term_to_slave(term, text, len);
|
||||
ime_reset_commit(seat);
|
||||
if (term != NULL) {
|
||||
if (term->is_searching) {
|
||||
search_add_chars(term, text, len);
|
||||
render_refresh_search(term);
|
||||
} else
|
||||
term_to_slave(term, text, len);
|
||||
}
|
||||
ime_reset_pending_commit(seat);
|
||||
}
|
||||
|
||||
/* 4. Calculate surrounding text to send - not supported */
|
||||
|
|
@ -155,41 +164,41 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
: 0;
|
||||
|
||||
if (wchars == 0 || wchars == (size_t)-1) {
|
||||
ime_reset_preedit(seat);
|
||||
ime_reset_pending_preedit(seat);
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, convert to unicode */
|
||||
term->ime.preedit.text = xmalloc((wchars + 1) * sizeof(wchar_t));
|
||||
mbstowcs(term->ime.preedit.text, seat->ime.preedit.pending.text, wchars);
|
||||
term->ime.preedit.text[wchars] = L'\0';
|
||||
seat->ime.preedit.text = xmalloc((wchars + 1) * sizeof(wchar_t));
|
||||
mbstowcs(seat->ime.preedit.text, seat->ime.preedit.pending.text, wchars);
|
||||
seat->ime.preedit.text[wchars] = L'\0';
|
||||
|
||||
/* Next, count number of cells needed */
|
||||
size_t cell_count = 0;
|
||||
size_t widths[wchars + 1];
|
||||
|
||||
for (size_t i = 0; i < wchars; i++) {
|
||||
int width = max(wcwidth(term->ime.preedit.text[i]), 1);
|
||||
int width = max(wcwidth(seat->ime.preedit.text[i]), 1);
|
||||
widths[i] = width;
|
||||
cell_count += width;
|
||||
}
|
||||
|
||||
/* Allocate cells */
|
||||
term->ime.preedit.cells = xmalloc(
|
||||
cell_count * sizeof(term->ime.preedit.cells[0]));
|
||||
term->ime.preedit.count = cell_count;
|
||||
seat->ime.preedit.cells = xmalloc(
|
||||
cell_count * sizeof(seat->ime.preedit.cells[0]));
|
||||
seat->ime.preedit.count = cell_count;
|
||||
|
||||
/* Populate cells */
|
||||
for (size_t i = 0, cell_idx = 0; i < wchars; i++) {
|
||||
struct cell *cell = &term->ime.preedit.cells[cell_idx];
|
||||
struct cell *cell = &seat->ime.preedit.cells[cell_idx];
|
||||
|
||||
int width = widths[i];
|
||||
|
||||
cell->wc = term->ime.preedit.text[i];
|
||||
cell->wc = seat->ime.preedit.text[i];
|
||||
cell->attrs = (struct attributes){.clean = 0};
|
||||
|
||||
for (int j = 1; j < width; j++) {
|
||||
cell = &term->ime.preedit.cells[cell_idx + j];
|
||||
cell = &seat->ime.preedit.cells[cell_idx + j];
|
||||
cell->wc = CELL_MULT_COL_SPACER;
|
||||
cell->attrs = (struct attributes){.clean = 1};
|
||||
}
|
||||
|
|
@ -206,18 +215,18 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
/* Note: docs says *both* begin and end should be -1,
|
||||
* but what else can we do if only one is -1? */
|
||||
LOG_DBG("pre-edit cursor is hidden");
|
||||
term->ime.preedit.cursor.hidden = true;
|
||||
term->ime.preedit.cursor.start = -1;
|
||||
term->ime.preedit.cursor.end = -1;
|
||||
seat->ime.preedit.cursor.hidden = true;
|
||||
seat->ime.preedit.cursor.start = -1;
|
||||
seat->ime.preedit.cursor.end = -1;
|
||||
}
|
||||
|
||||
else if (seat->ime.preedit.pending.cursor_begin == byte_len &&
|
||||
seat->ime.preedit.pending.cursor_end == byte_len)
|
||||
{
|
||||
/* Cursor is *after* the entire pre-edit string */
|
||||
term->ime.preedit.cursor.hidden = false;
|
||||
term->ime.preedit.cursor.start = cell_count;
|
||||
term->ime.preedit.cursor.end = cell_count;
|
||||
seat->ime.preedit.cursor.hidden = false;
|
||||
seat->ime.preedit.cursor.start = cell_count;
|
||||
seat->ime.preedit.cursor.end = cell_count;
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
@ -271,7 +280,7 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
|
||||
/* Expand cursor end to end of glyph */
|
||||
while (cell_end > cell_begin && cell_end < cell_count &&
|
||||
term->ime.preedit.cells[cell_end].wc == CELL_MULT_COL_SPACER)
|
||||
seat->ime.preedit.cells[cell_end].wc == CELL_MULT_COL_SPACER)
|
||||
{
|
||||
cell_end++;
|
||||
}
|
||||
|
|
@ -284,54 +293,69 @@ done(void *data, struct zwp_text_input_v3 *zwp_text_input_v3,
|
|||
xassert(cell_end >= 0);
|
||||
xassert(cell_end <= cell_count);
|
||||
|
||||
term->ime.preedit.cursor.hidden = false;
|
||||
term->ime.preedit.cursor.start = cell_begin;
|
||||
term->ime.preedit.cursor.end = cell_end;
|
||||
seat->ime.preedit.cursor.hidden = false;
|
||||
seat->ime.preedit.cursor.start = cell_begin;
|
||||
seat->ime.preedit.cursor.end = cell_end;
|
||||
}
|
||||
|
||||
/* Underline pre-edit string that is *not* covered by the cursor */
|
||||
bool hidden = term->ime.preedit.cursor.hidden;
|
||||
int start = term->ime.preedit.cursor.start;
|
||||
int end = term->ime.preedit.cursor.end;
|
||||
bool hidden = seat->ime.preedit.cursor.hidden;
|
||||
int start = seat->ime.preedit.cursor.start;
|
||||
int end = seat->ime.preedit.cursor.end;
|
||||
|
||||
for (size_t i = 0, cell_idx = 0; i < wchars; cell_idx += widths[i], i++) {
|
||||
if (hidden || start == end || cell_idx < start || cell_idx >= end) {
|
||||
struct cell *cell = &term->ime.preedit.cells[cell_idx];
|
||||
struct cell *cell = &seat->ime.preedit.cells[cell_idx];
|
||||
cell->attrs.underline = true;
|
||||
}
|
||||
}
|
||||
|
||||
ime_reset_preedit(seat);
|
||||
ime_reset_pending_preedit(seat);
|
||||
|
||||
if (term->is_searching)
|
||||
render_refresh_search(term);
|
||||
else
|
||||
render_refresh(term);
|
||||
if (term != NULL) {
|
||||
if (term->is_searching)
|
||||
render_refresh_search(term);
|
||||
else
|
||||
render_refresh(term);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ime_reset_preedit(struct seat *seat)
|
||||
ime_reset_pending_preedit(struct seat *seat)
|
||||
{
|
||||
free(seat->ime.preedit.pending.text);
|
||||
seat->ime.preedit.pending.text = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ime_reset_commit(struct seat *seat)
|
||||
ime_reset_pending_commit(struct seat *seat)
|
||||
{
|
||||
free(seat->ime.commit.pending.text);
|
||||
seat->ime.commit.pending.text = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ime_reset(struct seat *seat)
|
||||
ime_reset_pending(struct seat *seat)
|
||||
{
|
||||
ime_reset_preedit(seat);
|
||||
ime_reset_commit(seat);
|
||||
ime_reset_pending_preedit(seat);
|
||||
ime_reset_pending_commit(seat);
|
||||
}
|
||||
|
||||
void
|
||||
ime_send_cursor_rect(struct seat *seat, struct terminal *term)
|
||||
ime_reset_preedit(struct seat *seat)
|
||||
{
|
||||
if (seat->ime.preedit.cells == NULL)
|
||||
return;
|
||||
|
||||
free(seat->ime.preedit.text);
|
||||
free(seat->ime.preedit.cells);
|
||||
seat->ime.preedit.text = NULL;
|
||||
seat->ime.preedit.cells = NULL;
|
||||
seat->ime.preedit.count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ime_send_cursor_rect(struct seat *seat)
|
||||
{
|
||||
if (unlikely(seat->wayl->text_input_manager == NULL))
|
||||
return;
|
||||
|
|
@ -339,7 +363,9 @@ ime_send_cursor_rect(struct seat *seat, struct terminal *term)
|
|||
if (!seat->ime.focused)
|
||||
return;
|
||||
|
||||
if (!term->ime.enabled)
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
|
||||
if (!term->ime_enabled)
|
||||
return;
|
||||
|
||||
if (seat->ime.cursor_rect.pending.x == seat->ime.cursor_rect.sent.x &&
|
||||
|
|
@ -369,16 +395,18 @@ ime_enable(struct seat *seat)
|
|||
if (unlikely(seat->wayl->text_input_manager == NULL))
|
||||
return;
|
||||
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
xassert(term != NULL);
|
||||
|
||||
if (!seat->ime.focused)
|
||||
return;
|
||||
|
||||
if (!term->ime.enabled)
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
if (term == NULL)
|
||||
return;
|
||||
|
||||
ime_reset(seat);
|
||||
if (!term->ime_enabled)
|
||||
return;
|
||||
|
||||
ime_reset_pending(seat);
|
||||
ime_reset_preedit(seat);
|
||||
|
||||
zwp_text_input_v3_enable(seat->wl_text_input);
|
||||
zwp_text_input_v3_set_content_type(
|
||||
|
|
@ -408,7 +436,8 @@ ime_disable(struct seat *seat)
|
|||
if (!seat->ime.focused)
|
||||
return;
|
||||
|
||||
ime_reset(seat);
|
||||
ime_reset_pending(seat);
|
||||
ime_reset_preedit(seat);
|
||||
|
||||
zwp_text_input_v3_disable(seat->wl_text_input);
|
||||
zwp_text_input_v3_commit(seat->wl_text_input);
|
||||
|
|
@ -416,10 +445,12 @@ ime_disable(struct seat *seat)
|
|||
}
|
||||
|
||||
void
|
||||
ime_update_cursor_rect(struct seat *seat, struct terminal *term)
|
||||
ime_update_cursor_rect(struct seat *seat)
|
||||
{
|
||||
struct terminal *term = seat->kbd_focus;
|
||||
|
||||
/* Set in render_ime_preedit() */
|
||||
if (term->ime.preedit.cells != NULL)
|
||||
if (seat->ime.preedit.cells != NULL)
|
||||
goto update;
|
||||
|
||||
/* Set in render_search_box() */
|
||||
|
|
@ -448,7 +479,7 @@ ime_update_cursor_rect(struct seat *seat, struct terminal *term)
|
|||
seat->ime.cursor_rect.pending.height = height;
|
||||
|
||||
update:
|
||||
ime_send_cursor_rect(seat, term);
|
||||
ime_send_cursor_rect(seat);
|
||||
}
|
||||
|
||||
const struct zwp_text_input_v3_listener text_input_listener = {
|
||||
|
|
@ -464,11 +495,11 @@ const struct zwp_text_input_v3_listener text_input_listener = {
|
|||
|
||||
void ime_enable(struct seat *seat) {}
|
||||
void ime_disable(struct seat *seat) {}
|
||||
void ime_update_cursor_rect(struct seat *seat, struct terminal *term) {}
|
||||
void ime_update_cursor_rect(struct seat *seat) {}
|
||||
|
||||
void ime_reset_pending_preedit(struct seat *seat) {}
|
||||
void ime_reset_pending_commit(struct seat *seat) {}
|
||||
void ime_reset_pending(struct seat *seat) {}
|
||||
void ime_reset_preedit(struct seat *seat) {}
|
||||
void ime_reset_commit(struct seat *seat) {}
|
||||
void ime_reset(struct seat *seat) {}
|
||||
void ime_send_cursor_rect(struct seat *seat, struct terminal *term) {}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
8
ime.h
8
ime.h
|
|
@ -13,9 +13,9 @@ struct terminal;
|
|||
|
||||
void ime_enable(struct seat *seat);
|
||||
void ime_disable(struct seat *seat);
|
||||
void ime_update_cursor_rect(struct seat *seat, struct terminal *term);
|
||||
void ime_update_cursor_rect(struct seat *seat);
|
||||
|
||||
void ime_reset_pending_preedit(struct seat *seat);
|
||||
void ime_reset_pending_commit(struct seat *seat);
|
||||
void ime_reset_pending(struct seat *seat);
|
||||
void ime_reset_preedit(struct seat *seat);
|
||||
void ime_reset_commit(struct seat *seat);
|
||||
void ime_reset(struct seat *seat);
|
||||
void ime_send_cursor_rect(struct seat *seat, struct terminal *term);
|
||||
|
|
|
|||
2
input.c
2
input.c
|
|
@ -450,7 +450,7 @@ maybe_repair_key_combo(const struct seat *seat,
|
|||
|
||||
/* Check if key combo’s modifier set intersects */
|
||||
for (size_t j = 0; j < mod_mask_count; j++) {
|
||||
if (!(mod_masks[j] & mods))
|
||||
if ((mod_masks[j] & mods) != mod_masks[j])
|
||||
continue;
|
||||
|
||||
char combo[64] = {0};
|
||||
|
|
|
|||
6
main.c
6
main.c
|
|
@ -45,8 +45,10 @@ static const char *
|
|||
version_and_features(void)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "version: %s %cime",
|
||||
FOOT_VERSION, feature_ime() ? '+' : '-');
|
||||
snprintf(buf, sizeof(buf), "version: %s %cime %cpgo",
|
||||
FOOT_VERSION,
|
||||
feature_ime() ? '+' : '-',
|
||||
feature_pgo() ? '+' : '-');
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
|||
40
meson.build
40
meson.build
|
|
@ -24,6 +24,9 @@ add_project_arguments(
|
|||
(get_option('ime')
|
||||
? ['-DFOOT_IME_ENABLED=1']
|
||||
: []) +
|
||||
(get_option('b_pgo') == 'use'
|
||||
? ['-DFOOT_PGO_ENABLED=1']
|
||||
: []) +
|
||||
cc.get_supported_arguments(
|
||||
['-pedantic',
|
||||
'-fstrict-aliasing',
|
||||
|
|
@ -114,16 +117,20 @@ version = custom_target(
|
|||
output: 'version.h',
|
||||
command: [generate_version_sh, meson.project_version(), '@SOURCE_ROOT@', '@OUTPUT@'])
|
||||
|
||||
common = static_library(
|
||||
'common',
|
||||
'log.c', 'log.h',
|
||||
'debug.c', 'debug.h',
|
||||
'xmalloc.c', 'xmalloc.h',
|
||||
'xsnprintf.c', 'xsnprintf.h'
|
||||
)
|
||||
|
||||
misc = static_library(
|
||||
'misc',
|
||||
'debug.c', 'debug.h',
|
||||
'hsl.c', 'hsl.h',
|
||||
'log.c', 'log.h',
|
||||
'macros.h',
|
||||
'misc.c', 'misc.h',
|
||||
'uri.c', 'uri.h',
|
||||
'xmalloc.c', 'xmalloc.h',
|
||||
'xsnprintf.c', 'xsnprintf.h',
|
||||
'uri.c', 'uri.h'
|
||||
)
|
||||
|
||||
vtlib = static_library(
|
||||
|
|
@ -137,7 +144,7 @@ vtlib = static_library(
|
|||
wl_proto_src + wl_proto_headers,
|
||||
version,
|
||||
dependencies: [libepoll, pixman, fcft, tllist, wayland_client],
|
||||
link_with: misc,
|
||||
link_with: [common, misc],
|
||||
)
|
||||
|
||||
pgolib = static_library(
|
||||
|
|
@ -150,13 +157,15 @@ pgolib = static_library(
|
|||
link_with: vtlib,
|
||||
)
|
||||
|
||||
executable(
|
||||
'pgo',
|
||||
'pgo/pgo.c',
|
||||
wl_proto_src + wl_proto_headers,
|
||||
dependencies: [math, threads, libepoll, pixman, wayland_client, fcft, tllist],
|
||||
link_with: pgolib,
|
||||
)
|
||||
if get_option('b_pgo') == 'generate'
|
||||
executable(
|
||||
'pgo',
|
||||
'pgo/pgo.c',
|
||||
wl_proto_src + wl_proto_headers,
|
||||
dependencies: [math, threads, libepoll, pixman, wayland_client, fcft, tllist],
|
||||
link_with: pgolib,
|
||||
)
|
||||
endif
|
||||
|
||||
executable(
|
||||
'foot',
|
||||
|
|
@ -192,14 +201,11 @@ executable(
|
|||
executable(
|
||||
'footclient',
|
||||
'client.c', 'client-protocol.h',
|
||||
'debug.c', 'debug.h',
|
||||
'foot-features.h',
|
||||
'log.c', 'log.h',
|
||||
'macros.h',
|
||||
'util.h',
|
||||
'xmalloc.c', 'xmalloc.h',
|
||||
'xsnprintf.c', 'xsnprintf.h',
|
||||
version,
|
||||
link_with: common,
|
||||
install: true)
|
||||
|
||||
if tic.found()
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ void cmd_scrollback_down(struct terminal *term, int rows) {}
|
|||
|
||||
void ime_enable(struct seat *seat) {}
|
||||
void ime_disable(struct seat *seat) {}
|
||||
void ime_reset_preedit(struct seat *seat) {}
|
||||
|
||||
void
|
||||
notify_notify(const struct terminal *term, const char *title, const char *body)
|
||||
|
|
|
|||
168
render.c
168
render.c
|
|
@ -1114,12 +1114,12 @@ render_sixel_images(struct terminal *term, pixman_image_t *pix,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_ime_preedit(struct terminal *term, struct buffer *buf)
|
||||
{
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
|
||||
if (likely(term->ime.preedit.cells == NULL))
|
||||
static void
|
||||
render_ime_preedit_for_seat(struct terminal *term, struct seat *seat,
|
||||
struct buffer *buf)
|
||||
{
|
||||
if (likely(seat->ime.preedit.cells == NULL))
|
||||
return;
|
||||
|
||||
if (unlikely(term->is_searching))
|
||||
|
|
@ -1135,10 +1135,10 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
if (cursor.row < 0 || cursor.row >= term->rows)
|
||||
return;
|
||||
|
||||
int cells_needed = term->ime.preedit.count;
|
||||
int cells_needed = seat->ime.preedit.count;
|
||||
|
||||
if (term->ime.preedit.cursor.start == cells_needed &&
|
||||
term->ime.preedit.cursor.end == cells_needed)
|
||||
if (seat->ime.preedit.cursor.start == cells_needed &&
|
||||
seat->ime.preedit.cursor.end == cells_needed)
|
||||
{
|
||||
/* Cursor will be drawn *after* the pre-edit string, i.e. in
|
||||
* the cell *after*. This means we need to copy, and dirty,
|
||||
|
|
@ -1160,8 +1160,8 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
col_idx -= cells_used - cells_left;
|
||||
|
||||
if (cells_needed > cells_used) {
|
||||
int start = term->ime.preedit.cursor.start;
|
||||
int end = term->ime.preedit.cursor.end;
|
||||
int start = seat->ime.preedit.cursor.start;
|
||||
int end = seat->ime.preedit.cursor.end;
|
||||
|
||||
if (start == end) {
|
||||
/* Ensure *end* of pre-edit string is visible */
|
||||
|
|
@ -1177,7 +1177,7 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
|
||||
/* Make sure we don't start in the middle of a character */
|
||||
while (ime_ofs < cells_needed &&
|
||||
term->ime.preedit.cells[ime_ofs].wc == CELL_MULT_COL_SPACER)
|
||||
seat->ime.preedit.cells[ime_ofs].wc == CELL_MULT_COL_SPACER)
|
||||
{
|
||||
ime_ofs++;
|
||||
}
|
||||
|
|
@ -1208,9 +1208,9 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
row->dirty = true;
|
||||
|
||||
/* Render pre-edit text */
|
||||
xassert(term->ime.preedit.cells[ime_ofs].wc != CELL_MULT_COL_SPACER);
|
||||
for (int i = 0, idx = ime_ofs; idx < term->ime.preedit.count; i++, idx++) {
|
||||
const struct cell *cell = &term->ime.preedit.cells[idx];
|
||||
xassert(seat->ime.preedit.cells[ime_ofs].wc != CELL_MULT_COL_SPACER);
|
||||
for (int i = 0, idx = ime_ofs; idx < seat->ime.preedit.count; i++, idx++) {
|
||||
const struct cell *cell = &seat->ime.preedit.cells[idx];
|
||||
|
||||
if (cell->wc == CELL_MULT_COL_SPACER)
|
||||
continue;
|
||||
|
|
@ -1223,11 +1223,11 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
render_cell(term, buf->pix[0], row, col_idx + i, row_idx, false);
|
||||
}
|
||||
|
||||
int start = term->ime.preedit.cursor.start - ime_ofs;
|
||||
int end = term->ime.preedit.cursor.end - ime_ofs;
|
||||
int start = seat->ime.preedit.cursor.start - ime_ofs;
|
||||
int end = seat->ime.preedit.cursor.end - ime_ofs;
|
||||
|
||||
if (!term->ime.preedit.cursor.hidden) {
|
||||
const struct cell *start_cell = &term->ime.preedit.cells[0];
|
||||
if (!seat->ime.preedit.cursor.hidden) {
|
||||
const struct cell *start_cell = &seat->ime.preedit.cells[0];
|
||||
|
||||
pixman_color_t fg = color_hex_to_pixman(term->colors.fg);
|
||||
pixman_color_t bg = color_hex_to_pixman(term->colors.bg);
|
||||
|
|
@ -1271,6 +1271,17 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
term->margins.top + row_idx * term->cell_height,
|
||||
term->width - term->margins.left - term->margins.right,
|
||||
1 * term->cell_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
render_ime_preedit(struct terminal *term, struct buffer *buf)
|
||||
{
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
if (it->item.kbd_focus == term)
|
||||
render_ime_preedit_for_seat(term, &it->item, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1398,6 +1409,9 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
|
|||
static void
|
||||
csd_commit(struct terminal *term, struct wl_surface *surf, struct buffer *buf)
|
||||
{
|
||||
xassert(buf->width % term->scale == 0);
|
||||
xassert(buf->height % term->scale == 0);
|
||||
|
||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_buffer_scale(surf, term->scale);
|
||||
|
|
@ -1429,6 +1443,9 @@ render_csd_title(struct terminal *term)
|
|||
|
||||
xassert(info.width > 0 && info.height > 0);
|
||||
|
||||
xassert(info.width % term->scale == 0);
|
||||
xassert(info.height % term->scale == 0);
|
||||
|
||||
unsigned long cookie = shm_cookie_csd(term, CSD_SURF_TITLE);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
||||
|
|
@ -1461,6 +1478,9 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx)
|
|||
if (info.width == 0 || info.height == 0)
|
||||
return;
|
||||
|
||||
xassert(info.width % term->scale == 0);
|
||||
xassert(info.height % term->scale == 0);
|
||||
|
||||
unsigned long cookie = shm_cookie_csd(term, surf_idx);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
||||
|
|
@ -1630,6 +1650,9 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx)
|
|||
if (info.width == 0 || info.height == 0)
|
||||
return;
|
||||
|
||||
xassert(info.width % term->scale == 0);
|
||||
xassert(info.height % term->scale == 0);
|
||||
|
||||
unsigned long cookie = shm_cookie_csd(term, surf_idx);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
||||
|
|
@ -1740,12 +1763,12 @@ render_osd(struct terminal *term,
|
|||
struct wl_surface *surf, struct wl_subsurface *sub_surf,
|
||||
struct buffer *buf,
|
||||
const wchar_t *text, uint32_t _fg, uint32_t _bg,
|
||||
unsigned width, unsigned height, unsigned x, unsigned y)
|
||||
unsigned x, unsigned y)
|
||||
{
|
||||
pixman_color_t bg = color_hex_to_pixman(_bg);
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, buf->pix[0], &bg, 1,
|
||||
&(pixman_rectangle16_t){0, 0, width, height});
|
||||
&(pixman_rectangle16_t){0, 0, buf->width, buf->height});
|
||||
|
||||
struct fcft_font *font = term->fonts[0];
|
||||
pixman_color_t fg = color_hex_to_pixman(_fg);
|
||||
|
|
@ -1769,14 +1792,17 @@ render_osd(struct terminal *term,
|
|||
x += term->cell_width;
|
||||
}
|
||||
|
||||
xassert(buf->width % term->scale == 0);
|
||||
xassert(buf->height % term->scale == 0);
|
||||
|
||||
quirk_weston_subsurface_desync_on(sub_surf);
|
||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(surf, 0, 0, width, height);
|
||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_buffer_scale(surf, term->scale);
|
||||
|
||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||
if (region != NULL) {
|
||||
wl_region_add(region, 0, 0, width, height);
|
||||
wl_region_add(region, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_opaque_region(surf, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
|
@ -1862,8 +1888,11 @@ render_scrollback_position(struct terminal *term)
|
|||
|
||||
const int scale = term->scale;
|
||||
const int margin = 3 * scale;
|
||||
const int width = 2 * margin + cell_count * term->cell_width;
|
||||
const int height = 2 * margin + term->cell_height;
|
||||
|
||||
const int width =
|
||||
(2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale;
|
||||
const int height =
|
||||
(2 * margin + term->cell_height + scale - 1) / scale * scale;
|
||||
|
||||
unsigned long cookie = shm_cookie_scrollback_indicator(term);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
|
|
@ -1905,7 +1934,7 @@ render_scrollback_position(struct terminal *term)
|
|||
win->scrollback_indicator.sub,
|
||||
buf, text,
|
||||
term->colors.table[0], term->colors.table[8 + 4],
|
||||
width, height, width - margin - wcslen(text) * term->cell_width, margin);
|
||||
width - margin - wcslen(text) * term->cell_width, margin);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1918,10 +1947,13 @@ render_render_timer(struct terminal *term, struct timeval render_time)
|
|||
double usecs = render_time.tv_sec * 1000000 + render_time.tv_usec;
|
||||
swprintf(text, sizeof(text) / sizeof(text[0]), L"%.2f µs", usecs);
|
||||
|
||||
const int scale = term->scale;
|
||||
const int cell_count = wcslen(text);
|
||||
const int margin = 3 * term->scale;
|
||||
const int width = 2 * margin + cell_count * term->cell_width;
|
||||
const int height = 2 * margin + term->cell_height;
|
||||
const int margin = 3 * scale;
|
||||
const int width =
|
||||
(2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale;
|
||||
const int height =
|
||||
(2 * margin + term->cell_height + scale - 1) / scale * scale;
|
||||
|
||||
unsigned long cookie = shm_cookie_render_timer(term);
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
|
|
@ -1938,7 +1970,7 @@ render_render_timer(struct terminal *term, struct timeval render_time)
|
|||
win->render_timer.sub,
|
||||
buf, text,
|
||||
term->colors.table[0], term->colors.table[8 + 1],
|
||||
width, height, margin, margin);
|
||||
margin, margin);
|
||||
}
|
||||
|
||||
static void frame_callback(
|
||||
|
|
@ -2079,6 +2111,8 @@ grid_render(struct terminal *term)
|
|||
cursor.row &= term->grid->num_rows - 1;
|
||||
}
|
||||
|
||||
render_sixel_images(term, buf->pix[0], &cursor);
|
||||
|
||||
if (term->render.workers.count > 0) {
|
||||
mtx_lock(&term->render.workers.lock);
|
||||
term->render.workers.buf = buf;
|
||||
|
|
@ -2088,8 +2122,6 @@ grid_render(struct terminal *term)
|
|||
xassert(tll_length(term->render.workers.queue) == 0);
|
||||
}
|
||||
|
||||
render_sixel_images(term, buf->pix[0], &cursor);
|
||||
|
||||
int first_dirty_row = -1;
|
||||
for (int r = 0; r < term->rows; r++) {
|
||||
struct row *row = grid_row_in_view(term->grid, r);
|
||||
|
|
@ -2216,6 +2248,9 @@ grid_render(struct terminal *term)
|
|||
term->window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
}
|
||||
|
||||
xassert(buf->width % term->scale == 0);
|
||||
xassert(buf->height % term->scale == 0);
|
||||
|
||||
wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0);
|
||||
quirk_kde_damage_before_attach(term->window->surface);
|
||||
wl_surface_commit(term->window->surface);
|
||||
|
|
@ -2238,9 +2273,18 @@ render_search_box(struct terminal *term)
|
|||
*/
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
/* TODO: do we want to/need to handle multi-seat? */
|
||||
struct seat *ime_seat = NULL;
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
if (it->item.kbd_focus == term) {
|
||||
ime_seat = &it->item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t text_len = term->search.len;
|
||||
if (term->ime.preedit.text != NULL)
|
||||
text_len += wcslen(term->ime.preedit.text);
|
||||
if (ime_seat != NULL && ime_seat->ime.preedit.text != NULL)
|
||||
text_len += wcslen(ime_seat->ime.preedit.text);
|
||||
|
||||
wchar_t *text = xmalloc((text_len + 1) * sizeof(wchar_t));
|
||||
text[0] = L'\0';
|
||||
|
|
@ -2250,8 +2294,8 @@ render_search_box(struct terminal *term)
|
|||
text[term->search.cursor] = L'\0';
|
||||
|
||||
/* Insert pre-edit text at cursor */
|
||||
if (term->ime.preedit.text != NULL)
|
||||
wcscat(text, term->ime.preedit.text);
|
||||
if (ime_seat != NULL && ime_seat->ime.preedit.text != NULL)
|
||||
wcscat(text, ime_seat->ime.preedit.text);
|
||||
|
||||
/* And finally everything after the cursor */
|
||||
wcsncat(text, &term->search.buf[term->search.cursor],
|
||||
|
|
@ -2278,10 +2322,10 @@ render_search_box(struct terminal *term)
|
|||
const size_t width = term->width - 2 * margin;
|
||||
const size_t visible_width = min(
|
||||
term->width - 2 * margin,
|
||||
2 * margin + wanted_visible_cells * term->cell_width);
|
||||
(2 * margin + wanted_visible_cells * term->cell_width + scale - 1) / scale * scale);
|
||||
const size_t height = min(
|
||||
term->height - 2 * margin,
|
||||
2 * margin + 1 * term->cell_height);
|
||||
(2 * margin + 1 * term->cell_height + scale - 1) / scale * scale);
|
||||
|
||||
const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width;
|
||||
size_t glyph_offset = term->render.search_glyph_offset;
|
||||
|
|
@ -2319,18 +2363,18 @@ render_search_box(struct terminal *term)
|
|||
continue;
|
||||
|
||||
#if (FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (term->ime.preedit.cells != NULL) {
|
||||
if (term->ime.preedit.cursor.start == term->ime.preedit.cursor.end) {
|
||||
if (ime_seat != NULL && ime_seat->ime.preedit.cells != NULL) {
|
||||
if (ime_seat->ime.preedit.cursor.start == ime_seat->ime.preedit.cursor.end) {
|
||||
/* All IME's I've seen so far keeps the cursor at
|
||||
* index 0, so ensure the *end* of the pre-edit string
|
||||
* is visible */
|
||||
cell_idx += term->ime.preedit.count;
|
||||
cell_idx += ime_seat->ime.preedit.count;
|
||||
} else {
|
||||
/* Try to predict in which direction we'll shift the text */
|
||||
if (cell_idx + term->ime.preedit.cursor.start > glyph_offset)
|
||||
cell_idx += term->ime.preedit.cursor.end;
|
||||
if (cell_idx + ime_seat->ime.preedit.cursor.start > glyph_offset)
|
||||
cell_idx += ime_seat->ime.preedit.cursor.end;
|
||||
else
|
||||
cell_idx += term->ime.preedit.cursor.start;
|
||||
cell_idx += ime_seat->ime.preedit.cursor.start;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -2383,8 +2427,10 @@ render_search_box(struct terminal *term)
|
|||
/* Render cursor */
|
||||
if (i == term->search.cursor) {
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
bool have_preedit = term->ime.preedit.cells != NULL;
|
||||
bool hidden = term->ime.preedit.cursor.hidden;
|
||||
bool have_preedit =
|
||||
ime_seat != NULL && ime_seat->ime.preedit.cells != NULL;
|
||||
bool hidden =
|
||||
ime_seat != NULL && ime_seat->ime.preedit.cursor.hidden;
|
||||
|
||||
if (have_preedit && !hidden) {
|
||||
/* Cursor may be outside the visible area:
|
||||
|
|
@ -2394,13 +2440,13 @@ render_search_box(struct terminal *term)
|
|||
|
||||
/* If cursor is outside the visible area, we need to
|
||||
* adjust our rectangle's position */
|
||||
int start = term->ime.preedit.cursor.start
|
||||
int start = ime_seat->ime.preedit.cursor.start
|
||||
+ min((ssize_t)(cell_idx - glyph_offset), 0);
|
||||
int end = term->ime.preedit.cursor.end
|
||||
int end = ime_seat->ime.preedit.cursor.end
|
||||
+ min((ssize_t)(cell_idx - glyph_offset), 0);
|
||||
|
||||
if (start == end) {
|
||||
int count = min(term->ime.preedit.count, cells_left);
|
||||
int count = min(ime_seat->ime.preedit.count, cells_left);
|
||||
|
||||
/* Underline the entire (visible part of) pre-edit text */
|
||||
draw_underline(term, buf->pix[0], font, &fg, x, y, count);
|
||||
|
|
@ -2415,7 +2461,7 @@ render_search_box(struct terminal *term)
|
|||
/* Underline everything before and after the cursor */
|
||||
int count1 = min(start, cells_left);
|
||||
int count2 = max(
|
||||
min(term->ime.preedit.count - term->ime.preedit.cursor.end,
|
||||
min(ime_seat->ime.preedit.count - ime_seat->ime.preedit.cursor.end,
|
||||
cells_left - end),
|
||||
0);
|
||||
draw_underline(term, buf->pix[0], font, &fg, x, y, count1);
|
||||
|
|
@ -2487,7 +2533,7 @@ render_search_box(struct terminal *term)
|
|||
}
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (term->ime.preedit.cells != NULL)
|
||||
if (ime_seat != NULL && ime_seat->ime.preedit.cells != NULL)
|
||||
/* Already rendered */;
|
||||
else
|
||||
#endif
|
||||
|
|
@ -2505,6 +2551,9 @@ render_search_box(struct terminal *term)
|
|||
margin / scale,
|
||||
max(0, (int32_t)term->height - height - margin) / scale);
|
||||
|
||||
xassert(buf->width % scale == 0);
|
||||
xassert(buf->height % scale == 0);
|
||||
|
||||
wl_surface_attach(term->window->search.surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(term->window->search.surf, 0, 0, width, height);
|
||||
wl_surface_set_buffer_scale(term->window->search.surf, scale);
|
||||
|
|
@ -2612,10 +2661,13 @@ render_urls(struct terminal *term)
|
|||
size_t len = wcslen(label);
|
||||
int cols = wcswidth(label, len);
|
||||
|
||||
const int x_margin = 2 * term->scale;
|
||||
const int y_margin = 1 * term->scale;
|
||||
int width = 2 * x_margin + cols * term->cell_width;
|
||||
int height = 2 * y_margin + term->cell_height;
|
||||
const int scale = term->scale;
|
||||
const int x_margin = 2 * scale;
|
||||
const int y_margin = 1 * scale;
|
||||
const int width =
|
||||
(2 * x_margin + cols * term->cell_width + scale - 1) / scale * scale;
|
||||
const int height =
|
||||
(2 * y_margin + term->cell_height + scale - 1) / scale * scale;
|
||||
|
||||
struct buffer *buf = shm_get_buffer(
|
||||
term->wl->shm, width, height, shm_cookie_url(url), false, 1);
|
||||
|
|
@ -2648,8 +2700,8 @@ render_urls(struct terminal *term)
|
|||
? term->conf->colors.jump_label.bg
|
||||
: term->colors.table[3];
|
||||
|
||||
render_osd(term, surf, sub_surf, buf, label,
|
||||
fg, bg, width, height, x_margin, y_margin);
|
||||
render_osd(
|
||||
term, surf, sub_surf, buf, label, fg, bg, x_margin, y_margin);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2717,7 +2769,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
|||
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
if (it->item.kbd_focus == term)
|
||||
ime_update_cursor_rect(&it->item, term);
|
||||
ime_update_cursor_rect(&it->item);
|
||||
}
|
||||
|
||||
term->grid = original_grid;
|
||||
|
|
@ -3173,7 +3225,7 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
|||
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
if (it->item.kbd_focus == term)
|
||||
ime_update_cursor_rect(&it->item, term);
|
||||
ime_update_cursor_rect(&it->item);
|
||||
}
|
||||
|
||||
term->grid = original_grid;
|
||||
|
|
|
|||
3
search.c
3
search.c
|
|
@ -241,6 +241,9 @@ matches_cell(const struct terminal *term, const struct cell *cell, size_t search
|
|||
base = composed->base;
|
||||
}
|
||||
|
||||
if (composed == NULL && base == 0 && term->search.buf[search_ofs] == L' ')
|
||||
return 1;
|
||||
|
||||
if (wcsncasecmp(&base, &term->search.buf[search_ofs], 1) != 0)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
15
sixel.c
15
sixel.c
|
|
@ -48,7 +48,7 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
|
|||
|
||||
term->sixel.state = SIXEL_DECSIXEL;
|
||||
term->sixel.pos = (struct coord){0, 0};
|
||||
term->sixel.max_non_empty_row_no = 0;
|
||||
term->sixel.max_non_empty_row_no = -1;
|
||||
term->sixel.row_byte_ofs = 0;
|
||||
term->sixel.color_idx = 0;
|
||||
term->sixel.param = 0;
|
||||
|
|
@ -726,6 +726,11 @@ sixel_unhook(struct terminal *term)
|
|||
term->sixel.image.height = term->sixel.max_non_empty_row_no + 1;
|
||||
}
|
||||
|
||||
if (term->sixel.image.height == 0 || term->sixel.image.width == 0) {
|
||||
/* We won’t be emitting any sixels - free backing image */
|
||||
free(term->sixel.image.data);
|
||||
}
|
||||
|
||||
int pixel_row_idx = 0;
|
||||
int pixel_rows_left = term->sixel.image.height;
|
||||
const int stride = term->sixel.image.width * sizeof(uint32_t);
|
||||
|
|
@ -1032,7 +1037,7 @@ sixel_add(struct terminal *term, int col, int width, uint32_t color, uint8_t six
|
|||
size_t ofs = term->sixel.row_byte_ofs + col;
|
||||
uint32_t *data = &term->sixel.image.data[ofs];
|
||||
|
||||
int max_non_empty_row = 0;
|
||||
int max_non_empty_row = -1;
|
||||
int row = term->sixel.pos.row;
|
||||
|
||||
for (int i = 0; i < 6; i++, sixel >>= 1, data += width) {
|
||||
|
|
@ -1175,7 +1180,11 @@ decgra(struct terminal *term, uint8_t c)
|
|||
ph <= term->sixel.max_height && pv <= term->sixel.max_width)
|
||||
{
|
||||
resize(term, ph, pv);
|
||||
term->sixel.max_non_empty_row_no = pv - 1;
|
||||
if (!term->sixel.transparent_bg) {
|
||||
/* This ensures the sixel’s final image size is *at
|
||||
* least* this large */
|
||||
term->sixel.max_non_empty_row_no = pv - 1;
|
||||
}
|
||||
}
|
||||
|
||||
term->sixel.state = SIXEL_DECSIXEL;
|
||||
|
|
|
|||
57
terminal.c
57
terminal.c
|
|
@ -649,8 +649,8 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
|
|||
: term->fonts[0]->max_advance.x)
|
||||
+ pt_or_px_as_pixels(term, &conf->letter_spacing);
|
||||
|
||||
term->cell_height = conf->line_height.px >= 0
|
||||
? pt_or_px_as_pixels(term, &conf->line_height)
|
||||
term->cell_height = term->font_line_height.px >= 0
|
||||
? pt_or_px_as_pixels(term, &term->font_line_height)
|
||||
: max(term->fonts[0]->height,
|
||||
term->fonts[0]->ascent + term->fonts[0]->descent);
|
||||
|
||||
|
|
@ -979,6 +979,7 @@ load_fonts_from_conf(struct terminal *term)
|
|||
}
|
||||
}
|
||||
|
||||
term->font_line_height = term->conf->line_height;
|
||||
return reload_fonts(term);
|
||||
}
|
||||
|
||||
|
|
@ -1181,9 +1182,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.foot_exe = xstrdup(foot_exe),
|
||||
.cwd = xstrdup(cwd),
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
.ime = {
|
||||
.enabled = true,
|
||||
},
|
||||
.ime_enabled = true,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -1196,6 +1195,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.pt_size = it->item.pt_size, .px_size = it->item.px_size};
|
||||
}
|
||||
}
|
||||
term->font_line_height = conf->line_height;
|
||||
|
||||
/* Start the slave/client */
|
||||
if ((term->slave = slave_spawn(
|
||||
|
|
@ -1780,6 +1780,15 @@ term_font_size_adjust(struct terminal *term, double amount)
|
|||
}
|
||||
}
|
||||
|
||||
if (term->font_line_height.px >= 0) {
|
||||
double old_pt_size = term->font_line_height.px > 0
|
||||
? term->font_line_height.px * 72. / term->font_dpi
|
||||
: term->font_line_height.pt;
|
||||
|
||||
term->font_line_height.px = 0;
|
||||
term->font_line_height.pt = fmax(old_pt_size + amount, 0);
|
||||
}
|
||||
|
||||
return reload_fonts(term);
|
||||
}
|
||||
|
||||
|
|
@ -2394,10 +2403,8 @@ term_kbd_focus_out(struct terminal *term)
|
|||
return;
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (term->ime.preedit.cells != NULL) {
|
||||
term_ime_reset(term);
|
||||
if (term_ime_reset(term))
|
||||
render_refresh(term);
|
||||
}
|
||||
#endif
|
||||
|
||||
term->kbd_focus = false;
|
||||
|
|
@ -2859,6 +2866,7 @@ term_print(struct terminal *term, wchar_t wc, int width)
|
|||
cell->attrs = term->vt.attrs;
|
||||
|
||||
row->dirty = true;
|
||||
row->linebreak = false;
|
||||
cell->attrs.clean = 0;
|
||||
|
||||
/* Advance cursor the 'additional' columns while dirty:ing the cells */
|
||||
|
|
@ -2898,6 +2906,7 @@ ascii_printer_fast(struct terminal *term, wchar_t wc)
|
|||
cell->attrs = term->vt.attrs;
|
||||
|
||||
row->dirty = true;
|
||||
row->linebreak = false;
|
||||
cell->attrs.clean = 0;
|
||||
|
||||
/* Advance cursor */
|
||||
|
|
@ -3026,7 +3035,7 @@ bool
|
|||
term_ime_is_enabled(const struct terminal *term)
|
||||
{
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
return term->ime.enabled;
|
||||
return term->ime_enabled;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
|
@ -3036,13 +3045,12 @@ void
|
|||
term_ime_enable(struct terminal *term)
|
||||
{
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (term->ime.enabled)
|
||||
if (term->ime_enabled)
|
||||
return;
|
||||
|
||||
LOG_DBG("IME enabled");
|
||||
|
||||
term->ime.enabled = true;
|
||||
term_ime_reset(term);
|
||||
term->ime_enabled = true;
|
||||
|
||||
/* IME is per seat - enable on all seat currently focusing us */
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
|
|
@ -3056,13 +3064,12 @@ void
|
|||
term_ime_disable(struct terminal *term)
|
||||
{
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (!term->ime.enabled)
|
||||
if (!term->ime_enabled)
|
||||
return;
|
||||
|
||||
LOG_DBG("IME disabled");
|
||||
|
||||
term->ime.enabled = false;
|
||||
term_ime_reset(term);
|
||||
term->ime_enabled = false;
|
||||
|
||||
/* IME is per seat - disable on all seat currently focusing us */
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
|
|
@ -3072,18 +3079,24 @@ term_ime_disable(struct terminal *term)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
term_ime_reset(struct terminal *term)
|
||||
{
|
||||
bool at_least_one_seat_was_reset = false;
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (term->ime.preedit.cells != NULL) {
|
||||
free(term->ime.preedit.text);
|
||||
free(term->ime.preedit.cells);
|
||||
term->ime.preedit.text = NULL;
|
||||
term->ime.preedit.cells = NULL;
|
||||
term->ime.preedit.count = 0;
|
||||
tll_foreach(term->wl->seats, it) {
|
||||
struct seat *seat = &it->item;
|
||||
|
||||
if (seat->kbd_focus != term)
|
||||
continue;
|
||||
|
||||
ime_reset_preedit(seat);
|
||||
at_least_one_seat_was_reset = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return at_least_one_seat_was_reset;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
24
terminal.h
24
terminal.h
|
|
@ -261,6 +261,12 @@ struct url {
|
|||
};
|
||||
typedef tll(struct url) url_list_t;
|
||||
|
||||
/* If px != 0 then px is valid, otherwise pt is valid */
|
||||
struct pt_or_px {
|
||||
int16_t px;
|
||||
float pt;
|
||||
};
|
||||
|
||||
struct terminal {
|
||||
struct fdm *fdm;
|
||||
struct reaper *reaper;
|
||||
|
|
@ -312,6 +318,7 @@ struct terminal {
|
|||
|
||||
struct fcft_font *fonts[4];
|
||||
struct config_font *font_sizes[4];
|
||||
struct pt_or_px font_line_height;
|
||||
float font_dpi;
|
||||
int font_scale;
|
||||
int16_t font_x_ofs;
|
||||
|
|
@ -560,20 +567,7 @@ struct terminal {
|
|||
struct grid *url_grid_snapshot;
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
struct {
|
||||
bool enabled;
|
||||
struct {
|
||||
wchar_t *text;
|
||||
struct cell *cells;
|
||||
int count;
|
||||
|
||||
struct {
|
||||
bool hidden;
|
||||
int start; /* Cell index, inclusive */
|
||||
int end; /* Cell index, exclusive */
|
||||
} cursor;
|
||||
} preedit;
|
||||
} ime;
|
||||
bool ime_enabled;
|
||||
#endif
|
||||
|
||||
bool is_shutting_down;
|
||||
|
|
@ -706,7 +700,7 @@ bool term_view_to_text(
|
|||
bool term_ime_is_enabled(const struct terminal *term);
|
||||
void term_ime_enable(struct terminal *term);
|
||||
void term_ime_disable(struct terminal *term);
|
||||
void term_ime_reset(struct terminal *term);
|
||||
bool term_ime_reset(struct terminal *term);
|
||||
void term_ime_set_cursor_rect(
|
||||
struct terminal *term, int x, int y, int width, int height);
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ seat_destroy(struct seat *seat)
|
|||
if (seat->wl_seat != NULL)
|
||||
wl_seat_release(seat->wl_seat);
|
||||
|
||||
ime_reset(seat);
|
||||
ime_reset_pending(seat);
|
||||
free(seat->clipboard.text);
|
||||
free(seat->primary.text);
|
||||
free(seat->name);
|
||||
|
|
|
|||
|
|
@ -256,6 +256,15 @@ struct seat {
|
|||
int32_t cursor_begin;
|
||||
int32_t cursor_end;
|
||||
} pending;
|
||||
|
||||
wchar_t *text;
|
||||
struct cell *cells;
|
||||
int count;
|
||||
struct {
|
||||
bool hidden;
|
||||
int start; /* Cell index, inclusive */
|
||||
int end; /* Cell index, exclusive */
|
||||
} cursor;
|
||||
} preedit;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue