aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-01-15 10:19:49 -0500
committerLibravatar GitHub <noreply@github.com>2018-01-15 10:19:49 -0500
commiteb0f432a840dbe860b8c20f7a16e0281f9026326 (patch)
treea8b8e1a5a92a4203503ead496d8d50fd72fcf850 /sway
parentMerge pull request #1556 from martinetd/cleanup_logging (diff)
parentxwm handle map and unmap (diff)
downloadsway-eb0f432a840dbe860b8c20f7a16e0281f9026326.tar.gz
sway-eb0f432a840dbe860b8c20f7a16e0281f9026326.tar.zst
sway-eb0f432a840dbe860b8c20f7a16e0281f9026326.zip
Merge pull request #1566 from acrisci/render-loop
Subsurfaces and popups
Diffstat (limited to 'sway')
-rw-r--r--sway/desktop/output.c248
-rw-r--r--sway/desktop/wl_shell.c6
-rw-r--r--sway/desktop/xwayland.c87
-rw-r--r--sway/input/cursor.c25
-rw-r--r--sway/tree/container.c30
-rw-r--r--sway/tree/layout.c1
6 files changed, 324 insertions, 73 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 2b428c30..0f00222b 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -1,9 +1,11 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <assert.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <time.h> 4#include <time.h>
4#include <wayland-server.h> 5#include <wayland-server.h>
5#include <wlr/types/wlr_output.h> 6#include <wlr/types/wlr_output.h>
6#include <wlr/types/wlr_surface.h> 7#include <wlr/types/wlr_surface.h>
8#include <wlr/types/wlr_wl_shell.h>
7#include <wlr/render.h> 9#include <wlr/render.h>
8#include <wlr/render/matrix.h> 10#include <wlr/render/matrix.h>
9#include "log.h" 11#include "log.h"
@@ -15,76 +17,198 @@
15#include "sway/input/input-manager.h" 17#include "sway/input/input-manager.h"
16#include "sway/input/seat.h" 18#include "sway/input/seat.h"
17 19
18static void output_frame_view(swayc_t *view, void *data) { 20/**
19 struct sway_output *output = data; 21 * Rotate a child's position relative to a parent. The parent size is (pw, ph),
20 struct wlr_output *wlr_output = output->wlr_output; 22 * the child position is (*sx, *sy) and its size is (sw, sh).
21 struct sway_view *sway_view = view->sway_view; 23 */
22 struct wlr_surface *surface = sway_view->surface; 24static void rotate_child_position(double *sx, double *sy, double sw, double sh,
25 double pw, double ph, float rotation) {
26 if (rotation != 0.0) {
27 // Coordinates relative to the center of the subsurface
28 double ox = *sx - pw/2 + sw/2,
29 oy = *sy - ph/2 + sh/2;
30 // Rotated coordinates
31 double rx = cos(-rotation)*ox - sin(-rotation)*oy,
32 ry = cos(-rotation)*oy + sin(-rotation)*ox;
33 *sx = rx + pw/2 - sw/2;
34 *sy = ry + ph/2 - sh/2;
35 }
36}
37
38static void render_surface(struct wlr_surface *surface,
39 struct wlr_output *wlr_output, struct timespec *when,
40 double lx, double ly, float rotation) {
23 if (!wlr_surface_has_buffer(surface)) { 41 if (!wlr_surface_has_buffer(surface)) {
24 return; 42 return;
25 } 43 }
26 // TODO 44 struct wlr_output_layout *layout = root_container.sway_root->output_layout;
27 // - Deal with wlr_output_layout 45 int width = surface->current->width;
28 int width = sway_view->surface->current->width; 46 int height = surface->current->height;
29 int height = sway_view->surface->current->height;
30 int render_width = width * wlr_output->scale; 47 int render_width = width * wlr_output->scale;
31 int render_height = height * wlr_output->scale; 48 int render_height = height * wlr_output->scale;
32 double ox = view->x, oy = view->y; 49 double ox = lx, oy = ly;
33 // TODO 50 wlr_output_layout_output_coords(layout, wlr_output, &ox, &oy);
34 //wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy);
35 ox *= wlr_output->scale; 51 ox *= wlr_output->scale;
36 oy *= wlr_output->scale; 52 oy *= wlr_output->scale;
37 // TODO 53
38 //if (wlr_output_layout_intersects(desktop->layout, wlr_output, 54 struct wlr_box render_box = {
39 // lx, ly, lx + render_width, ly + render_height)) { 55 .x = lx, .y = ly,
40 // return; 56 .width = render_width, .height = render_height,
41 //} 57 };
42 58 if (wlr_output_layout_intersects(layout, wlr_output, &render_box)) {
43 // if the shell specifies window geometry, make the top left corner of the 59 float matrix[16];
44 // window in the top left corner of the container to avoid arbitrarily 60
45 // sized gaps based on the attached buffer size 61 float translate_center[16];
46 int window_offset_x = 0; 62 wlr_matrix_translate(&translate_center,
47 int window_offset_y = 0; 63 (int)ox + render_width / 2, (int)oy + render_height / 2, 0);
48 64
49 if (view->sway_view->type == SWAY_XDG_SHELL_V6_VIEW) { 65 float rotate[16];
50 window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; 66 wlr_matrix_rotate(&rotate, rotation);
51 window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; 67
68 float translate_origin[16];
69 wlr_matrix_translate(&translate_origin, -render_width / 2,
70 -render_height / 2, 0);
71
72 float scale[16];
73 wlr_matrix_scale(&scale, render_width, render_height, 1);
74
75 float transform[16];
76 wlr_matrix_mul(&translate_center, &rotate, &transform);
77 wlr_matrix_mul(&transform, &translate_origin, &transform);
78 wlr_matrix_mul(&transform, &scale, &transform);
79
80 if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) {
81 float surface_translate_center[16];
82 wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0);
83
84 float surface_transform[16];
85 wlr_matrix_transform(surface_transform,
86 wlr_output_transform_invert(surface->current->transform));
87
88 float surface_translate_origin[16];
89 wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0);
90
91 wlr_matrix_mul(&transform, &surface_translate_center,
92 &transform);
93 wlr_matrix_mul(&transform, &surface_transform, &transform);
94 wlr_matrix_mul(&transform, &surface_translate_origin,
95 &transform);
96 }
97
98 wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix);
99
100 wlr_render_with_matrix(server.renderer, surface->texture,
101 &matrix);
102
103 wlr_surface_send_frame_done(surface, when);
52 } 104 }
53 105
54 // TODO 106 struct wlr_subsurface *subsurface;
55 double rotation = 0; 107 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
56 float matrix[16]; 108 struct wlr_surface_state *state = subsurface->surface->current;
109 double sx = state->subsurface_position.x;
110 double sy = state->subsurface_position.y;
111 double sw = state->buffer_width / state->scale;
112 double sh = state->buffer_height / state->scale;
113 rotate_child_position(&sx, &sy, sw, sh, width, height, rotation);
57 114
58 float translate_origin[16]; 115 render_surface(subsurface->surface, wlr_output, when,
59 wlr_matrix_translate(&translate_origin, 116 lx + sx,
60 (int)ox + render_width / 2 - window_offset_x, 117 ly + sy,
61 (int)oy + render_height / 2 - window_offset_y, 118 rotation);
62 0); 119 }
120}
63 121
64 float rotate[16]; 122static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface,
65 wlr_matrix_rotate(&rotate, rotation); 123 struct wlr_output *wlr_output, struct timespec *when, double base_x,
124 double base_y, float rotation) {
125 double width = surface->surface->current->width;
126 double height = surface->surface->current->height;
66 127
67 float translate_center[16]; 128 struct wlr_xdg_surface_v6 *popup;
68 wlr_matrix_translate(&translate_center, 129 wl_list_for_each(popup, &surface->popups, popup_link) {
69 -render_width / 2, 130 if (!popup->configured) {
70 -render_height / 2, 0); 131 continue;
132 }
71 133
72 float scale[16]; 134 double popup_width = popup->surface->current->width;
73 wlr_matrix_scale(&scale, render_width, render_height, 1); 135 double popup_height = popup->surface->current->height;
74 136
75 float transform[16]; 137 double popup_sx, popup_sy;
76 wlr_matrix_mul(&translate_origin, &rotate, &transform); 138 wlr_xdg_surface_v6_popup_get_position(popup, &popup_sx, &popup_sy);
77 wlr_matrix_mul(&transform, &translate_center, &transform); 139 rotate_child_position(&popup_sx, &popup_sy, popup_width, popup_height,
78 wlr_matrix_mul(&transform, &scale, &transform); 140 width, height, rotation);
79 wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix);
80 141
81 wlr_render_with_matrix(output->server->renderer, surface->texture, &matrix); 142 render_surface(popup->surface, wlr_output, when,
143 base_x + popup_sx, base_y + popup_sy, rotation);
144 render_xdg_v6_popups(popup, wlr_output, when,
145 base_x + popup_sx, base_y + popup_sy, rotation);
146 }
147}
82 148
83 // TODO: move into wlroots 149static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
84 struct timespec now; 150 struct wlr_output *wlr_output, struct timespec *when,
85 clock_gettime(CLOCK_MONOTONIC, &now); 151 double lx, double ly, float rotation,
152 bool is_child) {
153 if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) {
154 render_surface(surface->surface, wlr_output, when,
155 lx, ly, rotation);
156
157 double width = surface->surface->current->width;
158 double height = surface->surface->current->height;
159
160 struct wlr_wl_shell_surface *popup;
161 wl_list_for_each(popup, &surface->popups, popup_link) {
162 double popup_width = popup->surface->current->width;
163 double popup_height = popup->surface->current->height;
164
165 double popup_x = popup->transient_state->x;
166 double popup_y = popup->transient_state->y;
167 rotate_child_position(&popup_x, &popup_y, popup_width, popup_height,
168 width, height, rotation);
169
170 render_wl_shell_surface(popup, wlr_output, when,
171 lx + popup_x, ly + popup_y, rotation, true);
172 }
173 }
174}
175
176
177static void output_frame_view(swayc_t *view, void *data) {
178 struct sway_output *output = data;
179 struct wlr_output *wlr_output = output->wlr_output;
180 struct sway_view *sway_view = view->sway_view;
181 struct wlr_surface *surface = sway_view->surface;
182
183 if (!surface) {
184 return;
185 }
86 186
87 wlr_surface_send_frame_done(surface, &now); 187 switch (sway_view->type) {
188 case SWAY_XDG_SHELL_V6_VIEW: {
189 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x;
190 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y;
191 render_surface(surface, wlr_output, &output->last_frame,
192 view->x - window_offset_x,
193 view->y - window_offset_y,
194 0);
195 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output,
196 &output->last_frame,
197 view->x - window_offset_x, view->y - window_offset_y,
198 0);
199 break;
200 }
201 case SWAY_WL_SHELL_VIEW:
202 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output,
203 &output->last_frame, view->x, view->y, 0, false);
204 break;
205 case SWAY_XWAYLAND_VIEW:
206 render_surface(surface, wlr_output, &output->last_frame, view->x,
207 view->y, 0);
208 break;
209 default:
210 break;
211 }
88} 212}
89 213
90static void output_frame_notify(struct wl_listener *listener, void *data) { 214static void output_frame_notify(struct wl_listener *listener, void *data) {
@@ -92,18 +216,30 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
92 struct wlr_output *wlr_output = data; 216 struct wlr_output *wlr_output = data;
93 struct sway_server *server = soutput->server; 217 struct sway_server *server = soutput->server;
94 218
95 struct timespec now;
96 clock_gettime(CLOCK_MONOTONIC, &now);
97
98 wlr_output_make_current(wlr_output); 219 wlr_output_make_current(wlr_output);
99 wlr_renderer_begin(server->renderer, wlr_output); 220 wlr_renderer_begin(server->renderer, wlr_output);
100 221
101 swayc_descendants_of_type( 222 swayc_descendants_of_type(
102 &root_container, C_VIEW, output_frame_view, soutput); 223 &root_container, C_VIEW, output_frame_view, soutput);
103 224
225 // render unmanaged views on top
226 struct sway_view *view;
227 wl_list_for_each(view, &root_container.sway_root->unmanaged_views,
228 unmanaged_view_link) {
229 if (view->type == SWAY_XWAYLAND_VIEW) {
230 // the only kind of unamanged view right now is xwayland override redirect
231 int view_x = view->wlr_xwayland_surface->x;
232 int view_y = view->wlr_xwayland_surface->y;
233 render_surface(view->surface, wlr_output, &soutput->last_frame,
234 view_x, view_y, 0);
235 }
236 }
237
104 wlr_renderer_end(server->renderer); 238 wlr_renderer_end(server->renderer);
105 wlr_output_swap_buffers(wlr_output); 239 wlr_output_swap_buffers(wlr_output);
106 240
241 struct timespec now;
242 clock_gettime(CLOCK_MONOTONIC, &now);
107 soutput->last_frame = now; 243 soutput->last_frame = now;
108} 244}
109 245
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index 345a1398..e34f5160 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -77,11 +77,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
77 listener, server, wl_shell_surface); 77 listener, server, wl_shell_surface);
78 struct wlr_wl_shell_surface *shell_surface = data; 78 struct wlr_wl_shell_surface *shell_surface = data;
79 79
80 if (shell_surface->state != WLR_WL_SHELL_SURFACE_STATE_TOPLEVEL) { 80 if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) {
81 // TODO: transient and popups should be floating 81 // popups don't get views
82 return; 82 return;
83 } 83 }
84 84
85 // TODO make transient windows floating
86
85 wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", 87 wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'",
86 shell_surface->title, shell_surface->class); 88 shell_surface->title, shell_surface->class);
87 wlr_wl_shell_surface_ping(shell_surface); 89 wlr_wl_shell_surface_ping(shell_surface);
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 43bb2e00..a4d9687d 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -93,13 +93,68 @@ static void handle_commit(struct wl_listener *listener, void *data) {
93static void handle_destroy(struct wl_listener *listener, void *data) { 93static void handle_destroy(struct wl_listener *listener, void *data) {
94 struct sway_xwayland_surface *sway_surface = 94 struct sway_xwayland_surface *sway_surface =
95 wl_container_of(listener, sway_surface, destroy); 95 wl_container_of(listener, sway_surface, destroy);
96 struct wlr_xwayland_surface *xsurface = data;
96 wl_list_remove(&sway_surface->commit.link); 97 wl_list_remove(&sway_surface->commit.link);
97 wl_list_remove(&sway_surface->destroy.link); 98 wl_list_remove(&sway_surface->destroy.link);
98 wl_list_remove(&sway_surface->request_configure.link); 99 wl_list_remove(&sway_surface->request_configure.link);
100 if (xsurface->override_redirect) {
101 if (xsurface->mapped) {
102 wl_list_remove(&sway_surface->view->unmanaged_view_link);
103 }
104 }
105
99 swayc_t *parent = destroy_view(sway_surface->view->swayc); 106 swayc_t *parent = destroy_view(sway_surface->view->swayc);
107 if (parent) {
108 arrange_windows(parent, -1, -1);
109 }
110
100 free(sway_surface->view); 111 free(sway_surface->view);
101 free(sway_surface); 112 free(sway_surface);
102 arrange_windows(parent, -1, -1); 113}
114
115static void handle_unmap_notify(struct wl_listener *listener, void *data) {
116 struct sway_xwayland_surface *sway_surface =
117 wl_container_of(listener, sway_surface, unmap_notify);
118 struct wlr_xwayland_surface *xsurface = data;
119 if (xsurface->override_redirect) {
120 wl_list_remove(&sway_surface->view->unmanaged_view_link);
121 }
122
123 // take it out of the tree
124 swayc_t *parent = destroy_view(sway_surface->view->swayc);
125 if (parent) {
126 arrange_windows(parent, -1, -1);
127 }
128
129 sway_surface->view->swayc = NULL;
130 sway_surface->view->surface = NULL;
131}
132
133static void handle_map_notify(struct wl_listener *listener, void *data) {
134 // TODO put the view back into the tree
135 struct sway_xwayland_surface *sway_surface =
136 wl_container_of(listener, sway_surface, map_notify);
137 struct wlr_xwayland_surface *xsurface = data;
138
139 sway_surface->view->surface = xsurface->surface;
140
141 // put it back into the tree
142 if (xsurface->override_redirect) {
143 wl_list_insert(&root_container.sway_root->unmanaged_views,
144 &sway_surface->view->unmanaged_view_link);
145 } else {
146 struct sway_view *view = sway_surface->view;
147 destroy_view(view->swayc);
148
149 swayc_t *parent = root_container.children->items[0];
150 parent = parent->children->items[0]; // workspace
151
152 swayc_t *cont = new_view(parent, view);
153 view->swayc = cont;
154
155 arrange_windows(cont->parent, -1, -1);
156 sway_input_manager_set_focus(input_manager, cont);
157 }
103} 158}
104 159
105static void handle_configure_request(struct wl_listener *listener, void *data) { 160static void handle_configure_request(struct wl_listener *listener, void *data) {
@@ -119,11 +174,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
119 listener, server, xwayland_surface); 174 listener, server, xwayland_surface);
120 struct wlr_xwayland_surface *xsurface = data; 175 struct wlr_xwayland_surface *xsurface = data;
121 176
122 if (xsurface->override_redirect) {
123 // TODO: floating popups
124 return;
125 }
126
127 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", 177 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'",
128 xsurface->title, xsurface->class); 178 xsurface->title, xsurface->class);
129 179
@@ -144,26 +194,37 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
144 sway_view->iface.set_activated = set_activated; 194 sway_view->iface.set_activated = set_activated;
145 sway_view->wlr_xwayland_surface = xsurface; 195 sway_view->wlr_xwayland_surface = xsurface;
146 sway_view->sway_xwayland_surface = sway_surface; 196 sway_view->sway_xwayland_surface = sway_surface;
147 // TODO remove from the tree when the surface goes away (unmapped)
148 sway_view->surface = xsurface->surface; 197 sway_view->surface = xsurface->surface;
149 sway_surface->view = sway_view; 198 sway_surface->view = sway_view;
150 199
151 // TODO: 200 // TODO:
152 // - Wire up listeners
153 // - Handle popups
154 // - Look up pid and open on appropriate workspace 201 // - Look up pid and open on appropriate workspace
155 // - Set new view to maximized so it behaves nicely 202 // - Set new view to maximized so it behaves nicely
156 // - Criteria 203 // - Criteria
157 204
158 sway_surface->commit.notify = handle_commit;
159 wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); 205 wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit);
160 sway_surface->destroy.notify = handle_destroy; 206 sway_surface->commit.notify = handle_commit;
207
161 wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); 208 wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy);
162 sway_surface->request_configure.notify = handle_configure_request; 209 sway_surface->destroy.notify = handle_destroy;
210
163 wl_signal_add(&xsurface->events.request_configure, 211 wl_signal_add(&xsurface->events.request_configure,
164 &sway_surface->request_configure); 212 &sway_surface->request_configure);
213 sway_surface->request_configure.notify = handle_configure_request;
214
215 wl_signal_add(&xsurface->events.unmap_notify, &sway_surface->unmap_notify);
216 sway_surface->unmap_notify.notify = handle_unmap_notify;
217
218 wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify);
219 sway_surface->map_notify.notify = handle_map_notify;
220
221 if (xsurface->override_redirect) {
222 // these don't get a container in the tree
223 wl_list_insert(&root_container.sway_root->unmanaged_views,
224 &sway_view->unmanaged_view_link);
225 return;
226 }
165 227
166 // TODO: actual focus semantics
167 swayc_t *parent = root_container.children->items[0]; 228 swayc_t *parent = root_container.children->items[0];
168 parent = parent->children->items[0]; // workspace 229 parent = parent->children->items[0]; // workspace
169 230
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index c51b59f9..e6a4eca8 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -24,6 +24,31 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
24 struct wlr_seat *seat = cursor->seat->wlr_seat; 24 struct wlr_seat *seat = cursor->seat->wlr_seat;
25 struct wlr_surface *surface = NULL; 25 struct wlr_surface *surface = NULL;
26 double sx, sy; 26 double sx, sy;
27
28 // check for unmanaged views first
29 struct sway_view *view;
30 wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views,
31 unmanaged_view_link) {
32 if (view->type == SWAY_XWAYLAND_VIEW) {
33 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
34 struct wlr_box box = {
35 .x = xsurface->x,
36 .y = xsurface->y,
37 .width = xsurface->width,
38 .height = xsurface->height,
39 };
40
41 if (wlr_box_contains_point(&box, cursor->x, cursor->y)) {
42 surface = xsurface->surface;
43 sx = cursor->x - box.x;
44 sy = cursor->y - box.y;
45 wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
46 wlr_seat_pointer_notify_motion(seat, time, sx, sy);
47 return;
48 }
49 }
50 }
51
27 swayc_t *swayc = 52 swayc_t *swayc =
28 swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); 53 swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy);
29 if (swayc) { 54 if (swayc) {
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 31ec2ce5..d241f69a 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -207,7 +207,7 @@ swayc_t *destroy_output(swayc_t *output) {
207} 207}
208 208
209swayc_t *destroy_view(swayc_t *view) { 209swayc_t *destroy_view(swayc_t *view) {
210 if (!sway_assert(view, "null view passed to destroy_view")) { 210 if (!view) {
211 return NULL; 211 return NULL;
212 } 212 }
213 wlr_log(L_DEBUG, "Destroying view '%s'", view->name); 213 wlr_log(L_DEBUG, "Destroying view '%s'", view->name);
@@ -259,7 +259,6 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly,
259 int width = swayc->sway_view->surface->current->width; 259 int width = swayc->sway_view->surface->current->width;
260 int height = swayc->sway_view->surface->current->height; 260 int height = swayc->sway_view->surface->current->height;
261 261
262 // TODO popups and subsurfaces
263 switch (sview->type) { 262 switch (sview->type) {
264 case SWAY_WL_SHELL_VIEW: 263 case SWAY_WL_SHELL_VIEW:
265 break; 264 break;
@@ -268,6 +267,20 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly,
268 // coordinate of the top left corner of the window geometry 267 // coordinate of the top left corner of the window geometry
269 view_sx += sview->wlr_xdg_surface_v6->geometry->x; 268 view_sx += sview->wlr_xdg_surface_v6->geometry->x;
270 view_sy += sview->wlr_xdg_surface_v6->geometry->y; 269 view_sy += sview->wlr_xdg_surface_v6->geometry->y;
270
271 // check for popups
272 double popup_sx, popup_sy;
273 struct wlr_xdg_surface_v6 *popup =
274 wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6,
275 view_sx, view_sy, &popup_sx, &popup_sy);
276
277 if (popup) {
278 *sx = view_sx - popup_sx;
279 *sy = view_sy - popup_sy;
280 *surface = popup->surface;
281 list_free(queue);
282 return swayc;
283 }
271 break; 284 break;
272 case SWAY_XWAYLAND_VIEW: 285 case SWAY_XWAYLAND_VIEW:
273 break; 286 break;
@@ -275,6 +288,19 @@ swayc_t *swayc_at(swayc_t *parent, double lx, double ly,
275 break; 288 break;
276 } 289 }
277 290
291 // check for subsurfaces
292 double sub_x, sub_y;
293 struct wlr_subsurface *subsurface =
294 wlr_surface_subsurface_at(sview->surface,
295 view_sx, view_sy, &sub_x, &sub_y);
296 if (subsurface) {
297 *sx = view_sx - sub_x;
298 *sy = view_sy - sub_y;
299 *surface = subsurface->surface;
300 list_free(queue);
301 return swayc;
302 }
303
278 if (view_sx > 0 && view_sx < width && 304 if (view_sx > 0 && view_sx < width &&
279 view_sy > 0 && view_sy < height && 305 view_sy > 0 && view_sy < height &&
280 pixman_region32_contains_point( 306 pixman_region32_contains_point(
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 13b8a395..01535f2d 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -51,6 +51,7 @@ void init_layout(void) {
51 51
52 root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); 52 root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
53 root_container.sway_root->output_layout = wlr_output_layout_create(); 53 root_container.sway_root->output_layout = wlr_output_layout_create();
54 wl_list_init(&root_container.sway_root->unmanaged_views);
54 55
55 root_container.sway_root->output_layout_change.notify = 56 root_container.sway_root->output_layout_change.notify =
56 output_layout_change_notify; 57 output_layout_change_notify;