2020-11-14 11:00:43 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
2020-11-14 14:56:25 +01:00
|
|
|
#include <string.h>
|
2020-11-14 11:00:43 +01:00
|
|
|
#include <unistd.h>
|
2020-11-14 14:56:25 +01:00
|
|
|
#include <errno.h>
|
2020-11-14 11:00:43 +01:00
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
2020-11-21 13:25:56 +01:00
|
|
|
#include <sys/epoll.h>
|
|
|
|
|
#include <sys/timerfd.h>
|
|
|
|
|
#include <sys/mman.h>
|
2020-11-14 11:00:43 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
|
|
#include "async.h"
|
2020-11-21 13:25:56 +01:00
|
|
|
#include "config.h"
|
2022-04-19 17:24:25 +02:00
|
|
|
#include "key-binding.h"
|
2020-12-26 01:29:40 +01:00
|
|
|
#include "reaper.h"
|
2020-11-23 20:10:55 +01:00
|
|
|
#include "sixel.h"
|
2020-11-14 11:00:43 +01:00
|
|
|
#include "user-notification.h"
|
|
|
|
|
#include "vt.h"
|
|
|
|
|
|
2020-11-21 13:25:56 +01:00
|
|
|
extern bool fdm_ptmx(struct fdm *fdm, int fd, int events, void *data);
|
|
|
|
|
|
2020-11-14 14:56:25 +01:00
|
|
|
static void
|
|
|
|
|
usage(const char *prog_name)
|
|
|
|
|
{
|
|
|
|
|
printf(
|
|
|
|
|
"Usage: %s stimuli-file1 stimuli-file2 ... stimuli-fileN\n",
|
|
|
|
|
prog_name);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
enum async_write_status
|
|
|
|
|
async_write(int fd, const void *data, size_t len, size_t *idx)
|
|
|
|
|
{
|
|
|
|
|
return ASYNC_WRITE_DONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2021-02-10 16:17:36 +01:00
|
|
|
fdm_add(struct fdm *fdm, int fd, int events, fdm_fd_handler_t handler, void *data)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
fdm_del(struct fdm *fdm, int fd)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
fdm_event_add(struct fdm *fdm, int fd, int events)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
fdm_event_del(struct fdm *fdm, int fd, int events)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2024-02-08 16:44:55 +01:00
|
|
|
render_resize(
|
|
|
|
|
struct terminal *term, int width, int height, uint8_t resize_options)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void render_refresh(struct terminal *term) {}
|
|
|
|
|
void render_refresh_csd(struct terminal *term) {}
|
|
|
|
|
void render_refresh_title(struct terminal *term) {}
|
2024-02-06 14:04:22 +01:00
|
|
|
void render_refresh_app_id(struct terminal *term) {}
|
2024-09-10 19:13:00 +02:00
|
|
|
void render_refresh_icon(struct terminal *term) {}
|
2020-11-14 11:00:43 +01:00
|
|
|
|
2025-01-04 22:26:00 -05:00
|
|
|
void render_overlay(struct terminal *term) {}
|
|
|
|
|
|
render: when double-buffering, pre-apply previous frame's damage early
Foot likes it when compositor releases buffer immediately, as that
means we only have to re-render the cells that have changed since the
last frame.
For various reasons, not all compositors do this. In this case, foot
is typically forced to switch between two buffers, i.e. double-buffer.
In this case, each frame starts with copying over the damage from the
previous frame, to the new frame. Then we start rendering the updated
cells.
Bringing over the previous frame's damage can be slow, if the changed
area was large (e.g. when scrolling one or a few lines, or on full
screen updates). It's also done single-threaded. Thus it not only
slows down frame rendering, but pauses everything else (i.e. input
processing). All in all, it reduces performance and increases input
latency.
But we don't have to wait until it's time to render a frame to copy
over the previous frame's damage. We can do that as soon as the
compositor has released the buffer (for the frame _before_ the
previous frame). And we can do this in a thread.
This frees up foot to continue processing input, and reduces frame
rendering time since we can now start rendering the modified cells
immediately, without first doing a large memcpy(3).
In worst case scenarios (or perhaps we should consider them best case
scenarios...), I've seen up to a 10x performance increase in frame
rendering times (this obviously does *not* include the time it takes
to copy over the previous frame's damage, since that doesn't affect
neither input processing nor frame rendering).
Implemented by adding a callback mechanism to the shm abstraction
layer. Use it for the grid buffers, and kick off a thread that copies
the previous frame's damage, and resets the buffers age to 0 (so that
foot understands it can start render to it immediately when it later
needs to render a frame).
Since we have certain way of knowing if a compositor releases buffers
immediately or not, use a bit of heuristics; if we see 10 consecutive
non-immediate releases (that is, we reset the counter as soon as we do
see an immediate release), this new "pre-apply damage" logic is
enabled. It can be force-disabled with tweak.pre-apply-damage=no.
We also need to take care to wait for the thread before resetting the
render's "last_buf" pointer (or we'll SEGFAULT in the thread...).
We must also ensure we wait for the thread to finish before we start
rendering a new frame. Under normal circumstances, the wait time is
always 0, the thread has almost always finished long before we need to
render the next frame. But it _can_ happen.
Closes #2188
2025-10-05 10:48:36 +02:00
|
|
|
void render_buffer_release_callback(struct buffer *buf, void *data) {}
|
|
|
|
|
|
2022-02-07 20:31:20 +05:30
|
|
|
bool
|
|
|
|
|
render_xcursor_is_valid(const struct seat *seat, const char *cursor)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
bool
|
2023-06-27 18:16:33 +02:00
|
|
|
render_xcursor_set(struct seat *seat, struct terminal *term, enum cursor_shape shape)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 18:16:33 +02:00
|
|
|
enum cursor_shape
|
2021-11-30 22:43:41 +01:00
|
|
|
xcursor_for_csd_border(struct terminal *term, int x, int y)
|
|
|
|
|
{
|
2023-06-27 18:16:33 +02:00
|
|
|
return CURSOR_SHAPE_LEFT_PTR;
|
2021-11-30 22:43:41 +01:00
|
|
|
}
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
struct wl_window *
|
2021-10-28 17:51:44 -07:00
|
|
|
wayl_win_init(struct terminal *term, const char *token)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void wayl_win_destroy(struct wl_window *win) {}
|
osc: update font subpixel mode, and window opaque compositor hint, on alpha changes
When background alpha is changed at runtime (using OSC-11), we (may)
have to update the opaque hint we send to the compositor.
We must also update the subpixel mode used when rendering font
glyphs.
Why?
When the window is fully opaque, we use wl_surface_set_opaque_region()
on the entire surface, to hint to the compositor that it doesn’t have
to blend the window content with whatever is behind the
window. Obviously, if alpha is changed from opaque, to transparent (or
semi-transparent), that hint must be removed.
Sub-pixel mode is harder to explain, but in short, we can’t do
subpixel hinting with a (semi-)transparent background. Thus, similar
to the opaque hint, subpixel antialiasing must be enabled/disabled
when background alpha is changed.
2023-05-25 18:39:32 +02:00
|
|
|
void wayl_win_alpha_changed(struct wl_window *win) {}
|
2021-05-11 07:56:04 +02:00
|
|
|
bool wayl_win_set_urgent(struct wl_window *win) { return true; }
|
2025-01-17 10:10:10 +01:00
|
|
|
bool wayl_win_ring_bell(const struct wl_window *win) { return true; }
|
2023-07-17 20:13:50 +02:00
|
|
|
bool wayl_fractional_scaling(const struct wayland *wayl) { return true; }
|
2020-11-14 11:00:43 +01:00
|
|
|
|
2024-07-23 07:43:42 +02:00
|
|
|
pid_t
|
2020-11-14 11:00:43 +01:00
|
|
|
spawn(struct reaper *reaper, const char *cwd, char *const argv[],
|
2022-05-06 10:39:49 +02:00
|
|
|
int stdin_fd, int stdout_fd, int stderr_fd,
|
2024-07-23 07:43:42 +02:00
|
|
|
reaper_cb cb, void *cb_data, const char *xdg_activation_token)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
2024-07-23 07:43:42 +02:00
|
|
|
return 2;
|
2020-11-14 11:00:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pid_t
|
|
|
|
|
slave_spawn(
|
2022-04-12 15:23:41 +02:00
|
|
|
int ptmx, int argc, const char *cwd, char *const *argv, char *const *envp,
|
2022-06-13 16:32:59 +02:00
|
|
|
const env_var_list_t *extra_env_vars, const char *term_env,
|
|
|
|
|
const char *conf_shell, bool login_shell,
|
2020-11-14 11:00:43 +01:00
|
|
|
const user_notifications_t *notifications)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
render_worker_thread(void *_ctx)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
render: gamma-correct blending
This implements gamma-correct blending, which mainly affects font
rendering.
The implementation requires compile-time availability of the new
color-management protocol (available in wayland-protocols >= 1.41),
and run-time support for the same in the compositor (specifically, the
EXT_LINEAR TF function and sRGB primaries).
How it works: all colors are decoded from sRGB to linear (using a
lookup table, generated in the exact same way pixman generates it's
internal conversion tables) before being used by pixman. The resulting
image buffer is thus in decoded/linear format. We use the
color-management protocol to inform the compositor of this, by tagging
the wayland surfaces with the 'ext_linear' image attribute.
Sixes: all colors are sRGB internally, and decoded to linear before
being used in any sixels. Thus, the image buffers will contain linear
colors. This is important, since otherwise there would be a
decode/encode penalty every time a sixel is blended to the grid.
Emojis: we require fcft >= 3.2, which adds support for sRGB decoding
color glyphs. Meaning, the emoji pixman surfaces can be blended
directly to the grid, just like sixels.
Gamma-correct blending is enabled by default *when the compositor
supports it*. There's a new option to explicitly enable/disable it:
gamma-correct-blending=no|yes. If set to 'yes', and the compositor
does not implement the required color-management features, warning
logs are emitted.
There's a loss of precision when storing linear pixels in 8-bit
channels. For this reason, this patch also adds supports for 10-bit
surfaces. For now, this is disabled by default since such surfaces
only have 2 bits for alpha. It can be enabled with
tweak.surface-bit-depth=10-bit.
Perhaps, in the future, we can enable it by default if:
* gamma-correct blending is enabled
* the user has not enabled a transparent background
2025-02-21 11:01:29 +01:00
|
|
|
bool
|
2025-05-01 08:34:49 +02:00
|
|
|
wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf)
|
render: gamma-correct blending
This implements gamma-correct blending, which mainly affects font
rendering.
The implementation requires compile-time availability of the new
color-management protocol (available in wayland-protocols >= 1.41),
and run-time support for the same in the compositor (specifically, the
EXT_LINEAR TF function and sRGB primaries).
How it works: all colors are decoded from sRGB to linear (using a
lookup table, generated in the exact same way pixman generates it's
internal conversion tables) before being used by pixman. The resulting
image buffer is thus in decoded/linear format. We use the
color-management protocol to inform the compositor of this, by tagging
the wayland surfaces with the 'ext_linear' image attribute.
Sixes: all colors are sRGB internally, and decoded to linear before
being used in any sixels. Thus, the image buffers will contain linear
colors. This is important, since otherwise there would be a
decode/encode penalty every time a sixel is blended to the grid.
Emojis: we require fcft >= 3.2, which adds support for sRGB decoding
color glyphs. Meaning, the emoji pixman surfaces can be blended
directly to the grid, just like sixels.
Gamma-correct blending is enabled by default *when the compositor
supports it*. There's a new option to explicitly enable/disable it:
gamma-correct-blending=no|yes. If set to 'yes', and the compositor
does not implement the required color-management features, warning
logs are emitted.
There's a loss of precision when storing linear pixels in 8-bit
channels. For this reason, this patch also adds supports for 10-bit
surfaces. For now, this is disabled by default since such surfaces
only have 2 bits for alpha. It can be enabled with
tweak.surface-bit-depth=10-bit.
Perhaps, in the future, we can enable it by default if:
* gamma-correct blending is enabled
* the user has not enabled a transparent background
2025-02-21 11:01:29 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
struct extraction_context *
|
2021-03-30 14:40:21 +02:00
|
|
|
extract_begin(enum selection_kind kind, bool strip_trailing_empty)
|
2020-11-14 11:00:43 +01:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
extract_one(
|
|
|
|
|
const struct terminal *term, const struct row *row, const struct cell *cell,
|
|
|
|
|
int col, void *context)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
extract_finish(struct extraction_context *context, char **text, size_t *len)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 22:37:47 +01:00
|
|
|
void cmd_scrollback_up(struct terminal *term, int rows) {}
|
|
|
|
|
void cmd_scrollback_down(struct terminal *term, int rows) {}
|
|
|
|
|
|
2020-12-04 18:39:11 +01:00
|
|
|
void ime_enable(struct seat *seat) {}
|
|
|
|
|
void ime_disable(struct seat *seat) {}
|
2021-03-23 13:03:07 +01:00
|
|
|
void ime_reset_preedit(struct seat *seat) {}
|
2020-12-04 18:39:11 +01:00
|
|
|
|
2024-07-23 07:43:56 +02:00
|
|
|
bool
|
2024-07-23 12:15:37 +02:00
|
|
|
notify_notify(struct terminal *term, struct notification *notif)
|
2024-07-23 07:43:56 +02:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-25 19:31:27 +02:00
|
|
|
void
|
|
|
|
|
notify_close(struct terminal *term, const char *id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 18:06:24 +01:00
|
|
|
void
|
2024-07-23 07:43:56 +02:00
|
|
|
notify_free(struct terminal *term, struct notification *notif)
|
2020-12-10 18:06:24 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 12:15:37 +02:00
|
|
|
void
|
|
|
|
|
notify_icon_add(struct terminal *term, const char *id,
|
|
|
|
|
const char *symbolic_name, const uint8_t *data,
|
|
|
|
|
size_t data_sz)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
notify_icon_del(struct terminal *term, const char *id)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
notify_icon_free(struct notification_icon *icon)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-07-23 07:43:56 +02:00
|
|
|
|
2020-12-26 01:29:40 +01:00
|
|
|
void reaper_add(struct reaper *reaper, pid_t pid, reaper_cb cb, void *cb_data) {}
|
2021-01-12 09:20:54 +01:00
|
|
|
void reaper_del(struct reaper *reaper, pid_t pid) {}
|
2020-12-26 01:29:40 +01:00
|
|
|
|
2021-01-31 11:12:07 +01:00
|
|
|
void urls_reset(struct terminal *term) {}
|
2020-12-26 01:29:40 +01:00
|
|
|
|
2021-07-22 10:02:52 +02:00
|
|
|
void shm_unref(struct buffer *buf) {}
|
|
|
|
|
void shm_chain_free(struct buffer_chain *chain) {}
|
2025-05-01 08:34:49 +02:00
|
|
|
enum shm_bit_depth shm_chain_bit_depth(const struct buffer_chain *chain) { return SHM_BITS_8; }
|
2021-07-22 10:02:52 +02:00
|
|
|
|
|
|
|
|
struct buffer_chain *
|
render: gamma-correct blending
This implements gamma-correct blending, which mainly affects font
rendering.
The implementation requires compile-time availability of the new
color-management protocol (available in wayland-protocols >= 1.41),
and run-time support for the same in the compositor (specifically, the
EXT_LINEAR TF function and sRGB primaries).
How it works: all colors are decoded from sRGB to linear (using a
lookup table, generated in the exact same way pixman generates it's
internal conversion tables) before being used by pixman. The resulting
image buffer is thus in decoded/linear format. We use the
color-management protocol to inform the compositor of this, by tagging
the wayland surfaces with the 'ext_linear' image attribute.
Sixes: all colors are sRGB internally, and decoded to linear before
being used in any sixels. Thus, the image buffers will contain linear
colors. This is important, since otherwise there would be a
decode/encode penalty every time a sixel is blended to the grid.
Emojis: we require fcft >= 3.2, which adds support for sRGB decoding
color glyphs. Meaning, the emoji pixman surfaces can be blended
directly to the grid, just like sixels.
Gamma-correct blending is enabled by default *when the compositor
supports it*. There's a new option to explicitly enable/disable it:
gamma-correct-blending=no|yes. If set to 'yes', and the compositor
does not implement the required color-management features, warning
logs are emitted.
There's a loss of precision when storing linear pixels in 8-bit
channels. For this reason, this patch also adds supports for 10-bit
surfaces. For now, this is disabled by default since such surfaces
only have 2 bits for alpha. It can be enabled with
tweak.surface-bit-depth=10-bit.
Perhaps, in the future, we can enable it by default if:
* gamma-correct blending is enabled
* the user has not enabled a transparent background
2025-02-21 11:01:29 +01:00
|
|
|
shm_chain_new(
|
|
|
|
|
struct wayland *wayl, bool scrollable, size_t pix_instances,
|
render: when double-buffering, pre-apply previous frame's damage early
Foot likes it when compositor releases buffer immediately, as that
means we only have to re-render the cells that have changed since the
last frame.
For various reasons, not all compositors do this. In this case, foot
is typically forced to switch between two buffers, i.e. double-buffer.
In this case, each frame starts with copying over the damage from the
previous frame, to the new frame. Then we start rendering the updated
cells.
Bringing over the previous frame's damage can be slow, if the changed
area was large (e.g. when scrolling one or a few lines, or on full
screen updates). It's also done single-threaded. Thus it not only
slows down frame rendering, but pauses everything else (i.e. input
processing). All in all, it reduces performance and increases input
latency.
But we don't have to wait until it's time to render a frame to copy
over the previous frame's damage. We can do that as soon as the
compositor has released the buffer (for the frame _before_ the
previous frame). And we can do this in a thread.
This frees up foot to continue processing input, and reduces frame
rendering time since we can now start rendering the modified cells
immediately, without first doing a large memcpy(3).
In worst case scenarios (or perhaps we should consider them best case
scenarios...), I've seen up to a 10x performance increase in frame
rendering times (this obviously does *not* include the time it takes
to copy over the previous frame's damage, since that doesn't affect
neither input processing nor frame rendering).
Implemented by adding a callback mechanism to the shm abstraction
layer. Use it for the grid buffers, and kick off a thread that copies
the previous frame's damage, and resets the buffers age to 0 (so that
foot understands it can start render to it immediately when it later
needs to render a frame).
Since we have certain way of knowing if a compositor releases buffers
immediately or not, use a bit of heuristics; if we see 10 consecutive
non-immediate releases (that is, we reset the counter as soon as we do
see an immediate release), this new "pre-apply damage" logic is
enabled. It can be force-disabled with tweak.pre-apply-damage=no.
We also need to take care to wait for the thread before resetting the
render's "last_buf" pointer (or we'll SEGFAULT in the thread...).
We must also ensure we wait for the thread to finish before we start
rendering a new frame. Under normal circumstances, the wait time is
always 0, the thread has almost always finished long before we need to
render the next frame. But it _can_ happen.
Closes #2188
2025-10-05 10:48:36 +02:00
|
|
|
enum shm_bit_depth desired_bit_depth,
|
|
|
|
|
void (*release_cb)(struct buffer *buf, void *data), void *cb_data)
|
2021-07-22 10:02:52 +02:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-23 10:15:35 +02:00
|
|
|
void search_selection_cancelled(struct terminal *term) {}
|
|
|
|
|
|
2021-12-04 18:29:58 +01:00
|
|
|
void get_current_modifiers(const struct seat *seat,
|
|
|
|
|
xkb_mod_mask_t *effective,
|
2024-02-06 14:03:07 +01:00
|
|
|
xkb_mod_mask_t *consumed, uint32_t key,
|
|
|
|
|
bool filter_locked) {}
|
2021-12-04 18:29:58 +01:00
|
|
|
|
2022-04-19 17:24:25 +02:00
|
|
|
static struct key_binding_set kbd;
|
|
|
|
|
static bool kbd_initialized = false;
|
|
|
|
|
|
|
|
|
|
struct key_binding_set *
|
|
|
|
|
key_binding_for(
|
terminal: don’t unref a not-yet-referenced key-binding set
Key-binding sets are bound to a seat/configuration pair. The conf
reference is done when a new terminal instance is created.
When that same terminal instance is destroyed, the key binding set is
unref:ed.
If the terminal instance is destroyed *before* the key binding set has
been referenced, we’ll still unref it. This creates an imbalance.
In particular, when the there is exactly one other terminal instance
referencing that same key binding set, that terminal instance will
trigger a foot server crash as soon as it receives a key press/release
event. This happens because the next-to-last terminal instance brought
the reference count of the binding set down to 0, causing it to be
free:d.
Thus, we *must* reference the binding set *before* we can error
out (when instantiating a new terminal instance).
At this point, we don’t yet have a valid terminal instance. But,
that’s ok, because all the key_binding_new_for_term() did with the
terminal instance was get the "struct wayland" and "struct config"
pointers. So, rename the function and simply pass these pointers
explicitly.
Similarly, change key_binding_for() to take a "struct config" pointer,
rather than a "struct terminal" pointer.
Also rename key_binding_unref_term() -> key_binding_unref().
2022-09-05 19:23:40 +02:00
|
|
|
struct key_binding_manager *mgr, const struct config *conf,
|
2022-04-19 17:24:25 +02:00
|
|
|
const struct seat *seat)
|
2022-04-23 00:44:46 +02:00
|
|
|
{
|
|
|
|
|
return &kbd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
terminal: don’t unref a not-yet-referenced key-binding set
Key-binding sets are bound to a seat/configuration pair. The conf
reference is done when a new terminal instance is created.
When that same terminal instance is destroyed, the key binding set is
unref:ed.
If the terminal instance is destroyed *before* the key binding set has
been referenced, we’ll still unref it. This creates an imbalance.
In particular, when the there is exactly one other terminal instance
referencing that same key binding set, that terminal instance will
trigger a foot server crash as soon as it receives a key press/release
event. This happens because the next-to-last terminal instance brought
the reference count of the binding set down to 0, causing it to be
free:d.
Thus, we *must* reference the binding set *before* we can error
out (when instantiating a new terminal instance).
At this point, we don’t yet have a valid terminal instance. But,
that’s ok, because all the key_binding_new_for_term() did with the
terminal instance was get the "struct wayland" and "struct config"
pointers. So, rename the function and simply pass these pointers
explicitly.
Similarly, change key_binding_for() to take a "struct config" pointer,
rather than a "struct terminal" pointer.
Also rename key_binding_unref_term() -> key_binding_unref().
2022-09-05 19:23:40 +02:00
|
|
|
key_binding_new_for_conf(
|
|
|
|
|
struct key_binding_manager *mgr, const struct wayland *wayl,
|
|
|
|
|
const struct config *conf)
|
2022-04-19 17:24:25 +02:00
|
|
|
{
|
|
|
|
|
if (!kbd_initialized) {
|
|
|
|
|
kbd_initialized = true;
|
|
|
|
|
kbd = (struct key_binding_set){
|
|
|
|
|
.key = tll_init(),
|
|
|
|
|
.search = tll_init(),
|
|
|
|
|
.url = tll_init(),
|
|
|
|
|
.mouse = tll_init(),
|
|
|
|
|
.selection_overrides = 0,
|
|
|
|
|
};
|
|
|
|
|
}
|
2022-04-23 00:44:46 +02:00
|
|
|
}
|
2022-04-19 17:24:25 +02:00
|
|
|
|
2022-04-23 00:44:46 +02:00
|
|
|
void
|
terminal: don’t unref a not-yet-referenced key-binding set
Key-binding sets are bound to a seat/configuration pair. The conf
reference is done when a new terminal instance is created.
When that same terminal instance is destroyed, the key binding set is
unref:ed.
If the terminal instance is destroyed *before* the key binding set has
been referenced, we’ll still unref it. This creates an imbalance.
In particular, when the there is exactly one other terminal instance
referencing that same key binding set, that terminal instance will
trigger a foot server crash as soon as it receives a key press/release
event. This happens because the next-to-last terminal instance brought
the reference count of the binding set down to 0, causing it to be
free:d.
Thus, we *must* reference the binding set *before* we can error
out (when instantiating a new terminal instance).
At this point, we don’t yet have a valid terminal instance. But,
that’s ok, because all the key_binding_new_for_term() did with the
terminal instance was get the "struct wayland" and "struct config"
pointers. So, rename the function and simply pass these pointers
explicitly.
Similarly, change key_binding_for() to take a "struct config" pointer,
rather than a "struct terminal" pointer.
Also rename key_binding_unref_term() -> key_binding_unref().
2022-09-05 19:23:40 +02:00
|
|
|
key_binding_unref(struct key_binding_manager *mgr, const struct config *conf)
|
2022-04-23 00:44:46 +02:00
|
|
|
{
|
2022-04-19 17:24:25 +02:00
|
|
|
}
|
2021-12-04 18:29:58 +01:00
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
int
|
|
|
|
|
main(int argc, const char *const *argv)
|
|
|
|
|
{
|
2020-11-14 14:56:25 +01:00
|
|
|
if (argc < 2) {
|
|
|
|
|
usage(argv[0]);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 13:45:39 +01:00
|
|
|
const int row_count = 67;
|
|
|
|
|
const int col_count = 135;
|
|
|
|
|
const int grid_row_count = 16384;
|
2020-11-14 11:00:43 +01:00
|
|
|
|
2020-11-21 13:25:56 +01:00
|
|
|
int lower_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
|
|
|
|
if (lower_fd < 0)
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
|
|
int upper_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
|
|
|
|
if (upper_fd < 0) {
|
|
|
|
|
close(lower_fd);
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-18 18:31:18 +02:00
|
|
|
struct row **normal_rows = calloc(grid_row_count, sizeof(normal_rows[0]));
|
|
|
|
|
struct row **alt_rows = calloc(grid_row_count, sizeof(alt_rows[0]));
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
for (int i = 0; i < grid_row_count; i++) {
|
2022-10-18 18:31:18 +02:00
|
|
|
normal_rows[i] = calloc(1, sizeof(*normal_rows[i]));
|
|
|
|
|
normal_rows[i]->cells = calloc(col_count, sizeof(normal_rows[i]->cells[0]));
|
|
|
|
|
alt_rows[i] = calloc(1, sizeof(*alt_rows[i]));
|
|
|
|
|
alt_rows[i]->cells = calloc(col_count, sizeof(alt_rows[i]->cells[0]));
|
2020-11-14 11:00:43 +01:00
|
|
|
}
|
|
|
|
|
|
2020-11-21 13:25:56 +01:00
|
|
|
struct config conf = {
|
|
|
|
|
.tweak = {
|
|
|
|
|
.delayed_render_lower_ns = 500000, /* 0.5ms */
|
|
|
|
|
.delayed_render_upper_ns = 16666666 / 2, /* half a frame period (60Hz) */
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-19 19:11:58 +01:00
|
|
|
struct wayland wayl = {
|
|
|
|
|
.seats = tll_init(),
|
|
|
|
|
.monitors = tll_init(),
|
|
|
|
|
.terms = tll_init(),
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
struct terminal term = {
|
2020-11-21 13:25:56 +01:00
|
|
|
.conf = &conf,
|
2020-11-19 19:11:58 +01:00
|
|
|
.wl = &wayl,
|
2020-11-14 11:00:43 +01:00
|
|
|
.grid = &term.normal,
|
|
|
|
|
.normal = {
|
|
|
|
|
.num_rows = grid_row_count,
|
|
|
|
|
.num_cols = col_count,
|
2022-10-18 18:31:18 +02:00
|
|
|
.rows = normal_rows,
|
|
|
|
|
.cur_row = normal_rows[0],
|
2020-11-14 11:00:43 +01:00
|
|
|
},
|
|
|
|
|
.alt = {
|
|
|
|
|
.num_rows = grid_row_count,
|
|
|
|
|
.num_cols = col_count,
|
2022-10-18 18:31:18 +02:00
|
|
|
.rows = alt_rows,
|
|
|
|
|
.cur_row = alt_rows[0],
|
2020-11-14 11:00:43 +01:00
|
|
|
},
|
|
|
|
|
.scale = 1,
|
|
|
|
|
.width = col_count * 8,
|
|
|
|
|
.height = row_count * 15,
|
|
|
|
|
.cols = col_count,
|
|
|
|
|
.rows = row_count,
|
|
|
|
|
.cell_width = 8,
|
|
|
|
|
.cell_height = 15,
|
|
|
|
|
.scroll_region = {
|
|
|
|
|
.start = 0,
|
|
|
|
|
.end = row_count,
|
|
|
|
|
},
|
2020-11-19 19:12:32 +01:00
|
|
|
.selection = {
|
2022-04-10 18:31:13 +02:00
|
|
|
.coords = {
|
|
|
|
|
.start = {-1, -1},
|
|
|
|
|
.end = {-1, -1},
|
|
|
|
|
},
|
2020-11-19 19:12:32 +01:00
|
|
|
},
|
2020-11-21 13:25:56 +01:00
|
|
|
.delayed_render_timer = {
|
|
|
|
|
.lower_fd = lower_fd,
|
|
|
|
|
.upper_fd = upper_fd
|
2020-11-23 20:10:55 +01:00
|
|
|
},
|
|
|
|
|
.sixel = {
|
|
|
|
|
.palette_size = SIXEL_MAX_COLORS,
|
|
|
|
|
.max_width = SIXEL_MAX_WIDTH,
|
|
|
|
|
.max_height = SIXEL_MAX_HEIGHT,
|
|
|
|
|
},
|
2020-11-14 11:00:43 +01:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 19:11:58 +01:00
|
|
|
tll_push_back(wayl.terms, &term);
|
|
|
|
|
|
2020-11-14 14:56:25 +01:00
|
|
|
int ret = EXIT_FAILURE;
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
|
struct stat st;
|
|
|
|
|
if (stat(argv[i], &st) < 0) {
|
2020-11-21 13:25:56 +01:00
|
|
|
fprintf(stderr, "error: %s: failed to stat: %s\n",
|
2020-11-14 14:56:25 +01:00
|
|
|
argv[i], strerror(errno));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t *data = malloc(st.st_size);
|
|
|
|
|
if (data == NULL) {
|
2020-11-21 13:25:56 +01:00
|
|
|
fprintf(stderr, "error: %s: failed to allocate buffer: %s\n",
|
2020-11-14 14:56:25 +01:00
|
|
|
argv[i], strerror(errno));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int fd = open(argv[1], O_RDONLY);
|
|
|
|
|
if (fd < 0) {
|
2020-11-21 13:25:56 +01:00
|
|
|
fprintf(stderr, "error: %s: failed to open: %s\n",
|
2020-11-14 14:56:25 +01:00
|
|
|
argv[i], strerror(errno));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssize_t amount = read(fd, data, st.st_size);
|
|
|
|
|
if (amount != st.st_size) {
|
2020-11-21 13:25:56 +01:00
|
|
|
fprintf(stderr, "error: %s: failed to read: %s\n",
|
2020-11-14 14:56:25 +01:00
|
|
|
argv[i], strerror(errno));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
2021-01-19 14:20:55 +00:00
|
|
|
#if defined(MEMFD_CREATE)
|
2020-11-21 13:25:56 +01:00
|
|
|
int mem_fd = memfd_create("foot-pgo-ptmx", MFD_CLOEXEC);
|
2021-01-19 14:20:55 +00:00
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
|
// memfd_create on FreeBSD 13 is SHM_ANON without sealing support
|
|
|
|
|
int mem_fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);
|
|
|
|
|
#else
|
|
|
|
|
char name[] = "/tmp/foot-pgo-ptmx-XXXXXX";
|
|
|
|
|
int mem_fd = mkostemp(name, O_CLOEXEC);
|
|
|
|
|
unlink(name);
|
|
|
|
|
#endif
|
2020-11-21 13:25:56 +01:00
|
|
|
if (mem_fd < 0) {
|
|
|
|
|
fprintf(stderr, "error: failed to create memory FD\n");
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (write(mem_fd, data, st.st_size) < 0) {
|
|
|
|
|
fprintf(stderr, "error: failed to write memory FD\n");
|
|
|
|
|
close(mem_fd);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 14:56:25 +01:00
|
|
|
free(data);
|
2020-11-21 13:25:56 +01:00
|
|
|
|
|
|
|
|
term.ptmx = mem_fd;
|
|
|
|
|
lseek(mem_fd, 0, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
printf("Feeding VT parser with %s (%lld bytes)\n",
|
|
|
|
|
argv[i], (long long)st.st_size);
|
|
|
|
|
|
|
|
|
|
while (lseek(mem_fd, 0, SEEK_CUR) < st.st_size) {
|
|
|
|
|
if (!fdm_ptmx(NULL, -1, EPOLLIN, &term)) {
|
|
|
|
|
fprintf(stderr, "error: fdm_ptmx() failed\n");
|
|
|
|
|
close(mem_fd);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
close(mem_fd);
|
2020-11-14 14:56:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = EXIT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
out:
|
2020-11-19 19:11:58 +01:00
|
|
|
tll_free(wayl.terms);
|
|
|
|
|
|
2020-11-14 11:00:43 +01:00
|
|
|
for (int i = 0; i < grid_row_count; i++) {
|
2022-10-18 18:31:18 +02:00
|
|
|
if (normal_rows[i] != NULL)
|
|
|
|
|
free(normal_rows[i]->cells);
|
|
|
|
|
free(normal_rows[i]);
|
|
|
|
|
|
|
|
|
|
if (alt_rows[i] != NULL)
|
|
|
|
|
free(alt_rows[i]->cells);
|
|
|
|
|
free(alt_rows[i]);
|
2020-11-14 11:00:43 +01:00
|
|
|
}
|
2020-11-14 14:56:25 +01:00
|
|
|
|
2022-10-18 18:31:18 +02:00
|
|
|
free(normal_rows);
|
|
|
|
|
free(alt_rows);
|
2020-11-21 13:25:56 +01:00
|
|
|
close(lower_fd);
|
|
|
|
|
close(upper_fd);
|
2020-11-14 14:56:25 +01:00
|
|
|
return ret;
|
2020-11-14 11:00:43 +01:00
|
|
|
}
|