diff options
-rw-r--r-- | include/sway/output.h | 1 | ||||
-rw-r--r-- | include/sway/tree/container.h | 3 | ||||
-rw-r--r-- | include/sway/tree/view.h | 15 | ||||
-rw-r--r-- | sway/desktop/output.c | 73 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 38 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 46 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 61 | ||||
-rw-r--r-- | sway/tree/view.c | 125 |
8 files changed, 212 insertions, 150 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index b4980cd8..cfe7502b 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 6aa66da0..d707df17 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -70,9 +70,8 @@ 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 | // in output-local coordinates |
74 | double x, y; | 74 | double x, y; |
75 | |||
76 | // does not include borders or gaps. | 75 | // does not include borders or gaps. |
77 | double width, height; | 76 | double width, height; |
78 | 77 | ||
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3965d2b7..82a5541b 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; |
@@ -94,9 +96,13 @@ struct sway_view { | |||
94 | } iface; | 96 | } iface; |
95 | 97 | ||
96 | // only used for unmanaged views (shell specific) | 98 | // only used for unmanaged views (shell specific) |
97 | struct wl_list unmanaged_view_link; // sway_root::unmanaged views | 99 | struct wl_list unmanaged_view_link; // sway_root::unmanaged_views |
98 | }; | 100 | }; |
99 | 101 | ||
102 | struct sway_view *view_create(enum sway_view_type type); | ||
103 | |||
104 | void view_destroy(struct sway_view *view); | ||
105 | |||
100 | const char *view_get_title(struct sway_view *view); | 106 | const char *view_get_title(struct sway_view *view); |
101 | 107 | ||
102 | const char *view_get_app_id(struct sway_view *view); | 108 | const char *view_get_app_id(struct sway_view *view); |
@@ -113,7 +119,12 @@ void view_set_activated(struct sway_view *view, bool activated); | |||
113 | 119 | ||
114 | void view_close(struct sway_view *view); | 120 | void view_close(struct sway_view *view); |
115 | 121 | ||
116 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before); | 122 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); |
123 | |||
124 | void view_map_unmanaged(struct sway_view *view, | ||
125 | struct wlr_surface *wlr_surface); | ||
126 | |||
127 | void view_unmap(struct sway_view *view); | ||
117 | 128 | ||
118 | void view_damage_whole(struct sway_view *view); | 129 | void view_damage_whole(struct sway_view *view); |
119 | 130 | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0d706c52..6c97ac37 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); |
@@ -338,6 +355,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { | |||
338 | arrange_windows(output->swayc, -1, -1); | 355 | arrange_windows(output->swayc, -1, -1); |
339 | } | 356 | } |
340 | 357 | ||
358 | static void handle_scale(struct wl_listener *listener, void *data) { | ||
359 | struct sway_output *output = wl_container_of(listener, output, scale); | ||
360 | arrange_layers(output); | ||
361 | arrange_windows(output->swayc, -1, -1); | ||
362 | } | ||
363 | |||
341 | void handle_new_output(struct wl_listener *listener, void *data) { | 364 | void handle_new_output(struct wl_listener *listener, void *data) { |
342 | struct sway_server *server = wl_container_of(listener, server, new_output); | 365 | struct sway_server *server = wl_container_of(listener, server, new_output); |
343 | struct wlr_output *wlr_output = data; | 366 | struct wlr_output *wlr_output = data; |
@@ -378,6 +401,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
378 | output->mode.notify = handle_mode; | 401 | output->mode.notify = handle_mode; |
379 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 402 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
380 | output->transform.notify = handle_transform; | 403 | output->transform.notify = handle_transform; |
404 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
405 | output->scale.notify = handle_scale; | ||
381 | 406 | ||
382 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | 407 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); |
383 | output->damage_frame.notify = damage_handle_frame; | 408 | output->damage_frame.notify = damage_handle_frame; |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 4fcc6317..ab969b17 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -75,15 +75,13 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
75 | wl_container_of(listener, sway_surface, destroy); | 75 | wl_container_of(listener, sway_surface, destroy); |
76 | wl_list_remove(&sway_surface->commit.link); | 76 | wl_list_remove(&sway_surface->commit.link); |
77 | wl_list_remove(&sway_surface->destroy.link); | 77 | wl_list_remove(&sway_surface->destroy.link); |
78 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | 78 | view_destroy(sway_surface->view); |
79 | free(sway_surface->view); | ||
80 | free(sway_surface); | 79 | free(sway_surface); |
81 | arrange_windows(parent, -1, -1); | ||
82 | } | 80 | } |
83 | 81 | ||
84 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | 82 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { |
85 | struct sway_server *server = wl_container_of( | 83 | struct sway_server *server = wl_container_of(listener, server, |
86 | listener, server, wl_shell_surface); | 84 | wl_shell_surface); |
87 | struct wlr_wl_shell_surface *shell_surface = data; | 85 | struct wlr_wl_shell_surface *shell_surface = data; |
88 | 86 | ||
89 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { | 87 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { |
@@ -103,20 +101,18 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
103 | return; | 101 | return; |
104 | } | 102 | } |
105 | 103 | ||
106 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 104 | struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW); |
107 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 105 | if (!sway_assert(view, "Failed to allocate view")) { |
108 | return; | 106 | return; |
109 | } | 107 | } |
110 | sway_view->type = SWAY_WL_SHELL_VIEW; | 108 | view->iface.get_prop = get_prop; |
111 | sway_view->iface.get_prop = get_prop; | 109 | view->iface.set_size = set_size; |
112 | sway_view->iface.set_size = set_size; | 110 | view->iface.set_position = set_position; |
113 | sway_view->iface.set_position = set_position; | 111 | view->iface.set_activated = set_activated; |
114 | sway_view->iface.set_activated = set_activated; | 112 | view->iface.close = close; |
115 | sway_view->iface.close = close; | 113 | view->wlr_wl_shell_surface = shell_surface; |
116 | sway_view->wlr_wl_shell_surface = shell_surface; | 114 | view->sway_wl_shell_surface = sway_surface; |
117 | sway_view->sway_wl_shell_surface = sway_surface; | 115 | sway_surface->view = view; |
118 | sway_view->surface = shell_surface->surface; | ||
119 | sway_surface->view = sway_view; | ||
120 | 116 | ||
121 | // TODO: | 117 | // TODO: |
122 | // - Wire up listeners | 118 | // - Wire up listeners |
@@ -132,11 +128,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
132 | sway_surface->destroy.notify = handle_destroy; | 128 | sway_surface->destroy.notify = handle_destroy; |
133 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); | 129 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); |
134 | 130 | ||
135 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 131 | view_map(view, shell_surface->surface); |
136 | struct sway_container *focus = sway_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 | sway_input_manager_set_focus(input_manager, cont); | ||
142 | } | 132 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 713437f2..77a35b13 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -82,29 +82,14 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
82 | static void handle_unmap(struct wl_listener *listener, void *data) { | 82 | static void handle_unmap(struct wl_listener *listener, void *data) { |
83 | struct sway_xdg_surface_v6 *sway_surface = | 83 | struct sway_xdg_surface_v6 *sway_surface = |
84 | wl_container_of(listener, sway_surface, unmap); | 84 | wl_container_of(listener, sway_surface, unmap); |
85 | view_damage_whole(sway_surface->view); | 85 | 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 | } | 86 | } |
90 | 87 | ||
91 | static void handle_map(struct wl_listener *listener, void *data) { | 88 | static void handle_map(struct wl_listener *listener, void *data) { |
92 | struct sway_xdg_surface_v6 *sway_surface = | 89 | struct sway_xdg_surface_v6 *sway_surface = |
93 | wl_container_of(listener, sway_surface, map); | 90 | wl_container_of(listener, sway_surface, map); |
94 | struct sway_view *view = sway_surface->view; | 91 | struct sway_view *view = sway_surface->view; |
95 | 92 | 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 = sway_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 | sway_input_manager_set_focus(input_manager, cont); | ||
106 | |||
107 | view_damage_whole(sway_surface->view); | ||
108 | } | 93 | } |
109 | 94 | ||
110 | static void handle_destroy(struct wl_listener *listener, void *data) { | 95 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -112,8 +97,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
112 | wl_container_of(listener, sway_xdg_surface, destroy); | 97 | wl_container_of(listener, sway_xdg_surface, destroy); |
113 | wl_list_remove(&sway_xdg_surface->commit.link); | 98 | wl_list_remove(&sway_xdg_surface->commit.link); |
114 | wl_list_remove(&sway_xdg_surface->destroy.link); | 99 | wl_list_remove(&sway_xdg_surface->destroy.link); |
115 | container_view_destroy(sway_xdg_surface->view->swayc); | 100 | wl_list_remove(&sway_xdg_surface->map.link); |
116 | free(sway_xdg_surface->view); | 101 | wl_list_remove(&sway_xdg_surface->unmap.link); |
102 | view_destroy(sway_xdg_surface->view); | ||
117 | free(sway_xdg_surface); | 103 | free(sway_xdg_surface); |
118 | } | 104 | } |
119 | 105 | ||
@@ -138,23 +124,21 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
138 | return; | 124 | return; |
139 | } | 125 | } |
140 | 126 | ||
141 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 127 | struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW); |
142 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 128 | if (!sway_assert(view, "Failed to allocate view")) { |
143 | return; | 129 | return; |
144 | } | 130 | } |
145 | sway_view->type = SWAY_XDG_SHELL_V6_VIEW; | 131 | view->iface.get_prop = get_prop; |
146 | sway_view->iface.get_prop = get_prop; | 132 | view->iface.set_size = set_size; |
147 | sway_view->iface.set_size = set_size; | 133 | view->iface.set_position = set_position; |
148 | sway_view->iface.set_position = set_position; | 134 | view->iface.set_activated = set_activated; |
149 | sway_view->iface.set_activated = set_activated; | 135 | view->iface.close = close; |
150 | sway_view->iface.close = close; | 136 | view->wlr_xdg_surface_v6 = xdg_surface; |
151 | sway_view->wlr_xdg_surface_v6 = xdg_surface; | 137 | view->sway_xdg_surface_v6 = sway_surface; |
152 | sway_view->sway_xdg_surface_v6 = sway_surface; | 138 | sway_surface->view = view; |
153 | sway_surface->view = sway_view; | ||
154 | 139 | ||
155 | // TODO: | 140 | // TODO: |
156 | // - Look up pid and open on appropriate workspace | 141 | // - Look up pid and open on appropriate workspace |
157 | // - Set new view to maximized so it behaves nicely | ||
158 | // - Criteria | 142 | // - Criteria |
159 | 143 | ||
160 | sway_surface->commit.notify = handle_commit; | 144 | sway_surface->commit.notify = handle_commit; |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 273ca2bf..e1c2ad08 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -102,56 +102,35 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
102 | static void handle_destroy(struct wl_listener *listener, void *data) { | 102 | static void handle_destroy(struct wl_listener *listener, void *data) { |
103 | struct sway_xwayland_surface *sway_surface = | 103 | struct sway_xwayland_surface *sway_surface = |
104 | wl_container_of(listener, sway_surface, destroy); | 104 | wl_container_of(listener, sway_surface, destroy); |
105 | |||
106 | wl_list_remove(&sway_surface->commit.link); | 105 | wl_list_remove(&sway_surface->commit.link); |
107 | wl_list_remove(&sway_surface->destroy.link); | 106 | wl_list_remove(&sway_surface->destroy.link); |
108 | wl_list_remove(&sway_surface->request_configure.link); | 107 | wl_list_remove(&sway_surface->request_configure.link); |
109 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 108 | wl_list_remove(&sway_surface->map.link); |
110 | container_view_destroy(sway_surface->view->swayc); | 109 | wl_list_remove(&sway_surface->unmap.link); |
111 | sway_surface->view->swayc = NULL; | 110 | view_destroy(sway_surface->view); |
112 | sway_surface->view->surface = NULL; | 111 | free(sway_surface); |
113 | } | 112 | } |
114 | 113 | ||
115 | static void handle_unmap(struct wl_listener *listener, void *data) { | 114 | static void handle_unmap(struct wl_listener *listener, void *data) { |
116 | struct sway_xwayland_surface *sway_surface = | 115 | struct sway_xwayland_surface *sway_surface = |
117 | wl_container_of(listener, sway_surface, unmap); | 116 | wl_container_of(listener, sway_surface, unmap); |
118 | view_damage_whole(sway_surface->view); | 117 | 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 | } | 118 | } |
125 | 119 | ||
126 | static void handle_map(struct wl_listener *listener, void *data) { | 120 | static void handle_map(struct wl_listener *listener, void *data) { |
127 | struct sway_xwayland_surface *sway_surface = | 121 | struct sway_xwayland_surface *sway_surface = |
128 | wl_container_of(listener, sway_surface, map); | 122 | wl_container_of(listener, sway_surface, map); |
129 | struct wlr_xwayland_surface *xsurface = data; | 123 | struct wlr_xwayland_surface *xsurface = data; |
130 | 124 | struct sway_view *view = sway_surface->view; | |
131 | sway_surface->view->surface = xsurface->surface; | ||
132 | 125 | ||
133 | // put it back into the tree | 126 | // put it back into the tree |
134 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | 127 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || |
135 | xsurface->override_redirect) { | 128 | xsurface->override_redirect) { |
136 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 129 | view_map_unmanaged(view, xsurface->surface); |
137 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
138 | &sway_surface->view->unmanaged_view_link); | ||
139 | } else { | 130 | } else { |
140 | struct sway_view *view = sway_surface->view; | ||
141 | container_view_destroy(view->swayc); | ||
142 | |||
143 | wlr_xwayland_surface_set_maximized(xsurface, true); | 131 | wlr_xwayland_surface_set_maximized(xsurface, true); |
144 | 132 | view_map(view, xsurface->surface); | |
145 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
146 | struct sway_container *focus = sway_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 | sway_input_manager_set_focus(input_manager, cont); | ||
152 | } | 133 | } |
153 | |||
154 | view_damage_whole(sway_surface->view); | ||
155 | } | 134 | } |
156 | 135 | ||
157 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 136 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
@@ -180,25 +159,21 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
180 | return; | 159 | return; |
181 | } | 160 | } |
182 | 161 | ||
183 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 162 | struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW); |
184 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 163 | if (!sway_assert(view, "Failed to allocate view")) { |
185 | return; | 164 | return; |
186 | } | 165 | } |
187 | sway_view->type = SWAY_XWAYLAND_VIEW; | 166 | view->iface.get_prop = get_prop; |
188 | sway_view->iface.get_prop = get_prop; | 167 | view->iface.set_size = set_size; |
189 | sway_view->iface.set_size = set_size; | 168 | view->iface.set_position = set_position; |
190 | sway_view->iface.set_position = set_position; | 169 | view->iface.set_activated = set_activated; |
191 | sway_view->iface.set_activated = set_activated; | 170 | view->iface.close = close_view; |
192 | sway_view->iface.close = close_view; | 171 | view->wlr_xwayland_surface = xsurface; |
193 | sway_view->wlr_xwayland_surface = xsurface; | 172 | view->sway_xwayland_surface = sway_surface; |
194 | sway_view->sway_xwayland_surface = sway_surface; | 173 | sway_surface->view = view; |
195 | sway_surface->view = sway_view; | ||
196 | |||
197 | wl_list_init(&sway_view->unmanaged_view_link); | ||
198 | 174 | ||
199 | // TODO: | 175 | // TODO: |
200 | // - Look up pid and open on appropriate workspace | 176 | // - Look up pid and open on appropriate workspace |
201 | // - Set new view to maximized so it behaves nicely | ||
202 | // - Criteria | 177 | // - Criteria |
203 | 178 | ||
204 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); | 179 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); |
diff --git a/sway/tree/view.c b/sway/tree/view.c index b7d1a41b..2950812a 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,6 +7,31 @@ | |||
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 | struct sway_view *view = calloc(1, sizeof(struct sway_view)); | ||
12 | if (view == NULL) { | ||
13 | return NULL; | ||
14 | } | ||
15 | view->type = type; | ||
16 | wl_list_init(&view->unmanaged_view_link); | ||
17 | return view; | ||
18 | } | ||
19 | |||
20 | void view_destroy(struct sway_view *view) { | ||
21 | if (view == NULL) { | ||
22 | return; | ||
23 | } | ||
24 | |||
25 | if (view->surface != NULL) { | ||
26 | view_unmap(view); | ||
27 | } | ||
28 | if (view->swayc != NULL) { | ||
29 | container_view_destroy(view->swayc); | ||
30 | } | ||
31 | |||
32 | free(view); | ||
33 | } | ||
34 | |||
9 | const char *view_get_title(struct sway_view *view) { | 35 | const char *view_get_title(struct sway_view *view) { |
10 | if (view->iface.get_prop) { | 36 | if (view->iface.get_prop) { |
11 | return view->iface.get_prop(view, VIEW_PROP_TITLE); | 37 | return view->iface.get_prop(view, VIEW_PROP_TITLE); |
@@ -34,6 +60,31 @@ const char *view_get_instance(struct sway_view *view) { | |||
34 | return NULL; | 60 | return NULL; |
35 | } | 61 | } |
36 | 62 | ||
63 | static void view_update_outputs(struct sway_view *view, | ||
64 | const struct wlr_box *before) { | ||
65 | struct wlr_output_layout *output_layout = | ||
66 | root_container.sway_root->output_layout; | ||
67 | struct wlr_box box = { | ||
68 | .x = view->swayc->x, | ||
69 | .y = view->swayc->y, | ||
70 | .width = view->width, | ||
71 | .height = view->height, | ||
72 | }; | ||
73 | struct wlr_output_layout_output *layout_output; | ||
74 | wl_list_for_each(layout_output, &output_layout->outputs, link) { | ||
75 | bool intersected = before != NULL && wlr_output_layout_intersects( | ||
76 | output_layout, layout_output->output, before); | ||
77 | bool intersects = wlr_output_layout_intersects(output_layout, | ||
78 | layout_output->output, &box); | ||
79 | if (intersected && !intersects) { | ||
80 | wlr_surface_send_leave(view->surface, layout_output->output); | ||
81 | } | ||
82 | if (!intersected && intersects) { | ||
83 | wlr_surface_send_enter(view->surface, layout_output->output); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
37 | void view_set_size(struct sway_view *view, int width, int height) { | 88 | void view_set_size(struct sway_view *view, int width, int height) { |
38 | if (view->iface.set_size) { | 89 | if (view->iface.set_size) { |
39 | struct wlr_box box = { | 90 | struct wlr_box box = { |
@@ -73,30 +124,6 @@ void view_close(struct sway_view *view) { | |||
73 | } | 124 | } |
74 | } | 125 | } |
75 | 126 | ||
76 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | ||
77 | struct wlr_output_layout *output_layout = | ||
78 | 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; | ||
86 | wl_list_for_each(layout_output, &output_layout->outputs, link) { | ||
87 | bool intersected = before != NULL && wlr_output_layout_intersects( | ||
88 | output_layout, layout_output->output, before); | ||
89 | bool intersects = wlr_output_layout_intersects(output_layout, | ||
90 | layout_output->output, &box); | ||
91 | if (intersected && !intersects) { | ||
92 | wlr_surface_send_leave(view->surface, layout_output->output); | ||
93 | } | ||
94 | if (!intersected && intersects) { | ||
95 | wlr_surface_send_enter(view->surface, layout_output->output); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | struct sway_container *container_view_destroy(struct sway_container *view) { | 127 | struct sway_container *container_view_destroy(struct sway_container *view) { |
101 | if (!view) { | 128 | if (!view) { |
102 | return NULL; | 129 | return NULL; |
@@ -107,6 +134,56 @@ struct sway_container *container_view_destroy(struct sway_container *view) { | |||
107 | return parent; | 134 | return parent; |
108 | } | 135 | } |
109 | 136 | ||
137 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | ||
138 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
143 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, | ||
144 | &root_container); | ||
145 | struct sway_container *cont = container_view_create(focus, view); | ||
146 | |||
147 | view->surface = wlr_surface; | ||
148 | view->swayc = cont; | ||
149 | |||
150 | arrange_windows(cont->parent, -1, -1); | ||
151 | sway_input_manager_set_focus(input_manager, cont); | ||
152 | |||
153 | view_damage_whole(view); | ||
154 | } | ||
155 | |||
156 | void view_map_unmanaged(struct sway_view *view, | ||
157 | struct wlr_surface *wlr_surface) { | ||
158 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | view->surface = wlr_surface; | ||
163 | view->swayc = NULL; | ||
164 | |||
165 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
166 | &view->unmanaged_view_link); | ||
167 | |||
168 | view_damage_whole(view); | ||
169 | } | ||
170 | |||
171 | void view_unmap(struct sway_view *view) { | ||
172 | if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | view_damage_whole(view); | ||
177 | |||
178 | wl_list_remove(&view->unmanaged_view_link); | ||
179 | wl_list_init(&view->unmanaged_view_link); | ||
180 | |||
181 | container_view_destroy(view->swayc); | ||
182 | |||
183 | view->swayc = NULL; | ||
184 | view->surface = NULL; | ||
185 | } | ||
186 | |||
110 | void view_damage_whole(struct sway_view *view) { | 187 | void view_damage_whole(struct sway_view *view) { |
111 | struct sway_container *cont = NULL; | 188 | struct sway_container *cont = NULL; |
112 | for (int i = 0; i < root_container.children->length; ++i) { | 189 | for (int i = 0; i < root_container.children->length; ++i) { |