This commit is contained in:
Alexander Orzechowski 2024-11-05 02:01:22 -05:00 committed by GitHub
commit 5539422c5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 159 additions and 151 deletions

View File

@ -84,9 +84,16 @@ struct sway_cursor {
struct sway_node;
struct wlr_scene_node *scene_node_at_coords(
double lx, double ly, double *sx, double *sy);
struct wlr_surface *surface_try_from_scene_node(struct wlr_scene_node *node);
struct sway_node *sway_node_try_from_scene_node(struct wlr_scene_node *node,
double lx, double ly);
struct sway_node *node_at_coords(
struct sway_seat *seat, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy);
double lx, double ly, struct wlr_surface **surface, double *sx, double *sy);
void sway_cursor_destroy(struct sway_cursor *cursor);
struct sway_cursor *sway_cursor_create(struct sway_seat *seat);

View File

@ -36,9 +36,6 @@ struct sway_layer_popup {
struct sway_output;
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
struct wlr_surface *surface);
void arrange_layers(struct sway_output *output);
#endif

View File

@ -10,6 +10,14 @@
#define _SWAY_SCENE_DESCRIPTOR_H
#include <wlr/types/wlr_scene.h>
struct sway_view;
// used for SWAY_SCENE_DESC_POPUP
struct sway_popup_desc {
struct wlr_scene_node *relative;
struct sway_view *view;
};
enum sway_scene_descriptor_type {
SWAY_SCENE_DESC_BUFFER_TIMER,
SWAY_SCENE_DESC_NON_INTERACTIVE,
@ -24,10 +32,23 @@ enum sway_scene_descriptor_type {
bool scene_descriptor_assign(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type, void *data);
bool scene_descriptor_reassign(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type, void *data);
void *scene_descriptor_try_get(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type);
void scene_descriptor_destroy(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type);
/*
* Searches the scene node and all its parents for this scene descriptor.
*
* Note that while searching, SWAY_SCENE_DESC_POPUP types will start tracking
* its relative node. With popups, they are part of a seperate layer in the scene
* graph, but that's irrelavent to users of this function.
*/
void *scene_descriptor_find(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type);
#endif

View File

@ -11,6 +11,7 @@
#endif
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/scene_descriptor.h"
struct sway_container;
struct sway_xdg_decoration;
@ -185,11 +186,6 @@ struct sway_xwayland_unmanaged {
};
#endif
struct sway_popup_desc {
struct wlr_scene_node *relative;
struct sway_view *view;
};
struct sway_xdg_popup {
struct sway_view *view;

View File

@ -621,7 +621,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
|| binding->type == BINDING_MOUSECODE) {
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
struct sway_node *node = node_at_coords(
seat->cursor->cursor->x, seat->cursor->cursor->y,
&surface, &sx, &sy);
if (node && node->type == N_CONTAINER) {

View File

@ -20,39 +20,6 @@
#include "sway/tree/arrange.h"
#include "sway/tree/workspace.h"
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
struct wlr_surface *surface) {
struct wlr_layer_surface_v1 *layer;
do {
if (!surface) {
return NULL;
}
// Topmost layer surface
if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
return layer;
}
// Layer subsurface
if (wlr_subsurface_try_from_wlr_surface(surface)) {
surface = wlr_surface_get_root_surface(surface);
continue;
}
// Layer surface popup
struct wlr_xdg_surface *xdg_surface = NULL;
if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) &&
xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) {
if (!xdg_surface->popup->parent) {
return NULL;
}
surface = wlr_surface_get_root_surface(xdg_surface->popup->parent);
continue;
}
// Return early if the surface is not a layer/xdg_popup/sub surface
return NULL;
} while (true);
}
static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) {
struct wlr_scene_node *node;

View File

@ -152,20 +152,9 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
return;
}
struct wlr_scene_node *current = &buffer->node;
while (true) {
struct sway_view *view = scene_descriptor_try_get(current,
SWAY_SCENE_DESC_VIEW);
if (view) {
view_max_render_time = view->max_render_time;
break;
}
if (!current->parent) {
break;
}
current = &current->parent->node;
struct sway_view *view = scene_descriptor_find(&buffer->node, SWAY_SCENE_DESC_VIEW);
if (view) {
view_max_render_time = view->max_render_time;
}
int delay = data->msec_until_refresh - output->max_render_time

View File

@ -38,15 +38,8 @@ static uint32_t get_current_time_msec(void) {
return now.tv_sec * 1000 + now.tv_nsec / 1000000;
}
/**
* Returns the node at the cursor's position. If there is a surface at that
* location, it is stored in **surface (it may not be a view).
*/
struct sway_node *node_at_coords(
struct sway_seat *seat, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
struct wlr_scene_node *scene_node = NULL;
struct wlr_scene_node *scene_node_at_coords(
double lx, double ly, double *sx, double *sy) {
struct wlr_scene_node *node;
wl_list_for_each_reverse(node, &root->layer_tree->children, link) {
struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node);
@ -57,69 +50,58 @@ struct sway_node *node_at_coords(
continue;
}
scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy);
if (scene_node) {
break;
struct wlr_scene_node *node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy);
if (node) {
return node;
}
}
if (scene_node) {
// determine what wlr_surface we clicked on
if (scene_node->type == WLR_SCENE_NODE_BUFFER) {
struct wlr_scene_buffer *scene_buffer =
wlr_scene_buffer_from_node(scene_node);
struct wlr_scene_surface *scene_surface =
wlr_scene_surface_try_from_buffer(scene_buffer);
return NULL;
}
if (scene_surface) {
*surface = scene_surface->surface;
}
}
struct wlr_surface *surface_try_from_scene_node(struct wlr_scene_node *node) {
if (!node || node->type != WLR_SCENE_NODE_BUFFER) {
return NULL;
}
// determine what container we clicked on
struct wlr_scene_node *current = scene_node;
while (true) {
struct sway_container *con = scene_descriptor_try_get(current,
SWAY_SCENE_DESC_CONTAINER);
struct wlr_scene_buffer *scene_buffer =
wlr_scene_buffer_from_node(node);
struct wlr_scene_surface *scene_surface =
wlr_scene_surface_try_from_buffer(scene_buffer);
if (!con) {
struct sway_view *view = scene_descriptor_try_get(current,
SWAY_SCENE_DESC_VIEW);
if (view) {
con = view->container;
}
}
if (scene_surface) {
return scene_surface->surface;
}
if (!con) {
struct sway_popup_desc *popup =
scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
if (popup && popup->view) {
con = popup->view->container;
}
}
return NULL;
}
if (con && (!con->view || con->view->surface)) {
return &con->node;
}
if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) {
// We don't want to feed through the current workspace on
// layer shells
struct sway_node *sway_node_try_from_scene_node(struct wlr_scene_node *node,
double lx, double ly) {
if (node) {
struct sway_container *con =
scene_descriptor_find(node, SWAY_SCENE_DESC_CONTAINER);
if (con) {
// If this condition succeeds, the container is currently in the
// process of being destroyed. In this case, ignore the container
if (con->view && !con->view->surface) {
return NULL;
}
return &con->node;
}
// if we clicked on a layer shell or unmanaged xwayland we don't
// want to return the workspace node.
if (scene_descriptor_find(node, SWAY_SCENE_DESC_LAYER_SHELL)) {
return NULL;
}
#if WLR_HAS_XWAYLAND
if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) {
return NULL;
}
#endif
if (!current->parent) {
break;
}
current = &current->parent->node;
if (scene_descriptor_find(node, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) {
return NULL;
}
#endif
}
// if we aren't on a container, determine what workspace we are on
@ -143,6 +125,18 @@ struct sway_node *node_at_coords(
return &ws->node;
}
/**
* Returns the node at the cursor's position. If there is a surface at that
* location, it is stored in **surface (it may not be a view).
*/
struct sway_node *node_at_coords(double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
struct wlr_scene_node *scene_node = scene_node_at_coords(lx, ly, sx, sy);
*surface = surface_try_from_scene_node(scene_node);
return sway_node_try_from_scene_node(scene_node, lx, ly);
}
void cursor_rebase(struct sway_cursor *cursor) {
uint32_t time_msec = get_current_time_msec();
seatop_rebase(cursor->seat, time_msec);
@ -305,8 +299,7 @@ void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
if (cursor->active_constraint && device->type == WLR_INPUT_DEVICE_POINTER) {
struct wlr_surface *surface = NULL;
double sx, sy;
node_at_coords(cursor->seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (cursor->active_constraint->surface != surface) {
return;
@ -565,7 +558,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
double sx, sy;
struct wlr_surface *surface = NULL;
struct sway_seat *seat = cursor->seat;
node_at_coords(seat, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
// The logic for whether we should send a tablet event or an emulated pointer
// event is tricky. It comes down to:
@ -655,8 +648,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
double sx, sy;
struct wlr_surface *surface = NULL;
node_at_coords(seat, cursor->cursor->x, cursor->cursor->y,
&surface, &sx, &sy);
node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (cursor->simulating_pointer_from_tool_tip &&
event->state == WLR_TABLET_TOOL_TIP_UP) {
@ -740,8 +732,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
double sx, sy;
struct wlr_surface *surface = NULL;
node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
&surface, &sx, &sy);
node_at_coords(cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
// TODO: floating resize should support graphics tablet events
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);

View File

@ -223,7 +223,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
struct sway_node *node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (!sway_assert(surface,
@ -334,10 +334,12 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct sway_cursor *cursor = seat->cursor;
// Determine what's under the cursor
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct wlr_scene_node *scene_node =
scene_node_at_coords(cursor->cursor->x, cursor->cursor->y, &sx, &sy);
struct wlr_surface *surface = scene_node ? surface_try_from_scene_node(scene_node) : NULL;
struct sway_node *node = sway_node_try_from_scene_node(scene_node,
cursor->cursor->x, cursor->cursor->y);
struct sway_container *cont = node && node->type == N_CONTAINER ?
node->sway_container : NULL;
@ -379,10 +381,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Handle clicking a layer surface and its popups/subsurfaces
struct wlr_layer_surface_v1 *layer = NULL;
if ((layer = toplevel_layer_surface_from_surface(surface))) {
if (layer->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer);
struct sway_layer_surface *layer = NULL;
if ((layer = scene_descriptor_find(scene_node, SWAY_SCENE_DESC_LAYER_SHELL))) {
if (layer->layer_surface->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer->layer_surface);
transaction_commit_dirty();
}
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
@ -547,16 +549,14 @@ static void check_focus_follows_mouse(struct sway_seat *seat,
return;
}
struct wlr_surface *surface = NULL;
double sx, sy;
node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y,
&surface, &sx, &sy);
struct wlr_scene_node *node = scene_node_at_coords(
seat->cursor->cursor->x, seat->cursor->cursor->y, NULL, NULL);
// Focus topmost layer surface
struct wlr_layer_surface_v1 *layer = NULL;
if ((layer = toplevel_layer_surface_from_surface(surface)) &&
layer->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer);
struct sway_layer_surface *layer = NULL;
if ((layer = scene_descriptor_find(node, SWAY_SCENE_DESC_LAYER_SHELL)) &&
layer->layer_surface->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer->layer_surface);
transaction_commit_dirty();
return;
}
@ -604,8 +604,8 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_node *node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (config->focus_follows_mouse != FOLLOWS_NO) {
check_focus_follows_mouse(seat, e, node);
@ -633,8 +633,8 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_node *node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (config->focus_follows_mouse != FOLLOWS_NO) {
check_focus_follows_mouse(seat, e, node);
@ -662,7 +662,7 @@ static void handle_touch_down(struct sway_seat *seat,
struct wlr_seat *wlr_seat = seat->wlr_seat;
struct sway_cursor *cursor = seat->cursor;
double sx, sy;
node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
node_at_coords(seat->touch_x, seat->touch_y, &surface, &sx, &sy);
if (surface && wlr_surface_accepts_touch(surface, wlr_seat)) {
if (seat_is_input_allowed(seat, surface)) {
@ -714,7 +714,7 @@ static void handle_pointer_axis(struct sway_seat *seat,
// Determine what's under the cursor
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_node *node = node_at_coords(seat,
struct sway_node *node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_container *cont = node && node->type == N_CONTAINER ?
node->sway_container : NULL;
@ -1106,8 +1106,8 @@ static void handle_rebase(struct sway_seat *seat, uint32_t time_msec) {
struct sway_cursor *cursor = seat->cursor;
struct wlr_surface *surface = NULL;
double sx = 0.0, sy = 0.0;
e->previous_node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
e->previous_node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (surface) {
if (seat_is_input_allowed(seat, surface)) {

View File

@ -75,7 +75,7 @@ static void handle_touch_down(struct sway_seat *seat,
struct seatop_down_event *e = seat->seatop_data;
double sx, sy;
struct wlr_surface *surface = NULL;
struct sway_node *focused_node = node_at_coords(seat, seat->touch_x,
struct sway_node *focused_node = node_at_coords(seat->touch_x,
seat->touch_y, &surface, &sx, &sy);
if (!surface || surface != e->surface) { // Must start from the initial surface

View File

@ -163,8 +163,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_cursor *cursor = seat->cursor;
struct sway_node *node = node_at_coords(seat,
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
struct sway_node *node = node_at_coords(
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (!node) {
// Eg. hovered over a layer surface such as swaybar

View File

@ -36,6 +36,31 @@ void *scene_descriptor_try_get(struct wlr_scene_node *node,
return desc->data;
}
void *scene_descriptor_find(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type) {
while (node) {
struct scene_descriptor *desc = scene_node_get_descriptor(node, type);
if (desc) {
return desc->data;
}
struct sway_popup_desc *popup =
scene_descriptor_try_get(node, SWAY_SCENE_DESC_POPUP);
if (popup) {
node = popup->relative;
continue;
}
if (!node->parent) {
break;
}
node = &node->parent->node;
}
return NULL;
}
void scene_descriptor_destroy(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type) {
struct scene_descriptor *desc = scene_node_get_descriptor(node, type);
@ -67,3 +92,14 @@ bool scene_descriptor_assign(struct wlr_scene_node *node,
desc->data = data;
return true;
}
bool scene_descriptor_reassign(struct wlr_scene_node *node,
enum sway_scene_descriptor_type type, void *data) {
struct scene_descriptor *desc = scene_node_get_descriptor(node, type);
if (desc) {
desc->data = data;
return true;
}
return scene_descriptor_assign(node, type, data);
}

View File

@ -508,6 +508,8 @@ void container_destroy(struct sway_container *con) {
if (con->view && con->view->container == con) {
con->view->container = NULL;
scene_descriptor_destroy(&con->view->scene_tree->node, SWAY_SCENE_DESC_CONTAINER);
wlr_scene_node_destroy(&con->output_handler->node);
if (con->view->destroying) {
view_destroy(con->view);

View File

@ -720,6 +720,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
view->surface = wlr_surface;
view_populate_pid(view);
view->container = container_create(view);
scene_descriptor_assign(&view->scene_tree->node,
SWAY_SCENE_DESC_CONTAINER, view->container);
if (view->ctx == NULL) {
struct launcher_ctx *ctx = launcher_ctx_find_pid(view->pid);