2018-03-31 23:49:40 +02:00
|
|
|
#include <stdlib.h>
|
2018-08-06 13:46:28 +02:00
|
|
|
#include <strings.h>
|
2019-07-27 22:02:56 +02:00
|
|
|
#include <wayland-server-core.h>
|
2018-04-30 13:24:13 +02:00
|
|
|
#include <wlr/render/wlr_renderer.h>
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
#include <wlr/types/wlr_buffer.h>
|
2024-02-15 12:01:24 +01:00
|
|
|
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
|
|
|
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
2018-02-25 23:23:36 +01:00
|
|
|
#include <wlr/types/wlr_output_layout.h>
|
2018-09-24 12:54:57 +02:00
|
|
|
#include <wlr/types/wlr_server_decoration.h>
|
2022-01-13 11:15:39 +01:00
|
|
|
#include <wlr/types/wlr_subcompositor.h>
|
2018-09-24 12:54:57 +02:00
|
|
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
2018-07-25 13:43:21 +02:00
|
|
|
#include "config.h"
|
2018-11-18 00:33:06 +01:00
|
|
|
#if HAVE_XWAYLAND
|
2018-06-27 02:32:09 +02:00
|
|
|
#include <wlr/xwayland.h>
|
2018-07-24 22:16:06 +02:00
|
|
|
#endif
|
2018-05-13 00:16:36 +02:00
|
|
|
#include "list.h"
|
2018-03-30 19:18:50 +02:00
|
|
|
#include "log.h"
|
2018-04-24 06:59:49 +02:00
|
|
|
#include "sway/criteria.h"
|
|
|
|
#include "sway/commands.h"
|
Prepare arrange code for type safe arguments
This commit changes the arrange code in a way that will support type
safe arguments.
The arrange_output et al functions are now public, however I opted not
to use them directly yet. I've kept the generic arrange_windows there
for convenience until type safety is fully implemented. This means this
patch has much less risk of breaking things as it would otherwise.
To be type safe, arrange_children_of cannot exist in its previous form
because the thing passed to it could be either a workspace or a
container. So it's now renamed to arrange_children and accepts a list_t,
as well as the parent layout and parent's box.
There was some code which checked the grandparent's layout to see if it
was tabbed or stacked and adjusted the Y offset of the grandchild
accordingly. Accessing the grandparent layout isn't easy when using type
safe arguments, and it seemed odd to even need to do this. I determined
that this was needed because a child of a tabbed container would have a
swayc Y matching the top of the tab bar. I've changed this so a child of
a tabbed container will have a swayc Y matching the bottom of the tab
bar, which means we don't need to access the grandparent layout. Some
tweaks to the rendering and autoconfigure code have been made to
implement this, and the container_at code appears to work without
needing any changes.
arrange_children_of (now arrange_children) would check if the parent had
gaps and would copy them to the child, effectively making the
workspace's gaps recurse into all children. We can't do this any more
without passing has_gaps, gaps_inner and gaps_outer as arguments to
arrange_children, so I've changed the add_gaps function to retrieve it
from the workspace directly.
apply_tabbed_or_stacked_layout has been split into two functions, as it
had different logic depending on the layout.
Lastly, arrange.h had an unnecessary include of transaction.h. I've
removed it, which means I've had to add it to several other files.
2018-08-26 02:16:49 +02:00
|
|
|
#include "sway/desktop/transaction.h"
|
2020-05-05 18:35:03 +02:00
|
|
|
#include "sway/desktop/idle_inhibit_v1.h"
|
2022-11-16 23:50:34 +01:00
|
|
|
#include "sway/desktop/launcher.h"
|
2018-09-10 07:47:58 +02:00
|
|
|
#include "sway/input/cursor.h"
|
2018-04-16 12:36:40 +02:00
|
|
|
#include "sway/ipc-server.h"
|
2018-03-30 19:18:50 +02:00
|
|
|
#include "sway/output.h"
|
2018-04-24 06:59:49 +02:00
|
|
|
#include "sway/input/seat.h"
|
2023-11-23 16:09:48 +01:00
|
|
|
#include "sway/scene_descriptor.h"
|
2019-08-20 11:30:09 +02:00
|
|
|
#include "sway/server.h"
|
2023-11-22 01:51:57 +01:00
|
|
|
#include "sway/sway_text_node.h"
|
2018-04-28 03:26:14 +02:00
|
|
|
#include "sway/tree/arrange.h"
|
2018-03-30 05:41:33 +02:00
|
|
|
#include "sway/tree/container.h"
|
|
|
|
#include "sway/tree/view.h"
|
2018-04-17 01:31:34 +02:00
|
|
|
#include "sway/tree/workspace.h"
|
2018-05-07 18:30:45 +02:00
|
|
|
#include "sway/config.h"
|
2018-09-24 12:54:57 +02:00
|
|
|
#include "sway/xdg_decoration.h"
|
2018-05-07 18:30:45 +02:00
|
|
|
#include "pango.h"
|
2018-05-25 13:07:59 +02:00
|
|
|
#include "stringop.h"
|
2018-01-21 15:09:53 +01:00
|
|
|
|
2022-03-05 01:23:27 +01:00
|
|
|
bool view_init(struct sway_view *view, enum sway_view_type type,
|
2018-04-01 00:07:44 +02:00
|
|
|
const struct sway_view_impl *impl) {
|
2024-01-18 16:00:45 +01:00
|
|
|
bool failed = false;
|
|
|
|
view->scene_tree = alloc_scene_tree(root->staging, &failed);
|
|
|
|
view->content_tree = alloc_scene_tree(view->scene_tree, &failed);
|
2023-11-23 16:09:48 +01:00
|
|
|
|
|
|
|
if (!failed && !scene_descriptor_assign(&view->scene_tree->node,
|
|
|
|
SWAY_SCENE_DESC_VIEW, view)) {
|
|
|
|
failed = true;
|
|
|
|
}
|
|
|
|
|
2024-01-18 16:00:45 +01:00
|
|
|
if (failed) {
|
|
|
|
wlr_scene_node_destroy(&view->scene_tree->node);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-31 23:49:40 +02:00
|
|
|
view->type = type;
|
2018-04-01 00:07:44 +02:00
|
|
|
view->impl = impl;
|
2018-05-13 00:16:36 +02:00
|
|
|
view->executed_criteria = create_list();
|
2018-07-15 14:43:33 +02:00
|
|
|
view->allow_request_urgent = true;
|
2020-03-12 22:10:04 +01:00
|
|
|
view->shortcuts_inhibit = SHORTCUTS_INHIBIT_DEFAULT;
|
2018-04-05 20:46:02 +02:00
|
|
|
wl_signal_init(&view->events.unmap);
|
2022-03-05 01:23:27 +01:00
|
|
|
return true;
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
|
|
|
|
2018-08-20 07:54:30 +02:00
|
|
|
void view_destroy(struct sway_view *view) {
|
2018-06-23 08:24:11 +02:00
|
|
|
if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) {
|
2018-03-31 23:49:40 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-06-23 08:24:11 +02:00
|
|
|
if (!sway_assert(view->destroying,
|
|
|
|
"Tried to free view which wasn't marked as destroying")) {
|
|
|
|
return;
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (!sway_assert(view->container == NULL,
|
|
|
|
"Tried to free view which still has a container "
|
2018-06-23 08:24:11 +02:00
|
|
|
"(might have a pending transaction?)")) {
|
2018-06-03 08:35:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-04-18 02:11:59 +02:00
|
|
|
wl_list_remove(&view->events.unmap.listener_list);
|
2018-05-13 00:16:36 +02:00
|
|
|
list_free(view->executed_criteria);
|
|
|
|
|
2022-11-16 23:50:34 +01:00
|
|
|
view_assign_ctx(view, NULL);
|
2024-01-18 16:00:45 +01:00
|
|
|
wlr_scene_node_destroy(&view->scene_tree->node);
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
free(view->title_format);
|
2018-05-15 06:48:19 +02:00
|
|
|
|
2018-06-26 05:18:33 +02:00
|
|
|
if (view->impl->destroy) {
|
|
|
|
view->impl->destroy(view);
|
2018-04-05 17:38:14 +02:00
|
|
|
} else {
|
|
|
|
free(view);
|
|
|
|
}
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
|
|
|
|
2018-08-20 07:54:30 +02:00
|
|
|
void view_begin_destroy(struct sway_view *view) {
|
2018-06-23 08:24:11 +02:00
|
|
|
if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
view->destroying = true;
|
|
|
|
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (!view->container) {
|
2018-08-20 07:54:30 +02:00
|
|
|
view_destroy(view);
|
2018-06-23 08:24:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-21 15:09:53 +01:00
|
|
|
const char *view_get_title(struct sway_view *view) {
|
2018-05-13 00:16:36 +02:00
|
|
|
if (view->impl->get_string_prop) {
|
|
|
|
return view->impl->get_string_prop(view, VIEW_PROP_TITLE);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *view_get_app_id(struct sway_view *view) {
|
2018-05-13 00:16:36 +02:00
|
|
|
if (view->impl->get_string_prop) {
|
|
|
|
return view->impl->get_string_prop(view, VIEW_PROP_APP_ID);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *view_get_class(struct sway_view *view) {
|
2018-05-13 00:16:36 +02:00
|
|
|
if (view->impl->get_string_prop) {
|
|
|
|
return view->impl->get_string_prop(view, VIEW_PROP_CLASS);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *view_get_instance(struct sway_view *view) {
|
2018-05-13 00:16:36 +02:00
|
|
|
if (view->impl->get_string_prop) {
|
|
|
|
return view->impl->get_string_prop(view, VIEW_PROP_INSTANCE);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-11-18 00:33:06 +01:00
|
|
|
#if HAVE_XWAYLAND
|
2018-05-13 00:16:36 +02:00
|
|
|
uint32_t view_get_x11_window_id(struct sway_view *view) {
|
|
|
|
if (view->impl->get_int_prop) {
|
|
|
|
return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-10-22 21:17:27 +02:00
|
|
|
|
|
|
|
uint32_t view_get_x11_parent_id(struct sway_view *view) {
|
|
|
|
if (view->impl->get_int_prop) {
|
|
|
|
return view->impl->get_int_prop(view, VIEW_PROP_X11_PARENT_ID);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-07-24 22:16:06 +02:00
|
|
|
#endif
|
2018-05-13 00:17:46 +02:00
|
|
|
const char *view_get_window_role(struct sway_view *view) {
|
|
|
|
if (view->impl->get_string_prop) {
|
|
|
|
return view->impl->get_string_prop(view, VIEW_PROP_WINDOW_ROLE);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-05-13 00:16:36 +02:00
|
|
|
uint32_t view_get_window_type(struct sway_view *view) {
|
|
|
|
if (view->impl->get_int_prop) {
|
|
|
|
return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-27 13:59:38 +02:00
|
|
|
const char *view_get_shell(struct sway_view *view) {
|
2018-05-05 04:36:50 +02:00
|
|
|
switch(view->type) {
|
2018-05-13 17:38:56 +02:00
|
|
|
case SWAY_VIEW_XDG_SHELL:
|
|
|
|
return "xdg_shell";
|
2018-11-18 00:33:06 +01:00
|
|
|
#if HAVE_XWAYLAND
|
2018-05-05 04:36:50 +02:00
|
|
|
case SWAY_VIEW_XWAYLAND:
|
|
|
|
return "xwayland";
|
2018-07-24 23:37:41 +02:00
|
|
|
#endif
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
2018-07-21 04:13:00 +02:00
|
|
|
void view_get_constraints(struct sway_view *view, double *min_width,
|
|
|
|
double *max_width, double *min_height, double *max_height) {
|
|
|
|
if (view->impl->get_constraints) {
|
|
|
|
view->impl->get_constraints(view,
|
|
|
|
min_width, max_width, min_height, max_height);
|
|
|
|
} else {
|
|
|
|
*min_width = DBL_MIN;
|
|
|
|
*max_width = DBL_MAX;
|
|
|
|
*min_height = DBL_MIN;
|
|
|
|
*max_height = DBL_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-03 08:35:06 +02:00
|
|
|
uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
|
2018-04-02 16:57:45 +02:00
|
|
|
int height) {
|
|
|
|
if (view->impl->configure) {
|
2018-06-03 08:35:06 +02:00
|
|
|
return view->impl->configure(view, lx, ly, width, height);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
2018-06-03 08:35:06 +02:00
|
|
|
return 0;
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
|
2020-05-05 18:35:03 +02:00
|
|
|
bool view_inhibit_idle(struct sway_view *view) {
|
|
|
|
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
|
|
|
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
|
|
|
|
|
|
|
struct sway_idle_inhibitor_v1 *application_inhibitor =
|
|
|
|
sway_idle_inhibit_v1_application_inhibitor_for_view(view);
|
|
|
|
|
|
|
|
if (!user_inhibitor && !application_inhibitor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!user_inhibitor) {
|
|
|
|
return sway_idle_inhibit_v1_is_active(application_inhibitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!application_inhibitor) {
|
|
|
|
return sway_idle_inhibit_v1_is_active(user_inhibitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sway_idle_inhibit_v1_is_active(user_inhibitor)
|
|
|
|
|| sway_idle_inhibit_v1_is_active(application_inhibitor);
|
|
|
|
}
|
|
|
|
|
2020-06-01 01:03:42 +02:00
|
|
|
bool view_ancestor_is_only_visible(struct sway_view *view) {
|
|
|
|
bool only_visible = true;
|
2018-10-01 15:41:15 +02:00
|
|
|
struct sway_container *con = view->container;
|
|
|
|
while (con) {
|
|
|
|
enum sway_container_layout layout = container_parent_layout(con);
|
|
|
|
if (layout != L_TABBED && layout != L_STACKED) {
|
|
|
|
list_t *siblings = container_get_siblings(con);
|
|
|
|
if (siblings && siblings->length > 1) {
|
2020-06-01 01:03:42 +02:00
|
|
|
only_visible = false;
|
2018-10-01 15:41:15 +02:00
|
|
|
}
|
2020-06-01 01:03:42 +02:00
|
|
|
} else {
|
|
|
|
only_visible = true;
|
2018-10-01 15:41:15 +02:00
|
|
|
}
|
2021-02-12 23:22:51 +01:00
|
|
|
con = con->pending.parent;
|
2018-10-01 15:41:15 +02:00
|
|
|
}
|
2020-06-01 01:03:42 +02:00
|
|
|
return only_visible;
|
2018-10-01 15:41:15 +02:00
|
|
|
}
|
|
|
|
|
2020-06-27 02:12:28 +02:00
|
|
|
static bool view_is_only_visible(struct sway_view *view) {
|
|
|
|
struct sway_container *con = view->container;
|
|
|
|
while (con) {
|
|
|
|
enum sway_container_layout layout = container_parent_layout(con);
|
|
|
|
if (layout != L_TABBED && layout != L_STACKED) {
|
|
|
|
list_t *siblings = container_get_siblings(con);
|
|
|
|
if (siblings && siblings->length > 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
con = con->pending.parent;
|
2020-06-27 02:12:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-10-01 18:56:27 +02:00
|
|
|
static bool gaps_to_edge(struct sway_view *view) {
|
2021-02-12 23:22:51 +01:00
|
|
|
struct side_gaps gaps = view->container->pending.workspace->current_gaps;
|
2018-11-08 04:44:11 +01:00
|
|
|
return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0;
|
2018-10-01 18:56:27 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 13:24:13 +02:00
|
|
|
void view_autoconfigure(struct sway_view *view) {
|
Move view {x,y,width,height} into container struct
This renames/moves the following properties:
* sway_view.{x,y,width,height} ->
sway_container.content_{x,y,width,height}
* This is required to support placeholder containers as they don't
have a view.
* sway_container_state.view_{x,y,width,height} ->
sway_container_state.content_{x,y,width,height}
* To remain consistent with the above.
* sway_container_state.con_{x,y,width,height} ->
sway_container_state.{x,y,width,height}
* The con prefix was there to give it contrast from the view
properties, and is no longer useful.
The function container_set_geometry_from_floating_view has also been
renamed to container_set_geometry_from_content.
2018-11-17 09:32:03 +01:00
|
|
|
struct sway_container *con = view->container;
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_workspace *ws = con->pending.workspace;
|
2019-04-16 21:11:35 +02:00
|
|
|
|
2019-04-01 05:27:18 +02:00
|
|
|
if (container_is_scratchpad_hidden(con) &&
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.fullscreen_mode != FULLSCREEN_GLOBAL) {
|
2018-09-05 09:59:31 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-04-16 21:11:35 +02:00
|
|
|
struct sway_output *output = ws ? ws->output : NULL;
|
2018-05-14 06:20:34 +02:00
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
|
|
|
|
con->pending.content_x = output->lx;
|
|
|
|
con->pending.content_y = output->ly;
|
|
|
|
con->pending.content_width = output->width;
|
|
|
|
con->pending.content_height = output->height;
|
2018-04-30 13:24:13 +02:00
|
|
|
return;
|
2021-02-12 23:22:51 +01:00
|
|
|
} else if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
|
|
|
|
con->pending.content_x = root->x;
|
|
|
|
con->pending.content_y = root->y;
|
|
|
|
con->pending.content_width = root->width;
|
|
|
|
con->pending.content_height = root->height;
|
2019-01-24 23:29:21 +01:00
|
|
|
return;
|
2018-04-30 13:24:13 +02:00
|
|
|
}
|
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_top = con->pending.border_bottom = true;
|
|
|
|
con->pending.border_left = con->pending.border_right = true;
|
2019-04-16 21:20:48 +02:00
|
|
|
double y_offset = 0;
|
|
|
|
|
2021-05-17 15:48:08 +02:00
|
|
|
if (!container_is_floating_or_child(con) && ws) {
|
2019-04-01 05:27:18 +02:00
|
|
|
if (config->hide_edge_borders == E_BOTH
|
2020-06-27 02:12:28 +02:00
|
|
|
|| config->hide_edge_borders == E_VERTICAL) {
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_left = con->pending.x != ws->x;
|
|
|
|
int right_x = con->pending.x + con->pending.width;
|
|
|
|
con->pending.border_right = right_x != ws->x + ws->width;
|
2019-04-01 05:27:18 +02:00
|
|
|
}
|
2020-06-27 02:12:28 +02:00
|
|
|
|
2019-04-01 05:27:18 +02:00
|
|
|
if (config->hide_edge_borders == E_BOTH
|
2020-06-27 02:12:28 +02:00
|
|
|
|| config->hide_edge_borders == E_HORIZONTAL) {
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_top = con->pending.y != ws->y;
|
|
|
|
int bottom_y = con->pending.y + con->pending.height;
|
|
|
|
con->pending.border_bottom = bottom_y != ws->y + ws->height;
|
2019-04-01 05:27:18 +02:00
|
|
|
}
|
2018-05-14 06:20:34 +02:00
|
|
|
|
2020-06-27 02:12:28 +02:00
|
|
|
bool smart = config->hide_edge_borders_smart == ESMART_ON ||
|
|
|
|
(config->hide_edge_borders_smart == ESMART_NO_GAPS &&
|
|
|
|
!gaps_to_edge(view));
|
|
|
|
if (smart) {
|
2021-05-17 15:48:08 +02:00
|
|
|
bool show_border = !view_is_only_visible(view);
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_left &= show_border;
|
|
|
|
con->pending.border_right &= show_border;
|
|
|
|
con->pending.border_top &= show_border;
|
|
|
|
con->pending.border_bottom &= show_border;
|
2020-06-27 02:12:28 +02:00
|
|
|
}
|
2021-05-17 15:48:08 +02:00
|
|
|
}
|
2020-06-27 02:12:28 +02:00
|
|
|
|
2021-05-17 15:48:08 +02:00
|
|
|
if (!container_is_floating(con)) {
|
2019-04-16 21:20:48 +02:00
|
|
|
// In a tabbed or stacked container, the container's y is the top of the
|
|
|
|
// title area. We have to offset the surface y by the height of the title,
|
|
|
|
// bar, and disable any top border because we'll always have the title bar.
|
|
|
|
list_t *siblings = container_get_siblings(con);
|
|
|
|
bool show_titlebar = (siblings && siblings->length > 1)
|
|
|
|
|| !config->hide_lone_tab;
|
|
|
|
if (show_titlebar) {
|
|
|
|
enum sway_container_layout layout = container_parent_layout(con);
|
|
|
|
if (layout == L_TABBED) {
|
|
|
|
y_offset = container_titlebar_height();
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_top = false;
|
2019-04-16 21:20:48 +02:00
|
|
|
} else if (layout == L_STACKED) {
|
|
|
|
y_offset = container_titlebar_height() * siblings->length;
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border_top = false;
|
2019-04-16 21:20:48 +02:00
|
|
|
}
|
2019-02-24 10:00:15 +01:00
|
|
|
}
|
2018-05-20 07:34:08 +02:00
|
|
|
}
|
|
|
|
|
2019-01-22 16:07:38 +01:00
|
|
|
double x, y, width, height;
|
2021-02-12 23:22:51 +01:00
|
|
|
switch (con->pending.border) {
|
2019-01-22 16:07:38 +01:00
|
|
|
default:
|
2018-09-24 12:54:57 +02:00
|
|
|
case B_CSD:
|
2018-05-01 09:36:12 +02:00
|
|
|
case B_NONE:
|
2021-02-12 23:22:51 +01:00
|
|
|
x = con->pending.x;
|
|
|
|
y = con->pending.y + y_offset;
|
|
|
|
width = con->pending.width;
|
|
|
|
height = con->pending.height - y_offset;
|
2018-05-01 09:36:12 +02:00
|
|
|
break;
|
|
|
|
case B_PIXEL:
|
2021-02-12 23:22:51 +01:00
|
|
|
x = con->pending.x + con->pending.border_thickness * con->pending.border_left;
|
|
|
|
y = con->pending.y + con->pending.border_thickness * con->pending.border_top + y_offset;
|
|
|
|
width = con->pending.width
|
|
|
|
- con->pending.border_thickness * con->pending.border_left
|
|
|
|
- con->pending.border_thickness * con->pending.border_right;
|
|
|
|
height = con->pending.height - y_offset
|
|
|
|
- con->pending.border_thickness * con->pending.border_top
|
|
|
|
- con->pending.border_thickness * con->pending.border_bottom;
|
2018-05-01 09:36:12 +02:00
|
|
|
break;
|
|
|
|
case B_NORMAL:
|
2018-05-21 14:58:46 +02:00
|
|
|
// Height is: 1px border + 3px pad + title height + 3px pad + 1px border
|
2021-02-12 23:22:51 +01:00
|
|
|
x = con->pending.x + con->pending.border_thickness * con->pending.border_left;
|
|
|
|
width = con->pending.width
|
|
|
|
- con->pending.border_thickness * con->pending.border_left
|
|
|
|
- con->pending.border_thickness * con->pending.border_right;
|
2018-09-06 01:13:36 +02:00
|
|
|
if (y_offset) {
|
2021-02-12 23:22:51 +01:00
|
|
|
y = con->pending.y + y_offset;
|
|
|
|
height = con->pending.height - y_offset
|
|
|
|
- con->pending.border_thickness * con->pending.border_bottom;
|
2018-09-06 01:13:36 +02:00
|
|
|
} else {
|
2021-02-12 23:22:51 +01:00
|
|
|
y = con->pending.y + container_titlebar_height();
|
|
|
|
height = con->pending.height - container_titlebar_height()
|
|
|
|
- con->pending.border_thickness * con->pending.border_bottom;
|
2018-09-06 01:13:36 +02:00
|
|
|
}
|
2018-05-01 09:36:12 +02:00
|
|
|
break;
|
2018-04-30 13:24:13 +02:00
|
|
|
}
|
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.content_x = x;
|
|
|
|
con->pending.content_y = y;
|
|
|
|
con->pending.content_width = width;
|
|
|
|
con->pending.content_height = height;
|
2018-04-30 13:24:13 +02:00
|
|
|
}
|
|
|
|
|
2018-01-21 15:09:53 +01:00
|
|
|
void view_set_activated(struct sway_view *view, bool activated) {
|
2018-04-01 00:07:44 +02:00
|
|
|
if (view->impl->set_activated) {
|
|
|
|
view->impl->set_activated(view, activated);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
2019-08-20 11:30:09 +02:00
|
|
|
if (view->foreign_toplevel) {
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_activated(
|
|
|
|
view->foreign_toplevel, activated);
|
|
|
|
}
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
|
2022-11-30 20:02:10 +01:00
|
|
|
void view_request_activate(struct sway_view *view, struct sway_seat *seat) {
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_workspace *ws = view->container->pending.workspace;
|
2022-11-30 20:02:10 +01:00
|
|
|
if (!seat) {
|
|
|
|
seat = input_manager_current_seat();
|
|
|
|
}
|
2018-09-02 10:25:45 +02:00
|
|
|
|
|
|
|
switch (config->focus_on_window_activation) {
|
|
|
|
case FOWA_SMART:
|
2023-01-25 21:54:16 +01:00
|
|
|
if (ws && workspace_is_visible(ws)) {
|
2018-09-06 11:26:56 +02:00
|
|
|
seat_set_focus_container(seat, view->container);
|
2023-01-15 16:13:01 +01:00
|
|
|
container_raise_floating(view->container);
|
2018-09-02 10:25:45 +02:00
|
|
|
} else {
|
|
|
|
view_set_urgent(view, true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FOWA_URGENT:
|
2018-09-02 07:03:58 +02:00
|
|
|
view_set_urgent(view, true);
|
2018-09-02 10:25:45 +02:00
|
|
|
break;
|
|
|
|
case FOWA_FOCUS:
|
2023-01-25 21:54:16 +01:00
|
|
|
if (container_is_scratchpad_hidden_or_child(view->container)) {
|
|
|
|
root_scratchpad_show(view->container);
|
|
|
|
} else {
|
|
|
|
seat_set_focus_container(seat, view->container);
|
|
|
|
container_raise_floating(view->container);
|
|
|
|
}
|
2018-09-02 10:25:45 +02:00
|
|
|
break;
|
|
|
|
case FOWA_NONE:
|
|
|
|
break;
|
2018-09-02 07:03:58 +02:00
|
|
|
}
|
2023-01-15 16:13:01 +01:00
|
|
|
transaction_commit_dirty();
|
2018-09-02 07:03:58 +02:00
|
|
|
}
|
|
|
|
|
2023-12-27 07:26:02 +01:00
|
|
|
void view_request_urgent(struct sway_view *view) {
|
|
|
|
if (config->focus_on_window_activation != FOWA_NONE) {
|
|
|
|
view_set_urgent(view, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 12:54:57 +02:00
|
|
|
void view_set_csd_from_server(struct sway_view *view, bool enabled) {
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "Telling view %p to set CSD to %i", view, enabled);
|
2018-09-24 12:54:57 +02:00
|
|
|
if (view->xdg_decoration) {
|
|
|
|
uint32_t mode = enabled ?
|
|
|
|
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE :
|
|
|
|
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
|
|
|
|
wlr_xdg_toplevel_decoration_v1_set_mode(
|
|
|
|
view->xdg_decoration->wlr_xdg_decoration, mode);
|
2018-07-12 21:01:33 +02:00
|
|
|
}
|
2018-09-27 14:44:57 +02:00
|
|
|
view->using_csd = enabled;
|
2018-09-24 12:54:57 +02:00
|
|
|
}
|
2018-07-17 02:14:33 +02:00
|
|
|
|
2018-09-27 09:09:05 +02:00
|
|
|
void view_update_csd_from_client(struct sway_view *view, bool enabled) {
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "View %p updated CSD to %i", view, enabled);
|
2018-10-31 11:28:36 +01:00
|
|
|
struct sway_container *con = view->container;
|
2021-02-12 23:22:51 +01:00
|
|
|
if (enabled && con && con->pending.border != B_CSD) {
|
|
|
|
con->saved_border = con->pending.border;
|
2018-10-31 11:28:36 +01:00
|
|
|
if (container_is_floating(con)) {
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.border = B_CSD;
|
2018-07-17 02:14:33 +02:00
|
|
|
}
|
2021-02-12 23:22:51 +01:00
|
|
|
} else if (!enabled && con && con->pending.border == B_CSD) {
|
|
|
|
con->pending.border = con->saved_border;
|
2018-07-12 21:01:33 +02:00
|
|
|
}
|
2018-09-27 14:44:57 +02:00
|
|
|
view->using_csd = enabled;
|
2018-09-24 12:54:57 +02:00
|
|
|
}
|
2018-07-17 02:14:33 +02:00
|
|
|
|
2018-09-24 12:54:57 +02:00
|
|
|
void view_set_tiled(struct sway_view *view, bool tiled) {
|
2018-06-27 18:53:13 +02:00
|
|
|
if (view->impl->set_tiled) {
|
|
|
|
view->impl->set_tiled(view, tiled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-21 15:09:53 +01:00
|
|
|
void view_close(struct sway_view *view) {
|
2018-04-01 00:07:44 +02:00
|
|
|
if (view->impl->close) {
|
|
|
|
view->impl->close(view);
|
2018-01-21 15:09:53 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-25 23:23:36 +01:00
|
|
|
|
2018-07-31 11:58:34 +02:00
|
|
|
void view_close_popups(struct sway_view *view) {
|
|
|
|
if (view->impl->close_popups) {
|
|
|
|
view->impl->close_popups(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-13 00:16:36 +02:00
|
|
|
static bool view_has_executed_criteria(struct sway_view *view,
|
|
|
|
struct criteria *criteria) {
|
|
|
|
for (int i = 0; i < view->executed_criteria->length; ++i) {
|
|
|
|
struct criteria *item = view->executed_criteria->items[i];
|
|
|
|
if (item == criteria) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void view_execute_criteria(struct sway_view *view) {
|
|
|
|
list_t *criterias = criteria_for_view(view, CT_COMMAND);
|
|
|
|
for (int i = 0; i < criterias->length; i++) {
|
|
|
|
struct criteria *criteria = criterias->items[i];
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "Checking criteria %s", criteria->raw);
|
2018-05-13 00:16:36 +02:00
|
|
|
if (view_has_executed_criteria(view, criteria)) {
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "Criteria already executed");
|
2018-05-13 00:16:36 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
2018-05-13 00:16:36 +02:00
|
|
|
criteria->raw, view, criteria->cmdlist);
|
|
|
|
list_add(view->executed_criteria, criteria);
|
2018-11-28 03:42:09 +01:00
|
|
|
list_t *res_list = execute_command(
|
2018-09-23 00:38:15 +02:00
|
|
|
criteria->cmdlist, NULL, view->container);
|
2018-11-28 03:42:09 +01:00
|
|
|
while (res_list->length) {
|
|
|
|
struct cmd_results *res = res_list->items[0];
|
|
|
|
free_cmd_results(res);
|
|
|
|
list_del(res_list, 0);
|
|
|
|
}
|
|
|
|
list_free(res_list);
|
2018-04-24 06:59:49 +02:00
|
|
|
}
|
2018-05-13 00:16:36 +02:00
|
|
|
list_free(criterias);
|
2018-04-24 06:59:49 +02:00
|
|
|
}
|
|
|
|
|
2019-09-20 17:58:19 +02:00
|
|
|
static void view_populate_pid(struct sway_view *view) {
|
|
|
|
pid_t pid;
|
|
|
|
switch (view->type) {
|
|
|
|
#if HAVE_XWAYLAND
|
|
|
|
case SWAY_VIEW_XWAYLAND:;
|
|
|
|
struct wlr_xwayland_surface *surf =
|
2023-02-01 19:45:21 +01:00
|
|
|
wlr_xwayland_surface_try_from_wlr_surface(view->surface);
|
2019-09-20 17:58:19 +02:00
|
|
|
pid = surf->pid;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case SWAY_VIEW_XDG_SHELL:;
|
|
|
|
struct wl_client *client =
|
|
|
|
wl_resource_get_client(view->surface->resource);
|
|
|
|
wl_client_get_credentials(client, &pid, NULL, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
view->pid = pid;
|
|
|
|
}
|
|
|
|
|
2022-11-16 23:50:34 +01:00
|
|
|
void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx) {
|
|
|
|
if (view->ctx) {
|
|
|
|
// This ctx has been replaced
|
|
|
|
launcher_ctx_destroy(view->ctx);
|
|
|
|
view->ctx = NULL;
|
|
|
|
}
|
|
|
|
if (ctx == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
launcher_ctx_consume(ctx);
|
|
|
|
|
|
|
|
view->ctx = ctx;
|
|
|
|
}
|
|
|
|
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
static struct sway_workspace *select_workspace(struct sway_view *view) {
|
2018-10-18 13:20:00 +02:00
|
|
|
struct sway_seat *seat = input_manager_current_seat();
|
2018-07-25 15:34:00 +02:00
|
|
|
|
|
|
|
// Check if there's any `assign` criteria for the view
|
|
|
|
list_t *criterias = criteria_for_view(view,
|
2018-08-12 01:38:19 +02:00
|
|
|
CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT);
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
struct sway_workspace *ws = NULL;
|
2018-07-25 15:34:00 +02:00
|
|
|
for (int i = 0; i < criterias->length; ++i) {
|
|
|
|
struct criteria *criteria = criterias->items[i];
|
2018-08-12 01:38:19 +02:00
|
|
|
if (criteria->type == CT_ASSIGN_OUTPUT) {
|
2018-12-20 19:02:45 +01:00
|
|
|
struct sway_output *output = output_by_name_or_id(criteria->target);
|
2018-08-12 01:38:19 +02:00
|
|
|
if (output) {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
ws = output_get_active_workspace(output);
|
2018-08-12 01:38:19 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// CT_ASSIGN_WORKSPACE(_NUMBER)
|
|
|
|
ws = criteria->type == CT_ASSIGN_WORKSPACE_NUMBER ?
|
|
|
|
workspace_by_number(criteria->target) :
|
|
|
|
workspace_by_name(criteria->target);
|
|
|
|
|
2018-07-25 15:34:00 +02:00
|
|
|
if (!ws) {
|
2018-08-06 13:46:28 +02:00
|
|
|
if (strcasecmp(criteria->target, "back_and_forth") == 0) {
|
2018-10-21 03:26:22 +02:00
|
|
|
if (seat->prev_workspace_name) {
|
|
|
|
ws = workspace_create(NULL, seat->prev_workspace_name);
|
2018-08-06 13:46:28 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ws = workspace_create(NULL, criteria->target);
|
|
|
|
}
|
2018-07-25 15:34:00 +02:00
|
|
|
}
|
|
|
|
break;
|
2018-07-16 14:18:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
list_free(criterias);
|
2018-07-25 15:34:00 +02:00
|
|
|
if (ws) {
|
2022-11-16 23:50:34 +01:00
|
|
|
view_assign_ctx(view, NULL);
|
2018-07-25 15:34:00 +02:00
|
|
|
return ws;
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
|
|
|
|
2018-07-25 15:34:00 +02:00
|
|
|
// Check if there's a PID mapping
|
2022-11-16 23:50:34 +01:00
|
|
|
ws = view->ctx ? launcher_ctx_get_workspace(view->ctx) : NULL;
|
2018-07-25 15:34:00 +02:00
|
|
|
if (ws) {
|
2022-11-16 23:50:34 +01:00
|
|
|
view_assign_ctx(view, NULL);
|
2018-07-25 15:34:00 +02:00
|
|
|
return ws;
|
|
|
|
}
|
2018-06-27 02:32:09 +02:00
|
|
|
|
2018-07-25 15:34:00 +02:00
|
|
|
// Use the focused workspace
|
2018-10-13 11:15:04 +02:00
|
|
|
struct sway_node *node = seat_get_focus_inactive(seat, &root->node);
|
|
|
|
if (node && node->type == N_WORKSPACE) {
|
|
|
|
return node->sway_workspace;
|
|
|
|
} else if (node && node->type == N_CONTAINER) {
|
2021-02-12 23:22:51 +01:00
|
|
|
return node->sway_container->pending.workspace;
|
2018-10-13 11:15:04 +02:00
|
|
|
}
|
|
|
|
|
2019-01-17 11:16:23 +01:00
|
|
|
// When there's no outputs connected, the above should match a workspace on
|
|
|
|
// the noop output.
|
|
|
|
sway_assert(false, "Expected to find a workspace");
|
|
|
|
return NULL;
|
2018-07-25 15:34:00 +02:00
|
|
|
}
|
|
|
|
|
2024-02-11 12:20:15 +01:00
|
|
|
static void update_ext_foreign_toplevel(struct sway_view *view) {
|
|
|
|
struct wlr_ext_foreign_toplevel_handle_v1_state toplevel_state = {
|
|
|
|
.app_id = view_get_app_id(view),
|
|
|
|
.title = view_get_title(view),
|
|
|
|
};
|
|
|
|
wlr_ext_foreign_toplevel_handle_v1_update_state(view->ext_foreign_toplevel, &toplevel_state);
|
|
|
|
}
|
|
|
|
|
2018-07-25 15:34:00 +02:00
|
|
|
static bool should_focus(struct sway_view *view) {
|
2018-10-18 13:20:00 +02:00
|
|
|
struct sway_seat *seat = input_manager_current_seat();
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
struct sway_container *prev_con = seat_get_focused_container(seat);
|
|
|
|
struct sway_workspace *prev_ws = seat_get_focused_workspace(seat);
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_workspace *map_ws = view->container->pending.workspace;
|
2018-05-13 00:16:36 +02:00
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
if (view->container->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
|
2019-04-01 05:27:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-24 19:06:40 +02:00
|
|
|
// View opened "under" fullscreen view should not be given focus.
|
view: handle case where map_ws is NULL
When a criteria places the view into the scratchpad, map_ws is NULL and
trying to access map_ws->fullscreen will result in SIGSEGFAULT with:
#0 0x0000000000455327 in should_focus (view=0x15a6a70) at ../sway/tree/view.c:604
prev_con = 0x0
len = <optimized out>
seat = 0x12233c0
prev_ws = 0x1264c80
map_ws = 0x0
criterias = <optimized out>
seat = <optimized out>
prev_con = <optimized out>
prev_ws = <optimized out>
map_ws = <optimized out>
criterias = <optimized out>
len = <optimized out>
num_children = <optimized out>
#1 view_map (view=view@entry=0x15a6a70, wlr_surface=0x15a5cb0, fullscreen=<optimized out>, fullscreen_output=<optimized out>, decoration=<optimized out>) at ../sway/tree/view.c:809
__PRETTY_FUNCTION__ = "view_map"
ws = <optimized out>
seat = <optimized out>
node = <optimized out>
target_sibling = <optimized out>
container = 0x1625400
set_focus = <optimized out>
app_id = <optimized out>
class = <optimized out>
#2 0x0000000000423a7e in handle_map (listener=0x15a6c78, data=<optimized out>) at ../sway/desktop/xdg_shell.c:454
xdg_shell_view = 0x15a6a70
view = 0x15a6a70
xdg_surface = 0x15a6620
csd = <optimized out>
#3 0x00007f508bd3674c in wlr_signal_emit_safe (signal=signal@entry=0x15a6718, data=data@entry=0x15a6620) at ../subprojects/wlroots/util/signal.c:29
pos = 0x15a6c78
l = 0x15a6c78
cursor = {link = {prev = 0x15a6c78, next = 0x7fff53d58190}, notify = 0x7f508bd366c0 <handle_noop>}
end = {link = {prev = 0x7fff53d58170, next = 0x15a6718}, notify = 0x7f508bd366c0 <handle_noop>}
#4 0x00007f508bd15b29 in handle_xdg_surface_commit (wlr_surface=<optimized out>) at ../subprojects/wlroots/types/xdg_shell/wlr_xdg_surface.c:384
surface = 0x15a6620
#5 0x00007f508bd2e981 in surface_commit_state (surface=surface@entry=0x15a5cb0, next=next@entry=0x15a5e18) at ../subprojects/wlroots/types/wlr_surface.c:455
__PRETTY_FUNCTION__ = "surface_commit_state"
invalid_buffer = <optimized out>
subsurface = 0x15a6038
#6 0x00007f508bd2f53b in surface_commit_pending (surface=0x15a5cb0) at ../subprojects/wlroots/types/wlr_surface.c:474
next_seq = 3
next_seq = <optimized out>
#7 surface_commit (client=<optimized out>, resource=<optimized out>) at ../subprojects/wlroots/types/wlr_surface.c:542
surface = 0x15a5cb0
subsurface = <optimized out>
If map_ws is NULL we assume the view is places into the scratchpad and
return false as well.
2021-04-29 08:49:04 +02:00
|
|
|
if (root->fullscreen_global || !map_ws || map_ws->fullscreen) {
|
2021-04-24 19:06:40 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-25 15:34:00 +02:00
|
|
|
// Views can only take focus if they are mapped into the active workspace
|
|
|
|
if (prev_ws != map_ws) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the view is the only one in the focused workspace, it'll get focus
|
|
|
|
// regardless of any no_focus criteria.
|
2021-02-12 23:22:51 +01:00
|
|
|
if (!view->container->pending.parent && !prev_con) {
|
|
|
|
size_t num_children = view->container->pending.workspace->tiling->length +
|
|
|
|
view->container->pending.workspace->floating->length;
|
2018-07-25 15:34:00 +02:00
|
|
|
if (num_children == 1) {
|
|
|
|
return true;
|
2018-05-13 00:16:36 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-25 15:34:00 +02:00
|
|
|
|
|
|
|
// Check no_focus criteria
|
|
|
|
list_t *criterias = criteria_for_view(view, CT_NO_FOCUS);
|
|
|
|
size_t len = criterias->length;
|
2018-06-27 02:32:09 +02:00
|
|
|
list_free(criterias);
|
2018-07-25 15:34:00 +02:00
|
|
|
return len == 0;
|
|
|
|
}
|
2018-06-27 02:32:09 +02:00
|
|
|
|
2019-08-20 11:30:09 +02:00
|
|
|
static void handle_foreign_activate_request(
|
|
|
|
struct wl_listener *listener, void *data) {
|
|
|
|
struct sway_view *view = wl_container_of(
|
|
|
|
listener, view, foreign_activate_request);
|
|
|
|
struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
|
|
|
|
struct sway_seat *seat;
|
|
|
|
wl_list_for_each(seat, &server.input->seats, link) {
|
|
|
|
if (seat->wlr_seat == event->seat) {
|
2020-07-24 19:33:01 +02:00
|
|
|
if (container_is_scratchpad_hidden_or_child(view->container)) {
|
|
|
|
root_scratchpad_show(view->container);
|
|
|
|
}
|
2019-08-20 11:30:09 +02:00
|
|
|
seat_set_focus_container(seat, view->container);
|
2020-07-24 19:33:01 +02:00
|
|
|
seat_consider_warp_to_focus(seat);
|
|
|
|
container_raise_floating(view->container);
|
2019-08-20 11:30:09 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-05-12 23:38:59 +02:00
|
|
|
transaction_commit_dirty();
|
2019-08-20 11:30:09 +02:00
|
|
|
}
|
|
|
|
|
2020-07-31 01:31:52 +02:00
|
|
|
static void handle_foreign_fullscreen_request(
|
|
|
|
struct wl_listener *listener, void *data) {
|
|
|
|
struct sway_view *view = wl_container_of(
|
|
|
|
listener, view, foreign_fullscreen_request);
|
|
|
|
struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
|
|
|
|
|
|
|
|
// Match fullscreen command behavior for scratchpad hidden views
|
|
|
|
struct sway_container *container = view->container;
|
2021-02-12 23:22:51 +01:00
|
|
|
if (!container->pending.workspace) {
|
|
|
|
while (container->pending.parent) {
|
|
|
|
container = container->pending.parent;
|
2020-07-31 01:31:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-20 22:15:23 +01:00
|
|
|
if (event->fullscreen && event->output && event->output->data) {
|
|
|
|
struct sway_output *output = event->output->data;
|
|
|
|
struct sway_workspace *ws = output_get_active_workspace(output);
|
|
|
|
if (ws && !container_is_scratchpad_hidden(view->container)) {
|
|
|
|
if (container_is_floating(view->container)) {
|
|
|
|
workspace_add_floating(ws, view->container);
|
|
|
|
} else {
|
|
|
|
workspace_add_tiling(ws, view->container);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-31 01:31:52 +02:00
|
|
|
container_set_fullscreen(container,
|
|
|
|
event->fullscreen ? FULLSCREEN_WORKSPACE : FULLSCREEN_NONE);
|
|
|
|
if (event->fullscreen) {
|
|
|
|
arrange_root();
|
|
|
|
} else {
|
2021-02-12 23:22:51 +01:00
|
|
|
if (container->pending.parent) {
|
|
|
|
arrange_container(container->pending.parent);
|
|
|
|
} else if (container->pending.workspace) {
|
|
|
|
arrange_workspace(container->pending.workspace);
|
2020-07-31 01:31:52 +02:00
|
|
|
}
|
|
|
|
}
|
2021-05-12 23:38:59 +02:00
|
|
|
transaction_commit_dirty();
|
2020-07-31 01:31:52 +02:00
|
|
|
}
|
|
|
|
|
2019-08-20 11:30:09 +02:00
|
|
|
static void handle_foreign_close_request(
|
|
|
|
struct wl_listener *listener, void *data) {
|
|
|
|
struct sway_view *view = wl_container_of(
|
|
|
|
listener, view, foreign_close_request);
|
|
|
|
view_close(view);
|
|
|
|
}
|
|
|
|
|
2020-08-03 21:22:03 +02:00
|
|
|
static void handle_foreign_destroy(
|
|
|
|
struct wl_listener *listener, void *data) {
|
|
|
|
struct sway_view *view = wl_container_of(
|
|
|
|
listener, view, foreign_destroy);
|
|
|
|
|
|
|
|
wl_list_remove(&view->foreign_activate_request.link);
|
|
|
|
wl_list_remove(&view->foreign_fullscreen_request.link);
|
|
|
|
wl_list_remove(&view->foreign_close_request.link);
|
|
|
|
wl_list_remove(&view->foreign_destroy.link);
|
|
|
|
}
|
|
|
|
|
2018-10-13 21:01:02 +02:00
|
|
|
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
2019-03-25 04:24:02 +01:00
|
|
|
bool fullscreen, struct wlr_output *fullscreen_output,
|
|
|
|
bool decoration) {
|
2018-07-25 15:34:00 +02:00
|
|
|
if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
|
|
|
|
return;
|
2018-06-27 02:32:09 +02:00
|
|
|
}
|
2018-07-25 15:34:00 +02:00
|
|
|
view->surface = wlr_surface;
|
2019-09-20 17:58:19 +02:00
|
|
|
view_populate_pid(view);
|
2019-09-22 19:28:12 +02:00
|
|
|
view->container = container_create(view);
|
2018-07-25 15:34:00 +02:00
|
|
|
|
2022-11-16 23:50:34 +01:00
|
|
|
if (view->ctx == NULL) {
|
|
|
|
struct launcher_ctx *ctx = launcher_ctx_find_pid(view->pid);
|
|
|
|
if (ctx != NULL) {
|
|
|
|
view_assign_ctx(view, ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-25 04:24:02 +01:00
|
|
|
// If there is a request to be opened fullscreen on a specific output, try
|
|
|
|
// to honor that request. Otherwise, fallback to assigns, pid mappings,
|
|
|
|
// focused workspace, etc
|
|
|
|
struct sway_workspace *ws = NULL;
|
|
|
|
if (fullscreen_output && fullscreen_output->data) {
|
|
|
|
struct sway_output *output = fullscreen_output->data;
|
|
|
|
ws = output_get_active_workspace(output);
|
|
|
|
}
|
|
|
|
if (!ws) {
|
|
|
|
ws = select_workspace(view);
|
|
|
|
}
|
|
|
|
|
2018-10-18 13:20:00 +02:00
|
|
|
struct sway_seat *seat = input_manager_current_seat();
|
2021-10-10 16:27:43 +02:00
|
|
|
struct sway_node *node =
|
|
|
|
seat_get_focus_inactive(seat, ws ? &ws->node : &root->node);
|
|
|
|
struct sway_container *target_sibling = NULL;
|
|
|
|
if (node && node->type == N_CONTAINER) {
|
|
|
|
if (container_is_floating(node->sway_container)) {
|
|
|
|
// If we're about to launch the view into the floating container, then
|
|
|
|
// launch it as a tiled view instead.
|
|
|
|
if (ws) {
|
|
|
|
target_sibling = seat_get_focus_inactive_tiling(seat, ws);
|
|
|
|
if (target_sibling) {
|
|
|
|
struct sway_container *con =
|
|
|
|
seat_get_focus_inactive_view(seat, &target_sibling->node);
|
|
|
|
if (con) {
|
|
|
|
target_sibling = con;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ws = seat_get_last_known_workspace(seat);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
target_sibling = node->sway_container;
|
|
|
|
}
|
|
|
|
}
|
2018-07-25 15:34:00 +02:00
|
|
|
|
2024-02-11 12:20:15 +01:00
|
|
|
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
|
|
|
|
.app_id = view_get_app_id(view),
|
|
|
|
.title = view_get_title(view),
|
|
|
|
};
|
|
|
|
view->ext_foreign_toplevel =
|
|
|
|
wlr_ext_foreign_toplevel_handle_v1_create(server.foreign_toplevel_list, &foreign_toplevel_state);
|
|
|
|
|
2019-08-20 11:30:09 +02:00
|
|
|
view->foreign_toplevel =
|
|
|
|
wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager);
|
|
|
|
view->foreign_activate_request.notify = handle_foreign_activate_request;
|
|
|
|
wl_signal_add(&view->foreign_toplevel->events.request_activate,
|
|
|
|
&view->foreign_activate_request);
|
2020-07-31 01:31:52 +02:00
|
|
|
view->foreign_fullscreen_request.notify = handle_foreign_fullscreen_request;
|
|
|
|
wl_signal_add(&view->foreign_toplevel->events.request_fullscreen,
|
|
|
|
&view->foreign_fullscreen_request);
|
2019-08-20 11:30:09 +02:00
|
|
|
view->foreign_close_request.notify = handle_foreign_close_request;
|
|
|
|
wl_signal_add(&view->foreign_toplevel->events.request_close,
|
|
|
|
&view->foreign_close_request);
|
2020-08-03 21:22:03 +02:00
|
|
|
view->foreign_destroy.notify = handle_foreign_destroy;
|
|
|
|
wl_signal_add(&view->foreign_toplevel->events.destroy,
|
|
|
|
&view->foreign_destroy);
|
2019-08-20 11:30:09 +02:00
|
|
|
|
2020-10-25 22:20:11 +01:00
|
|
|
struct sway_container *container = view->container;
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (target_sibling) {
|
2020-10-25 22:20:11 +01:00
|
|
|
container_add_sibling(target_sibling, container, 1);
|
2019-04-01 05:27:18 +02:00
|
|
|
} else if (ws) {
|
2020-10-25 22:20:11 +01:00
|
|
|
container = workspace_add_tiling(ws, container);
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
}
|
|
|
|
ipc_event_window(view->container, "new");
|
2018-03-31 23:49:40 +02:00
|
|
|
|
2019-06-27 09:57:58 +02:00
|
|
|
if (decoration) {
|
|
|
|
view_update_csd_from_client(view, decoration);
|
|
|
|
}
|
|
|
|
|
2018-05-24 14:30:44 +02:00
|
|
|
if (view->impl->wants_floating && view->impl->wants_floating(view)) {
|
2021-02-12 23:22:51 +01:00
|
|
|
view->container->pending.border = config->floating_border;
|
|
|
|
view->container->pending.border_thickness = config->floating_border_thickness;
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
container_set_floating(view->container, true);
|
2018-07-05 01:04:15 +02:00
|
|
|
} else {
|
2021-02-12 23:22:51 +01:00
|
|
|
view->container->pending.border = config->border;
|
|
|
|
view->container->pending.border_thickness = config->border_thickness;
|
2018-07-05 01:04:15 +02:00
|
|
|
view_set_tiled(view, true);
|
2018-05-24 14:30:44 +02:00
|
|
|
}
|
|
|
|
|
2018-10-08 15:50:43 +02:00
|
|
|
if (config->popup_during_fullscreen == POPUP_LEAVE &&
|
2021-02-12 23:22:51 +01:00
|
|
|
container->pending.workspace &&
|
|
|
|
container->pending.workspace->fullscreen &&
|
|
|
|
container->pending.workspace->fullscreen->view) {
|
|
|
|
struct sway_container *fs = container->pending.workspace->fullscreen;
|
2018-10-08 15:50:43 +02:00
|
|
|
if (view_is_transient_for(view, fs->view)) {
|
|
|
|
container_set_fullscreen(fs, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-13 00:16:36 +02:00
|
|
|
view_update_title(view, false);
|
2020-10-25 22:20:11 +01:00
|
|
|
container_update_representation(container);
|
2018-10-13 21:01:02 +02:00
|
|
|
|
|
|
|
if (fullscreen) {
|
|
|
|
container_set_fullscreen(view->container, true);
|
2021-02-12 23:22:51 +01:00
|
|
|
arrange_workspace(view->container->pending.workspace);
|
2018-10-13 21:01:02 +02:00
|
|
|
} else {
|
2021-02-12 23:22:51 +01:00
|
|
|
if (container->pending.parent) {
|
|
|
|
arrange_container(container->pending.parent);
|
|
|
|
} else if (container->pending.workspace) {
|
|
|
|
arrange_workspace(container->pending.workspace);
|
2018-10-13 21:01:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-12 11:54:09 +01:00
|
|
|
view_execute_criteria(view);
|
|
|
|
|
2021-01-12 14:56:33 +01:00
|
|
|
bool set_focus = should_focus(view);
|
|
|
|
|
|
|
|
#if HAVE_XWAYLAND
|
2023-02-01 19:45:21 +01:00
|
|
|
struct wlr_xwayland_surface *xsurface;
|
|
|
|
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) {
|
2021-04-24 19:06:40 +02:00
|
|
|
set_focus &= wlr_xwayland_icccm_input_model(xsurface) !=
|
|
|
|
WLR_ICCCM_INPUT_MODEL_NONE;
|
2021-01-12 14:56:33 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (set_focus) {
|
2018-10-18 13:20:00 +02:00
|
|
|
input_manager_set_focus(&view->container->node);
|
2018-10-13 21:01:02 +02:00
|
|
|
}
|
2019-08-20 11:30:09 +02:00
|
|
|
|
2024-02-11 12:20:15 +01:00
|
|
|
if (view->ext_foreign_toplevel) {
|
|
|
|
update_ext_foreign_toplevel(view);
|
|
|
|
}
|
|
|
|
|
2020-06-24 07:55:42 +02:00
|
|
|
const char *app_id;
|
|
|
|
const char *class;
|
|
|
|
if ((app_id = view_get_app_id(view)) != NULL) {
|
2021-04-24 19:06:40 +02:00
|
|
|
wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id);
|
2020-06-24 07:55:42 +02:00
|
|
|
} else if ((class = view_get_class(view)) != NULL) {
|
2021-04-24 19:06:40 +02:00
|
|
|
wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, class);
|
2019-08-20 11:30:09 +02:00
|
|
|
}
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
|
|
|
|
2018-06-26 05:15:45 +02:00
|
|
|
void view_unmap(struct sway_view *view) {
|
2022-11-10 14:35:14 +01:00
|
|
|
wl_signal_emit_mutable(&view->events.unmap, view);
|
2018-04-05 20:46:02 +02:00
|
|
|
|
2023-10-20 19:29:06 +02:00
|
|
|
view->executed_criteria->length = 0;
|
|
|
|
|
2018-07-15 14:43:33 +02:00
|
|
|
if (view->urgent_timer) {
|
|
|
|
wl_event_source_remove(view->urgent_timer);
|
|
|
|
view->urgent_timer = NULL;
|
|
|
|
}
|
|
|
|
|
2024-02-11 12:20:15 +01:00
|
|
|
if (view->ext_foreign_toplevel) {
|
|
|
|
wlr_ext_foreign_toplevel_handle_v1_destroy(view->ext_foreign_toplevel);
|
|
|
|
view->ext_foreign_toplevel = NULL;
|
|
|
|
}
|
|
|
|
|
2019-08-20 11:30:09 +02:00
|
|
|
if (view->foreign_toplevel) {
|
|
|
|
wlr_foreign_toplevel_handle_v1_destroy(view->foreign_toplevel);
|
|
|
|
view->foreign_toplevel = NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_container *parent = view->container->pending.parent;
|
|
|
|
struct sway_workspace *ws = view->container->pending.workspace;
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
container_begin_destroy(view->container);
|
|
|
|
if (parent) {
|
|
|
|
container_reap_empty(parent);
|
2018-09-02 07:37:56 +02:00
|
|
|
} else if (ws) {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
workspace_consider_destroy(ws);
|
|
|
|
}
|
2018-08-03 09:55:58 +02:00
|
|
|
|
2019-01-24 23:29:21 +01:00
|
|
|
if (root->fullscreen_global) {
|
|
|
|
// Container may have been a child of the root fullscreen container
|
|
|
|
arrange_root();
|
|
|
|
} else if (ws && !ws->node.destroying) {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
arrange_workspace(ws);
|
2018-07-16 05:15:35 +02:00
|
|
|
workspace_detect_urgent(ws);
|
2018-06-26 05:15:45 +02:00
|
|
|
}
|
2018-08-03 09:55:58 +02:00
|
|
|
|
2018-09-11 19:34:58 +02:00
|
|
|
struct sway_seat *seat;
|
2018-10-18 13:20:00 +02:00
|
|
|
wl_list_for_each(seat, &server.input->seats, link) {
|
2019-01-07 13:23:28 +01:00
|
|
|
seat->cursor->image_surface = NULL;
|
2019-02-10 21:23:50 +01:00
|
|
|
if (seat->cursor->active_constraint) {
|
|
|
|
struct wlr_surface *constrain_surface =
|
|
|
|
seat->cursor->active_constraint->surface;
|
|
|
|
if (view_from_wlr_surface(constrain_surface) == view) {
|
|
|
|
sway_cursor_constrain(seat->cursor, NULL);
|
|
|
|
}
|
|
|
|
}
|
2019-01-07 13:21:02 +01:00
|
|
|
seat_consider_warp_to_focus(seat);
|
2018-09-11 19:34:58 +02:00
|
|
|
}
|
2018-09-11 02:52:42 +02:00
|
|
|
|
2018-07-14 15:14:55 +02:00
|
|
|
transaction_commit_dirty();
|
2018-06-27 09:54:57 +02:00
|
|
|
view->surface = NULL;
|
2018-03-31 23:49:40 +02:00
|
|
|
}
|
|
|
|
|
2021-02-08 01:45:50 +01:00
|
|
|
void view_update_size(struct sway_view *view) {
|
2019-01-28 07:00:34 +01:00
|
|
|
struct sway_container *con = view->container;
|
2021-02-12 23:22:51 +01:00
|
|
|
con->pending.content_width = view->geometry.width;
|
|
|
|
con->pending.content_height = view->geometry.height;
|
2021-02-08 01:05:51 +01:00
|
|
|
container_set_geometry_from_content(con);
|
2018-03-30 19:18:50 +02:00
|
|
|
}
|
2018-04-05 20:46:02 +02:00
|
|
|
|
2023-11-22 21:11:12 +01:00
|
|
|
void view_center_and_clip_surface(struct sway_view *view) {
|
2021-02-08 01:03:44 +01:00
|
|
|
struct sway_container *con = view->container;
|
2023-04-27 10:25:40 +02:00
|
|
|
|
2023-11-22 21:11:12 +01:00
|
|
|
if (container_is_floating(con)) {
|
|
|
|
// We always center the current coordinates rather than the next, as the
|
|
|
|
// geometry immediately affects the currently active rendering.
|
|
|
|
int x = (int) fmax(0, (con->current.content_width - view->geometry.width) / 2);
|
|
|
|
int y = (int) fmax(0, (con->current.content_height - view->geometry.height) / 2);
|
|
|
|
|
|
|
|
wlr_scene_node_set_position(&view->content_tree->node, x, y);
|
|
|
|
} else {
|
|
|
|
wlr_scene_node_set_position(&view->content_tree->node, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// only make sure to clip the content if there is content to clip
|
|
|
|
if (!wl_list_empty(&con->view->content_tree->children)) {
|
|
|
|
wlr_scene_subsurface_tree_set_clip(&con->view->content_tree->node, &(struct wlr_box){
|
|
|
|
.x = con->view->geometry.x,
|
|
|
|
.y = con->view->geometry.y,
|
|
|
|
.width = con->current.content_width,
|
|
|
|
.height = con->current.content_height,
|
|
|
|
});
|
|
|
|
}
|
2021-02-08 01:03:44 +01:00
|
|
|
}
|
|
|
|
|
2018-06-30 07:00:24 +02:00
|
|
|
struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
|
2023-02-01 20:24:40 +01:00
|
|
|
struct wlr_xdg_surface *xdg_surface;
|
|
|
|
if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) {
|
2018-06-30 07:00:24 +02:00
|
|
|
return view_from_wlr_xdg_surface(xdg_surface);
|
|
|
|
}
|
2018-11-18 00:33:06 +01:00
|
|
|
#if HAVE_XWAYLAND
|
2023-02-01 19:45:21 +01:00
|
|
|
struct wlr_xwayland_surface *xsurface;
|
|
|
|
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) {
|
2018-06-30 07:00:24 +02:00
|
|
|
return view_from_wlr_xwayland_surface(xsurface);
|
|
|
|
}
|
2018-07-24 23:37:41 +02:00
|
|
|
#endif
|
2023-02-01 20:24:40 +01:00
|
|
|
struct wlr_subsurface *subsurface;
|
|
|
|
if ((subsurface = wlr_subsurface_try_from_wlr_surface(wlr_surface))) {
|
2018-06-30 07:00:24 +02:00
|
|
|
return view_from_wlr_surface(subsurface->parent);
|
|
|
|
}
|
2023-02-01 20:24:40 +01:00
|
|
|
if (wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
2018-06-30 07:00:24 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-07-09 23:59:57 +02:00
|
|
|
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
2019-01-20 19:51:12 +01:00
|
|
|
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
2018-07-09 23:59:57 +02:00
|
|
|
role, wlr_surface);
|
2018-06-30 07:00:24 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-11-24 02:42:18 +01:00
|
|
|
static char *escape_pango_markup(const char *buffer) {
|
|
|
|
size_t length = escape_markup_text(buffer, NULL);
|
|
|
|
char *escaped_title = calloc(length + 1, sizeof(char));
|
|
|
|
escape_markup_text(buffer, escaped_title);
|
|
|
|
return escaped_title;
|
|
|
|
}
|
|
|
|
|
2018-05-28 04:03:43 +02:00
|
|
|
static size_t append_prop(char *buffer, const char *value) {
|
|
|
|
if (!value) {
|
|
|
|
return 0;
|
|
|
|
}
|
2018-11-25 09:09:32 +01:00
|
|
|
// If using pango_markup in font, we need to escape all markup chars
|
|
|
|
// from values to make sure tags are not inserted by clients
|
|
|
|
if (config->pango_markup) {
|
2018-11-24 02:42:18 +01:00
|
|
|
char *escaped_value = escape_pango_markup(value);
|
|
|
|
lenient_strcat(buffer, escaped_value);
|
|
|
|
size_t len = strlen(escaped_value);
|
|
|
|
free(escaped_value);
|
|
|
|
return len;
|
|
|
|
} else {
|
|
|
|
lenient_strcat(buffer, value);
|
|
|
|
return strlen(value);
|
|
|
|
}
|
2018-05-28 04:03:43 +02:00
|
|
|
}
|
|
|
|
|
2018-05-05 10:18:54 +02:00
|
|
|
/**
|
|
|
|
* Calculate and return the length of the formatted title.
|
|
|
|
* If buffer is not NULL, also populate the buffer with the formatted title.
|
|
|
|
*/
|
|
|
|
static size_t parse_title_format(struct sway_view *view, char *buffer) {
|
2018-05-05 04:36:50 +02:00
|
|
|
if (!view->title_format || strcmp(view->title_format, "%title") == 0) {
|
2018-11-25 09:09:32 +01:00
|
|
|
return append_prop(buffer, view_get_title(view));
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t len = 0;
|
|
|
|
char *format = view->title_format;
|
|
|
|
char *next = strchr(format, '%');
|
|
|
|
while (next) {
|
2018-05-25 13:07:59 +02:00
|
|
|
// Copy everything up to the %
|
|
|
|
lenient_strncat(buffer, format, next - format);
|
2018-05-05 10:18:54 +02:00
|
|
|
len += next - format;
|
2018-05-05 04:36:50 +02:00
|
|
|
format = next;
|
|
|
|
|
|
|
|
if (strncmp(next, "%title", 6) == 0) {
|
2018-05-28 04:03:43 +02:00
|
|
|
len += append_prop(buffer, view_get_title(view));
|
2018-05-05 04:36:50 +02:00
|
|
|
format += 6;
|
2018-05-27 01:50:38 +02:00
|
|
|
} else if (strncmp(next, "%app_id", 7) == 0) {
|
2018-05-28 04:03:43 +02:00
|
|
|
len += append_prop(buffer, view_get_app_id(view));
|
2018-05-27 01:50:38 +02:00
|
|
|
format += 7;
|
2018-05-05 04:36:50 +02:00
|
|
|
} else if (strncmp(next, "%class", 6) == 0) {
|
2018-05-28 04:03:43 +02:00
|
|
|
len += append_prop(buffer, view_get_class(view));
|
2018-05-05 04:36:50 +02:00
|
|
|
format += 6;
|
|
|
|
} else if (strncmp(next, "%instance", 9) == 0) {
|
2018-05-28 04:03:43 +02:00
|
|
|
len += append_prop(buffer, view_get_instance(view));
|
2018-05-05 04:36:50 +02:00
|
|
|
format += 9;
|
|
|
|
} else if (strncmp(next, "%shell", 6) == 0) {
|
2018-05-28 04:03:43 +02:00
|
|
|
len += append_prop(buffer, view_get_shell(view));
|
2018-05-05 04:36:50 +02:00
|
|
|
format += 6;
|
|
|
|
} else {
|
2018-05-25 13:07:59 +02:00
|
|
|
lenient_strcat(buffer, "%");
|
2018-05-05 04:36:50 +02:00
|
|
|
++format;
|
2018-05-05 10:18:54 +02:00
|
|
|
++len;
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
|
|
|
next = strchr(format, '%');
|
|
|
|
}
|
2018-05-25 13:07:59 +02:00
|
|
|
lenient_strcat(buffer, format);
|
2018-05-05 10:18:54 +02:00
|
|
|
len += strlen(format);
|
2018-05-05 04:36:50 +02:00
|
|
|
|
2018-05-05 10:18:54 +02:00
|
|
|
return len;
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
|
|
|
|
2024-02-11 12:20:15 +01:00
|
|
|
void view_update_app_id(struct sway_view *view) {
|
|
|
|
const char *app_id = view_get_app_id(view);
|
|
|
|
|
|
|
|
if (view->foreign_toplevel && app_id) {
|
|
|
|
wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (view->ext_foreign_toplevel) {
|
|
|
|
update_ext_foreign_toplevel(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-05 04:36:50 +02:00
|
|
|
void view_update_title(struct sway_view *view, bool force) {
|
|
|
|
const char *title = view_get_title(view);
|
|
|
|
|
|
|
|
if (!force) {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (title && view->container->title &&
|
|
|
|
strcmp(title, view->container->title) == 0) {
|
2018-05-05 04:36:50 +02:00
|
|
|
return;
|
|
|
|
}
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (!title && !view->container->title) {
|
2018-05-05 04:36:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
free(view->container->title);
|
|
|
|
free(view->container->formatted_title);
|
2022-08-07 12:12:05 +02:00
|
|
|
|
|
|
|
size_t len = parse_title_format(view, NULL);
|
|
|
|
|
|
|
|
if (len) {
|
2018-05-07 18:30:45 +02:00
|
|
|
char *buffer = calloc(len + 1, sizeof(char));
|
2018-05-05 10:18:54 +02:00
|
|
|
if (!sway_assert(buffer, "Unable to allocate title string")) {
|
|
|
|
return;
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
2018-05-05 10:18:54 +02:00
|
|
|
|
2022-08-07 12:12:05 +02:00
|
|
|
parse_title_format(view, buffer);
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
view->container->formatted_title = buffer;
|
2018-05-05 04:36:50 +02:00
|
|
|
} else {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
view->container->formatted_title = NULL;
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
2018-06-02 23:32:18 +02:00
|
|
|
|
2022-08-07 12:12:05 +02:00
|
|
|
view->container->title = title ? strdup(title) : NULL;
|
|
|
|
|
2018-06-02 23:32:18 +02:00
|
|
|
// Update title after the global font height is updated
|
2023-11-22 01:51:57 +01:00
|
|
|
if (view->container->title_bar.title_text && len) {
|
|
|
|
sway_text_node_set_text(view->container->title_bar.title_text,
|
|
|
|
view->container->formatted_title);
|
|
|
|
container_arrange_title_bar(view->container);
|
|
|
|
} else {
|
|
|
|
container_update_title_bar(view->container);
|
|
|
|
}
|
2018-07-13 18:19:16 +02:00
|
|
|
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
ipc_event_window(view->container, "title");
|
2019-08-20 11:30:09 +02:00
|
|
|
|
2020-07-02 12:14:52 +02:00
|
|
|
if (view->foreign_toplevel && title) {
|
2019-08-20 11:30:09 +02:00
|
|
|
wlr_foreign_toplevel_handle_v1_set_title(view->foreign_toplevel, title);
|
|
|
|
}
|
2024-02-11 12:20:15 +01:00
|
|
|
|
|
|
|
if (view->ext_foreign_toplevel) {
|
|
|
|
update_ext_foreign_toplevel(view);
|
|
|
|
}
|
2018-05-05 04:36:50 +02:00
|
|
|
}
|
2018-05-14 14:47:10 +02:00
|
|
|
|
2018-05-20 01:11:55 +02:00
|
|
|
bool view_is_visible(struct sway_view *view) {
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (view->container->node.destroying) {
|
2018-05-20 01:11:55 +02:00
|
|
|
return false;
|
|
|
|
}
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_workspace *workspace = view->container->pending.workspace;
|
|
|
|
if (!workspace && view->container->pending.fullscreen_mode != FULLSCREEN_GLOBAL) {
|
2019-04-01 05:27:18 +02:00
|
|
|
bool fs_global_descendant = false;
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_container *parent = view->container->pending.parent;
|
2019-04-01 05:27:18 +02:00
|
|
|
while (parent) {
|
2021-02-12 23:22:51 +01:00
|
|
|
if (parent->pending.fullscreen_mode == FULLSCREEN_GLOBAL) {
|
2019-04-01 05:27:18 +02:00
|
|
|
fs_global_descendant = true;
|
|
|
|
}
|
2021-02-12 23:22:51 +01:00
|
|
|
parent = parent->pending.parent;
|
2019-04-01 05:27:18 +02:00
|
|
|
}
|
|
|
|
if (!fs_global_descendant) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-26 14:27:42 +02:00
|
|
|
}
|
2020-11-03 06:16:15 +01:00
|
|
|
|
|
|
|
if (!container_is_sticky_or_child(view->container) && workspace &&
|
|
|
|
!workspace_is_visible(workspace)) {
|
2018-09-28 09:02:35 +02:00
|
|
|
return false;
|
|
|
|
}
|
2018-05-20 01:11:55 +02:00
|
|
|
// Check view isn't in a tabbed or stacked container on an inactive tab
|
2018-10-18 13:20:00 +02:00
|
|
|
struct sway_seat *seat = input_manager_current_seat();
|
2018-09-16 14:01:54 +02:00
|
|
|
struct sway_container *con = view->container;
|
|
|
|
while (con) {
|
|
|
|
enum sway_container_layout layout = container_parent_layout(con);
|
2018-09-28 09:02:35 +02:00
|
|
|
if ((layout == L_TABBED || layout == L_STACKED)
|
|
|
|
&& !container_is_floating(con)) {
|
2021-02-12 23:22:51 +01:00
|
|
|
struct sway_node *parent = con->pending.parent ?
|
|
|
|
&con->pending.parent->node : &con->pending.workspace->node;
|
2018-09-16 14:01:54 +02:00
|
|
|
if (seat_get_active_tiling_child(seat, parent) != &con->node) {
|
2018-05-20 01:11:55 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-02-12 23:22:51 +01:00
|
|
|
con = con->pending.parent;
|
2018-05-20 01:11:55 +02:00
|
|
|
}
|
|
|
|
// Check view isn't hidden by another fullscreen view
|
2019-01-24 23:29:21 +01:00
|
|
|
struct sway_container *fs = root->fullscreen_global ?
|
|
|
|
root->fullscreen_global : workspace->fullscreen;
|
|
|
|
if (fs && !container_is_fullscreen_or_child(view->container) &&
|
|
|
|
!container_is_transient_for(view->container, fs)) {
|
|
|
|
return false;
|
2018-05-20 01:11:55 +02:00
|
|
|
}
|
2018-05-24 14:30:44 +02:00
|
|
|
return true;
|
2018-05-20 01:11:55 +02:00
|
|
|
}
|
2018-07-15 14:43:33 +02:00
|
|
|
|
|
|
|
void view_set_urgent(struct sway_view *view, bool enable) {
|
2018-07-17 02:27:03 +02:00
|
|
|
if (view_is_urgent(view) == enable) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-15 14:43:33 +02:00
|
|
|
if (enable) {
|
2018-10-18 13:20:00 +02:00
|
|
|
struct sway_seat *seat = input_manager_current_seat();
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
if (seat_get_focused_container(seat) == view->container) {
|
2018-07-15 14:43:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &view->urgent);
|
2023-11-22 01:51:57 +01:00
|
|
|
container_update_itself_and_parents(view->container);
|
2018-07-15 14:43:33 +02:00
|
|
|
} else {
|
|
|
|
view->urgent = (struct timespec){ 0 };
|
|
|
|
if (view->urgent_timer) {
|
|
|
|
wl_event_source_remove(view->urgent_timer);
|
|
|
|
view->urgent_timer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement type safe arguments and demote sway_container
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.
2018-08-30 13:00:10 +02:00
|
|
|
ipc_event_window(view->container, "urgent");
|
2018-07-16 00:13:58 +02:00
|
|
|
|
2019-01-28 10:06:42 +01:00
|
|
|
if (!container_is_scratchpad_hidden(view->container)) {
|
2021-02-12 23:22:51 +01:00
|
|
|
workspace_detect_urgent(view->container->pending.workspace);
|
2018-09-04 14:37:03 +02:00
|
|
|
}
|
2018-07-15 14:43:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool view_is_urgent(struct sway_view *view) {
|
|
|
|
return view->urgent.tv_sec || view->urgent.tv_nsec;
|
|
|
|
}
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
|
|
|
|
void view_remove_saved_buffer(struct sway_view *view) {
|
2023-04-27 10:25:40 +02:00
|
|
|
if (!sway_assert(view->saved_surface_tree, "Expected a saved buffer")) {
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
return;
|
|
|
|
}
|
2023-04-27 10:25:40 +02:00
|
|
|
|
|
|
|
wlr_scene_node_destroy(&view->saved_surface_tree->node);
|
|
|
|
view->saved_surface_tree = NULL;
|
|
|
|
wlr_scene_node_set_enabled(&view->content_tree->node, true);
|
2020-05-31 01:37:43 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 10:25:40 +02:00
|
|
|
static void view_save_buffer_iterator(struct wlr_scene_buffer *buffer,
|
2020-05-31 01:37:43 +02:00
|
|
|
int sx, int sy, void *data) {
|
2023-04-27 10:25:40 +02:00
|
|
|
struct wlr_scene_tree *tree = data;
|
|
|
|
|
|
|
|
struct wlr_scene_buffer *sbuf = wlr_scene_buffer_create(tree, NULL);
|
|
|
|
if (!sbuf) {
|
|
|
|
sway_log(SWAY_ERROR, "Could not allocate a scene buffer when saving a surface");
|
|
|
|
return;
|
2020-05-31 01:37:43 +02:00
|
|
|
}
|
2023-04-27 10:25:40 +02:00
|
|
|
|
|
|
|
wlr_scene_buffer_set_dest_size(sbuf,
|
|
|
|
buffer->dst_width, buffer->dst_height);
|
|
|
|
wlr_scene_buffer_set_opaque_region(sbuf, &buffer->opaque_region);
|
|
|
|
wlr_scene_buffer_set_source_box(sbuf, &buffer->src_box);
|
|
|
|
wlr_scene_node_set_position(&sbuf->node, sx, sy);
|
|
|
|
wlr_scene_buffer_set_transform(sbuf, buffer->transform);
|
|
|
|
wlr_scene_buffer_set_buffer(sbuf, buffer->buffer);
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void view_save_buffer(struct sway_view *view) {
|
2023-04-27 10:25:40 +02:00
|
|
|
if (!sway_assert(!view->saved_surface_tree, "Didn't expect saved buffer")) {
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
view_remove_saved_buffer(view);
|
|
|
|
}
|
2023-04-27 10:25:40 +02:00
|
|
|
|
|
|
|
view->saved_surface_tree = wlr_scene_tree_create(view->scene_tree);
|
|
|
|
if (!view->saved_surface_tree) {
|
|
|
|
sway_log(SWAY_ERROR, "Could not allocate a scene tree node when saving a surface");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable and disable the saved surface tree like so to atomitaclly update
|
|
|
|
// the tree. This will prevent over damaging or other weirdness.
|
|
|
|
wlr_scene_node_set_enabled(&view->saved_surface_tree->node, false);
|
|
|
|
|
|
|
|
wlr_scene_node_for_each_buffer(&view->content_tree->node,
|
|
|
|
view_save_buffer_iterator, view->saved_surface_tree);
|
|
|
|
|
|
|
|
wlr_scene_node_set_enabled(&view->content_tree->node, false);
|
|
|
|
wlr_scene_node_set_enabled(&view->saved_surface_tree->node, true);
|
Correctly track saved surfaces during multiple transactions
Fixes #2364.
Suppose a view is 600px wide, and we tell it to resize to 601px during a
resize operation. We create a transaction, save the 600px buffer and
send the configure. This buffer is saved into the associated
instruction, and is rendered while we wait for the view to commit a
601px buffer.
Before the view commits the 601px buffer, suppose we tell it to resize
to 602px. The new transaction will also save the buffer, but it's still
the 600px buffer because we haven't received a new one yet.
Then suppose the view commits its original 601px buffer. This completes
the first transaction, so we apply the 601px width to the container.
There's still the second (now only) transaction remaining, so we render
the saved buffer from that. But this is still the 600px buffer, and we
believe it's 601px. Whoops.
The problem here is we can't stack buffers like this. So this commit
removes the saved buffer from the instructions, places it in the view
instead, and re-saves the latest buffer every time the view completes a
transaction and still has further pending transactions.
As saved buffers are now specific to views rather than instructions, the
functions for saving and removing the saved buffer have been moved to
view.c.
The calls to save and restore the buffer have been relocated to more
appropriate functions too, favouring transaction_commit and
transaction_apply rather than transaction_add_container and
transaction_destroy.
2018-08-01 08:23:11 +02:00
|
|
|
}
|
2018-10-07 12:40:05 +02:00
|
|
|
|
|
|
|
bool view_is_transient_for(struct sway_view *child,
|
|
|
|
struct sway_view *ancestor) {
|
|
|
|
return child->impl->is_transient_for &&
|
|
|
|
child->impl->is_transient_for(child, ancestor);
|
|
|
|
}
|
2023-04-27 10:25:40 +02:00
|
|
|
|
|
|
|
static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer,
|
|
|
|
int x, int y, void *data) {
|
|
|
|
struct timespec *when = data;
|
|
|
|
wl_signal_emit_mutable(&scene_buffer->events.frame_done, when);
|
|
|
|
}
|
|
|
|
|
|
|
|
void view_send_frame_done(struct sway_view *view) {
|
|
|
|
struct timespec when;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &when);
|
|
|
|
|
|
|
|
struct wlr_scene_node *node;
|
|
|
|
wl_list_for_each(node, &view->content_tree->children, link) {
|
|
|
|
wlr_scene_node_for_each_buffer(node, send_frame_done_iterator, &when);
|
|
|
|
}
|
|
|
|
}
|