aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2023-11-23 10:09:48 -0500
committerLibravatar Kirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commit5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d (patch)
treef420022ad3a48215f9182505c0060d91edcd848e /sway/input/cursor.c
parentIntroduce sway_text_node (diff)
downloadsway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.tar.gz
sway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.tar.zst
sway-5b8b505af5d5925ae9e617ee8f3c7a0f9c43409d.zip
input: Query scene graph for relevant surface/node intersections
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c184
1 files changed, 55 insertions, 129 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 107424c9..79373e40 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -37,43 +37,6 @@ static uint32_t get_current_time_msec(void) {
37 return now.tv_sec * 1000 + now.tv_nsec / 1000000; 37 return now.tv_sec * 1000 + now.tv_nsec / 1000000;
38} 38}
39 39
40static struct wlr_surface *layer_surface_at(struct sway_output *output,
41 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
42 struct sway_layer_surface *sway_layer;
43 wl_list_for_each_reverse(sway_layer, layer, link) {
44 double _sx = ox - sway_layer->geo.x;
45 double _sy = oy - sway_layer->geo.y;
46 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
47 sway_layer->layer_surface, _sx, _sy, sx, sy);
48 if (sub) {
49 return sub;
50 }
51 }
52 return NULL;
53}
54
55static bool surface_is_xdg_popup(struct wlr_surface *surface) {
56 struct wlr_xdg_surface *xdg_surface =
57 wlr_xdg_surface_try_from_wlr_surface(surface);
58 return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP &&
59 xdg_surface->popup != NULL;
60}
61
62static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
63 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
64 struct sway_layer_surface *sway_layer;
65 wl_list_for_each_reverse(sway_layer, layer, link) {
66 double _sx = ox - sway_layer->geo.x;
67 double _sy = oy - sway_layer->geo.y;
68 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
69 sway_layer->layer_surface, _sx, _sy, sx, sy);
70 if (sub && surface_is_xdg_popup(sub)) {
71 return sub;
72 }
73 }
74 return NULL;
75}
76
77/** 40/**
78 * Returns the node at the cursor's position. If there is a surface at that 41 * Returns the node at the cursor's position. If there is a surface at that
79 * location, it is stored in **surface (it may not be a view). 42 * location, it is stored in **surface (it may not be a view).
@@ -81,116 +44,79 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
81struct sway_node *node_at_coords( 44struct sway_node *node_at_coords(
82 struct sway_seat *seat, double lx, double ly, 45 struct sway_seat *seat, double lx, double ly,
83 struct wlr_surface **surface, double *sx, double *sy) { 46 struct wlr_surface **surface, double *sx, double *sy) {
84 // find the output the cursor is on 47 struct wlr_scene_node *scene_node = NULL;
85 struct wlr_output *wlr_output = wlr_output_layout_output_at(
86 root->output_layout, lx, ly);
87 if (wlr_output == NULL) {
88 return NULL;
89 }
90 struct sway_output *output = wlr_output->data;
91 if (!output || !output->enabled) {
92 // output is being destroyed or is being enabled
93 return NULL;
94 }
95 double ox = lx, oy = ly;
96 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
97 48
98 // layer surfaces on the overlay layer are rendered on top 49 struct wlr_scene_node *node;
99 if ((*surface = layer_surface_at(output, 50 wl_list_for_each_reverse(node, &root->layer_tree->children, link) {
100 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], 51 struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node);
101 ox, oy, sx, sy))) {
102 return NULL;
103 }
104 52
105 // check for unmanaged views 53 bool non_interactive = scene_descriptor_try_get(&layer->node,
106#if HAVE_XWAYLAND 54 SWAY_SCENE_DESC_NON_INTERACTIVE);
107 struct wl_list *unmanaged = &root->xwayland_unmanaged; 55 if (non_interactive) {
108 struct sway_xwayland_unmanaged *unmanaged_surface; 56 continue;
109 wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) {
110 struct wlr_xwayland_surface *xsurface =
111 unmanaged_surface->wlr_xwayland_surface;
112
113 double _sx = lx - unmanaged_surface->lx;
114 double _sy = ly - unmanaged_surface->ly;
115 if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) {
116 *surface = xsurface->surface;
117 *sx = _sx;
118 *sy = _sy;
119 return NULL;
120 } 57 }
121 }
122#endif
123 58
124 if (root->fullscreen_global) { 59 scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy);
125 // Try fullscreen container 60 if (scene_node) {
126 struct sway_container *con = tiling_container_at( 61 break;
127 &root->fullscreen_global->node, lx, ly, surface, sx, sy);
128 if (con) {
129 return &con->node;
130 } 62 }
131 return NULL;
132 } 63 }
133 64
134 // find the focused workspace on the output for this seat 65 if (scene_node) {
135 struct sway_workspace *ws = output_get_active_workspace(output); 66 // determine what wlr_surface we clicked on
136 if (!ws) { 67 if (scene_node->type == WLR_SCENE_NODE_BUFFER) {
137 return NULL; 68 struct wlr_scene_buffer *scene_buffer =
138 } 69 wlr_scene_buffer_from_node(scene_node);
70 struct wlr_scene_surface *scene_surface =
71 wlr_scene_surface_try_from_buffer(scene_buffer);
72
73 if (scene_surface) {
74 *surface = scene_surface->surface;
75 }
76 }
139 77
140 if (ws->fullscreen) { 78 // determine what container we clicked on
141 // Try transient containers 79 struct wlr_scene_node *current = scene_node;
142 for (int i = 0; i < ws->floating->length; ++i) { 80 while (true) {
143 struct sway_container *floater = ws->floating->items[i]; 81 struct sway_container *con = scene_descriptor_try_get(current,
144 if (container_is_transient_for(floater, ws->fullscreen)) { 82 SWAY_SCENE_DESC_CONTAINER);
145 struct sway_container *con = tiling_container_at( 83 if (!con) {
146 &floater->node, lx, ly, surface, sx, sy); 84 struct sway_view *view = scene_descriptor_try_get(current,
147 if (con) { 85 SWAY_SCENE_DESC_VIEW);
86 if (view) {
87 con = view->container;
88 }
89 }
90
91 if (con) {
92 if (!con->view || con->view->surface) {
148 return &con->node; 93 return &con->node;
149 } 94 }
150 } 95 }
96
97 if (!current->parent) {
98 break;
99 }
100
101 current = &current->parent->node;
151 } 102 }
152 // Try fullscreen container
153 struct sway_container *con =
154 tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy);
155 if (con) {
156 return &con->node;
157 }
158 return NULL;
159 }
160 if ((*surface = layer_surface_popup_at(output,
161 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
162 ox, oy, sx, sy))) {
163 return NULL;
164 }
165 if ((*surface = layer_surface_popup_at(output,
166 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
167 ox, oy, sx, sy))) {
168 return NULL;
169 }
170 if ((*surface = layer_surface_popup_at(output,
171 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
172 ox, oy, sx, sy))) {
173 return NULL;
174 }
175 if ((*surface = layer_surface_at(output,
176 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
177 ox, oy, sx, sy))) {
178 return NULL;
179 } 103 }
180 104
181 struct sway_container *c; 105 // if we aren't on a container, determine what workspace we are on
182 if ((c = container_at(ws, lx, ly, surface, sx, sy))) { 106 struct wlr_output *wlr_output = wlr_output_layout_output_at(
183 return &c->node; 107 root->output_layout, lx, ly);
108 if (wlr_output == NULL) {
109 return NULL;
184 } 110 }
185 111
186 if ((*surface = layer_surface_at(output, 112 struct sway_output *output = wlr_output->data;
187 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], 113 if (!output || !output->enabled) {
188 ox, oy, sx, sy))) { 114 // output is being destroyed or is being enabled
189 return NULL; 115 return NULL;
190 } 116 }
191 if ((*surface = layer_surface_at(output, 117
192 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], 118 struct sway_workspace *ws = output_get_active_workspace(output);
193 ox, oy, sx, sy))) { 119 if (!ws) {
194 return NULL; 120 return NULL;
195 } 121 }
196 122