Make i3 send arguments as command to a running i3 instance (like i3-msg)

From i3 --help:

If you pass plain text arguments, i3 will interpret them as a command
to send to a currently running i3 (like i3-msg). This allows you to
use nice and logical commands, such as:

	i3 border none
	i3 floating toggle
	i3 kill window
This commit is contained in:
Michael Stapelberg 2011-10-02 19:20:43 +01:00
parent 4243a4053e
commit b755397687
1 changed files with 70 additions and 0 deletions

View File

@ -3,6 +3,9 @@
*/
#include <ev.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "all.h"
#include "sd-daemon.h"
@ -281,10 +284,77 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "\n");
fprintf(stderr, "\t--get-socketpath\n"
"\tRetrieve the i3 IPC socket path from X11, print it, then exit.\n");
fprintf(stderr, "\n");
fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
"to send to a currently running i3 (like i3-msg). This allows you to\n"
"use nice and logical commands, such as:\n"
"\n"
"\ti3 border none\n"
"\ti3 floating toggle\n"
"\ti3 kill window\n"
"\n");
exit(EXIT_FAILURE);
}
}
/* If the user passes more arguments, we act like i3-msg would: Just send
* the arguments as an IPC message to i3. This allows for nice semantic
* commands such as 'i3 border none'. */
if (optind < argc) {
/* We enable verbose mode so that the user knows whats going on.
* This should make it easier to find mistakes when the user passes
* arguments by mistake. */
set_verbosity(true);
LOG("Additional arguments passed. Sending them as a command to i3.\n");
char *payload = NULL;
while (optind < argc) {
if (!payload) {
payload = sstrdup(argv[optind]);
} else {
char *both;
if (asprintf(&both, "%s %s", payload, argv[optind]) == -1)
err(EXIT_FAILURE, "asprintf");
free(payload);
payload = both;
}
optind++;
}
LOG("Command is: %s (%d bytes)\n", payload, strlen(payload));
char *socket_path = socket_path_from_x11();
if (!socket_path) {
ELOG("Could not get i3 IPC socket path\n");
return 1;
}
int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
if (sockfd == -1)
err(EXIT_FAILURE, "Could not create socket");
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_LOCAL;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
err(EXIT_FAILURE, "Could not connect to i3");
if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
(uint8_t*)payload) == -1)
err(EXIT_FAILURE, "IPC: write()");
uint32_t reply_length;
uint8_t *reply;
int ret;
if ((ret = ipc_recv_message(sockfd, I3_IPC_MESSAGE_TYPE_COMMAND,
&reply_length, &reply)) != 0) {
if (ret == -1)
err(EXIT_FAILURE, "IPC: read()");
return 1;
}
printf("%.*s\n", reply_length, reply);
return 0;
}
LOG("i3 (tree) version " I3_VERSION " starting\n");
conn = xcb_connect(NULL, &screens);