]> git.sur5r.net Git - i3/i3/commitdiff
Merge pull request #1521 from Airblader/feature-use-refactored-function
authorMichael Stapelberg <stapelberg@users.noreply.github.com>
Fri, 13 Mar 2015 07:54:52 +0000 (00:54 -0700)
committerMichael Stapelberg <stapelberg@users.noreply.github.com>
Fri, 13 Mar 2015 07:54:52 +0000 (00:54 -0700)
Use the already existing function to get rid of some code duplication

31 files changed:
RELEASE-NOTES-4.9 [deleted file]
RELEASE-NOTES-4.9.1 [new file with mode: 0644]
debian/changelog
docs/hacking-howto
i3-dmenu-desktop
i3-migrate-config-to-v4
i3-nagbar/main.c
i3.config
include/atoms.xmacro
include/config.h
include/data.h
include/key_press.h
include/output.h
include/workspace.h
libi3/font.c
man/asciidoc.conf
man/i3-sensible-editor.man
man/i3-sensible-pager.man
man/i3-sensible-terminal.man
release.sh [new file with mode: 0755]
src/bindings.c
src/click.c
src/commands.c
src/config_parser.c
src/handlers.c
src/main.c
src/output.c
src/restore_layout.c
src/workspace.c
testcases/t/231-wm-change-state.t [deleted file]
testcases/t/522-rename-assigned-workspace.t [new file with mode: 0644]

diff --git a/RELEASE-NOTES-4.9 b/RELEASE-NOTES-4.9
deleted file mode 100644 (file)
index 9012646..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.9    │
- └──────────────────────────────┘
-
-This is i3 v4.9. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-Notable new features include mouse button bindings and improved EWMH
-compatibility, meaning more external pager programs work with i3 now.
-
-Aside from that, this release contains plenty of bugfixes and little
-enhancements.
-
-The new dependency on libxkbcommon ≥ 0.4.0 is notable for distribution
-packages. This dependency allowed us to drop our last direct dependency
-on Xlib :).
-
-It’s also worth mentioning that all i3 repositories are now on GitHub, see
-http://thread.gmane.org/gmane.comp.window-managers.i3.general/1666 for the
-announcement.
-
- ┌────────────────────────────┐
- │ Changes in v4.9            │
- └────────────────────────────┘
-
-  • docs/ipc: use an actual event type
-  • docs/debugging: use logs.i3wm.org
-  • docs/testsuite: add hint to use xvfb-run
-  • testcases: use Xephyr instead of XDummy
-  • i3-sensible-*: use command -v (built-in) instead of which(1)
-  • i3.xsession.desktop: set DesktopNames (which gdm uses)
-  • i3-save-tree: interpret commandline parameters as utf-8
-  • i3-save-tree: add 'mark' as allowed key to i3-save-tree output
-  • i3bar-protocol: ensure align = left is the default
-  • i3bar: implement custom mouse wheel commands
-  • i3bar: improve error message when a full_text property is missing
-  • i3bar: respect the urgency flag on status blocks
-  • i3bar: inset the urgent background of a status block for consistency with
-    workspace buttons
-  • i3bar: suspend the child when bars are fully obscured
-  • i3bar: use Pango markup
-  • ipc: implement the window::close event
-  • ipc: implement the window::move event
-  • ipc: implement the window::floating event
-  • ipc: implement the window::urgent event
-  • ipc: set ws reply "num" member to -1 when named
-  • ipc: add deco_rect property to con in ipc response
-  • ipc: include workspace con in workspace event
-  • ewmh: implement property _NET_NUMBER_OF_DESKTOPS
-  • ewmh: implement property _NET_DESKTOP_VIEWPORT
-  • ewmh: implement property _NET_DESKTOP_NAMES
-  • ewmh: handle _NET_CURRENT_DESKTOP requests
-  • ewmh: handle _NET_CLOSE_WINDOW requests
-  • ewmh: handle _NET_WM_MOVERESIZE requests
-  • implement mouse bindings (e.g. bindsym button3 kill)
-  • add mouse binding --whole-window flag
-  • add mouse binding --release flag
-  • switch to xcb-xkb and libxkbcommon, removing our last direct Xlib dep
-  • make “move [direction]” work with criteria
-  • make “move <window|container> to <absolute> position” work with criteria
-  • “workspace <n>” and “move to workspace <n>” now look for a workspace
-    starting with number <n> (unless there is a workspace exactly matching that
-    number). I.e., “workspace 4” will go to a workspace called “4: www” unless
-    you have a workspace “4”
-  • “focus <direction>” now focuses floating containers when there are no
-    tiling containers on the destination output
-  • take the motif border into account when calculating floating window
-    geometry
-  • revert “Disable pointer warps when focus_follows_mouse is disabled” as it
-    was unexpected by a number of users. Sorry for the back-and-forth
-  • handle WM_CLASS changes
-  • raise floating windows on “focus <direction>”
-  • align lower line of bar decoration to border width
-  • parse tray_output as a word, not string
-  • allow to validate the config file without X
-  • do not resend focus on click, fixes compatibility problems with some wine
-    or mono apps (e.g. Office 2010)
-  • don't draw borders wider than actual width
-  • prevent workspace change during global fullscreen
-  • extend the fullscreen command (fullscreen <enable|toggle|disable> [global])
-  • fix start_application() doc about which shell is used
-
- ┌────────────────────────────┐
- │ Bugfixes                   │
- └────────────────────────────┘
-
-  • i3-dmenu-desktop: quote path
-  • i3bar: fix a double free when changing color configuration
-  • i3bar: render bars after the first chunk of JSON
-  • i3bar: add a sync call to confirm reparents before exiting (fixes tray
-    restart issues)
-  • i3bar: correctly calculate clicks on i3bar status blocks
-  • i3bar: make click events on status blocks work with 'workspace_buttons no'
-  • retina support: convert logical to physical pixels for default_border_width
-  • retina support: treat everything up to 120 dpi as 96 dpi
-  • don’t set input focus if not accepted (fixes problems with xfce4-notifyd)
-  • don’t focus unmapped container on manage
-  • create the directory for storing the restart state
-  • avoid changing border width when changing containers from tiling to
-    floating
-  • layout saving: properly restore workspace containers
-  • rerender the decoration when the container requires a pixmap and doesn’t
-    have one
-  • don’t set focus in con_set_layout() on invisible workspaces
-  • properly handle windows unsetting WM_TRANSIENT_FOR
-  • use the command parser to properly extract workspace names
-  • copy binding before run (fixes reloads)
-  • revert "Bugfix: Set input focus with last timestamp"
-  • render floating windows during global fullscreen
-  • actually parse client.placeholder
-
- ┌────────────────────────────┐
- │ Thanks!                    │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
-  Alexander Monakov, aszlig, cornerman, dmurph, Mats, dsargrad, hercek, hjem,
-  Ingo, Ingo Bürk, Janus, javier, jefvel, Lukas K, Marein Konings, Mats,
-  Michael Stapelberg, Mii, nikolaus, okraits, Peter, smlb, sur5r, Tony Crisci,
-  val, vals, xeen, Yves-Alexis
-
--- Michael Stapelberg, 2015-02-28
diff --git a/RELEASE-NOTES-4.9.1 b/RELEASE-NOTES-4.9.1
new file mode 100644 (file)
index 0000000..5ff6d22
--- /dev/null
@@ -0,0 +1,36 @@
+
+ ┌──────────────────────────────┐
+ │ Release notes for i3 v4.9.1  │
+ └──────────────────────────────┘
+
+This is i3 v4.9.1. This version is considered stable. All users of i3 are
+strongly encouraged to upgrade.
+
+This is a bugfix release for i3 v4.9.
+
+ ┌────────────────────────────┐
+ │ Bugfixes                   │
+ └────────────────────────────┘
+
+  • i3bar: fix incorrect y-offset for text
+  • fix key bindings on big-endian platforms
+  • fix key bindings using Mode_switch
+  • fix keyboard layout change detection
+  • revert "Handle WM_CHANGE_STATE requests for iconic state" (fixes problems
+    with application windows disappearing, like SDL-based games when switching
+    workspaces)
+  • insert id-based match at HEAD, not TAIL (fixes window swallowing not
+    working when the criteria match the placeholder window)
+  • improve error messages on failing commands
+  • replace ~ in filepath when calling append_layout
+  • properly error out when the layout file cannot be read
+
+ ┌────────────────────────────┐
+ │ Thanks!                    │
+ └────────────────────────────┘
+
+Thanks for testing, bugfixes, discussions and everything I forgot go out to:
+
+  Steven McDonald, Ton van den Heuvel, Ingo Bürk
+
+-- Michael Stapelberg, 2015-03-07
index 3b5cdb212f12a2f1b77d077f53db3ca480630d61..1dcfc9f9fc6b45a458ded6042da814f30149c967 100644 (file)
@@ -1,8 +1,14 @@
-i3-wm (4.9.1-1) experimental; urgency=medium
+i3-wm (4.9.2-1) experimental; urgency=medium
 
   * NOT YET RELEASED.
 
