When running 'floating toggle' (or enable/disable) on an empty
workspace, the focused container is the workspace itself, which has
window=NULL. The command would call run_assignments(workspace->window),
which would pass NULL to match_matches_window(), causing a crash when
trying to access window->id.
Add a NULL check at the beginning of `run_assignments` to immediately
skip assignments for that case.
Fixes: #6561
tree_move calls tree_flatten which can destroy redundant containers.
An example reproduction would be V[H[a V[b]]] where V[b] is focused
(parent of b) and a is moved away using the DT_PARENT target.
Note: Found with [bugfinder](https://github.com/stanek-michal/bugfinder)
Inspired by #5384, but instead of just using the border width, this PR
reports the actual frame extents for the window, which may also include
the title bar (for floating windows and tiled windows in plain split
containers, but not for tiled windows in stacked/tabbed containers).
The existing `con_border_style_rect()` function should already handle
all configuration options which can affect the decoration sizes (if it
does not, that would also show up in other places); its result just
needs to be converted into the format used by the `_NET_FRAME_EXTENTS`
property.
This PR fixes#4292 probably in the best way possible (the reported
`_NET_FRAME_EXTENTS` values should always match the actual sizes of
window frame elements which are actually drawn into the X11 frame window
into which the client window is reparented). The only really problematic
case is with the stacked/tabbed containers, for which the title bar is
actually drawn into a completely separate window, therefore the title
bar size cannot be reported in `_NET_FRAME_EXTENTS` (actually I tried to
calculate the size of those decorations and add it to the top decoration
size, but that did not change the behavior of `picom`).
<details><summary>Large screenshots here (3840×2160)</summary>
Example of configuration with `hide_edge_borders smart` — a single
window does not have borders, so only the top frame size is non-zero:

but multiple windows have borders:

Changing border width works too (although with `border normal 8` you can
see that the top border overlaps the title text, because on the i3 side
that border does not really exists, and `picom` just draws it over; also
the pixel sizes reported by `xprop` and `xwininfo` are not identical to
what is specified in i3, because I use 168 dpi on this system, therefore
4 px in the i3 config = 7 dpx):

Handling of tabbed containers is less perfect though. Here is a single
tabbed container with `hide_edge_borders smart`, so it does not really
have a border — note that all frame extents are zero, and the titlebar
is rounded separately (although it could easily be excluded from
rounding, that does not really help much):

Once the border actually appears, you may notice that the top part of
the `picom` border actually gets drawn over the top part of the window,
partially obscuring the top line in this terminal (`picom` does not mind
that the top frame size is reported as 0):

Some examples of floating windows (no major problems there):

Options like `hide_edge_borders both` work too when gaps are removed
(although the resulting behavior with `picom` is probably not very
useful — the rounded border gets drawn only if all of the left, bottom
and right borders are present):

The same with `border pixel 8` (note that windows with only the top
border hidden still get the rounded border treatment by `picom`, but the
border overlaps the top part of the window):

</details>
---------
Signed-off-by: Sergey Vlasov <sigprof@gmail.com>
Co-authored-by: Orestis Floros <orestisflo@gmail.com>
This was originally mentioned in #3085 but left for a future PR.
One of the noticeable limitations is that pressing the modifier while
the drag is already initiated, will not swap the containers but instead
cancel the drag. This is because of how `drag_pointer()` is written and
would be quite an involved case to handle it.
The crash was brought up in a comment in
https://github.com/i3/i3/discussions/6076#discussioncomment-9536969
The cause is that the command criteria are matching a window in the
scratchpad. In that case, the assertion in get_output_for_con() fails.
That happens because there is no `Output` for the `Con` output of a
scratchpad window.
I've decided to *not* remove the offending assertion but rather rely on
the caller not using the function with internal containers. My reasoning
is:
1. If get_output_for_con can return NULL then the caller will either
segfault (which is worse) or needs to check the return for NULL.
2. The case where the return can be NULL is already known, it happens
for internal containers.
3. Therefore, the caller should already prevent the situation with a
call to con_is_internal(). Thus, the `assert`ion can remain.
There is also the potential fix of con_get_workspace returning some
arbitrary output (e.g. first in the list or currently focused one)
instead of NULL. This can lead to more tricky to catch bugs.
eg if you have workspaces: { 1, 2:a, 2:b, 3 } and are on workspace 1,
then 'workspace next' should traverse 1 -> 2:a -> 2:b -> 3 -> 1 instead
of 1 -> 2:a -> 3 -> 1.
Fixes#4452
This had pretty much identical behaviour to hide_edge_borders which made
it confusing. The `hide_edge_borders smart_no_gaps` implementation has an extra check
which fixes#5406.
If a window occupies the entirety of its workspace vertically and/or horizontally, pass it the _NET_WM_STATE_MAXIMIZED_{HORZ, VERT} atoms. This helps applications like Google Chrome draw the tab bar correctly and handle tab clicks correctly (see https://crbug.com/1495853).
This change is based on work from @yshui in #2380.
Grabing the pointer produces a `GrabFrozen` error in applications that
are run from key bindings. Since we don't need the pointer in such
cases, we can change the call to use ASYNC. This seems to be a
historical leftover.
I've tested locally that these still work:
- bindsym $mod+x ...
- bindsym --release $mod+x ...
- bindsym $mod+button1 ...
- bindsym --release $mod+button1 ...
- bindsym --release $mod+x exec program that grabs the keyboard
now works (see original issue)
Even in the main branch, I actually couldn't get `import` and `xdotool`
to fail with the pointer being frozen, potentially because these
programs wait a bit for the pointer to be unfrozen like i3lock does.
This patch came up in
https://github.com/i3/i3/issues/5735#issuecomment-1781321011
I wonder why the pointer is actually grabbed.
The argument I change in `xcb_grab_key` there, is `pointer_mode`, from
https://www.x.org/releases/X11R7.7/doc/man/man3/xcb_grab_key.3.xhtml:
```
pointer_mode
One of the following values:
XCB_GRAB_MODE_SYNC
The state of the keyboard appears to freeze: No further keyboard events are generated by the server until the grabbing client issues a releasing AllowEvents request or until the keyboard grab is released.
XCB_GRAB_MODE_ASYNC
Keyboard event processing continues normally.
```
I traced via `git blame` the usage of `xcb_grab_key` throughout 14 years
of i3 development and it seems that `pointer_mode` was always set to
`XCB_GRAB_MODE_SYNC`, going all the way back to
b664456706.
Fixes#5735
Unfortunately, grabbing / ungrabbing doesn't seem to work correctly in
xvfb so we can't really test this.
I also fixed the deduplication code in bindings_get_buttons_to_grab().
This commit moves subtracting the global gaps from the workspace gaps:
previously, this calculation was done while parsing the configuration
(order dependent), now it’s done at workspace assignment evaluation time.
related to https://github.com/i3/i3/issues/3724
fixes https://github.com/i3/i3/issues/5253
This reverts commit 6b658f88be.
The commit was misguided: the pixel values are already run through logical_px()
when parsing the configuration directive or command, so they should not be run
through another logical_px() pass at rendering time.
See https://linux.die.net/man/3/vendorshell
The important part is:
> MWM_DECOR_ALL
> All decorations *except* those specified by other flag bits that are set
This is the last remaining diff from the i3-gaps tree.
related to https://github.com/i3/i3/issues/3724
Tested using the following config with picom:
bar {
i3bar_command i3bar -t
status_command i3status
colors {
# fully transparent text on opaque background:
statusline #ffffff00
background #000000ff
}
}