Merge branch 'exec_nosn' into next
This commit is contained in:
commit
704c9967b2
|
@ -541,16 +541,21 @@ keyword. These commands will be run in order.
|
||||||
|
|
||||||
*Syntax*:
|
*Syntax*:
|
||||||
-------------------
|
-------------------
|
||||||
exec command
|
exec [--no-startup-id] command
|
||||||
exec_always command
|
exec_always [--no-startup-id] command
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
*Examples*:
|
*Examples*:
|
||||||
--------------------------------
|
--------------------------------
|
||||||
exec chromium
|
exec chromium
|
||||||
exec_always ~/my_script.sh
|
exec_always ~/my_script.sh
|
||||||
|
|
||||||
|
# Execute the terminal emulator urxvt, which is not yet startup-notification aware.
|
||||||
|
exec --no-startup-id urxvt
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
The flag --no-startup-id is explained in <<exec>>.
|
||||||
|
|
||||||
[[workspace_screen]]
|
[[workspace_screen]]
|
||||||
|
|
||||||
=== Automatically putting workspaces on specific screens
|
=== Automatically putting workspaces on specific screens
|
||||||
|
@ -1034,6 +1039,37 @@ The criteria +class+, +instance+, +role+, +title+ and +mark+ are actually
|
||||||
regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for
|
regular expressions (PCRE). See +pcresyntax(3)+ or +perldoc perlre+ for
|
||||||
information on how to use them.
|
information on how to use them.
|
||||||
|
|
||||||
|
[[exec]]
|
||||||
|
|
||||||
|
=== Executing applications (exec)
|
||||||
|
|
||||||
|
What good is a window manager if you can’t actually start any applications?
|
||||||
|
The exec command starts an application by passing the command you specify to a
|
||||||
|
shell. This implies that you can use globbing (wildcards) and programs will be
|
||||||
|
searched in your $PATH.
|
||||||
|
|
||||||
|
*Syntax*:
|
||||||
|
------------------------------
|
||||||
|
exec [--no-startup-id] command
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
*Example*:
|
||||||
|
------------------------------
|
||||||
|
# Start the GIMP
|
||||||
|
bindsym mod+g exec gimp
|
||||||
|
|
||||||
|
# Start the terminal emulator urxvt which is not yet startup-notification-aware
|
||||||
|
bindsym mod+enter exec --no-startup-id urxvt
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
The +--no-startup-id+ parameter disables startup-notification support for this
|
||||||
|
particular exec command. With startup-notification, i3 can make sure that a
|
||||||
|
window appears on the workspace on which you used the exec command. Also, it
|
||||||
|
will change the X11 cursor to +watch+ (a clock) while the application is
|
||||||
|
launching. So, if an application is not startup-notification aware (most GTK
|
||||||
|
and Qt using applications seem to be, though), you will end up with a watch
|
||||||
|
cursor for 60 seconds.
|
||||||
|
|
||||||
=== Splitting containers
|
=== Splitting containers
|
||||||
|
|
||||||
The split command makes the current window a split container. Split containers
|
The split command makes the current window a split container. Split containers
|
||||||
|
|
|
@ -218,6 +218,9 @@ struct Binding {
|
||||||
struct Autostart {
|
struct Autostart {
|
||||||
/** Command, like in command mode */
|
/** Command, like in command mode */
|
||||||
char *command;
|
char *command;
|
||||||
|
/** no_startup_id flag for start_application(). Determines whether a
|
||||||
|
* startup notification context/ID should be created. */
|
||||||
|
bool no_startup_id;
|
||||||
TAILQ_ENTRY(Autostart) autostarts;
|
TAILQ_ENTRY(Autostart) autostarts;
|
||||||
TAILQ_ENTRY(Autostart) autostarts_always;
|
TAILQ_ENTRY(Autostart) autostarts_always;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,8 +25,11 @@
|
||||||
* The shell is determined by looking for the SHELL environment variable. If
|
* The shell is determined by looking for the SHELL environment variable. If
|
||||||
* it does not exist, /bin/sh is used.
|
* it does not exist, /bin/sh is used.
|
||||||
*
|
*
|
||||||
|
* The no_startup_id flag determines whether a startup notification context
|
||||||
|
* (and ID) should be created, which is the default and encouraged behavior.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void start_application(const char *command);
|
void start_application(const char *command, bool no_startup_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by libstartup-notification when something happens
|
* Called by libstartup-notification when something happens
|
||||||
|
|
|
@ -1507,8 +1507,19 @@ restart_state:
|
||||||
exec:
|
exec:
|
||||||
TOKEXEC STR
|
TOKEXEC STR
|
||||||
{
|
{
|
||||||
|
char *command = $2;
|
||||||
|
bool no_startup_id = false;
|
||||||
|
if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) {
|
||||||
|
no_startup_id = true;
|
||||||
|
/* We need to make a copy here, otherwise we leak the
|
||||||
|
* --no-startup-id bytes in the beginning of the string */
|
||||||
|
command = sstrdup(command + strlen("--no-startup-id "));
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
|
||||||
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
||||||
new->command = $2;
|
new->command = command;
|
||||||
|
new->no_startup_id = no_startup_id;
|
||||||
TAILQ_INSERT_TAIL(&autostarts, new, autostarts);
|
TAILQ_INSERT_TAIL(&autostarts, new, autostarts);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -1516,8 +1527,19 @@ exec:
|
||||||
exec_always:
|
exec_always:
|
||||||
TOKEXEC_ALWAYS STR
|
TOKEXEC_ALWAYS STR
|
||||||
{
|
{
|
||||||
|
char *command = $2;
|
||||||
|
bool no_startup_id = false;
|
||||||
|
if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) {
|
||||||
|
no_startup_id = true;
|
||||||
|
/* We need to make a copy here, otherwise we leak the
|
||||||
|
* --no-startup-id bytes in the beginning of the string */
|
||||||
|
command = sstrdup(command + strlen("--no-startup-id "));
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
|
||||||
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
struct Autostart *new = smalloc(sizeof(struct Autostart));
|
||||||
new->command = $2;
|
new->command = command;
|
||||||
|
new->no_startup_id = no_startup_id;
|
||||||
TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always);
|
TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -389,8 +389,15 @@ operation:
|
||||||
exec:
|
exec:
|
||||||
TOK_EXEC STR
|
TOK_EXEC STR
|
||||||
{
|
{
|
||||||
printf("should execute %s\n", $2);
|
char *command = $2;
|
||||||
start_application($2);
|
bool no_startup_id = false;
|
||||||
|
if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) {
|
||||||
|
no_startup_id = true;
|
||||||
|
command += strlen("--no-startup-id ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("should execute %s, no_startup_id = %d\n", command, no_startup_id);
|
||||||
|
start_application(command, no_startup_id);
|
||||||
free($2);
|
free($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -635,7 +635,7 @@ int main(int argc, char *argv[]) {
|
||||||
struct Autostart *exec;
|
struct Autostart *exec;
|
||||||
TAILQ_FOREACH(exec, &autostarts, autostarts) {
|
TAILQ_FOREACH(exec, &autostarts, autostarts) {
|
||||||
LOG("auto-starting %s\n", exec->command);
|
LOG("auto-starting %s\n", exec->command);
|
||||||
start_application(exec->command);
|
start_application(exec->command, exec->no_startup_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ int main(int argc, char *argv[]) {
|
||||||
struct Autostart *exec_always;
|
struct Autostart *exec_always;
|
||||||
TAILQ_FOREACH(exec_always, &autostarts_always, autostarts_always) {
|
TAILQ_FOREACH(exec_always, &autostarts_always, autostarts_always) {
|
||||||
LOG("auto-starting (always!) %s\n", exec_always->command);
|
LOG("auto-starting (always!) %s\n", exec_always->command);
|
||||||
start_application(exec_always->command);
|
start_application(exec_always->command, exec_always->no_startup_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start i3bar processes for all configured bars */
|
/* Start i3bar processes for all configured bars */
|
||||||
|
@ -653,7 +653,7 @@ int main(int argc, char *argv[]) {
|
||||||
sasprintf(&command, "i3bar --bar_id=%s --socket=\"%s\"",
|
sasprintf(&command, "i3bar --bar_id=%s --socket=\"%s\"",
|
||||||
barconfig->id, current_socketpath);
|
barconfig->id, current_socketpath);
|
||||||
LOG("Starting bar process: %s\n", command);
|
LOG("Starting bar process: %s\n", command);
|
||||||
start_application(command);
|
start_application(command, true);
|
||||||
free(command);
|
free(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,16 @@ static void startup_timeout(EV_P_ ev_timer *w, int revents) {
|
||||||
* The shell is determined by looking for the SHELL environment variable. If it
|
* The shell is determined by looking for the SHELL environment variable. If it
|
||||||
* does not exist, /bin/sh is used.
|
* does not exist, /bin/sh is used.
|
||||||
*
|
*
|
||||||
|
* The no_startup_id flag determines whether a startup notification context
|
||||||
|
* (and ID) should be created, which is the default and encouraged behavior.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void start_application(const char *command) {
|
void start_application(const char *command, bool no_startup_id) {
|
||||||
|
SnLauncherContext *context;
|
||||||
|
|
||||||
|
if (!no_startup_id) {
|
||||||
/* Create a startup notification context to monitor the progress of this
|
/* Create a startup notification context to monitor the progress of this
|
||||||
* startup. */
|
* startup. */
|
||||||
SnLauncherContext *context;
|
|
||||||
context = sn_launcher_context_new(sndisplay, conn_screen);
|
context = sn_launcher_context_new(sndisplay, conn_screen);
|
||||||
sn_launcher_context_set_name(context, "i3");
|
sn_launcher_context_set_name(context, "i3");
|
||||||
sn_launcher_context_set_description(context, "exec command in i3");
|
sn_launcher_context_set_description(context, "exec command in i3");
|
||||||
|
@ -101,6 +106,7 @@ void start_application(const char *command) {
|
||||||
* the timeout. Even if the sequence gets completed, the timeout still
|
* the timeout. Even if the sequence gets completed, the timeout still
|
||||||
* needs the context (but will unref it then) */
|
* needs the context (but will unref it then) */
|
||||||
sn_launcher_context_ref(context);
|
sn_launcher_context_ref(context);
|
||||||
|
}
|
||||||
|
|
||||||
LOG("executing: %s\n", command);
|
LOG("executing: %s\n", command);
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
|
@ -108,6 +114,7 @@ void start_application(const char *command) {
|
||||||
setsid();
|
setsid();
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
/* Setup the environment variable(s) */
|
/* Setup the environment variable(s) */
|
||||||
|
if (!no_startup_id)
|
||||||
sn_launcher_context_setup_child_process(context);
|
sn_launcher_context_setup_child_process(context);
|
||||||
|
|
||||||
/* Stores the path of the shell */
|
/* Stores the path of the shell */
|
||||||
|
@ -125,11 +132,13 @@ void start_application(const char *command) {
|
||||||
}
|
}
|
||||||
wait(0);
|
wait(0);
|
||||||
|
|
||||||
|
if (!no_startup_id) {
|
||||||
/* Change the pointer of the root window to indicate progress */
|
/* Change the pointer of the root window to indicate progress */
|
||||||
if (xcursor_supported)
|
if (xcursor_supported)
|
||||||
xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
||||||
else xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
else xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by libstartup-notification when something happens
|
* Called by libstartup-notification when something happens
|
||||||
|
|
|
@ -53,6 +53,7 @@ sub activate_i3 {
|
||||||
if ($pid == 0) {
|
if ($pid == 0) {
|
||||||
$ENV{LISTEN_PID} = $$;
|
$ENV{LISTEN_PID} = $$;
|
||||||
$ENV{LISTEN_FDS} = 1;
|
$ENV{LISTEN_FDS} = 1;
|
||||||
|
delete $ENV{DESKTOP_STARTUP_ID};
|
||||||
$ENV{DISPLAY} = $args{display};
|
$ENV{DISPLAY} = $args{display};
|
||||||
$ENV{PATH} = join(':',
|
$ENV{PATH} = join(':',
|
||||||
'../i3-nagbar',
|
'../i3-nagbar',
|
||||||
|
|
|
@ -84,6 +84,8 @@ close($fh);
|
||||||
|
|
||||||
unlink($tmp);
|
unlink($tmp);
|
||||||
|
|
||||||
|
isnt($startup_id, '', 'startup_id not empty');
|
||||||
|
|
||||||
$ENV{DESKTOP_STARTUP_ID} = $startup_id;
|
$ENV{DESKTOP_STARTUP_ID} = $startup_id;
|
||||||
|
|
||||||
# Create a new libstartup-notification launchee context
|
# Create a new libstartup-notification launchee context
|
||||||
|
@ -132,4 +134,21 @@ sync_with_i3($x);
|
||||||
my $otherwin = open_window($x);
|
my $otherwin = open_window($x);
|
||||||
is(@{get_ws_content($second_ws)}, 1, 'one container on the second workspace');
|
is(@{get_ws_content($second_ws)}, 1, 'one container on the second workspace');
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# 3) test that the --no-startup-id flag for exec leads to no DESKTOP_STARTUP_ID
|
||||||
|
# environment variable.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
mkfifo($tmp, 0600) or die "Could not create FIFO in $tmp";
|
||||||
|
|
||||||
|
cmd qq|exec --no-startup-id echo \$DESKTOP_STARTUP_ID >$tmp|;
|
||||||
|
|
||||||
|
open($fh, '<', $tmp);
|
||||||
|
chomp($startup_id = <$fh>);
|
||||||
|
close($fh);
|
||||||
|
|
||||||
|
unlink($tmp);
|
||||||
|
|
||||||
|
is($startup_id, '', 'startup_id empty');
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
|
Loading…
Reference in New Issue