mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Merge branch 'fractional-scaling'
This commit is contained in:
commit
a44a0b4ebe
18 changed files with 508 additions and 315 deletions
|
|
@ -50,6 +50,9 @@
|
|||
is `auto`, which will select `libutempter` on Linux, `ulog` on
|
||||
FreeBSD, and `none` for all others.
|
||||
* Sixel aspect ratio.
|
||||
* Support for the new fractional-scaling-v1 Wayland protocol. This
|
||||
brings true fractional scaling to Wayland in general, and with this
|
||||
release, foot.
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
@ -77,6 +80,8 @@
|
|||
is explicitly added.
|
||||
* Default sixel aspect ratio is now 2:1 instead of 1:1.
|
||||
* Sixel images are no longer cropped to the last non-transparent row.
|
||||
* `dpi-aware` now defaults to `no`, and the `auto` value has been
|
||||
removed.
|
||||
|
||||
|
||||
[1371]: https://codeberg.org/dnkl/foot/pulls/1371
|
||||
|
|
@ -89,6 +94,10 @@
|
|||
|
||||
|
||||
### Removed
|
||||
|
||||
* `auto` value for the `dpi-aware` option.
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
* Incorrect icon in dock and window switcher on Gnome ([#1317][1317])
|
||||
|
|
|
|||
52
README.md
52
README.md
|
|
@ -411,27 +411,53 @@ 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’s default behavior is to use the monitor’s DPI to size fonts when
|
||||
output scaling has been disabled on **all** monitors. If at least one
|
||||
monitor has output scaling enabled, fonts will instead by sized using
|
||||
the scaling factor.
|
||||
That said, on Wayland, Hi-DPI monitors are typically handled by
|
||||
configuring a _"scaling factor"_ in the compositor. This is usually
|
||||
expressed as either a rational value (e.g. _1.5_), or as a percentage
|
||||
(e.g. _150%_), by which all fonts and window sizes are supposed to be
|
||||
multiplied.
|
||||
|
||||
This can be changed to either **always** use the monitor’s DPI
|
||||
(regardless of scaling factor), or to **never** use it, with the
|
||||
`dpi-aware` option in `foot.ini`. See the man page, **foot.ini**(5)
|
||||
for more information.
|
||||
For this reason, and because of the new _fractional scaling_ protocol
|
||||
(see below for details), and because this is how Wayland applications
|
||||
are expected to behave, foot >= 1.15 will default to scaling fonts
|
||||
using the compositor’s scaling factor, and **not** the monitor
|
||||
DPI.
|
||||
|
||||
When fonts are sized using the monitor’s DPI, glyphs should always
|
||||
have the same physical height, regardless of monitor.
|
||||
This means the (assuming the monitors are at the same viewing
|
||||
distance) the font size will appear to change when you move the foot
|
||||
window across different monitors, **unless** you have configured the
|
||||
monitors’ scaling factors correctly in the compositor.
|
||||
|
||||
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.
|
||||
This can be changed by setting the `dpi-aware` option to `yes` in
|
||||
`foot.ini`. When enabled, fonts will **not** be sized using the
|
||||
scaling factor, but will instead be sized using the monitor’s
|
||||
DPI. When the foot window is moved across monitors, the font size is
|
||||
updated for the current monitor’s DPI.
|
||||
|
||||
This means that, assuming the monitors are **at the same viewing
|
||||
distance**, the font size will appear to be the same, at all times.
|
||||
|
||||
_Note_: if you configure **pixelsize**, rather than **size**, then DPI
|
||||
changes will **not** change the font size. Pixels are always pixels.
|
||||
|
||||
|
||||
### Fractional scaling on Wayland
|
||||
|
||||
For a long time, there was no **true** support for _fractional
|
||||
scaling_. That is, values like 1.5 (150%), 1.8 (180%) etc, only
|
||||
integer values, like 2 (200%).
|
||||
|
||||
Compositors that _did_ support fractional scaling did so using a hack;
|
||||
all applications were told to scale to 200%, and then the compositor
|
||||
would down-scale the rendered image to e.g. 150%. This works OK for
|
||||
everything **except fonts**, which ended up blurry.
|
||||
|
||||
With _wayland-protocols 1.32_, a new protocol was introduced, that
|
||||
allows compositors to tell applications the _actual_ scaling
|
||||
factor. Applications can then scale the image using a _viewport_
|
||||
object, instead of setting a scale factor on the raw pixel buffer.
|
||||
|
||||
|
||||
## Supported OSCs
|
||||
|
||||
OSC, _Operating System Command_, are escape sequences that interacts
|
||||
|
|
|
|||
4
client.c
4
client.c
|
|
@ -66,11 +66,13 @@ static const char *
|
|||
version_and_features(void)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "version: %s %cpgo %cime %cgraphemes %cassertions",
|
||||
snprintf(buf, sizeof(buf),
|
||||
"version: %s %cpgo %cime %cgraphemes %cfractional-scaling %cassertions",
|
||||
FOOT_VERSION,
|
||||
feature_pgo() ? '+' : '-',
|
||||
feature_ime() ? '+' : '-',
|
||||
feature_graphemes() ? '+' : '-',
|
||||
feature_fractional_scaling() ? '+' : ':',
|
||||
feature_assertions() ? '+' : '-');
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
15
config.c
15
config.c
|
|
@ -972,17 +972,8 @@ parse_section_main(struct context *ctx)
|
|||
else if (strcmp(key, "underline-thickness") == 0)
|
||||
return value_to_pt_or_px(ctx, &conf->underline_thickness);
|
||||
|
||||
else if (strcmp(key, "dpi-aware") == 0) {
|
||||
if (strcmp(value, "auto") == 0)
|
||||
conf->dpi_aware = DPI_AWARE_AUTO;
|
||||
else {
|
||||
bool value;
|
||||
if (!value_to_bool(ctx, &value))
|
||||
return false;
|
||||
conf->dpi_aware = value ? DPI_AWARE_YES : DPI_AWARE_NO;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(key, "dpi-aware") == 0)
|
||||
return value_to_bool(ctx, &conf->dpi_aware);
|
||||
|
||||
else if (strcmp(key, "workers") == 0)
|
||||
return value_to_uint16(ctx, 10, &conf->render_worker_count);
|
||||
|
|
@ -2939,7 +2930,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.use_custom_underline_offset = false,
|
||||
.box_drawings_uses_font_glyphs = false,
|
||||
.underline_thickness = {.pt = 0., .px = -1},
|
||||
.dpi_aware = DPI_AWARE_AUTO, /* DPI-aware when scaling-factor == 1 */
|
||||
.dpi_aware = false,
|
||||
.bell = {
|
||||
.urgent = false,
|
||||
.notify = false,
|
||||
|
|
|
|||
2
config.h
2
config.h
|
|
@ -137,7 +137,7 @@ struct config {
|
|||
|
||||
enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode;
|
||||
|
||||
enum {DPI_AWARE_AUTO, DPI_AWARE_YES, DPI_AWARE_NO} dpi_aware;
|
||||
bool dpi_aware;
|
||||
struct config_font_list fonts[4];
|
||||
struct font_size_adjustment font_size_adjustment;
|
||||
|
||||
|
|
|
|||
20
csi.c
20
csi.c
|
|
@ -1206,8 +1206,10 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
if (width >= 0 && height >= 0) {
|
||||
char reply[64];
|
||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[4;%d;%dt",
|
||||
height / term->scale, width / term->scale);
|
||||
size_t n = xsnprintf(
|
||||
reply, sizeof(reply), "\033[4;%d;%dt",
|
||||
(int)round(height / term->scale),
|
||||
(int)(width / term->scale));
|
||||
term_to_slave(term, reply, n);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1229,9 +1231,10 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
case 16: { /* report cell size in pixels */
|
||||
char reply[64];
|
||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[6;%d;%dt",
|
||||
term->cell_height / term->scale,
|
||||
term->cell_width / term->scale);
|
||||
size_t n = xsnprintf(
|
||||
reply, sizeof(reply), "\033[6;%d;%dt",
|
||||
(int)round(term->cell_height / term->scale),
|
||||
(int)round(term->cell_width / term->scale));
|
||||
term_to_slave(term, reply, n);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1247,9 +1250,10 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
case 19: { /* report screen size in chars */
|
||||
tll_foreach(term->window->on_outputs, it) {
|
||||
char reply[64];
|
||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[9;%d;%dt",
|
||||
it->item->dim.px_real.height / term->cell_height / term->scale,
|
||||
it->item->dim.px_real.width / term->cell_width / term->scale);
|
||||
size_t n = xsnprintf(
|
||||
reply, sizeof(reply), "\033[9;%d;%dt",
|
||||
(int)round(it->item->dim.px_real.height / term->cell_height / term->scale),
|
||||
(int)round(it->item->dim.px_real.width / term->cell_width / term->scale));
|
||||
term_to_slave(term, reply, n);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
|
|||
Default: _no_.
|
||||
|
||||
*dpi-aware*
|
||||
*auto*, *yes*, or *no*.
|
||||
Boolean.
|
||||
|
||||
When set to *yes*, fonts are sized using the monitor's DPI, making
|
||||
a font of a given size have the same physical size, regardless of
|
||||
|
|
@ -199,12 +199,6 @@ empty string to be set, but it must be quoted: *KEY=""*)
|
|||
instead sized using the monitor's scaling factor; doubling the
|
||||
scaling factor *does* double the font size.
|
||||
|
||||
Finally, if set to *auto*, fonts will be sized using the monitor's
|
||||
DPI if _all_ monitors have a scaling factor of 1. If at least one
|
||||
monitor as a scaling factor larger than 1 (regardless of whether
|
||||
the foot window is mapped on that monitor or not), fonts will be
|
||||
scaled using the scaling factor.
|
||||
|
||||
Note that this option typically does not work with bitmap fonts,
|
||||
which only contains a pre-defined set of sizes, and cannot be
|
||||
dynamically scaled. Whichever size (of the available ones) that
|
||||
|
|
@ -217,7 +211,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
|
|||
to size the font (*dpi-aware=no*), the font's pixel size will be
|
||||
multiplied with the scaling factor.
|
||||
|
||||
Default: _auto_
|
||||
Default: _no_
|
||||
|
||||
*pad*
|
||||
Padding between border and glyphs, in pixels (subject to output
|
||||
|
|
|
|||
|
|
@ -37,3 +37,12 @@ static inline bool feature_graphemes(void)
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool feature_fractional_scaling(void)
|
||||
{
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
2
foot.ini
2
foot.ini
|
|
@ -20,7 +20,7 @@
|
|||
# underline-offset=<font metrics>
|
||||
# underline-thickness=<font underline thickness>
|
||||
# box-drawings-uses-font-glyphs=no
|
||||
# dpi-aware=auto
|
||||
# dpi-aware=no
|
||||
|
||||
# initial-window-size-pixels=700x500 # Or,
|
||||
# initial-window-size-chars=<COLSxROWS>
|
||||
|
|
|
|||
4
main.c
4
main.c
|
|
@ -52,11 +52,13 @@ static const char *
|
|||
version_and_features(void)
|
||||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf), "version: %s %cpgo %cime %cgraphemes %cassertions",
|
||||
snprintf(buf, sizeof(buf),
|
||||
"version: %s %cpgo %cime %cgraphemes %cfractional-scaling %cassertions",
|
||||
FOOT_VERSION,
|
||||
feature_pgo() ? '+' : '-',
|
||||
feature_ime() ? '+' : '-',
|
||||
feature_graphemes() ? '+' : '-',
|
||||
feature_fractional_scaling() ? '+' : '-',
|
||||
feature_assertions() ? '+' : '-');
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,6 +158,11 @@ if wayland_protocols.version().version_compare('>=1.21')
|
|||
add_project_arguments('-DHAVE_XDG_ACTIVATION', language: 'c')
|
||||
wl_proto_xml += [wayland_protocols_datadir + '/staging/xdg-activation/xdg-activation-v1.xml']
|
||||
endif
|
||||
if wayland_protocols.version().version_compare('>=1.31')
|
||||
add_project_arguments('-DHAVE_FRACTIONAL_SCALE', language: 'c')
|
||||
wl_proto_xml += [wayland_protocols_datadir + '/stable/viewporter/viewporter.xml']
|
||||
wl_proto_xml += [wayland_protocols_datadir + '/staging/fractional-scale/fractional-scale-v1.xml']
|
||||
endif
|
||||
|
||||
foreach prot : wl_proto_xml
|
||||
wl_proto_headers += custom_target(
|
||||
|
|
|
|||
2
quirks.c
2
quirks.c
|
|
@ -89,5 +89,5 @@ quirk_sway_subsurface_unmap(struct terminal *term)
|
|||
if (!is_sway())
|
||||
return;
|
||||
|
||||
wl_surface_damage_buffer(term->window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_damage_buffer(term->window->surface.surf, 0, 0, INT32_MAX, INT32_MAX);
|
||||
}
|
||||
|
|
|
|||
231
render.c
231
render.c
|
|
@ -311,7 +311,7 @@ static void
|
|||
draw_unfocused_block(const struct terminal *term, pixman_image_t *pix,
|
||||
const pixman_color_t *color, int x, int y, int cell_cols)
|
||||
{
|
||||
const int scale = term->scale;
|
||||
const int scale = round(term->scale);
|
||||
const int width = min(min(scale, term->cell_width), term->cell_height);
|
||||
|
||||
pixman_image_fill_rectangles(
|
||||
|
|
@ -905,21 +905,21 @@ render_margin(struct terminal *term, struct buffer *buf,
|
|||
if (apply_damage) {
|
||||
/* Top */
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, 0, 0, term->width, term->margins.top);
|
||||
term->window->surface.surf, 0, 0, term->width, term->margins.top);
|
||||
|
||||
/* Bottom */
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, 0, bmargin, term->width, term->margins.bottom);
|
||||
term->window->surface.surf, 0, bmargin, term->width, term->margins.bottom);
|
||||
|
||||
/* Left */
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface,
|
||||
term->window->surface.surf,
|
||||
0, term->margins.top + start_line * term->cell_height,
|
||||
term->margins.left, line_count * term->cell_height);
|
||||
|
||||
/* Right */
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface,
|
||||
term->window->surface.surf,
|
||||
rmargin, term->margins.top + start_line * term->cell_height,
|
||||
term->margins.right, line_count * term->cell_height);
|
||||
}
|
||||
|
|
@ -1027,7 +1027,7 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
|||
#endif
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, term->margins.left, dst_y,
|
||||
term->window->surface.surf, term->margins.left, dst_y,
|
||||
term->width - term->margins.left - term->margins.right, height);
|
||||
|
||||
/*
|
||||
|
|
@ -1104,7 +1104,7 @@ grid_render_scroll_reverse(struct terminal *term, struct buffer *buf,
|
|||
#endif
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, term->margins.left, dst_y,
|
||||
term->window->surface.surf, term->margins.left, dst_y,
|
||||
term->width - term->margins.left - term->margins.right, height);
|
||||
|
||||
/*
|
||||
|
|
@ -1153,7 +1153,7 @@ render_sixel_chunk(struct terminal *term, pixman_image_t *pix, const struct sixe
|
|||
x, y,
|
||||
width, height);
|
||||
|
||||
wl_surface_damage_buffer(term->window->surface, x, y, width, height);
|
||||
wl_surface_damage_buffer(term->window->surface.surf, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1480,7 +1480,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat,
|
|||
free(real_cells);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface,
|
||||
term->window->surface.surf,
|
||||
term->margins.left,
|
||||
term->margins.top + row_idx * term->cell_height,
|
||||
term->width - term->margins.left - term->margins.right,
|
||||
|
|
@ -1502,7 +1502,7 @@ render_ime_preedit(struct terminal *term, struct buffer *buf)
|
|||
static void
|
||||
render_overlay(struct terminal *term)
|
||||
{
|
||||
struct wl_surf_subsurf *overlay = &term->window->overlay;
|
||||
struct wayl_sub_surface *overlay = &term->window->overlay;
|
||||
bool unicode_mode_active = false;
|
||||
|
||||
/* Check if unicode mode is active on at least one seat focusing
|
||||
|
|
@ -1523,8 +1523,8 @@ render_overlay(struct terminal *term)
|
|||
if (likely(style == OVERLAY_NONE)) {
|
||||
if (term->render.last_overlay_style != OVERLAY_NONE) {
|
||||
/* Unmap overlay sub-surface */
|
||||
wl_surface_attach(overlay->surf, NULL, 0, 0);
|
||||
wl_surface_commit(overlay->surf);
|
||||
wl_surface_attach(overlay->surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(overlay->surface.surf);
|
||||
term->render.last_overlay_style = OVERLAY_NONE;
|
||||
term->render.last_overlay_buf = NULL;
|
||||
|
||||
|
|
@ -1691,17 +1691,18 @@ render_overlay(struct terminal *term)
|
|||
&(pixman_rectangle16_t){0, 0, term->width, term->height});
|
||||
|
||||
quirk_weston_subsurface_desync_on(overlay->sub);
|
||||
wayl_surface_scale(
|
||||
term->window, &overlay->surface, buf, term->scale);
|
||||
wl_subsurface_set_position(overlay->sub, 0, 0);
|
||||
wl_surface_set_buffer_scale(overlay->surf, term->scale);
|
||||
wl_surface_attach(overlay->surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_attach(overlay->surface.surf, buf->wl_buf, 0, 0);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
overlay->surf,
|
||||
overlay->surface.surf,
|
||||
damage_bounds.x1, damage_bounds.y1,
|
||||
damage_bounds.x2 - damage_bounds.x1,
|
||||
damage_bounds.y2 - damage_bounds.y1);
|
||||
|
||||
wl_surface_commit(overlay->surf);
|
||||
wl_surface_commit(overlay->surface.surf);
|
||||
quirk_weston_subsurface_desync_off(overlay->sub);
|
||||
|
||||
buf->age = 0;
|
||||
|
|
@ -1828,15 +1829,12 @@ 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)
|
||||
csd_commit(struct terminal *term, struct wayl_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);
|
||||
wl_surface_commit(surf);
|
||||
wayl_surface_scale(term->window, surf, buf, term->scale);
|
||||
wl_surface_attach(surf->surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(surf->surf, 0, 0, buf->width, buf->height);
|
||||
wl_surface_commit(surf->surf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1852,8 +1850,7 @@ render_csd_part(struct terminal *term,
|
|||
}
|
||||
|
||||
static void
|
||||
render_osd(struct terminal *term,
|
||||
struct wl_surface *surf, struct wl_subsurface *sub_surf,
|
||||
render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf,
|
||||
struct fcft_font *font, struct buffer *buf,
|
||||
const char32_t *text, uint32_t _fg, uint32_t _bg,
|
||||
unsigned x, unsigned y)
|
||||
|
|
@ -1926,23 +1923,20 @@ render_osd(struct terminal *term,
|
|||
pixman_image_unref(src);
|
||||
pixman_image_set_clip_region32(buf->pix[0], NULL);
|
||||
|
||||
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, buf->width, buf->height);
|
||||
wl_surface_set_buffer_scale(surf, term->scale);
|
||||
quirk_weston_subsurface_desync_on(sub_surf->sub);
|
||||
wayl_surface_scale(term->window, &sub_surf->surface, buf, term->scale);
|
||||
wl_surface_attach(sub_surf->surface.surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(sub_surf->surface.surf, 0, 0, buf->width, buf->height);
|
||||
|
||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||
if (region != NULL) {
|
||||
wl_region_add(region, 0, 0, buf->width, buf->height);
|
||||
wl_surface_set_opaque_region(surf, region);
|
||||
wl_surface_set_opaque_region(sub_surf->surface.surf, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
wl_surface_commit(surf);
|
||||
quirk_weston_subsurface_desync_off(sub_surf);
|
||||
wl_surface_commit(sub_surf->surface.surf);
|
||||
quirk_weston_subsurface_desync_off(sub_surf->sub);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1951,13 +1945,10 @@ render_csd_title(struct terminal *term, const struct csd_data *info,
|
|||
{
|
||||
xassert(term->window->csd_mode == CSD_YES);
|
||||
|
||||
struct wl_surf_subsurf *surf = &term->window->csd.surface[CSD_SURF_TITLE];
|
||||
struct wayl_sub_surface *surf = &term->window->csd.surface[CSD_SURF_TITLE];
|
||||
if (info->width == 0 || info->height == 0)
|
||||
return;
|
||||
|
||||
xassert(info->width % term->scale == 0);
|
||||
xassert(info->height % term->scale == 0);
|
||||
|
||||
uint32_t bg = term->conf->csd.color.title_set
|
||||
? term->conf->csd.color.title
|
||||
: 0xffu << 24 | term->conf->colors.fg;
|
||||
|
|
@ -1980,11 +1971,10 @@ render_csd_title(struct terminal *term, const struct csd_data *info,
|
|||
|
||||
const int margin = M != NULL ? M->advance.x : win->csd.font->max_advance.x;
|
||||
|
||||
render_osd(term, surf->surf, surf->sub, win->csd.font,
|
||||
buf, title_text, fg, bg, margin,
|
||||
render_osd(term, surf, win->csd.font, buf, title_text, fg, bg, margin,
|
||||
(buf->height - win->csd.font->height) / 2);
|
||||
|
||||
csd_commit(term, surf->surf, buf);
|
||||
csd_commit(term, &surf->surface, buf);
|
||||
free(_title_text);
|
||||
}
|
||||
|
||||
|
|
@ -1995,26 +1985,23 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
|
|||
xassert(term->window->csd_mode == CSD_YES);
|
||||
xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM);
|
||||
|
||||
struct wl_surface *surf = term->window->csd.surface[surf_idx].surf;
|
||||
struct wayl_surface *surf = &term->window->csd.surface[surf_idx].surface;
|
||||
|
||||
if (info->width == 0 || info->height == 0)
|
||||
return;
|
||||
|
||||
xassert(info->width % term->scale == 0);
|
||||
xassert(info->height % term->scale == 0);
|
||||
|
||||
{
|
||||
pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0);
|
||||
render_csd_part(term, surf, buf, info->width, info->height, &color);
|
||||
render_csd_part(term, surf->surf, buf, info->width, info->height, &color);
|
||||
}
|
||||
|
||||
/*
|
||||
* The “visible” border.
|
||||
*/
|
||||
|
||||
int scale = term->scale;
|
||||
int bwidth = term->conf->csd.border_width * scale;
|
||||
int vwidth = term->conf->csd.border_width_visible * scale; /* Visible size */
|
||||
float scale = term->scale;
|
||||
int bwidth = round(term->conf->csd.border_width * scale);
|
||||
int vwidth = round(term->conf->csd.border_width_visible * scale); /* Visible size */
|
||||
|
||||
xassert(bwidth >= vwidth);
|
||||
|
||||
|
|
@ -2067,7 +2054,6 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
|
|||
uint16_t alpha = _color >> 24 | (_color >> 24 << 8);
|
||||
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha);
|
||||
|
||||
|
||||
pixman_image_fill_rectangles(
|
||||
PIXMAN_OP_SRC, buf->pix[0], &color, 1,
|
||||
&(pixman_rectangle16_t){x, y, w, h});
|
||||
|
|
@ -2284,14 +2270,11 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
|
|||
xassert(term->window->csd_mode == CSD_YES);
|
||||
xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE);
|
||||
|
||||
struct wl_surface *surf = term->window->csd.surface[surf_idx].surf;
|
||||
struct wayl_surface *surf = &term->window->csd.surface[surf_idx].surface;
|
||||
|
||||
if (info->width == 0 || info->height == 0)
|
||||
return;
|
||||
|
||||
xassert(info->width % term->scale == 0);
|
||||
xassert(info->height % term->scale == 0);
|
||||
|
||||
uint32_t _color;
|
||||
uint16_t alpha = 0xffff;
|
||||
bool is_active = false;
|
||||
|
|
@ -2339,7 +2322,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
|
|||
_color = color_dim(term, _color);
|
||||
|
||||
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha);
|
||||
render_csd_part(term, surf, buf, info->width, info->height, &color);
|
||||
render_csd_part(term, surf->surf, buf, info->width, info->height, &color);
|
||||
|
||||
switch (surf_idx) {
|
||||
case CSD_SURF_MINIMIZE: render_csd_button_minimize(term, buf); break;
|
||||
|
|
@ -2374,7 +2357,7 @@ render_csd(struct terminal *term)
|
|||
const int width = infos[i].width;
|
||||
const int height = infos[i].height;
|
||||
|
||||
struct wl_surface *surf = term->window->csd.surface[i].surf;
|
||||
struct wl_surface *surf = term->window->csd.surface[i].surface.surf;
|
||||
struct wl_subsurface *sub = term->window->csd.surface[i].sub;
|
||||
|
||||
xassert(surf != NULL);
|
||||
|
|
@ -2413,7 +2396,7 @@ render_scrollback_position(struct terminal *term)
|
|||
struct wl_window *win = term->window;
|
||||
|
||||
if (term->grid->view == term->grid->offset) {
|
||||
if (win->scrollback_indicator.surf != NULL) {
|
||||
if (win->scrollback_indicator.surface.surf != NULL) {
|
||||
wayl_win_subsurface_destroy(&win->scrollback_indicator);
|
||||
|
||||
/* Work around Sway bug - unmapping a sub-surface does not damage
|
||||
|
|
@ -2423,7 +2406,7 @@ render_scrollback_position(struct terminal *term)
|
|||
return;
|
||||
}
|
||||
|
||||
if (win->scrollback_indicator.surf == NULL) {
|
||||
if (win->scrollback_indicator.surface.surf == NULL) {
|
||||
if (!wayl_win_subsurface_new(
|
||||
win, &win->scrollback_indicator, false))
|
||||
{
|
||||
|
|
@ -2432,7 +2415,7 @@ render_scrollback_position(struct terminal *term)
|
|||
}
|
||||
}
|
||||
|
||||
xassert(win->scrollback_indicator.surf != NULL);
|
||||
xassert(win->scrollback_indicator.surface.surf != NULL);
|
||||
xassert(win->scrollback_indicator.sub != NULL);
|
||||
|
||||
/* Find absolute row number of the scrollback start */
|
||||
|
|
@ -2530,8 +2513,8 @@ render_scrollback_position(struct terminal *term)
|
|||
const int y = (term->margins.top + surf_top) / scale * scale;
|
||||
|
||||
if (y + height > term->height) {
|
||||
wl_surface_attach(win->scrollback_indicator.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->scrollback_indicator.surf);
|
||||
wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->scrollback_indicator.surface.surf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2550,8 +2533,7 @@ render_scrollback_position(struct terminal *term)
|
|||
|
||||
render_osd(
|
||||
term,
|
||||
win->scrollback_indicator.surf,
|
||||
win->scrollback_indicator.sub,
|
||||
&win->scrollback_indicator,
|
||||
term->fonts[0], buf, text,
|
||||
fg, 0xffu << 24 | bg,
|
||||
width - margin - c32len(text) * term->cell_width, margin);
|
||||
|
|
@ -2569,7 +2551,7 @@ render_render_timer(struct terminal *term, struct timespec render_time)
|
|||
char32_t text[256];
|
||||
mbstoc32(text, usecs_str, ALEN(text));
|
||||
|
||||
const int scale = term->scale;
|
||||
const int scale = round(term->scale);
|
||||
const int cell_count = c32len(text);
|
||||
const int margin = 3 * scale;
|
||||
const int width =
|
||||
|
|
@ -2587,8 +2569,7 @@ render_render_timer(struct terminal *term, struct timespec render_time)
|
|||
|
||||
render_osd(
|
||||
term,
|
||||
win->render_timer.surf,
|
||||
win->render_timer.sub,
|
||||
&win->render_timer,
|
||||
term->fonts[0], buf, text,
|
||||
term->colors.table[0], 0xffu << 24 | term->colors.table[8 + 1],
|
||||
margin, margin);
|
||||
|
|
@ -2935,7 +2916,7 @@ grid_render(struct terminal *term)
|
|||
int height = (r - first_dirty_row) * term->cell_height;
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, x, y, width, height);
|
||||
term->window->surface.surf, x, y, width, height);
|
||||
pixman_region32_union_rect(
|
||||
&buf->dirty, &buf->dirty, 0, y, buf->width, height);
|
||||
}
|
||||
|
|
@ -2963,7 +2944,7 @@ grid_render(struct terminal *term)
|
|||
int width = term->width - term->margins.left - term->margins.right;
|
||||
int height = (term->rows - first_dirty_row) * term->cell_height;
|
||||
|
||||
wl_surface_damage_buffer(term->window->surface, x, y, width, height);
|
||||
wl_surface_damage_buffer(term->window->surface.surf, x, y, width, height);
|
||||
pixman_region32_union_rect(&buf->dirty, &buf->dirty, 0, y, buf->width, height);
|
||||
}
|
||||
|
||||
|
|
@ -3030,17 +3011,17 @@ grid_render(struct terminal *term)
|
|||
xassert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows);
|
||||
|
||||
xassert(term->window->frame_callback == NULL);
|
||||
term->window->frame_callback = wl_surface_frame(term->window->surface);
|
||||
term->window->frame_callback = wl_surface_frame(term->window->surface.surf);
|
||||
wl_callback_add_listener(term->window->frame_callback, &frame_listener, term);
|
||||
|
||||
wl_surface_set_buffer_scale(term->window->surface, term->scale);
|
||||
wayl_win_scale(term->window, buf);
|
||||
|
||||
if (term->wl->presentation != NULL && term->conf->presentation_timings) {
|
||||
struct timespec commit_time;
|
||||
clock_gettime(term->wl->presentation_clock_id, &commit_time);
|
||||
|
||||
struct wp_presentation_feedback *feedback = wp_presentation_feedback(
|
||||
term->wl->presentation, term->window->surface);
|
||||
term->wl->presentation, term->window->surface.surf);
|
||||
|
||||
if (feedback == NULL) {
|
||||
LOG_WARN("failed to create presentation feedback");
|
||||
|
|
@ -3064,14 +3045,11 @@ grid_render(struct terminal *term)
|
|||
|
||||
if (term->conf->tweak.damage_whole_window) {
|
||||
wl_surface_damage_buffer(
|
||||
term->window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
term->window->surface.surf, 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);
|
||||
wl_surface_commit(term->window->surface);
|
||||
wl_surface_attach(term->window->surface.surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_commit(term->window->surface.surf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3133,17 +3111,17 @@ render_search_box(struct terminal *term)
|
|||
const size_t wanted_visible_cells = max(20, total_cells);
|
||||
|
||||
xassert(term->scale >= 1);
|
||||
const int scale = term->scale;
|
||||
const int rounded_scale = round(term->scale);
|
||||
|
||||
const size_t margin = 3 * scale;
|
||||
const size_t margin = 3 * rounded_scale;
|
||||
|
||||
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 + scale - 1) / scale * scale);
|
||||
(2 * margin + wanted_visible_cells * term->cell_width + rounded_scale - 1) / rounded_scale * rounded_scale);
|
||||
const size_t height = min(
|
||||
term->height - 2 * margin,
|
||||
(2 * margin + 1 * term->cell_height + scale - 1) / scale * scale);
|
||||
(2 * margin + 1 * term->cell_height + rounded_scale - 1) / rounded_scale * rounded_scale);
|
||||
|
||||
const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width;
|
||||
size_t glyph_offset = term->render.search_glyph_offset;
|
||||
|
|
@ -3390,24 +3368,21 @@ render_search_box(struct terminal *term)
|
|||
/* TODO: this is only necessary on a window resize */
|
||||
wl_subsurface_set_position(
|
||||
term->window->search.sub,
|
||||
margin / scale,
|
||||
max(0, (int32_t)term->height - height - margin) / scale);
|
||||
margin / term->scale,
|
||||
max(0, (int32_t)term->height - height - margin) / term->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);
|
||||
wayl_surface_scale(term->window, &term->window->search.surface, buf, term->scale);
|
||||
wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0);
|
||||
wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height);
|
||||
|
||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||
if (region != NULL) {
|
||||
wl_region_add(region, width - visible_width, 0, visible_width, height);
|
||||
wl_surface_set_opaque_region(term->window->search.surf, region);
|
||||
wl_surface_set_opaque_region(term->window->search.surface.surf, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
wl_surface_commit(term->window->search.surf);
|
||||
wl_surface_commit(term->window->search.surface.surf);
|
||||
quirk_weston_subsurface_desync_off(term->window->search.sub);
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
|
|
@ -3423,7 +3398,7 @@ render_urls(struct terminal *term)
|
|||
struct wl_window *win = term->window;
|
||||
xassert(tll_length(win->urls) > 0);
|
||||
|
||||
const int scale = term->scale;
|
||||
const int scale = round(term->scale);
|
||||
const int x_margin = 2 * scale;
|
||||
const int y_margin = 1 * scale;
|
||||
|
||||
|
|
@ -3488,7 +3463,7 @@ render_urls(struct terminal *term)
|
|||
continue;
|
||||
}
|
||||
|
||||
struct wl_surface *surf = it->item.surf.surf;
|
||||
struct wl_surface *surf = it->item.surf.surface.surf;
|
||||
struct wl_subsurface *sub_surf = it->item.surf.sub;
|
||||
|
||||
if (surf == NULL || sub_surf == NULL)
|
||||
|
|
@ -3623,23 +3598,22 @@ render_urls(struct terminal *term)
|
|||
: term->colors.table[3];
|
||||
|
||||
for (size_t i = 0; i < render_count; i++) {
|
||||
struct wl_surface *surf = info[i].url->surf.surf;
|
||||
struct wl_subsurface *sub_surf = info[i].url->surf.sub;
|
||||
const struct wayl_sub_surface *sub_surf = &info[i].url->surf;
|
||||
|
||||
const char32_t *label = info[i].text;
|
||||
const int x = info[i].x;
|
||||
const int y = info[i].y;
|
||||
|
||||
xassert(surf != NULL);
|
||||
xassert(sub_surf != NULL);
|
||||
xassert(sub_surf->surface.surf != NULL);
|
||||
xassert(sub_surf->sub != NULL);
|
||||
|
||||
wl_subsurface_set_position(
|
||||
sub_surf,
|
||||
sub_surf->sub,
|
||||
(term->margins.left + x) / term->scale,
|
||||
(term->margins.top + y) / term->scale);
|
||||
|
||||
render_osd(
|
||||
term, surf, sub_surf, term->fonts[0], bufs[i], label,
|
||||
term, sub_surf, term->fonts[0], bufs[i], label,
|
||||
fg, 0xffu << 24 | bg, x_margin, y_margin);
|
||||
|
||||
free(info[i].text);
|
||||
|
|
@ -3869,13 +3843,17 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
if (term->cell_width == 0 && term->cell_height == 0)
|
||||
return false;
|
||||
|
||||
int scale = -1;
|
||||
tll_foreach(term->window->on_outputs, it) {
|
||||
if (it->item->scale > scale)
|
||||
scale = it->item->scale;
|
||||
float scale = -1;
|
||||
if (wayl_fractional_scaling(term->wl)) {
|
||||
scale = term->window->scale;
|
||||
} else {
|
||||
tll_foreach(term->window->on_outputs, it) {
|
||||
if (it->item->scale > scale)
|
||||
scale = it->item->scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale < 0) {
|
||||
if (scale < 0.) {
|
||||
/* Haven't 'entered' an output yet? */
|
||||
scale = term->scale;
|
||||
}
|
||||
|
|
@ -3923,13 +3901,18 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
* Ensure we can scale to logical size, and back to
|
||||
* pixels without truncating.
|
||||
*/
|
||||
if (width % scale)
|
||||
width += scale - width % scale;
|
||||
if (height % scale)
|
||||
height += scale - height % scale;
|
||||
if (wayl_fractional_scaling(term->wl)) {
|
||||
xassert((int)round(scale) == (int)scale);
|
||||
|
||||
xassert(width % scale == 0);
|
||||
xassert(height % scale == 0);
|
||||
int iscale = scale;
|
||||
if (width % iscale)
|
||||
width += iscale - width % iscale;
|
||||
if (height % iscale)
|
||||
height += iscale - height % iscale;
|
||||
|
||||
xassert(width % iscale == 0);
|
||||
xassert(height % iscale == 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -4270,34 +4253,36 @@ render_xcursor_update(struct seat *seat)
|
|||
|
||||
if (seat->pointer.xcursor == XCURSOR_HIDDEN) {
|
||||
/* Hide cursor */
|
||||
wl_surface_attach(seat->pointer.surface, NULL, 0, 0);
|
||||
wl_surface_commit(seat->pointer.surface);
|
||||
wl_surface_attach(seat->pointer.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(seat->pointer.surface.surf);
|
||||
return;
|
||||
}
|
||||
|
||||
xassert(seat->pointer.cursor != NULL);
|
||||
|
||||
const int scale = seat->pointer.scale;
|
||||
const float scale = seat->pointer.scale;
|
||||
struct wl_cursor_image *image = seat->pointer.cursor->images[0];
|
||||
struct wl_buffer *buf = wl_cursor_image_get_buffer(image);
|
||||
|
||||
wl_surface_attach(
|
||||
seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0);
|
||||
wayl_surface_scale_explicit_width_height(
|
||||
seat->mouse_focus->window,
|
||||
&seat->pointer.surface, image->width, image->height, scale);
|
||||
|
||||
wl_surface_attach(seat->pointer.surface.surf, buf, 0, 0);
|
||||
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl_pointer, seat->pointer.serial,
|
||||
seat->pointer.surface,
|
||||
seat->pointer.surface.surf,
|
||||
image->hotspot_x / scale, image->hotspot_y / scale);
|
||||
|
||||
wl_surface_damage_buffer(
|
||||
seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
|
||||
wl_surface_set_buffer_scale(seat->pointer.surface, scale);
|
||||
seat->pointer.surface.surf, 0, 0, INT32_MAX, INT32_MAX);
|
||||
|
||||
xassert(seat->pointer.xcursor_callback == NULL);
|
||||
seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface);
|
||||
seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface.surf);
|
||||
wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat);
|
||||
|
||||
wl_surface_commit(seat->pointer.surface);
|
||||
wl_surface_commit(seat->pointer.surface.surf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
64
terminal.c
64
terminal.c
|
|
@ -912,42 +912,6 @@ get_font_subpixel(const struct terminal *term)
|
|||
return FCFT_SUBPIXEL_DEFAULT;
|
||||
}
|
||||
|
||||
static bool
|
||||
term_font_size_by_dpi(const struct terminal *term)
|
||||
{
|
||||
switch (term->conf->dpi_aware) {
|
||||
case DPI_AWARE_YES: return true;
|
||||
case DPI_AWARE_NO: return false;
|
||||
|
||||
case DPI_AWARE_AUTO:
|
||||
/*
|
||||
* Scale using DPI if all monitors have a scaling factor or 1.
|
||||
*
|
||||
* The idea is this: if a user, with multiple monitors, have
|
||||
* enabled scaling on at least one monitor, then he/she has
|
||||
* most likely done so to match the size of his/hers other
|
||||
* monitors.
|
||||
*
|
||||
* I.e. if the user has one monitor with a scaling factor of
|
||||
* one, and another with a scaling factor of two, he/she
|
||||
* expects things to be twice as large on the second
|
||||
* monitor.
|
||||
*
|
||||
* If we (foot) scale using DPI on the first monitor, and
|
||||
* using the scaling factor on the second monitor, foot will
|
||||
* *not* look twice as big on the second monitor.
|
||||
*/
|
||||
tll_foreach(term->wl->monitors, it) {
|
||||
const struct monitor *mon = &it->item;
|
||||
if (mon->scale > 1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BUG("unhandled DPI awareness value");
|
||||
}
|
||||
|
||||
int
|
||||
term_pt_or_px_as_pixels(const struct terminal *term,
|
||||
const struct pt_or_px *pt_or_px)
|
||||
|
|
@ -1000,14 +964,14 @@ reload_fonts(struct terminal *term)
|
|||
bool use_px_size = term->font_sizes[i][j].px_size > 0;
|
||||
char size[64];
|
||||
|
||||
const int scale = term->font_is_sized_by_dpi ? 1 : term->scale;
|
||||
const float scale = term->font_is_sized_by_dpi ? 1. : term->scale;
|
||||
|
||||
if (use_px_size)
|
||||
snprintf(size, sizeof(size), ":pixelsize=%d",
|
||||
term->font_sizes[i][j].px_size * scale);
|
||||
(int)round(term->font_sizes[i][j].px_size * scale));
|
||||
else
|
||||
snprintf(size, sizeof(size), ":size=%.2f",
|
||||
term->font_sizes[i][j].pt_size * (double)scale);
|
||||
term->font_sizes[i][j].pt_size * scale);
|
||||
|
||||
size_t len = strlen(font->pattern) + strlen(size) + 1;
|
||||
names[i][j] = xmalloc(len);
|
||||
|
|
@ -1232,7 +1196,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.reverse_wrap = true,
|
||||
.auto_margin = true,
|
||||
.window_title_stack = tll_init(),
|
||||
.scale = 1,
|
||||
.scale = 1.,
|
||||
.flash = {.fd = flash_fd},
|
||||
.blink = {.fd = -1},
|
||||
.vt = {
|
||||
|
|
@ -2158,7 +2122,7 @@ term_font_dpi_changed(struct terminal *term, int old_scale)
|
|||
xassert(term->scale > 0);
|
||||
|
||||
bool was_scaled_using_dpi = term->font_is_sized_by_dpi;
|
||||
bool will_scale_using_dpi = term_font_size_by_dpi(term);
|
||||
bool will_scale_using_dpi = term->conf->dpi_aware;
|
||||
|
||||
bool need_font_reload =
|
||||
was_scaled_using_dpi != will_scale_using_dpi ||
|
||||
|
|
@ -3589,23 +3553,23 @@ term_single_shift(struct terminal *term, enum charset_designator idx)
|
|||
enum term_surface
|
||||
term_surface_kind(const struct terminal *term, const struct wl_surface *surface)
|
||||
{
|
||||
if (likely(surface == term->window->surface))
|
||||
if (likely(surface == term->window->surface.surf))
|
||||
return TERM_SURF_GRID;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TITLE].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TITLE].surface.surf)
|
||||
return TERM_SURF_TITLE;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_LEFT].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_LEFT].surface.surf)
|
||||
return TERM_SURF_BORDER_LEFT;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_RIGHT].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_RIGHT].surface.surf)
|
||||
return TERM_SURF_BORDER_RIGHT;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TOP].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_TOP].surface.surf)
|
||||
return TERM_SURF_BORDER_TOP;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_BOTTOM].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_BOTTOM].surface.surf)
|
||||
return TERM_SURF_BORDER_BOTTOM;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MINIMIZE].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MINIMIZE].surface.surf)
|
||||
return TERM_SURF_BUTTON_MINIMIZE;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MAXIMIZE].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_MAXIMIZE].surface.surf)
|
||||
return TERM_SURF_BUTTON_MAXIMIZE;
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_CLOSE].surf)
|
||||
else if (surface == term->window->csd.surface[CSD_SURF_CLOSE].surface.surf)
|
||||
return TERM_SURF_BUTTON_CLOSE;
|
||||
else
|
||||
return TERM_SURF_NONE;
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ struct terminal {
|
|||
int fd;
|
||||
} blink;
|
||||
|
||||
int scale;
|
||||
float scale;
|
||||
int width; /* pixels */
|
||||
int height; /* pixels */
|
||||
int stashed_width;
|
||||
|
|
|
|||
|
|
@ -511,6 +511,7 @@ test_section_main(void)
|
|||
test_boolean(&ctx, &parse_section_main, "box-drawings-uses-font-glyphs", &conf.box_drawings_uses_font_glyphs);
|
||||
test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title);
|
||||
test_boolean(&ctx, &parse_section_main, "notify-focus-inhibit", &conf.notify_focus_inhibit);
|
||||
test_boolean(&ctx, &parse_section_main, "dpi-aware", &conf.dpi_aware);
|
||||
|
||||
test_pt_or_px(&ctx, &parse_section_main, "font-size-adjustment", &conf.font_size_adjustment.pt_or_px); /* TODO: test ‘N%’ values too */
|
||||
test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height);
|
||||
|
|
@ -524,17 +525,6 @@ test_section_main(void)
|
|||
|
||||
test_spawn_template(&ctx, &parse_section_main, "notify", &conf.notify);
|
||||
|
||||
test_enum(
|
||||
&ctx, &parse_section_main, "dpi-aware",
|
||||
9,
|
||||
(const char *[]){"on", "true", "yes", "1",
|
||||
"off", "false", "no", "0",
|
||||
"auto"},
|
||||
(int []){DPI_AWARE_YES, DPI_AWARE_YES, DPI_AWARE_YES, DPI_AWARE_YES,
|
||||
DPI_AWARE_NO, DPI_AWARE_NO, DPI_AWARE_NO, DPI_AWARE_NO,
|
||||
DPI_AWARE_AUTO},
|
||||
(int *)&conf.dpi_aware);
|
||||
|
||||
test_enum(&ctx, &parse_section_main, "selection-target",
|
||||
4,
|
||||
(const char *[]){"none", "primary", "clipboard", "both"},
|
||||
|
|
|
|||
311
wayland.c
311
wayland.c
|
|
@ -32,12 +32,12 @@
|
|||
#include "xmalloc.h"
|
||||
|
||||
static void
|
||||
csd_reload_font(struct wl_window *win, int old_scale)
|
||||
csd_reload_font(struct wl_window *win, float old_scale)
|
||||
{
|
||||
struct terminal *term = win->term;
|
||||
const struct config *conf = term->conf;
|
||||
|
||||
const int scale = term->scale;
|
||||
const float scale = term->scale;
|
||||
|
||||
bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen;
|
||||
if (!enable_csd)
|
||||
|
|
@ -52,10 +52,10 @@ csd_reload_font(struct wl_window *win, int old_scale)
|
|||
patterns[i] = conf->csd.font.arr[i].pattern;
|
||||
|
||||
char pixelsize[32];
|
||||
snprintf(pixelsize, sizeof(pixelsize),
|
||||
"pixelsize=%u", conf->csd.title_height * scale * 1 / 2);
|
||||
snprintf(pixelsize, sizeof(pixelsize), "pixelsize=%u",
|
||||
(int)round(conf->csd.title_height * scale * 1 / 2));
|
||||
|
||||
LOG_DBG("loading CSD font \"%s:%s\" (old-scale=%d, scale=%d)",
|
||||
LOG_DBG("loading CSD font \"%s:%s\" (old-scale=%.2f, scale=%.2f)",
|
||||
patterns[0], pixelsize, old_scale, scale);
|
||||
|
||||
win->csd.font = fcft_from_name(conf->csd.font.count, patterns, pixelsize);
|
||||
|
|
@ -74,12 +74,12 @@ csd_instantiate(struct wl_window *win)
|
|||
|
||||
for (size_t i = CSD_SURF_MINIMIZE; i < CSD_SURF_COUNT; i++) {
|
||||
bool ret = wayl_win_subsurface_new_with_custom_parent(
|
||||
win, win->csd.surface[CSD_SURF_TITLE].surf, &win->csd.surface[i],
|
||||
win, win->csd.surface[CSD_SURF_TITLE].surface.surf, &win->csd.surface[i],
|
||||
true);
|
||||
xassert(ret);
|
||||
}
|
||||
|
||||
csd_reload_font(win, -1);
|
||||
csd_reload_font(win, -1.);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -187,8 +187,12 @@ seat_destroy(struct seat *seat)
|
|||
|
||||
if (seat->pointer.theme != NULL)
|
||||
wl_cursor_theme_destroy(seat->pointer.theme);
|
||||
if (seat->pointer.surface != NULL)
|
||||
wl_surface_destroy(seat->pointer.surface);
|
||||
if (seat->pointer.surface.surf != NULL)
|
||||
wl_surface_destroy(seat->pointer.surface.surf);
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (seat->pointer.surface.viewport != NULL)
|
||||
wp_viewport_destroy(seat->pointer.surface.viewport);
|
||||
#endif
|
||||
if (seat->pointer.xcursor_callback != NULL)
|
||||
wl_callback_destroy(seat->pointer.xcursor_callback);
|
||||
|
||||
|
|
@ -288,27 +292,46 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
|||
|
||||
if (caps & WL_SEAT_CAPABILITY_POINTER) {
|
||||
if (seat->wl_pointer == NULL) {
|
||||
xassert(seat->pointer.surface == NULL);
|
||||
seat->pointer.surface = wl_compositor_create_surface(seat->wayl->compositor);
|
||||
xassert(seat->pointer.surface.surf == NULL);
|
||||
seat->pointer.surface.surf =
|
||||
wl_compositor_create_surface(seat->wayl->compositor);
|
||||
|
||||
if (seat->pointer.surface == NULL) {
|
||||
if (seat->pointer.surface.surf == NULL) {
|
||||
LOG_ERR("%s: failed to create pointer surface", seat->name);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
xassert(seat->pointer.surface.viewport == NULL);
|
||||
seat->pointer.surface.viewport = wp_viewporter_get_viewport(
|
||||
seat->wayl->viewporter, seat->pointer.surface.surf);
|
||||
|
||||
if (seat->pointer.surface.viewport == NULL) {
|
||||
LOG_ERR("%s: failed to create pointer viewport", seat->name);
|
||||
wl_surface_destroy(seat->pointer.surface.surf);
|
||||
seat->pointer.surface.surf = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
seat->wl_pointer = wl_seat_get_pointer(wl_seat);
|
||||
wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
|
||||
}
|
||||
} else {
|
||||
if (seat->wl_pointer != NULL) {
|
||||
wl_pointer_release(seat->wl_pointer);
|
||||
wl_surface_destroy(seat->pointer.surface);
|
||||
wl_surface_destroy(seat->pointer.surface.surf);
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
wp_viewport_destroy(seat->pointer.surface.viewport);
|
||||
seat->pointer.surface.viewport = NULL;
|
||||
#endif
|
||||
|
||||
if (seat->pointer.theme != NULL)
|
||||
wl_cursor_theme_destroy(seat->pointer.theme);
|
||||
|
||||
seat->wl_pointer = NULL;
|
||||
seat->pointer.surface = NULL;
|
||||
seat->pointer.surface.surf = NULL;
|
||||
seat->pointer.theme = NULL;
|
||||
seat->pointer.cursor = NULL;
|
||||
}
|
||||
|
|
@ -334,7 +357,7 @@ update_term_for_output_change(struct terminal *term)
|
|||
if (tll_length(term->window->on_outputs) == 0)
|
||||
return;
|
||||
|
||||
int old_scale = term->scale;
|
||||
float old_scale = term->scale;
|
||||
|
||||
render_resize(term, term->width / term->scale, term->height / term->scale);
|
||||
term_font_dpi_changed(term, old_scale);
|
||||
|
|
@ -350,11 +373,6 @@ update_terms_on_monitor(struct monitor *mon)
|
|||
tll_foreach(wayl->terms, it) {
|
||||
struct terminal *term = it->item;
|
||||
|
||||
if (term->conf->dpi_aware == DPI_AWARE_AUTO) {
|
||||
update_term_for_output_change(term);
|
||||
continue;
|
||||
}
|
||||
|
||||
tll_foreach(term->window->on_outputs, it2) {
|
||||
if (it2->item == mon) {
|
||||
update_term_for_output_change(term);
|
||||
|
|
@ -848,7 +866,7 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
|
|||
* anytime soon. Some compositors require a commit in
|
||||
* combination with an ack - make them happy.
|
||||
*/
|
||||
wl_surface_commit(win->surface);
|
||||
wl_surface_commit(win->surface.surf);
|
||||
}
|
||||
|
||||
if (wasnt_configured)
|
||||
|
|
@ -1121,6 +1139,27 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->viewporter = wl_registry_bind(
|
||||
wayl->registry, name, &wp_viewporter_interface, required);
|
||||
}
|
||||
|
||||
else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->fractional_scale_manager = wl_registry_bind(
|
||||
wayl->registry, name,
|
||||
&wp_fractional_scale_manager_v1_interface, required);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
|
||||
const uint32_t required = 1;
|
||||
|
|
@ -1204,7 +1243,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
|||
|
||||
if (seat->wl_keyboard != NULL)
|
||||
keyboard_listener.leave(
|
||||
seat, seat->wl_keyboard, -1, seat->kbd_focus->window->surface);
|
||||
seat, seat->wl_keyboard, -1, seat->kbd_focus->window->surface.surf);
|
||||
}
|
||||
|
||||
if (seat->mouse_focus != NULL) {
|
||||
|
|
@ -1214,7 +1253,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
|||
|
||||
if (seat->wl_pointer != NULL)
|
||||
pointer_listener.leave(
|
||||
seat, seat->wl_pointer, -1, seat->mouse_focus->window->surface);
|
||||
seat, seat->wl_pointer, -1, seat->mouse_focus->window->surface.surf);
|
||||
}
|
||||
|
||||
seat_destroy(seat);
|
||||
|
|
@ -1347,6 +1386,14 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager,
|
|||
"bell.urgent will fall back to coloring the window margins red");
|
||||
}
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (wayl->fractional_scale_manager == NULL || wayl->viewporter == NULL) {
|
||||
#else
|
||||
if (true) {
|
||||
#endif
|
||||
LOG_WARN("fractional scaling not available");
|
||||
}
|
||||
|
||||
if (presentation_timings && wayl->presentation == NULL) {
|
||||
LOG_ERR("presentation time interface not implemented by compositor");
|
||||
goto out;
|
||||
|
|
@ -1435,6 +1482,12 @@ wayl_destroy(struct wayland *wayl)
|
|||
zwp_text_input_manager_v3_destroy(wayl->text_input_manager);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (wayl->fractional_scale_manager != NULL)
|
||||
wp_fractional_scale_manager_v1_destroy(wayl->fractional_scale_manager);
|
||||
if (wayl->viewporter != NULL)
|
||||
wp_viewporter_destroy(wayl->viewporter);
|
||||
#endif
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
if (wayl->xdg_activation != NULL)
|
||||
xdg_activation_v1_destroy(wayl->xdg_activation);
|
||||
|
|
@ -1469,6 +1522,24 @@ wayl_destroy(struct wayland *wayl)
|
|||
free(wayl);
|
||||
}
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
static void fractional_scale_preferred_scale(
|
||||
void *data, struct wp_fractional_scale_v1 *wp_fractional_scale_v1,
|
||||
uint32_t scale)
|
||||
{
|
||||
struct wl_window *win = data;
|
||||
win->scale = (float)scale / 120.;
|
||||
win->have_preferred_scale = true;
|
||||
|
||||
LOG_DBG("fractional scale: %.3f", win->scale);
|
||||
update_term_for_output_change(win->term);
|
||||
}
|
||||
|
||||
static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
|
||||
.preferred_scale = &fractional_scale_preferred_scale,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct wl_window *
|
||||
wayl_win_init(struct terminal *term, const char *token)
|
||||
{
|
||||
|
|
@ -1485,21 +1556,34 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
win->csd_mode = CSD_UNKNOWN;
|
||||
win->csd.move_timeout_fd = -1;
|
||||
win->resize_timeout_fd = -1;
|
||||
win->scale = -1.;
|
||||
|
||||
win->wm_capabilities.maximize = true;
|
||||
win->wm_capabilities.minimize = true;
|
||||
|
||||
win->surface = wl_compositor_create_surface(wayl->compositor);
|
||||
if (win->surface == NULL) {
|
||||
win->surface.surf = wl_compositor_create_surface(wayl->compositor);
|
||||
if (win->surface.surf == NULL) {
|
||||
LOG_ERR("failed to create wayland surface");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wayl_win_alpha_changed(win);
|
||||
|
||||
wl_surface_add_listener(win->surface, &surface_listener, win);
|
||||
wl_surface_add_listener(win->surface.surf, &surface_listener, win);
|
||||
|
||||
win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface);
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) {
|
||||
win->surface.viewport = wp_viewporter_get_viewport(wayl->viewporter, win->surface.surf);
|
||||
|
||||
win->fractional_scale =
|
||||
wp_fractional_scale_manager_v1_get_fractional_scale(
|
||||
wayl->fractional_scale_manager, win->surface.surf);
|
||||
wp_fractional_scale_v1_add_listener(
|
||||
win->fractional_scale, &fractional_scale_listener, win);
|
||||
}
|
||||
#endif
|
||||
|
||||
win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface.surf);
|
||||
xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win);
|
||||
|
||||
win->xdg_toplevel = xdg_surface_get_toplevel(win->xdg_surface);
|
||||
|
|
@ -1532,12 +1616,12 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
LOG_WARN("no decoration manager available - using CSDs unconditionally");
|
||||
}
|
||||
|
||||
wl_surface_commit(win->surface);
|
||||
wl_surface_commit(win->surface.surf);
|
||||
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
/* Complete XDG startup notification */
|
||||
if (token)
|
||||
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface);
|
||||
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf);
|
||||
#endif
|
||||
|
||||
if (!wayl_win_subsurface_new(win, &win->overlay, false)) {
|
||||
|
|
@ -1587,33 +1671,33 @@ wayl_win_destroy(struct wl_window *win)
|
|||
* nor mouse focus).
|
||||
*/
|
||||
|
||||
if (win->render_timer.surf != NULL) {
|
||||
wl_surface_attach(win->render_timer.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->render_timer.surf);
|
||||
if (win->render_timer.surface.surf != NULL) {
|
||||
wl_surface_attach(win->render_timer.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->render_timer.surface.surf);
|
||||
}
|
||||
|
||||
if (win->scrollback_indicator.surf != NULL) {
|
||||
wl_surface_attach(win->scrollback_indicator.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->scrollback_indicator.surf);
|
||||
if (win->scrollback_indicator.surface.surf != NULL) {
|
||||
wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->scrollback_indicator.surface.surf);
|
||||
}
|
||||
|
||||
/* Scrollback search */
|
||||
if (win->search.surf != NULL) {
|
||||
wl_surface_attach(win->search.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->search.surf);
|
||||
if (win->search.surface.surf != NULL) {
|
||||
wl_surface_attach(win->search.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->search.surface.surf);
|
||||
}
|
||||
|
||||
/* URLs */
|
||||
tll_foreach(win->urls, it) {
|
||||
wl_surface_attach(it->item.surf.surf, NULL, 0, 0);
|
||||
wl_surface_commit(it->item.surf.surf);
|
||||
wl_surface_attach(it->item.surf.surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(it->item.surf.surface.surf);
|
||||
}
|
||||
|
||||
/* CSD */
|
||||
for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
|
||||
if (win->csd.surface[i].surf != NULL) {
|
||||
wl_surface_attach(win->csd.surface[i].surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->csd.surface[i].surf);
|
||||
if (win->csd.surface[i].surface.surf != NULL) {
|
||||
wl_surface_attach(win->csd.surface[i].surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->csd.surface[i].surface.surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1621,8 +1705,8 @@ wayl_win_destroy(struct wl_window *win)
|
|||
|
||||
/* Main window */
|
||||
win->unmapped = true;
|
||||
wl_surface_attach(win->surface, NULL, 0, 0);
|
||||
wl_surface_commit(win->surface);
|
||||
wl_surface_attach(win->surface.surf, NULL, 0, 0);
|
||||
wl_surface_commit(win->surface.surf);
|
||||
wayl_roundtrip(win->term->wl);
|
||||
|
||||
tll_free(win->on_outputs);
|
||||
|
|
@ -1652,6 +1736,12 @@ wayl_win_destroy(struct wl_window *win)
|
|||
|
||||
tll_remove(win->xdg_tokens, it);
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (win->fractional_scale != NULL)
|
||||
wp_fractional_scale_v1_destroy(win->fractional_scale);
|
||||
if (win->surface.viewport != NULL)
|
||||
wp_viewport_destroy(win->surface.viewport);
|
||||
#endif
|
||||
if (win->frame_callback != NULL)
|
||||
wl_callback_destroy(win->frame_callback);
|
||||
|
|
@ -1661,8 +1751,8 @@ wayl_win_destroy(struct wl_window *win)
|
|||
xdg_toplevel_destroy(win->xdg_toplevel);
|
||||
if (win->xdg_surface != NULL)
|
||||
xdg_surface_destroy(win->xdg_surface);
|
||||
if (win->surface != NULL)
|
||||
wl_surface_destroy(win->surface);
|
||||
if (win->surface.surf != NULL)
|
||||
wl_surface_destroy(win->surface.surf);
|
||||
|
||||
wayl_roundtrip(win->term->wl);
|
||||
|
||||
|
|
@ -1672,7 +1762,7 @@ wayl_win_destroy(struct wl_window *win)
|
|||
}
|
||||
|
||||
bool
|
||||
wayl_reload_xcursor_theme(struct seat *seat, int new_scale)
|
||||
wayl_reload_xcursor_theme(struct seat *seat, float new_scale)
|
||||
{
|
||||
if (seat->pointer.theme != NULL && seat->pointer.scale == new_scale) {
|
||||
/* We already have a theme loaded, and the scale hasn't changed */
|
||||
|
|
@ -1705,7 +1795,7 @@ wayl_reload_xcursor_theme(struct seat *seat, int new_scale)
|
|||
|
||||
const char *xcursor_theme = getenv("XCURSOR_THEME");
|
||||
|
||||
LOG_INFO("cursor theme: %s, size: %d, scale: %d",
|
||||
LOG_INFO("cursor theme: %s, size: %d, scale: %.2f",
|
||||
xcursor_theme ? xcursor_theme : "(null)",
|
||||
xcursor_size, new_scale);
|
||||
|
||||
|
|
@ -1789,6 +1879,68 @@ wayl_roundtrip(struct wayland *wayl)
|
|||
wayl_flush(wayl);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
wayl_fractional_scaling(const struct wayland *wayl)
|
||||
{
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
return wayl->fractional_scale_manager != NULL;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
wayl_surface_scale_explicit_width_height(
|
||||
const struct wl_window *win, const struct wayl_surface *surf,
|
||||
int width, int height, float scale)
|
||||
{
|
||||
|
||||
if (wayl_fractional_scaling(win->term->wl) && win->have_preferred_scale) {
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
LOG_DBG("scaling by a factor of %.2f using fractional scaling "
|
||||
"(width=%d, height=%d) ", scale, width, height);
|
||||
|
||||
wl_surface_set_buffer_scale(surf->surf, 1);
|
||||
wp_viewport_set_destination(
|
||||
surf->viewport,
|
||||
round((float)width / scale),
|
||||
round((float)height / scale));
|
||||
#else
|
||||
BUG("wayl_fraction_scaling() returned true, "
|
||||
"but fractional scaling was not available at compile time").
|
||||
#endif
|
||||
} else {
|
||||
LOG_DBG("scaling by a factor of %.2f using legacy mode "
|
||||
"(width=%d, height=%d)", scale, width, height);
|
||||
|
||||
xassert(scale == floor(scale));
|
||||
|
||||
const int iscale = (int)scale;
|
||||
xassert(width % iscale == 0);
|
||||
xassert(height % iscale == 0);
|
||||
|
||||
wl_surface_set_buffer_scale(surf->surf, iscale);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wayl_surface_scale(const struct wl_window *win, const struct wayl_surface *surf,
|
||||
const struct buffer *buf, float scale)
|
||||
{
|
||||
wayl_surface_scale_explicit_width_height(
|
||||
win, surf, buf->width, buf->height, scale);
|
||||
}
|
||||
|
||||
void
|
||||
wayl_win_scale(struct wl_window *win, const struct buffer *buf)
|
||||
{
|
||||
const struct terminal *term = win->term;
|
||||
const float scale = term->scale;
|
||||
|
||||
wayl_surface_scale(win, &win->surface, buf, scale);
|
||||
}
|
||||
|
||||
void
|
||||
wayl_win_alpha_changed(struct wl_window *win)
|
||||
{
|
||||
|
|
@ -1800,11 +1952,11 @@ wayl_win_alpha_changed(struct wl_window *win)
|
|||
|
||||
if (region != NULL) {
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_set_opaque_region(win->surface, region);
|
||||
wl_surface_set_opaque_region(win->surface.surf, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
} else
|
||||
wl_surface_set_opaque_region(win->surface, NULL);
|
||||
wl_surface_set_opaque_region(win->surface.surf, NULL);
|
||||
}
|
||||
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
|
|
@ -1815,7 +1967,7 @@ activation_token_for_urgency_done(const char *token, void *data)
|
|||
struct wayland *wayl = win->term->wl;
|
||||
|
||||
win->urgency_token_is_pending = false;
|
||||
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface);
|
||||
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf);
|
||||
}
|
||||
#endif /* HAVE_XDG_ACTIVATION */
|
||||
|
||||
|
|
@ -1860,27 +2012,43 @@ wayl_win_csd_borders_visible(const struct wl_window *win)
|
|||
bool
|
||||
wayl_win_subsurface_new_with_custom_parent(
|
||||
struct wl_window *win, struct wl_surface *parent,
|
||||
struct wl_surf_subsurf *surf, bool allow_pointer_input)
|
||||
struct wayl_sub_surface *surf, bool allow_pointer_input)
|
||||
{
|
||||
struct wayland *wayl = win->term->wl;
|
||||
|
||||
surf->surf = NULL;
|
||||
surf->surface.surf = NULL;
|
||||
surf->sub = NULL;
|
||||
|
||||
struct wl_surface *main_surface
|
||||
= wl_compositor_create_surface(wayl->compositor);
|
||||
|
||||
if (main_surface == NULL)
|
||||
if (main_surface == NULL) {
|
||||
LOG_ERR("failed to instantiate surface for sub-surface");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wl_subsurface *sub = wl_subcompositor_get_subsurface(
|
||||
wayl->sub_compositor, main_surface, parent);
|
||||
|
||||
if (sub == NULL) {
|
||||
LOG_ERR("failed to instantiate sub-surface");
|
||||
wl_surface_destroy(main_surface);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
struct wp_viewport *viewport = NULL;
|
||||
if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) {
|
||||
viewport = wp_viewporter_get_viewport(wayl->viewporter, main_surface);
|
||||
if (viewport == NULL) {
|
||||
LOG_ERR("failed to instantiate viewport for sub-surface");
|
||||
wl_subsurface_destroy(sub);
|
||||
wl_surface_destroy(main_surface);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wl_surface_set_user_data(main_surface, win);
|
||||
wl_subsurface_set_sync(sub);
|
||||
|
||||
|
|
@ -1892,31 +2060,42 @@ wayl_win_subsurface_new_with_custom_parent(
|
|||
wl_region_destroy(empty);
|
||||
}
|
||||
|
||||
surf->surf = main_surface;
|
||||
surf->surface.surf = main_surface;
|
||||
surf->sub = sub;
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
surf->surface.viewport = viewport;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wayl_win_subsurface_new(struct wl_window *win, struct wl_surf_subsurf *surf,
|
||||
wayl_win_subsurface_new(struct wl_window *win, struct wayl_sub_surface *surf,
|
||||
bool allow_pointer_input)
|
||||
{
|
||||
return wayl_win_subsurface_new_with_custom_parent(
|
||||
win, win->surface, surf, allow_pointer_input);
|
||||
win, win->surface.surf, surf, allow_pointer_input);
|
||||
}
|
||||
|
||||
void
|
||||
wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf)
|
||||
wayl_win_subsurface_destroy(struct wayl_sub_surface *surf)
|
||||
{
|
||||
if (surf == NULL)
|
||||
return;
|
||||
if (surf->sub != NULL)
|
||||
wl_subsurface_destroy(surf->sub);
|
||||
if (surf->surf != NULL)
|
||||
wl_surface_destroy(surf->surf);
|
||||
|
||||
surf->surf = NULL;
|
||||
surf->sub = NULL;
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
if (surf->surface.viewport != NULL) {
|
||||
wp_viewport_destroy(surf->surface.viewport);
|
||||
surf->surface.viewport = NULL;
|
||||
}
|
||||
#endif
|
||||
if (surf->sub != NULL) {
|
||||
wl_subsurface_destroy(surf->sub);
|
||||
surf->sub = NULL;
|
||||
}
|
||||
if (surf->surface.surf != NULL) {
|
||||
wl_surface_destroy(surf->surface.surf);
|
||||
surf->surface.surf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
|
|
@ -1981,7 +2160,7 @@ wayl_get_activation_token(
|
|||
if (seat != NULL && serial != 0)
|
||||
xdg_activation_token_v1_set_serial(token, serial, seat->wl_seat);
|
||||
|
||||
xdg_activation_token_v1_set_surface(token, win->surface);
|
||||
xdg_activation_token_v1_set_surface(token, win->surface.surf);
|
||||
xdg_activation_token_v1_add_listener(token, &activation_token_listener, ctx);
|
||||
xdg_activation_token_v1_commit(token);
|
||||
return true;
|
||||
|
|
|
|||
69
wayland.h
69
wayland.h
|
|
@ -20,6 +20,11 @@
|
|||
#include <xdg-activation-v1.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
#include <viewporter.h>
|
||||
#include <fractional-scale-v1.h>
|
||||
#endif
|
||||
|
||||
#include <fcft/fcft.h>
|
||||
#include <tllist.h>
|
||||
|
||||
|
|
@ -27,6 +32,7 @@
|
|||
|
||||
/* Forward declarations */
|
||||
struct terminal;
|
||||
struct buffer;
|
||||
|
||||
/* Mime-types we support when dealing with data offers (e.g. copy-paste, or DnD) */
|
||||
enum data_offer_mime_type {
|
||||
|
|
@ -40,6 +46,18 @@ enum data_offer_mime_type {
|
|||
DATA_OFFER_MIME_TEXT_UTF8_STRING,
|
||||
};
|
||||
|
||||
struct wayl_surface {
|
||||
struct wl_surface *surf;
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
struct wp_viewport *viewport;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct wayl_sub_surface {
|
||||
struct wayl_surface surface;
|
||||
struct wl_subsurface *sub;
|
||||
};
|
||||
|
||||
struct wl_window;
|
||||
struct wl_clipboard {
|
||||
struct wl_window *window; /* For DnD */
|
||||
|
|
@ -127,10 +145,10 @@ struct seat {
|
|||
struct {
|
||||
uint32_t serial;
|
||||
|
||||
struct wl_surface *surface;
|
||||
struct wayl_surface surface;
|
||||
struct wl_cursor_theme *theme;
|
||||
struct wl_cursor *cursor;
|
||||
int scale;
|
||||
float scale;
|
||||
bool hidden;
|
||||
|
||||
const char *xcursor;
|
||||
|
|
@ -289,14 +307,9 @@ struct monitor {
|
|||
bool use_output_release;
|
||||
};
|
||||
|
||||
struct wl_surf_subsurf {
|
||||
struct wl_surface *surf;
|
||||
struct wl_subsurface *sub;
|
||||
};
|
||||
|
||||
struct wl_url {
|
||||
const struct url *url;
|
||||
struct wl_surf_subsurf surf;
|
||||
struct wayl_sub_surface surf;
|
||||
};
|
||||
|
||||
enum csd_mode {CSD_UNKNOWN, CSD_NO, CSD_YES};
|
||||
|
|
@ -320,21 +333,27 @@ struct xdg_activation_token_context {
|
|||
struct wayland;
|
||||
struct wl_window {
|
||||
struct terminal *term;
|
||||
struct wl_surface *surface;
|
||||
struct wayl_surface surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
tll(struct xdg_activation_token_context *) xdg_tokens;
|
||||
bool urgency_token_is_pending;
|
||||
#endif
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
struct wp_fractional_scale_v1 *fractional_scale;
|
||||
#endif
|
||||
bool unmapped;
|
||||
|
||||
float scale;
|
||||
bool have_preferred_scale;
|
||||
|
||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
||||
|
||||
enum csd_mode csd_mode;
|
||||
|
||||
struct {
|
||||
struct wl_surf_subsurf surface[CSD_SURF_COUNT];
|
||||
struct wayl_sub_surface surface[CSD_SURF_COUNT];
|
||||
struct fcft_font *font;
|
||||
int move_timeout_fd;
|
||||
uint32_t serial;
|
||||
|
|
@ -345,10 +364,10 @@ struct wl_window {
|
|||
bool minimize:1;
|
||||
} wm_capabilities;
|
||||
|
||||
struct wl_surf_subsurf search;
|
||||
struct wl_surf_subsurf scrollback_indicator;
|
||||
struct wl_surf_subsurf render_timer;
|
||||
struct wl_surf_subsurf overlay;
|
||||
struct wayl_sub_surface search;
|
||||
struct wayl_sub_surface scrollback_indicator;
|
||||
struct wayl_sub_surface render_timer;
|
||||
struct wayl_sub_surface overlay;
|
||||
|
||||
struct wl_callback *frame_callback;
|
||||
|
||||
|
|
@ -414,6 +433,11 @@ struct wayland {
|
|||
struct zwp_text_input_manager_v3 *text_input_manager;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FRACTIONAL_SCALE)
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
|
||||
#endif
|
||||
|
||||
bool have_argb8888;
|
||||
tll(struct monitor) monitors; /* All available outputs */
|
||||
tll(struct seat) seats;
|
||||
|
|
@ -426,14 +450,23 @@ struct wayland *wayl_init(
|
|||
bool presentation_timings);
|
||||
void wayl_destroy(struct wayland *wayl);
|
||||
|
||||
bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale);
|
||||
bool wayl_reload_xcursor_theme(struct seat *seat, float new_scale);
|
||||
|
||||
void wayl_flush(struct wayland *wayl);
|
||||
void wayl_roundtrip(struct wayland *wayl);
|
||||
|
||||
bool wayl_fractional_scaling(const struct wayland *wayl);
|
||||
void wayl_surface_scale(
|
||||
const struct wl_window *win, const struct wayl_surface *surf,
|
||||
const struct buffer *buf, float scale);
|
||||
void wayl_surface_scale_explicit_width_height(
|
||||
const struct wl_window *win, const struct wayl_surface *surf,
|
||||
int width, int height, float scale);
|
||||
|
||||
struct wl_window *wayl_win_init(struct terminal *term, const char *token);
|
||||
void wayl_win_destroy(struct wl_window *win);
|
||||
|
||||
void wayl_win_scale(struct wl_window *win, const struct buffer *buf);
|
||||
void wayl_win_alpha_changed(struct wl_window *win);
|
||||
bool wayl_win_set_urgent(struct wl_window *win);
|
||||
|
||||
|
|
@ -441,12 +474,12 @@ bool wayl_win_csd_titlebar_visible(const struct wl_window *win);
|
|||
bool wayl_win_csd_borders_visible(const struct wl_window *win);
|
||||
|
||||
bool wayl_win_subsurface_new(
|
||||
struct wl_window *win, struct wl_surf_subsurf *surf,
|
||||
struct wl_window *win, struct wayl_sub_surface *surf,
|
||||
bool allow_pointer_input);
|
||||
bool wayl_win_subsurface_new_with_custom_parent(
|
||||
struct wl_window *win, struct wl_surface *parent,
|
||||
struct wl_surf_subsurf *surf, bool allow_pointer_input);
|
||||
void wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf);
|
||||
struct wayl_sub_surface *surf, bool allow_pointer_input);
|
||||
void wayl_win_subsurface_destroy(struct wayl_sub_surface *surf);
|
||||
|
||||
#if defined(HAVE_XDG_ACTIVATION)
|
||||
bool wayl_get_activation_token(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue