diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index b3290b956..726b40079 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -15,10 +15,16 @@ IMPORTANT NOTE: If your issue is not specific to any feature provided by i3-gaps
## Current Behavior
-
+
## Expected Behavior
-
+
## Reproduction Instructions
+
+## I'm submitting a…
+
+
+[x] Bug
+[ ] Feature Request
+[ ] Documentation Request
+[ ] Other (Please describe in detail)
+
+- Linux Distribution & Version:
+- Are you using a compositor (e.g., xcompmgr or compton):
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..e1c169a58
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,47 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+---
+
+
+
+## I'm submitting a…
+
+
+[ ] Bug
+[x] Feature Request
+[ ] Documentation Request
+[ ] Other (Please describe in detail)
+
+
+## Current Behavior
+
+
+## Desired Behavior
+
+
+## Environment
+
+Output of `i3 --moreversion 2>&-`:
+
+i3 version:
+
+
+
+
+- Linux Distribution & Version:
+- Are you using a compositor (e.g., xcompmgr or compton):
+
diff --git a/Makefile.am b/Makefile.am
index 09bbb6d50..7ca32506b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -301,6 +301,7 @@ libi3_a_SOURCES = \
libi3/fake_configure_notify.c \
libi3/font.c \
libi3/format_placeholders.c \
+ libi3/g_utf8_make_valid.c \
libi3/get_colorpixel.c \
libi3/get_config_path.c \
libi3/get_exe_path.c \
diff --git a/configure.ac b/configure.ac
index 1784fa83d..5cc9d4a69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,12 +110,27 @@ AC_PROG_MAKE_SET
AC_PROG_RANLIB
AC_PROG_LN_S
-AC_PATH_PROG([PATH_ASCIIDOC], [asciidoc])
-AC_PATH_PROG([PATH_XMLTO], [xmlto])
-AC_PATH_PROG([PATH_POD2MAN], [pod2man])
-
-AM_CONDITIONAL([BUILD_MANS], [test x$PATH_ASCIIDOC != x && test x$PATH_XMLTO != x && test x$PATH_POD2MAN != x])
-AM_CONDITIONAL([BUILD_DOCS], [test x$PATH_ASCIIDOC != x])
+AC_ARG_ENABLE(docs,
+ AS_HELP_STRING(
+ [--disable-docs],
+ [disable building documentation]),
+ [ax_docs=$enableval],
+ [ax_docs=yes])
+AC_ARG_ENABLE(mans,
+ AS_HELP_STRING(
+ [--disable-mans],
+ [disable building manual pages]),
+ [ax_mans=$enableval],
+ [ax_mans=yes])
+AS_IF([test x$ax_docs = xyes || test x$ax_mans = xyes], [
+ AC_PATH_PROG([PATH_ASCIIDOC], [asciidoc])
+])
+AS_IF([test x$ax_mans = xyes], [
+ AC_PATH_PROG([PATH_XMLTO], [xmlto])
+ AC_PATH_PROG([PATH_POD2MAN], [pod2man])
+])
+AM_CONDITIONAL([BUILD_MANS], [test x$ax_mans = xyes && test x$PATH_ASCIIDOC != x && test x$PATH_XMLTO != x && test x$PATH_POD2MAN != x])
+AM_CONDITIONAL([BUILD_DOCS], [test x$ax_docs = xyes && test x$PATH_ASCIIDOC != x])
AM_PROG_AR
diff --git a/debian/control b/debian/control
index 46e35dfea..71a2599c6 100644
--- a/debian/control
+++ b/debian/control
@@ -40,7 +40,7 @@ Description: metapackage (i3 window manager, screen locker, menu, statusbar)
Package: i3-wm
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, x11-utils
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
Provides: x-window-manager
Recommends: xfonts-base, fonts-dejavu-core, libanyevent-i3-perl (>= 0.12), libjson-xs-perl, rxvt-unicode | x-terminal-emulator
Description: improved dynamic tiling window manager
diff --git a/docs/userguide b/docs/userguide
index d24131fe3..2988209b6 100644
--- a/docs/userguide
+++ b/docs/userguide
@@ -755,14 +755,23 @@ set_from_resource $black i3wm.color0 #000000
To automatically make a specific window show up on a specific workspace, you
can use an *assignment*. You can match windows by using any criteria,
-see <>. It is recommended that you match on window classes
-(and instances, when appropriate) instead of window titles whenever possible
-because some applications first create their window, and then worry about
-setting the correct title. Firefox with Vimperator comes to mind. The window
-starts up being named Firefox, and only when Vimperator is loaded does the
-title change. As i3 will get the title as soon as the application maps the
-window (mapping means actually displaying it on the screen), you’d need to have
-to match on 'Firefox' in this case.
+see <>. The difference between +assign+ and
++for_window move to workspace+ is that the former will only be
+executed when the application maps the window (mapping means actually displaying
+it on the screen) but the latter will be executed whenever a window changes its
+properties to something that matches the specified criteria.
+
+Thus, it is recommended that you match on window classes (and instances, when
+appropriate) instead of window titles whenever possible because some
+applications first create their window, and then worry about setting the correct
+title. Firefox with Vimperator comes to mind. The window starts up being named
+Firefox, and only when Vimperator is loaded does the title change. As i3 will
+get the title as soon as the application maps the window, you’d need to have to
+match on 'Firefox' in this case.
+Another known issue is with Spotify, which doesn't set the class hints when
+mapping the window, meaning you'll have to use a +for_window+ rule to assign
+Spotify to a specific workspace.
+Finally, using +assign [tiling]+ and +assign [floating]+ is not supported.
You can also assign a window to show up on a specific output. You can use RandR
names such as +VGA1+ or names relative to the output with the currently focused
@@ -995,7 +1004,7 @@ ipc-socket ~/.i3/i3-ipc.sock
----------------------------
You can then use the +i3-msg+ application to perform any command listed in
-the next section.
+<>.
=== Focus follows mouse
@@ -1733,6 +1742,7 @@ bar {
}
--------------------------------------
+[[list_of_commands]]
== List of commands
Commands are what you bind to specific keypresses. You can also issue commands
diff --git a/etc/config b/etc/config
index 3be9831dd..da51d5703 100644
--- a/etc/config
+++ b/etc/config
@@ -147,7 +147,7 @@ bindsym Mod1+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym Mod1+Shift+r restart
# exit i3 (logs you out of your X session)
-bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"
+bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"
# resize window (you can also use the mouse for that)
mode "resize" {
diff --git a/etc/config.keycodes b/etc/config.keycodes
index 2d56876c2..6fc19426a 100644
--- a/etc/config.keycodes
+++ b/etc/config.keycodes
@@ -133,7 +133,7 @@ bindcode $mod+Shift+54 reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindcode $mod+Shift+27 restart
# exit i3 (logs you out of your X session)
-bindcode $mod+Shift+26 exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'"
+bindcode $mod+Shift+26 exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"
# resize window (you can also use the mouse for that)
mode "resize" {
diff --git a/i3-msg/main.c b/i3-msg/main.c
index 96edb2c3a..fe1114168 100644
--- a/i3-msg/main.c
+++ b/i3-msg/main.c
@@ -166,16 +166,18 @@ int main(int argc, char *argv[]) {
uint32_t message_type = I3_IPC_MESSAGE_TYPE_RUN_COMMAND;
char *payload = NULL;
bool quiet = false;
+ bool monitor = false;
static struct option long_options[] = {
{"socket", required_argument, 0, 's'},
{"type", required_argument, 0, 't'},
{"version", no_argument, 0, 'v'},
{"quiet", no_argument, 0, 'q'},
+ {"monitor", no_argument, 0, 'm'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}};
- char *options_string = "s:t:vhq";
+ char *options_string = "s:t:vhqm";
while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) {
if (o == 's') {
@@ -204,25 +206,34 @@ int main(int argc, char *argv[]) {
message_type = I3_IPC_MESSAGE_TYPE_GET_CONFIG;
} else if (strcasecmp(optarg, "send_tick") == 0) {
message_type = I3_IPC_MESSAGE_TYPE_SEND_TICK;
+ } else if (strcasecmp(optarg, "subscribe") == 0) {
+ message_type = I3_IPC_MESSAGE_TYPE_SUBSCRIBE;
} else {
printf("Unknown message type\n");
- printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config, send_tick\n");
+ printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config, send_tick, subscribe\n");
exit(EXIT_FAILURE);
}
} else if (o == 'q') {
quiet = true;
+ } else if (o == 'm') {
+ monitor = true;
} else if (o == 'v') {
printf("i3-msg " I3_VERSION "\n");
return 0;
} else if (o == 'h') {
printf("i3-msg " I3_VERSION "\n");
- printf("i3-msg [-s ] [-t ] \n");
+ printf("i3-msg [-s ] [-t ] [-m] \n");
return 0;
} else if (o == '?') {
exit(EXIT_FAILURE);
}
}
+ if (monitor && message_type != I3_IPC_MESSAGE_TYPE_SUBSCRIBE) {
+ fprintf(stderr, "The monitor option -m is used with -t SUBSCRIBE exclusively.\n");
+ exit(EXIT_FAILURE);
+ }
+
/* Use all arguments, separated by whitespace, as payload.
* This way, you don’t have to do i3-msg 'mark foo', you can use
* i3-msg mark foo */
@@ -246,9 +257,6 @@ int main(int argc, char *argv[]) {
err(EXIT_FAILURE, "IPC: write()");
free(payload);
- if (quiet)
- return 0;
-
uint32_t reply_length;
uint32_t reply_type;
uint8_t *reply;
@@ -275,8 +283,9 @@ int main(int argc, char *argv[]) {
errx(EXIT_FAILURE, "IPC: Could not parse JSON reply.");
}
- /* NB: We still fall-through and print the reply, because even if one
- * command failed, that doesn’t mean that all commands failed. */
+ if (!quiet) {
+ printf("%.*s\n", reply_length, reply);
+ }
} else if (reply_type == I3_IPC_REPLY_TYPE_CONFIG) {
yajl_handle handle = yajl_alloc(&config_callbacks, NULL, NULL);
yajl_status state = yajl_parse(handle, (const unsigned char *)reply, reply_length);
@@ -289,12 +298,30 @@ int main(int argc, char *argv[]) {
case yajl_status_error:
errx(EXIT_FAILURE, "IPC: Could not parse JSON reply.");
}
+ } else if (reply_type == I3_IPC_REPLY_TYPE_SUBSCRIBE) {
+ do {
+ free(reply);
+ if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
+ if (ret == -1)
+ err(EXIT_FAILURE, "IPC: read()");
+ exit(1);
+ }
- goto exit;
+ if (!(reply_type & I3_IPC_EVENT_MASK)) {
+ errx(EXIT_FAILURE, "IPC: Received reply of type %d but expected an event", reply_type);
+ }
+
+ if (!quiet) {
+ fprintf(stdout, "%.*s\n", reply_length, reply);
+ fflush(stdout);
+ }
+ } while (monitor);
+ } else {
+ if (!quiet) {
+ printf("%.*s\n", reply_length, reply);
+ }
}
- printf("%.*s\n", reply_length, reply);
-exit:
free(reply);
close(sockfd);
diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c
index 1d600c023..fd7acd6e7 100644
--- a/i3-nagbar/main.c
+++ b/i3-nagbar/main.c
@@ -55,6 +55,7 @@ typedef struct {
char *action;
int16_t x;
uint16_t width;
+ bool terminal;
} button_t;
static xcb_window_t win;
@@ -187,7 +188,11 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve
}
char *terminal_cmd;
- sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
+ if (button->terminal) {
+ sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path);
+ } else {
+ terminal_cmd = sstrdup(link_path);
+ }
printf("argv0 = %s\n", argv0);
printf("terminal_cmd = %s\n", terminal_cmd);
@@ -361,12 +366,13 @@ int main(int argc, char *argv[]) {
{"version", no_argument, 0, 'v'},
{"font", required_argument, 0, 'f'},
{"button", required_argument, 0, 'b'},
+ {"button-no-terminal", required_argument, 0, 'B'},
{"help", no_argument, 0, 'h'},
{"message", required_argument, 0, 'm'},
{"type", required_argument, 0, 't'},
{0, 0, 0, 0}};
- char *options_string = "b:f:m:t:vh";
+ char *options_string = "b:B:f:m:t:vh";
prompt = i3string_from_utf8("Please do not run this program.");
@@ -388,12 +394,14 @@ int main(int argc, char *argv[]) {
break;
case 'h':
printf("i3-nagbar " I3_VERSION "\n");
- printf("i3-nagbar [-m ] [-b