This commit adds support for laptop lid and tablet
mode switches as provided by evdev/libinput and
handled by wlroots.
Adds a new bindswitch command with syntax:
bindswitch <switch>:<state> <command>
Where <switch> is one of:
tablet for WLR_SWITCH_TYPE_TABLET_MODE
lid for WLR_SWITCH_TYPE_LID
<state> is one of:
on for WLR_SWITCH_STATE_ON
off for WLR_SWITCH_STATE_OFF
toggle for WLR_SWITCH_STATE_TOGGLE
(Note that WLR_SWITCH_STATE_TOGGLE doesn't map to
libinput and will trigger at both on and off events)
This introduces a `default` seat operation which is used when no mouse
buttons are being held. This means there is now always a seat operation
in progress. It allows us to separate `default` code from the standard
cursor management code.
The sway_seatop_impl struct has gained callbacks `axis`, `rebase` and
`end`, and lost callbacks `finish` and `abort`. `axis` and `rebase` are
only used by the default seatop. `end` is called when a seatop is being
replaced by another one and allows the seatop to free any resources,
though no seatop currently needs to do this. `finish` is no longer
required, as each seatop can gracefully finish in their `button`
callback. And `abort` is not needed, as calling `end` would achieve the
same thing. The struct has also gained a bool named allow_set_cursor
which allows the client to set a new cursor during `default` and `down`
seatops.
Seatops would previously store which button they were started with and
stop when that button was released. This behaviour is changed so that it
only ends once all buttons are released. So you can start a drag with
$mod+left, then click and hold right, release left and it'll continue
dragging while the right button is held.
The motion callback now accepts dx and dy. Most seatops don't use this
as they store the cursor position when the seatop is started and compare
it with the current cursor position. This approach doesn't make sense
for the default seatop though, hence why dx and dy are needed.
The pressed_buttons array has been moved from the sway_cursor struct to
the default seatop's data. This is only used for the default seatop to
check bindings. The total pressed button count remains in the
sway_cursor struct though, because all the other seatops check it to
know if they should end.
The `down` seatop no longer has a `moved` property. This was used to
track if the cursor moved and to recheck focus_follows_mouse, but seems
to work without it.
The logic for focus_follows_mouse has been refactored. As part of this
I've removed the call to wlr_seat_keyboard_has_grab as we don't appear
to use keyboard grabs.
The functions for handling relative motion, absolute motion and tool
axis have been changed. Previously the handler functions were
handle_cursor_motion, handle_cursor_motion_absolute and
handle_tool_axis. The latter two both called cursor_motion_absolute.
Both handle_cursor_motion and cursor_motion_absolute did very similar
things. These are now simplified into three handlers and a single common
function called cursor_motion. All three handlers call cursor_motion. As
cursor_motion works with relative distances, the absolute and tool axis
handlers convert them to relative first.
This moves setting `seat->prev_workspace_name` from `workspace_switch`
to `set_workspace`. `workspace_switch` is only called when using a
`workspace` command to change the workspace so any workspace change
based on criteria was not altering `seat->prev_workspace_name`. By
moving it to `set_workspace`, which is called by `seat_set_focus`, it
will change any time focus changes to a node on a different workspace
It turns out sending button events during all seat operations is not
desirable. This patch introduces a new property
`seatop_impl.allows_events` which allows each operation to define
whether button events should be passed to the surface or not.
The `down` seat operation is the only one that supports this. As all the
other seatops don't support it, the calls to seat_pointer_notify_button
prior to starting them have been removed.
All seat operations except "down" eat the button pressed event and don't send
it to clients. Thus, when ending such seat operations we shouldn't send the
button released event.
This commit moves the logic used to send pressed/released into the "down"
operation.
If an unmanaged or layer surface is focused when an output gets
disabled and an empty workspace on the output was focused by the seat,
the seat needs to refocus it's focus inactive to update the value of
`seat->workspace`.
This allows the focused inactive tree node and visible workspaces to be
changed while a surface layer has focus. The layer temporarily loses
focus, the tree focus changes, and the layer gets refocused.
Since a tablet tool provides the WL_SEAT_CAPABILITY_POINTER capability,
sway will attempt to use the xcursor manager to set a cursor image. If
the tablet tool was the first (and possibly only) device to provide the
capability for the seat, the xcursor manager was not being configured
before attempting to set a cursor image. This was due to
`seat_configure_xcursor` only being called in `seat_configure_pointer`.
Since the xcursor manager was NULL in this case, it would cause a
segfault when attempting to set a cursor image. This adds a call to
`seat_configure_xcursor` in `seat_configure_tablet_tool` to ensure that
the seat has a xcursor manager.
This commit mostly duplicates the wlr_log functions, although
with a sway_* prefix. (This is very similar to PR #2009.)
However, the logging function no longer needs to be replaceable,
so sway_log_init's second argument is used to set the exit
callback for sway_abort.
wlr_log_init is still invoked in sway/main.c
This commit makes it easier to remove the wlroots dependency for
the helper programs swaymsg, swaybg, swaybar, and swaynag.
When resetting the keyboard during reload, disarm the key repeat on all
keyboards since the bindings (and possibly keyboard) will be freed before
the key repeat can go off.
This splits each seat operation (drag/move tiling/floating etc) into a
separate file and introduces a struct sway_seatop_impl to abstract the
operation.
The move_tiling_threshold operation has been merged into move_tiling.
The main logic for each operation is untouched aside from variable
renames.
The following previously-static functions have been made public:
* node_at_coords
* container_raise_floating
* render_rect
* premultiply_alpha
* scale_box
evdev-proto is installed by a dependency, so some files have been missed:
In file included from ../sway/input/cursor.c:3:
/usr/local/include/libevdev-1.0/libevdev/libevdev.h:30:10: fatal error: 'linux/input.h' file not found
#include <linux/input.h>
^~~~~~~~~~~~~~~
../swaybar/i3bar.c:3:10: fatal error: 'linux/input-event-codes.h' file not found
#include <linux/input-event-codes.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~~
Unhide the cursor if container warping is enabled.
Also set the image_surface to NULL during view_unmap, otherwise the cursor will
try to access the surface which is currently being unmapped.
Implements `tiling_drag_threshold <threshold>` to prevent accidental
dragging of tiling containers. If a container (and all of its
descendants) are unfocused and the tile bar is pressed, a threshold
will be used before actually starting the drag. Once the threshold has
been exceeded, the cursor will change to the grab icon and the operation
will switch from `OP_MOVE_TILING_THRESHOLD` to `OP_MOVE_TILING`.
This combines `output_by_name` and `output_by_identifier` into a single
function called `output_by_name_or_id`. This allows for output
identifiers to be used in all commands, simplifies the logic of the
callers, and is more efficient since worst case is a single pass through
the output list.
My previous attempt was not quite right. Changing the focus stack on a
non-visible workspace should only be blocked if the focus would be set
to the workspace itself
Changing the focus stack when destroying a container's node on a
non-visible workspace (on an non-focused output) incorrectly causes
the non-visible workspace to become visible. If the workspace is empty,
it will not be destroyed since it is now visible. Additionally since
there was no workspace::focus event, swaybar still shows the previous
workspace as focus-inactive. It also makes no sense to change visible
workspaces due to a container on a non-visible workspace being
destroyed.
Since the focus will either be set when switching to the non-visible
workspace or the workspace will be destroyed due to being empty, there
is no need to change the focus stack when destroying a container on a
non-visible workspace.
The code being changed is responsible for updating the focus stack when
a container is destroyed in a different part of the tree to where the
real focus is. It's attempting to set focus_inactive to a sibling (or
parent if no siblings) of the container that is being destroyed, then
put our real focus back on the end of the focus stack.
The problem occurs when the container being destroyed is in a different
workspace. For example:
* Have a focused view on workspace 1
* Have workspace 2 not visible with a single view that is unmapping
* The first call to seat_set_raw_focus sets focus to workspace 2 because
it's the parent
* Prior to this patch, the second call to seat_set_raw_focus would set
focus to the view on workspace 1
* Later, when using output_get_active_workspace, this function would
return workspace 2 because it's the first workspace it finds in the
focus stack.
To fix this, workspace 1 must be placed on the focus stack between
workspace 2 and the focused view. That's what this patch does.
Lastly, it also uses seat_get_focus_inactive to choose the focus. This
fixes a crash when a view unmaps while a non-container is focused (eg.
swaylock), because focus is NULL.
This approaches cursor rebasing from a different angle. Rather than
littering the codebase with cursor_rebase calls and using transaction
callbacks, this just runs cursor_rebase after applying every transaction
- but only if there's outputs connected, because otherwise it causes a
crash during shutdown.
There is one known case where we still need to call cursor_rebase
directly, and that's when running `seat seat0 cursor move ...`. This
command doesn't set anything as dirty so no transaction occurs.
* When using multiple seats, each seat has its own prev_workspace_name
for the purpose of workspace back_and_forth.
* Removes prev_workspace_name global variable.
* Removes unused next_name_map function in tree/workspace.c.
* Fixes memory leak in seat_destroy (seat was not freed).
The directive controlled whether floating views should raise to the top
when the cursor is moved over it while using focus_follows_mouse. The
default was enabled, which is undesirable. For example, if you have two
floating views where one completely covers the other, the smaller one
would be inaccessible because moving the mouse over the bigger one would
raise it above the smaller one.
There is no known use case for having raise_floating enabled, so this
patch removes the directive and implements the raise_floating disabled
behaviour instead.
The input manager is a singleton object. Passing the sway_input_manager
argument to each of its functions is unnecessary, while removing the
argument makes it obvious to the caller that it's a singleton. This
patch removes the argument and makes the input manager use server.input
instead.
On a similar note:
* sway_input_manager.server is removed in favour of using the server
global.
* seat.input is removed because it can get it from server.input.
Due to a circular dependency, creating seat0 is now done directly in
server_init rather than in input_manager_create. This is because
creating seats must be done after server.input is set.
Lastly, it now stores the default seat name using a constant and removes
a second reference to seat0 (in input_manager_get_default_seat).
If the container being dragged has a parent that needs to be reaped, it
must be reaped after we've reinserted the dragging container into the
tree. During reaping, handle_seat_node_destroy tries to refocus the
dragging container which isn't possible while it's detached.
Fixes a regression introduced in
24a90e5d86.
consider_warp_to_focus has been renamed to seat_consider_warp_to_focus,
moved to seat.c and made public. It is now called when switching
workspaces via `workspace <ws>`.
Because cursor warping was the default behaviour in seat_set_focus,
there may be cases where we may have been warping the cursor
unintentionally. This patch removes cursor warping from seat_set_focus
and only does it in the focus command. This is managed by a static
function in focus.c.
To know whether to warp or not, we need to know which node had focus
previously. To keep track of this easily, seat->prev_focus has been
introduced and is set to the previous in seat_set_focus.
Previously we would compare the last focus's workspace with the new
focus's workspace to determine if we need to emit an IPC
workspace::focus event. This doesn't work when moving the focused
container to a new workspace.
This adds a workspace property to the seat which stores the last emitted
workspace::focus workspace. Using this method, after moving the
container, refocusing it will trigger exactly one workspace::focus
event: from the old workspace to the new workspace.
This introduces seat_set_raw_focus: a function that manipulates the
focus stack without doing any other behaviour whatsoever. There are a
few places where this is useful, such as where we set focus_inactive
followed by another call to set the real focus again. With this change,
the notify argument to seat_set_focus_warp is also removed as these
cases now use the raw function instead.
A bonus of this is we are no longer emitting window::focus IPC events
when setting focus_inactive, nor are we sending focus/unfocus events to
the surface.
This also fixes the following:
* When running `move workspace to output <name>` and moving the last
workspace from the source output, the workspace::focus IPC event is no
longer emitted for the newly created workspace.
* When splitting the currently focused container, unfocus/focus events
will not be sent to the surface when giving focus_inactive to the newly
created parent, and window::focus events will not be emitted.
* Set focus to a floating container when clicking its title bar.
* Raise floating when user clicks title bar or decorations (in the
seat_begin functions).
* In container_at, it only returned a floating container if the user had
clicked the surface. This makes it use floating_container_at instead.
This introduces a new view_impl function: is_transient_for. Similar to
container_has_ancestor but works using the surface parents rather than
the tree.
This patch modifies view_is_visible, container_at and so on to allow
transient views to function normally when they're in front of a
fullscreen view.
* Create a view on workspace 1
* Switch to workspace 2 (on the same output) and create a floating
sticky view
* Use criteria to focus the view on workspace 1
Previously, we only moved the sticky containers when using
workspace_switch, but the above method of focusing doesn't call it. This
patch relocates the sticky-moving code into seat_set_focus_warp.
A side effect of this patch is that if you have a sticky container
focused and then switch workspaces, the sticky container will no longer
be focused. It would previously retain focus.
In seat_set_focus_warp, new_output_last_ws was only set when changing
outputs, but now it's always set. This means new_output_last_ws and
last_workspace might point to the same workspace, which means we have to
make sure we don't destroy it twice. It now checks to make sure they're
different, and to make this more obvious I've moved both calls to
workspace_consider_destroy to be next to each other.
container_flatten removes the container from the tree (via
container_replace) before destroying it. When destroying, the recent
changes to handle_seat_node_destroy incorrectly assumes that the
container has a parent.
This adds a check for destroying a container which is no longer in the
tree. If this is the case, focus does not need to be changed.
* Have multiple outputs
* Launch swaylock
* Unplug an output (possibly has to be the last "connected" one)
* The swaylock surface on the remaining output would not respond to key
events
This was happening because when the output destroys, focus was not given
to the other swaylock surface.
This patch makes focus be transferred to another surface owned by the
same Wayland client, but only if input was inhibited by the surface
being destroyed, and only if it's in the overlay layer. I figure it's
best to be overly specific and relax the requirements later if needed.
This patch removes a check in seat_set_focus_surface which was
preventing focus from being passed from a layer surface to any other
surface. I don't know of a use case for this check, but it's possible
that this change could produce issues.
* New configuration option: raise_floating
(From the discussion on https://github.com/i3/i3/issues/2990)
* By default, it still raises the window on focus, otherwise it
will raise the window on click.
To reproduce the problem, create layout
H[view V[view view view-focused]], then switch to another workspace and
have the previously focused view in the vsplit close (eg. using
criteria, or an mpv video finishing). Return to the workspace using
`$mod+<num>` and the entire vsplit would be focused. This happens
because handle_seat_node_destroy would only set a new focus if the
currently focused view or a parent was being destroyed. To fix it, it
needs to set a sibling of the destroying container to focus_inactive
regardless of the current focus, then restore current focus if needed.
This patch changes the function accordingly. Additionally:
* The function now makes an early return if the node being destroyed is
a workspace.
* set_focus has been renamed to needs_new_focus. This variable is true
if the head focus needs to be changed.
seat_get_active_child is used to get the active tiling child in a few
places, such as outputs getting their active workspace and
tabbed/stacked containers getting their visible child. When a workspace
uses a tabbed or stacked layout and contains a focused floating view,
calling seat_get_active_child on the workspace would incorrectly return
the floating view. This changes it so it will return the tiling child.
This fixes the following bug:
* Create layout T[view view] then float one of the views
* Attempt to click the tiling view to give it focus - it wouldn't work
because seat_get_active_child would return the floating view
* Make container_add_sibling's `after` argument a boolean.
* Use a constant for drop layout border
* Make thickness an int
* Add button state check
* Move comments in seat_end_move_tiling
These are the same as seat_set_focus, but accept a specific type rather
than using nodes. Doing this adds more typesafety and lets us avoid
using &con->node which looks a little ugly.
This fixes a crash that pretty much nobody would ever come across. If
you have a bindsym for "focus" with no arguments and run it from an
empty workspace, sway would crash because it assumes `container` is not
NULL.
* Was crashing when a view was moved to the scratchpad (prev focus had
no parent).
* Was crashing when a hidden scratchpad view unmaps because it has no
workspace.
When changing focus from a view in one workspace to an empty workspace
using `focus <direction>`, the view in the previous workspace would keep
focused styling. This is because the check to unfocus it was only done
in the container case and not workspace case, so it's been moved out of
both.
This commit changes the meaning of sway_container so that it only refers
to layout containers and view containers. Workspaces, outputs and the
root are no longer known as containers. Instead, root, outputs,
workspaces and containers are all a type of node, and containers come in
two types: layout containers and view containers.
In addition to the above, this implements type safe variables. This
means we use specific types such as sway_output and sway_workspace
instead of generic containers or nodes. However, it's worth noting that
in a few places places (eg. seat focus and transactions) referring to
them in a generic way is unavoidable which is why we still use nodes in
some places.
If you want a TL;DR, look at node.h, as well as the struct definitions
for root, output, workspace and container. Note that sway_output now
contains a workspaces list, and workspaces now contain a tiling and
floating list, and containers now contain a pointer back to the
workspace.
There are now functions for seat_get_focused_workspace and
seat_get_focused_container. The latter will return NULL if a workspace
itself is focused. Most other seat functions like seat_get_focus and
seat_set_focus now accept and return nodes.
In the config->handler_context struct, current_container has been
replaced with three pointers: node, container and workspace. node is the
same as what current_container was, while workspace is the workspace
that the node resides on and container is the actual container, which
may be NULL if a workspace itself is focused.
The global root_container variable has been replaced with one simply
called root, which is a pointer to the sway_root instance.
The way outputs are created, enabled, disabled and destroyed has
changed. Previously we'd wrap the sway_output in a container when it is
enabled, but as we don't have containers any more it needs a different
approach. The output_create and output_destroy functions previously
created/destroyed the container, but now they create/destroy the
sway_output. There is a new function output_disable to disable an output
without destroying it.
Containers have a new view property. If this is populated then the
container is a view container, otherwise it's a layout container. Like
before, this property is immutable for the life of the container.
Containers have both a `sway_container *parent` and
`sway_workspace *workspace`. As we use specific types now, parent cannot
point to a workspace so it'll be NULL for containers which are direct
children of the workspace. The workspace property is set for all
containers, except those which are hidden in the scratchpad as they have
no workspace.
In some cases we need to refer to workspaces in a container-like way.
For example, workspaces have layout and children, but when using
specific types this makes it difficult. Likewise, it's difficult for a
container to get its parent's layout when the parent could be another
container or a workspace. To make it easier, some helper functions have
been created: container_parent_layout and container_get_siblings.
container_remove_child has been renamed to container_detach and
container_replace_child has been renamed to container_replace.
`container_handle_fullscreen_reparent(con, old_parent)` has had the
old_parent removed. We now unfullscreen the workspace when detaching the
container, so this function is simplified and only needs one argument
now.
container_notify_subtree_changed has been renamed to
container_update_representation. This is more descriptive of its
purpose. I also wanted to be able to call it with whatever container was
changed rather than the container's parent, which makes bubbling up to
the workspace easier.
There are now state structs per node thing. ie. sway_output_state,
sway_workspace_state and sway_container_state.
The focus, move and layout commands have been completely refactored to
work with the specific types. I considered making these a separate PR,
but I'd be backporting my changes only to replace them again, and it's
easier just to test everything at once.
This moves the arrange_windows call into the arrange_layers function,
where we know the output actually needs to be arranged.
Additionally, we shouldn't set focus to the parent of an unknown
container type, because the parent may be an output and this causes a
crash because outputs can't have direct focus.
Fixes#2543
When we have type safety we'll need to have functions for
workspace_add_tiling and so on. This means the existing container
functions will be just for containers, so they are being moved to
container.c. At this point layout.c doesn't contain much else, so I've
relocated everything and removed the file.
* container_swap and its static functions have been moved to the swap
command and made static.
* container_recursive_resize has been moved to the resize command and
made static.
* The following have been moved to container.c:
* container_handle_fullscreen_reparent
* container_insert_child
* container_add_sibling
* container_add_child
* container_remove_child
* container_replace_child
* container_split
* enum movement_direction and sway_dir_to_wlr have been moved to util.c.
Side note: Several commands included layout.h which then included
root.h. With layout.h gone, root.h has to be included by those commands.
This changes the destroy functions to the following:
* output_begin_destroy
* output_destroy
* workspace_begin_destroy
* workspace_destroy
* container_begin_destroy
* container_destroy
* view_begin_destroy
* view_destroy
The terminology was `destroy` and `free`, and it has been changed to
`begin_destroy` and `destroy` respectively.
When the last output is disconnected, its workspaces will now be stashed
in the root. Upon connection of a new output they will be restored.
There is a new function `workspace_consider_destroy` which decides
whether the given workspace should be destroyed or not (ie. empty and
not visible).
Calling container_begin_destroy will no longer automatically reap the
parents. In some places we want to reap the parents and in some we
don't, so this is left to the caller.
container_reap_empty_recursive and container_reap_empty have been
combined into one function and it will recurse up the tree.
Workspaces previously had a magical `workspace->floating` container,
which had a layout of L_FLOATING and whose children were actual floating
views. This allowed some conveniences, but was a hacky solution because
the container has to be exempt from focus, coordinate transactions with
the workspace, and omit emitting IPC events (which we didn't do).
This commit changes it to be a list directly in the sway_workspace. The
L_FLOATING layout is no longer used so this has been removed as well.
* Fixes incorrect check in the swap command (it checked if the
containers had the L_FLOATING layout, but this layout applied to the
magical container).
* Introduces workspace_add_floating
This introduces the following `for_each` functions:
* root_for_each_workspace
* root_for_each_container
* output_for_each_workspace
* output_for_each_container
* workspace_for_each_container
And introduces the following `find` functions:
* root_find_output
* root_find_workspace
* root_find_container
* output_find_workspace
* output_find_container
* workspace_find_container
* container_find_child
And removes the following functions:
* container_descendants
* container_for_each_descendant
* container_find
This change is preparing the way for demoting sway_container. Eventually
these functions will accept and return sway_outputs, sway_workspaces and
sway_containers (meaning a C_CONTAINER or C_VIEW).
This change also makes it easy to handle abnormalities like the
workspace floating list, root's scratchpad list and (once implemented)
root's saved workspaces list for when there's no connected outputs.