]> git.sur5r.net Git - i3/i3/commitdiff
Merge pull request #2959 from orestisf1993/issue-2764
authorIngo Bürk <admin@airblader.de>
Fri, 22 Sep 2017 14:24:26 +0000 (16:24 +0200)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2017 14:24:26 +0000 (16:24 +0200)
Allow assign to output

16 files changed:
AnyEvent-I3/MANIFEST
AnyEvent-I3/MANIFEST.SKIP
AnyEvent-I3/Makefile.PL
AnyEvent-I3/lib/AnyEvent/I3.pm
docs/ipc
i3-msg/main.c
i3bar/src/xcb.c
include/i3/ipc.h
src/con.c
src/fake_outputs.c
src/ipc.c
src/main.c
src/randr.c
testcases/t/291-swap.t
testcases/t/292-regress-layout-toggle.t [new file with mode: 0644]
testcases/t/538-i3bar-primary-output.t [new file with mode: 0644]

index 34c8a8fb182c6f001a5fc09264eb88f2c7515a57..8a1669293df4fba7c13cbb35d07407b1c62fa010 100644 (file)
@@ -1,17 +1,8 @@
 Changes
-inc/Module/Install.pm
-inc/Module/Install/Base.pm
-inc/Module/Install/Can.pm
-inc/Module/Install/Fetch.pm
-inc/Module/Install/Makefile.pm
-inc/Module/Install/Metadata.pm
-inc/Module/Install/Win32.pm
-inc/Module/Install/WriteAll.pm
 lib/AnyEvent/I3.pm
 Makefile.PL
-MANIFEST
+MANIFEST                       This list of files
 MANIFEST.SKIP
-META.yml
 README
 t/00-load.t
 t/01-workspaces.t
index 01bee91f3f7e3f77956e128af1be11464d5d362d..18e9d9dffb9f2d217565e198739b0d81cb9863f9 100644 (file)
@@ -9,3 +9,5 @@ Build.bat
 \.tar\.gz$
 ^pod2htm(.*).tmp$
 ^AnyEvent-I3-
+^MYMETA.*
+^MANIFEST\.bak
index 5d2ab32e1b8f7596d2baa44ecb57defc45790014..29a442f4d3e5aeca12af39da4ce87bc045559192 100644 (file)
-use lib '.';
-use inc::Module::Install;
+use strict;
+use warnings;
 
-name     'AnyEvent-I3';
-all_from 'lib/AnyEvent/I3.pm';
-author   'Michael Stapelberg';
+use 5.006;
+use ExtUtils::MakeMaker;
 
-requires 'AnyEvent';
-requires 'AnyEvent::Handle';
-requires 'AnyEvent::Socket';
-requires 'JSON::XS';
-
-if ($^O eq 'MSWin32') {
+if ( $^O eq 'MSWin32' ) {
     die "AnyEvent::I3 cannot be used on win32 (unix sockets are missing)";
 }
 
-WriteAll;
+my %meta = (
+    name        => 'AnyEvent-I3',
+    author      => 'Michael Stapelberg, C<< <michael at i3wm.org> >>',
+    license     => ['perl'],
+    'meta-spec' => { version => 2 },
+    resources   => {
+        repository => {
+            url  => 'git://github.com/i3/i3',
+            web  => 'https://github.com/i3/i3',
+            type => 'git',
+        },
+        bugtracker => {
+            web => 'https://github.com/i3/i3/issues',
+        },
+        homepage => 'https://i3wm.org/',
+        license  => ['http://dev.perl.org/licenses'],
+    },
+);
+
+my %requirements = (
+    configure_requires => {
+        'ExtUtils::MakeMaker' => 6.36,
+    },
+    build_requires => {
+        'ExtUtils::MakeMaker' => 6.36
+    },
+    runtime_requires => {
+        'AnyEvent'         => 0,
+        'AnyEvent::Handle' => 0,
+        'AnyEvent::Socket' => 0,
+        'JSON::XS'         => 0,
+    },
+    test_requires => {
+        'Test::More' => 0.80,
+    },
+);
+
+my %merged_requirements = (
+    'ExtUtils::MakeMaker' => 0,
+    'AnyEvent'            => 0,
+    'AnyEvent::Handle'    => 0,
+    'AnyEvent::Socket'    => 0,
+    'JSON::XS'            => 0,
+    'Test::More'          => 0.80,
+);
+
+$meta{prereqs}{configure}{requires} = $requirements{configure_requires};
+$meta{prereqs}{build}{requires}     = $requirements{build_requires};
+$meta{prereqs}{runtime}{requires}   = $requirements{runtime_requires};
+$meta{prereqs}{test}{requires}      = $requirements{test_requires};
+
+my %MM_Args = (
+    AUTHOR           => 'Michael Stapelberg',
+    NAME             => 'AnyEvent::I3',
+    DISTNAME         => 'AnyEvent-I3',
+    EXE_FILES        => [],
+    MIN_PERL_VERSION => '5.006',
+    VERSION_FROM     => 'lib/AnyEvent/I3.pm',
+    ABSTRACT_FROM    => 'lib/AnyEvent/I3.pm',
+    test             => {
+        TESTS => 't/*.t',
+    },
+);
+
+sub is_eumm {
+    eval { ExtUtils::MakeMaker->VERSION( $_[0] ) };
+}
+
+is_eumm(6.30) and $MM_Args{LICENSE} = $meta{license}[0];
+is_eumm(6.47_01) or delete $MM_Args{MIN_PERL_VERSION};
+is_eumm(6.52)
+  and $MM_Args{CONFIGURE_REQUIRES} = $requirements{configure_requires};
+
+is_eumm(6.57_02) and !is_eumm(6.57_07) and $MM_Args{NO_MYMETA} = 1;
+
+if ( is_eumm(6.63_03) ) {
+    %MM_Args = (
+        %MM_Args,
+        TEST_REQUIRES  => $requirements{test_requires},
+        BUILD_REQUIRES => $requirements{build_requires},
+        PREREQ_PM      => $requirements{runtime_requires},
+    );
+}
+else {
+    $MM_Args{PREREQ_PM} = \%merged_requirements;
+}
+unless ( -f 'META.yml' ) {
+    $MM_Args{META_ADD} = \%meta;
+}
+WriteMakefile(%MM_Args);
index 8598f8501e94d9448f0af0c80853b7694f695620..6850b267c0c7bc20b7fd76dd1ed34cac7337dd51 100644 (file)
@@ -88,6 +88,7 @@ use base 'Exporter';
 
 our @EXPORT = qw(i3);
 
+use constant TYPE_RUN_COMMAND => 0;
 use constant TYPE_COMMAND => 0;
 use constant TYPE_GET_WORKSPACES => 1;
 use constant TYPE_SUBSCRIBE => 2;
@@ -100,7 +101,7 @@ use constant TYPE_GET_BINDING_MODES => 8;
 use constant TYPE_GET_CONFIG => 9;
 
 our %EXPORT_TAGS = ( 'all' => [
-    qw(i3 TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS
+    qw(i3 TYPE_RUN_COMMAND TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS
        TYPE_GET_TREE TYPE_GET_MARKS TYPE_GET_BAR_CONFIG TYPE_GET_VERSION
        TYPE_GET_BINDING_MODES TYPE_GET_CONFIG)
 ] );
@@ -322,7 +323,7 @@ Sends a message of the specified C<type> to i3, possibly containing the data
 structure C<content> (or C<content>, encoded as utf8, if C<content> is a
 scalar), if specified.
 
-    my $reply = $i3->message(TYPE_COMMAND, "reload")->recv;
+    my $reply = $i3->message(TYPE_RUN_COMMAND, "reload")->recv;
     if ($reply->{success}) {
         say "Configuration successfully reloaded";
     }
@@ -532,7 +533,7 @@ sub command {
 
     $self->_ensure_connection;
 
-    $self->message(TYPE_COMMAND, $content)
+    $self->message(TYPE_RUN_COMMAND, $content)
 }
 
 =head1 AUTHOR
index ab2997fd4f72292b0a683740bc82aa9bd142f5a6..4c2c778a06ad16b090e61d6a661ca60cb514ea4c 100644 (file)
--- a/docs/ipc
+++ b/docs/ipc
@@ -50,38 +50,20 @@ The magic string currently is "i3-ipc" and will only be changed when a change
 in the IPC API is done which breaks compatibility (we hope that we don’t need
 to do that).
 
-Currently implemented message types are the following:
-
-COMMAND (0)::
-       The payload of the message is a command for i3 (like the commands you
-       can bind to keys in the configuration file) and will be executed
-       directly after receiving it.
-GET_WORKSPACES (1)::
-       Gets the current workspaces. The reply will be a JSON-encoded list of
-       workspaces (see the reply section).
-SUBSCRIBE (2)::
-       Subscribes your connection to certain events. See <<events>> for a
-       description of this message and the concept of events.
-GET_OUTPUTS (3)::
-       Gets the current outputs. The reply will be a JSON-encoded list of outputs
-       (see the reply section).
-GET_TREE (4)::
-       Gets the layout tree. i3 uses a tree as data structure which includes
-       every container. The reply will be the JSON-encoded tree (see the reply
-       section).
-GET_MARKS (5)::
-       Gets a list of marks (identifiers for containers to easily jump to them
-       later). The reply will be a JSON-encoded list of window marks (see
-       reply section).
-GET_BAR_CONFIG (6)::
-       Gets the configuration (as JSON map) of the workspace bar with the
-       given ID. If no ID is provided, an array with all configured bar IDs is
-       returned instead.
-GET_VERSION (7)::
-       Gets the version of i3. The reply will be a JSON-encoded dictionary
-       with the major, minor, patch and human-readable version.
-GET_BINDING_MODES (8)::
-        Gets a list of currently configured binding modes.
+.Currently implemented message types
+[options="header",cols="^10%,^20%,^20%,^50%"]
+|======================================================
+| Type (numeric) | Type (name) | Reply type | Purpose
+| 0 | +RUN_COMMAND+ | <<_command_reply,COMMAND>> | Run the payload as an i3 command (like the commands you can bind to keys).
+| 1 | +GET_WORKSPACES+ | <<_workspaces_reply,WORKSPACES>> | Get the list of current workspaces.
+| 2 | +SUBSCRIBE+ | <<_subscribe_reply,SUBSCRIBE>> | Subscribe this IPC connection to the event types specified in the message payload. See <<events>>.
+| 3 | +GET_OUTPUTS+ | <<_outputs_reply,OUTPUTS>> | Get the list of current outputs.
+| 4 | +GET_TREE+ | <<_tree_reply,TREE>> | Get the i3 layout tree.
+| 5 | +GET_MARKS+ | <<_marks_reply,MARKS>> | Gets the names of all currently set marks.
+| 6 | +GET_BAR_CONFIG+ | <<_bar_config_reply,BAR_CONFIG>> | Gets the specified bar configuration or the names of all bar configurations if payload is empty.
+| 7 | +GET_VERSION+ | <<_version_reply,VERSION>> | Gets the i3 version.
+| 8 | +GET_BINDING_MODES+ | <<_binding_modes_reply,BINDING_MODES>> | Gets the names of all currently configured binding modes.
+|======================================================
 
 So, a typical message could look like this:
 --------------------------------------------------
@@ -124,7 +106,7 @@ payload.
 The following reply types are implemented:
 
 COMMAND (0)::
-       Confirmation/Error code for the COMMAND message.
+       Confirmation/Error code for the RUN_COMMAND message.
 WORKSPACES (1)::
        Reply to the GET_WORKSPACES message.
 SUBSCRIBE (2)::
@@ -142,6 +124,7 @@ VERSION (7)::
 BINDING_MODES (8)::
         Reply to the GET_BINDING_MODES message.
 
+[[_command_reply]]
 === COMMAND reply
 
 The reply consists of a list of serialized maps for each command that was
@@ -153,6 +136,7 @@ human-readable error message in the property +error (string)+.
 [{ "success": true }]
 -------------------
 
+[[_workspaces_reply]]
 === WORKSPACES reply
 
 The reply consists of a serialized list of workspaces. Each workspace has the
@@ -212,6 +196,7 @@ output (string)::
 ]
 -------------------
 
+[[_subscribe_reply]]
 === SUBSCRIBE reply
 
 The reply consists of a single serialized map. The only property is
@@ -223,6 +208,7 @@ default) or whether a JSON parse error occurred.
 { "success": true }
 -------------------
 
+[[_outputs_reply]]
 === OUTPUTS reply
 
 The reply consists of a serialized list of outputs. Each output has the
@@ -269,6 +255,7 @@ rect (map)::
 ]
 -------------------
 
+[[_tree_reply]]
 === TREE reply
 
 The reply consists of a serialized tree. Each node in the tree (representing
@@ -335,7 +322,10 @@ window (integer)::
        containers. This ID corresponds to what xwininfo(1) and other
        X11-related tools display (usually in hex).
 urgent (bool)::
-       Whether this container (window or workspace) has the urgency hint set.
+       Whether this container (window, split container, floating container or
+       workspace) has the urgency hint set, directly or indirectly. All parent
+       containers up until the workspace container will be marked urgent if they
+       have at least one urgent child.
 focused (bool)::
        Whether this container is currently focused.
 focus (array of integer)::
@@ -481,6 +471,7 @@ JSON dump:
 }
 ------------------------
 
+[[_marks_reply]]
 === MARKS reply
 
 The reply consists of a single array of strings for each container that has a
@@ -489,6 +480,7 @@ The order of that array is undefined.
 
 If no window has a mark the response will be the empty array [].
 
+[[_bar_config_reply]]
 === BAR_CONFIG reply
 
 This can be used by third-party workspace bars (especially i3bar, but others
@@ -588,6 +580,7 @@ binding_mode_text/binding_mode_bg/binding_mode_border::
 }
 --------------
 
+[[_version_reply]]
 === VERSION reply
 
 The reply consists of a single JSON dictionary with the following keys:
@@ -620,6 +613,7 @@ loaded_config_file_name (string)::
 }
 -------------------
 
+[[_binding_modes_reply]]
 === BINDING_MODES reply
 
 The reply consists of an array of all currently configured binding modes.
@@ -889,3 +883,63 @@ Rust::
        * https://github.com/tmerr/i3ipc-rs
 OCaml::
        * https://github.com/Armael/ocaml-i3ipc
+
+== Appendix A: Detecting byte order in memory-safe languages
+
+Some programming languages such as Go don’t offer a way to serialize data in the
+native byte order of the machine they’re running on without resorting to tricks
+involving the +unsafe+ package.
+
+The following technique can be used (and will not be broken by changes to i3) to
+detect the byte order i3 is using:
+
+1. The byte order dependent fields of an IPC message are message type and
+   payload length.
+
+   * The message type +RUN_COMMAND+ (0) is the same in big and little endian, so
+     we can use it in either byte order to elicit a reply from i3.
+
+   * The payload length 65536 + 256 (+0x00 01 01 00+) is the same in big and
+     little endian, and also small enough to not worry about memory allocations
+     of that size. We must use payloads of length 65536 + 256 in every message
+     we send, so that i3 will be able to read the entire message regardless of
+     the byte order it uses.
+
+2. Send a big endian encoded message of type +SUBSCRIBE+ (2) with payload `[]`
+   followed by 65536 + 256 - 2 +SPACE+ (ASCII 0x20) bytes.
+
+   * If i3 is running in big endian, this message is treated as a noop,
+     resulting in a +SUBSCRIBE+ reply with payload `{"success":true}`
+     footnote:[A small payload is important: that way, we circumvent dealing
+     with UNIX domain socket buffer sizes, whose size depends on the
+     implementation/operating system. Exhausting such a buffer results in an i3
+     deadlock unless you concurrently read and write, which — depending on the
+     programming language — makes the technique much more complicated.].
+
+   * If i3 is running in little endian, this message is read in its entirety due
+     to the byte order independent payload length, then
+     https://github.com/i3/i3/blob/d726d09d496577d1c337a4b97486f2c9fbc914f1/src/ipc.c#L1188[silently
+     discarded] due to the unknown message type.
+
+3. Send a byte order independent message, i.e. type +RUN_COMMAND+ (0) with
+   payload +nop byte order detection. padding:+, padded to 65536 + 256 bytes
+   with +a+ (ASCII 0x61) bytes. i3 will reply to this message with a reply of
+   type +COMMAND+ (0).
+
+   * The human-readable prefix is in there to not confuse readers of the i3 log.
+
+   * This messages serves as a synchronization primitive so that we know whether
+     i3 discarded the +SUBSCRIBE+ message or didn’t answer it yet.
+
+4. Receive a message header from i3, decoding the message type as big endian.
+
+   * If the message’s reply type is +COMMAND+ (0), i3 is running in little
+     endian (because the +SUBSCRIBE+ message was discarded). Decode the message
+     payload length as little endian, receive the message payload.
+
+   * If the message’s reply type is anything else, i3 is running in big endian
+     (because our big endian encoded +SUBSCRIBE+ message was answered). Decode
+     the message payload length in big endian, receive the message
+     payload. Then, receive the pending +COMMAND+ message reply in big endian.
+
+5. From here on out, send/receive all messages using the detected byte order.
index 1a1727894b407283b7db50ff6fba8cc70dce8688..8907a6f7adf80cf68729983d264748505040b732 100644 (file)
@@ -167,7 +167,7 @@ int main(int argc, char *argv[]) {
     else
         socket_path = NULL;
     int o, option_index = 0;
-    uint32_t message_type = I3_IPC_MESSAGE_TYPE_COMMAND;
+    uint32_t message_type = I3_IPC_MESSAGE_TYPE_RUN_COMMAND;
     char *payload = NULL;
     bool quiet = false;
 
@@ -188,7 +188,9 @@ int main(int argc, char *argv[]) {
             socket_path = sstrdup(optarg);
         } else if (o == 't') {
             if (strcasecmp(optarg, "command") == 0) {
-                message_type = I3_IPC_MESSAGE_TYPE_COMMAND;
+                message_type = I3_IPC_MESSAGE_TYPE_RUN_COMMAND;
+            } else if (strcasecmp(optarg, "run_command") == 0) {
+                message_type = I3_IPC_MESSAGE_TYPE_RUN_COMMAND;
             } else if (strcasecmp(optarg, "get_workspaces") == 0) {
                 message_type = I3_IPC_MESSAGE_TYPE_GET_WORKSPACES;
             } else if (strcasecmp(optarg, "get_outputs") == 0) {
@@ -207,7 +209,7 @@ int main(int argc, char *argv[]) {
                 message_type = I3_IPC_MESSAGE_TYPE_GET_CONFIG;
             } else {
                 printf("Unknown message type\n");
-                printf("Known types: command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config\n");
+                printf("Known types: run_command, get_workspaces, get_outputs, get_tree, get_marks, get_bar_config, get_binding_modes, get_version, get_config\n");
                 exit(EXIT_FAILURE);
             }
         } else if (o == 'q') {
index 2ba446b1176be8596d34d2b3b7c6e19287dcd19a..462184cb7ff829ce162d6de613b2455997cdfa30 100644 (file)
@@ -522,7 +522,7 @@ void handle_button(xcb_button_press_event_t *event) {
         if (binding->input_code != event->detail)
             continue;
 
-        i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, binding->command);
+        i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, binding->command);
         return;
     }
 
@@ -603,7 +603,7 @@ void handle_button(xcb_button_press_event_t *event) {
         buffer[outpos] = utf8_name[inpos];
     }
     buffer[outpos] = '"';
-    i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer);
+    i3_send_msg(I3_IPC_MESSAGE_TYPE_RUN_COMMAND, buffer);
     free(buffer);
 }
 
index e3891454fdc561bca4847fbe96a010a8b0f4a33d..993a2a2482d1de70ed67433ae2189948c6f53f35 100644 (file)
@@ -27,9 +27,12 @@ typedef struct i3_ipc_header {
 /** Never change this, only on major IPC breakage (don’t do that) */
 #define I3_IPC_MAGIC "i3-ipc"
 
-/** The payload of the message will be interpreted as a command */
+/** Deprecated: use I3_IPC_MESSAGE_TYPE_RUN_COMMAND */
 #define I3_IPC_MESSAGE_TYPE_COMMAND 0
 
+/** The payload of the message will be interpreted as a command */
+#define I3_IPC_MESSAGE_TYPE_RUN_COMMAND 0
+
 /** Requests the current workspaces from i3 */
 #define I3_IPC_MESSAGE_TYPE_GET_WORKSPACES 1
 
index 8254672f4c47bb6ab26c0424caa5dea5590989a8..29a326e701a2a369737330760d6eb423e2407270 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -1862,7 +1862,9 @@ void con_toggle_layout(Con *con, const char *toggle_mode) {
             }
         }
 
-        con_set_layout(con, new_layout);
+        if (new_layout != L_DEFAULT) {
+            con_set_layout(con, new_layout);
+        }
     } else if (strcasecmp(toggle_mode, "all") == 0 || strcasecmp(toggle_mode, "default") == 0) {
         if (parent->layout == L_STACKED)
             con_set_layout(con, L_TABBED);
index 6639b3611005b3a393a1c493558724ff0122490c..39cbd7bbc6e98fead58a72f94074b45f2826a933 100644 (file)
@@ -28,17 +28,27 @@ static Output *get_screen_at(unsigned int x, unsigned int y) {
 /*
  * Creates outputs according to the given specification.
  * The specification must be in the format wxh+x+y, for example 1024x768+0+0,
+ * optionally followed by 'P' to indicate a primary output,
  * with multiple outputs separated by commas:
- *   1900x1200+0+0,1280x1024+1900+0
+ *   1900x1200+0+0P,1280x1024+1900+0
  *
  */
 void fake_outputs_init(const char *output_spec) {
-    char useless_buffer[1024];
     const char *walk = output_spec;
     unsigned int x, y, width, height;
-    while (sscanf(walk, "%ux%u+%u+%u", &width, &height, &x, &y) == 4) {
-        DLOG("Parsed output as width = %u, height = %u at (%u, %u)\n",
-             width, height, x, y);
+    int chars_consumed;
+    while (sscanf(walk, "%ux%u+%u+%u%n", &width, &height, &x, &y, &chars_consumed) == 4) {
+        walk += chars_consumed;
+        bool primary = false;
+        if (*walk == 'P') {
+            primary = true;
+            walk++;
+        }
+        if (*walk == ',')
+            walk++; /* Skip delimiter */
+        DLOG("Parsed output as width = %u, height = %u at (%u, %u)%s\n",
+             width, height, x, y, primary ? " (primary)" : "");
+
         Output *new_output = get_screen_at(x, y);
         if (new_output != NULL) {
             DLOG("Re-used old output %p\n", new_output);
@@ -67,9 +77,7 @@ void fake_outputs_init(const char *output_spec) {
             init_ws_for_output(new_output, output_get_content(new_output->con));
             num_screens++;
         }
-
-        /* Figure out how long the input was to skip it */
-        walk += sprintf(useless_buffer, "%ux%u+%u+%u", width, height, x, y) + 1;
+        new_output->primary = primary;
     }
 
     if (num_screens == 0) {
index 274f60106bd2eb67fb4562a40f62aa053b405291..759665fe91b76341e74128807ce830c39e0ef63e 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -113,7 +113,7 @@ void ipc_shutdown(shutdown_reason_t reason) {
  * or not (at the moment, always returns true).
  *
  */
-IPC_HANDLER(command) {
+IPC_HANDLER(run_command) {
     /* To get a properly terminated buffer, we copy
      * message_size bytes out of the buffer */
     char *command = scalloc(message_size + 1, 1);
@@ -580,6 +580,10 @@ static void dump_bar_bindings(yajl_gen gen, Barconfig *config) {
 }
 
 static char *canonicalize_output_name(char *name) {
+    /* Do not canonicalize special output names. */
+    if (strcasecmp(name, "primary") == 0) {
+        return name;
+    }
     Output *output = get_output_by_name(name, false);
     return output ? output_primary_name(output) : name;
 }
@@ -1121,7 +1125,7 @@ IPC_HANDLER(get_config) {
 /* The index of each callback function corresponds to the numeric
  * value of the message type (see include/i3/ipc.h) */
 handler_t handlers[10] = {
-    handle_command,
+    handle_run_command,
     handle_get_workspaces,
     handle_subscribe,
     handle_get_outputs,
index 44e4517ee6678681c9a2b72b5b4c86d772a78649..f651ad6e69917f2f16411117897080306f88e2b7 100644 (file)
@@ -418,7 +418,7 @@ int main(int argc, char *argv[]) {
         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,
+        if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_RUN_COMMAND,
                              (uint8_t *)payload) == -1)
             err(EXIT_FAILURE, "IPC: write()");
         FREE(payload);
@@ -432,8 +432,8 @@ int main(int argc, char *argv[]) {
                 err(EXIT_FAILURE, "IPC: read()");
             return 1;
         }
-        if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND)
-            errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND);
+        if (reply_type != I3_IPC_REPLY_TYPE_COMMAND)
+            errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_REPLY_TYPE_COMMAND);
         printf("%.*s\n", reply_length, reply);
         FREE(reply);
         return 0;
index 88cad7c51d5c9df1c2f32f44463665da4c9b31cd..19c40577ed1401316258a5e06697de1742a089a5 100644 (file)
@@ -380,6 +380,10 @@ void output_init_con(Output *output) {
     FREE(name);
     DLOG("attaching\n");
     con_attach(bottomdock, con, false);
+
+    /* Change focus to the content container */
+    TAILQ_REMOVE(&(con->focus_head), content, focused);
+    TAILQ_INSERT_HEAD(&(con->focus_head), content, focused);
 }
 
 /*
index f9ac3b6ac3ab97a9915bb8d20addaba2fd03a509..9bbd3795c137b613407948f98767865c151bd6fa 100644 (file)
@@ -226,6 +226,7 @@ $expected_focus = get_focused($ws1);
 $ws2 = fresh_workspace;
 $B = open_window(wm_class => 'mark_B');
 $B->fullscreen(1);
+sync_with_i3;
 
 cmd '[con_mark=B] swap container with mark A';
 
@@ -263,6 +264,7 @@ $expected_focus = get_focused($ws1);
 $ws2 = fresh_workspace;
 $B = open_window(wm_class => 'mark_B');
 $B->fullscreen(1);
+sync_with_i3;
 
 cmd '[con_mark=B] swap container with mark A';
 
diff --git a/testcases/t/292-regress-layout-toggle.t b/testcases/t/292-regress-layout-toggle.t
new file mode 100644 (file)
index 0000000..a8fd3a6
--- /dev/null
@@ -0,0 +1,29 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+#   (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+#   (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+#   (unless you are already familiar with Perl)
+#
+# Regression test: verify layout toggle with invalid parameters does not set
+# layout to L_DEFAULT, which crashes i3 upon the next IPC message.
+# Ticket: #2903
+# Bug still in: 4.14-87-g607e97e6
+use i3test;
+
+cmd 'layout toggle 1337 1337';
+
+fresh_workspace;
+
+does_i3_live;
+
+done_testing;
diff --git a/testcases/t/538-i3bar-primary-output.t b/testcases/t/538-i3bar-primary-output.t
new file mode 100644 (file)
index 0000000..67fd1b6
--- /dev/null
@@ -0,0 +1,40 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+#   (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+#   (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+#   (unless you are already familiar with Perl)
+#
+# Tests that i3bars configured to use the primary output do not have
+# their output names canonicalized to something other than "primary".
+# Ticket: #2948
+# Bug still in: 4.14-93-ga3a7d04a
+use i3test i3_config => <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+fake-outputs 1024x768+0+0P
+
+bar {
+    output primary
+}
+EOT
+
+my $bars = i3->get_bar_config()->recv;
+is(@$bars, 1, 'one bar configured');
+
+my $bar_id = shift @$bars;
+
+my $bar_config = i3->get_bar_config($bar_id)->recv;
+is_deeply($bar_config->{outputs}, [ "primary" ], 'bar_config output is primary');
+
+done_testing;