- -- Michael Stapelberg <stapelberg@debian.org>  Sat, 28 Feb 2015 15:04:25 +0100
+ -- Michael Stapelberg <stapelberg@debian.org>  Sat, 07 Mar 2015 20:31:31 +0100
+
+i3-wm (4.9.1-1) experimental; urgency=medium
+
+  * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org>  Sat, 07 Mar 2015 20:01:46 +0100
 
 i3-wm (4.9-1) experimental; urgency=medium
 
index a591047ede3986f6235d1e9ba301292902c9932a..12d6b14ee1b2da3406d4b78e7960c66288207749 100644 (file)
@@ -1012,7 +1012,7 @@ gets started in any way) and the window(s) which appear.
 
 Imagine for example using dmenu: The user starts dmenu by pressing Mod+d, dmenu
 gets started with PID 3390. The user then decides to launch Firefox, which
-takes a long time. So he enters firefox into dmenu and presses enter. Firefox
+takes a long time. So they enter firefox into dmenu and press enter. Firefox
 gets started with PID 4001. When it finally finishes loading, it creates an X11
 window and uses MapWindow to make it visible. This is the first time i3
 actually gets in touch with Firefox. It decides to map the window, but it has
index 2c54233d02501a57bb776cf7dad0260aea777a4f..cc72f1016429780c2e13a2ef8378c119701cb9e0 100755 (executable)
@@ -306,7 +306,7 @@ for my $app (keys %apps) {
 #   };
 
 # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
-# ┃ Run dmenu to ask the user for her choice                                  ┃
+# ┃ Run dmenu to ask the user for their choice                                ┃
 # ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
 
 # open2 will just make dmenu’s STDERR go to our own STDERR.
index ae5bf4deb02811e715885dc622c741dcf114a6cd..b78378be1c65a68225a38d8ebace7b5be0845a3d 100755 (executable)
@@ -341,7 +341,7 @@ sub convert_command {
             # NOTE: This is not 100% accurate, as it only works for one level
             # of nested containers. As this is a common use case, we use 'focus
             # parent; $command' nevertheless. For advanced use cases, the user
-            # has to modify his config.
+            # has to modify their config.
             print "$statement $key focus parent; $command\n";
         }
         return;
index bdf6582bd04f917fe642892702c90349249d7e6c..b501ff6a304536437e02525d9f4846bd860922a8 100644 (file)
@@ -5,7 +5,7 @@
  * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
  *
  * i3-nagbar is a utility which displays a nag message, for example in the case
- * when the user has an error in his configuration file.
+ * when the user has an error in their configuration file.
  *
  */
 #include <stdio.h>
index c53ecadf5f0d654af1d32b1f6b42cf7a1122bd10..f7722d361957c5d48b8aedc42c3d2033bba89d36 100644 (file)
--- a/i3.config
+++ b/i3.config
@@ -169,7 +169,7 @@ bar {
 
 #######################################################################
 # automatically start i3-config-wizard to offer the user to create a
-# keysym-based config which used his favorite modifier (alt or windows)
+# keysym-based config which used their favorite modifier (alt or windows)
 #
 # i3-config-wizard will not launch if there already is a config file
 # in ~/.i3/config.
index 1f28c01405209022c8567c6d9370fe0a1d7426e7..59dab6eddd1c1eeeff16b3b5b26d5992b137ad85 100644 (file)
@@ -39,4 +39,3 @@ xmacro(I3_PID)
 xmacro(_NET_REQUEST_FRAME_EXTENTS)
 xmacro(_NET_FRAME_EXTENTS)
 xmacro(_MOTIF_WM_HINTS)
-xmacro(WM_CHANGE_STATE)
index dea26d96344548a5573ebdb6de2813b4a1ccc32e..afafb64be0cb8da35017684d0ec354e7cd03f50c 100644 (file)
@@ -105,7 +105,7 @@ struct Config {
 
     /** By default, focus follows mouse. If the user explicitly wants to
      * turn this off (and instead rely only on the keyboard for changing
-     * focus), we allow him to do this with this relatively special option.
+     * focus), we allow them to do this with this relatively special option.
      * It is not planned to add any different focus models. */
     bool disable_focus_follows_mouse;
 
index 8f2c197df3e11e4a9234323a5fd8b3fd6049b289..eba0f968088363202eb519130e05f4bee0ad30e3 100644 (file)
@@ -450,7 +450,7 @@ struct Match {
 /**
  * An Assignment makes specific windows go to a specific workspace/output or
  * run a command for that window. With this mechanism, the user can -- for
- * example -- assign his browser to workspace "www". Checking if a window is
+ * example -- assign their browser to workspace "www". Checking if a window is
  * assigned works by comparing the Match data structure with the window (see
  * match_matches_window()).
  *
index 9712e8b9eda608542ff331ca39bd148726568f89..86cc6836f1300402ad29a26c3cddcc62968c4ff2 100644 (file)
@@ -19,7 +19,7 @@ void handle_key_press(xcb_key_press_event_t *event);
 /**
  * Kills the commanderror i3-nagbar process, if any.
  *
- * Called when reloading/restarting, since the user probably fixed his wrong
+ * Called when reloading/restarting, since the user probably fixed their wrong
  * keybindings.
  *
  * If wait_for_it is set (restarting), this function will waitpid(), otherwise,
index 10ee7d1740ac4d4f96ee7dca366063713ab06511..6514c477fc7f5ca01b5e9e6daec629eb2877743d 100644 (file)
  *
  */
 Con *output_get_content(Con *output);
+
+/**
+ * Returns an 'output' corresponding to one of left/right/down/up or a specific
+ * output name.
+ *
+ */
+Output *get_output_from_string(Output *current_output, const char *output_str);
index 9ee6f156674976275f37220d46e4aa594b8459b8..d0f801e0039240195496c6d3245f0ff9540e43d9 100644 (file)
@@ -179,3 +179,10 @@ Con *workspace_attach_to(Con *ws);
  * The container inherits the layout from the workspace.
  */
 Con *workspace_encapsulate(Con *ws);
+
+/**
+ * Move the given workspace to the specified output.
+ * This returns true if and only if moving the workspace was successful.
+ *
+ */
+bool workspace_move_to_output(Con *ws, char *output);
index df478fb4fc87f69e6a7d659b4bec7ab8cee4a10d..cb92d52fbd29bc8281cb9beabcc269f2c5fca93b 100644 (file)
@@ -455,7 +455,7 @@ static int xcb_query_text_width(const xcb_char2b_t *text, size_t text_len) {
                                                                          cookie, &error);
     if (reply == NULL) {
         /* We return a safe estimate because a rendering error is better than
-         * a crash. Plus, the user will see the error in his log. */
+         * a crash. Plus, the user will see the error in their log. */
         fprintf(stderr, "Could not get text extents (X error code %d)\n",
                 error->error_code);
         return savedFont->specific.xcb.info->max_bounds.character_width * text_len;
index f358e81b88478b4058aad21d909ac9ca8697d37c..d441e78f8449be4a42379bdd713c5609c0a72f2e 100644 (file)
@@ -7,7 +7,7 @@ template::[header-declarations]
 <refentrytitle>{mantitle}</refentrytitle>
 <manvolnum>{manvolnum}</manvolnum>
 <refmiscinfo class="source">i3</refmiscinfo>
-<refmiscinfo class="version">4.9</refmiscinfo>
+<refmiscinfo class="version">4.9.1</refmiscinfo>
 <refmiscinfo class="manual">i3 Manual</refmiscinfo>
 </refmeta>
 <refnamediv>
index 2a0448813ecb48ecb97624cc4717b5df8f7ab540..19b0f3a59267378ec30c54e146d19da93a3f8c07 100644 (file)
@@ -30,7 +30,7 @@ It tries to start one of the following (in that order):
 * gedit
 * mc-edit
 
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
 have $VISUAL or $EDITOR set.
 
 == SEE ALSO
index 6b04c4316fda10d0f8fe7a1876ad356df1db5984..22754c0bd96686e74e5cb372384b9381db9b8ef4 100644 (file)
@@ -23,7 +23,7 @@ It tries to start one of the following (in that order):
 * w3m
 * i3-sensible-editor(1)
 
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
 have $PAGER set.
 
 == SEE ALSO
index d1ad5198edaa8bd9fa30f63f3056d5f93a34149e..6fa91ac893900c61d077fba66a60a453fed3a5b6 100644 (file)
@@ -33,8 +33,8 @@ It tries to start one of the following (in that order):
 * roxterm
 * xfce4-terminal
 
-Please don’t complain about the order: If the user has any preference, she will
-have $TERMINAL set or modified her i3 configuration file.
+Please don’t complain about the order: If the user has any preference, they will
+have $TERMINAL set or modified their i3 configuration file.
 
 == SEE ALSO
 
diff --git a/release.sh b/release.sh
new file mode 100755 (executable)
index 0000000..db5ca09
--- /dev/null
@@ -0,0 +1,193 @@
+#!/bin/zsh
+# This script is used to prepare a new release of i3.
+
+export RELEASE_VERSION="4.9.1"
+export PREVIOUS_VERSION="4.9"
+export RELEASE_BRANCH="master"
+
+if [ ! -e "../i3.github.io" ]
+then
+       echo "../i3.github.io does not exist."
+       echo "Use git clone git://github.com/i3/i3.github.io"
+       exit 1
+fi
+
+if [ ! -e "RELEASE-NOTES-${RELEASE_VERSION}" ]
+then
+       echo "RELEASE-NOTES-${RELEASE_VERSION} not found."
+       exit 1
+fi
+
+if git diff-files --quiet --exit-code debian/changelog
+then
+       echo "Expected debian/changelog to be changed (containing the changelog for ${RELEASE_VERSION})."
+       exit 1
+fi
+
+eval $(gpg-agent --daemon)
+export GPG_AGENT_INFO
+
+################################################################################
+# Section 1: update git and build the release tarball
+################################################################################
+
+STARTDIR=$PWD
+
+TMPDIR=$(mktemp -d)
+cd $TMPDIR
+if ! wget http://i3wm.org/downloads/i3-${PREVIOUS_VERSION}.tar.bz2; then
+       echo "Could not download i3-${PREVIOUS_VERSION}.tar.bz2 (required for comparing files)."
+       exit 1
+fi
+git clone --quiet --branch "${RELEASE_BRANCH}" file://${STARTDIR}
+cd i3
+if [ ! -e "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" ]; then
+       echo "Required file RELEASE-NOTES-${RELEASE_VERSION} not found."
+       exit 1
+fi
+git checkout -b release-${RELEASE_VERSION}
+cp "${STARTDIR}/RELEASE-NOTES-${RELEASE_VERSION}" "RELEASE-NOTES-${RELEASE_VERSION}"
+git add RELEASE-NOTES-${RELEASE_VERSION}
+git rm RELEASE-NOTES-${PREVIOUS_VERSION}
+sed -i "s,<refmiscinfo class=\"version\">[^<]*</refmiscinfo>,<refmiscinfo class=\"version\">${RELEASE_VERSION}</refmiscinfo>,g" man/asciidoc.conf
+git commit -a -m "release i3 ${RELEASE_VERSION}"
+git tag "${RELEASE_VERSION}" -m "release i3 ${RELEASE_VERSION}" --sign --local-user=0x4AC8EE1D
+
+make dist
+
+echo "Differences in the release tarball file lists:"
+
+diff -u \
+       <(tar tf ../i3-${PREVIOUS_VERSION}.tar.bz2 | sed "s,i3-${PREVIOUS_VERSION}/,,g" | sort) \
+       <(tar tf    i3-${RELEASE_VERSION}.tar.bz2  | sed "s,i3-${RELEASE_VERSION}/,,g"  | sort) \
+       | colordiff
+
+if ! tar xf i3-${RELEASE_VERSION}.tar.bz2 --to-stdout --strip-components=1 i3-${RELEASE_VERSION}/I3_VERSION | grep -q "^${RELEASE_VERSION} "
+then
+       echo "I3_VERSION file does not start with ${RELEASE_VERSION}"
+       exit 1
+fi
+
+gpg --armor -b i3-${RELEASE_VERSION}.tar.bz2
+
+if [ "${RELEASE_BRANCH}" = "master" ]; then
+       git checkout master
+       git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
+       git checkout next
+       git merge --no-ff master -m "Merge branch 'master' into next"
+else
+       git checkout next
+       git merge --no-ff release-${RELEASE_VERSION} -m "Merge branch 'release-${RELEASE_VERSION}'"
+       git checkout master
+       git merge --no-ff next -m "Merge branch 'next' into master"
+fi
+
+################################################################################
+# Section 2: Debian packaging
+################################################################################
+
+cd "${TMPDIR}"
+mkdir debian
+
+# Copy over the changelog because we expect it to be locally modified in the
+# start directory.
+cp "${STARTDIR}/debian/changelog" i3/debian/changelog
+
+cat > ${TMPDIR}/Dockerfile <<EOT
+FROM debian:sid
+RUN sed -i 's,^deb \(.*\),deb \1\ndeb-src \1,g' /etc/apt/sources.list
+RUN apt-get update && apt-get install -y dpkg-dev devscripts
+COPY i3/i3-${RELEASE_VERSION}.tar.bz2 /usr/src/i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+WORKDIR /usr/src/
+RUN tar xf i3-wm_${RELEASE_VERSION}.orig.tar.bz2
+WORKDIR /usr/src/i3-${RELEASE_VERSION}
+COPY i3/debian /usr/src/i3-${RELEASE_VERSION}/debian/
+RUN mkdir debian/source
+RUN echo '3.0 (quilt)' > debian/source/format
+WORKDIR /usr/src
+RUN mk-build-deps --install --remove --tool 'apt-get --no-install-recommends -y' i3-${RELEASE_VERSION}/debian/control
+WORKDIR /usr/src/i3-${RELEASE_VERSION}
+RUN dpkg-buildpackage -sa -j8
+EOT
+
+CONTAINER_NAME=$(echo "i3-${TMPDIR}" | sed 's,/,,g')
+docker build -t i3 .
+for file in $(docker run --name "${CONTAINER_NAME}" i3 /bin/sh -c "ls /usr/src/i3*_${RELEASE_VERSION}*")
+do
+       docker cp "${CONTAINER_NAME}:${file}" ${TMPDIR}/debian/
+done
+
+echo "Content of resulting package’s .changes file:"
+cat ${TMPDIR}/debian/*.changes
+
+# debsign is in devscripts, which is available in fedora and debian
+debsign -k4AC8EE1D ${TMPDIR}/debian/*.changes
+
+# TODO: docker cleanup
+
+################################################################################
+# Section 3: website
+################################################################################
+
+cd ${TMPDIR}
+git clone --quiet ${STARTDIR}/../i3.github.io
+cd i3.github.io
+cp ${TMPDIR}/i3/i3-${RELEASE_VERSION}.tar.bz2* downloads/
+git add downloads/i3-${RELEASE_VERSION}.tar.bz2*
+cp ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION} downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
+git add downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt
+sed -i "s,<h2>Documentation for i3 v[^<]*</h2>,<h2>Documentation for i3 v${RELEASE_VERSION}</h2>,g" docs/index.html
+sed -i "s,<span style=\"margin-left: 2em; color: #c0c0c0\">[^<]*</span>,<span style=\"margin-left: 2em; color: #c0c0c0\">${RELEASE_VERSION}</span>,g" index.html
+sed -i "s,The current stable version is .*$,The current stable version is ${RELEASE_VERSION}.,g" downloads/index.html
+sed -i "s,<tbody>,<tbody>\n  <tr>\n    <td>${RELEASE_VERSION}</td>\n    <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2\">i3-${RELEASE_VERSION}.tar.bz2</a></td>\n    <td>$(ls -lh ../i3/i3-${RELEASE_VERSION}.tar.bz2 | awk -F " " {'print $5'} | sed 's/K$/ KiB/g')</td>\n    <td><a href=\"/downloads/i3-${RELEASE_VERSION}.tar.bz2.asc\">signature</a></td>\n    <td>$(date +'%Y-%m-%d')</td>\n    <td><a href=\"/downloads/RELEASE-NOTES-${RELEASE_VERSION}.txt\">release notes</a></td>\n  </tr>\n,g" downloads/index.html
+
+git commit -a -m "add ${RELEASE_VERSION} release"
+
+mkdir docs/${PREVIOUS_VERSION}
+tar cf - '--exclude=[0-9]\.[0-9e]*' docs | tar xf - --strip-components=1 -C docs/${PREVIOUS_VERSION}
+git add docs/${PREVIOUS_VERSION}
+git commit -a -m "save docs for ${PREVIOUS_VERSION}"
+
+for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile")
+do
+       base="$(basename $i)"
+       [ -e "${STARTDIR}/docs/${base}" ] && cp "${STARTDIR}/docs/${base}" "_docs/${base}"
+done
+
+(cd _docs && make)
+
+for i in $(find _docs -maxdepth 1 -and -type f -and \! -regex ".*\.\(html\|man\)$" -and \! -name "Makefile")
+do
+       base="$(basename $i)"
+       [ -e "${STARTDIR}/docs/${base}" ] && cp "_docs/${base}.html" docs/
+done
+
+git commit -a -m "update docs for ${RELEASE_VERSION}"
+
+################################################################################
+# Section 4: final push instructions
+################################################################################
+
+echo "As a final sanity check, install the debian package and see whether i3 works."
+
+echo "When satisfied, run:"
+echo "  cd ${TMPDIR}/i3"
+echo "  git checkout next"
+echo "  vi debian/changelog"
+# TODO: can we just set up the remote spec properly?
+echo "  git push git@github.com:i3/i3 next"
+echo "  git push git@github.com:i3/i3 master"
+echo "  git push git@github.com:i3/i3 --tags"
+echo ""
+echo "  cd ${TMPDIR}/i3.github.io"
+# TODO: can we just set up the remote spec properly?
+echo "  git push git@github.com:i3/i3.github.io master"
+echo ""
+echo "  cd ${TMPDIR}/debian"
+echo "  dput *.changes"
+echo ""
+echo "Announce on:"
+echo "  twitter"
+echo "  google+"
+echo "  mailing list"
+echo "  #i3 topic"
index e7e424cc4b3a7ac89634686b6326033d0c226c7e..cbac2dfd96dfd0f3826dcb669ab9b5400fb720f1 100644 (file)
@@ -211,7 +211,7 @@ Binding *get_binding_from_xcb_event(xcb_generic_event_t *event) {
     state_filtered &= 0xFF;
     DLOG("(removed upper 8 bits, state = %d)\n", state_filtered);
 
-    if (xkb_current_group == XkbGroup2Index)
+    if (xkb_current_group == XCB_XKB_GROUP_2)
         state_filtered |= BIND_MODE_SWITCH;
 
     DLOG("(checked mode_switch, state %d)\n", state_filtered);
@@ -294,8 +294,8 @@ void translate_keysyms(void) {
             bind->translated_to[bind->number_keycodes - 1] = i;
         }
 
-        DLOG("Translated symbol \"%s\" to %d keycode\n", bind->symbol,
-             bind->number_keycodes);
+        DLOG("Translated symbol \"%s\" to %d keycode (mods %d)\n", bind->symbol,
+             bind->number_keycodes, bind->mods);
     }
 }
 
index 51ffcf3ab3c4361452897713bf399bdf70c87302..55e7147c557237c6cef5d7a1ff10978c86bc154b 100644 (file)
@@ -380,11 +380,6 @@ int handle_button_press(xcb_button_press_event_t *event) {
         return 0;
     }
 
-    if (event->child != XCB_NONE) {
-        DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
-        return route_click(con, event, mod_pressed, CLICK_INSIDE);
-    }
-
     /* Check if the click was on the decoration of a child */
     Con *child;
     TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
@@ -394,5 +389,10 @@ int handle_button_press(xcb_button_press_event_t *event) {
         return route_click(child, event, mod_pressed, CLICK_DECORATION);
     }
 
+    if (event->child != XCB_NONE) {
+        DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
+        return route_click(con, event, mod_pressed, CLICK_INSIDE);
+    }
+
     return route_click(con, event, mod_pressed, CLICK_BORDER);
 }
index c41352bdf5acf8df6e61ec9859c17a46e89aa89d..f5f8d05c7c9a1befe8b9ea4112edc93dcdca8aed 100644 (file)
@@ -65,28 +65,6 @@ static bool definitelyGreaterThan(float a, float b, float epsilon) {
     return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
 }
 
-/*
- * Returns an 'output' corresponding to one of left/right/down/up or a specific
- * output name.
- *
- */
-static Output *get_output_from_string(Output *current_output, const char *output_str) {
-    Output *output;
-
-    if (strcasecmp(output_str, "left") == 0)
-        output = get_output_next_wrap(D_LEFT, current_output);
-    else if (strcasecmp(output_str, "right") == 0)
-        output = get_output_next_wrap(D_RIGHT, current_output);
-    else if (strcasecmp(output_str, "up") == 0)
-        output = get_output_next_wrap(D_UP, current_output);
-    else if (strcasecmp(output_str, "down") == 0)
-        output = get_output_next_wrap(D_DOWN, current_output);
-    else
-        output = get_output_by_name(output_str);
-
-    return output;
-}
-
 /*
  * Returns the output containing the given container.
  */
@@ -909,7 +887,7 @@ void cmd_append_layout(I3_CMD, char *path) {
     LOG("JSON content = %d\n", content);
     if (content == JSON_CONTENT_UNKNOWN) {
         ELOG("Could not determine the contents of \"%s\", not loading.\n", path);
-        ysuccess(false);
+        yerror("Could not determine the contents of \"%s\".", path);
         free(path);
         return;
     }
@@ -1250,102 +1228,13 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
 
     owindow *current;
     TAILQ_FOREACH(current, &owindows, owindows) {
-        Output *current_output = get_output_of_con(current->con);
-        if (!current_output) {
-            ELOG("Cannot get current output. This is a bug in i3.\n");
-            ysuccess(false);
-            return;
-        }
-        Output *output = get_output_from_string(current_output, name);
-        if (!output) {
-            ELOG("Could not get output from string \"%s\"\n", name);
+        Con *ws = con_get_workspace(current->con);
+        bool success = workspace_move_to_output(ws, name);
+        if (!success) {
+            ELOG("Failed to move workspace to output.\n");
             ysuccess(false);
             return;
         }
-
-        Con *content = output_get_content(output->con);
-        LOG("got output %p with content %p\n", output, content);
-
-        Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head));
-        LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name);
-
-        Con *ws = con_get_workspace(current->con);
-        LOG("should move workspace %p / %s\n", ws, ws->name);
-        bool workspace_was_visible = workspace_is_visible(ws);
-
-        if (con_num_children(ws->parent) == 1) {
-            LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name);
-
-            /* check if we can find a workspace assigned to this output */
-            bool used_assignment = false;
-            struct Workspace_Assignment *assignment;
-            TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
-                if (strcmp(assignment->output, current_output->name) != 0)
-                    continue;
-
-                /* check if this workspace is already attached to the tree */
-                Con *workspace = NULL, *out;
-                TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
-                GREP_FIRST(workspace, output_get_content(out),
-                           !strcasecmp(child->name, assignment->name));
-                if (workspace != NULL)
-                    continue;
-
-                /* so create the workspace referenced to by this assignment */
-                LOG("Creating workspace from assignment %s.\n", assignment->name);
-                workspace_get(assignment->name, NULL);
-                used_assignment = true;
-                break;
-            }
-
-            /* if we couldn't create the workspace using an assignment, create
-             * it on the output */
-            if (!used_assignment)
-                create_workspace_on_output(current_output, ws->parent);
-
-            /* notify the IPC listeners */
-            ipc_send_workspace_event("init", ws, NULL);
-        }
-        DLOG("Detaching\n");
-
-        /* detach from the old output and attach to the new output */
-        Con *old_content = ws->parent;
-        con_detach(ws);
-        if (workspace_was_visible) {
-            /* The workspace which we just detached was visible, so focus
-             * the next one in the focus-stack. */
-            Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head));
-            LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name);
-            workspace_show(focus_ws);
-        }
-        con_attach(ws, content, false);
-
-        /* fix the coordinates of the floating containers */
-        Con *floating_con;
-        TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
-        floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
-
-        ipc_send_workspace_event("move", ws, NULL);
-        if (workspace_was_visible) {
-            /* Focus the moved workspace on the destination output. */
-            workspace_show(ws);
-        }
-
-        /* NB: We cannot simply work with previously_visible_ws since it might
-         * have been cleaned up by workspace_show() already, depending on the
-         * focus order/number of other workspaces on the output.
-         * Instead, we loop through the available workspaces and only work with
-         * previously_visible_ws if we still find it. */
-        TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
-            if (ws != previously_visible_ws)
-                continue;
-
-            /* Call the on_remove_child callback of the workspace which previously
-             * was visible on the destination output. Since it is no longer
-             * visible, it might need to get cleaned up. */
-            CALL(previously_visible_ws, on_remove_child);
-            break;
-        }
     }
 
     cmd_output->needs_tree_render = true;
@@ -2019,6 +1908,22 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
     Con *parent = workspace->parent;
     con_detach(workspace);
     con_attach(workspace, parent, false);
+
+    /* Move the workspace to the correct output if it has an assignment */
+    struct Workspace_Assignment *assignment = NULL;
+    TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+        if (assignment->output == NULL)
+            continue;
+        if (strcmp(assignment->name, workspace->name) != 0
+            && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) {
+
+            continue;
+        }
+
+        workspace_move_to_output(workspace, assignment->output);
+        break;
+    }
+
     /* Restore the previous focus since con_attach messes with the focus. */
     con_focus(previously_focused);
 
index 24cebcece9707755087d83928a49030629ecea63..b229b445ba24ae71358cfcc891e4fafa06d40490 100644 (file)
@@ -823,11 +823,11 @@ static char *migrate_config(char *input, off_t size) {
         fprintf(stderr, "Migration process exit code was != 0\n");
         if (returncode == 2) {
             fprintf(stderr, "could not start the migration script\n");
-            /* TODO: script was not found. tell the user to fix his system or create a v4 config */
+            /* TODO: script was not found. tell the user to fix their system or create a v4 config */
         } else if (returncode == 1) {
             fprintf(stderr, "This already was a v4 config. Please add the following line to your config file:\n");
             fprintf(stderr, "# i3 config file (v4)\n");
-            /* TODO: nag the user with a message to include a hint for i3 in his config file */
+            /* TODO: nag the user with a message to include a hint for i3 in their config file */
         }
         return NULL;
     }
index 37a61036f00a2761df4fa8c723113e56ac4590f8..0cd397fd0669e6f855dc80e6a4957498f3c8c1b6 100644 (file)
@@ -106,7 +106,7 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) {
         return;
     }
 
-    /* Focus the output on which the user moved his cursor */
+    /* Focus the output on which the user moved their cursor */
     Con *old_focused = focused;
     Con *next = con_descend_focused(output_get_content(output->con));
     /* Since we are switching outputs, this *must* be a different workspace, so
@@ -149,7 +149,7 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) {
         enter_child = true;
     }
 
-    /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */
+    /* If not, then the user moved their cursor to the root window. In that case, we adjust c_ws */
     if (con == NULL) {
         DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y);
         check_crossing_screen_boundary(event->root_x, event->root_y);
@@ -804,21 +804,6 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             XCB_ATOM_CARDINAL, 32, 4,
             &r);
         xcb_flush(conn);
-    } else if (event->type == A_WM_CHANGE_STATE) {
-        /* http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4 */
-        Con *con = con_by_window_id(event->window);
-
-        if (con && event->data.data32[0] == 3) {
-            /* this request is so we can play some animiation showing the
-             * window physically moving to the tray before we close it (I
-             * think) */
-            DLOG("Client has requested iconic state. Closing this con. (con = %p)\n", con);
-            tree_close(con, DONT_KILL_WINDOW, false, false);
-            tree_render();
-        } else {
-            DLOG("Not handling WM_CHANGE_STATE request. (window = %d, state = %d)\n", event->window, event->data.data32[0]);
-        }
-
     } else if (event->type == A__NET_CURRENT_DESKTOP) {
         /* This request is used by pagers and bars to change the current
          * desktop likely as a result of some user action. We interpret this as
@@ -1282,7 +1267,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
             /* See The XKB Extension: Library Specification, section 14.1 */
             /* We check if the current group (each group contains
              * two levels) has been changed. Mode_switch activates
-             * group XkbGroup2Index */
+             * group XCB_XKB_GROUP_2 */
             if (xkb_current_group == state->group)
                 return;
             xkb_current_group = state->group;
@@ -1292,7 +1277,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
                 grab_all_keys(conn, false);
             } else {
                 DLOG("Mode_switch enabled\n");
-                grab_all_keys(conn, false);
+                grab_all_keys(conn, true);
             }
         }
 
@@ -1330,7 +1315,7 @@ void handle_event(int type, xcb_generic_event_t *event) {
             handle_motion_notify((xcb_motion_notify_event_t *)event);
             break;
 
-        /* Enter window = user moved his mouse over the window */
+        /* Enter window = user moved their mouse over the window */
         case XCB_ENTER_NOTIFY:
             handle_enter_notify((xcb_enter_notify_event_t *)event);
             break;
index 708df38e0af57f77fe0a655adf5c2884c709dad7..8b514178bbbf3283fc9391f11ef5c6f42643ba1a 100644 (file)
@@ -778,7 +778,7 @@ int main(int argc, char *argv[]) {
         ELOG("Could not setup signal handler");
 
     /* Ignore SIGPIPE to survive errors when an IPC client disconnects
-     * while we are sending him a message */
+     * while we are sending them a message */
     signal(SIGPIPE, SIG_IGN);
 
     /* Autostarting exec-lines */
index 6499c65df77d46dea56fb8c75b432ebedb1dad61..822a0f8891004b5c8c8b14cc4c8f68deace51f3b 100644 (file)
@@ -24,3 +24,25 @@ Con *output_get_content(Con *output) {
 
     return NULL;
 }
+
+/*
+ * Returns an 'output' corresponding to one of left/right/down/up or a specific
+ * output name.
+ *
+ */
+Output *get_output_from_string(Output *current_output, const char *output_str) {
+    Output *output;
+
+    if (strcasecmp(output_str, "left") == 0)
+        output = get_output_next_wrap(D_LEFT, current_output);
+    else if (strcasecmp(output_str, "right") == 0)
+        output = get_output_next_wrap(D_RIGHT, current_output);
+    else if (strcasecmp(output_str, "up") == 0)
+        output = get_output_next_wrap(D_UP, current_output);
+    else if (strcasecmp(output_str, "down") == 0)
+        output = get_output_next_wrap(D_DOWN, current_output);
+    else
+        output = get_output_by_name(output_str);
+
+    return output;
+}
index 11590a33b1969a8d67656fea477d4cbb718a624f..0f6e54f9cc18e68d01d832680ab201e4b503838d 100644 (file)
@@ -219,7 +219,7 @@ static void open_placeholder_window(Con *con) {
         Match *temp_id = smalloc(sizeof(Match));
         match_init(temp_id);
         temp_id->id = placeholder;
-        TAILQ_INSERT_TAIL(&(con->swallow_head), temp_id, matches);
+        TAILQ_INSERT_HEAD(&(con->swallow_head), temp_id, matches);
     }
 
     Con *child;
index a30566339f246b40e10de9932d1eac7f82a1ab6e..f55c920ebd4697b7cd9346c8d233993d7625c202 100644 (file)
@@ -879,3 +879,111 @@ Con *workspace_encapsulate(Con *ws) {
 
     return new;
 }
+
+/**
+ * Move the given workspace to the specified output.
+ * This returns true if and only if moving the workspace was successful.
+ */
+bool workspace_move_to_output(Con *ws, char *name) {
+    LOG("Trying to move workspace %p / %s to output \"%s\".\n", ws, ws->name, name);
+
+    Con *current_output_con = con_get_output(ws);
+    if (!current_output_con) {
+        ELOG("Could not get the output container for workspace %p / %s.\n", ws, ws->name);
+        return false;
+    }
+
+    Output *current_output = get_output_by_name(current_output_con->name);
+    if (!current_output) {
+        ELOG("Cannot get current output. This is a bug in i3.\n");
+        return false;
+    }
+    Output *output = get_output_from_string(current_output, name);
+    if (!output) {
+        ELOG("Could not get output from string \"%s\"\n", name);
+        return false;
+    }
+
+    Con *content = output_get_content(output->con);
+    LOG("got output %p with content %p\n", output, content);
+
+    Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head));
+    LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name);
+
+    bool workspace_was_visible = workspace_is_visible(ws);
+    if (con_num_children(ws->parent) == 1) {
+        LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name);
+
+        /* check if we can find a workspace assigned to this output */
+        bool used_assignment = false;
+        struct Workspace_Assignment *assignment;
+        TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+            if (assignment->output == NULL || strcmp(assignment->output, current_output->name) != 0)
+                continue;
+
+            /* check if this workspace is already attached to the tree */
+            Con *workspace = NULL, *out;
+            TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
+            GREP_FIRST(workspace, output_get_content(out),
+                       !strcasecmp(child->name, assignment->name));
+            if (workspace != NULL)
+                continue;
+
+            /* so create the workspace referenced to by this assignment */
+            LOG("Creating workspace from assignment %s.\n", assignment->name);
+            workspace_get(assignment->name, NULL);
+            used_assignment = true;
+            break;
+        }
+
+        /* if we couldn't create the workspace using an assignment, create
+         * it on the output */
+        if (!used_assignment)
+            create_workspace_on_output(current_output, ws->parent);
+
+        /* notify the IPC listeners */
+        ipc_send_workspace_event("init", ws, NULL);
+    }
+    DLOG("Detaching\n");
+
+    /* detach from the old output and attach to the new output */
+    Con *old_content = ws->parent;
+    con_detach(ws);
+    if (workspace_was_visible) {
+        /* The workspace which we just detached was visible, so focus
+         * the next one in the focus-stack. */
+        Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head));
+        LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name);
+        workspace_show(focus_ws);
+    }
+    con_attach(ws, content, false);
+
+    /* fix the coordinates of the floating containers */
+    Con *floating_con;
+    TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
+    floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
+
+    ipc_send_workspace_event("move", ws, NULL);
+    if (workspace_was_visible) {
+        /* Focus the moved workspace on the destination output. */
+        workspace_show(ws);
+    }
+
+    /* NB: We cannot simply work with previously_visible_ws since it might
+     * have been cleaned up by workspace_show() already, depending on the
+     * focus order/number of other workspaces on the output.
+     * Instead, we loop through the available workspaces and only work with
+     * previously_visible_ws if we still find it. */
+    TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
+        if (ws != previously_visible_ws)
+            continue;
+
+        /* Call the on_remove_child callback of the workspace which previously
+         * was visible on the destination output. Since it is no longer
+         * visible, it might need to get cleaned up. */
+        CALL(previously_visible_ws, on_remove_child);
+        break;
+    }
+
+    return true;
+}
diff --git a/testcases/t/231-wm-change-state.t b/testcases/t/231-wm-change-state.t
deleted file mode 100644 (file)
index 92992b4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!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)
-#
-# Correctly handle WM_CHANGE_STATE requests for the iconic state
-# See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4
-# Ticket: #1279
-# Bug still in: 4.8-7-gf4a8253
-use i3test;
-
-sub send_iconic_state_request {
-    my ($win) = @_;
-
-    my $msg = pack "CCSLLLLLL",
-        X11::XCB::CLIENT_MESSAGE, # response_type
-        32, # format
-        0, # sequence
-        $win->id, # window
-        $x->atom(name => 'WM_CHANGE_STATE')->id, # message type
-        3, # data32[0]
-        0, # data32[1]
-        0, # data32[2]
-        0, # data32[3]
-        0; # data32[4]
-
-    $x->send_event(0, $x->get_root_window(), X11::XCB::EVENT_MASK_SUBSTRUCTURE_REDIRECT, $msg);
-}
-
-my $ws = fresh_workspace;
-my $win = open_window;
-
-send_iconic_state_request($win);
-sync_with_i3;
-
-is(@{get_ws($ws)->{nodes}}, 0, 'When a window requests the iconic state, the container should be closed');
-
-done_testing;
diff --git a/testcases/t/522-rename-assigned-workspace.t b/testcases/t/522-rename-assigned-workspace.t
new file mode 100644 (file)
index 0000000..aa69d66
--- /dev/null
@@ -0,0 +1,90 @@
+#!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 workspaces are moved to the assigned output if they
+# are renamed to an assigned name.
+# Ticket: #1473
+
+use i3test i3_autostart => 0;
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+fake-outputs 1024x768+0+0,1024x768+1024+0
+
+workspace 1 output fake-0
+workspace 2 output fake-1
+workspace 3:foo output fake-1
+workspace baz output fake-1
+EOT
+
+my $pid = launch_with_config($config);
+my $i3 = i3(get_socket_path());
+$i3->connect->recv;
+
+# Returns the name of the output on which this workspace resides
+sub get_output_for_workspace {
+    my $ws_name = shift @_;
+
+    foreach (grep { not $_->{name} =~ /^__/ } @{$i3->get_tree->recv->{nodes}}) {
+        my $output = $_->{name};
+        foreach (grep { $_->{name} =~ "content" } @{$_->{nodes}}) {
+            return $output if $_->{nodes}[0]->{name} =~ $ws_name;
+        }
+    }
+}
+
+##########################################################################
+# Renaming the workspace to an unassigned name does not move the workspace
+# (regression test)
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to unassigned';
+is(get_output_for_workspace('unassigned'), 'fake-0',
+    'Unassigned workspace should stay on its output when being renamed');
+
+##########################################################################
+# Renaming a workspace by number only triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to 2';
+is(get_output_for_workspace('2'), 'fake-1',
+    'Renaming the workspace to a number should move it to the assigned output');
+
+##########################################################################
+# Renaming a workspace by number and name triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to "2:foo"';
+is(get_output_for_workspace('2:foo'), 'fake-1',
+    'Renaming the workspace to a number and name should move it to the assigned output');
+
+##########################################################################
+# Renaming a workspace by name only triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to baz';
+is(get_output_for_workspace('baz'), 'fake-1',
+    'Renaming the workspace to a number and name should move it to the assigned output');
+
+
+exit_gracefully($pid);
+done_testing;