diff options
-rw-r--r-- | include/sway/layout.h | 2 | ||||
-rw-r--r-- | include/sway/view.h | 5 | ||||
-rw-r--r-- | sway/desktop/output.c | 13 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 61 | ||||
-rw-r--r-- | sway/input/cursor.c | 25 | ||||
-rw-r--r-- | sway/tree/container.c | 2 | ||||
-rw-r--r-- | sway/tree/layout.c | 1 |
7 files changed, 97 insertions, 12 deletions
diff --git a/include/sway/layout.h b/include/sway/layout.h index bfd96a02..af561453 100644 --- a/include/sway/layout.h +++ b/include/sway/layout.h | |||
@@ -9,6 +9,8 @@ struct sway_root { | |||
9 | struct wlr_output_layout *output_layout; | 9 | struct wlr_output_layout *output_layout; |
10 | 10 | ||
11 | struct wl_listener output_layout_change; | 11 | struct wl_listener output_layout_change; |
12 | |||
13 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link | ||
12 | }; | 14 | }; |
13 | 15 | ||
14 | void init_layout(void); | 16 | void init_layout(void); |
diff --git a/include/sway/view.h b/include/sway/view.h index 900bd296..08c5480b 100644 --- a/include/sway/view.h +++ b/include/sway/view.h | |||
@@ -28,6 +28,8 @@ struct sway_xwayland_surface { | |||
28 | struct wl_listener request_resize; | 28 | struct wl_listener request_resize; |
29 | struct wl_listener request_maximize; | 29 | struct wl_listener request_maximize; |
30 | struct wl_listener request_configure; | 30 | struct wl_listener request_configure; |
31 | struct wl_listener unmap_notify; | ||
32 | struct wl_listener map_notify; | ||
31 | struct wl_listener destroy; | 33 | struct wl_listener destroy; |
32 | 34 | ||
33 | int pending_width, pending_height; | 35 | int pending_width, pending_height; |
@@ -91,6 +93,9 @@ struct sway_view { | |||
91 | double ox, double oy); | 93 | double ox, double oy); |
92 | void (*set_activated)(struct sway_view *view, bool activated); | 94 | void (*set_activated)(struct sway_view *view, bool activated); |
93 | } iface; | 95 | } iface; |
96 | |||
97 | // only used for unmanaged views (shell specific) | ||
98 | struct wl_list unmanaged_view_link; // sway_root::unmanaged views | ||
94 | }; | 99 | }; |
95 | 100 | ||
96 | #endif | 101 | #endif |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ec204c6f..21c8513f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -218,6 +218,19 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { | |||
218 | swayc_descendants_of_type( | 218 | swayc_descendants_of_type( |
219 | &root_container, C_VIEW, output_frame_view, soutput); | 219 | &root_container, C_VIEW, output_frame_view, soutput); |
220 | 220 | ||
221 | // render unmanaged views on top | ||
222 | struct sway_view *view; | ||
223 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, | ||
224 | unmanaged_view_link) { | ||
225 | if (view->type == SWAY_XWAYLAND_VIEW) { | ||
226 | // the only kind of unamanged view right now is xwayland override redirect | ||
227 | int view_x = view->wlr_xwayland_surface->x; | ||
228 | int view_y = view->wlr_xwayland_surface->y; | ||
229 | render_surface(view->surface, wlr_output, &soutput->last_frame, | ||
230 | view_x, view_y, 0); | ||
231 | } | ||
232 | } | ||
233 | |||
221 | wlr_renderer_end(server->renderer); | 234 | wlr_renderer_end(server->renderer); |
222 | wlr_output_swap_buffers(wlr_output); | 235 | wlr_output_swap_buffers(wlr_output); |
223 | 236 | ||
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 43bb2e00..0c0dbfff 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -93,13 +93,43 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
93 | static void handle_destroy(struct wl_listener *listener, void *data) { | 93 | static 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); |
99 | swayc_t *parent = destroy_view(sway_surface->view->swayc); | 100 | if (xsurface->override_redirect) { |
101 | if (xsurface->mapped) { | ||
102 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
103 | } | ||
104 | } else { | ||
105 | swayc_t *parent = destroy_view(sway_surface->view->swayc); | ||
106 | arrange_windows(parent, -1, -1); | ||
107 | } | ||
100 | free(sway_surface->view); | 108 | free(sway_surface->view); |
101 | free(sway_surface); | 109 | free(sway_surface); |
102 | arrange_windows(parent, -1, -1); | 110 | } |
111 | |||
112 | static void handle_unmap_notify(struct wl_listener *listener, void *data) { | ||
113 | // TODO take the view out of the tree | ||
114 | struct sway_xwayland_surface *sway_surface = | ||
115 | wl_container_of(listener, sway_surface, unmap_notify); | ||
116 | struct wlr_xwayland_surface *xsurface = data; | ||
117 | if (xsurface->override_redirect) { | ||
118 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
119 | } | ||
120 | sway_surface->view->surface = NULL; | ||
121 | } | ||
122 | |||
123 | static void handle_map_notify(struct wl_listener *listener, void *data) { | ||
124 | // TODO put the view back into the tree | ||
125 | struct sway_xwayland_surface *sway_surface = | ||
126 | wl_container_of(listener, sway_surface, map_notify); | ||
127 | struct wlr_xwayland_surface *xsurface = data; | ||
128 | if (xsurface->override_redirect) { | ||
129 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
130 | &sway_surface->view->unmanaged_view_link); | ||
131 | } | ||
132 | sway_surface->view->surface = xsurface->surface; | ||
103 | } | 133 | } |
104 | 134 | ||
105 | static void handle_configure_request(struct wl_listener *listener, void *data) { | 135 | static void handle_configure_request(struct wl_listener *listener, void *data) { |
@@ -119,11 +149,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
119 | listener, server, xwayland_surface); | 149 | listener, server, xwayland_surface); |
120 | struct wlr_xwayland_surface *xsurface = data; | 150 | struct wlr_xwayland_surface *xsurface = data; |
121 | 151 | ||
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'", | 152 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", |
128 | xsurface->title, xsurface->class); | 153 | xsurface->title, xsurface->class); |
129 | 154 | ||
@@ -155,15 +180,29 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
155 | // - Set new view to maximized so it behaves nicely | 180 | // - Set new view to maximized so it behaves nicely |
156 | // - Criteria | 181 | // - Criteria |
157 | 182 | ||
158 | sway_surface->commit.notify = handle_commit; | ||
159 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); | 183 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); |
160 | sway_surface->destroy.notify = handle_destroy; | 184 | sway_surface->commit.notify = handle_commit; |
185 | |||
161 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); | 186 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); |
162 | sway_surface->request_configure.notify = handle_configure_request; | 187 | sway_surface->destroy.notify = handle_destroy; |
188 | |||
163 | wl_signal_add(&xsurface->events.request_configure, | 189 | wl_signal_add(&xsurface->events.request_configure, |
164 | &sway_surface->request_configure); | 190 | &sway_surface->request_configure); |
191 | sway_surface->request_configure.notify = handle_configure_request; | ||
192 | |||
193 | wl_signal_add(&xsurface->events.unmap_notify, &sway_surface->unmap_notify); | ||
194 | sway_surface->unmap_notify.notify = handle_unmap_notify; | ||
195 | |||
196 | wl_signal_add(&xsurface->events.map_notify, &sway_surface->map_notify); | ||
197 | sway_surface->map_notify.notify = handle_map_notify; | ||
198 | |||
199 | if (xsurface->override_redirect) { | ||
200 | // these don't get a container in the tree | ||
201 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
202 | &sway_view->unmanaged_view_link); | ||
203 | return; | ||
204 | } | ||
165 | 205 | ||
166 | // TODO: actual focus semantics | ||
167 | swayc_t *parent = root_container.children->items[0]; | 206 | swayc_t *parent = root_container.children->items[0]; |
168 | parent = parent->children->items[0]; // workspace | 207 | parent = parent->children->items[0]; // workspace |
169 | 208 | ||
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 862406cf..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 | ||
209 | swayc_t *destroy_view(swayc_t *view) { | 209 | swayc_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); |
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; |