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)
+
+ +## Current Behavior + + +## Expected Behavior + + +## Reproduction Instructions + + +## Environment + +Output of `i3 --moreversion 2>&-`: +
+i3 version: 
+
+ + +
+
+ + +
+Logfile URL:
+
+ + +
+- 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