Basic idea: if the window has a shape, set the parent container shape as
the union of the window shape and the shape of the frame borders.
Co-authored-by: Uli Schlachter <psychon@znc.in>
- ICCCM says: > If a base size is not provided, the minimum size is to
be used in its place and vice versa.
i3 didn't obey the "vice versa" part. Min size and base size are both
saved without replacements in window_update_normal_hints,
floating_check_size makes the needed replacements if either was not
provided.
- Aspect ratio is now saved correctly in manage_window because
window_update_normal_hints is called.
- i3 didn't save the aspect ratio if the window conformed the given
aspect ratio range when handle_normal_hints was called. If the window
was resized to a size outside of the given bounds, i3 didn't correct it.
- Aspect ratio now affects only tiling windows, like the rest of the
normal size hints
- The aspect ratio calculation is now done without a loop
A real life example of how these changes affect the workflow:
An mpv window, when playing a video, sets its min == max aspect ratio
during mapping. i3 ignored these hints. When resized, the window's
aspect ratio was not preserved. With this commit, resizing floating mpv
windows will always preserve the aspect ratio.
Previously, it first calculated one of the containers' next percentage, and then subtracted the previous percentage to find the actual change.
Now it directly calculates the change, and subtracts and adds the change to the two affected containers.
Added util function con_rect_size_in_orientation.
Removed px_resize_to_percent; inlined, using con_rect_size_in_orientation.
Also, prematurely return when pixel diff is 0, as no action is necessary.
This is related to [this issue on i3-gaps](https://github.com/Airblader/i3/issues/247).
Example problematic layout:
{
"layout": "splith",
"marks": ["H1"],
"nodes": [
{
"swallows": [
{
"class": "^a$"
}
]
}
]
}
Since the marks were added to the json_node during end_map, the
container that ended up getting the "H1" mark was the child instead of
the parent.
This fixes a regression introduced in 6d983b5. Consider 2 outputs:
fake-0: workspace '1'
fake-1: workspaces '2','3'
Workspace 1 focused, workspace 2 visible.
Open a floating window in 1 and move it to 3. Now, the floating window
appears in workspace 2 and disappears once focus is switched to
that workspace.
Instead of focusing 'old_focus' which might refer to a container in a
different output, we should restore focus by focusing the previously
focused workspace of the output.
Controls the window titles alignment in title bars. Possible values are:
- left
- center
- right
Co-authored-by: Orestis Floros <orestisf1993@gmail.com>
- Made title_align a config directive instead of a command. Helps with
some tree_render() issues we had.
- Made title_max_width the same for all 3 cases.
- Modified title offset calculations and added explanations for each
case.
- Append title_padding to mark_width if a mark exists.
Fixes#1750
Benefits are that we don't open a fake container and don't call many
complicated functions that can lead to redraws (x_push_changes calls) as
discussed in #2954.
Fixes#2810:
Windows exchange floating mode & window rects.
Swap will still not work with CT_FLOATING_CONs but this doesn't make
much sense.
Fixes#3280:
The behaviour is not very user friendly but swap behaves exactly as it
should. The rest is a tree_flatten issue. Attached pictures in #2954.
- Use workspace_show that correctly updates _NET_CURRENT_DESKTOP, warps
mouse.
- Use TAILQ_INSERT_TAIL only for focus_head. Focus order is not related
to direction.
- Call con_focus only if con was focused before. See testcase for
directional move with command criteria.
- Correct first call of move_to_output_directed in tree_move which
didn't call ipc_send_window_event("move", con) and
ewmh_update_wm_desktop().
- Don't produce events when the move doesn't happen. Correct
276-ipc-window-move.t as well.
For compatiblity reasons, Wine will request iconic state and cannot
ensure that the WM has agreed on it; immediately revert to normal to
avoid being stuck in a paused state.
con_detach and con_attach modify the focus stack.
This will make sure that the currently focused workspace will remain
focused after disabling an output.
This fixes a crash produced with the following config:
# i3 config file (v4)
workspace 1 output $screen1
workspace 2 output $screen2
exec --no-startup-id "i3-msg workspace 1, open && i3-msg workspace 2 && xrandr --output $screen2 --off && xrandr --output $screen1 --auto --output $screen2 --auto --right-of $screen1 "
Which results in:
ERROR: AddressSanitizer: heap-use-after-free on address …
READ of size 8 at 0x614000001f48 thread T0
#0 0x5563df6e73a8 in init_ws_for_output i3/src/randr.c:468
#1 0x5563df6ef3b4 in randr_query_outputs i3/src/randr.c:940
#2 0x5563df68dbe1 in handle_screen_change i3/src/handlers.c:450
… is located 264 bytes inside of 448-byte region …
freed by thread T0 here:
#1 0x5563df634b0a in con_free i3/src/con.c:96
#2 0x5563df7151e6 in tree_close_internal i3/src/tree.c:344
#3 0x5563df7280fe in workspace_show i3/src/workspace.c:499
#4 0x5563df6e7315 in init_ws_for_output i3/src/randr.c:457
#5 0x5563df6ef3b4 in randr_query_outputs i3/src/randr.c:940
#6 0x5563df68dbe1 in handle_screen_change i3/src/handlers.c:450
Which is similar to #3228, #3248.
- Improve / add various error messages.
- Replace all `LOG(…); ysuccess(false);` with `yerror(…);`.
- switch_mode: Remove redundant "ERROR:" ELOG string.
- cmd_move_con_to_workspace*: Make sure that we don't try to move an
empty workspace to another workspace. This can be problematic when we
match a workspace using command criteria (eg marks) and the target is a
non-existing workspace. We create the new workspace but since nothing is
moved there, we are left with an empty workspace. See added testcase.
Fixes#3156.
I couldn't reproduce the problem in a "natural" way so I cheated:
1. Start i3 with gdb
2. Set breakpoing on tree_restore
3. Run, open window, i3-msg restart
5. Open the file in *path with a hex editor
6. Edit the "name" field of the window and insert bytes that are not
valid UTF8
7. Continue
After parsing fails, all nodes including croot are incomplete, meaning
they have to be deleted. We can't recover in any reasonable way so we
have to allow non-UTF8 characters to avoid this situation altogether.
Introduces resize_neighboring_cons in resize.c which is also used by
resize_graphical_handler.
Co-authored-by: Andrew Laucius <andrewla@gmail.com>
Authored original code and tests in #3240. I rewrote most of the
resizing code and fixed the failing tests.
These are the changes that clang-format 6.0.1 makes to the codebase that
clang-format-3.8 doesn't change back.
Useful for those that use a more recent version of clang-format in their
local machines.
This commit will also fix the following bugs:
1. click.c: Users could drag global fullscreen floating containers.
2. render.c: Floating containers would get rendered with a global fullscreen container in another
workspace.
The first issue is that there seems to be a typo: fullscreen->window
should have been child->window. The corrected check is redundant since
the while loop checks if the transient_con has a window.
The second issue is that popup_during_fullscreen is never checked even
though the behaviour should be exclusive to the "smart" option.
A race condition is possible. For example, if we first receive a
XCB_MOTION_NOTIFY event and then, while drain_drag_events is still
running, a XCB_BUTTON_RELEASE event the first event is never handled
because we return.
This fixes the flakiness of the tests in #3085.
Right now tree_render() is called twice on DRAG_REVERT since
floating_reposition calls it.
Also, on DRAG_REVERT the scratchpad state shouldn't change since the
user canceled the action.
This change only affects clients that are subscribed to events, which
should be the main cause of our problems.
In the common case (no buffered data) the behaviour doesn't change at
all: the message is sent directly, no ev_io / ev_timeout callback is
enabled. Once a write to a client's socket is not completed fully
(returns with EAGAIN error), we put the message in the tail of a queue
and init an ev_io callback and a corresponding timer. If the timer is
triggered first, the socket is closed and the client connection is
removed. If the socket becomes writeable before the timeout we either
reset the timer if we couldn't push all the buffered data or completely
remove it if everything was pushed.
We could also replace ipc_send_message() for all client connections in
i3, not just those subscribed to events.
Furthermore, we could limit the amount of messages stored and increase
the timeout (or use multiple timeouts): eg it's ok if a client is not
reading for 10 seconds and we are only holding 5KB of messages for them
but it is not ok if they are inactive for 5 seconds and we have 30MB of
messages held.
Closes#2999Closes#2539
This commit makes multiple changes in tree_close_internal. I didn't
split them because they are not completely independent.
- Remove force_set_focus parameter
This parameter was always set to `false` throughout the code base except
for one case where it was set to `(con == focused)`, when killing a
floating con's parent (the one with type CT_FLOATING_CON). But this case
is not needed anymore since the special handling of CT_FLOATING_CONs in
con_next_focused was removed in #2941.
- Assume that con_next_focused does not returned a container of type
CT_DOCKAREA. This is reasonable since con_next_focused uses the
focus_head stack and has special handling of CT_DOCKAREA containers.
- Remove is_mapped
This variable was only used in the if block towards the end of
tree_close_internal. Ignoring the, now removed, dockarea code and the
use of force_set_focus this block performed only one useful action:
focus the `next` container when `con == focused`. `con == focused` was a
necessary and sufficient condition for the con_activate call:
if `con != focused` we could reach the inner if blocks because of the
other conditions but would never focus another container. If `con ==
focused` then all other conditions would be irrelevant.
- Remove special handling of floating containers
Since the `next` focused container is calculated through the parent for
floating containers, I moved this code to con_next_focused.
Also, because of the removal of force_set_focus, it appears that we can
call con_on_remove_child for floating containers as well.
This was introduced in 252db3b8c (#3245). That commit moved the
con_activate line inside the loop, meaning it wouldn't always be called.
When the mouse moved after a rename with focus_follows_mouse enabled,
check_crossing_screen_boundary (src/handlers.c:111) called
con_descend_focused that used the wrong focus order.
I also change con_activate to con_focus since we don't really want to
raise floating containers there.
Fixes#3325
This prohibits the usage of workspaces assigned to other outputs in
create_workspace_on_output.
Eg, with config:
workspace 1 output fake-0
workspace 2 output fake-0
and 2 screens workspace 2 would be used for the second screen even
though it is assigned to the first one.
Also introduces a test for workspace assignments that includes the case
described above and some tests that don't fail in the next branch.
This also replaces code in create_workspace_on_output() that is
theoretically more efficient but:
1. It isn't a huge difference since it depends on the number of outputs,
that shouldn't be high.
2. get_assigned_output will be modified and used for #555, then its
logic should be followed in create_workspace_on_output() too.
Another note for create_workspace_on_output: if assigned is not NULL the
condition (assigned != output->con) should never be false, ie if there
is an assigned output to this name, it isn't the current one. This
happens because the current callers check for assignments before calling
create_workspace_on_output().
https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
Detectable autorepeat should only affect --release bindings. Currently,
when a user keeps a key pressed, we get multiple KeyPress and KeyRelease
events. With this change, we still get multiple KeyPress events, which
means that you can still keep a key pressed to repeatedly execute a
normal binding, but only one KeyRelease event when the key is physically
released.
Unfortunately, this change is not currently testable because detectable
autorepeat doesn't seem to work under Xephyr. AwesomeWM experienced the
same problem:
6f2424e901Fixes#3306
X will not allow a window with ParentRelative background to be created
or reparented under a window with mismatching color depth.
Deal with this by destroying the container frame and creating a new one
with the right depth upon swallowing.
Defer destruction of the frame window until after the updated tree has
been rendered to avoid some distracting flickering.
Fixes#3297
fbce834b introduced a bug where scrolling over the decoration while
another container is focused would not focus the tabbed/stacked
container itself, but would instead move focus through the currently
focused container.
When moving a workspace to the current output by way of a rename, if the
current workspace is empty, it will be removed by `workspace_show`.
Attempting to restore focus to this removed workspace causes a crash.
Follow the pattern in workspace.c:996 to only restore the original focus if the
original workspace still exists.
Add a test to ensure that the renamed workspace moves to its appropriate
output and that a crash does not occur.
Fixes#3228
handle_screen_change() and handle_configure_notify() call
randr_query_outputs() where root_output is not initialized because
randr_init() is never called when config.fake_outputs is not NULL.
When we don't modify the focus we aren't risking giving focus to a
container behind the current fullscreen one.
_con_move_to_con can with ignore_focus is called through the swap
command or through con_move_to_workspace for floating containers. This
change shouldn't break the expectations of the callers there.
Fixes issue #3259.
This is enough to fix the crash discussed in #3259 even though the next
commit can fix it independently. This commit is useful because it
generally makes sense to abort the command when the first call to
_con_move_to_con fails.
- 'border toggle' now accepts an optional pixel argument which will be
ignored when switching to BS_NONE.
- 'border pixel' now defaults to 1 pixel instead of 2.
- Calling 'border normal' or 'border pixel' will use the configured
default_border_width if one exists. Also applies to floating windows.
Fix the issue #3227(https://github.com/i3/i3/issues/3227).
1).Make cmd_scratchpad_show() use the information coming from scratchpad_show().
2).Add a test case 298-scratchpad-show.t.
Was used for the removed option 'terminal' and for 'font'. 'font' is no
longer this aggressive and doesn't use the macro.
Killing i3 when an option is missing would be super backwards
incompatible so I doubt we are going to use this ever again.
Was a small typo.
This also has the (positive) side-effect of allowing to move all the
content of a marked workspace next to the target container, see added
tests.
Currently when renaming outputs, an output assignment of "left" will
cause the workspace to move left. Treat this assignment as a proper name
instead (even though it is unlikely an output will be named "left").
Move logic for determining output to move to out of
`workspace_move_to_output`
Add test for ignoring direcionality during rename.
Fixes#3208.
Using 'default:' cases can hide logical errors which would lead to i3
crashes for users. With this change the compiler will print a warning
when a case is not handled. For example, if I add a new value in the
Font.type enum:
../../i3/libi3/font.c: In function ‘draw_text’:
../../i3/libi3/font.c:378:5: warning: enumeration value ‘NEWFONT’ not handled in switch [-Wswitch]
switch (savedFont->type) {
^~~~~~
The current behaviour is buggy in the following layout:
T [ A* V [ B C ] ], where the focus stack in V is B > C.
When the user scrolls down, focus correctly moves to B but if the user
scrolls down again the whole vertical container is focused.
This happens because 'bool scroll_next_possible' is false but
con_activate is called on the tabbed container's sibling - the vertical
container.
Sending the sync command via IPC ensures pending IPC messages are handled by i3
before the sync response is read. This is rarely useful for direct IPC
connections to i3, but becomes useful when synchronizing with i3bar, which might
have pending IPC messages in response to button clicks.
Explanation for the changed test:
After $third is switched to floating, the test moves focus to $second.
So, the parent of $second (the stacked container) is above $third in the
focus stack and it's children ($first, $second) should get focused
before $second. When $second is switched to floating the correct focus
order for the workspace should be $second->parent (floating con is the
parent) > $first->parent (stacked con) > $third.
Fixes#1975
Steps to reproduce:
1. Force the branch to be taken:
diff --git a/src/bindings.c b/src/bindings.c
index fe77bc8f..caa5848c 100644
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -941,7 +941,7 @@ bool load_keymap(void) {
struct xkb_keymap *new_keymap = NULL;
int32_t device_id;
- if (xkb_supported && (device_id = xkb_x11_get_core_keyboard_device_id(conn)) > -1) {
+ if (0) {
if ((new_keymap = xkb_x11_keymap_new_from_device(xkb_context, conn, device_id, 0)) == NULL) {
ELOG("xkb_x11_keymap_new_from_device failed\n");
return false;
2. Run `python2 ./xproperty.py _XKB_RULES_NAMES ''` (from
https://github.com/siemer/xproperty) in the xinitrc
3. Memory sanitizers detect memory leaks.
Note: We don't (and didn't) pass NULL in xkb_keymap_new_from_names() but
an xkb_rule_names structures with NULL fields (fill_rmlvo_from_root only
fills its argument when there are no errors) should be equivalent:
767fa86d42/NEWS (L349-L351)
> The function xkb_keymap_new_from_names() now accepts a NULL value for
the 'names' parameter, instead of failing. This is equivalent to passing
a 'struct xkb_rule_names' with all fields set to NULL.
Fixes#2535.