mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-28 06:46:38 -04:00
HACK fractional scaling
This commit is contained in:
parent
68db8ff1f5
commit
4564d78eff
8 changed files with 268 additions and 70 deletions
10
csi.c
10
csi.c
|
|
@ -1208,7 +1208,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
if (width >= 0 && height >= 0) {
|
if (width >= 0 && height >= 0) {
|
||||||
char reply[64];
|
char reply[64];
|
||||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[4;%d;%dt",
|
size_t n = xsnprintf(reply, sizeof(reply), "\033[4;%d;%dt",
|
||||||
height / term->scale, width / term->scale);
|
(int)round(height / term->scale), (int)round(width / term->scale));
|
||||||
term_to_slave(term, reply, n);
|
term_to_slave(term, reply, n);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1231,8 +1231,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
case 16: { /* report cell size in pixels */
|
case 16: { /* report cell size in pixels */
|
||||||
char reply[64];
|
char reply[64];
|
||||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[6;%d;%dt",
|
size_t n = xsnprintf(reply, sizeof(reply), "\033[6;%d;%dt",
|
||||||
term->cell_height / term->scale,
|
(int)round(term->cell_height / term->scale),
|
||||||
term->cell_width / term->scale);
|
(int)round(term->cell_width / term->scale));
|
||||||
term_to_slave(term, reply, n);
|
term_to_slave(term, reply, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1249,8 +1249,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
tll_foreach(term->window->on_outputs, it) {
|
tll_foreach(term->window->on_outputs, it) {
|
||||||
char reply[64];
|
char reply[64];
|
||||||
size_t n = xsnprintf(reply, sizeof(reply), "\033[9;%d;%dt",
|
size_t n = xsnprintf(reply, sizeof(reply), "\033[9;%d;%dt",
|
||||||
it->item->dim.px_real.height / term->cell_height / term->scale,
|
(int)round(it->item->dim.px_real.height / term->cell_height / term->scale),
|
||||||
it->item->dim.px_real.width / term->cell_width / term->scale);
|
(int)round(it->item->dim.px_real.width / term->cell_width / term->scale));
|
||||||
term_to_slave(term, reply, n);
|
term_to_slave(term, reply, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
113
fractional-scale-v1.xml
Normal file
113
fractional-scale-v1.xml
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="fractional_scale_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2022 Kenny Levinsen
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="Protocol for requesting fractional surface scales">
|
||||||
|
This protocol allows a compositor to suggest for surfaces to render at
|
||||||
|
fractional scales.
|
||||||
|
|
||||||
|
A client can submit scaled content by utilizing wp_viewport. This is done by
|
||||||
|
creating a wp_viewport object for the surface and setting the destination
|
||||||
|
rectangle set to the surface size before the scale factor is applied.
|
||||||
|
|
||||||
|
If the surface is not a subsurface, then the buffer size is calculated by
|
||||||
|
multiplying the surface size by the intended scale, rounding the result
|
||||||
|
halfway away from zero.
|
||||||
|
|
||||||
|
If the surface is a subsurface, then the calculation must account for the
|
||||||
|
surface position when rounding the buffer size. First, add the subsurface
|
||||||
|
position relative to its parent to the surface size, multiplying them by the
|
||||||
|
intended scale and rounding the result halfway away from zero. Second, take
|
||||||
|
the subsurface position relative to its parent, multiplying it by the
|
||||||
|
intended scale and rounding the result halfway away from zero. Finally,
|
||||||
|
subtract the result of the second calculation from the first calculation to
|
||||||
|
get the buffer size.
|
||||||
|
|
||||||
|
The wl_surface buffer scale should remain set to 1 in both cases.
|
||||||
|
|
||||||
|
In the compositor, final subsurface positions are calculated by multiplying
|
||||||
|
the position of the subsurface relative to its parent by the intended scale,
|
||||||
|
and rounding the result halfway away from zero. The positions of the parent
|
||||||
|
surfaces, calculated using the same mechanism, are then recursively added to
|
||||||
|
the result. This ensures that position and size rounding is not affected by
|
||||||
|
the movement of parent surfaces.
|
||||||
|
|
||||||
|
If a surface has a surface-local size of 100 px by 50 px and wishes to
|
||||||
|
submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should
|
||||||
|
be used and the wp_viewport destination rectangle should be 100 px by 50 px.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="wp_fractional_scale_manager_v1" version="1">
|
||||||
|
<description summary="fractional surface scale information">
|
||||||
|
A global interface for requesting surfaces to use fractional scales.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="unbind the surface scale interface">
|
||||||
|
Informs the server that the client will not be using this protocol
|
||||||
|
object anymore. This does not affect any other objects,
|
||||||
|
wp_fractional_scale_v1 objects included.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="fractional_scale_exists" value="0"
|
||||||
|
summary="the surface already has a fractional_scale object associated"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="get_fractional_scale">
|
||||||
|
<description summary="extend surface interface for scale information">
|
||||||
|
Create an add-on object for the the wl_surface to let the compositor
|
||||||
|
request fractional scales. If the given wl_surface already has a
|
||||||
|
wp_fractional_scale_v1 object associated, the fractional_scale_exists
|
||||||
|
protocol error is raised.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="wp_fractional_scale_v1"
|
||||||
|
summary="the new surface scale info interface id"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"
|
||||||
|
summary="the surface"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="wp_fractional_scale_v1" version="1">
|
||||||
|
<description summary="fractional scale interface to a wl_surface">
|
||||||
|
An additional interface to a wl_surface object which allows the compositor
|
||||||
|
to inform the client of the preferred scale.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="remove surface scale information for surface">
|
||||||
|
The associated wl_surface's fractional scale object is destroyed.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="preferred_scale">
|
||||||
|
<description summary="notify of new preferred scale">
|
||||||
|
Notification of a new preferred scale for this surface that the
|
||||||
|
compositor suggests that the client should use.
|
||||||
|
</description>
|
||||||
|
<arg name="scale" type="fixed" summary="the new preferred scale"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
||||||
|
|
@ -107,6 +107,8 @@ wl_proto_xml = [
|
||||||
wayland_protocols_datadir + '/unstable/primary-selection/primary-selection-unstable-v1.xml',
|
wayland_protocols_datadir + '/unstable/primary-selection/primary-selection-unstable-v1.xml',
|
||||||
wayland_protocols_datadir + '/stable/presentation-time/presentation-time.xml',
|
wayland_protocols_datadir + '/stable/presentation-time/presentation-time.xml',
|
||||||
wayland_protocols_datadir + '/unstable/text-input/text-input-unstable-v3.xml',
|
wayland_protocols_datadir + '/unstable/text-input/text-input-unstable-v3.xml',
|
||||||
|
wayland_protocols_datadir + '/stable/viewporter/viewporter.xml',
|
||||||
|
'fractional-scale-v1.xml',
|
||||||
]
|
]
|
||||||
|
|
||||||
if wayland_protocols.version().version_compare('>=1.21')
|
if wayland_protocols.version().version_compare('>=1.21')
|
||||||
|
|
|
||||||
124
render.c
124
render.c
|
|
@ -1753,15 +1753,15 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
csd_commit(struct terminal *term, struct wl_surface *surf, struct buffer *buf)
|
csd_commit(struct terminal *term, struct wl_surf_subsurf *surf, struct buffer *buf)
|
||||||
{
|
{
|
||||||
xassert(buf->width % term->scale == 0);
|
// xassert(buf->width % term->scale == 0);
|
||||||
xassert(buf->height % term->scale == 0);
|
// xassert(buf->height % term->scale == 0);
|
||||||
|
|
||||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
wl_surface_attach(surf->surf, buf->wl_buf, 0, 0);
|
||||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
wl_surface_damage_buffer(surf->surf, 0, 0, buf->width, buf->height);
|
||||||
wl_surface_set_buffer_scale(surf, term->scale);
|
// wl_surface_set_buffer_scale(surf, term->scale);
|
||||||
wl_surface_commit(surf);
|
wl_surface_commit(surf->surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1851,13 +1851,14 @@ render_osd(struct terminal *term,
|
||||||
pixman_image_unref(src);
|
pixman_image_unref(src);
|
||||||
pixman_image_set_clip_region32(buf->pix[0], NULL);
|
pixman_image_set_clip_region32(buf->pix[0], NULL);
|
||||||
|
|
||||||
xassert(buf->width % term->scale == 0);
|
// xassert(buf->width % term->scale == 0);
|
||||||
xassert(buf->height % term->scale == 0);
|
// xassert(buf->height % term->scale == 0);
|
||||||
|
|
||||||
quirk_weston_subsurface_desync_on(sub_surf);
|
quirk_weston_subsurface_desync_on(sub_surf);
|
||||||
|
|
||||||
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
wl_surface_attach(surf, buf->wl_buf, 0, 0);
|
||||||
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height);
|
||||||
wl_surface_set_buffer_scale(surf, term->scale);
|
// wl_surface_set_buffer_scale(surf, term->scale);
|
||||||
|
|
||||||
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
struct wl_region *region = wl_compositor_create_region(term->wl->compositor);
|
||||||
if (region != NULL) {
|
if (region != NULL) {
|
||||||
|
|
@ -1880,8 +1881,8 @@ render_csd_title(struct terminal *term, const struct csd_data *info,
|
||||||
if (info->width == 0 || info->height == 0)
|
if (info->width == 0 || info->height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xassert(info->width % term->scale == 0);
|
// xassert(info->width % term->scale == 0);
|
||||||
xassert(info->height % term->scale == 0);
|
// xassert(info->height % term->scale == 0);
|
||||||
|
|
||||||
uint32_t bg = term->conf->csd.color.title_set
|
uint32_t bg = term->conf->csd.color.title_set
|
||||||
? term->conf->csd.color.title
|
? term->conf->csd.color.title
|
||||||
|
|
@ -1909,7 +1910,7 @@ render_csd_title(struct terminal *term, const struct csd_data *info,
|
||||||
buf, title_text, fg, bg, margin,
|
buf, title_text, fg, bg, margin,
|
||||||
(buf->height - win->csd.font->height) / 2);
|
(buf->height - win->csd.font->height) / 2);
|
||||||
|
|
||||||
csd_commit(term, surf->surf, buf);
|
csd_commit(term, surf, buf);
|
||||||
free(_title_text);
|
free(_title_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1920,13 +1921,15 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
|
||||||
xassert(term->window->csd_mode == CSD_YES);
|
xassert(term->window->csd_mode == CSD_YES);
|
||||||
xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM);
|
xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM);
|
||||||
|
|
||||||
struct wl_surface *surf = term->window->csd.surface[surf_idx].surf;
|
struct wl_surf_subsurf *ssurf
|
||||||
|
= &term->window->csd.surface[surf_idx];
|
||||||
|
struct wl_surface *surf = ssurf->surf;
|
||||||
|
|
||||||
if (info->width == 0 || info->height == 0)
|
if (info->width == 0 || info->height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xassert(info->width % term->scale == 0);
|
// xassert(info->width % term->scale == 0);
|
||||||
xassert(info->height % term->scale == 0);
|
// xassert(info->height % term->scale == 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0);
|
pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0);
|
||||||
|
|
@ -1998,7 +2001,7 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
|
||||||
&(pixman_rectangle16_t){x, y, w, h});
|
&(pixman_rectangle16_t){x, y, w, h});
|
||||||
}
|
}
|
||||||
|
|
||||||
csd_commit(term, surf, buf);
|
csd_commit(term, ssurf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static pixman_color_t
|
static pixman_color_t
|
||||||
|
|
@ -2174,13 +2177,15 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
|
||||||
xassert(term->window->csd_mode == CSD_YES);
|
xassert(term->window->csd_mode == CSD_YES);
|
||||||
xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE);
|
xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE);
|
||||||
|
|
||||||
struct wl_surface *surf = term->window->csd.surface[surf_idx].surf;
|
struct wl_surf_subsurf *ssurf =
|
||||||
|
&term->window->csd.surface[surf_idx];
|
||||||
|
struct wl_surface *surf = ssurf->surf;
|
||||||
|
|
||||||
if (info->width == 0 || info->height == 0)
|
if (info->width == 0 || info->height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xassert(info->width % term->scale == 0);
|
// xassert(info->width % term->scale == 0);
|
||||||
xassert(info->height % term->scale == 0);
|
// xassert(info->height % term->scale == 0);
|
||||||
|
|
||||||
uint32_t _color;
|
uint32_t _color;
|
||||||
uint16_t alpha = 0xffff;
|
uint16_t alpha = 0xffff;
|
||||||
|
|
@ -2242,7 +2247,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
csd_commit(term, surf, buf);
|
csd_commit(term, ssurf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2264,24 +2269,30 @@ render_csd(struct terminal *term)
|
||||||
const int width = infos[i].width;
|
const int width = infos[i].width;
|
||||||
const int height = infos[i].height;
|
const int height = infos[i].height;
|
||||||
|
|
||||||
struct wl_surface *surf = term->window->csd.surface[i].surf;
|
struct wl_surf_subsurf *surf = &term->window->csd.surface[i];
|
||||||
struct wl_subsurface *sub = term->window->csd.surface[i].sub;
|
struct wl_surface *wl_surf = surf->surf;
|
||||||
|
struct wl_subsurface *wl_sub = surf->sub;
|
||||||
|
|
||||||
xassert(surf != NULL);
|
xassert(wl_surf != NULL);
|
||||||
xassert(sub != NULL);
|
xassert(wl_sub != NULL);
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
widths[i] = heights[i] = 0;
|
widths[i] = heights[i] = 0;
|
||||||
wl_subsurface_set_position(sub, 0, 0);
|
wp_viewport_set_destination(surf->viewport, -1, -1);
|
||||||
wl_surface_attach(surf, NULL, 0, 0);
|
wl_subsurface_set_position(wl_sub, 0, 0);
|
||||||
wl_surface_commit(surf);
|
wl_surface_attach(wl_surf, NULL, 0, 0);
|
||||||
|
wl_surface_commit(wl_surf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
widths[i] = width;
|
widths[i] = round(x + width) - round(x);
|
||||||
heights[i] = height;
|
heights[i] = round(y + height) - round(y);
|
||||||
|
|
||||||
wl_subsurface_set_position(sub, x / term->scale, y / term->scale);
|
wp_viewport_set_destination(surf->viewport,
|
||||||
|
round(width / term->scale),
|
||||||
|
round(height / term->scale));
|
||||||
|
|
||||||
|
wl_subsurface_set_position(wl_sub, x / term->scale, y / term->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer *bufs[CSD_SURF_COUNT];
|
struct buffer *bufs[CSD_SURF_COUNT];
|
||||||
|
|
@ -2377,13 +2388,13 @@ render_scrollback_position(struct terminal *term)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int scale = term->scale;
|
const double scale = term->scale;
|
||||||
const int margin = 3 * scale;
|
const double margin = 3 * scale;
|
||||||
|
|
||||||
const int width =
|
const int width =
|
||||||
(2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale;
|
round(2.0 * margin + cell_count * term->cell_width);
|
||||||
const int height =
|
const int height =
|
||||||
(2 * margin + term->cell_height + scale - 1) / scale * scale;
|
round(2.0 * margin + term->cell_height);
|
||||||
|
|
||||||
/* *Where* to render - parent relative coordinates */
|
/* *Where* to render - parent relative coordinates */
|
||||||
int surf_top = 0;
|
int surf_top = 0;
|
||||||
|
|
@ -2920,7 +2931,7 @@ grid_render(struct terminal *term)
|
||||||
term->window->frame_callback = wl_surface_frame(term->window->surface);
|
term->window->frame_callback = wl_surface_frame(term->window->surface);
|
||||||
wl_callback_add_listener(term->window->frame_callback, &frame_listener, term);
|
wl_callback_add_listener(term->window->frame_callback, &frame_listener, term);
|
||||||
|
|
||||||
wl_surface_set_buffer_scale(term->window->surface, term->scale);
|
// wl_surface_set_buffer_scale(term->window->surface, term->scale);
|
||||||
|
|
||||||
if (term->wl->presentation != NULL && term->conf->presentation_timings) {
|
if (term->wl->presentation != NULL && term->conf->presentation_timings) {
|
||||||
struct timespec commit_time;
|
struct timespec commit_time;
|
||||||
|
|
@ -2954,8 +2965,11 @@ grid_render(struct terminal *term)
|
||||||
term->window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
term->window->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
xassert(buf->width % term->scale == 0);
|
// xassert(buf->width % term->scale == 0);
|
||||||
xassert(buf->height % term->scale == 0);
|
// xassert(buf->height % term->scale == 0);
|
||||||
|
wp_viewport_set_destination(term->window->viewport,
|
||||||
|
round(buf->width / term->scale),
|
||||||
|
round(buf->height / term->scale));
|
||||||
|
|
||||||
wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0);
|
wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0);
|
||||||
wl_surface_commit(term->window->surface);
|
wl_surface_commit(term->window->surface);
|
||||||
|
|
@ -3019,11 +3033,13 @@ render_search_box(struct terminal *term)
|
||||||
const size_t total_cells = c32swidth(text, text_len);
|
const size_t total_cells = c32swidth(text, text_len);
|
||||||
const size_t wanted_visible_cells = max(20, total_cells);
|
const size_t wanted_visible_cells = max(20, total_cells);
|
||||||
|
|
||||||
xassert(term->scale >= 1);
|
// xassert(term->scale >= 1);
|
||||||
const int scale = term->scale;
|
const int scale = term->scale;
|
||||||
|
|
||||||
const size_t margin = 3 * scale;
|
const size_t margin = 3 * scale;
|
||||||
|
|
||||||
|
// These calculations do not round correctly right now
|
||||||
|
|
||||||
const size_t width = term->width - 2 * margin;
|
const size_t width = term->width - 2 * margin;
|
||||||
const size_t visible_width = min(
|
const size_t visible_width = min(
|
||||||
term->width - 2 * margin,
|
term->width - 2 * margin,
|
||||||
|
|
@ -3265,8 +3281,11 @@ render_search_box(struct terminal *term)
|
||||||
margin / scale,
|
margin / scale,
|
||||||
max(0, (int32_t)term->height - height - margin) / scale);
|
max(0, (int32_t)term->height - height - margin) / scale);
|
||||||
|
|
||||||
xassert(buf->width % scale == 0);
|
// xassert(buf->width % scale == 0);
|
||||||
xassert(buf->height % scale == 0);
|
// xassert(buf->height % scale == 0);
|
||||||
|
wp_viewport_set_destination(term->window->search.viewport,
|
||||||
|
round(buf->width / term->scale),
|
||||||
|
round(buf->height / term->scale));
|
||||||
|
|
||||||
wl_surface_attach(term->window->search.surf, buf->wl_buf, 0, 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_damage_buffer(term->window->search.surf, 0, 0, width, height);
|
||||||
|
|
@ -3681,17 +3700,20 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
||||||
if (term->cell_width == 0 && term->cell_height == 0)
|
if (term->cell_width == 0 && term->cell_height == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int scale = -1;
|
double scale = -1;
|
||||||
|
if (!term->window->fractional_scale) {
|
||||||
tll_foreach(term->window->on_outputs, it) {
|
tll_foreach(term->window->on_outputs, it) {
|
||||||
if (it->item->scale > scale)
|
if (it->item->scale > scale)
|
||||||
scale = it->item->scale;
|
scale = it->item->scale;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
scale = term->window->scale;
|
||||||
|
}
|
||||||
|
|
||||||
if (scale < 0) {
|
if (scale < 0) {
|
||||||
/* Haven't 'entered' an output yet? */
|
/* Haven't 'entered' an output yet? */
|
||||||
scale = term->scale;
|
scale = term->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
width *= scale;
|
width *= scale;
|
||||||
height *= scale;
|
height *= scale;
|
||||||
|
|
||||||
|
|
@ -3735,13 +3757,13 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
||||||
* Ensure we can scale to logical size, and back to
|
* Ensure we can scale to logical size, and back to
|
||||||
* pixels without truncating.
|
* pixels without truncating.
|
||||||
*/
|
*/
|
||||||
if (width % scale)
|
// if (width % scale)
|
||||||
width += scale - width % scale;
|
// width += scale - width % scale;
|
||||||
if (height % scale)
|
// if (height % scale)
|
||||||
height += scale - height % scale;
|
// height += scale - height % scale;
|
||||||
|
|
||||||
xassert(width % scale == 0);
|
// xassert(width % scale == 0);
|
||||||
xassert(height % scale == 0);
|
// xassert(height % scale == 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3911,8 +3933,8 @@ damage_view:
|
||||||
term->window->xdg_surface,
|
term->window->xdg_surface,
|
||||||
-border_width,
|
-border_width,
|
||||||
-title_height - border_width,
|
-title_height - border_width,
|
||||||
term->width / term->scale + 2 * border_width,
|
round(term->width / term->scale + 2 * border_width),
|
||||||
term->height / term->scale + title_height + 2 * border_width);
|
round(term->height / term->scale + title_height + 2 * border_width));
|
||||||
}
|
}
|
||||||
|
|
||||||
tll_free(term->normal.scroll_damage);
|
tll_free(term->normal.scroll_damage);
|
||||||
|
|
|
||||||
|
|
@ -902,11 +902,10 @@ reload_fonts(struct terminal *term)
|
||||||
bool use_px_size = term->font_sizes[i][j].px_size > 0;
|
bool use_px_size = term->font_sizes[i][j].px_size > 0;
|
||||||
char size[64];
|
char size[64];
|
||||||
|
|
||||||
const int scale = term->font_is_sized_by_dpi ? 1 : term->scale;
|
const double scale = term->font_is_sized_by_dpi ? 1 : term->scale;
|
||||||
|
|
||||||
if (use_px_size)
|
if (use_px_size)
|
||||||
snprintf(size, sizeof(size), ":pixelsize=%d",
|
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
|
else
|
||||||
snprintf(size, sizeof(size), ":size=%.2f",
|
snprintf(size, sizeof(size), ":size=%.2f",
|
||||||
term->font_sizes[i][j].pt_size * (double)scale);
|
term->font_sizes[i][j].pt_size * (double)scale);
|
||||||
|
|
|
||||||
|
|
@ -445,7 +445,7 @@ struct terminal {
|
||||||
int fd;
|
int fd;
|
||||||
} blink;
|
} blink;
|
||||||
|
|
||||||
int scale;
|
double scale;
|
||||||
int width; /* pixels */
|
int width; /* pixels */
|
||||||
int height; /* pixels */
|
int height; /* pixels */
|
||||||
int stashed_width;
|
int stashed_width;
|
||||||
|
|
|
||||||
64
wayland.c
64
wayland.c
|
|
@ -31,12 +31,12 @@
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
csd_reload_font(struct wl_window *win, int old_scale)
|
csd_reload_font(struct wl_window *win, double old_scale)
|
||||||
{
|
{
|
||||||
struct terminal *term = win->term;
|
struct terminal *term = win->term;
|
||||||
const struct config *conf = term->conf;
|
const struct config *conf = term->conf;
|
||||||
|
|
||||||
const int scale = term->scale;
|
const double scale = term->scale;
|
||||||
|
|
||||||
bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen;
|
bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen;
|
||||||
if (!enable_csd)
|
if (!enable_csd)
|
||||||
|
|
@ -52,9 +52,9 @@ csd_reload_font(struct wl_window *win, int old_scale)
|
||||||
|
|
||||||
char pixelsize[32];
|
char pixelsize[32];
|
||||||
snprintf(pixelsize, sizeof(pixelsize),
|
snprintf(pixelsize, sizeof(pixelsize),
|
||||||
"pixelsize=%u", conf->csd.title_height * scale * 1 / 2);
|
"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=%lf, scale=%lf)",
|
||||||
patterns[0], pixelsize, old_scale, scale);
|
patterns[0], pixelsize, old_scale, scale);
|
||||||
|
|
||||||
win->csd.font = fcft_from_name(conf->csd.font.count, patterns, pixelsize);
|
win->csd.font = fcft_from_name(conf->csd.font.count, patterns, pixelsize);
|
||||||
|
|
@ -317,9 +317,9 @@ update_term_for_output_change(struct terminal *term)
|
||||||
if (tll_length(term->window->on_outputs) == 0)
|
if (tll_length(term->window->on_outputs) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int old_scale = term->scale;
|
double old_scale = term->scale;
|
||||||
|
|
||||||
render_resize(term, term->width / term->scale, term->height / term->scale);
|
render_resize(term, round(term->width / term->scale), round(term->height / term->scale));
|
||||||
term_font_dpi_changed(term, old_scale);
|
term_font_dpi_changed(term, old_scale);
|
||||||
term_font_subpixel_changed(term);
|
term_font_subpixel_changed(term);
|
||||||
csd_reload_font(term->window, old_scale);
|
csd_reload_font(term->window, old_scale);
|
||||||
|
|
@ -812,6 +812,21 @@ static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration
|
||||||
.configure = &xdg_toplevel_decoration_configure,
|
.configure = &xdg_toplevel_decoration_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void fractional_scale_handle_preferred_scale(void *data, struct
|
||||||
|
wp_fractional_scale_v1 *info, wl_fixed_t scale) {
|
||||||
|
struct wl_window *win = data;
|
||||||
|
|
||||||
|
double dscale = wl_fixed_to_double(scale);
|
||||||
|
fprintf(stderr, "Preferred scale: %lf\n", dscale);
|
||||||
|
|
||||||
|
win->scale = dscale;
|
||||||
|
update_term_for_output_change(win->term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
|
||||||
|
.preferred_scale = fractional_scale_handle_preferred_scale,
|
||||||
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
fdm_repeat(struct fdm *fdm, int fd, int events, void *data)
|
fdm_repeat(struct fdm *fdm, int fd, int events, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -1049,6 +1064,27 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
seat_add_text_input(&it->item);
|
seat_add_text_input(&it->item);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1420,6 +1456,16 @@ wayl_win_init(struct terminal *term, const char *token)
|
||||||
|
|
||||||
wl_surface_add_listener(win->surface, &surface_listener, win);
|
wl_surface_add_listener(win->surface, &surface_listener, win);
|
||||||
|
|
||||||
|
if (wayl->fractional_scale_manager) {
|
||||||
|
win->fractional_scale =
|
||||||
|
wp_fractional_scale_manager_v1_get_fractional_scale(wayl->fractional_scale_manager,
|
||||||
|
win->surface);
|
||||||
|
wp_fractional_scale_v1_add_listener(win->fractional_scale,
|
||||||
|
&fractional_scale_listener, win);
|
||||||
|
}
|
||||||
|
win->viewport = wp_viewporter_get_viewport(wayl->viewporter,
|
||||||
|
win->surface);
|
||||||
|
|
||||||
win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface);
|
win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface);
|
||||||
xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win);
|
xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win);
|
||||||
|
|
||||||
|
|
@ -1540,6 +1586,9 @@ wayl_win_destroy(struct wl_window *win)
|
||||||
|
|
||||||
wayl_roundtrip(win->term->wl);
|
wayl_roundtrip(win->term->wl);
|
||||||
|
|
||||||
|
wp_viewport_set_destination(win->viewport,
|
||||||
|
win->configure.width, win->configure.height);
|
||||||
|
|
||||||
/* Main window */
|
/* Main window */
|
||||||
wl_surface_attach(win->surface, NULL, 0, 0);
|
wl_surface_attach(win->surface, NULL, 0, 0);
|
||||||
wl_surface_commit(win->surface);
|
wl_surface_commit(win->surface);
|
||||||
|
|
@ -1809,6 +1858,9 @@ wayl_win_subsurface_new_with_custom_parent(
|
||||||
|
|
||||||
surf->surf = main_surface;
|
surf->surf = main_surface;
|
||||||
surf->sub = sub;
|
surf->sub = sub;
|
||||||
|
surf->viewport = wp_viewporter_get_viewport(wayl->viewporter,
|
||||||
|
main_surface);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
wayland.h
12
wayland.h
|
|
@ -15,6 +15,8 @@
|
||||||
#include <xdg-decoration-unstable-v1.h>
|
#include <xdg-decoration-unstable-v1.h>
|
||||||
#include <xdg-output-unstable-v1.h>
|
#include <xdg-output-unstable-v1.h>
|
||||||
#include <xdg-shell.h>
|
#include <xdg-shell.h>
|
||||||
|
#include <viewporter.h>
|
||||||
|
#include <fractional-scale-v1.h>
|
||||||
|
|
||||||
#if defined(HAVE_XDG_ACTIVATION)
|
#if defined(HAVE_XDG_ACTIVATION)
|
||||||
#include <xdg-activation-v1.h>
|
#include <xdg-activation-v1.h>
|
||||||
|
|
@ -131,7 +133,7 @@ struct seat {
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wl_cursor_theme *theme;
|
struct wl_cursor_theme *theme;
|
||||||
struct wl_cursor *cursor;
|
struct wl_cursor *cursor;
|
||||||
int scale;
|
double scale;
|
||||||
bool hidden;
|
bool hidden;
|
||||||
|
|
||||||
const char *xcursor;
|
const char *xcursor;
|
||||||
|
|
@ -288,6 +290,7 @@ struct monitor {
|
||||||
struct wl_surf_subsurf {
|
struct wl_surf_subsurf {
|
||||||
struct wl_surface *surf;
|
struct wl_surface *surf;
|
||||||
struct wl_subsurface *sub;
|
struct wl_subsurface *sub;
|
||||||
|
struct wp_viewport *viewport;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wl_url {
|
struct wl_url {
|
||||||
|
|
@ -306,6 +309,8 @@ struct wl_window {
|
||||||
#if defined(HAVE_XDG_ACTIVATION)
|
#if defined(HAVE_XDG_ACTIVATION)
|
||||||
struct xdg_activation_token_v1 *xdg_activation_token;
|
struct xdg_activation_token_v1 *xdg_activation_token;
|
||||||
#endif
|
#endif
|
||||||
|
struct wp_viewport *viewport;
|
||||||
|
struct wp_fractional_scale_v1 *fractional_scale;
|
||||||
|
|
||||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration;
|
||||||
|
|
||||||
|
|
@ -352,6 +357,7 @@ struct wl_window {
|
||||||
} configure;
|
} configure;
|
||||||
|
|
||||||
int resize_timeout_fd;
|
int resize_timeout_fd;
|
||||||
|
double scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct terminal;
|
struct terminal;
|
||||||
|
|
@ -383,6 +389,10 @@ struct wayland {
|
||||||
struct wp_presentation *presentation;
|
struct wp_presentation *presentation;
|
||||||
uint32_t presentation_clock_id;
|
uint32_t presentation_clock_id;
|
||||||
|
|
||||||
|
struct wp_viewporter *viewporter;
|
||||||
|
struct wp_fractional_scale_manager_v1
|
||||||
|
*fractional_scale_manager;
|
||||||
|
|
||||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
struct zwp_text_input_manager_v3 *text_input_manager;
|
struct zwp_text_input_manager_v3 *text_input_manager;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue