aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/output.h1
-rw-r--r--include/sway/tree/container.h3
-rw-r--r--include/sway/tree/view.h15
-rw-r--r--sway/desktop/output.c73
-rw-r--r--sway/desktop/wl_shell.c38
-rw-r--r--sway/desktop/xdg_shell_v6.c46
-rw-r--r--sway/desktop/xwayland.c61
-rw-r--r--sway/tree/view.c125
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
8struct sway_container; 10struct sway_container;
9struct sway_view; 11struct 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
102struct sway_view *view_create(enum sway_view_type type);
103
104void view_destroy(struct sway_view *view);
105
100const char *view_get_title(struct sway_view *view); 106const char *view_get_title(struct sway_view *view);
101 107
102const char *view_get_app_id(struct sway_view *view); 108const 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
114void view_close(struct sway_view *view); 120void view_close(struct sway_view *view);
115 121
116void view_update_outputs(struct sway_view *view, const struct wlr_box *before); 122void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
123
124void view_map_unmanaged(struct sway_view *view,
125 struct wlr_surface *wlr_surface);
126
127void view_unmap(struct sway_view *view);
117 128
118void view_damage_whole(struct sway_view *view); 129void 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 */
47static 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
42static void render_surface(struct wlr_surface *surface, 68static 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
358static 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
341void handle_new_output(struct wl_listener *listener, void *data) { 364void 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
84void handle_wl_shell_surface(struct wl_listener *listener, void *data) { 82void 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) {
82static void handle_unmap(struct wl_listener *listener, void *data) { 82static 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
91static void handle_map(struct wl_listener *listener, void *data) { 88static 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
110static void handle_destroy(struct wl_listener *listener, void *data) { 95static 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) {
102static void handle_destroy(struct wl_listener *listener, void *data) { 102static 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
115static void handle_unmap(struct wl_listener *listener, void *data) { 114static 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
126static void handle_map(struct wl_listener *listener, void *data) { 120static 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
157static void handle_request_configure(struct wl_listener *listener, void *data) { 136static 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
10struct 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
20void 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
9const char *view_get_title(struct sway_view *view) { 35const 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
63static 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
37void view_set_size(struct sway_view *view, int width, int height) { 88void 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
76void 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
100struct sway_container *container_view_destroy(struct sway_container *view) { 127struct 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
137void 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
156void 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
171void 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
110void view_damage_whole(struct sway_view *view) { 187void 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) {