mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-24 09:05:48 -04:00
output: initial support for output scaling
* Not updated run-time; only scale at start up used * Multiple monitors (outputs) not supported, as we can't track which output we're on (yet).
This commit is contained in:
parent
c6640adde3
commit
74f723e0cf
4 changed files with 156 additions and 6 deletions
132
main.c
132
main.c
|
|
@ -20,6 +20,8 @@
|
||||||
#include <xdg-shell.h>
|
#include <xdg-shell.h>
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
|
||||||
|
#include <xdg-output-unstable-v1.h>
|
||||||
|
|
||||||
#define LOG_MODULE "main"
|
#define LOG_MODULE "main"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
@ -99,6 +101,87 @@ static const struct wl_seat_listener seat_listener = {
|
||||||
.name = seat_handle_name,
|
.name = seat_handle_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
|
||||||
|
int32_t physical_width, int32_t physical_height,
|
||||||
|
int32_t subpixel, const char *make, const char *model,
|
||||||
|
int32_t transform)
|
||||||
|
{
|
||||||
|
struct monitor *mon = data;
|
||||||
|
mon->width_mm = physical_width;
|
||||||
|
mon->height_mm = physical_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
||||||
|
int32_t width, int32_t height, int32_t refresh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_done(void *data, struct wl_output *wl_output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_scale(void *data, struct wl_output *wl_output, int32_t factor)
|
||||||
|
{
|
||||||
|
struct monitor *mon = data;
|
||||||
|
mon->scale = factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_output_listener output_listener = {
|
||||||
|
.geometry = &output_geometry,
|
||||||
|
.mode = &output_mode,
|
||||||
|
.done = &output_done,
|
||||||
|
.scale = &output_scale,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_output_handle_logical_position(
|
||||||
|
void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
struct monitor *mon = data;
|
||||||
|
mon->x = x;
|
||||||
|
mon->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
|
||||||
|
int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
struct monitor *mon = data;
|
||||||
|
mon->width_px = width;
|
||||||
|
mon->height_px = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct monitor *mon = data;
|
||||||
|
mon->name = strdup(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output,
|
||||||
|
const char *description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zxdg_output_v1_listener xdg_output_listener = {
|
||||||
|
.logical_position = xdg_output_handle_logical_position,
|
||||||
|
.logical_size = xdg_output_handle_logical_size,
|
||||||
|
.done = xdg_output_handle_done,
|
||||||
|
.name = xdg_output_handle_name,
|
||||||
|
.description = xdg_output_handle_description,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_global(void *data, struct wl_registry *registry,
|
handle_global(void *data, struct wl_registry *registry,
|
||||||
uint32_t name, const char *interface, uint32_t version)
|
uint32_t name, const char *interface, uint32_t version)
|
||||||
|
|
@ -131,6 +214,27 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
wl_display_roundtrip(term->wl.display);
|
wl_display_roundtrip(term->wl.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
||||||
|
term->wl.xdg_output_manager = wl_registry_bind(
|
||||||
|
term->wl.registry, name, &zxdg_output_manager_v1_interface, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
|
struct wl_output *output = wl_registry_bind(
|
||||||
|
term->wl.registry, name, &wl_output_interface, 3);
|
||||||
|
|
||||||
|
tll_push_back(
|
||||||
|
term->wl.monitors, ((struct monitor){.output = output}));
|
||||||
|
|
||||||
|
struct monitor *mon = &tll_back(term->wl.monitors);
|
||||||
|
wl_output_add_listener(output, &output_listener, mon);
|
||||||
|
|
||||||
|
mon->xdg = zxdg_output_manager_v1_get_xdg_output(
|
||||||
|
term->wl.xdg_output_manager, mon->output);
|
||||||
|
zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon);
|
||||||
|
wl_display_roundtrip(term->wl.display);
|
||||||
|
}
|
||||||
|
|
||||||
else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
|
else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
|
||||||
term->wl.data_device_manager = wl_registry_bind(
|
term->wl.data_device_manager = wl_registry_bind(
|
||||||
term->wl.registry, name, &wl_data_device_manager_interface, 1);
|
term->wl.registry, name, &wl_data_device_manager_interface, 1);
|
||||||
|
|
@ -493,6 +597,18 @@ main(int argc, char *const *argv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tll_foreach(term.wl.monitors, it) {
|
||||||
|
LOG_INFO("%s: %dx%d+%dx%d (scale=%d)",
|
||||||
|
it->item.name, it->item.width_px, it->item.height_px,
|
||||||
|
it->item.x, it->item.y, it->item.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(tll_length(term.wl.monitors) == 1 &&
|
||||||
|
"unimplemented: output tracking");
|
||||||
|
|
||||||
|
/* TODO: dynamic tracking */
|
||||||
|
term.scale = tll_back(term.wl.monitors).scale;
|
||||||
|
|
||||||
/* Clipboard */
|
/* Clipboard */
|
||||||
term.wl.data_device = wl_data_device_manager_get_data_device(
|
term.wl.data_device = wl_data_device_manager_get_data_device(
|
||||||
term.wl.data_device_manager, term.wl.seat);
|
term.wl.data_device_manager, term.wl.seat);
|
||||||
|
|
@ -526,8 +642,7 @@ main(int argc, char *const *argv)
|
||||||
LOG_INFO("cursor theme: %s, size: %u", cursor_theme, cursor_size);
|
LOG_INFO("cursor theme: %s, size: %u", cursor_theme, cursor_size);
|
||||||
|
|
||||||
term.wl.pointer.theme = wl_cursor_theme_load(
|
term.wl.pointer.theme = wl_cursor_theme_load(
|
||||||
cursor_theme, cursor_size * 1 /* backend->monitor->scale */,
|
cursor_theme, cursor_size * term.scale, term.wl.shm);
|
||||||
term.wl.shm);
|
|
||||||
if (term.wl.pointer.theme == NULL) {
|
if (term.wl.pointer.theme == NULL) {
|
||||||
LOG_ERR("failed to load cursor theme");
|
LOG_ERR("failed to load cursor theme");
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -814,6 +929,19 @@ out:
|
||||||
mtx_unlock(&term.render.workers.lock);
|
mtx_unlock(&term.render.workers.lock);
|
||||||
|
|
||||||
shm_fini();
|
shm_fini();
|
||||||
|
|
||||||
|
tll_foreach(term.wl.monitors, it) {
|
||||||
|
free(it->item.name);
|
||||||
|
if (it->item.xdg != NULL)
|
||||||
|
zxdg_output_v1_destroy(it->item.xdg);
|
||||||
|
if (it->item.output != NULL)
|
||||||
|
wl_output_destroy(it->item.output);
|
||||||
|
tll_remove(term.wl.monitors, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (term.wl.xdg_output_manager != NULL)
|
||||||
|
zxdg_output_manager_v1_destroy(term.wl.xdg_output_manager);
|
||||||
|
|
||||||
if (term.render.frame_callback != NULL)
|
if (term.render.frame_callback != NULL)
|
||||||
wl_callback_destroy(term.render.frame_callback);
|
wl_callback_destroy(term.render.frame_callback);
|
||||||
if (term.wl.xdg_toplevel != NULL)
|
if (term.wl.xdg_toplevel != NULL)
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ wl_proto_src = []
|
||||||
foreach prot : [
|
foreach prot : [
|
||||||
#'external/wlr-layer-shell-unstable-v1.xml',
|
#'external/wlr-layer-shell-unstable-v1.xml',
|
||||||
wayland_protocols_datadir + '/stable/xdg-shell/xdg-shell.xml',
|
wayland_protocols_datadir + '/stable/xdg-shell/xdg-shell.xml',
|
||||||
|
wayland_protocols_datadir + '/unstable/xdg-output/xdg-output-unstable-v1.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 + '/unstable/xdg-output/xdg-output-unstable-v1.xml']
|
#wayland_protocols_datadir + '/unstable/xdg-output/xdg-output-unstable-v1.xml']
|
||||||
]
|
]
|
||||||
|
|
|
||||||
9
render.c
9
render.c
|
|
@ -624,6 +624,7 @@ grid_render(struct terminal *term)
|
||||||
term->render.frame_callback = wl_surface_frame(term->wl.surface);
|
term->render.frame_callback = wl_surface_frame(term->wl.surface);
|
||||||
wl_callback_add_listener(term->render.frame_callback, &frame_listener, term);
|
wl_callback_add_listener(term->render.frame_callback, &frame_listener, term);
|
||||||
|
|
||||||
|
wl_surface_set_buffer_scale(term->wl.surface, term->scale);
|
||||||
wl_surface_commit(term->wl.surface);
|
wl_surface_commit(term->wl.surface);
|
||||||
|
|
||||||
#if TIME_FRAME_RENDERING
|
#if TIME_FRAME_RENDERING
|
||||||
|
|
@ -676,6 +677,9 @@ reflow(struct row **new_grid, int new_cols, int new_rows,
|
||||||
void
|
void
|
||||||
render_resize(struct terminal *term, int width, int height)
|
render_resize(struct terminal *term, int width, int height)
|
||||||
{
|
{
|
||||||
|
width *= term->scale;
|
||||||
|
height *= term->scale;
|
||||||
|
|
||||||
if (width == term->width && height == term->height)
|
if (width == term->width && height == term->height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -779,11 +783,8 @@ render_update_cursor_surface(struct terminal *term)
|
||||||
if (term->wl.pointer.cursor == NULL)
|
if (term->wl.pointer.cursor == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int scale = 1;
|
const int scale = term->scale;
|
||||||
#if 0
|
|
||||||
//const int scale = backend->monitor->scale;
|
|
||||||
wl_surface_set_buffer_scale(term->wl.pointer.surface, scale);
|
wl_surface_set_buffer_scale(term->wl.pointer.surface, scale);
|
||||||
#endif
|
|
||||||
|
|
||||||
struct wl_cursor_image *image = term->wl.pointer.cursor->images[0];
|
struct wl_cursor_image *image = term->wl.pointer.cursor->images[0];
|
||||||
|
|
||||||
|
|
|
||||||
20
terminal.h
20
terminal.h
|
|
@ -20,6 +20,23 @@
|
||||||
#define likely(c) __builtin_expect(!!(c), 1)
|
#define likely(c) __builtin_expect(!!(c), 1)
|
||||||
#define unlikely(c) __builtin_expect(!!(c), 0)
|
#define unlikely(c) __builtin_expect(!!(c), 0)
|
||||||
|
|
||||||
|
struct monitor {
|
||||||
|
struct wl_output *output;
|
||||||
|
struct zxdg_output_v1 *xdg;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
int width_mm;
|
||||||
|
int height_mm;
|
||||||
|
|
||||||
|
int width_px;
|
||||||
|
int height_px;
|
||||||
|
|
||||||
|
int scale;
|
||||||
|
};
|
||||||
|
|
||||||
struct wayland {
|
struct wayland {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -27,6 +44,7 @@ struct wayland {
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
struct wl_seat *seat;
|
struct wl_seat *seat;
|
||||||
|
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||||
struct wl_data_device_manager *data_device_manager;
|
struct wl_data_device_manager *data_device_manager;
|
||||||
struct wl_data_device *data_device;
|
struct wl_data_device *data_device;
|
||||||
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
||||||
|
|
@ -44,6 +62,7 @@ struct wayland {
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
bool have_argb8888;
|
bool have_argb8888;
|
||||||
|
tll(struct monitor) monitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rgb { float r, g, b; };
|
struct rgb { float r, g, b; };
|
||||||
|
|
@ -246,6 +265,7 @@ struct terminal {
|
||||||
struct vt vt;
|
struct vt vt;
|
||||||
struct kbd kbd;
|
struct kbd kbd;
|
||||||
|
|
||||||
|
int scale;
|
||||||
int width; /* pixels */
|
int width; /* pixels */
|
||||||
int height; /* pixels */
|
int height; /* pixels */
|
||||||
int cols; /* number of columns */
|
int cols; /* number of columns */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue