diff options
author | Tony Crisci <tony@dubstepdish.com> | 2018-01-15 10:19:49 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-15 10:19:49 -0500 |
commit | eb0f432a840dbe860b8c20f7a16e0281f9026326 (patch) | |
tree | a8b8e1a5a92a4203503ead496d8d50fd72fcf850 | |
parent | Merge pull request #1556 from martinetd/cleanup_logging (diff) | |
parent | xwm handle map and unmap (diff) | |
download | sway-eb0f432a840dbe860b8c20f7a16e0281f9026326.tar.gz sway-eb0f432a840dbe860b8c20f7a16e0281f9026326.tar.zst sway-eb0f432a840dbe860b8c20f7a16e0281f9026326.zip |
Merge pull request #1566 from acrisci/render-loop
Subsurfaces and popups
-rw-r--r-- | include/sway/layout.h | 2 | ||||
-rw-r--r-- | include/sway/view.h | 5 | ||||
-rw-r--r-- | sway/desktop/output.c | 248 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 6 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 87 | ||||
-rw-r--r-- | sway/input/cursor.c | 25 | ||||
-rw-r--r-- | sway/tree/container.c | 30 | ||||
-rw-r--r-- | sway/tree/layout.c | 1 |
8 files changed, 331 insertions, 73 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 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 | ||
18 | static 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; | 24 | static 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 | |||
38 | static 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]; | 122 | static 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 | 149 | static 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 | |||
177 | static 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 | ||
90 | static void output_frame_notify(struct wl_listener *listener, void *data) { | 214 | static 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) { | |||
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); |
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 | |||
115 | static 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 | |||
133 | static 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 | ||
105 | static void handle_configure_request(struct wl_listener *listener, void *data) { | 160 | static 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 | ||
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); |
@@ -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; |