diff options
-rw-r--r-- | include/sway/output.h | 1 | ||||
-rw-r--r-- | include/sway/tree/container.h | 5 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 2 | ||||
-rw-r--r-- | include/sway/tree/view.h | 59 | ||||
-rw-r--r-- | sway/desktop/output.c | 87 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 61 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 67 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 136 | ||||
-rw-r--r-- | sway/input/cursor.c | 11 | ||||
-rw-r--r-- | sway/tree/layout.c | 10 | ||||
-rw-r--r-- | sway/tree/output.c | 1 | ||||
-rw-r--r-- | sway/tree/view.c | 188 |
12 files changed, 355 insertions, 273 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index b343ecff..98d0f83f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -24,6 +24,7 @@ struct sway_output { | |||
24 | struct wl_listener destroy; | 24 | struct wl_listener destroy; |
25 | struct wl_listener mode; | 25 | struct wl_listener mode; |
26 | struct wl_listener transform; | 26 | struct wl_listener transform; |
27 | struct wl_listener scale; | ||
27 | 28 | ||
28 | struct wl_listener damage_destroy; | 29 | struct wl_listener damage_destroy; |
29 | struct wl_listener damage_frame; | 30 | struct wl_listener damage_frame; |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index aff2e58e..bd02197c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -70,9 +70,10 @@ struct sway_container { | |||
70 | enum sway_container_layout prev_layout; | 70 | enum sway_container_layout prev_layout; |
71 | enum sway_container_layout workspace_layout; | 71 | enum sway_container_layout workspace_layout; |
72 | 72 | ||
73 | // TODO convert to layout coordinates | 73 | // For C_ROOT, this has no meaning |
74 | // For C_OUTPUT, this is the output position in layout coordinates | ||
75 | // For other types, this is the position in output-local coordinates | ||
74 | double x, y; | 76 | double x, y; |
75 | |||
76 | // does not include borders or gaps. | 77 | // does not include borders or gaps. |
77 | double width, height; | 78 | double width, height; |
78 | 79 | ||
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index e1034657..a14152e8 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -20,7 +20,7 @@ struct sway_root { | |||
20 | 20 | ||
21 | struct wl_listener output_layout_change; | 21 | struct wl_listener output_layout_change; |
22 | 22 | ||
23 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link | 23 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link |
24 | 24 | ||
25 | struct { | 25 | struct { |
26 | struct wl_signal new_container; | 26 | struct wl_signal new_container; |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3965d2b7..4b84205e 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <wlr/types/wlr_surface.h> | 4 | #include <wlr/types/wlr_surface.h> |
5 | #include <wlr/types/wlr_xdg_shell_v6.h> | 5 | #include <wlr/types/wlr_xdg_shell_v6.h> |
6 | #include <wlr/xwayland.h> | 6 | #include <wlr/xwayland.h> |
7 | #include "sway/input/input-manager.h" | ||
8 | #include "sway/input/seat.h" | ||
7 | 9 | ||
8 | struct sway_container; | 10 | struct sway_container; |
9 | struct sway_view; | 11 | struct sway_view; |
@@ -37,6 +39,13 @@ struct sway_xwayland_surface { | |||
37 | int pending_width, pending_height; | 39 | int pending_width, pending_height; |
38 | }; | 40 | }; |
39 | 41 | ||
42 | struct sway_xwayland_unmanaged { | ||
43 | struct wlr_xwayland_surface *wlr_xwayland_surface; | ||
44 | struct wl_list link; | ||
45 | |||
46 | struct wl_listener destroy; | ||
47 | }; | ||
48 | |||
40 | struct sway_wl_shell_surface { | 49 | struct sway_wl_shell_surface { |
41 | struct sway_view *view; | 50 | struct sway_view *view; |
42 | 51 | ||
@@ -64,10 +73,21 @@ enum sway_view_prop { | |||
64 | VIEW_PROP_INSTANCE, | 73 | VIEW_PROP_INSTANCE, |
65 | }; | 74 | }; |
66 | 75 | ||
76 | struct sway_view_impl { | ||
77 | const char *(*get_prop)(struct sway_view *view, | ||
78 | enum sway_view_prop prop); | ||
79 | void (*configure)(struct sway_view *view, double ox, double oy, int width, | ||
80 | int height); | ||
81 | void (*set_activated)(struct sway_view *view, bool activated); | ||
82 | void (*close)(struct sway_view *view); | ||
83 | }; | ||
84 | |||
67 | struct sway_view { | 85 | struct sway_view { |
68 | enum sway_view_type type; | 86 | enum sway_view_type type; |
69 | struct sway_container *swayc; | 87 | const struct sway_view_impl *impl; |
70 | struct wlr_surface *surface; | 88 | |
89 | struct sway_container *swayc; // NULL for unmanaged views | ||
90 | struct wlr_surface *surface; // NULL for unmapped views | ||
71 | int width, height; | 91 | int width, height; |
72 | 92 | ||
73 | union { | 93 | union { |
@@ -82,21 +102,15 @@ struct sway_view { | |||
82 | struct sway_wl_shell_surface *sway_wl_shell_surface; | 102 | struct sway_wl_shell_surface *sway_wl_shell_surface; |
83 | }; | 103 | }; |
84 | 104 | ||
85 | struct { | ||
86 | const char *(*get_prop)(struct sway_view *view, | ||
87 | enum sway_view_prop prop); | ||
88 | void (*set_size)(struct sway_view *view, | ||
89 | int width, int height); | ||
90 | void (*set_position)(struct sway_view *view, | ||
91 | double ox, double oy); | ||
92 | void (*set_activated)(struct sway_view *view, bool activated); | ||
93 | void (*close)(struct sway_view *view); | ||
94 | } iface; | ||
95 | |||
96 | // only used for unmanaged views (shell specific) | 105 | // only used for unmanaged views (shell specific) |
97 | struct wl_list unmanaged_view_link; // sway_root::unmanaged views | 106 | struct wl_list unmanaged_view_link; // sway_root::unmanaged_views |
98 | }; | 107 | }; |
99 | 108 | ||
109 | struct sway_view *view_create(enum sway_view_type type, | ||
110 | const struct sway_view_impl *impl); | ||
111 | |||
112 | void view_destroy(struct sway_view *view); | ||
113 | |||
100 | const char *view_get_title(struct sway_view *view); | 114 | const char *view_get_title(struct sway_view *view); |
101 | 115 | ||
102 | const char *view_get_app_id(struct sway_view *view); | 116 | const char *view_get_app_id(struct sway_view *view); |
@@ -105,18 +119,25 @@ const char *view_get_class(struct sway_view *view); | |||
105 | 119 | ||
106 | const char *view_get_instance(struct sway_view *view); | 120 | const char *view_get_instance(struct sway_view *view); |
107 | 121 | ||
108 | void view_set_size(struct sway_view *view, int width, int height); | 122 | void view_configure(struct sway_view *view, double ox, double oy, int width, |
109 | 123 | int height); | |
110 | void view_set_position(struct sway_view *view, double ox, double oy); | ||
111 | 124 | ||
112 | void view_set_activated(struct sway_view *view, bool activated); | 125 | void view_set_activated(struct sway_view *view, bool activated); |
113 | 126 | ||
114 | void view_close(struct sway_view *view); | 127 | void view_close(struct sway_view *view); |
115 | 128 | ||
116 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before); | ||
117 | |||
118 | void view_damage_whole(struct sway_view *view); | 129 | void view_damage_whole(struct sway_view *view); |
119 | 130 | ||
120 | void view_damage_from(struct sway_view *view); | 131 | void view_damage_from(struct sway_view *view); |
121 | 132 | ||
133 | // view implementation | ||
134 | |||
135 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); | ||
136 | |||
137 | void view_unmap(struct sway_view *view); | ||
138 | |||
139 | void view_update_position(struct sway_view *view, double ox, double oy); | ||
140 | |||
141 | void view_update_size(struct sway_view *view, int width, int height); | ||
142 | |||
122 | #endif | 143 | #endif |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5e8a081c..10ed1f6d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /** | ||
43 | * Checks whether a surface at (lx, ly) intersects an output. If `box` is not | ||
44 | * NULL, it populates it with the surface box in the output, in output-local | ||
45 | * coordinates. | ||
46 | */ | ||
47 | static bool surface_intersect_output(struct wlr_surface *surface, | ||
48 | struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, | ||
49 | double lx, double ly, float rotation, struct wlr_box *box) { | ||
50 | double ox = lx, oy = ly; | ||
51 | wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); | ||
52 | |||
53 | if (box != NULL) { | ||
54 | box->x = ox * wlr_output->scale; | ||
55 | box->y = oy * wlr_output->scale; | ||
56 | box->width = surface->current->width * wlr_output->scale; | ||
57 | box->height = surface->current->height * wlr_output->scale; | ||
58 | } | ||
59 | |||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx, .y = ly, | ||
62 | .width = surface->current->width, .height = surface->current->height, | ||
63 | }; | ||
64 | wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); | ||
65 | return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); | ||
66 | } | ||
67 | |||
42 | static void render_surface(struct wlr_surface *surface, | 68 | static void render_surface(struct wlr_surface *surface, |
43 | struct wlr_output *wlr_output, struct timespec *when, | 69 | struct wlr_output *wlr_output, struct timespec *when, |
44 | double lx, double ly, float rotation) { | 70 | double lx, double ly, float rotation) { |
@@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface, | |||
48 | if (!wlr_surface_has_buffer(surface)) { | 74 | if (!wlr_surface_has_buffer(surface)) { |
49 | return; | 75 | return; |
50 | } | 76 | } |
77 | |||
51 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 78 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; |
52 | int width = surface->current->width; | 79 | |
53 | int height = surface->current->height; | 80 | struct wlr_box box; |
54 | int render_width = width * wlr_output->scale; | 81 | bool intersects = surface_intersect_output(surface, layout, wlr_output, |
55 | int render_height = height * wlr_output->scale; | 82 | lx, ly, rotation, &box); |
56 | int owidth, oheight; | 83 | if (intersects) { |
57 | wlr_output_effective_resolution(wlr_output, &owidth, &oheight); | ||
58 | |||
59 | // FIXME: view coords are inconsistently assumed to be in output or layout coords | ||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, | ||
62 | .width = render_width, .height = render_height, | ||
63 | }; | ||
64 | if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { | ||
65 | struct wlr_box render_box = { | ||
66 | .x = lx, .y = ly, | ||
67 | .width = render_width, .height = render_height | ||
68 | }; | ||
69 | float matrix[9]; | 84 | float matrix[9]; |
70 | wlr_matrix_project_box(matrix, &render_box, surface->current->transform, | 85 | enum wl_output_transform transform = |
71 | 0, wlr_output->transform_matrix); | 86 | wlr_output_transform_invert(surface->current->transform); |
72 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, | 87 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
73 | 1.0f); // TODO: configurable alpha | 88 | wlr_output->transform_matrix); |
89 | |||
90 | // TODO: configurable alpha | ||
91 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); | ||
74 | 92 | ||
75 | wlr_surface_send_frame_done(surface, when); | 93 | wlr_surface_send_frame_done(surface, when); |
76 | } | 94 | } |
@@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface, | |||
80 | struct wlr_surface_state *state = subsurface->surface->current; | 98 | struct wlr_surface_state *state = subsurface->surface->current; |
81 | double sx = state->subsurface_position.x; | 99 | double sx = state->subsurface_position.x; |
82 | double sy = state->subsurface_position.y; | 100 | double sy = state->subsurface_position.y; |
83 | double sw = state->buffer_width / state->scale; | 101 | rotate_child_position(&sx, &sy, state->width, state->height, |
84 | double sh = state->buffer_height / state->scale; | 102 | surface->current->width, surface->current->height, rotation); |
85 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); | ||
86 | 103 | ||
87 | render_surface(subsurface->surface, wlr_output, when, | 104 | render_surface(subsurface->surface, wlr_output, when, |
88 | lx + sx, ly + sy, rotation); | 105 | lx + sx, ly + sy, rotation); |
@@ -243,15 +260,15 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
243 | container_descendants(workspace, C_VIEW, render_view, &rdata); | 260 | container_descendants(workspace, C_VIEW, render_view, &rdata); |
244 | 261 | ||
245 | // render unmanaged views on top | 262 | // render unmanaged views on top |
246 | struct sway_view *view; | 263 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
247 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, | 264 | struct sway_xwayland_unmanaged *sway_surface; |
248 | unmanaged_view_link) { | 265 | wl_list_for_each(sway_surface, unmanaged, link) { |
249 | if (view->type != SWAY_XWAYLAND_VIEW) { | 266 | struct wlr_xwayland_surface *xsurface = |
267 | sway_surface->wlr_xwayland_surface; | ||
268 | if (xsurface->surface == NULL) { | ||
250 | continue; | 269 | continue; |
251 | } | 270 | } |
252 | 271 | ||
253 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
254 | |||
255 | const struct wlr_box view_box = { | 272 | const struct wlr_box view_box = { |
256 | .x = xsurface->x, | 273 | .x = xsurface->x, |
257 | .y = xsurface->y, | 274 | .y = xsurface->y, |
@@ -263,7 +280,7 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
263 | continue; | 280 | continue; |
264 | } | 281 | } |
265 | 282 | ||
266 | render_surface(view->surface, wlr_output, &output->last_frame, | 283 | render_surface(xsurface->surface, wlr_output, &output->last_frame, |
267 | view_box.x - output_box->x, view_box.y - output_box->y, 0); | 284 | view_box.x - output_box->x, view_box.y - output_box->y, 0); |
268 | } | 285 | } |
269 | 286 | ||
@@ -341,6 +358,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { | |||
341 | arrange_windows(output->swayc, -1, -1); | 358 | arrange_windows(output->swayc, -1, -1); |
342 | } | 359 | } |
343 | 360 | ||
361 | static void handle_scale(struct wl_listener *listener, void *data) { | ||
362 | struct sway_output *output = wl_container_of(listener, output, scale); | ||
363 | arrange_layers(output); | ||
364 | arrange_windows(output->swayc, -1, -1); | ||
365 | } | ||
366 | |||
344 | void handle_new_output(struct wl_listener *listener, void *data) { | 367 | void handle_new_output(struct wl_listener *listener, void *data) { |
345 | struct sway_server *server = wl_container_of(listener, server, new_output); | 368 | struct sway_server *server = wl_container_of(listener, server, new_output); |
346 | struct wlr_output *wlr_output = data; | 369 | struct wlr_output *wlr_output = data; |
@@ -381,6 +404,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
381 | output->mode.notify = handle_mode; | 404 | output->mode.notify = handle_mode; |
382 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 405 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
383 | output->transform.notify = handle_transform; | 406 | output->transform.notify = handle_transform; |
407 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
408 | output->scale.notify = handle_scale; | ||
384 | 409 | ||
385 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | 410 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); |
386 | output->damage_frame.notify = damage_handle_frame; | 411 | output->damage_frame.notify = damage_handle_frame; |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index c44fcf27..6528a397 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -30,28 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | static void set_size(struct sway_view *view, int width, int height) { | 33 | static void configure(struct sway_view *view, double ox, double oy, int width, |
34 | int height) { | ||
34 | if (!assert_wl_shell(view)) { | 35 | if (!assert_wl_shell(view)) { |
35 | return; | 36 | return; |
36 | } | 37 | } |
38 | view_update_position(view, ox, oy); | ||
37 | view->sway_wl_shell_surface->pending_width = width; | 39 | view->sway_wl_shell_surface->pending_width = width; |
38 | view->sway_wl_shell_surface->pending_height = height; | 40 | view->sway_wl_shell_surface->pending_height = height; |
39 | wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); | 41 | wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); |
40 | } | 42 | } |
41 | 43 | ||
42 | static void set_position(struct sway_view *view, double ox, double oy) { | 44 | static void _close(struct sway_view *view) { |
43 | if (!assert_wl_shell(view)) { | ||
44 | return; | ||
45 | } | ||
46 | view->swayc->x = ox; | ||
47 | view->swayc->y = oy; | ||
48 | } | ||
49 | |||
50 | static void set_activated(struct sway_view *view, bool activated) { | ||
51 | // no way to activate wl_shell | ||
52 | } | ||
53 | |||
54 | static void close(struct sway_view *view) { | ||
55 | if (!assert_wl_shell(view)) { | 45 | if (!assert_wl_shell(view)) { |
56 | return; | 46 | return; |
57 | } | 47 | } |
@@ -59,14 +49,20 @@ static void close(struct sway_view *view) { | |||
59 | wl_client_destroy(view->wlr_wl_shell_surface->client); | 49 | wl_client_destroy(view->wlr_wl_shell_surface->client); |
60 | } | 50 | } |
61 | 51 | ||
52 | static const struct sway_view_impl view_impl = { | ||
53 | .get_prop = get_prop, | ||
54 | .configure = configure, | ||
55 | .close = _close, | ||
56 | }; | ||
57 | |||
62 | static void handle_commit(struct wl_listener *listener, void *data) { | 58 | static void handle_commit(struct wl_listener *listener, void *data) { |
63 | struct sway_wl_shell_surface *sway_surface = | 59 | struct sway_wl_shell_surface *sway_surface = |
64 | wl_container_of(listener, sway_surface, commit); | 60 | wl_container_of(listener, sway_surface, commit); |
65 | struct sway_view *view = sway_surface->view; | 61 | struct sway_view *view = sway_surface->view; |
66 | // NOTE: We intentionally discard the view's desired width here | 62 | // NOTE: We intentionally discard the view's desired width here |
67 | // TODO: Let floating views do whatever | 63 | // TODO: Let floating views do whatever |
68 | view->width = sway_surface->pending_width; | 64 | view_update_size(view, sway_surface->pending_width, |
69 | view->height = sway_surface->pending_height; | 65 | sway_surface->pending_height); |
70 | view_damage_from(view); | 66 | view_damage_from(view); |
71 | } | 67 | } |
72 | 68 | ||
@@ -75,15 +71,13 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
75 | wl_container_of(listener, sway_surface, destroy); | 71 | wl_container_of(listener, sway_surface, destroy); |
76 | wl_list_remove(&sway_surface->commit.link); | 72 | wl_list_remove(&sway_surface->commit.link); |
77 | wl_list_remove(&sway_surface->destroy.link); | 73 | wl_list_remove(&sway_surface->destroy.link); |
78 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | 74 | view_destroy(sway_surface->view); |
79 | free(sway_surface->view); | ||
80 | free(sway_surface); | 75 | free(sway_surface); |
81 | arrange_windows(parent, -1, -1); | ||
82 | } | 76 | } |
83 | 77 | ||
84 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | 78 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { |
85 | struct sway_server *server = wl_container_of( | 79 | struct sway_server *server = wl_container_of(listener, server, |
86 | listener, server, wl_shell_surface); | 80 | wl_shell_surface); |
87 | struct wlr_wl_shell_surface *shell_surface = data; | 81 | struct wlr_wl_shell_surface *shell_surface = data; |
88 | 82 | ||
89 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { | 83 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { |
@@ -103,20 +97,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
103 | return; | 97 | return; |
104 | } | 98 | } |
105 | 99 | ||
106 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 100 | struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl); |
107 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 101 | if (!sway_assert(view, "Failed to allocate view")) { |
108 | return; | 102 | return; |
109 | } | 103 | } |
110 | sway_view->type = SWAY_WL_SHELL_VIEW; | 104 | view->wlr_wl_shell_surface = shell_surface; |
111 | sway_view->iface.get_prop = get_prop; | 105 | view->sway_wl_shell_surface = sway_surface; |
112 | sway_view->iface.set_size = set_size; | 106 | sway_surface->view = view; |
113 | sway_view->iface.set_position = set_position; | ||
114 | sway_view->iface.set_activated = set_activated; | ||
115 | sway_view->iface.close = close; | ||
116 | sway_view->wlr_wl_shell_surface = shell_surface; | ||
117 | sway_view->sway_wl_shell_surface = sway_surface; | ||
118 | sway_view->surface = shell_surface->surface; | ||
119 | sway_surface->view = sway_view; | ||
120 | 107 | ||
121 | // TODO: | 108 | // TODO: |
122 | // - Wire up listeners | 109 | // - Wire up listeners |
@@ -132,11 +119,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
132 | sway_surface->destroy.notify = handle_destroy; | 119 | sway_surface->destroy.notify = handle_destroy; |
133 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); | 120 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); |
134 | 121 | ||
135 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 122 | view_map(view, shell_surface->surface); |
136 | struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); | ||
137 | struct sway_container *cont = container_view_create(focus, sway_view); | ||
138 | sway_view->swayc = cont; | ||
139 | |||
140 | arrange_windows(cont->parent, -1, -1); | ||
141 | input_manager_set_focus(input_manager, cont); | ||
142 | } | 123 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index cffe83fb..49305b39 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -30,23 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | static void set_size(struct sway_view *view, int width, int height) { | 33 | static void configure(struct sway_view *view, double ox, double oy, int width, |
34 | int height) { | ||
34 | if (!assert_xdg(view)) { | 35 | if (!assert_xdg(view)) { |
35 | return; | 36 | return; |
36 | } | 37 | } |
38 | |||
39 | view_update_position(view, ox, oy); | ||
37 | view->sway_xdg_surface_v6->pending_width = width; | 40 | view->sway_xdg_surface_v6->pending_width = width; |
38 | view->sway_xdg_surface_v6->pending_height = height; | 41 | view->sway_xdg_surface_v6->pending_height = height; |
39 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); | 42 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); |
40 | } | 43 | } |
41 | 44 | ||
42 | static void set_position(struct sway_view *view, double ox, double oy) { | ||
43 | if (!assert_xdg(view)) { | ||
44 | return; | ||
45 | } | ||
46 | view->swayc->x = ox; | ||
47 | view->swayc->y = oy; | ||
48 | } | ||
49 | |||
50 | static void set_activated(struct sway_view *view, bool activated) { | 45 | static void set_activated(struct sway_view *view, bool activated) { |
51 | if (!assert_xdg(view)) { | 46 | if (!assert_xdg(view)) { |
52 | return; | 47 | return; |
@@ -57,7 +52,7 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
57 | } | 52 | } |
58 | } | 53 | } |
59 | 54 | ||
60 | static void close(struct sway_view *view) { | 55 | static void _close(struct sway_view *view) { |
61 | if (!assert_xdg(view)) { | 56 | if (!assert_xdg(view)) { |
62 | return; | 57 | return; |
63 | } | 58 | } |
@@ -67,6 +62,13 @@ static void close(struct sway_view *view) { | |||
67 | } | 62 | } |
68 | } | 63 | } |
69 | 64 | ||
65 | static const struct sway_view_impl view_impl = { | ||
66 | .get_prop = get_prop, | ||
67 | .configure = configure, | ||
68 | .set_activated = set_activated, | ||
69 | .close = _close, | ||
70 | }; | ||
71 | |||
70 | static void handle_commit(struct wl_listener *listener, void *data) { | 72 | static void handle_commit(struct wl_listener *listener, void *data) { |
71 | struct sway_xdg_surface_v6 *sway_surface = | 73 | struct sway_xdg_surface_v6 *sway_surface = |
72 | wl_container_of(listener, sway_surface, commit); | 74 | wl_container_of(listener, sway_surface, commit); |
@@ -74,37 +76,22 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
74 | // NOTE: We intentionally discard the view's desired width here | 76 | // NOTE: We intentionally discard the view's desired width here |
75 | // TODO: Store this for restoration when moving to floating plane | 77 | // TODO: Store this for restoration when moving to floating plane |
76 | // TODO: Let floating views do whatever | 78 | // TODO: Let floating views do whatever |
77 | view->width = sway_surface->pending_width; | 79 | view_update_size(view, sway_surface->pending_width, |
78 | view->height = sway_surface->pending_height; | 80 | sway_surface->pending_height); |
79 | view_damage_from(view); | 81 | view_damage_from(view); |
80 | } | 82 | } |
81 | 83 | ||
82 | static void handle_unmap(struct wl_listener *listener, void *data) { | 84 | static void handle_unmap(struct wl_listener *listener, void *data) { |
83 | struct sway_xdg_surface_v6 *sway_surface = | 85 | struct sway_xdg_surface_v6 *sway_surface = |
84 | wl_container_of(listener, sway_surface, unmap); | 86 | wl_container_of(listener, sway_surface, unmap); |
85 | view_damage_whole(sway_surface->view); | 87 | view_unmap(sway_surface->view); |
86 | container_view_destroy(sway_surface->view->swayc); | ||
87 | sway_surface->view->swayc = NULL; | ||
88 | sway_surface->view->surface = NULL; | ||
89 | } | 88 | } |
90 | 89 | ||
91 | static void handle_map(struct wl_listener *listener, void *data) { | 90 | static void handle_map(struct wl_listener *listener, void *data) { |
92 | struct sway_xdg_surface_v6 *sway_surface = | 91 | struct sway_xdg_surface_v6 *sway_surface = |
93 | wl_container_of(listener, sway_surface, map); | 92 | wl_container_of(listener, sway_surface, map); |
94 | struct sway_view *view = sway_surface->view; | 93 | struct sway_view *view = sway_surface->view; |
95 | 94 | view_map(view, view->wlr_xdg_surface_v6->surface); | |
96 | sway_surface->view->surface = view->wlr_xdg_surface_v6->surface; | ||
97 | |||
98 | container_view_destroy(view->swayc); | ||
99 | |||
100 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
101 | struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); | ||
102 | struct sway_container *cont = container_view_create(focus, view); | ||
103 | view->swayc = cont; | ||
104 | arrange_windows(cont->parent, -1, -1); | ||
105 | input_manager_set_focus(input_manager, cont); | ||
106 | |||
107 | view_damage_whole(sway_surface->view); | ||
108 | } | 95 | } |
109 | 96 | ||
110 | static void handle_destroy(struct wl_listener *listener, void *data) { | 97 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -112,8 +99,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
112 | wl_container_of(listener, sway_xdg_surface, destroy); | 99 | wl_container_of(listener, sway_xdg_surface, destroy); |
113 | wl_list_remove(&sway_xdg_surface->commit.link); | 100 | wl_list_remove(&sway_xdg_surface->commit.link); |
114 | wl_list_remove(&sway_xdg_surface->destroy.link); | 101 | wl_list_remove(&sway_xdg_surface->destroy.link); |
115 | container_view_destroy(sway_xdg_surface->view->swayc); | 102 | wl_list_remove(&sway_xdg_surface->map.link); |
116 | free(sway_xdg_surface->view); | 103 | wl_list_remove(&sway_xdg_surface->unmap.link); |
104 | view_destroy(sway_xdg_surface->view); | ||
117 | free(sway_xdg_surface); | 105 | free(sway_xdg_surface); |
118 | } | 106 | } |
119 | 107 | ||
@@ -138,23 +126,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
138 | return; | 126 | return; |
139 | } | 127 | } |
140 | 128 | ||
141 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 129 | struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl); |
142 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 130 | if (!sway_assert(view, "Failed to allocate view")) { |
143 | return; | 131 | return; |
144 | } | 132 | } |
145 | sway_view->type = SWAY_XDG_SHELL_V6_VIEW; | 133 | view->wlr_xdg_surface_v6 = xdg_surface; |
146 | sway_view->iface.get_prop = get_prop; | 134 | view->sway_xdg_surface_v6 = sway_surface; |
147 | sway_view->iface.set_size = set_size; | 135 | sway_surface->view = view; |
148 | sway_view->iface.set_position = set_position; | ||
149 | sway_view->iface.set_activated = set_activated; | ||
150 | sway_view->iface.close = close; | ||
151 | sway_view->wlr_xdg_surface_v6 = xdg_surface; | ||
152 | sway_view->sway_xdg_surface_v6 = sway_surface; | ||
153 | sway_surface->view = sway_view; | ||
154 | 136 | ||
155 | // TODO: | 137 | // TODO: |
156 | // - Look up pid and open on appropriate workspace | 138 | // - Look up pid and open on appropriate workspace |
157 | // - Set new view to maximized so it behaves nicely | ||
158 | // - Criteria | 139 | // - Criteria |
159 | 140 | ||
160 | sway_surface->commit.notify = handle_commit; | 141 | sway_surface->commit.notify = handle_commit; |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 17f827d9..bfef68cf 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -14,6 +14,33 @@ | |||
14 | #include "sway/input/input-manager.h" | 14 | #include "sway/input/input-manager.h" |
15 | #include "log.h" | 15 | #include "log.h" |
16 | 16 | ||
17 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { | ||
18 | struct sway_xwayland_unmanaged *sway_surface = | ||
19 | wl_container_of(listener, sway_surface, destroy); | ||
20 | wl_list_remove(&sway_surface->destroy.link); | ||
21 | wl_list_remove(&sway_surface->link); | ||
22 | free(sway_surface); | ||
23 | } | ||
24 | |||
25 | static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { | ||
26 | struct sway_xwayland_unmanaged *sway_surface = | ||
27 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | ||
28 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | sway_surface->wlr_xwayland_surface = xsurface; | ||
33 | |||
34 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); | ||
35 | sway_surface->destroy.notify = unmanaged_handle_destroy; | ||
36 | |||
37 | wl_list_insert(&root_container.sway_root->xwayland_unmanaged, | ||
38 | &sway_surface->link); | ||
39 | |||
40 | // TODO: damage tracking | ||
41 | } | ||
42 | |||
43 | |||
17 | static bool assert_xwayland(struct sway_view *view) { | 44 | static bool assert_xwayland(struct sway_view *view) { |
18 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, | 45 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, |
19 | "Expected xwayland view!"); | 46 | "Expected xwayland view!"); |
@@ -33,22 +60,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
33 | } | 60 | } |
34 | } | 61 | } |
35 | 62 | ||
36 | static void set_size(struct sway_view *view, int width, int height) { | 63 | static void configure(struct sway_view *view, double ox, double oy, int width, |
64 | int height) { | ||
37 | if (!assert_xwayland(view)) { | 65 | if (!assert_xwayland(view)) { |
38 | return; | 66 | return; |
39 | } | 67 | } |
40 | view->sway_xwayland_surface->pending_width = width; | ||
41 | view->sway_xwayland_surface->pending_height = height; | ||
42 | |||
43 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 68 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
44 | wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y, | ||
45 | width, height); | ||
46 | } | ||
47 | 69 | ||
48 | static void set_position(struct sway_view *view, double ox, double oy) { | ||
49 | if (!assert_xwayland(view)) { | ||
50 | return; | ||
51 | } | ||
52 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 70 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
53 | if (!sway_assert(output, "view must be within tree to set position")) { | 71 | if (!sway_assert(output, "view must be within tree to set position")) { |
54 | return; | 72 | return; |
@@ -64,13 +82,12 @@ static void set_position(struct sway_view *view, double ox, double oy) { | |||
64 | return; | 82 | return; |
65 | } | 83 | } |
66 | 84 | ||
67 | view->swayc->x = ox; | 85 | view_update_position(view, ox, oy); |
68 | view->swayc->y = oy; | ||
69 | 86 | ||
70 | wlr_xwayland_surface_configure(view->wlr_xwayland_surface, | 87 | view->sway_xwayland_surface->pending_width = width; |
71 | ox + loutput->x, oy + loutput->y, | 88 | view->sway_xwayland_surface->pending_height = height; |
72 | view->wlr_xwayland_surface->width, | 89 | wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, |
73 | view->wlr_xwayland_surface->height); | 90 | width, height); |
74 | } | 91 | } |
75 | 92 | ||
76 | static void set_activated(struct sway_view *view, bool activated) { | 93 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -81,77 +98,58 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
81 | wlr_xwayland_surface_activate(surface, activated); | 98 | wlr_xwayland_surface_activate(surface, activated); |
82 | } | 99 | } |
83 | 100 | ||
84 | static void close_view(struct sway_view *view) { | 101 | static void _close(struct sway_view *view) { |
85 | if (!assert_xwayland(view)) { | 102 | if (!assert_xwayland(view)) { |
86 | return; | 103 | return; |
87 | } | 104 | } |
88 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); | 105 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); |
89 | } | 106 | } |
90 | 107 | ||
108 | static const struct sway_view_impl view_impl = { | ||
109 | .get_prop = get_prop, | ||
110 | .configure = configure, | ||
111 | .set_activated = set_activated, | ||
112 | .close = _close, | ||
113 | }; | ||
114 | |||
91 | static void handle_commit(struct wl_listener *listener, void *data) { | 115 | static void handle_commit(struct wl_listener *listener, void *data) { |
92 | struct sway_xwayland_surface *sway_surface = | 116 | struct sway_xwayland_surface *sway_surface = |
93 | wl_container_of(listener, sway_surface, commit); | 117 | wl_container_of(listener, sway_surface, commit); |
94 | struct sway_view *view = sway_surface->view; | 118 | struct sway_view *view = sway_surface->view; |
95 | // NOTE: We intentionally discard the view's desired width here | 119 | // NOTE: We intentionally discard the view's desired width here |
96 | // TODO: Let floating views do whatever | 120 | // TODO: Let floating views do whatever |
97 | view->width = sway_surface->pending_width; | 121 | view_update_size(view, sway_surface->pending_width, |
98 | view->height = sway_surface->pending_height; | 122 | sway_surface->pending_height); |
99 | view_damage_from(view); | 123 | view_damage_from(view); |
100 | } | 124 | } |
101 | 125 | ||
102 | static void handle_destroy(struct wl_listener *listener, void *data) { | 126 | static void handle_destroy(struct wl_listener *listener, void *data) { |
103 | struct sway_xwayland_surface *sway_surface = | 127 | struct sway_xwayland_surface *sway_surface = |
104 | wl_container_of(listener, sway_surface, destroy); | 128 | wl_container_of(listener, sway_surface, destroy); |
105 | |||
106 | wl_list_remove(&sway_surface->commit.link); | 129 | wl_list_remove(&sway_surface->commit.link); |
107 | wl_list_remove(&sway_surface->destroy.link); | 130 | wl_list_remove(&sway_surface->destroy.link); |
108 | wl_list_remove(&sway_surface->request_configure.link); | 131 | wl_list_remove(&sway_surface->request_configure.link); |
109 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 132 | wl_list_remove(&sway_surface->map.link); |
110 | container_view_destroy(sway_surface->view->swayc); | 133 | wl_list_remove(&sway_surface->unmap.link); |
111 | sway_surface->view->swayc = NULL; | 134 | view_destroy(sway_surface->view); |
112 | sway_surface->view->surface = NULL; | 135 | free(sway_surface); |
113 | } | 136 | } |
114 | 137 | ||
115 | static void handle_unmap(struct wl_listener *listener, void *data) { | 138 | static void handle_unmap(struct wl_listener *listener, void *data) { |
116 | struct sway_xwayland_surface *sway_surface = | 139 | struct sway_xwayland_surface *sway_surface = |
117 | wl_container_of(listener, sway_surface, unmap); | 140 | wl_container_of(listener, sway_surface, unmap); |
118 | view_damage_whole(sway_surface->view); | 141 | view_unmap(sway_surface->view); |
119 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
120 | wl_list_init(&sway_surface->view->unmanaged_view_link); | ||
121 | container_view_destroy(sway_surface->view->swayc); | ||
122 | sway_surface->view->swayc = NULL; | ||
123 | sway_surface->view->surface = NULL; | ||
124 | } | 142 | } |
125 | 143 | ||
126 | static void handle_map(struct wl_listener *listener, void *data) { | 144 | static void handle_map(struct wl_listener *listener, void *data) { |
127 | struct sway_xwayland_surface *sway_surface = | 145 | struct sway_xwayland_surface *sway_surface = |
128 | wl_container_of(listener, sway_surface, map); | 146 | wl_container_of(listener, sway_surface, map); |
129 | struct wlr_xwayland_surface *xsurface = data; | 147 | struct wlr_xwayland_surface *xsurface = data; |
130 | 148 | struct sway_view *view = sway_surface->view; | |
131 | sway_surface->view->surface = xsurface->surface; | ||
132 | 149 | ||
133 | // put it back into the tree | 150 | // put it back into the tree |
134 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | 151 | wlr_xwayland_surface_set_maximized(xsurface, true); |
135 | xsurface->override_redirect) { | 152 | view_map(view, xsurface->surface); |
136 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
137 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
138 | &sway_surface->view->unmanaged_view_link); | ||
139 | } else { | ||
140 | struct sway_view *view = sway_surface->view; | ||
141 | container_view_destroy(view->swayc); | ||
142 | |||
143 | wlr_xwayland_surface_set_maximized(xsurface, true); | ||
144 | |||
145 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
146 | struct sway_container *focus = seat_get_focus_inactive(seat, | ||
147 | &root_container); | ||
148 | struct sway_container *cont = container_view_create(focus, view); | ||
149 | view->swayc = cont; | ||
150 | arrange_windows(cont->parent, -1, -1); | ||
151 | input_manager_set_focus(input_manager, cont); | ||
152 | } | ||
153 | |||
154 | view_damage_whole(sway_surface->view); | ||
155 | } | 153 | } |
156 | 154 | ||
157 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 155 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
@@ -171,34 +169,32 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
171 | listener, server, xwayland_surface); | 169 | listener, server, xwayland_surface); |
172 | struct wlr_xwayland_surface *xsurface = data; | 170 | struct wlr_xwayland_surface *xsurface = data; |
173 | 171 | ||
172 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | ||
173 | xsurface->override_redirect) { | ||
174 | wlr_log(L_DEBUG, "New xwayland unmanaged surface"); | ||
175 | create_unmanaged(xsurface); | ||
176 | return; | ||
177 | } | ||
178 | |||
174 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", | 179 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", |
175 | xsurface->title, xsurface->class); | 180 | xsurface->title, xsurface->class); |
176 | 181 | ||
177 | struct sway_xwayland_surface *sway_surface = | 182 | struct sway_xwayland_surface *sway_surface = |
178 | calloc(1, sizeof(struct sway_xwayland_surface)); | 183 | calloc(1, sizeof(struct sway_xwayland_surface)); |
179 | if (!sway_assert(sway_surface, "Failed to allocate surface!")) { | 184 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { |
180 | return; | 185 | return; |
181 | } | 186 | } |
182 | 187 | ||
183 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 188 | struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); |
184 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 189 | if (!sway_assert(view, "Failed to allocate view")) { |
185 | return; | 190 | return; |
186 | } | 191 | } |
187 | sway_view->type = SWAY_XWAYLAND_VIEW; | 192 | view->wlr_xwayland_surface = xsurface; |
188 | sway_view->iface.get_prop = get_prop; | 193 | view->sway_xwayland_surface = sway_surface; |
189 | sway_view->iface.set_size = set_size; | 194 | sway_surface->view = view; |
190 | sway_view->iface.set_position = set_position; | ||
191 | sway_view->iface.set_activated = set_activated; | ||
192 | sway_view->iface.close = close_view; | ||
193 | sway_view->wlr_xwayland_surface = xsurface; | ||
194 | sway_view->sway_xwayland_surface = sway_surface; | ||
195 | sway_surface->view = sway_view; | ||
196 | |||
197 | wl_list_init(&sway_view->unmanaged_view_link); | ||
198 | 195 | ||
199 | // TODO: | 196 | // TODO: |
200 | // - Look up pid and open on appropriate workspace | 197 | // - Look up pid and open on appropriate workspace |
201 | // - Set new view to maximized so it behaves nicely | ||
202 | // - Criteria | 198 | // - Criteria |
203 | 199 | ||
204 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); | 200 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 7d05e942..97b4473c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -47,14 +47,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output, | |||
47 | static struct sway_container *container_at_cursor(struct sway_cursor *cursor, | 47 | static struct sway_container *container_at_cursor(struct sway_cursor *cursor, |
48 | struct wlr_surface **surface, double *sx, double *sy) { | 48 | struct wlr_surface **surface, double *sx, double *sy) { |
49 | // check for unmanaged views first | 49 | // check for unmanaged views first |
50 | struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; | 50 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
51 | struct sway_view *view; | 51 | struct sway_xwayland_unmanaged *sway_surface; |
52 | wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { | 52 | wl_list_for_each_reverse(sway_surface, unmanaged, link) { |
53 | if (view->type != SWAY_XWAYLAND_VIEW) { | 53 | struct wlr_xwayland_surface *xsurface = |
54 | sway_surface->wlr_xwayland_surface; | ||
55 | if (xsurface->surface == NULL) { | ||
54 | continue; | 56 | continue; |
55 | } | 57 | } |
56 | 58 | ||
57 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
58 | struct wlr_box box = { | 59 | struct wlr_box box = { |
59 | .x = xsurface->x, | 60 | .x = xsurface->x, |
60 | .y = xsurface->y, | 61 | .y = xsurface->y, |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 62ae0603..3333f9f1 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -57,7 +57,7 @@ void layout_init(void) { | |||
57 | 57 | ||
58 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | 58 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); |
59 | root_container.sway_root->output_layout = wlr_output_layout_create(); | 59 | root_container.sway_root->output_layout = wlr_output_layout_create(); |
60 | wl_list_init(&root_container.sway_root->unmanaged_views); | 60 | wl_list_init(&root_container.sway_root->xwayland_unmanaged); |
61 | wl_signal_init(&root_container.sway_root->events.new_container); | 61 | wl_signal_init(&root_container.sway_root->events.new_container); |
62 | 62 | ||
63 | root_container.sway_root->output_layout_change.notify = | 63 | root_container.sway_root->output_layout_change.notify = |
@@ -287,7 +287,7 @@ void arrange_windows(struct sway_container *container, | |||
287 | { | 287 | { |
288 | container->width = width; | 288 | container->width = width; |
289 | container->height = height; | 289 | container->height = height; |
290 | view_set_size(container->sway_view, | 290 | view_configure(container->sway_view, container->x, container->y, |
291 | container->width, container->height); | 291 | container->width, container->height); |
292 | wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", | 292 | wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", |
293 | container->width, container->height, | 293 | container->width, container->height, |
@@ -348,7 +348,8 @@ static void apply_horiz_layout(struct sway_container *container, | |||
348 | wlr_log(L_DEBUG, | 348 | wlr_log(L_DEBUG, |
349 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 349 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
350 | child, child->type, width, scale); | 350 | child, child->type, width, scale); |
351 | view_set_position(child->sway_view, child_x, y); | 351 | view_configure(child->sway_view, child_x, y, child->width, |
352 | child->height); | ||
352 | 353 | ||
353 | if (i == end - 1) { | 354 | if (i == end - 1) { |
354 | double remaining_width = x + width - child_x; | 355 | double remaining_width = x + width - child_x; |
@@ -399,7 +400,8 @@ void apply_vert_layout(struct sway_container *container, | |||
399 | wlr_log(L_DEBUG, | 400 | wlr_log(L_DEBUG, |
400 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 401 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
401 | child, child->type, height, scale); | 402 | child, child->type, height, scale); |
402 | view_set_position(child->sway_view, x, child_y); | 403 | view_configure(child->sway_view, x, child_y, child->width, |
404 | child->height); | ||
403 | 405 | ||
404 | if (i == end - 1) { | 406 | if (i == end - 1) { |
405 | double remaining_height = y + height - child_y; | 407 | double remaining_height = y + height - child_y; |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 2331dc2b..0509db23 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -30,6 +30,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) { | |||
30 | wl_list_remove(&output->sway_output->destroy.link); | 30 | wl_list_remove(&output->sway_output->destroy.link); |
31 | wl_list_remove(&output->sway_output->mode.link); | 31 | wl_list_remove(&output->sway_output->mode.link); |
32 | wl_list_remove(&output->sway_output->transform.link); | 32 | wl_list_remove(&output->sway_output->transform.link); |
33 | wl_list_remove(&output->sway_output->scale.link); | ||
33 | 34 | ||
34 | wl_list_remove(&output->sway_output->damage_destroy.link); | 35 | wl_list_remove(&output->sway_output->damage_destroy.link); |
35 | wl_list_remove(&output->sway_output->damage_frame.link); | 36 | wl_list_remove(&output->sway_output->damage_frame.link); |
diff --git a/sway/tree/view.c b/sway/tree/view.c index b7d1a41b..09c804e4 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <stdlib.h> | ||
1 | #include <wayland-server.h> | 2 | #include <wayland-server.h> |
2 | #include <wlr/types/wlr_output_layout.h> | 3 | #include <wlr/types/wlr_output_layout.h> |
3 | #include "log.h" | 4 | #include "log.h" |
@@ -6,82 +7,117 @@ | |||
6 | #include "sway/tree/layout.h" | 7 | #include "sway/tree/layout.h" |
7 | #include "sway/tree/view.h" | 8 | #include "sway/tree/view.h" |
8 | 9 | ||
10 | struct sway_view *view_create(enum sway_view_type type, | ||
11 | const struct sway_view_impl *impl) { | ||
12 | struct sway_view *view = calloc(1, sizeof(struct sway_view)); | ||
13 | if (view == NULL) { | ||
14 | return NULL; | ||
15 | } | ||
16 | view->type = type; | ||
17 | view->impl = impl; | ||
18 | return view; | ||
19 | } | ||
20 | |||
21 | void view_destroy(struct sway_view *view) { | ||
22 | if (view == NULL) { | ||
23 | return; | ||
24 | } | ||
25 | |||
26 | if (view->surface != NULL) { | ||
27 | view_unmap(view); | ||
28 | } | ||
29 | |||
30 | container_view_destroy(view->swayc); | ||
31 | free(view); | ||
32 | } | ||
33 | |||
9 | const char *view_get_title(struct sway_view *view) { | 34 | const char *view_get_title(struct sway_view *view) { |
10 | if (view->iface.get_prop) { | 35 | if (view->impl->get_prop) { |
11 | return view->iface.get_prop(view, VIEW_PROP_TITLE); | 36 | return view->impl->get_prop(view, VIEW_PROP_TITLE); |
12 | } | 37 | } |
13 | return NULL; | 38 | return NULL; |
14 | } | 39 | } |
15 | 40 | ||
16 | const char *view_get_app_id(struct sway_view *view) { | 41 | const char *view_get_app_id(struct sway_view *view) { |
17 | if (view->iface.get_prop) { | 42 | if (view->impl->get_prop) { |
18 | return view->iface.get_prop(view, VIEW_PROP_APP_ID); | 43 | return view->impl->get_prop(view, VIEW_PROP_APP_ID); |
19 | } | 44 | } |
20 | return NULL; | 45 | return NULL; |
21 | } | 46 | } |
22 | 47 | ||
23 | const char *view_get_class(struct sway_view *view) { | 48 | const char *view_get_class(struct sway_view *view) { |
24 | if (view->iface.get_prop) { | 49 | if (view->impl->get_prop) { |
25 | return view->iface.get_prop(view, VIEW_PROP_CLASS); | 50 | return view->impl->get_prop(view, VIEW_PROP_CLASS); |
26 | } | 51 | } |
27 | return NULL; | 52 | return NULL; |
28 | } | 53 | } |
29 | 54 | ||
30 | const char *view_get_instance(struct sway_view *view) { | 55 | const char *view_get_instance(struct sway_view *view) { |
31 | if (view->iface.get_prop) { | 56 | if (view->impl->get_prop) { |
32 | return view->iface.get_prop(view, VIEW_PROP_INSTANCE); | 57 | return view->impl->get_prop(view, VIEW_PROP_INSTANCE); |
33 | } | 58 | } |
34 | return NULL; | 59 | return NULL; |
35 | } | 60 | } |
36 | 61 | ||
37 | void view_set_size(struct sway_view *view, int width, int height) { | 62 | void view_configure(struct sway_view *view, double ox, double oy, int width, |
38 | if (view->iface.set_size) { | 63 | int height) { |
39 | struct wlr_box box = { | 64 | if (view->impl->configure) { |
40 | .x = view->swayc->x, | 65 | view->impl->configure(view, ox, oy, width, height); |
41 | .y = view->swayc->y, | ||
42 | .width = view->width, | ||
43 | .height = view->height, | ||
44 | }; | ||
45 | view->iface.set_size(view, width, height); | ||
46 | view_update_outputs(view, &box); | ||
47 | } | 66 | } |
48 | } | 67 | } |
49 | 68 | ||
50 | // TODO make view coordinates in layout coordinates | 69 | void view_set_activated(struct sway_view *view, bool activated) { |
51 | void view_set_position(struct sway_view *view, double ox, double oy) { | 70 | if (view->impl->set_activated) { |
52 | if (view->iface.set_position) { | 71 | view->impl->set_activated(view, activated); |
53 | struct wlr_box box = { | ||
54 | .x = view->swayc->x, | ||
55 | .y = view->swayc->y, | ||
56 | .width = view->width, | ||
57 | .height = view->height, | ||
58 | }; | ||
59 | view->iface.set_position(view, ox, oy); | ||
60 | view_update_outputs(view, &box); | ||
61 | } | 72 | } |
62 | } | 73 | } |
63 | 74 | ||
64 | void view_set_activated(struct sway_view *view, bool activated) { | 75 | void view_close(struct sway_view *view) { |
65 | if (view->iface.set_activated) { | 76 | if (view->impl->close) { |
66 | view->iface.set_activated(view, activated); | 77 | view->impl->close(view); |
67 | } | 78 | } |
68 | } | 79 | } |
69 | 80 | ||
70 | void view_close(struct sway_view *view) { | 81 | struct sway_container *container_view_destroy(struct sway_container *view) { |
71 | if (view->iface.close) { | 82 | if (!view) { |
72 | view->iface.close(view); | 83 | return NULL; |
73 | } | 84 | } |
85 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
86 | struct sway_container *parent = container_destroy(view); | ||
87 | arrange_windows(parent, -1, -1); | ||
88 | return parent; | ||
89 | } | ||
90 | |||
91 | void view_damage_whole(struct sway_view *view) { | ||
92 | for (int i = 0; i < root_container.children->length; ++i) { | ||
93 | struct sway_container *cont = root_container.children->items[i]; | ||
94 | if (cont->type == C_OUTPUT) { | ||
95 | output_damage_whole_view(cont->sway_output, view); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | void view_damage_from(struct sway_view *view) { | ||
101 | // TODO | ||
102 | view_damage_whole(view); | ||
103 | } | ||
104 | |||
105 | static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { | ||
106 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | ||
107 | |||
108 | box->x = output->x + view->swayc->x; | ||
109 | box->y = output->y + view->swayc->y; | ||
110 | box->width = view->width; | ||
111 | box->height = view->height; | ||
74 | } | 112 | } |
75 | 113 | ||
76 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | 114 | static void view_update_outputs(struct sway_view *view, |
115 | const struct wlr_box *before) { | ||
116 | struct wlr_box box; | ||
117 | view_get_layout_box(view, &box); | ||
118 | |||
77 | struct wlr_output_layout *output_layout = | 119 | struct wlr_output_layout *output_layout = |
78 | root_container.sway_root->output_layout; | 120 | root_container.sway_root->output_layout; |
79 | struct wlr_box box = { | ||
80 | .x = view->swayc->x, | ||
81 | .y = view->swayc->y, | ||
82 | .width = view->width, | ||
83 | .height = view->height, | ||
84 | }; | ||
85 | struct wlr_output_layout_output *layout_output; | 121 | struct wlr_output_layout_output *layout_output; |
86 | wl_list_for_each(layout_output, &output_layout->outputs, link) { | 122 | wl_list_for_each(layout_output, &output_layout->outputs, link) { |
87 | bool intersected = before != NULL && wlr_output_layout_intersects( | 123 | bool intersected = before != NULL && wlr_output_layout_intersects( |
@@ -97,27 +133,63 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | |||
97 | } | 133 | } |
98 | } | 134 | } |
99 | 135 | ||
100 | struct sway_container *container_view_destroy(struct sway_container *view) { | 136 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
101 | if (!view) { | 137 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
102 | return NULL; | 138 | return; |
103 | } | 139 | } |
104 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | 140 | |
105 | struct sway_container *parent = container_destroy(view); | 141 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
106 | arrange_windows(parent, -1, -1); | 142 | struct sway_container *focus = seat_get_focus_inactive(seat, |
107 | return parent; | 143 | &root_container); |
144 | struct sway_container *cont = container_view_create(focus, view); | ||
145 | |||
146 | view->surface = wlr_surface; | ||
147 | view->swayc = cont; | ||
148 | |||
149 | arrange_windows(cont->parent, -1, -1); | ||
150 | input_manager_set_focus(input_manager, cont); | ||
151 | |||
152 | view_damage_whole(view); | ||
153 | view_update_outputs(view, NULL); | ||
108 | } | 154 | } |
109 | 155 | ||
110 | void view_damage_whole(struct sway_view *view) { | 156 | void view_unmap(struct sway_view *view) { |
111 | struct sway_container *cont = NULL; | 157 | if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { |
112 | for (int i = 0; i < root_container.children->length; ++i) { | 158 | return; |
113 | cont = root_container.children->items[i]; | ||
114 | if (cont->type == C_OUTPUT) { | ||
115 | output_damage_whole_view(cont->sway_output, view); | ||
116 | } | ||
117 | } | 159 | } |
160 | |||
161 | view_damage_whole(view); | ||
162 | |||
163 | container_view_destroy(view->swayc); | ||
164 | |||
165 | view->swayc = NULL; | ||
166 | view->surface = NULL; | ||
118 | } | 167 | } |
119 | 168 | ||
120 | void view_damage_from(struct sway_view *view) { | 169 | void view_update_position(struct sway_view *view, double ox, double oy) { |
121 | // TODO | 170 | if (view->swayc->x == ox && view->swayc->y == oy) { |
171 | return; | ||
172 | } | ||
173 | |||
174 | struct wlr_box box; | ||
175 | view_get_layout_box(view, &box); | ||
176 | view_damage_whole(view); | ||
177 | view->swayc->x = ox; | ||
178 | view->swayc->y = oy; | ||
179 | view_update_outputs(view, &box); | ||
180 | view_damage_whole(view); | ||
181 | } | ||
182 | |||
183 | void view_update_size(struct sway_view *view, int width, int height) { | ||
184 | if (view->width == width && view->height == height) { | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | struct wlr_box box; | ||
189 | view_get_layout_box(view, &box); | ||
190 | view_damage_whole(view); | ||
191 | view->width = width; | ||
192 | view->height = height; | ||
193 | view_update_outputs(view, &box); | ||
122 | view_damage_whole(view); | 194 | view_damage_whole(view); |
123 | } | 195 | } |