provide I3_WINDOW_ID to processes called with exec when possible (#6160)

fixes #1729
This commit is contained in:
Jesse Luehrs
2025-12-20 02:04:30 -05:00
committed by GitHub
parent cbe78b4e55
commit 0e2e8290f2
5 changed files with 43 additions and 6 deletions

View File

@ -30,7 +30,7 @@
* (and ID) should be created, which is the default and encouraged behavior.
*
*/
void start_application(const char *command, bool no_startup_id);
void start_application(const char *command, bool no_startup_id, xcb_window_t window_id);
/**
* Deletes a startup sequence, ignoring whether its timeout has elapsed.

View File

@ -1262,7 +1262,9 @@ void cmd_exec(I3_CMD, const char *nosn, const char *command) {
TAILQ_FOREACH (current, &OWINDOWS, owindows) {
DLOG("should execute %s, no_startup_id = %d\n", command, no_startup_id);
start_application(command, no_startup_id);
start_application(
command, no_startup_id,
current->con->window == NULL ? XCB_NONE : current->con->window->id);
}
ysuccess(true);

View File

@ -1175,7 +1175,7 @@ int main(int argc, char *argv[]) {
struct Autostart *exec = TAILQ_FIRST(&autostarts);
LOG("auto-starting %s\n", exec->command);
start_application(exec->command, exec->no_startup_id);
start_application(exec->command, exec->no_startup_id, XCB_NONE);
FREE(exec->command);
TAILQ_REMOVE(&autostarts, exec, autostarts);
@ -1188,7 +1188,7 @@ int main(int argc, char *argv[]) {
struct Autostart *exec_always = TAILQ_FIRST(&autostarts_always);
LOG("auto-starting (always!) %s\n", exec_always->command);
start_application(exec_always->command, exec_always->no_startup_id);
start_application(exec_always->command, exec_always->no_startup_id, XCB_NONE);
FREE(exec_always->command);
TAILQ_REMOVE(&autostarts_always, exec_always, autostarts_always);
@ -1204,7 +1204,7 @@ int main(int argc, char *argv[]) {
barconfig->verbose ? "-V" : "",
barconfig->id, current_socketpath);
LOG("Starting bar process: %s\n", command);
start_application(command, true);
start_application(command, true, XCB_NONE);
free(command);
}

View File

@ -129,8 +129,11 @@ void startup_sequence_delete(struct Startup_Sequence *sequence) {
* The no_startup_id flag determines whether a startup notification context
* (and ID) should be created, which is the default and encouraged behavior.
*
* The window_id, if given, will be provided to the child process via the
* I3_WINDOW_ID environment variable.
*
*/
void start_application(const char *command, bool no_startup_id) {
void start_application(const char *command, bool no_startup_id, xcb_window_t window_id) {
SnLauncherContext *context = NULL;
if (!no_startup_id) {
@ -194,6 +197,13 @@ void start_application(const char *command, bool no_startup_id) {
}
setenv("I3SOCK", current_socketpath, 1);
if (window_id != XCB_NONE) {
char *window_id_str;
sasprintf(&window_id_str, "%d", window_id);
setenv("I3_WINDOW_ID", window_id_str, 1);
free(window_id_str);
}
execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL);
err(EXIT_FAILURE, "execl return"); /* only reached on error */
}

View File

@ -15,10 +15,15 @@
# (unless you are already familiar with Perl)
#
use i3test i3_autostart => 0;
use POSIX qw(mkfifo);
use File::Temp qw(:POSIX);
use X11::XCB qw(PROP_MODE_REPLACE);
my (@nodes);
my $exec_tmp = tmpnam();
mkfifo($exec_tmp, 0600) or BAIL_OUT "Could not create FIFO in $exec_tmp: $!";
my $config = <<'EOT';
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
@ -51,6 +56,11 @@ for_window [window_role="i3test"] border none
for_window [workspace="trigger"] floating enable, mark triggered
EOT
$config .= <<EOT;
# test 13
for_window [class="exec"] exec echo "\$I3_WINDOW_ID" > "$exec_tmp"
EOT
# test all window types
my %window_types = (
'normal' => '_NET_WM_WINDOW_TYPE_NORMAL',
@ -390,6 +400,21 @@ is_deeply($nodes[0]->{nodes}[0]->{marks}, [ 'triggered' ], "mark set for workspa
kill_all_windows;
##############################################################
# 13: check that we pass $I3_WINDOW_ID to exec'ed subprocesses
##############################################################
$window = open_window(wm_class => 'exec');
open my $fh, '<', $exec_tmp
or die "couldn't open FIFO $exec_tmp for reading: $!";
chomp(my $window_id = do { local $/; <$fh> });
is($window_id, $window->id, "got the expected window id from \$I3_WINDOW_ID");
kill_all_windows;
unlink($exec_tmp);
##############################################################
exit_gracefully($pid);