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.
Since wayland does not currently allow swaybar to create global
keybinds, this is handled within sway and sent to the bar using a custom
event, so as not to pollute existing events, called bar_state_update.
Allows bar-subcommand to be a valid bar-ids
Destroys runtime created bar if trying to use a config only subcommand
Allow subcommands (except for id) to be ids
While allowing negative values for the outer gaps it is still prevented that negative values move windows out of the container. This replaces the non-i3 option for edge_gaps.
When locked, there is no active workspace so it must find the
focus_inactive workspace instead.
Additionally, this adds a check for if a view maps while there are no
outputs connected and handles it gracefully.
The basic idea here is to apply rounding after scaling. It's not as
simple as this, though, and I've detailed it in the comments for a
function.
In order to fix some pixel leaks in the title bar, I found it easier to
change how we place rectangles to fill the area. Instead of placing two
rectangles across the full width above and below the title and having
shorter rectangles in the inner area, it's now pieced together in
vertical chunks. This method involves drawing two less rectangles per
container.
* 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.
In view_autoconfigure the height of the view is adjusted if the parent
container has a tabbed/stacked layout. Previously this height change
would also be applied to floating views, although it is not needed for
them.
Returning a boolean from container_resize_tiled and resize_tiled doesn't
work in all cases. This patch changes it back to void and does a
before/after check to see if the container was resized.
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.
Sway sets a default status_command which runs date every second. This
patch removes this behaviour so the user can have a NULL status bar if
desired.
I had to swap swaybar's event_loop_poll and wl_display_flush so that it
would map the initial surface.
This patch makes it so when you run reload, the actual reloading is
deferred to the next time the event loop becomes idle. This avoids
several use-after-frees and removes the workarounds we have to avoid
them.
When you run reload, we validate the config before creating the idle
event. This is so the reload command will still return an error if there
are validation errors. To allow this, load_main_config has been adjusted
so it doesn't apply the config if validating is true rather than
applying it unconditionally.
This also fixes a memory leak in the reload command where if the config
failed to load, the bar_ids list would not be freed.
The previous behaviour was to damage the entire view, which would
recurse into each popup. This patch makes it damage only the popup's
surface, and respect the surface damage given by the client.
This adds listeners to the popup's map and unmap events rather than
doing the damage in the create and destroy functions. To get the popup's
position relative to the view, a new child_impl function get_root_coords
has been introduced, which traverses up the parents.
* 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.
* Click and hold a scrollbar
* Drag the cursor onto another surface
* While still holding the original button, press and release another
cursor button
* Things get weird
There's two ways to fix this. Either cancel the seat operation and do
the other click, or continue the seat operation and ignore the other
click. I opted for the latter (ignoring the click) because it's easier
to implement, and I suspect a second click during a seat operation is
probably unintentional anyway.
* 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.
Re-focus on the container on which the cursor hovers over. A
special case is, if there are menus or other subsurfaces open
in the focused container. It will prefer the focused container
as long as there are subsurfaces.
This commit starts caching the previous node as well as the
previous x/y cursor position. Re-calculating the previous
focused node by looking at the current state of the cursor
position does not work, if the environment changes.
* 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.
Fixes `hide_edge_borders smart` when gaps are in use.
Implements `hide_edge_borders smart_no_gaps` and `smart_borders
on|no_gaps|off`.
Since `smart_borders on` is equivalent to `hide_edge_borders smart`
and `smart_borders no_gaps` is equivalent to `hide_edge_borders
smart_no_gaps`, I opted to just save the last value set for
`hide_edge_borders` and restore that on `smart_borders off`. This
simplifies the conditions for setting the border.
It's better to use DT_RPATH dynamic section of the elf binary to store
the paths of libraries to load instead of overwriting LD_LIBRARY_PATH
for the whole environment, causing surprises. This solution is much more
transparent and perfectly suitable for running contained installations
of wayland/wlroots/sway.
The code unsetting the LD_LIBRARY_PATH/LD_PRELOAD was also deleted as
it's a placebo security at best - we should trust the execution path
that leads us to running sway, and it's way too late to care about those
variables since we already started executing our compositor, thus we
would be compromised anyway.
When the last output is disconnected, output_disable is called like
usual and evacuates the output to the root->saved_workspaces list. It
then calls root_for_each_container to remove (untrack) the output from
each container's outputs list. However root_for_each_container did not
iterate the saved workspaces, so when the output gets freed the
containers would have a dangling pointer in their outputs list. Upon
reconnect, container_discover_outputs would attempt to use the dangling
pointer, causing a crash.
This makes root_for_each_container check the saved workspaces list,
which fixes the problem.