mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-30 11:10:23 -04:00
Merge branch 'launch-new-instance'
This commit is contained in:
commit
0bb15d3d16
7 changed files with 159 additions and 5 deletions
5
input.c
5
input.c
|
|
@ -282,6 +282,11 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
search_begin(term);
|
search_begin(term);
|
||||||
goto maybe_repeat;
|
goto maybe_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (sym == XKB_KEY_Return) {
|
||||||
|
term_spawn_new(term);
|
||||||
|
goto maybe_repeat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
5
main.c
5
main.c
|
|
@ -223,8 +223,9 @@ main(int argc, char *const *argv)
|
||||||
if ((wayl = wayl_init(fdm)) == NULL)
|
if ((wayl = wayl_init(fdm)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!as_server && (term = term_init(&conf, fdm, wayl, conf.term, argc, argv,
|
if (!as_server && (term = term_init(
|
||||||
&term_shutdown_cb, &shutdown_ctx)) == NULL)
|
&conf, fdm, wayl, conf.term, "foot", argc, argv,
|
||||||
|
&term_shutdown_cb, &shutdown_ctx)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (as_server && (server = server_init(&conf, fdm, wayl)) == NULL)
|
if (as_server && (server = server_init(&conf, fdm, wayl)) == NULL)
|
||||||
|
|
|
||||||
65
osc.c
65
osc.c
|
|
@ -298,6 +298,66 @@ parse_rgb(const char *string, uint32_t *color)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t
|
||||||
|
nibble2hex(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case '0' ... '9': return c - '0';
|
||||||
|
case 'a' ... 'f': return c - 'a' + 10;
|
||||||
|
case 'A' ... 'F': return c - 'A' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
osc_set_pwd(struct terminal *term, char *string)
|
||||||
|
{
|
||||||
|
LOG_DBG("PWD: URI: %s", string);
|
||||||
|
|
||||||
|
if (memcmp(string, "file://", 7) != 0)
|
||||||
|
return;
|
||||||
|
string += 7;
|
||||||
|
|
||||||
|
/* Skip past hostname */
|
||||||
|
if ((string = strchr(string, '/')) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Decode %xx encoded characters */
|
||||||
|
char *pwd = malloc(strlen(string) + 1);
|
||||||
|
char *p = pwd;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
/* Find next '%' */
|
||||||
|
char *next = strchr(string, '%');
|
||||||
|
|
||||||
|
if (next == NULL) {
|
||||||
|
strcpy(p, string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy everything leading up to the '%' */
|
||||||
|
size_t prefix_len = next - string;
|
||||||
|
memcpy(p, string, prefix_len);
|
||||||
|
p += prefix_len;
|
||||||
|
|
||||||
|
if (isxdigit(next[1]) && isxdigit(next[2])) {
|
||||||
|
*p++ = nibble2hex(next[1]) << 4 | nibble2hex(next[2]);
|
||||||
|
*p = '\0';
|
||||||
|
string = next + 3;
|
||||||
|
} else {
|
||||||
|
*p++ = *next;
|
||||||
|
*p = '\0';
|
||||||
|
string = next + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("PWD: decoded: %s", pwd);
|
||||||
|
free(term->cwd);
|
||||||
|
term->cwd = pwd;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
osc_notify(struct terminal *term, char *string)
|
osc_notify(struct terminal *term, char *string)
|
||||||
|
|
@ -396,6 +456,11 @@ osc_dispatch(struct terminal *term)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
/* Update terminal's understanding of PWD */
|
||||||
|
osc_set_pwd(term, string);
|
||||||
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
case 11: {
|
case 11: {
|
||||||
/* Set default foreground/background color */
|
/* Set default foreground/background color */
|
||||||
|
|
|
||||||
2
server.c
2
server.c
|
|
@ -213,7 +213,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data)
|
||||||
client->term = term_init(
|
client->term = term_init(
|
||||||
server->conf, server->fdm, server->wayl,
|
server->conf, server->fdm, server->wayl,
|
||||||
strlen(term_env) > 0 ? term_env : server->conf->term,
|
strlen(term_env) > 0 ? term_env : server->conf->term,
|
||||||
argc, argv, &term_shutdown_handler, client);
|
"footclient", argc, argv, &term_shutdown_handler, client);
|
||||||
|
|
||||||
if (client->term == NULL) {
|
if (client->term == NULL) {
|
||||||
LOG_ERR("failed to instantiate new terminal");
|
LOG_ERR("failed to instantiate new terminal");
|
||||||
|
|
|
||||||
1
slave.c
1
slave.c
|
|
@ -64,6 +64,7 @@ err:
|
||||||
close(pts);
|
close(pts);
|
||||||
if (ptmx != -1)
|
if (ptmx != -1)
|
||||||
close(ptmx);
|
close(ptmx);
|
||||||
|
close(err_fd);
|
||||||
_exit(errno);
|
_exit(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
80
terminal.c
80
terminal.c
|
|
@ -465,7 +465,7 @@ initialize_fonts(struct terminal *term, const struct config *conf)
|
||||||
|
|
||||||
struct terminal *
|
struct terminal *
|
||||||
term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
const char *term_env, int argc, char *const *argv,
|
const char *term_env, const char *foot_exe, int argc, char *const *argv,
|
||||||
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data)
|
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data)
|
||||||
{
|
{
|
||||||
int ptmx = -1;
|
int ptmx = -1;
|
||||||
|
|
@ -600,8 +600,19 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
},
|
},
|
||||||
.shutdown_cb = shutdown_cb,
|
.shutdown_cb = shutdown_cb,
|
||||||
.shutdown_data = shutdown_data,
|
.shutdown_data = shutdown_data,
|
||||||
|
.foot_exe = strdup(foot_exe),
|
||||||
|
.cwd = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t buf_len = 1024;
|
||||||
|
do {
|
||||||
|
term->cwd = realloc(term->cwd, buf_len);
|
||||||
|
getcwd(term->cwd, buf_len);
|
||||||
|
buf_len *= 2;
|
||||||
|
} while (errno == ERANGE);
|
||||||
|
}
|
||||||
|
|
||||||
initialize_color_cube(term);
|
initialize_color_cube(term);
|
||||||
if (!initialize_render_workers(term))
|
if (!initialize_render_workers(term))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -831,6 +842,9 @@ term_destroy(struct terminal *term)
|
||||||
tll_free(term->ptmx_buffer);
|
tll_free(term->ptmx_buffer);
|
||||||
tll_free(term->tab_stops);
|
tll_free(term->tab_stops);
|
||||||
|
|
||||||
|
free(term->foot_exe);
|
||||||
|
free(term->cwd);
|
||||||
|
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (term->slave > 0) {
|
if (term->slave > 0) {
|
||||||
|
|
@ -1642,3 +1656,67 @@ term_flash(struct terminal *term, unsigned duration_ms)
|
||||||
term->flash.active = true;
|
term->flash.active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
term_spawn_new(const struct terminal *term)
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
LOG_ERRNO("failed to fork new terminal");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
/* Child */
|
||||||
|
int pipe_fds[2] = {-1, -1};
|
||||||
|
if (pipe2(pipe_fds, O_CLOEXEC) < 0) {
|
||||||
|
LOG_ERRNO("failed to create pipe");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Double fork */
|
||||||
|
pid_t pid2 = fork();
|
||||||
|
if (pid2 < 0) {
|
||||||
|
LOG_ERRNO("failed to double fork new terminal");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid2 == 0) {
|
||||||
|
/* Child */
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
chdir(term->cwd);
|
||||||
|
execlp(term->foot_exe, term->foot_exe, NULL);
|
||||||
|
write(pipe_fds[1], &errno, sizeof(errno));
|
||||||
|
_exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parent */
|
||||||
|
|
||||||
|
close(pipe_fds[1]);
|
||||||
|
|
||||||
|
int _errno;
|
||||||
|
static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch");
|
||||||
|
|
||||||
|
ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno));
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
_exit(0);
|
||||||
|
else if (ret < 0)
|
||||||
|
LOG_ERRNO("failed to read from pipe");
|
||||||
|
else {
|
||||||
|
LOG_ERRNO_P("%s: failed to spawn new terminal", _errno, term->foot_exe);
|
||||||
|
errno = _errno;
|
||||||
|
waitpid(pid2, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (pipe_fds[0] != -1)
|
||||||
|
close(pipe_fds[0]);
|
||||||
|
_exit(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
waitpid(pid, &result, 0);
|
||||||
|
return WIFEXITED(result) && WEXITSTATUS(result) == 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,12 +314,15 @@ struct terminal {
|
||||||
bool is_shutting_down;
|
bool is_shutting_down;
|
||||||
void (*shutdown_cb)(void *data, int exit_code);
|
void (*shutdown_cb)(void *data, int exit_code);
|
||||||
void *shutdown_data;
|
void *shutdown_data;
|
||||||
|
|
||||||
|
char *foot_exe;
|
||||||
|
char *cwd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config;
|
struct config;
|
||||||
struct terminal *term_init(
|
struct terminal *term_init(
|
||||||
const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
const struct config *conf, struct fdm *fdm, struct wayland *wayl,
|
||||||
const char *term_env, int argc, char *const *argv,
|
const char *term_env, const char *foot_exe, int argc, char *const *argv,
|
||||||
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
|
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
|
||||||
|
|
||||||
bool term_shutdown(struct terminal *term);
|
bool term_shutdown(struct terminal *term);
|
||||||
|
|
@ -379,3 +382,4 @@ void term_xcursor_update(struct terminal *term);
|
||||||
|
|
||||||
void term_set_window_title(struct terminal *term, const char *title);
|
void term_set_window_title(struct terminal *term, const char *title);
|
||||||
void term_flash(struct terminal *term, unsigned duration_ms);
|
void term_flash(struct terminal *term, unsigned duration_ms);
|
||||||
|
bool term_spawn_new(const struct terminal *term);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue