summaryrefslogtreecommitdiffstats
path: root/sway/desktop/xwayland.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/xwayland.c')
-rw-r--r--sway/desktop/xwayland.c136
1 files changed, 66 insertions, 70 deletions
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);