summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-02 19:19:38 -0400
committerLibravatar GitHub <noreply@github.com>2018-04-02 19:19:38 -0400
commit64b9b4b1556c1c45273bfbe0ae1c92245414cfed (patch)
tree380408259cba4ea6a536f64f9726d37e65c59032
parentMerge pull request #1701 from emersion/remove-xdg-shell-xml (diff)
parentMerge branch 'wlroots' into view-redesign (diff)
downloadsway-64b9b4b1556c1c45273bfbe0ae1c92245414cfed.tar.gz
sway-64b9b4b1556c1c45273bfbe0ae1c92245414cfed.tar.zst
sway-64b9b4b1556c1c45273bfbe0ae1c92245414cfed.zip
Merge pull request #1691 from emersion/view-redesign
Views redesign
-rw-r--r--include/sway/output.h1
-rw-r--r--include/sway/tree/container.h5
-rw-r--r--include/sway/tree/layout.h2
-rw-r--r--include/sway/tree/view.h59
-rw-r--r--sway/desktop/output.c87
-rw-r--r--sway/desktop/wl_shell.c61
-rw-r--r--sway/desktop/xdg_shell_v6.c67
-rw-r--r--sway/desktop/xwayland.c136
-rw-r--r--sway/input/cursor.c11
-rw-r--r--sway/tree/layout.c10
-rw-r--r--sway/tree/output.c1
-rw-r--r--sway/tree/view.c188
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
8struct sway_container; 10struct sway_container;
9struct sway_view; 11struct 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
42struct sway_xwayland_unmanaged {
43 struct wlr_xwayland_surface *wlr_xwayland_surface;
44 struct wl_list link;
45
46 struct wl_listener destroy;
47};
48
40struct sway_wl_shell_surface { 49struct 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
76struct 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
67struct sway_view { 85struct 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
109struct sway_view *view_create(enum sway_view_type type,
110 const struct sway_view_impl *impl);
111
112void view_destroy(struct sway_view *view);
113
100const char *view_get_title(struct sway_view *view); 114const char *view_get_title(struct sway_view *view);
101 115
102const char *view_get_app_id(struct sway_view *view); 116const char *view_get_app_id(struct sway_view *view);
@@ -105,18 +119,25 @@ const char *view_get_class(struct sway_view *view);
105 119
106const char *view_get_instance(struct sway_view *view); 120const char *view_get_instance(struct sway_view *view);
107 121
108void view_set_size(struct sway_view *view, int width, int height); 122void view_configure(struct sway_view *view, double ox, double oy, int width,
109 123 int height);
110void view_set_position(struct sway_view *view, double ox, double oy);
111 124
112void view_set_activated(struct sway_view *view, bool activated); 125void view_set_activated(struct sway_view *view, bool activated);
113 126
114void view_close(struct sway_view *view); 127void view_close(struct sway_view *view);
115 128
116void view_update_outputs(struct sway_view *view, const struct wlr_box *before);
117
118void view_damage_whole(struct sway_view *view); 129void view_damage_whole(struct sway_view *view);
119 130
120void view_damage_from(struct sway_view *view); 131void view_damage_from(struct sway_view *view);
121 132
133// view implementation
134
135void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
136
137void view_unmap(struct sway_view *view);
138
139void view_update_position(struct sway_view *view, double ox, double oy);
140
141void 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 */
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);
@@ -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
361static 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
344void handle_new_output(struct wl_listener *listener, void *data) { 367void 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
33static void set_size(struct sway_view *view, int width, int height) { 33static 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
42static void set_position(struct sway_view *view, double ox, double oy) { 44static 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
50static void set_activated(struct sway_view *view, bool activated) {
51 // no way to activate wl_shell
52}
53
54static 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
52static const struct sway_view_impl view_impl = {
53 .get_prop = get_prop,
54 .configure = configure,
55 .close = _close,
56};
57
62static void handle_commit(struct wl_listener *listener, void *data) { 58static 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
84void handle_wl_shell_surface(struct wl_listener *listener, void *data) { 78void 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
33static void set_size(struct sway_view *view, int width, int height) { 33static 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
42static 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
50static void set_activated(struct sway_view *view, bool activated) { 45static 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
60static void close(struct sway_view *view) { 55static 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
65static 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
70static void handle_commit(struct wl_listener *listener, void *data) { 72static 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
82static void handle_unmap(struct wl_listener *listener, void *data) { 84static 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
91static void handle_map(struct wl_listener *listener, void *data) { 90static 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
110static void handle_destroy(struct wl_listener *listener, void *data) { 97static 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
17static 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
25static 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
17static bool assert_xwayland(struct sway_view *view) { 44static 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
36static void set_size(struct sway_view *view, int width, int height) { 63static 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
48static 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
76static void set_activated(struct sway_view *view, bool activated) { 93static 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
84static void close_view(struct sway_view *view) { 101static 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
108static 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
91static void handle_commit(struct wl_listener *listener, void *data) { 115static 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
102static void handle_destroy(struct wl_listener *listener, void *data) { 126static 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
115static void handle_unmap(struct wl_listener *listener, void *data) { 138static 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
126static void handle_map(struct wl_listener *listener, void *data) { 144static 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
157static void handle_request_configure(struct wl_listener *listener, void *data) { 155static 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,
47static struct sway_container *container_at_cursor(struct sway_cursor *cursor, 47static 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
10struct 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
21void 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
9const char *view_get_title(struct sway_view *view) { 34const 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
16const char *view_get_app_id(struct sway_view *view) { 41const 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
23const char *view_get_class(struct sway_view *view) { 48const 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
30const char *view_get_instance(struct sway_view *view) { 55const 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
37void view_set_size(struct sway_view *view, int width, int height) { 62void 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 69void view_set_activated(struct sway_view *view, bool activated) {
51void 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
64void view_set_activated(struct sway_view *view, bool activated) { 75void 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
70void view_close(struct sway_view *view) { 81struct 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
91void 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
100void view_damage_from(struct sway_view *view) {
101 // TODO
102 view_damage_whole(view);
103}
104
105static 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
76void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { 114static 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
100struct sway_container *container_view_destroy(struct sway_container *view) { 136void 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
110void view_damage_whole(struct sway_view *view) { 156void 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
120void view_damage_from(struct sway_view *view) { 169void 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
183void 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}