aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/xdg_shell_v6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/xdg_shell_v6.c')
-rw-r--r--sway/desktop/xdg_shell_v6.c115
1 files changed, 106 insertions, 9 deletions
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index b28c4b9c..46fd4769 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -1,4 +1,5 @@
1#define _POSIX_C_SOURCE 199309L 1#define _POSIX_C_SOURCE 199309L
2#include <float.h>
2#include <stdbool.h> 3#include <stdbool.h>
3#include <stdlib.h> 4#include <stdlib.h>
4#include <wayland-server.h> 5#include <wayland-server.h>
@@ -44,6 +45,24 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
44 view_child_destroy(&popup->child); 45 view_child_destroy(&popup->child);
45} 46}
46 47
48static void popup_unconstrain(struct sway_xdg_popup_v6 *popup) {
49 struct sway_view *view = popup->child.view;
50 struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_xdg_surface_v6->popup;
51
52 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
53
54 // the output box expressed in the coordinate system of the toplevel parent
55 // of the popup
56 struct wlr_box output_toplevel_sx_box = {
57 .x = output->x - view->x,
58 .y = output->y - view->y,
59 .width = output->width,
60 .height = output->height,
61 };
62
63 wlr_xdg_popup_v6_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
64}
65
47static struct sway_xdg_popup_v6 *popup_create( 66static struct sway_xdg_popup_v6 *popup_create(
48 struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { 67 struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) {
49 struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; 68 struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base;
@@ -54,12 +73,15 @@ static struct sway_xdg_popup_v6 *popup_create(
54 return NULL; 73 return NULL;
55 } 74 }
56 view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); 75 view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
76 popup->wlr_xdg_surface_v6 = xdg_surface;
57 77
58 wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); 78 wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
59 popup->new_popup.notify = popup_handle_new_popup; 79 popup->new_popup.notify = popup_handle_new_popup;
60 wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); 80 wl_signal_add(&xdg_surface->events.destroy, &popup->destroy);
61 popup->destroy.notify = popup_handle_destroy; 81 popup->destroy.notify = popup_handle_destroy;
62 82
83 popup_unconstrain(popup);
84
63 return popup; 85 return popup;
64} 86}
65 87
@@ -73,6 +95,16 @@ static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view(
73 return (struct sway_xdg_shell_v6_view *)view; 95 return (struct sway_xdg_shell_v6_view *)view;
74} 96}
75 97
98static void get_constraints(struct sway_view *view, double *min_width,
99 double *max_width, double *min_height, double *max_height) {
100 struct wlr_xdg_toplevel_v6_state *state =
101 &view->wlr_xdg_surface_v6->toplevel->current;
102 *min_width = state->min_width > 0 ? state->min_width : DBL_MIN;
103 *max_width = state->max_width > 0 ? state->max_width : DBL_MAX;
104 *min_height = state->min_height > 0 ? state->min_height : DBL_MIN;
105 *max_height = state->max_height > 0 ? state->max_height : DBL_MAX;
106}
107
76static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) { 108static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) {
77 if (xdg_shell_v6_view_from_view(view) == NULL) { 109 if (xdg_shell_v6_view_from_view(view) == NULL) {
78 return NULL; 110 return NULL;
@@ -163,6 +195,7 @@ static void destroy(struct sway_view *view) {
163} 195}
164 196
165static const struct sway_view_impl view_impl = { 197static const struct sway_view_impl view_impl = {
198 .get_constraints = get_constraints,
166 .get_string_prop = get_string_prop, 199 .get_string_prop = get_string_prop,
167 .configure = configure, 200 .configure = configure,
168 .set_activated = set_activated, 201 .set_activated = set_activated,
@@ -187,10 +220,24 @@ static void handle_commit(struct wl_listener *listener, void *data) {
187 transaction_notify_view_ready(view, xdg_surface_v6->configure_serial); 220 transaction_notify_view_ready(view, xdg_surface_v6->configure_serial);
188 } 221 }
189 222
190 view_update_title(view, false);
191 view_damage_from(view); 223 view_damage_from(view);
192} 224}
193 225
226static void handle_set_title(struct wl_listener *listener, void *data) {
227 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
228 wl_container_of(listener, xdg_shell_v6_view, set_title);
229 struct sway_view *view = &xdg_shell_v6_view->view;
230 view_update_title(view, false);
231 view_execute_criteria(view);
232}
233
234static void handle_set_app_id(struct wl_listener *listener, void *data) {
235 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
236 wl_container_of(listener, xdg_shell_v6_view, set_app_id);
237 struct sway_view *view = &xdg_shell_v6_view->view;
238 view_execute_criteria(view);
239}
240
194static void handle_new_popup(struct wl_listener *listener, void *data) { 241static void handle_new_popup(struct wl_listener *listener, void *data) {
195 struct sway_xdg_shell_v6_view *xdg_shell_v6_view = 242 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
196 wl_container_of(listener, xdg_shell_v6_view, new_popup); 243 wl_container_of(listener, xdg_shell_v6_view, new_popup);
@@ -217,8 +264,37 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
217 264
218 view_set_fullscreen(view, e->fullscreen); 265 view_set_fullscreen(view, e->fullscreen);
219 266
220 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 267 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
221 arrange_and_commit(ws); 268 arrange_windows(output);
269 transaction_commit_dirty();
270}
271
272static void handle_request_move(struct wl_listener *listener, void *data) {
273 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
274 wl_container_of(listener, xdg_shell_v6_view, request_move);
275 struct sway_view *view = &xdg_shell_v6_view->view;
276 if (!container_is_floating(view->swayc)) {
277 return;
278 }
279 struct wlr_xdg_toplevel_v6_move_event *e = data;
280 struct sway_seat *seat = e->seat->seat->data;
281 if (e->serial == seat->last_button_serial) {
282 seat_begin_move(seat, view->swayc, seat->last_button);
283 }
284}
285
286static void handle_request_resize(struct wl_listener *listener, void *data) {
287 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
288 wl_container_of(listener, xdg_shell_v6_view, request_resize);
289 struct sway_view *view = &xdg_shell_v6_view->view;
290 if (!container_is_floating(view->swayc)) {
291 return;
292 }
293 struct wlr_xdg_toplevel_v6_resize_event *e = data;
294 struct sway_seat *seat = e->seat->seat->data;
295 if (e->serial == seat->last_button_serial) {
296 seat_begin_resize(seat, view->swayc, seat->last_button, e->edges);
297 }
222} 298}
223 299
224static void handle_unmap(struct wl_listener *listener, void *data) { 300static void handle_unmap(struct wl_listener *listener, void *data) {
@@ -235,6 +311,10 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
235 wl_list_remove(&xdg_shell_v6_view->commit.link); 311 wl_list_remove(&xdg_shell_v6_view->commit.link);
236 wl_list_remove(&xdg_shell_v6_view->new_popup.link); 312 wl_list_remove(&xdg_shell_v6_view->new_popup.link);
237 wl_list_remove(&xdg_shell_v6_view->request_fullscreen.link); 313 wl_list_remove(&xdg_shell_v6_view->request_fullscreen.link);
314 wl_list_remove(&xdg_shell_v6_view->request_move.link);
315 wl_list_remove(&xdg_shell_v6_view->request_resize.link);
316 wl_list_remove(&xdg_shell_v6_view->set_title.link);
317 wl_list_remove(&xdg_shell_v6_view->set_app_id.link);
238} 318}
239 319
240static void handle_map(struct wl_listener *listener, void *data) { 320static void handle_map(struct wl_listener *listener, void *data) {
@@ -246,8 +326,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
246 view->natural_width = view->wlr_xdg_surface_v6->geometry.width; 326 view->natural_width = view->wlr_xdg_surface_v6->geometry.width;
247 view->natural_height = view->wlr_xdg_surface_v6->geometry.height; 327 view->natural_height = view->wlr_xdg_surface_v6->geometry.height;
248 if (!view->natural_width && !view->natural_height) { 328 if (!view->natural_width && !view->natural_height) {
249 view->natural_width = view->wlr_xdg_surface_v6->surface->current->width; 329 view->natural_width = view->wlr_xdg_surface_v6->surface->current.width;
250 view->natural_height = view->wlr_xdg_surface_v6->surface->current->height; 330 view->natural_height = view->wlr_xdg_surface_v6->surface->current.height;
251 } 331 }
252 332
253 view_map(view, view->wlr_xdg_surface_v6->surface); 333 view_map(view, view->wlr_xdg_surface_v6->surface);
@@ -255,10 +335,11 @@ static void handle_map(struct wl_listener *listener, void *data) {
255 if (xdg_surface->toplevel->client_pending.fullscreen) { 335 if (xdg_surface->toplevel->client_pending.fullscreen) {
256 view_set_fullscreen(view, true); 336 view_set_fullscreen(view, true);
257 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); 337 struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
258 arrange_and_commit(ws); 338 arrange_windows(ws);
259 } else { 339 } else {
260 arrange_and_commit(view->swayc->parent); 340 arrange_windows(view->swayc->parent);
261 } 341 }
342 transaction_commit_dirty();
262 343
263 xdg_shell_v6_view->commit.notify = handle_commit; 344 xdg_shell_v6_view->commit.notify = handle_commit;
264 wl_signal_add(&xdg_surface->surface->events.commit, 345 wl_signal_add(&xdg_surface->surface->events.commit,
@@ -271,6 +352,22 @@ static void handle_map(struct wl_listener *listener, void *data) {
271 xdg_shell_v6_view->request_fullscreen.notify = handle_request_fullscreen; 352 xdg_shell_v6_view->request_fullscreen.notify = handle_request_fullscreen;
272 wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, 353 wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen,
273 &xdg_shell_v6_view->request_fullscreen); 354 &xdg_shell_v6_view->request_fullscreen);
355
356 xdg_shell_v6_view->request_move.notify = handle_request_move;
357 wl_signal_add(&xdg_surface->toplevel->events.request_move,
358 &xdg_shell_v6_view->request_move);
359
360 xdg_shell_v6_view->request_resize.notify = handle_request_resize;
361 wl_signal_add(&xdg_surface->toplevel->events.request_resize,
362 &xdg_shell_v6_view->request_resize);
363
364 xdg_shell_v6_view->set_title.notify = handle_set_title;
365 wl_signal_add(&xdg_surface->toplevel->events.set_title,
366 &xdg_shell_v6_view->set_title);
367
368 xdg_shell_v6_view->set_app_id.notify = handle_set_app_id;
369 wl_signal_add(&xdg_surface->toplevel->events.set_app_id,
370 &xdg_shell_v6_view->set_app_id);
274} 371}
275 372
276static void handle_destroy(struct wl_listener *listener, void *data) { 373static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -295,11 +392,11 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
295 struct wlr_xdg_surface_v6 *xdg_surface = data; 392 struct wlr_xdg_surface_v6 *xdg_surface = data;
296 393
297 if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { 394 if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
298 wlr_log(L_DEBUG, "New xdg_shell_v6 popup"); 395 wlr_log(WLR_DEBUG, "New xdg_shell_v6 popup");
299 return; 396 return;
300 } 397 }
301 398
302 wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", 399 wlr_log(WLR_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'",
303 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); 400 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
304 wlr_xdg_surface_v6_ping(xdg_surface); 401 wlr_xdg_surface_v6_ping(xdg_surface);
305 402