1. Read http://i3wm.org/docs/debugging.html
2. Make sure you include a link to your logfile in your report (section 3).
3. Make sure you include the i3 version number in your report (section 1).
+4. Please be aware that we cannot support compatibility issues with
+ closed-source software, as digging into compatibility problems without
+ having access to the source code is too time-consuming. Additionally,
+ experience has shown that often, the software in question is responsible for
+ the issue. Please raise an issue with the software in question, not i3.
# Pull requests
+++ /dev/null
-
- ┌──────────────────────────────┐
- │ Release notes for i3 v4.10.1 │
- └──────────────────────────────┘
-
-This is i3 v4.10.1. This version is considered stable. All users of i3 are
-strongly encouraged to upgrade.
-
-This release contains mostly bugfixes, but we felt it was necessary since there
-are two important changes in behavior: we have reverted the pango markup
-parsing by default (introduced with i3 v4.9) and the change in how the
-“workspace” command behaves (introduced with i3 v4.9). Both of them broke some
-user’s setups, which is not acceptable. In order to help us avoid such mistakes
-in the future, please consider using the i3 git version — it is typically
-stable.
-
-PS: The v4.10 release did not contain any of the commits we meant to release
-due to a human error in our release automation. Hence the v4.10.1 release.
-
- ┌────────────────────────────┐
- │ Changes in i3 v4.10.1 │
- └────────────────────────────┘
-
- • i3bar: cut long statuslines from the left
- • i3bar: add support for the short_text property
- • i3-sensible-terminal: launch i3-nagbar when no terminal is found
- • i3-config-wizard: switch modifier on key up/down
- • docs/layout-saving: added a troubleshooting section
- • docs: degender all the terms
- • Revert "Workspace command number selection"
- • don’t parse blocks as markup by default
- • Allow escaping backslashes in commands.
- • switch default font from “DejaVu Sans Mono 8” to “monospace 8”, which is
- typically a synonym, except for users who prefer a different font.
- • When renaming a workspace, look for assignments and move the renamed
- workspace to the appropriate output.
- • i3-save-tree: make --workspace optional by defaulting to the focused
- workspace
- • Allow nop command without argument
-
- ┌────────────────────────────┐
- │ Bugfixes │
- └────────────────────────────┘
-
- • i3bar: buffer the statusline to avoid flickering
- • i3bar: fix click events for workspace buttons with long statusline
- • i3bar: set correct initial position when reconfiguring
- • i3bar: reconfigure strut partial on reload
- • i3-nagbar: fix sizes/positioning on hi-dpi displays
- • i3-config-wizard: fix sizes/positioning on hi-dpi displays
- • i3-input: fix sizes/positioning on hi-dpi displays
- • Fix scrolling in window decoration with hidden cursor.
- • workspace rename focus mismatch
- • Don’t overwrite border width when already set (placeholders).
- • fix a segfault during config file validation
- • Restore placeholder windows after restarting.
- • Don’t focus placeholder windows.
-
- ┌────────────────────────────┐
- │ Thanks! │
- └────────────────────────────┘
-
-Thanks for testing, bugfixes, discussions and everything I forgot go out to:
-
- Chih-Chyuan Hwang, Deiz, Diana Dinosaur, Ingo Bürk, Michael Hofmann,
- Michael Tipton, Micha Rosenbaum, shdown, Tony Crisci
-
--- Michael Stapelberg, 2015-03-29
--- /dev/null
+
+ ┌──────────────────────────────┐
+ │ Release notes for i3 v4.10.2 │
+ └──────────────────────────────┘
+
+This is i3 v4.10.2. This version is considered stable. All users of i3 are
+strongly encouraged to upgrade.
+
+ ┌────────────────────────────┐
+ │ Bugfixes │
+ └────────────────────────────┘
+
+ • Cope with non-null-terminated x class properties.
+ • Get workspace name when renaming current workspace (fixes crash).
+ • Use a reasonable default sep_block_width if a separator_symbol is given.
+ • Remove windows from the save set when unmapping.
+
+ ┌────────────────────────────┐
+ │ Thanks! │
+ └────────────────────────────┘
+
+Thanks for testing, bugfixes, discussions and everything I forgot go out to:
+
+ Ingo Bürk, Michael Hofmann,
+
+-- Michael Stapelberg, 2015-04-16
DEBUG=1
INSTALL=install
LN=ln
+PKG_CONFIG=pkg-config
ifndef PREFIX
PREFIX=/usr
endif
+ifndef EXEC_PREFIX
+ EXEC_PREFIX=$(PREFIX)
+endif
ifndef SYSCONFDIR
ifeq ($(PREFIX),/usr)
SYSCONFDIR=/etc
## Libraries flags
-ifeq ($(shell which pkg-config 2>/dev/null 1>/dev/null || echo 1),1)
+ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null 1>/dev/null || echo 1),1)
$(error "pkg-config was not found")
endif
#
# We redirect stderr to /dev/null because pkg-config prints an error if support
# for gnome-config was enabled but gnome-config is not actually installed.
-cflags_for_lib = $(shell pkg-config --silence-errors --cflags $(1) 2>/dev/null)
-ldflags_for_lib = $(shell pkg-config --exists 2>/dev/null $(1) && pkg-config --libs $(1) 2>/dev/null || echo -l$(2))
+cflags_for_lib = $(shell $(PKG_CONFIG) --silence-errors --cflags $(1) 2>/dev/null)
+ldflags_for_lib = $(shell $(PKG_CONFIG) --exists 2>/dev/null $(1) && $(PKG_CONFIG) --libs $(1) 2>/dev/null || echo -l$(2))
# XCB common stuff
XCB_CFLAGS := $(call cflags_for_lib, xcb)
XCB_CFLAGS += $(call cflags_for_lib, xcb-event)
XCB_LIBS := $(call ldflags_for_lib, xcb,xcb)
XCB_LIBS += $(call ldflags_for_lib, xcb-event,xcb-event)
-ifeq ($(shell pkg-config --exists xcb-util 2>/dev/null || echo 1),1)
+ifeq ($(shell $(PKG_CONFIG) --exists xcb-util 2>/dev/null || echo 1),1)
XCB_CFLAGS += $(call cflags_for_lib, xcb-atom)
XCB_CFLAGS += $(call cflags_for_lib, xcb-aux)
XCB_LIBS += $(call ldflags_for_lib, xcb-atom,xcb-atom)
# libpcre
PCRE_CFLAGS := $(call cflags_for_lib, libpcre)
-ifeq ($(shell pkg-config --atleast-version=8.10 libpcre 2>/dev/null && echo 1),1)
+ifeq ($(shell $(PKG_CONFIG) --atleast-version=8.10 libpcre 2>/dev/null && echo 1),1)
I3_CPPFLAGS += -DPCRE_HAS_UCP=1
endif
PCRE_LIBS := $(call ldflags_for_lib, libpcre,pcre)
-i3-wm (4.10.2-1) experimental; urgency=medium
+i3-wm (4.10.3-1) experimental; urgency=medium
* NOT YET RELEASED.
- -- Michael Stapelberg <stapelberg@debian.org> Sun, 29 Mar 2015 19:10:38 +0200
+ -- Michael Stapelberg <stapelberg@debian.org> Thu, 16 Apr 2015 09:08:30 +0200
+
+i3-wm (4.10.2-1) experimental; urgency=medium
+
+ * New upstream release.
+
+ -- Michael Stapelberg <stapelberg@debian.org> Thu, 16 Apr 2015 09:02:53 +0200
i3-wm (4.10.1-1) experimental; urgency=medium
</div>\r
{disable-javascript%<div id="footnotes"><hr /></div>}\r
<div id="footer" lang="de">\r
-© 2009-2014 Michael Stapelberg, <a href="http://i3wm.org/impress.html">Impressum</a>
+© 2009 Michael Stapelberg, <a href="http://i3wm.org/impress.html">Impressum</a>
</div>\r
</body>\r
</html>\r
something to us to get your bug fixed. If you have any questions about the
process and/or need further help, do not hesitate to contact us!
-== Verify you are using i3 ≥ 4.7
+== Verify you are using i3 ≥ 4.10
-Only the latest major version of i3 is supported, i.e. version 4.7 currently.
-To verify which version you are running, use:
+Only the latest major version of i3 is supported. To verify which version
+you are running, use:
---------------
$ i3 --moreversion 2>&- || i3 --version
== Obtaining the debug logfile
+Please note that log files may contain sensitive data such as window titles.
+The best way to avoid submitting such information is to only run the necessary
+applications to reproduce the behavior when saving the log file. This will also
+make analyzing the log file easier.
+
No matter whether i3 misbehaved in some way without crashing or whether it just
crashed, the logfile provides all information necessary to debug the problem.
such as http://nopaste.info or http://pastebin.com because pasting large
amounts of text in IRC sometimes leads to incomplete lines (servers have line
length limitations) or flood kicks.
+
+== Debugging i3bar
+
+To debug i3bar problems, add +verbose yes+ to all +bar {}+ blocks in your i3 config
+and then restart all i3bar instances like this:
+
+---------------------------------------------------------------------
+$ killall i3bar
+$ for c in $(i3-msg -t get_bar_config | python -c \
+ 'import json,sys;print("\n".join(json.load(sys.stdin)))'); do \
+ (i3bar --bar_id=$c >i3bar.$c.log 2>&1) & \
+ done;
+---------------------------------------------------------------------
+
+There will now be +i3bar.*.log+ files in your current directory that you can provide
+in your bug report.
*Syntax*:
----------------------------------
-bindsym [--release] [--whole-window] [Modifiers+]button[n] command
+bindsym [--release] [--border] [--whole-window] [Modifiers+]button[n] command
----------------------------------
By default, the binding will only run when you click on the titlebar of the
-window. If the +--whole-window+ flag is given, it will run when any part of the
-window is clicked. If the +--release+ flag is given, it will run when the mouse
-button is released.
+window. If the +--release+ flag is given, it will run when the mouse button
+is released.
+
+If the +--whole-window+ flag is given, the binding will also run when any part
+of the window is clicked, with the exception of the border. To have a bind run
+when the border is clicked, specify the +--border+ flag.
*Examples*:
--------------------------------
also when restarting i3 you should use the +exec_always+
keyword. These commands will be run in order.
+See <<command_chaining>> for details on the special meaning of +;+ (semicolon)
+and +,+ (comma): they chain commands together in i3 and need to be escaped if
+you want to use them in your command.
+
*Syntax*:
-------------------
exec [--no-startup-id] command
i3-msg border none
--------------------------
+[[command_chaining]]
+
Commands can be chained by using +;+ (a semicolon). So, to move a window to a
specific workspace and immediately switch to that workspace, you can configure
the following keybinding:
Compares the window instance (the first part of WM_CLASS)
window_role::
Compares the window role (WM_WINDOW_ROLE).
+window_type::
+ Compare the window type (_NET_WM_WINDOW_TYPE). Possible values are
+ +normal+, +dialog+, +utility+, +toolbar+, +splash+, +menu+, +dropdown_menu+,
+ +popup_menu+ and +toolti+.
id::
Compares the X11 window ID, which you can get via +xwininfo+ for example.
title::
What good is a window manager if you can’t actually start any applications?
The exec command starts an application by passing the command you specify to a
shell. This implies that you can use globbing (wildcards) and programs will be
-searched in your $PATH.
+searched in your +$PATH+.
+
+See <<command_chaining>> for details on the special meaning of +;+ (semicolon)
+and +,+ (comma): they chain commands together in i3 and need to be escaped if
+you want to use them in your command.
*Syntax*:
------------------------------
bindsym $mod+x move container to output VGA1
--------------------------------------------------------
+=== Moving containers/workspaces to marks
+
+To move a container to another container with a specific mark (see <<vim_like_marks>>),
+you can use the following command.
+
+The window will be moved right after the marked container in the tree, i.e., it ends up
+in the same position as if you had opened a new window when the marked container was
+focused. If the mark is on a split container, the window will appear as a new child
+after the currently focused child within that container.
+
+*Syntax*:
+------------------------------------
+move window|container to mark <mark>
+------------------------------------
+
+*Example*:
+--------------------------------------------------------
+for_window [instance="tabme"] move window to mark target
+--------------------------------------------------------
+
[[resizingconfig]]
=== Resizing containers/windows
# vim:ts=4:sw=4:expandtab
#
# i3 - an improved dynamic tiling window manager
-# © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+# © 2009 Michael Stapelberg and contributors (see also: LICENSE)
#
# generate-command-parser.pl: script to generate parts of the command parser
# from its specification file parser-specs/commands.spec.
install-i3-config-wizard: i3-config-wizard/i3-config-wizard
echo "[i3-config-wizard] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3-config-wizard/i3-config-wizard $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3-config-wizard/i3-config-wizard $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3-config-wizard:
echo "[i3-config-wizard] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-config-wizard: Program to convert configs using keycodes to configs using
* keysyms.
#!/usr/bin/env perl
# vim:ts=4:sw=4:expandtab
#
-# © 2012-2014 Michael Stapelberg
+# © 2012 Michael Stapelberg
#
# No dependencies except for perl ≥ v5.10
'dmenu=s' => \$dmenu_cmd,
'entry-type=s' => \@entry_types,
'version' => sub {
- say "dmenu-desktop 1.5 © 2012-2013 Michael Stapelberg";
+ say "dmenu-desktop 1.5 © 2012 Michael Stapelberg";
exit 0;
},
'help' => sub {
install-i3-dump-log: i3-dump-log/i3-dump-log
echo "[i3-dump-log] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3-dump-log/i3-dump-log $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3-dump-log/i3-dump-log $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3-dump-log:
echo "[i3-dump-log] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-dump-log/main.c: Dumps the i3 SHM log to stdout.
*
install-i3-input: i3-input/i3-input
echo "[i3-input] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3-input/i3-input $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3-input/i3-input $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3-input:
echo "[i3-input] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-input/main.c: Utility which lets the user input commands and sends them
* to i3.
install-i3-msg: i3-msg/i3-msg
echo "[i3-msg] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3-msg/i3-msg $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3-msg/i3-msg $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3-msg:
echo "[i3-msg] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-msg/main.c: Utility which sends messages to a running i3-instance using
* IPC via UNIX domain sockets.
install-i3-nagbar: i3-nagbar/i3-nagbar
echo "[i3-nagbar] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3-nagbar/i3-nagbar $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3-nagbar/i3-nagbar $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3-nagbar:
echo "[i3-nagbar] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 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 their configuration file.
#!/usr/bin/env perl
# vim:ts=4:sw=4:expandtab
#
-# © 2013-2014 Michael Stapelberg
+# © 2013 Michael Stapelberg
#
# Requires perl ≥ v5.10, AnyEvent::I3 and JSON::XS
install-i3bar: i3bar/i3bar
echo "[i3bar] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -m 0755 i3bar/i3bar $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
+ $(INSTALL) -m 0755 i3bar/i3bar $(DESTDIR)$(EXEC_PREFIX)/bin/
clean-i3bar:
echo "[i3bar] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* child.c: Getting input for the statusline
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
*/
#pragma once
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* config.c: Parses the configuration (received from i3).
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* ipc.c: Communicating with i3
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* mode.c: Handle "mode" event and show current binding mode in the bar
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* outputs.c: Maintaining the outputs list
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* parse_json_header.c: Parse the JSON protocol header to determine
* protocol version and features.
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
*/
#pragma once
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#pragma once
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* workspaces.c: Maintaining the workspace lists
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* xcb.c: Communicating with X
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* child.c: Getting input for the statusline
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2011 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* config.c: Parses the configuration (received from i3).
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* ipc.c: Communicating with i3
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
*/
#include <stdio.h>
socket_path = expand_path(optarg);
break;
case 'v':
- printf("i3bar version " I3_VERSION " © 2010-2014 Axel Wagner and contributors\n");
+ printf("i3bar version " I3_VERSION " © 2010 Axel Wagner and contributors\n");
exit(EXIT_SUCCESS);
break;
case 'b':
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* mode.c: Handle mode event and show current binding mode in the bar
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* outputs.c: Maintaining the outputs list
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* parse_json_header.c: Parse the JSON protocol header to determine
* protocol version and features.
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* workspaces.c: Maintaining the workspace lists
*
* vim:ts=4:sw=4:expandtab
*
* i3bar - an xcb-based status- and ws-bar for i3
- * © 2010-2012 Axel Wagner and contributors (see also: LICENSE)
+ * © 2010 Axel Wagner and contributors (see also: LICENSE)
*
* xcb.c: Communicating with X
*
int offset = walk->rect.w - statusline_width - tray_width - logical_px(sb_hoff_px);
x = original_x - offset;
- if (x >= 0) {
+ if (x >= 0 && (size_t)x < statusline_width) {
struct status_block *block;
int sep_offset_remainder = 0;
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* This header file includes all relevant files of i3 and the most often used
* system header files. This reduces boilerplate (the amount of code duplicated
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* assignments.c: Assignments for specific windows (for_window).
*
xmacro(_NET_WM_STATE_FULLSCREEN)
xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
xmacro(_NET_WM_STATE_MODAL)
+xmacro(_NET_WM_STATE_HIDDEN)
xmacro(_NET_WM_STATE)
xmacro(_NET_WM_WINDOW_TYPE)
+xmacro(_NET_WM_WINDOW_TYPE_NORMAL)
xmacro(_NET_WM_WINDOW_TYPE_DOCK)
xmacro(_NET_WM_WINDOW_TYPE_DIALOG)
xmacro(_NET_WM_WINDOW_TYPE_UTILITY)
xmacro(_NET_WM_WINDOW_TYPE_TOOLBAR)
xmacro(_NET_WM_WINDOW_TYPE_SPLASH)
+xmacro(_NET_WM_WINDOW_TYPE_MENU)
+xmacro(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
+xmacro(_NET_WM_WINDOW_TYPE_POPUP_MENU)
+xmacro(_NET_WM_WINDOW_TYPE_TOOLTIP)
xmacro(_NET_WM_DESKTOP)
xmacro(_NET_WM_STRUT_PARTIAL)
xmacro(_NET_CLIENT_LIST)
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2014 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* bindings.h: Functions for configuring, finding, and running bindings.
*
*
*/
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
- const char *release, const char *whole_window, const char *command, const char *mode);
+ const char *release, const char *border, const char *whole_window,
+ const char *command, const char *mode);
/**
* Grab the bound keys (tell X to send us keypress events for those keycodes)
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* click.c: Button press (mouse click) events.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* cmdparse.y: the parser for commands you send to i3 (or bind on keys)
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* commands.c: all command functions (see commands_parser.c)
*
*/
void cmd_move_con_to_output(I3_CMD, char *name);
+/**
+ * Implementation of 'move [window|container] [to] mark <str>'.
+ *
+ */
+void cmd_move_con_to_mark(I3_CMD, char *mark);
+
/**
* Implementation of 'floating enable|disable|toggle'
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* commands.c: all command functions (see commands_parser.c)
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* con.c: Functions which deal with containers directly (creating containers,
* searching containers, getting specific properties from containers,
*/
bool con_has_managed_window(Con *con);
-/*
+/**
* Returns true if a container should be considered split.
*
*/
bool con_is_split(Con *con);
+/**
+ * This will only return true for containers which have some parent with
+ * a tabbed / stacked parent of which they are not the currently focused child.
+ *
+ */
+bool con_is_hidden(Con *con);
+
/**
* Returns true if this node has regular or floating children.
*
*/
Con *con_by_frame_id(xcb_window_t frame);
+/**
+ * Returns the container with the given mark or NULL if no such container
+ * exists.
+ *
+ */
+Con *con_by_mark(const char *mark);
+
/**
* Returns the first container below 'con' which wants to swallow this window
* TODO: priority
*/
void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool dont_warp);
+/**
+ * Moves the given container to the given mark.
+ *
+ */
+bool con_move_to_mark(Con *con, const char *mark);
+
/**
* Returns the orientation of the given container (for stacked containers,
* vertical orientation is used regardless of the actual orientation of the
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* include/config.h: Contains all structs/variables for the configurable
* part of i3 as well as functions handling the configuration file (calling
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config_directives.h: all config storing functions (see config_parser.c)
*
CFGFUN(floating_modifier, const char *modifiers);
CFGFUN(new_window, const char *windowtype, const char *border, const long width);
CFGFUN(workspace, const char *workspace, const char *output);
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command);
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command);
CFGFUN(enter_mode, const char *mode);
-CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command);
+CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command);
CFGFUN(bar_font, const char *font);
CFGFUN(bar_separator_symbol, const char *separator);
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config_parser.h: config parser-related definitions
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* include/data.h: This file defines all data structures used by i3
*
B_UPON_KEYRELEASE_IGNORE_MODS = 2,
} release;
+ /** If this is true for a mouse binding, the binding should be executed
+ * when the button is pressed over the window border. */
+ bool border;
+
/** If this is true for a mouse binding, the binding should be executed
* when the button is pressed over any part of the window, not just the
* title bar (default). */
* default will be 'accepts focus'. */
bool doesnt_accept_focus;
+ /** The _NET_WM_WINDOW_TYPE for this window. */
+ xcb_atom_t window_type;
+
/** Whether the window says it is a dock window */
enum { W_NODOCK = 0,
W_DOCK_TOP = 1,
struct regex *instance;
struct regex *mark;
struct regex *window_role;
+ xcb_atom_t window_type;
enum {
U_DONTCHECK = -1,
U_LATEST = 0,
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* debug.c: Debugging functions, especially FormatEvent, which prints unhandled
* events. This code is from xcb-util.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* display_version.c: displays the running i3 version, runs as part of
* i3 --moreversion.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* ewmh.c: Get/set certain EWMH properties easily.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* Faking outputs is useful in pathological situations (like network X servers
* which don’t support multi-monitor in a useful way) and for our testsuite.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* floating.c: Floating windows.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* handlers.c: Small handlers for various events (keypresses, focus changes,
* …).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3.h: global variables that are used all over i3.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* This public header defines the different constants and message types to use
* for the IPC interface to i3 (see docs/ipc for more information).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* key_press.c: key press handler
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* libi3: contains functions which are used by i3 *and* accompanying tools such
* as i3-msg, i3-config-wizard, …
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2014 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* load_layout.c: Restore (parts of) the layout, for example after an inplace
* restart.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* log.c: Logging functions.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* main.c: Initialization, main loop
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* manage.c: Initially managing new windows (or existing ones on restart).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* A "match" is a data structure which acts like a mask or expression to match
* certain windows or not. For example, when using commands, you can specify a
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* move.c: Moving containers into some direction.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* output.c: Output (monitor) related functions.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* For more information on RandR, please see the X.org RandR specification at
* http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* regex.c: Interface to libPCRE (perl compatible regular expressions).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* render.c: Renders (determines position/sizes) the layout tree, updating the
* various rects. Needs to be pushed to X11 (see x.c) to be visible.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* resize.c: Interactive resizing.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* restore_layout.c: Everything for restored containers that is not pure state
* parsing (which can be found in load_layout.c).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* scratchpad.c: Scratchpad functions (TODO: more description)
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* The format of the shmlog data structure which i3 development versions use by
* default (ringbuffer for storing the debug log).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
- * © 2009-2010 Jan-Erik Rediger
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Jan-Erik Rediger
*
* sighandler.c: Interactive crash dialog upon SIGSEGV/SIGABRT/SIGFPE (offers
* to restart inplace).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* startup.c: Startup notification code. Ensures a startup notification context
* is setup when launching applications. We store the current
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* tree.c: Everything that primarily modifies the layout tree data structure.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* util.c: Utility functions, which can be useful everywhere within i3 (see
* also libi3).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* window.c: Updates window attributes (X11 hints/properties).
*
*/
void window_update_role(i3Window *win, xcb_get_property_reply_t *prop, bool before_mgmt);
+/**
+ * Updates the _NET_WM_WINDOW_TYPE property.
+ *
+ */
+void window_update_type(i3Window *window, xcb_get_property_reply_t *reply);
+
/**
* Updates the WM_HINTS (we only care about the input focus handling part).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* workspace.c: Modifying workspaces, accessing them, moving containers to
* workspaces.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* x.c: Interface to X11, transfers our in-memory state to X11 (see also
* render.c). Basically a big state machine.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* xcb.c: Helper functions for easier usage of XCB
*
*/
void xcb_set_window_rect(xcb_connection_t *conn, xcb_window_t window, Rect r);
+/**
+ * Returns the first supported _NET_WM_WINDOW_TYPE atom.
+ *
+ */
+xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply);
+
+/**
+ * Returns true if the given reply contains the given data.
+ *
+ */
bool xcb_reply_contains_atom(xcb_get_property_reply_t *prop, xcb_atom_t atom);
/**
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* xcb_compat.h: uses #define to create aliases for xcb functions which got
* renamed. Makes the code work with >= 0.3.8 xcb-util and
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* xcursor.c: libXcursor support for themed cursors.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* This is LEGACY code (we support RandR, which can do much more than
* Xinerama), but necessary for the poor users of the nVidia binary
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* yajl_utils.h
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2014 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include "libi3.h"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <stdlib.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <assert.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <stdlib.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2015 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include "libi3.h"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <stdint.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <assert.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include "libi3.h"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <sys/types.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <string.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <string.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2015 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <stdio.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <string.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* string.c: Define an i3String type to automagically handle UTF-8/UCS-2
* conversions. Some font backends need UCS-2 (X core fonts),
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <sys/types.h>
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include <err.h>
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
<refmiscinfo class="source">i3</refmiscinfo>
-<refmiscinfo class="version">4.10.1</refmiscinfo>
+<refmiscinfo class="version">4.10.2</refmiscinfo>
<refmiscinfo class="manual">i3 Manual</refmiscinfo>
</refmeta>
<refnamediv>
# vim:ts=2:sw=2:expandtab
#
# i3 - an improved dynamic tiling window manager
-# © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+# © 2009 Michael Stapelberg and contributors (see also: LICENSE)
#
# parser-specs/commands.spec: Specification file for generate-command-parser.pl
# which will generate the appropriate header files for our C parser.
'bar' -> BAR
state CRITERIA:
- ctype = 'class' -> CRITERION
- ctype = 'instance' -> CRITERION
+ ctype = 'class' -> CRITERION
+ ctype = 'instance' -> CRITERION
ctype = 'window_role' -> CRITERION
- ctype = 'con_id' -> CRITERION
- ctype = 'id' -> CRITERION
- ctype = 'con_mark' -> CRITERION
- ctype = 'title' -> CRITERION
- ctype = 'urgent' -> CRITERION
+ ctype = 'con_id' -> CRITERION
+ ctype = 'id' -> CRITERION
+ ctype = 'window_type' -> CRITERION
+ ctype = 'con_mark' -> CRITERION
+ ctype = 'title' -> CRITERION
+ ctype = 'urgent' -> CRITERION
']' -> call cmd_criteria_match_windows(); INITIAL
state CRITERION:
# move <direction> [<pixels> [px]]
# move [window|container] [to] workspace [<str>|next|prev|next_on_output|prev_on_output|current]
# move [window|container] [to] output <str>
+# move [window|container] [to] mark <str>
# move [window|container] [to] scratchpad
# move workspace to [output] <str>
# move scratchpad
-> MOVE_WORKSPACE
'output'
-> MOVE_TO_OUTPUT
+ 'mark'
+ -> MOVE_TO_MARK
'scratchpad'
-> call cmd_move_scratchpad()
direction = 'left', 'right', 'up', 'down'
output = string
-> call cmd_move_con_to_output($output)
+state MOVE_TO_MARK:
+ mark = string
+ -> call cmd_move_con_to_mark($mark)
+
state MOVE_WORKSPACE_TO_OUTPUT:
'output'
->
# vim:ts=2:sw=2:expandtab
#
# i3 - an improved dynamic tiling window manager
-# © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+# © 2009 Michael Stapelberg and contributors (see also: LICENSE)
#
# parser-specs/config.spec: Specification file for generate-command-parser.pl
# which will generate the appropriate header files for our C parser.
ctype = 'window_role' -> CRITERION
ctype = 'con_id' -> CRITERION
ctype = 'id' -> CRITERION
+ ctype = 'window_type' -> CRITERION
ctype = 'con_mark' -> CRITERION
ctype = 'title' -> CRITERION
ctype = 'urgent' -> CRITERION
state BINDING:
release = '--release'
->
+ border = '--border'
+ ->
whole_window = '--whole-window'
->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod'
state BINDCOMMAND:
release = '--release'
->
+ border = '--border'
+ ->
whole_window = '--whole-window'
->
command = string
- -> call cfg_binding($bindtype, $modifiers, $key, $release, $whole_window, $command)
+ -> call cfg_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command)
################################################################################
# Mode configuration
state MODE_BINDING:
release = '--release'
->
+ border = '--border'
+ ->
whole_window = '--whole-window'
->
modifiers = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Shift', 'Control', 'Ctrl', 'Mode_switch', '$mod'
state MODE_BINDCOMMAND:
release = '--release'
->
+ border = '--border'
+ ->
whole_window = '--whole-window'
->
command = string
- -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $whole_window, $command); MODE
+ -> call cfg_mode_binding($bindtype, $modifiers, $key, $release, $border, $whole_window, $command); MODE
################################################################################
# Bar configuration (i3bar)
#!/bin/zsh
# This script is used to prepare a new release of i3.
-export RELEASE_VERSION="4.10.1"
-export PREVIOUS_VERSION="4.10"
-export RELEASE_BRANCH="next"
+export RELEASE_VERSION="4.10.2"
+export PREVIOUS_VERSION="4.10.1"
+export RELEASE_BRANCH="master"
if [ ! -e "../i3.github.io" ]
then
# Section 3: website
################################################################################
+# Ensure we are in the correct branch for copying the docs.
+cd ${TMPDIR}/i3
+git checkout ${RELEASE_BRANCH}
+
cd ${TMPDIR}
git clone --quiet ${STARTDIR}/../i3.github.io
cd i3.github.io
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,Verify you are using i3 ≥ .*,Verify you are using i3 ≥ ${RELEASE_VERSION},g" docs/debugging.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 remote remove origin
git remote add origin git@github.com:i3/i3.github.io.git
+git config --add remote.origin.push "+refs/heads/master:refs/heads/master"
################################################################################
# Section 4: prepare release announcement email
From: Michael Stapelberg <michael@i3wm.org>
To: i3-announce@i3.zekjur.net
Subject: i3 v${RELEASE_VERSION} released
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
Hi,
I just released i3 v${RELEASE_VERSION}. Release notes follow:
EOT
-cat ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION}.txt >>email.txt
+cat ${TMPDIR}/i3/RELEASE-NOTES-${RELEASE_VERSION} >>email.txt
################################################################################
# Section 5: final push instructions
echo " cd ${TMPDIR}/i3"
echo " git checkout next"
echo " vi debian/changelog"
+echo " git commit -a -m \"debian: update changelog\""
echo " git push"
echo ""
echo " cd ${TMPDIR}/i3.github.io"
echo " dput *.changes"
echo ""
echo " cd ${TMPDIR}"
-echo " sendmail < email.txt"
+echo " sendmail -t < email.txt"
echo ""
echo "Announce on:"
echo " twitter"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* assignments.c: Assignments for specific windows (for_window).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2014 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* bindings.c: Functions for configuring, finding and, running bindings.
*/
*
*/
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
- const char *release, const char *whole_window, const char *command, const char *modename) {
+ const char *release, const char *border, const char *whole_window,
+ const char *command, const char *modename) {
Binding *new_binding = scalloc(sizeof(Binding));
DLOG("bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
+ new_binding->border = (border != NULL);
new_binding->whole_window = (whole_window != NULL);
if (strcmp(bindtype, "bindsym") == 0) {
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
if (con == NULL)
command = sstrdup(bind->command);
else
- sasprintf(&command, "[con_id=\"%d\"] %s", con, bind->command);
+ sasprintf(&command, "[con_id=\"%p\"] %s", con, bind->command);
Binding *bind_cp = binding_copy(bind);
CommandResult *result = parse_command(command, NULL);
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* click.c: Button press (mouse click) events.
*
/* if the user has bound an action to this click, it should override the
* default behavior. */
- if (dest == CLICK_DECORATION || dest == CLICK_INSIDE) {
+ if (dest == CLICK_DECORATION || dest == CLICK_INSIDE || dest == CLICK_BORDER) {
Binding *bind = get_binding_from_xcb_event((xcb_generic_event_t *)event);
/* clicks over a window decoration will always trigger the binding and
* clicks on the inside of the window will only trigger a binding if
* the --whole-window flag was given for the binding. */
- if (bind && (dest == CLICK_DECORATION || bind->whole_window)) {
+ if (bind && ((dest == CLICK_DECORATION || bind->whole_window) ||
+ (dest == CLICK_BORDER && bind->border))) {
CommandResult *result = run_binding(bind, con);
/* ASYNC_POINTER eats the event */
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* commands.c: all command functions (see commands_parser.c)
*
return;
}
+ if (strcmp(ctype, "window_type") == 0) {
+ if (strcasecmp(cvalue, "normal") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_NORMAL;
+ else if (strcasecmp(cvalue, "dialog") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_DIALOG;
+ else if (strcasecmp(cvalue, "utility") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_UTILITY;
+ else if (strcasecmp(cvalue, "toolbar") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR;
+ else if (strcasecmp(cvalue, "splash") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_SPLASH;
+ else if (strcasecmp(cvalue, "menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_MENU;
+ else if (strcasecmp(cvalue, "dropdown_menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
+ else if (strcasecmp(cvalue, "popup_menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU;
+ else if (strcasecmp(cvalue, "tooltip") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP;
+ else
+ ELOG("unknown window_type value \"%s\"\n", cvalue);
+
+ return;
+ }
+
if (strcmp(ctype, "con_mark") == 0) {
current_match->mark = regex_new(cvalue);
return;
}
DLOG("removed all window marks");
} else {
- Con *con;
- TAILQ_FOREACH(con, &all_cons, all_cons) {
- if (con->mark && strcmp(con->mark, mark) == 0) {
- FREE(con->mark);
- con->mark_changed = true;
- }
+ Con *con = con_by_mark(mark);
+ if (con != NULL) {
+ FREE(con->mark);
+ con->mark_changed = true;
}
DLOG("removed window mark %s\n", mark);
}
ysuccess(true);
}
+/*
+ * Implementation of 'move [container|window] [to] mark <str>'.
+ *
+ */
+void cmd_move_con_to_mark(I3_CMD, char *mark) {
+ DLOG("moving window to mark \"%s\"\n", mark);
+
+ HANDLE_EMPTY_MATCH;
+
+ bool result = true;
+ owindow *current;
+ TAILQ_FOREACH(current, &owindows, owindows) {
+ DLOG("moving matched window %p / %s to mark \"%s\"\n", current->con, current->con->name, mark);
+ result &= con_move_to_mark(current->con, mark);
+ }
+
+ cmd_output->needs_tree_render = true;
+ ysuccess(result);
+}
+
/*
* Implementation of 'floating enable|disable|toggle'
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* commands_parser.c: hand-written parser to parse commands (commands are what
* you bind on keys and what you can send to i3 using the IPC interface, like
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* con.c: Functions which deal with containers directly (creating containers,
* searching containers, getting specific properties from containers,
return new;
}
-/*
- * Attaches the given container to the given parent. This happens when moving
- * a container or when inserting a new container at a specific place in the
- * tree.
- *
- * ignore_focus is to just insert the Con at the end (useful when creating a
- * new split container *around* some containers, that is, detaching and
- * attaching them in order without wanting to mess with the focus in between).
- *
- */
-void con_attach(Con *con, Con *parent, bool ignore_focus) {
+static void _con_attach(Con *con, Con *parent, Con *previous, bool ignore_focus) {
con->parent = parent;
Con *loop;
- Con *current = NULL;
+ Con *current = previous;
struct nodes_head *nodes_head = &(parent->nodes_head);
struct focus_head *focus_head = &(parent->focus_head);
/* Insert the container after the tiling container, if found.
* When adding to a CT_OUTPUT, just append one after another. */
if (current && parent->type != CT_OUTPUT) {
- DLOG("Inserting con = %p after last focused tiling con %p\n",
- con, current);
+ DLOG("Inserting con = %p after con %p\n", con, current);
TAILQ_INSERT_AFTER(nodes_head, current, con, nodes);
} else
TAILQ_INSERT_TAIL(nodes_head, con, nodes);
con_force_split_parents_redraw(con);
}
+/*
+ * Attaches the given container to the given parent. This happens when moving
+ * a container or when inserting a new container at a specific place in the
+ * tree.
+ *
+ * ignore_focus is to just insert the Con at the end (useful when creating a
+ * new split container *around* some containers, that is, detaching and
+ * attaching them in order without wanting to mess with the focus in between).
+ *
+ */
+void con_attach(Con *con, Con *parent, bool ignore_focus) {
+ _con_attach(con, parent, NULL, ignore_focus);
+}
+
/*
* Detaches the given container from its current parent
*
}
}
+/*
+ * This will only return true for containers which have some parent with
+ * a tabbed / stacked parent of which they are not the currently focused child.
+ *
+ */
+bool con_is_hidden(Con *con) {
+ Con *current = con;
+
+ /* ascend to the workspace level and memorize the highest-up container
+ * which is stacked or tabbed. */
+ while (current != NULL && current->type != CT_WORKSPACE) {
+ Con *parent = current->parent;
+ if (parent != NULL && (parent->layout == L_TABBED || parent->layout == L_STACKED)) {
+ if (TAILQ_FIRST(&(parent->focus_head)) != current)
+ return true;
+ }
+
+ current = parent;
+ }
+
+ return false;
+}
+
/*
* Returns true if this node accepts a window (if the node swallows windows,
* it might already have swallowed enough and cannot hold any more).
return NULL;
}
+/*
+ * Returns the container with the given mark or NULL if no such container
+ * exists.
+ *
+ */
+Con *con_by_mark(const char *mark) {
+ Con *con;
+ TAILQ_FOREACH(con, &all_cons, all_cons) {
+ if (con->mark != NULL && strcmp(con->mark, mark) == 0)
+ return con;
+ }
+
+ return NULL;
+}
+
/*
* Returns the first container below 'con' which wants to swallow this window
* TODO: priority
con_set_fullscreen_mode(con, CF_NONE);
}
-/*
- * Moves the given container to the currently focused container on the given
- * workspace.
- *
- * The fix_coordinates flag will translate the current coordinates (offset from
- * the monitor position basically) to appropriate coordinates on the
- * destination workspace.
- * Not enabling this behaviour comes in handy when this function gets called by
- * floating_maybe_reassign_ws, which will only "move" a floating window when it
- * *already* changed its coordinates to a different output.
- *
- * The dont_warp flag disables pointer warping and will be set when this
- * function is called while dragging a floating window.
- *
- * TODO: is there a better place for this function?
- *
- */
-void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool dont_warp) {
+static bool _con_move_to_con(Con *con, Con *target, bool behind_focused, bool fix_coordinates, bool dont_warp) {
+ Con *orig_target = target;
+
/* Prevent moving if this would violate the fullscreen focus restrictions. */
- if (!con_fullscreen_permits_focusing(workspace)) {
+ Con *target_ws = con_get_workspace(target);
+ if (!con_fullscreen_permits_focusing(target_ws)) {
LOG("Cannot move out of a fullscreen container");
- return;
+ return false;
}
if (con_is_floating(con)) {
}
Con *source_ws = con_get_workspace(con);
- if (workspace == source_ws) {
- DLOG("Not moving, already there\n");
- return;
- }
if (con->type == CT_WORKSPACE) {
/* Re-parent all of the old workspace's floating windows. */
Con *child;
while (!TAILQ_EMPTY(&(source_ws->floating_head))) {
child = TAILQ_FIRST(&(source_ws->floating_head));
- con_move_to_workspace(child, workspace, true, true);
+ con_move_to_workspace(child, target_ws, true, true);
}
/* If there are no non-floating children, ignore the workspace. */
if (con_is_leaf(con))
- return;
+ return false;
con = workspace_encapsulate(con);
if (con == NULL) {
ELOG("Workspace failed to move its contents into a container!\n");
- return;
+ return false;
}
}
Con *current_ws = con_get_workspace(focused);
Con *source_output = con_get_output(con),
- *dest_output = con_get_output(workspace);
+ *dest_output = con_get_output(target_ws);
/* 1: save the container which is going to be focused after the current
* container is moved away */
Con *focus_next = con_next_focused(con);
- /* 2: get the focused container of this workspace */
- Con *next = con_descend_focused(workspace);
-
- /* 3: we go up one level, but only when next is a normal container */
- if (next->type != CT_WORKSPACE) {
- DLOG("next originally = %p / %s / type %d\n", next, next->name, next->type);
- next = next->parent;
+ /* 2: we go up one level, but only when target is a normal container */
+ if (target->type != CT_WORKSPACE) {
+ DLOG("target originally = %p / %s / type %d\n", target, target->name, target->type);
+ target = target->parent;
}
- /* 4: if the target container is floating, we get the workspace instead.
+ /* 3: if the target container is floating, we get the workspace instead.
* Only tiling windows need to get inserted next to the current container.
* */
- Con *floatingcon = con_inside_floating(next);
+ Con *floatingcon = con_inside_floating(target);
if (floatingcon != NULL) {
DLOG("floatingcon, going up even further\n");
- next = floatingcon->parent;
+ target = floatingcon->parent;
}
if (con->type == CT_FLOATING_CON) {
- Con *ws = con_get_workspace(next);
+ Con *ws = con_get_workspace(target);
DLOG("This is a floating window, using workspace %p / %s\n", ws, ws->name);
- next = ws;
+ target = ws;
}
if (source_output != dest_output) {
/* If moving to a visible workspace, call show so it can be considered
* focused. Must do before attaching because workspace_show checks to see
* if focused container is in its area. */
- if (workspace_is_visible(workspace)) {
- workspace_show(workspace);
+ if (workspace_is_visible(target_ws)) {
+ workspace_show(target_ws);
/* Don’t warp if told so (when dragging floating windows with the
* mouse for example) */
/* If moving a fullscreen container and the destination already has a
* fullscreen window on it, un-fullscreen the target's fullscreen con. */
- Con *fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
+ Con *fullscreen = con_get_fullscreen_con(target_ws, CF_OUTPUT);
if (con->fullscreen_mode != CF_NONE && fullscreen != NULL) {
con_toggle_fullscreen(fullscreen, CF_OUTPUT);
fullscreen = NULL;
}
- DLOG("Re-attaching container to %p / %s\n", next, next->name);
- /* 5: re-attach the con to the parent of this focused container */
+ DLOG("Re-attaching container to %p / %s\n", target, target->name);
+ /* 4: re-attach the con to the parent of this focused container */
Con *parent = con->parent;
con_detach(con);
- con_attach(con, next, false);
+ _con_attach(con, target, behind_focused ? NULL : orig_target, !behind_focused);
- /* 6: fix the percentages */
+ /* 5: fix the percentages */
con_fix_percent(parent);
con->percent = 0.0;
- con_fix_percent(next);
+ con_fix_percent(target);
- /* 7: focus the con on the target workspace, but only within that
+ /* 6: focus the con on the target workspace, but only within that
* workspace, that is, don’t move focus away if the target workspace is
* invisible.
* We don’t focus the con for i3 pseudo workspaces like __i3_scratch and
* we don’t focus when there is a fullscreen con on that workspace. */
- if (!con_is_internal(workspace) && !fullscreen) {
+ if (!con_is_internal(target_ws) && !fullscreen) {
/* We need to save the focused workspace on the output in case the
* new workspace is hidden and it's necessary to immediately switch
* back to the originally-focused workspace. */
con_focus(old_focus);
}
- /* 8: when moving to another workspace, we leave the focus on the current
+ /* 7: when moving to another workspace, we leave the focus on the current
* workspace. (see also #809) */
/* Descend focus stack in case focus_next is a workspace which can
if (source_ws == current_ws)
con_focus(con_descend_focused(focus_next));
- /* 9. If anything within the container is associated with a startup sequence,
+ /* 8. If anything within the container is associated with a startup sequence,
* delete it so child windows won't be created on the old workspace. */
struct Startup_Sequence *sequence;
xcb_get_property_cookie_t cookie;
CALL(parent, on_remove_child);
- /* 10. If the container was marked urgent, move the urgency hint. */
+ /* 9. If the container was marked urgent, move the urgency hint. */
if (urgent) {
workspace_update_urgent_flag(source_ws);
con_set_urgency(con, true);
}
ipc_send_window_event("move", con);
+ return true;
+}
+
+/*
+ * Moves the given container to the given mark.
+ *
+ */
+bool con_move_to_mark(Con *con, const char *mark) {
+ Con *target = con_by_mark(mark);
+ if (target == NULL) {
+ DLOG("found no container with mark \"%s\"\n", mark);
+ return false;
+ }
+
+ /* For floating target containers, we just send the window to the same workspace. */
+ if (con_is_floating(target)) {
+ DLOG("target container is floating, moving container to target's workspace.\n");
+ con_move_to_workspace(con, con_get_workspace(target), true, false);
+ return true;
+ }
+
+ /* For split containers, we use the currently focused container within it.
+ * This allows setting marks on, e.g., tabbed containers which will move
+ * con to a new tab behind the focused tab. */
+ if (con_is_split(target)) {
+ DLOG("target is a split container, descending to the currently focused child.\n");
+ target = TAILQ_FIRST(&(target->focus_head));
+ }
+
+ if (con == target) {
+ DLOG("cannot move the container to itself, aborting.\n");
+ return false;
+ }
+
+ return _con_move_to_con(con, target, false, true, false);
+}
+
+/*
+ * Moves the given container to the currently focused container on the given
+ * workspace.
+ *
+ * The fix_coordinates flag will translate the current coordinates (offset from
+ * the monitor position basically) to appropriate coordinates on the
+ * destination workspace.
+ * Not enabling this behaviour comes in handy when this function gets called by
+ * floating_maybe_reassign_ws, which will only "move" a floating window when it
+ * *already* changed its coordinates to a different output.
+ *
+ * The dont_warp flag disables pointer warping and will be set when this
+ * function is called while dragging a floating window.
+ *
+ * TODO: is there a better place for this function?
+ *
+ */
+void con_move_to_workspace(Con *con, Con *workspace, bool fix_coordinates, bool dont_warp) {
+ assert(workspace->type == CT_WORKSPACE);
+
+ Con *source_ws = con_get_workspace(con);
+ if (workspace == source_ws) {
+ DLOG("Not moving, already there\n");
+ return;
+ }
+
+ Con *target = con_descend_focused(workspace);
+ _con_move_to_con(con, target, true, fix_coordinates, dont_warp);
}
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config.c: Configuration file (calling the parser (src/config_parser.c) with
* the correct path, switching key bindings mode).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config_directives.c: all config storing functions (see config_parser.c)
*
return;
}
+ if (strcmp(ctype, "window_type") == 0) {
+ if (strcasecmp(cvalue, "normal") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_NORMAL;
+ else if (strcasecmp(cvalue, "dialog") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_DIALOG;
+ else if (strcasecmp(cvalue, "utility") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_UTILITY;
+ else if (strcasecmp(cvalue, "toolbar") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR;
+ else if (strcasecmp(cvalue, "splash") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_SPLASH;
+ else if (strcasecmp(cvalue, "menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_MENU;
+ else if (strcasecmp(cvalue, "dropdown_menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
+ else if (strcasecmp(cvalue, "popup_menu") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU;
+ else if (strcasecmp(cvalue, "tooltip") == 0)
+ current_match->window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP;
+ else
+ ELOG("unknown window_type value \"%s\"\n", cvalue);
+
+ return;
+ }
+
if (strcmp(ctype, "con_mark") == 0) {
current_match->mark = regex_new(cvalue);
return;
font_pattern = sstrdup(font);
}
-CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) {
- configure_binding(bindtype, modifiers, key, release, whole_window, command, DEFAULT_BINDING_MODE);
+CFGFUN(binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
+ configure_binding(bindtype, modifiers, key, release, border, whole_window, command, DEFAULT_BINDING_MODE);
}
/*******************************************************************************
static char *current_mode;
-CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *whole_window, const char *command) {
- configure_binding(bindtype, modifiers, key, release, whole_window, command, current_mode);
+CFGFUN(mode_binding, const char *bindtype, const char *modifiers, const char *key, const char *release, const char *border, const char *whole_window, const char *command) {
+ configure_binding(bindtype, modifiers, key, release, border, whole_window, command, current_mode);
}
CFGFUN(enter_mode, const char *modename) {
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* config_parser.c: hand-written parser to parse configuration directives.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* debug.c: Debugging functions, especially FormatEvent, which prints unhandled
* events. This code is from xcb-util.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* display_version.c: displays the running i3 version, runs as part of
* i3 --moreversion.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* ewmh.c: Get/set certain EWMH properties easily.
*
/* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
- /* only send the first 24 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 24, supported_atoms);
+ /* only send the first 30 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 30, supported_atoms);
}
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* Faking outputs is useful in pathological situations (like network X servers
* which don’t support multi-monitor in a useful way) and for our testsuite.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* floating.c: Floating windows.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* handlers.c: Small handlers for various events (keypresses, focus changes,
* …).
floating_drag_window(con->parent, &fake);
break;
case _NET_WM_MOVERESIZE_SIZE_TOPLEFT... _NET_WM_MOVERESIZE_SIZE_LEFT:
- floating_resize_window(con->parent, FALSE, &fake);
+ floating_resize_window(con->parent, false, &fake);
break;
default:
DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
}
}
-#if 0
-int handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
- xcb_atom_t atom, xcb_get_property_reply_t *property) {
- /* TODO: Implement this one. To do this, implement a little test program which sleep(1)s
- before changing this property. */
- ELOG("_NET_WM_WINDOW_TYPE changed, this is not yet implemented.\n");
- return 0;
+bool handle_window_type(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
+ xcb_atom_t atom, xcb_get_property_reply_t *reply) {
+ Con *con;
+ if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
+ return false;
+
+ window_update_type(con->window, reply);
+ return true;
}
-#endif
/*
* Handles the size hints set by a window, but currently only the part necessary for displaying
{0, UINT_MAX, handle_transient_for},
{0, 128, handle_windowrole_change},
{0, 128, handle_class_change},
- {0, UINT_MAX, handle_strut_partial_change}};
+ {0, UINT_MAX, handle_strut_partial_change},
+ {0, UINT_MAX, handle_window_type}};
#define NUM_HANDLERS (sizeof(property_handlers) / sizeof(struct property_handler_t))
/*
property_handlers[6].atom = A_WM_WINDOW_ROLE;
property_handlers[7].atom = XCB_ATOM_WM_CLASS;
property_handlers[8].atom = A__NET_WM_STRUT_PARTIAL;
+ property_handlers[9].atom = A__NET_WM_WINDOW_TYPE;
}
static void property_notify(uint8_t state, xcb_window_t window, xcb_atom_t atom) {
install-i3: i3
echo "[i3] Install"
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/bin
$(INSTALL) -d -m 0755 $(DESTDIR)$(SYSCONFDIR)/i3
- $(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/include/i3
+ $(INSTALL) -d -m 0755 $(DESTDIR)$(EXEC_PREFIX)/include/i3
$(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/share/xsessions
$(INSTALL) -d -m 0755 $(DESTDIR)$(PREFIX)/share/applications
- $(INSTALL) -m 0755 i3 $(DESTDIR)$(PREFIX)/bin/
- $(LN) -sf i3 $(DESTDIR)$(PREFIX)/bin/i3-with-shmlog
- $(INSTALL) -m 0755 i3-migrate-config-to-v4 $(DESTDIR)$(PREFIX)/bin/
- $(INSTALL) -m 0755 i3-sensible-editor $(DESTDIR)$(PREFIX)/bin/
- $(INSTALL) -m 0755 i3-sensible-pager $(DESTDIR)$(PREFIX)/bin/
- $(INSTALL) -m 0755 i3-sensible-terminal $(DESTDIR)$(PREFIX)/bin/
- $(INSTALL) -m 0755 i3-save-tree $(DESTDIR)$(PREFIX)/bin/
- $(INSTALL) -m 0755 i3-dmenu-desktop $(DESTDIR)$(PREFIX)/bin/
+ $(INSTALL) -m 0755 i3 $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(LN) -sf i3 $(DESTDIR)$(EXEC_PREFIX)/bin/i3-with-shmlog
+ $(INSTALL) -m 0755 i3-migrate-config-to-v4 $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(INSTALL) -m 0755 i3-sensible-editor $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(INSTALL) -m 0755 i3-sensible-pager $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(INSTALL) -m 0755 i3-sensible-terminal $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(INSTALL) -m 0755 i3-save-tree $(DESTDIR)$(EXEC_PREFIX)/bin/
+ $(INSTALL) -m 0755 i3-dmenu-desktop $(DESTDIR)$(EXEC_PREFIX)/bin/
test -e $(DESTDIR)$(SYSCONFDIR)/i3/config || $(INSTALL) -m 0644 i3.config $(DESTDIR)$(SYSCONFDIR)/i3/config
test -e $(DESTDIR)$(SYSCONFDIR)/i3/config.keycodes || $(INSTALL) -m 0644 i3.config.keycodes $(DESTDIR)$(SYSCONFDIR)/i3/config.keycodes
$(INSTALL) -m 0644 i3.xsession.desktop $(DESTDIR)$(PREFIX)/share/xsessions/i3.desktop
$(INSTALL) -m 0644 i3-with-shmlog.xsession.desktop $(DESTDIR)$(PREFIX)/share/xsessions/i3-with-shmlog.desktop
$(INSTALL) -m 0644 i3.applications.desktop $(DESTDIR)$(PREFIX)/share/applications/i3.desktop
- $(INSTALL) -m 0644 include/i3/ipc.h $(DESTDIR)$(PREFIX)/include/i3/
+ $(INSTALL) -m 0644 include/i3/ipc.h $(DESTDIR)$(EXEC_PREFIX)/include/i3/
clean-i3:
echo "[i3] Clean"
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* key_press.c: key press handler
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* load_layout.c: Restore (parts of) the layout, for example after an inplace
* restart.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* log.c: Logging functions.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* main.c: Initialization, main loop
*
only_check_config = true;
break;
case 'v':
- printf("i3 version %s © 2009-2014 Michael Stapelberg and contributors\n", i3_version);
+ printf("i3 version %s © 2009 Michael Stapelberg and contributors\n", i3_version);
exit(EXIT_SUCCESS);
break;
case 'm':
- printf("Binary i3 version: %s © 2009-2014 Michael Stapelberg and contributors\n", i3_version);
+ printf("Binary i3 version: %s © 2009 Michael Stapelberg and contributors\n", i3_version);
display_running_version();
exit(EXIT_SUCCESS);
break;
root_screen = xcb_aux_get_screen(conn, conn_screen);
root = root_screen->root;
+/* Place requests for the atoms we need as soon as possible */
+#define xmacro(atom) \
+ xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
+#include "atoms.xmacro"
+#undef xmacro
+
/* By default, we use the same depth and visual as the root window, which
* usually is TrueColor (24 bit depth) and the corresponding visual.
* However, we also check if a 32 bit depth and visual are available (for
xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
+/* Setup NetWM atoms */
+#define xmacro(name) \
+ do { \
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
+ if (!reply) { \
+ ELOG("Could not get atom " #name "\n"); \
+ exit(-1); \
+ } \
+ A_##name = reply->atom; \
+ free(reply); \
+ } while (0);
+#include "atoms.xmacro"
+#undef xmacro
+
load_configuration(conn, override_configpath, false);
if (config.ipc_socket_path == NULL) {
}
DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
-/* Place requests for the atoms we need as soon as possible */
-#define xmacro(atom) \
- xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
-#include "atoms.xmacro"
-#undef xmacro
-
xcursor_load_cursors();
/* Set a cursor for the root window (otherwise the root window will show no
restore_connect();
-/* Setup NetWM atoms */
-#define xmacro(name) \
- do { \
- xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
- if (!reply) { \
- ELOG("Could not get atom " #name "\n"); \
- exit(-1); \
- } \
- A_##name = reply->atom; \
- free(reply); \
- } while (0);
-#include "atoms.xmacro"
-#undef xmacro
-
property_handlers_init();
ewmh_setup_hints();
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* manage.c: Initially managing new windows (or existing ones on restart).
*
/* check if the window needs WM_TAKE_FOCUS */
cwindow->needs_take_focus = window_supports_protocol(cwindow->id, A_WM_TAKE_FOCUS);
+ /* read the preferred _NET_WM_WINDOW_TYPE atom */
+ cwindow->window_type = xcb_get_preferred_window_type(type_reply);
+
/* Where to start searching for a container that swallows the new one? */
Con *search_at = croot;
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* A "match" is a data structure which acts like a mask or expression to match
* certain windows or not. For example, when using commands, you can specify a
*/
void match_init(Match *match) {
memset(match, 0, sizeof(Match));
- match->dock = -1;
+ match->dock = M_DONTCHECK;
match->urgent = U_DONTCHECK;
+ /* we use this as the placeholder value for "not set". */
+ match->window_type = UINT32_MAX;
}
/*
match->window_role == NULL &&
match->urgent == U_DONTCHECK &&
match->id == XCB_NONE &&
+ match->window_type == UINT32_MAX &&
match->con_id == NULL &&
match->dock == -1 &&
match->floating == M_ANY);
}
}
+ if (match->window_type != UINT32_MAX) {
+ if (window->window_type == match->window_type) {
+ LOG("window_type matches (%i)\n", match->window_type);
+ } else {
+ return false;
+ }
+ }
+
Con *con = NULL;
if (match->urgent == U_LATEST) {
/* if the window isn't urgent, no sense in searching */
LOG("urgent matches oldest\n");
}
- if (match->dock != -1) {
+ if (match->dock != M_DONTCHECK) {
if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) ||
(window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) ||
((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) &&
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* move.c: Moving containers into some direction.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* output.c: Output (monitor) related functions.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* For more information on RandR, please see the X.org RandR specification at
* http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* regex.c: Interface to libPCRE (perl compatible regular expressions).
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* render.c: Renders (determines position/sizes) the layout tree, updating the
* various rects. Needs to be pushed to X11 (see x.c) to be visible.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* resize.c: Interactive resizing.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* restore_layout.c: Everything for restored containers that is not pure state
* parsing (which can be found in load_layout.c).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* scratchpad.c: Moving windows to the scratchpad and making them visible again.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
- * © 2009-2010 Jan-Erik Rediger
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Jan-Erik Rediger
*
* sighandler.c: Interactive crash dialog upon SIGSEGV/SIGABRT/SIGFPE (offers
* to restart inplace).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* startup.c: Startup notification code. Ensures a startup notification context
* is setup when launching applications. We store the current
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* tree.c: Everything that primarily modifies the layout tree data structure.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* util.c: Utility functions, which can be useful everywhere within i3 (see
* also libi3).
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2015 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* Stores the latest Git commit identifier so that it can be linked into i3
* and used dynamically without recompiling every object file.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* window.c: Updates window attributes (X11 hints/properties).
*
free(prop);
}
+/*
+ * Updates the _NET_WM_WINDOW_TYPE property.
+ *
+ */
+void window_update_type(i3Window *window, xcb_get_property_reply_t *reply) {
+ xcb_atom_t new_type = xcb_get_preferred_window_type(reply);
+ if (new_type == XCB_NONE) {
+ DLOG("cannot read _NET_WM_WINDOW_TYPE from window.\n");
+ return;
+ }
+
+ window->window_type = new_type;
+ LOG("_NET_WM_WINDOW_TYPE changed to %i", window->window_type);
+
+ run_assignments(window);
+}
+
/*
* Updates the WM_HINTS (we only care about the input focus handling part).
*
return;
}
- win->doesnt_accept_focus = !hints.input;
- LOG("WM_HINTS.input changed to \"%d\"\n", hints.input);
+ if (hints.flags & XCB_ICCCM_WM_HINT_INPUT) {
+ win->doesnt_accept_focus = !hints.input;
+ LOG("WM_HINTS.input changed to \"%d\"\n", hints.input);
+ }
if (urgency_hint != NULL)
*urgency_hint = (xcb_icccm_wm_hints_get_urgency(&hints) != 0);
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* workspace.c: Modifying workspaces, accessing them, moving containers to
* workspaces.
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* x.c: Interface to X11, transfers our in-memory state to X11 (see also
* render.c). Basically a big state machine.
bool mapped;
bool unmap_now;
bool child_mapped;
+ bool is_hidden;
/** The con for which this state is. */
Con *con;
x_draw_decoration(con);
}
+/*
+ * Sets or removes the _NET_WM_STATE_HIDDEN property on con if necessary.
+ *
+ */
+static void set_hidden_state(Con *con) {
+ if (con->window == NULL) {
+ return;
+ }
+
+ con_state *state = state_for_frame(con->frame);
+ bool should_be_hidden = con_is_hidden(con);
+ if (should_be_hidden == state->is_hidden)
+ return;
+
+ unsigned int num = 0;
+ uint32_t values[1];
+ if (should_be_hidden) {
+ DLOG("setting _NET_WM_STATE_HIDDEN for con = %p\n", con);
+ values[num++] = A__NET_WM_STATE_HIDDEN;
+ } else {
+ DLOG("removing _NET_WM_STATE_HIDDEN for con = %p\n", con);
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, con->window->id, A__NET_WM_STATE, XCB_ATOM_ATOM, 32, num, values);
+ state->is_hidden = should_be_hidden;
+}
+
/*
* This function pushes the properties of each node of the layout tree to
* X11 if they have changed (like the map state, position of the window, …).
fake_absolute_configure_notify(con);
}
+ set_hidden_state(con);
+
/* Handle all children and floating windows of this node. We recurse
* in focus order to display the focused client in a stack first when
* switching workspaces (reduces flickering). */
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* xcb.c: Helper functions for easier usage of XCB
*
add_ignore_event(cookie.sequence, -1);
}
+/*
+ * Returns the first supported _NET_WM_WINDOW_TYPE atom.
+ *
+ */
+xcb_atom_t xcb_get_preferred_window_type(xcb_get_property_reply_t *reply) {
+ if (reply == NULL || xcb_get_property_value_length(reply) == 0)
+ return XCB_NONE;
+
+ xcb_atom_t *atoms;
+ if ((atoms = xcb_get_property_value(reply)) == NULL)
+ return XCB_NONE;
+
+ for (int i = 0; i < xcb_get_property_value_length(reply) / (reply->format / 8); i++) {
+ if (atoms[i] == A__NET_WM_WINDOW_TYPE_NORMAL ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_DIALOG ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_UTILITY ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_TOOLBAR ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_SPLASH ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_MENU ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_POPUP_MENU ||
+ atoms[i] == A__NET_WM_WINDOW_TYPE_TOOLTIP) {
+ return atoms[i];
+ }
+ }
+
+ return XCB_NONE;
+}
+
/*
* Returns true if the given reply contains the given atom.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* xcursor.c: xcursor support for themed cursors.
*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* This is LEGACY code (we support RandR, which can do much more than
* Xinerama), but necessary for the poor users of the nVidia binary
#!/usr/bin/env perl
# vim:ts=4:sw=4:expandtab
-# © 2010-2012 Michael Stapelberg and contributors
+# © 2010 Michael Stapelberg and contributors
package complete_run;
use strict;
use warnings;
}
subtest 'Window without WM_TAKE_FOCUS', sub {
- fresh_workspace;
+ my $ws = fresh_workspace;
my $window = open_window;
ok(!recv_take_focus($window), 'did not receive ClientMessage');
+ my $con = shift get_ws_content($ws);
+ ok($con->{focused}, 'con is focused');
+
done_testing;
};
# list), the window cannot accept input focus, so we should not try to focus
# the window at all.
subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub {
- fresh_workspace;
+ my $ws = fresh_workspace;
my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS');
ok(!recv_take_focus($window), 'did not receive ClientMessage');
+ my $con = shift get_ws_content($ws);
+ ok($con->{focused}, 'con is focused');
+
done_testing;
};
# nearly identical presently, so this is currently used also as a proxy test
# for the latter case.
subtest 'Window with WM_TAKE_FOCUS and unspecified InputHint', sub {
- fresh_workspace;
+ my $ws = fresh_workspace;
my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS');
ok(!recv_take_focus($window), 'did not receive ClientMessage');
+ my $con = shift get_ws_content($ws);
+ ok($con->{focused}, 'con is focused');
+
done_testing;
};
# 8: check that the role criterion works properly
##############################################################
-# this configuration is broken because "asdf" is not a valid integer
-# the for_window should therefore recognize this error and don’t add the
-# assignment
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# *after* the window has been mapped
##############################################################
-# this configuration is broken because "asdf" is not a valid integer
-# the for_window should therefore recognize this error and don’t add the
-# assignment
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
exit_gracefully($pid);
+##############################################################
+# 10: check that the criterion 'window_type' works
+##############################################################
+
+# test all window types
+my %window_types = (
+ 'normal' => '_NET_WM_WINDOW_TYPE_NORMAL',
+ 'dialog' => '_NET_WM_WINDOW_TYPE_DIALOG',
+ 'utility' => '_NET_WM_WINDOW_TYPE_UTILITY',
+ 'toolbar' => '_NET_WM_WINDOW_TYPE_TOOLBAR',
+ 'splash' => '_NET_WM_WINDOW_TYPE_SPLASH',
+ 'menu' => '_NET_WM_WINDOW_TYPE_MENU',
+ 'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU',
+ 'popup_menu' => '_NET_WM_WINDOW_TYPE_POPUP_MENU',
+ 'tooltip' => '_NET_WM_WINDOW_TYPE_TOOLTIP'
+);
+
+while (my ($window_type, $atom) = each %window_types) {
+
+ $config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_type="$window_type"] floating enable, mark branded
+EOT
+
+ $pid = launch_with_config($config);
+ $tmp = fresh_workspace;
+
+ $window = open_window(window_type => $x->atom(name => $atom));
+
+ my @nodes = @{get_ws($tmp)->{floating_nodes}};
+ cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+ is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
+
+ exit_gracefully($pid);
+
+}
+
+##############################################################
+# 11: check that the criterion 'window_type' works if the
+# _NET_WM_WINDOW_TYPE is changed after managing.
+##############################################################
+
+while (my ($window_type, $atom) = each %window_types) {
+
+ $config = <<"EOT";
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+for_window [window_type="$window_type"] floating enable, mark branded
+EOT
+
+ $pid = launch_with_config($config);
+ $tmp = fresh_workspace;
+
+ $window = open_window();
+
+ my $atomname = $x->atom(name => '_NET_WM_WINDOW_TYPE');
+ my $atomtype = $x->atom(name => 'ATOM');
+ $x->change_property(PROP_MODE_REPLACE, $window->id, $atomname->id, $atomtype->id,
+ 32, 1, pack('L1', $x->atom(name => $atom)->id));
+ $x->flush;
+ sync_with_i3;
+
+ my @nodes = @{get_ws($tmp)->{floating_nodes}};
+ cmp_ok(@nodes, '==', 1, 'one floating container on this workspace');
+ is($nodes[0]->{nodes}[0]->{mark}, 'branded', "mark set (window_type = $atom)");
+
+ exit_gracefully($pid);
+
+}
+
+##############################################################
done_testing;
'error for unknown literal ok');
is(parser_calls('move something to somewhere'),
- "ERROR: Expected one of these tokens: 'window', 'container', 'to', 'workspace', 'output', 'scratchpad', 'left', 'right', 'up', 'down', 'position', 'absolute'\n" .
+ "ERROR: Expected one of these tokens: 'window', 'container', 'to', 'workspace', 'output', 'mark', 'scratchpad', 'left', 'right', 'up', 'down', 'position', 'absolute'\n" .
"ERROR: Your command: move something to somewhere\n" .
"ERROR: ^^^^^^^^^^^^^^^^^^^^^^",
'error for unknown literal ok');
bindsym --release Mod1+x exec foo
bindsym --whole-window button3 nop
bindsym --release --whole-window button3 nop
+ bindsym --border button3 nop
+ bindsym --release --border button3 nop
}
EOT
my $expected = <<'EOT';
cfg_enter_mode(meh)
-cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), resize grow)
-cfg_mode_binding(bindcode, Mod1, 44, (null), (null), resize shrink)
-cfg_mode_binding(bindsym, Mod1, x, --release, (null), exec foo)
-cfg_mode_binding(bindsym, (null), button3, (null), --whole-window, nop)
-cfg_mode_binding(bindsym, (null), button3, --release, --whole-window, nop)
+cfg_mode_binding(bindsym, Mod1,Shift, x, (null), (null), (null), resize grow)
+cfg_mode_binding(bindcode, Mod1, 44, (null), (null), (null), resize shrink)
+cfg_mode_binding(bindsym, Mod1, x, --release, (null), (null), exec foo)
+cfg_mode_binding(bindsym, (null), button3, (null), (null), --whole-window, nop)
+cfg_mode_binding(bindsym, (null), button3, --release, (null), --whole-window, nop)
+cfg_mode_binding(bindsym, (null), button3, (null), --border, (null), nop)
+cfg_mode_binding(bindsym, (null), button3, --release, --border, (null), nop)
EOT
is(parser_calls($config),
$expected = <<'EOT';
cfg_enter_mode(yo)
-cfg_mode_binding(bindsym, (null), x, (null), (null), resize shrink left)
+cfg_mode_binding(bindsym, (null), x, (null), (null), (null), resize shrink left)
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: mode "yo" {
# Bug still in: 4.8-16-g6888a1f
use i3test;
-my $ws = fresh_workspace;
+my ($ws, $win1, $win2, $win3, $ws_con);
-my $win1 = open_window;
-my $win2 = open_window;
-my $win3 = open_window;
+###############################################################################
+# Tets moving with 'id' criterion.
+###############################################################################
+
+$ws = fresh_workspace;
+
+$win1 = open_window;
+$win2 = open_window;
+$win3 = open_window;
# move win1 from the left to the right
cmd '[id="' . $win1->{id} . '"] move right';
# now they should be switched, with win2 still being focused
-my $ws_con = get_ws($ws);
+$ws_con = get_ws($ws);
# win2 should be on the left
is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with criteria');
is($x->input_focus, $win3->{id}, 'it should not disturb focus');
+###############################################################################
+# Tets moving with 'window_type' criterion.
+###############################################################################
+
+# test all window types
+my %window_types = (
+ 'normal' => '_NET_WM_WINDOW_TYPE_NORMAL',
+ 'dialog' => '_NET_WM_WINDOW_TYPE_DIALOG',
+ 'utility' => '_NET_WM_WINDOW_TYPE_UTILITY',
+ 'toolbar' => '_NET_WM_WINDOW_TYPE_TOOLBAR',
+ 'splash' => '_NET_WM_WINDOW_TYPE_SPLASH',
+ 'menu' => '_NET_WM_WINDOW_TYPE_MENU',
+ 'dropdown_menu' => '_NET_WM_WINDOW_TYPE_DROPDOWN_MENU',
+ 'popup_menu' => '_NET_WM_WINDOW_TYPE_POPUP_MENU',
+ 'tooltip' => '_NET_WM_WINDOW_TYPE_TOOLTIP'
+);
+
+while (my ($window_type, $atom) = each %window_types) {
+
+ $ws = fresh_workspace;
+
+ $win1 = open_window(window_type => $x->atom(name => $atom));
+ $win2 = open_window;
+ $win3 = open_window;
+
+ cmd '[window_type="' . $window_type . '"] move right';
+
+ $ws_con = get_ws($ws);
+ is($ws_con->{nodes}[0]->{window}, $win2->{id}, 'the `move [direction]` command should work with window_type = ' . $window_type);
+ is($x->input_focus, $win3->{id}, 'it should not disturb focus');
+
+}
+
+###############################################################################
+
done_testing;
--- /dev/null
+#!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 for the 'move [window|container] to mark' command
+# Ticket: #1643
+use i3test;
+
+# In the following tests descriptions, we will always use the following names:
+# * 'S' for the source container which is going to be moved,
+# * 'M' for the marked target container to which 'S' will be moved.
+
+my ($A, $B, $S, $M, $F, $source_ws, $target_ws, $ws);
+my ($nodes, $focus);
+my $cmd_result;
+
+my $_NET_WM_STATE_REMOVE = 0;
+my $_NET_WM_STATE_ADD = 1;
+my $_NET_WM_STATE_TOGGLE = 2;
+
+sub set_urgency {
+ my ($win, $urgent_flag) = @_;
+ my $msg = pack "CCSLLLLLL",
+ X11::XCB::CLIENT_MESSAGE, # response_type
+ 32, # format
+ 0, # sequence
+ $win->id, # window
+ $x->atom(name => '_NET_WM_STATE')->id, # message type
+ ($urgent_flag ? $_NET_WM_STATE_ADD : $_NET_WM_STATE_REMOVE), # data32[0]
+ $x->atom(name => '_NET_WM_STATE_DEMANDS_ATTENTION')->id, # 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);
+}
+
+###############################################################################
+# Given 'M' and 'S' in a horizontal split, when 'S' is moved to 'M', then
+# verify that nothing changed.
+###############################################################################
+
+$ws = fresh_workspace;
+$M = open_window;
+cmd 'mark target';
+$S = open_window;
+
+cmd 'move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($ws);
+is(@{$nodes}, 2, 'there are two containers');
+is($nodes->[0]->{window}, $M->{id}, 'M is left of S');
+is($nodes->[1]->{window}, $S->{id}, 'S is right of M');
+
+###############################################################################
+# Given 'S' and 'M' in a horizontal split, when 'S' is moved to 'M', then
+# both containers switch places.
+###############################################################################
+
+$ws = fresh_workspace;
+$S = open_window;
+$M = open_window;
+cmd 'mark target';
+cmd 'focus left';
+
+cmd 'move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($ws);
+is(@{$nodes}, 2, 'there are two containers');
+is($nodes->[0]->{window}, $M->{id}, 'M is left of S');
+is($nodes->[1]->{window}, $S->{id}, 'S is right of M');
+
+###############################################################################
+# Given 'S' and no container 'M' exists, when 'S' is moved to 'M', then
+# the command is unsuccessful.
+###############################################################################
+
+$ws = fresh_workspace;
+$S = open_window;
+
+$cmd_result = cmd 'move container to mark absent';
+
+is($cmd_result->[0]->{success}, 0, 'command was unsuccessful');
+
+###############################################################################
+# Given 'S' and 'M' on different workspaces, when 'S' is moved to 'M', then
+# 'S' ends up on the same workspace as 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+$target_ws = fresh_workspace;
+$M = open_window;
+cmd 'mark target';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($source_ws);
+is(@{$nodes}, 0, 'source workspace is empty');
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 2, 'both containers are on the target workspace');
+is($nodes->[0]->{window}, $M->{id}, 'M is left of S');
+is($nodes->[1]->{window}, $S->{id}, 'S is right of M');
+
+###############################################################################
+# Given 'S' and 'M' on different workspaces and 'S' is urgent, when 'S' is
+# moved to 'M', then the urgency flag is transferred to the target workspace.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+$F = open_window;
+$target_ws = fresh_workspace;
+$M = open_window;
+cmd 'mark target';
+cmd 'workspace ' . $source_ws;
+set_urgency($S, 1);
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+$source_ws = get_ws($source_ws);
+$target_ws = get_ws($target_ws);
+ok(!$source_ws->{urgent}, 'source workspace is no longer urgent');
+ok($target_ws->{urgent}, 'target workspace is urgent');
+
+###############################################################################
+# Given 'S' and 'M' where 'M' is inside a tabbed container, when 'S' is moved
+# to 'M', then 'S' ends up as a new tab.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+
+# open tabbed container ['A' 'M' 'B']
+$target_ws = fresh_workspace;
+$A = open_window;
+cmd 'layout tabbed';
+$M = open_window;
+cmd 'mark target';
+$B = open_window;
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 1, 'there is a tabbed container');
+
+$nodes = $nodes->[0]->{nodes};
+is(@{$nodes}, 4, 'all four containers are on the target workspace');
+is($nodes->[0]->{window}, $A->{id}, 'A is the first tab');
+is($nodes->[1]->{window}, $M->{id}, 'M is the second tab');
+is($nodes->[2]->{window}, $S->{id}, 'S is the third tab');
+is($nodes->[3]->{window}, $B->{id}, 'B is the fourth tab');
+
+###############################################################################
+# Given 'S' and 'M' where 'M' is a tabbed container where the currently focused
+# tab is a nested layout, when 'S' is moved to 'M', then 'S' is a new tab
+# within 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+
+$target_ws = fresh_workspace;
+$A = open_window;
+cmd 'layout tabbed';
+cmd 'focus parent';
+cmd 'mark target';
+cmd 'focus child';
+$B = open_window;
+cmd 'split h';
+$F = open_window;
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 1, 'there is a tabbed container');
+
+$nodes = $nodes->[0]->{nodes};
+is(@{$nodes}, 3, 'there are three tabs');
+
+is($nodes->[0]->{window}, $A->{id}, 'A is the first tab');
+is($nodes->[2]->{window}, $S->{id}, 'S is the third tab');
+
+###############################################################################
+# Given 'S' and 'M' where 'M' is inside a split container inside a tabbed
+# container, when 'S' is moved to 'M', then 'S' ends up as a container
+# within the same tab as 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+
+# open tabbed container ['A'['B' 'M']]
+$target_ws = fresh_workspace;
+$A = open_window;
+cmd 'layout tabbed';
+$B = open_window;
+cmd 'split h';
+$M = open_window;
+cmd 'mark target';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 1, 'there is a tabbed container');
+
+$nodes = $nodes->[0]->{nodes};
+is(@{$nodes}, 2, 'there are two tabs');
+
+$nodes = $nodes->[1]->{nodes};
+is(@{$nodes}, 3, 'the tab with the marked children has three children');
+is($nodes->[0]->{window}, $B->{id}, 'B is the first tab');
+is($nodes->[1]->{window}, $M->{id}, 'M is the second tab');
+is($nodes->[2]->{window}, $S->{id}, 'S is the third tab');
+
+###############################################################################
+# Given 'S', 'A' and 'B' where 'A' and 'B' are inside the tabbed container 'M',
+# when 'S' is moved to 'M', then 'S' ends up as a new tab in 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+$target_ws = fresh_workspace;
+$A = open_window;
+cmd 'layout tabbed';
+$B = open_window;
+cmd 'focus parent';
+cmd 'mark target';
+cmd 'focus child';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 1, 'there is a tabbed container');
+
+$nodes = $nodes->[0]->{nodes};
+is(@{$nodes}, 3, 'there are three tabs');
+
+is($nodes->[0]->{window}, $A->{id}, 'A is the first tab');
+is($nodes->[1]->{window}, $B->{id}, 'B is the second tab');
+is($nodes->[2]->{window}, $S->{id}, 'S is the third tab');
+
+###############################################################################
+# Given 'S', 'A', 'F' and 'M', where 'M' is a workspace containing a tabbed
+# container, when 'S' is moved to 'M', then 'S' does not end up as a tab, but
+# rather as a new window next to the tabbed container.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+$target_ws = fresh_workspace;
+$A = open_window;
+cmd 'layout tabbed';
+$F = open_window;
+$M = $target_ws;
+cmd 'focus parent';
+cmd 'focus parent';
+cmd 'mark target';
+cmd 'focus ' . $source_ws;
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 2, 'there is a tabbed container and a window');
+is($nodes->[1]->{window}, $S->{id}, 'S is the second window');
+
+###############################################################################
+# Given 'S' and 'M' where 'S' is floating and 'M' on a different workspace,
+# when 'S' is moved to 'M', then 'S' is a floating container on the same
+# workspaces as 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_floating_window;
+$target_ws = fresh_workspace;
+$M = open_window;
+cmd 'mark target';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+is(@{get_ws($target_ws)->{floating_nodes}}, 1, 'target workspace has the container now');
+
+###############################################################################
+# Given 'S' and 'M' where 'M' is floating and on a different workspace,
+# when 'S' is moved to 'M', then 'S' ends up as a tiling container on the
+# same workspace as 'M'.
+###############################################################################
+
+$source_ws = fresh_workspace;
+$S = open_window;
+$target_ws = fresh_workspace;
+$M = open_floating_window;
+cmd 'mark target';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+($nodes, $focus) = get_ws_content($target_ws);
+is(@{$nodes}, 1, 'tiling container moved to the target workspace');
+
+###############################################################################
+# Given 'S' and 'M' are the same container, when 'S' is moved to 'M', then
+# the command is ignored.
+###############################################################################
+
+$ws = fresh_workspace;
+$S = open_window;
+$M = $S;
+cmd 'mark target';
+
+cmd '[id="' . $S->{id} . '"] move container to mark target';
+sync_with_i3;
+
+does_i3_live;
+
+###############################################################################
+
+done_testing;
--- /dev/null
+#!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 for setting and removing the _NET_WM_STATE_HIDDEN atom properly.
+# Ticket: #1648
+use i3test;
+use X11::XCB qw(:all);
+
+sub is_hidden {
+ sync_with_i3;
+ my $atom = $x->atom(name => '_NET_WM_STATE_HIDDEN');
+
+ my ($con) = @_;
+ my $cookie = $x->get_property(
+ 0,
+ $con->{id},
+ $x->atom(name => '_NET_WM_STATE')->id,
+ GET_PROPERTY_TYPE_ANY,
+ 0,
+ 4096
+ );
+
+ my $reply = $x->get_property_reply($cookie->{sequence});
+ my $len = $reply->{length};
+ return 0 if $len == 0;
+
+ my @atoms = unpack("L$len", $reply->{value});
+ for (my $i = 0; $i < $len; $i++) {
+ return 1 if $atoms[$i] == $atom->id;
+ }
+
+ return 0;
+}
+
+my ($tabA, $tabB, $tabC, $subtabA, $subtabB, $windowA, $windowB);
+
+###############################################################################
+# Given two containers next to each other, when focusing one, then the other
+# one does not have _NET_WM_STATE_HIDDEN set.
+###############################################################################
+
+fresh_workspace;
+$windowA = open_window;
+$windowB = open_window;
+
+ok(!is_hidden($windowA), 'left window does not have _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($windowB), 'right window does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given two containers on different workspaces, when one is focused, then
+# the other one does not have _NET_WM_STATE_HIDDEN set.
+###############################################################################
+
+fresh_workspace;
+$windowA = open_window;
+fresh_workspace;
+$windowB = open_window;
+
+ok(!is_hidden($windowA), 'left window does not have _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($windowB), 'right window does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given two containers in the same tabbed container, when one is focused, then
+# (only) the other one has _NET_WM_STATE_HIDDEN set.
+# Given the other tab is focused, then the atom is transferred.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout tabbed';
+$tabB = open_window;
+
+ok(is_hidden($tabA), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabB), 'focused tab does not have _NET_WM_STATE_HIDDEN set');
+
+cmd 'focus left';
+
+ok(!is_hidden($tabA), 'focused tab does not have _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($tabB), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given three containers in the same stacked container, when the focused tab
+# is moved to another workspace, then the now focused tab does not have
+# _NET_WM_STATE_HIDDEN set anymore.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout stacked';
+$tabB = open_window;
+$tabC = open_window;
+cmd 'move window to workspace unused';
+
+ok(is_hidden($tabA), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabB), 'focused tab does not have _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabC), 'moved window does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given three containers in the same stacked container, when a not focused
+# tab is moved to another workspace, then it does not have _NET_WM_STATE_HIDDEN
+# set anymore.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout stacked';
+$tabB = open_window;
+cmd 'mark moveme';
+$tabC = open_window;
+cmd '[con_mark="moveme"] move window to workspace unused';
+
+ok(is_hidden($tabA), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabB), 'moved window does not have _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabC), 'focused tab does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given a tabbed container and some other container, when the latter is moved
+# into the tabbed container, then all other tabs have _NET_WM_STATE_HIDDEN
+# set.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout tabbed';
+$tabB = open_window;
+cmd 'focus parent';
+cmd 'split h';
+$tabC = open_window;
+cmd 'move left';
+
+ok(is_hidden($tabA), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($tabB), 'unfocused tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabC), 'focused tab does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given a stacked container nested inside another tabbed container with the
+# inner one being in the currently focused tab, then the focused tab of the
+# inner container does not have _NET_WM_STATE_HIDDEN set.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout tabbed';
+$tabB = open_window;
+cmd 'split h';
+open_window;
+cmd 'split v';
+cmd 'layout stacked';
+$subtabA = open_window;
+$subtabB = open_window;
+
+ok(is_hidden($tabA), 'unfocused outer tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($tabB), 'focused outer tab does not have _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($subtabA), 'unfocused inner tab has _NET_WM_STATE_HIDDEN set');
+ok(!is_hidden($subtabB), 'focused inner tab does not have _NET_WM_STATE_HIDDEN set');
+
+cmd 'focus left';
+
+ok(!is_hidden($subtabB), 'focused inner tab does not have _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+# Given a stacked container nested inside another tabbed container with the
+# inner one being in a currently not focused tab, then all tabs of the inner
+# container have _NET_WM_STATE_HIDDEN set.
+###############################################################################
+
+fresh_workspace;
+$tabA = open_window;
+cmd 'layout tabbed';
+$tabB = open_window;
+cmd 'split h';
+open_window;
+cmd 'split v';
+cmd 'layout stacked';
+$subtabA = open_window;
+$subtabB = open_window;
+cmd 'focus parent';
+cmd 'focus parent';
+cmd 'focus left';
+
+ok(!is_hidden($tabA), 'focused outer tab does not have _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($tabB), 'unfocused outer tab has _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($subtabA), 'unfocused inner tab has _NET_WM_STATE_HIDDEN set');
+ok(is_hidden($subtabB), 'unfocused inner tab has _NET_WM_STATE_HIDDEN set');
+
+###############################################################################
+
+done_testing;