mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
Merge branch 'toplevel-icon'
This commit is contained in:
commit
33f3818520
16 changed files with 248 additions and 25 deletions
|
|
@ -61,6 +61,8 @@
|
|||
(and the grid reflowed) or not when e.g. zooming in/out
|
||||
([#1807][1807]).
|
||||
* `strikeout-thickness` option.
|
||||
* Implemented the new `xdg-toplevel-icon-v1` protocol.
|
||||
* Implemented `CSI 21 t`: report window title.
|
||||
|
||||
[1807]: https://codeberg.org/dnkl/foot/issues/1807
|
||||
|
||||
|
|
|
|||
9
csi.c
9
csi.c
|
|
@ -1250,7 +1250,6 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
case 9: LOG_WARN("unimplemented: maximize/unmaximize window"); break;
|
||||
case 10: LOG_WARN("unimplemented: to/from full screen"); break;
|
||||
case 20: LOG_WARN("unimplemented: report icon label"); break;
|
||||
case 21: LOG_WARN("unimplemented: report window title"); break;
|
||||
case 24: LOG_WARN("unimplemented: resize window (DECSLPP)"); break;
|
||||
|
||||
case 11: /* report if window is iconified */
|
||||
|
|
@ -1354,6 +1353,14 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
break;
|
||||
}
|
||||
|
||||
case 21: {
|
||||
char reply[3 + strlen(term->window_title) + 2 + 1];
|
||||
int chars = xsnprintf(
|
||||
reply, sizeof(reply), "\033]l%s\033\\", term->window_title);
|
||||
term_to_slave(term, reply, chars);
|
||||
break;
|
||||
}
|
||||
|
||||
case 22: { /* push window title */
|
||||
/* 0 - icon + title, 1 - icon, 2 - title */
|
||||
unsigned what = vt_param_get(term, 1, 0);
|
||||
|
|
|
|||
|
|
@ -388,15 +388,27 @@ manipulation sequences. The generic format is:
|
|||
| 19
|
||||
: -
|
||||
: Report screen size, in characters.
|
||||
| 20
|
||||
: -
|
||||
: Report icon label.
|
||||
| 21
|
||||
: -
|
||||
: Report window title.
|
||||
| 22
|
||||
: -
|
||||
: Push window title+icon. Foot does not support pushing the icon.
|
||||
: Push window title+icon.
|
||||
| 22
|
||||
: 1
|
||||
: Push window icon.
|
||||
| 22
|
||||
: 2
|
||||
: Push window title.
|
||||
| 23
|
||||
: -
|
||||
: Pop window title+icon. Foot does not support popping the icon.
|
||||
: Pop window title+icon.
|
||||
| 23
|
||||
: 1
|
||||
: Pop window icon.
|
||||
| 23
|
||||
: 2
|
||||
: Pop window title.
|
||||
|
|
@ -659,8 +671,10 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_.
|
|||
:< *Description*
|
||||
| \\E] 0 ; _Pt_ \\E\\
|
||||
: xterm
|
||||
: Set window icon and title to _Pt_ (foot does not support setting the
|
||||
icon)
|
||||
: Set window icon and title to _Pt_.
|
||||
| \\E] 1 ; _Pt_ \\E\\
|
||||
: xterm
|
||||
: Set window icon to _Pt_.
|
||||
| \\E] 2 ; _Pt_ \\E\\
|
||||
: xterm
|
||||
: Set window title to _Pt_
|
||||
|
|
|
|||
|
|
@ -37,3 +37,12 @@ static inline bool feature_graphemes(void)
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool feature_xdg_toplevel_icon(void)
|
||||
{
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
3
main.c
3
main.c
|
|
@ -51,11 +51,12 @@ version_and_features(void)
|
|||
{
|
||||
static char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"version: %s %cpgo %cime %cgraphemes %cassertions",
|
||||
"version: %s %cpgo %cime %cgraphemes %ctoplevel-icon %cassertions",
|
||||
FOOT_VERSION,
|
||||
feature_pgo() ? '+' : '-',
|
||||
feature_ime() ? '+' : '-',
|
||||
feature_graphemes() ? '+' : '-',
|
||||
feature_xdg_toplevel_icon() ? '+' : '-',
|
||||
feature_assertions() ? '+' : '-');
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,14 @@ wl_proto_xml = [
|
|||
wayland_protocols_datadir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
|
||||
]
|
||||
|
||||
if wayland_protocols.version().version_compare('>=1.37')
|
||||
add_project_arguments('-DHAVE_XDG_TOPLEVEL_ICON', language: 'c')
|
||||
wl_proto_xml += [wayland_protocols_datadir / 'staging/xdg-toplevel-icon/xdg-toplevel-icon-v1.xml']
|
||||
xdg_toplevel_icon = true
|
||||
else
|
||||
xdg_toplevel_icon = false
|
||||
endif
|
||||
|
||||
foreach prot : wl_proto_xml
|
||||
wl_proto_headers += custom_target(
|
||||
prot.underscorify() + '-client-header',
|
||||
|
|
@ -401,6 +409,7 @@ summary(
|
|||
'Themes': get_option('themes'),
|
||||
'IME': get_option('ime'),
|
||||
'Grapheme clustering': utf8proc.found(),
|
||||
'Wayland: xdg-toplevel-icon-v1': xdg_toplevel_icon,
|
||||
'utmp backend': utmp_backend,
|
||||
'utmp helper default path': utmp_default_helper_path,
|
||||
'Build terminfo': tic.found(),
|
||||
|
|
|
|||
7
misc.c
7
misc.c
|
|
@ -42,3 +42,10 @@ timespec_sub(const struct timespec *a, const struct timespec *b,
|
|||
res->tv_nsec += one_sec_in_ns;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_valid_utf8(const char *value)
|
||||
{
|
||||
return value != NULL &&
|
||||
mbsntoc32(NULL, value, strlen(value), 0) != (size_t)-1;
|
||||
}
|
||||
|
|
|
|||
2
misc.h
2
misc.h
|
|
@ -8,3 +8,5 @@ bool isword(char32_t wc, bool spaces_only, const char32_t *delimiters);
|
|||
|
||||
void timespec_add(const struct timespec *a, const struct timespec *b, struct timespec *res);
|
||||
void timespec_sub(const struct timespec *a, const struct timespec *b, struct timespec *res);
|
||||
|
||||
bool is_valid_utf8(const char *value);
|
||||
|
|
|
|||
13
osc.c
13
osc.c
|
|
@ -1145,9 +1145,16 @@ osc_dispatch(struct terminal *term)
|
|||
char *string = (char *)&term->vt.osc.data[data_ofs];
|
||||
|
||||
switch (param) {
|
||||
case 0: term_set_window_title(term, string); break; /* icon + title */
|
||||
case 1: break; /* icon */
|
||||
case 2: term_set_window_title(term, string); break; /* title */
|
||||
case 0: /* icon + title */
|
||||
term_set_window_title(term, string);
|
||||
break;
|
||||
|
||||
case 1: /* icon */
|
||||
break;
|
||||
|
||||
case 2: /* title */
|
||||
term_set_window_title(term, string);
|
||||
break;
|
||||
|
||||
case 4: {
|
||||
/* Set color<idx> */
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ void render_refresh(struct terminal *term) {}
|
|||
void render_refresh_csd(struct terminal *term) {}
|
||||
void render_refresh_title(struct terminal *term) {}
|
||||
void render_refresh_app_id(struct terminal *term) {}
|
||||
void render_refresh_icon(struct terminal *term) {}
|
||||
|
||||
bool
|
||||
render_xcursor_is_valid(const struct seat *seat, const char *cursor)
|
||||
|
|
|
|||
62
render.c
62
render.c
|
|
@ -12,15 +12,19 @@
|
|||
|
||||
#include "macros.h"
|
||||
#if HAS_INCLUDE(<pthread_np.h>)
|
||||
#include <pthread_np.h>
|
||||
#define pthread_setname_np(thread, name) (pthread_set_name_np(thread, name), 0)
|
||||
#include <pthread_np.h>
|
||||
#define pthread_setname_np(thread, name) (pthread_set_name_np(thread, name), 0)
|
||||
#elif defined(__NetBSD__)
|
||||
#define pthread_setname_np(thread, name) pthread_setname_np(thread, "%s", (void *)name)
|
||||
#define pthread_setname_np(thread, name) pthread_setname_np(thread, "%s", (void *)name)
|
||||
#endif
|
||||
|
||||
#include <presentation-time.h>
|
||||
#include <wayland-cursor.h>
|
||||
#include <xdg-shell.h>
|
||||
#include <presentation-time.h>
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
#include <xdg-toplevel-icon-v1.h>
|
||||
#endif
|
||||
|
||||
#include <fcft/fcft.h>
|
||||
|
||||
|
|
@ -4944,10 +4948,54 @@ render_refresh_app_id(struct terminal *term)
|
|||
};
|
||||
|
||||
timerfd_settime(term->render.app_id.timer_fd, 0, &timeout, NULL);
|
||||
} else {
|
||||
term->render.app_id.last_update = now;
|
||||
xdg_toplevel_set_app_id(term->window->xdg_toplevel, term->app_id ? term->app_id : term->conf->app_id);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *app_id =
|
||||
term->app_id != NULL ? term->app_id : term->conf->app_id;
|
||||
|
||||
xdg_toplevel_set_app_id(term->window->xdg_toplevel, app_id);
|
||||
term->render.app_id.last_update = now;
|
||||
}
|
||||
|
||||
void
|
||||
render_refresh_icon(struct terminal *term)
|
||||
{
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
if (term->wl->toplevel_icon_manager == NULL) {
|
||||
LOG_DBG("compositor does not implement xdg-toplevel-icon: "
|
||||
"ignoring request to refresh window icon");
|
||||
return;
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
|
||||
return;
|
||||
|
||||
struct timespec diff;
|
||||
timespec_sub(&now, &term->render.icon.last_update, &diff);
|
||||
|
||||
if (diff.tv_sec == 0 && diff.tv_nsec < 8333 * 1000) {
|
||||
const struct itimerspec timeout = {
|
||||
.it_value = {.tv_nsec = 8333 * 1000 - diff.tv_nsec},
|
||||
};
|
||||
|
||||
timerfd_settime(term->render.icon.timer_fd, 0, &timeout, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *icon_name = term_icon(term);
|
||||
LOG_DBG("setting toplevel icon: %s", icon_name);
|
||||
|
||||
struct xdg_toplevel_icon_v1 *icon =
|
||||
xdg_toplevel_icon_manager_v1_create_icon(term->wl->toplevel_icon_manager);
|
||||
xdg_toplevel_icon_v1_set_name(icon, icon_name);
|
||||
xdg_toplevel_icon_manager_v1_set_icon(
|
||||
term->wl->toplevel_icon_manager, term->window->xdg_toplevel, icon);
|
||||
xdg_toplevel_icon_v1_destroy(icon);
|
||||
|
||||
term->render.icon.last_update = now;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
1
render.h
1
render.h
|
|
@ -22,6 +22,7 @@ bool render_resize(
|
|||
|
||||
void render_refresh(struct terminal *term);
|
||||
void render_refresh_app_id(struct terminal *term);
|
||||
void render_refresh_icon(struct terminal *term);
|
||||
void render_refresh_csd(struct terminal *term);
|
||||
void render_refresh_search(struct terminal *term);
|
||||
void render_refresh_title(struct terminal *term);
|
||||
|
|
|
|||
67
terminal.c
67
terminal.c
|
|
@ -639,6 +639,30 @@ fdm_title_update_timeout(struct fdm *fdm, int fd, int events, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_icon_update_timeout(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
if (events & EPOLLHUP)
|
||||
return false;
|
||||
|
||||
struct terminal *term = data;
|
||||
uint64_t unused;
|
||||
ssize_t ret = read(term->render.icon.timer_fd, &unused, sizeof(unused));
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return true;
|
||||
LOG_ERRNO("failed to read icon update throttle timer");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct itimerspec reset = {{0}};
|
||||
timerfd_settime(term->render.icon.timer_fd, 0, &reset, NULL);
|
||||
|
||||
render_refresh_icon(term);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_app_id_update_timeout(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
|
|
@ -1114,6 +1138,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
int delay_upper_fd = -1;
|
||||
int app_sync_updates_fd = -1;
|
||||
int title_update_fd = -1;
|
||||
int icon_update_fd = -1;
|
||||
int app_id_update_fd = -1;
|
||||
|
||||
struct terminal *term = malloc(sizeof(*term));
|
||||
|
|
@ -1150,6 +1175,12 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
goto close_fds;
|
||||
}
|
||||
|
||||
if ((icon_update_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0)
|
||||
{
|
||||
LOG_ERRNO("failed to create icon update throttle timer FD");
|
||||
goto close_fds;
|
||||
}
|
||||
|
||||
if ((app_id_update_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK)) < 0)
|
||||
{
|
||||
LOG_ERRNO("failed to create app ID update throttle timer FD");
|
||||
|
|
@ -1187,6 +1218,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
!fdm_add(fdm, delay_upper_fd, EPOLLIN, &fdm_delayed_render, term) ||
|
||||
!fdm_add(fdm, app_sync_updates_fd, EPOLLIN, &fdm_app_sync_updates_timeout, term) ||
|
||||
!fdm_add(fdm, title_update_fd, EPOLLIN, &fdm_title_update_timeout, term) ||
|
||||
!fdm_add(fdm, icon_update_fd, EPOLLIN, &fdm_icon_update_timeout, term) ||
|
||||
!fdm_add(fdm, app_id_update_fd, EPOLLIN, &fdm_app_id_update_timeout, term))
|
||||
{
|
||||
goto err;
|
||||
|
|
@ -1288,6 +1320,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
.title = {
|
||||
.timer_fd = title_update_fd,
|
||||
},
|
||||
.icon = {
|
||||
.timer_fd = icon_update_fd,
|
||||
},
|
||||
.app_id = {
|
||||
.timer_fd = app_id_update_fd,
|
||||
},
|
||||
|
|
@ -1406,6 +1441,7 @@ close_fds:
|
|||
fdm_del(fdm, delay_upper_fd);
|
||||
fdm_del(fdm, app_sync_updates_fd);
|
||||
fdm_del(fdm, title_update_fd);
|
||||
fdm_del(fdm, icon_update_fd);
|
||||
fdm_del(fdm, app_id_update_fd);
|
||||
|
||||
free(term);
|
||||
|
|
@ -1626,6 +1662,7 @@ term_shutdown(struct terminal *term)
|
|||
fdm_del(term->fdm, term->selection.auto_scroll.fd);
|
||||
fdm_del(term->fdm, term->render.app_sync_updates.timer_fd);
|
||||
fdm_del(term->fdm, term->render.app_id.timer_fd);
|
||||
fdm_del(term->fdm, term->render.icon.timer_fd);
|
||||
fdm_del(term->fdm, term->render.title.timer_fd);
|
||||
fdm_del(term->fdm, term->delayed_render_timer.lower_fd);
|
||||
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
||||
|
|
@ -1677,6 +1714,7 @@ term_shutdown(struct terminal *term)
|
|||
term->selection.auto_scroll.fd = -1;
|
||||
term->render.app_sync_updates.timer_fd = -1;
|
||||
term->render.app_id.timer_fd = -1;
|
||||
term->render.icon.timer_fd = -1;
|
||||
term->render.title.timer_fd = -1;
|
||||
term->delayed_render_timer.lower_fd = -1;
|
||||
term->delayed_render_timer.upper_fd = -1;
|
||||
|
|
@ -1731,6 +1769,7 @@ term_destroy(struct terminal *term)
|
|||
fdm_del(term->fdm, term->selection.auto_scroll.fd);
|
||||
fdm_del(term->fdm, term->render.app_sync_updates.timer_fd);
|
||||
fdm_del(term->fdm, term->render.app_id.timer_fd);
|
||||
fdm_del(term->fdm, term->render.icon.timer_fd);
|
||||
fdm_del(term->fdm, term->render.title.timer_fd);
|
||||
fdm_del(term->fdm, term->delayed_render_timer.lower_fd);
|
||||
fdm_del(term->fdm, term->delayed_render_timer.upper_fd);
|
||||
|
|
@ -2007,6 +2046,7 @@ term_reset(struct terminal *term, bool hard)
|
|||
term->saved_charsets = term->charsets;
|
||||
tll_free_and_free(term->window_title_stack, free);
|
||||
term_set_window_title(term, term->conf->title);
|
||||
term_set_app_id(term, NULL);
|
||||
|
||||
term_set_user_mouse_cursor(term, NULL);
|
||||
|
||||
|
|
@ -3528,7 +3568,7 @@ term_set_window_title(struct terminal *term, const char *title)
|
|||
if (term->window_title != NULL && streq(term->window_title, title))
|
||||
return;
|
||||
|
||||
if (mbsntoc32(NULL, title, strlen(title), 0) == (size_t)-1) {
|
||||
if (!is_valid_utf8(title)) {
|
||||
/* It's an xdg_toplevel::set_title() protocol violation to set
|
||||
a title with an invalid UTF-8 sequence */
|
||||
LOG_WARN("%s: title is not valid UTF-8, ignoring", title);
|
||||
|
|
@ -3548,9 +3588,14 @@ term_set_app_id(struct terminal *term, const char *app_id)
|
|||
app_id = NULL;
|
||||
if (term->app_id == NULL && app_id == NULL)
|
||||
return;
|
||||
if (term->app_id != NULL && app_id != NULL && strcmp(term->app_id, app_id) == 0)
|
||||
if (term->app_id != NULL && app_id != NULL && streq(term->app_id, app_id))
|
||||
return;
|
||||
|
||||
if (app_id != NULL && !is_valid_utf8(app_id)) {
|
||||
LOG_WARN("%s: app-id is not valid UTF-8, ignoring", app_id);
|
||||
return;
|
||||
}
|
||||
|
||||
free(term->app_id);
|
||||
if (app_id != NULL) {
|
||||
term->app_id = xstrdup(app_id);
|
||||
|
|
@ -3558,6 +3603,24 @@ term_set_app_id(struct terminal *term, const char *app_id)
|
|||
term->app_id = NULL;
|
||||
}
|
||||
render_refresh_app_id(term);
|
||||
render_refresh_icon(term);
|
||||
}
|
||||
|
||||
const char *
|
||||
term_icon(const struct terminal *term)
|
||||
{
|
||||
const char *app_id =
|
||||
term->app_id != NULL ? term->app_id : term->conf->app_id;
|
||||
|
||||
return
|
||||
#if 0
|
||||
term->window_icon != NULL
|
||||
? term->window_icon
|
||||
:
|
||||
#endif
|
||||
streq(app_id, "footclient")
|
||||
? "foot"
|
||||
: app_id;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -552,6 +552,8 @@ struct terminal {
|
|||
bool window_title_has_been_set;
|
||||
char *window_title;
|
||||
tll(char *) window_title_stack;
|
||||
//char *window_icon; /* No escape sequence available to set the icon */
|
||||
//tll(char *)window_icon_stack;
|
||||
char *app_id;
|
||||
|
||||
struct {
|
||||
|
|
@ -670,6 +672,11 @@ struct terminal {
|
|||
int timer_fd;
|
||||
} title;
|
||||
|
||||
struct {
|
||||
struct timespec last_update;
|
||||
int timer_fd;
|
||||
} icon;
|
||||
|
||||
struct {
|
||||
struct timespec last_update;
|
||||
int timer_fd;
|
||||
|
|
@ -925,6 +932,7 @@ void term_set_user_mouse_cursor(struct terminal *term, const char *cursor);
|
|||
|
||||
void term_set_window_title(struct terminal *term, const char *title);
|
||||
void term_set_app_id(struct terminal *term, const char *app_id);
|
||||
const char *term_icon(const struct terminal *term);
|
||||
void term_flash(struct terminal *term, unsigned duration_ms);
|
||||
void term_bell(struct terminal *term);
|
||||
bool term_spawn_new(const struct terminal *term);
|
||||
|
|
|
|||
50
wayland.c
50
wayland.c
|
|
@ -1363,6 +1363,17 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
&wp_single_pixel_buffer_manager_v1_interface, required);
|
||||
}
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
else if (streq(interface, xdg_toplevel_icon_v1_interface.name)) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->toplevel_icon_manager = wl_registry_bind(
|
||||
wayl->registry, name, &xdg_toplevel_icon_v1_interface, required);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
else if (streq(interface, zwp_text_input_manager_v3_interface.name)) {
|
||||
const uint32_t required = 1;
|
||||
|
|
@ -1581,27 +1592,33 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (presentation_timings && wayl->presentation == NULL) {
|
||||
LOG_ERR("compositor does not implement the presentation time interface");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wayl->primary_selection_device_manager == NULL)
|
||||
LOG_WARN("no primary selection available");
|
||||
LOG_WARN("compositor does not implement the primary selection interface");
|
||||
|
||||
if (wayl->xdg_activation == NULL) {
|
||||
LOG_WARN(
|
||||
"no XDG activation support; "
|
||||
"compositor does not implement XDG activation, "
|
||||
"bell.urgent will fall back to coloring the window margins red");
|
||||
}
|
||||
|
||||
if (wayl->fractional_scale_manager == NULL || wayl->viewporter == NULL)
|
||||
LOG_WARN("fractional scaling not available");
|
||||
LOG_WARN("compositor does not implement fractional scaling");
|
||||
|
||||
if (wayl->cursor_shape_manager == NULL) {
|
||||
LOG_WARN("no server-side cursors available, "
|
||||
LOG_WARN("compositor does not implement server-side cursors, "
|
||||
"falling back to client-side cursors");
|
||||
}
|
||||
|
||||
if (presentation_timings && wayl->presentation == NULL) {
|
||||
LOG_ERR("presentation time interface not implemented by compositor");
|
||||
goto out;
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
if (wayl->toplevel_icon_manager == NULL) {
|
||||
LOG_WARN("compositor does not implement the XDG toplevel icon protocol");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
if (wayl->text_input_manager == NULL) {
|
||||
|
|
@ -1679,6 +1696,10 @@ wayl_destroy(struct wayland *wayl)
|
|||
zwp_text_input_manager_v3_destroy(wayl->text_input_manager);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
if (wayl->toplevel_icon_manager != NULL)
|
||||
xdg_toplevel_icon_manager_v1_destroy(wayl->toplevel_icon_manager);
|
||||
#endif
|
||||
if (wayl->single_pixel_manager != NULL)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(wayl->single_pixel_manager);
|
||||
if (wayl->fractional_scale_manager != NULL)
|
||||
|
|
@ -1796,6 +1817,21 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
|
||||
xdg_toplevel_set_app_id(win->xdg_toplevel, conf->app_id);
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
if (wayl->toplevel_icon_manager != NULL) {
|
||||
const char *app_id =
|
||||
term->app_id != NULL ? term->app_id : term->conf->app_id;
|
||||
|
||||
struct xdg_toplevel_icon_v1 *icon =
|
||||
xdg_toplevel_icon_manager_v1_create_icon(wayl->toplevel_icon_manager);
|
||||
xdg_toplevel_icon_v1_set_name(icon, streq(
|
||||
app_id, "footclient") ? "foot" : app_id);
|
||||
xdg_toplevel_icon_manager_v1_set_icon(
|
||||
wayl->toplevel_icon_manager, win->xdg_toplevel, icon);
|
||||
xdg_toplevel_icon_v1_destroy(icon);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (conf->csd.preferred == CONF_CSD_PREFER_NONE) {
|
||||
/* User specifically do *not* want decorations */
|
||||
win->csd_mode = CSD_NO;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#include <xdg-output-unstable-v1.h>
|
||||
#include <xdg-shell.h>
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
#include <xdg-toplevel-icon-v1.h>
|
||||
#endif
|
||||
|
||||
#include <fcft/fcft.h>
|
||||
#include <tllist.h>
|
||||
|
||||
|
|
@ -443,6 +447,10 @@ struct wayland {
|
|||
|
||||
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
|
||||
|
||||
#if defined(HAVE_XDG_TOPLEVEL_ICON)
|
||||
struct xdg_toplevel_icon_manager_v1 *toplevel_icon_manager;
|
||||
#endif
|
||||
|
||||
bool presentation_timings;
|
||||
struct wp_presentation *presentation;
|
||||
uint32_t presentation_clock_id;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue