From bbd0e23fa79ec39c872c09e49d09a9ccbda68bcd Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 26 Mar 2018 23:48:32 -0400 Subject: xdg-positioner constraint detection --- rootston/xdg_shell_v6.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 13d25331..36ecc897 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -45,6 +45,55 @@ static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, if (popup == NULL) { return NULL; } + + struct wlr_xdg_surface_v6 *parent = wlr_popup->parent; + double popup_lx = wlr_popup->geometry.x; + double popup_ly = wlr_popup->geometry.y; + while (parent->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + popup_lx += parent->popup->geometry.x; + popup_ly += parent->popup->geometry.y; + parent = parent->popup->parent; + } + + popup_lx += view->x + parent->geometry.x; + popup_ly += view->y + parent->geometry.y; + int popup_width = wlr_popup->geometry.width; + int popup_height = wlr_popup->geometry.height; + + int anchor_x, anchor_y; + wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_x, &anchor_y); + anchor_x += popup_lx; + anchor_y += popup_ly; + + struct wlr_output_layout *layout = view->desktop->layout; + + // get the output that contains (or closest to) the anchor point + struct wlr_output *output = + wlr_output_layout_output_at(layout, anchor_x, anchor_y); + if (output == NULL) { + // TODO find the closest output to the anchor + assert(false); + } + + // does the output completely contain the popup? + struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + bool output_contains_popup_x = popup_lx >= output_box->x && + popup_lx + popup_width <= output_box->x + output_box->width; + bool output_contains_popup_y = popup_ly >= output_box->y && + popup_ly + popup_height <= output_box->y + output_box->height; + + if (!output_contains_popup_x) { + // TODO flip_x + // TODO slide_x + // TODO resize_x + } + + if (!output_contains_popup_y) { + // TODO flip_y + // TODO slide_y + // TODO resize_y + } + popup->wlr_popup = wlr_popup; popup->view_child.destroy = popup_destroy; view_child_init(&popup->view_child, view, wlr_popup->base->surface); -- cgit v1.2.3 From 8371e2f41dbcb8d3ae42a4fb386577d97301ac5a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 27 Mar 2018 14:49:31 -0400 Subject: implement flip_x --- include/wlr/types/wlr_xdg_shell_v6.h | 8 ++- rootston/xdg_shell_v6.c | 107 +++++++++++++++++++++-------------- types/wlr_xdg_shell_v6.c | 79 +++++++++++--------------- 3 files changed, 106 insertions(+), 88 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index e192d36a..e085c493 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -296,13 +296,19 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at( struct wlr_xdg_surface_v6 *surface, double sx, double sy, double *popup_sx, double *popup_sy); +struct wlr_box wlr_xdg_positioner_v6_get_geometry( + struct wlr_xdg_positioner_v6_attributes *positioner); + /** * Get the anchor point for this popup in the root parent's coordinate system. */ void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, int *root_sx, int *root_sy); -void wlr_positioner_v6_invert( +void wlr_positioner_v6_invert_x( + struct wlr_xdg_positioner_v6_attributes *positioner); + +void wlr_positioner_v6_invert_y( struct wlr_xdg_positioner_v6_attributes *positioner); #endif diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 36ecc897..0a698e50 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -38,62 +38,84 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) { popup_create(popup->view_child.view, wlr_popup); } -static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, - struct wlr_xdg_popup_v6 *wlr_popup) { - struct roots_xdg_popup_v6 *popup = - calloc(1, sizeof(struct roots_xdg_popup_v6)); - if (popup == NULL) { - return NULL; - } - - struct wlr_xdg_surface_v6 *parent = wlr_popup->parent; - double popup_lx = wlr_popup->geometry.x; - double popup_ly = wlr_popup->geometry.y; +static void popup_get_coords(struct wlr_xdg_popup_v6 *popup, + double *sx, double *sy) { + struct wlr_xdg_surface_v6 *parent = popup->parent; + double popup_sx = popup->geometry.x; + double popup_sy = popup->geometry.y; while (parent->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { - popup_lx += parent->popup->geometry.x; - popup_ly += parent->popup->geometry.y; + popup_sx += parent->popup->geometry.x; + popup_sy += parent->popup->geometry.y; parent = parent->popup->parent; } - popup_lx += view->x + parent->geometry.x; - popup_ly += view->y + parent->geometry.y; + *sx = popup_sx + parent->geometry.x; + *sy = popup_sy + parent->geometry.y; +} + +static void popup_is_constrained(struct roots_xdg_popup_v6 *popup, + bool *x_constrained, bool *y_constrained) { + struct roots_view *view = popup->view_child.view; + struct wlr_output_layout *layout = view->desktop->layout; + struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; int popup_width = wlr_popup->geometry.width; int popup_height = wlr_popup->geometry.height; - int anchor_x, anchor_y; - wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_x, &anchor_y); - anchor_x += popup_lx; - anchor_y += popup_ly; + int anchor_lx, anchor_ly; + wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); - struct wlr_output_layout *layout = view->desktop->layout; + double popup_lx, popup_ly; + popup_get_coords(wlr_popup, &popup_lx, &popup_ly); + popup_lx += view->x; + popup_ly += view->y; + + anchor_lx += popup_lx; + anchor_ly += popup_ly; + + double dest_x = 0, dest_y = 0; + wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, + &dest_x, &dest_y); - // get the output that contains (or closest to) the anchor point struct wlr_output *output = - wlr_output_layout_output_at(layout, anchor_x, anchor_y); - if (output == NULL) { - // TODO find the closest output to the anchor - assert(false); - } + wlr_output_layout_output_at(layout, dest_x, dest_y); + // XXX: handle empty output layout + assert(output); - // does the output completely contain the popup? struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); - bool output_contains_popup_x = popup_lx >= output_box->x && - popup_lx + popup_width <= output_box->x + output_box->width; - bool output_contains_popup_y = popup_ly >= output_box->y && - popup_ly + popup_height <= output_box->y + output_box->height; - - if (!output_contains_popup_x) { - // TODO flip_x - // TODO slide_x - // TODO resize_x - } + *x_constrained = popup_lx <= output_box->x || + popup_lx + popup_width >= output_box->x + output_box->width; + *y_constrained = popup_ly <= output_box->y || + popup_ly + popup_height >= output_box->y + output_box->height; +} + +static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { + bool x_constrained, y_constrained; + popup_is_constrained(popup, &x_constrained, &y_constrained); - if (!output_contains_popup_y) { - // TODO flip_y - // TODO slide_y - // TODO resize_y + if (x_constrained) { + wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); } + if (y_constrained) { + wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); + } + + popup->wlr_popup->geometry = + wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); +} + +static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { + popup_unconstrain_flip(popup); + // TODO popup_unconstrain_slide(popup); + // TODO popup_unconstrain_resize(popup); +} +static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, + struct wlr_xdg_popup_v6 *wlr_popup) { + struct roots_xdg_popup_v6 *popup = + calloc(1, sizeof(struct roots_xdg_popup_v6)); + if (popup == NULL) { + return NULL; + } popup->wlr_popup = wlr_popup; popup->view_child.destroy = popup_destroy; view_child_init(&popup->view_child, view, wlr_popup->base->surface); @@ -101,6 +123,9 @@ static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); + + popup_unconstrain(popup); + return popup; } diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index fc3a38d4..76340a3c 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -399,9 +399,7 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client, positioner, xdg_positioner_destroy); } -static struct wlr_box xdg_positioner_get_geometry( - struct wlr_xdg_positioner_v6_attributes *positioner, - struct wlr_xdg_surface_v6 *surface, struct wlr_xdg_surface_v6 *parent) { +struct wlr_box wlr_xdg_positioner_v6_get_geometry(struct wlr_xdg_positioner_v6_attributes *positioner) { struct wlr_box geometry = { .x = positioner->offset.x, .y = positioner->offset.y, @@ -589,7 +587,7 @@ static void xdg_surface_handle_get_popup(struct wl_client *client, surface->popup->base = surface; surface->popup->parent = parent; surface->popup->geometry = - xdg_positioner_get_geometry(positioner->attrs, surface, parent); + wlr_xdg_positioner_v6_get_geometry(positioner->attrs); // positioner properties memcpy(&surface->popup->positioner, positioner->attrs, @@ -1675,50 +1673,39 @@ void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, */ } -void wlr_positioner_v6_invert( - struct wlr_xdg_positioner_v6_attributes *positioner) { - enum wlr_positioner_v6_anchor anchor = positioner->anchor; +void wlr_positioner_v6_invert_x(struct wlr_xdg_positioner_v6_attributes *positioner) { + if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_LEFT) { + positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_LEFT; + positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_RIGHT; + } else if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_RIGHT) { + positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_RIGHT; + positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_LEFT; + } - if (anchor == WLR_POSITIONER_V6_ANCHOR_NONE) { - // already inverted - } else if (anchor == WLR_POSITIONER_V6_ANCHOR_TOP) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_BOTTOM; - } else if (anchor == WLR_POSITIONER_V6_ANCHOR_BOTTOM) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_TOP; - } else if (anchor == WLR_POSITIONER_V6_ANCHOR_LEFT) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_RIGHT; - } else if (anchor == WLR_POSITIONER_V6_ANCHOR_RIGHT) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_LEFT; - } else if (anchor == (WLR_POSITIONER_V6_ANCHOR_TOP | - WLR_POSITIONER_V6_ANCHOR_LEFT)) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_BOTTOM | WLR_POSITIONER_V6_ANCHOR_RIGHT; - } else if (anchor == (WLR_POSITIONER_V6_ANCHOR_TOP | - WLR_POSITIONER_V6_ANCHOR_RIGHT)) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_BOTTOM | WLR_POSITIONER_V6_ANCHOR_LEFT; - } else if (anchor == (WLR_POSITIONER_V6_ANCHOR_BOTTOM | - WLR_POSITIONER_V6_ANCHOR_LEFT)) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_TOP | WLR_POSITIONER_V6_ANCHOR_RIGHT; - } else if (anchor == (WLR_POSITIONER_V6_ANCHOR_BOTTOM | - WLR_POSITIONER_V6_ANCHOR_RIGHT)) { - positioner->anchor = WLR_POSITIONER_V6_ANCHOR_TOP | WLR_POSITIONER_V6_ANCHOR_LEFT; + if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_RIGHT) { + positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_RIGHT; + positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_LEFT; + } else if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_LEFT) { + positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_LEFT; + positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_RIGHT; } +} - enum wlr_positioner_v6_gravity gravity = positioner->gravity; - switch (gravity) { - case WLR_POSITIONER_V6_GRAVITY_NONE: - // already inverted - break; - case WLR_POSITIONER_V6_GRAVITY_TOP: - positioner->gravity = WLR_POSITIONER_V6_GRAVITY_BOTTOM; - break; - case WLR_POSITIONER_V6_GRAVITY_BOTTOM: - positioner->gravity = WLR_POSITIONER_V6_GRAVITY_TOP; - break; - case WLR_POSITIONER_V6_GRAVITY_LEFT: - positioner->gravity = WLR_POSITIONER_V6_GRAVITY_RIGHT; - break; - case WLR_POSITIONER_V6_GRAVITY_RIGHT: - positioner->gravity = WLR_POSITIONER_V6_GRAVITY_LEFT; - break; +void wlr_positioner_v6_invert_y( + struct wlr_xdg_positioner_v6_attributes *positioner) { + if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_TOP) { + positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_TOP; + positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_BOTTOM; + } else if (positioner->anchor & WLR_POSITIONER_V6_ANCHOR_BOTTOM) { + positioner->anchor &= ~WLR_POSITIONER_V6_ANCHOR_BOTTOM; + positioner->anchor |= WLR_POSITIONER_V6_ANCHOR_TOP; + } + + if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_TOP) { + positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_TOP; + positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_BOTTOM; + } else if (positioner->gravity & WLR_POSITIONER_V6_GRAVITY_BOTTOM) { + positioner->gravity &= ~WLR_POSITIONER_V6_GRAVITY_BOTTOM; + positioner->gravity |= WLR_POSITIONER_V6_GRAVITY_TOP; } } -- cgit v1.2.3 From 9ff84db06d44aed7188cb574a6e877d93a12e8df Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 27 Mar 2018 15:13:35 -0400 Subject: unconstrain stubs --- rootston/xdg_shell_v6.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 0a698e50..60e2b541 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -103,10 +103,34 @@ static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); } +static void popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { + bool x_constrained, y_constrained; + popup_is_constrained(popup, &x_constrained, &y_constrained); + + if (x_constrained) { + // TODO slide_x + } + if (y_constrained) { + // TODO slide_y + } +} + +static void popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { + bool x_constrained, y_constrained; + popup_is_constrained(popup, &x_constrained, &y_constrained); + + if (x_constrained) { + // TODO resize_x + } + if (y_constrained) { + // TODO resize_y + } +} + static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { popup_unconstrain_flip(popup); - // TODO popup_unconstrain_slide(popup); - // TODO popup_unconstrain_resize(popup); + popup_unconstrain_slide(popup); + popup_unconstrain_resize(popup); } static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, -- cgit v1.2.3 From edb643fc6c55b47dd766b4e516b16108719d1ecd Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 27 Mar 2018 17:16:08 -0400 Subject: basic xdg-positioner --- rootston/xdg_shell_v6.c | 101 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 8 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 60e2b541..f5cb2cd7 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -92,6 +92,26 @@ static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { bool x_constrained, y_constrained; popup_is_constrained(popup, &x_constrained, &y_constrained); + if (!x_constrained && !y_constrained) { + return; + } + + if (x_constrained) { + wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); + } + if (y_constrained) { + wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); + } + + popup->wlr_popup->geometry = + wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); + + popup_is_constrained(popup, &x_constrained, &y_constrained); + + if (!x_constrained && !y_constrained) { + return; + } + if (x_constrained) { wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); } @@ -104,26 +124,91 @@ static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { } static void popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { - bool x_constrained, y_constrained; - popup_is_constrained(popup, &x_constrained, &y_constrained); + struct roots_view *view = popup->view_child.view; + struct wlr_output_layout *layout = view->desktop->layout; + struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; + int popup_width = wlr_popup->geometry.width; + int popup_height = wlr_popup->geometry.height; + + int anchor_lx, anchor_ly; + wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + + double popup_lx, popup_ly; + popup_get_coords(wlr_popup, &popup_lx, &popup_ly); + popup_lx += view->x; + popup_ly += view->y; + + anchor_lx += popup_lx; + anchor_ly += popup_ly; + + double dest_x = 0, dest_y = 0; + wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, + &dest_x, &dest_y); + + struct wlr_output *output = + wlr_output_layout_output_at(layout, dest_x, dest_y); + // XXX: handle empty output layout + assert(output); + + struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + + bool x_constrained = popup_lx <= output_box->x || + popup_lx + popup_width >= output_box->x + output_box->width; + bool y_constrained = popup_ly <= output_box->y || + popup_ly + popup_height >= output_box->y + output_box->height; + + double popup_ox = popup_lx - output_box->x, + popup_oy = popup_ly - output_box->y; if (x_constrained) { - // TODO slide_x + wlr_popup->geometry.x -= popup_width - (output_box->width - popup_ox); } if (y_constrained) { - // TODO slide_y + wlr_popup->geometry.y -= popup_height - (output_box->height - popup_oy); } } static void popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { - bool x_constrained, y_constrained; - popup_is_constrained(popup, &x_constrained, &y_constrained); + struct roots_view *view = popup->view_child.view; + struct wlr_output_layout *layout = view->desktop->layout; + struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; + int popup_width = wlr_popup->geometry.width; + int popup_height = wlr_popup->geometry.height; + + int anchor_lx, anchor_ly; + wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); + + double popup_lx, popup_ly; + popup_get_coords(wlr_popup, &popup_lx, &popup_ly); + popup_lx += view->x; + popup_ly += view->y; + + anchor_lx += popup_lx; + anchor_ly += popup_ly; + + double dest_x = 0, dest_y = 0; + wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, + &dest_x, &dest_y); + + struct wlr_output *output = + wlr_output_layout_output_at(layout, dest_x, dest_y); + // XXX: handle empty output layout + assert(output); + + struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + + bool x_constrained = popup_lx <= output_box->x || + popup_lx + popup_width >= output_box->x + output_box->width; + bool y_constrained = popup_ly <= output_box->y || + popup_ly + popup_height >= output_box->y + output_box->height; + + double popup_ox = popup_lx - output_box->x, popup_oy = popup_ly - output_box->y; if (x_constrained) { - // TODO resize_x + wlr_popup->geometry.width = output_box->x + output_box->width - popup_ox; } if (y_constrained) { - // TODO resize_y + wlr_popup->geometry.height = output_box->y + output_box->height - popup_oy; } } -- cgit v1.2.3 From 738f5e33440eac4f1619c639784b9815f451285a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 11:42:01 -0400 Subject: cleanup xdg-positioner rootston code --- rootston/xdg_shell_v6.c | 151 +++++++++++++++++++----------------------------- 1 file changed, 60 insertions(+), 91 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index e3c70e96..5fa016a0 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -65,8 +65,8 @@ static void popup_get_coords(struct wlr_xdg_popup_v6 *popup, *sy = popup_sy + parent->geometry.y; } -static void popup_is_constrained(struct roots_xdg_popup_v6 *popup, - bool *x_constrained, bool *y_constrained) { +static void popup_constraint_offset(struct roots_xdg_popup_v6 *popup, + int *offset_x, int *offset_y) { struct roots_view *view = popup->view_child.view; struct wlr_output_layout *layout = view->desktop->layout; struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; @@ -94,134 +94,103 @@ static void popup_is_constrained(struct roots_xdg_popup_v6 *popup, assert(output); struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); - *x_constrained = popup_lx <= output_box->x || + bool x_constrained = popup_lx <= output_box->x || popup_lx + popup_width >= output_box->x + output_box->width; - *y_constrained = popup_ly <= output_box->y || + bool y_constrained = popup_ly <= output_box->y || popup_ly + popup_height >= output_box->y + output_box->height; + + *offset_x = *offset_y = 0; + + double popup_ox = popup_lx - output_box->x; + double popup_oy = popup_ly - output_box->y; + + if (x_constrained) { + *offset_x = popup_width - (output_box->width - popup_ox); + } + + if (y_constrained) { + *offset_y = popup_height - (output_box->height - popup_oy); + } } -static void popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { - bool x_constrained, y_constrained; - popup_is_constrained(popup, &x_constrained, &y_constrained); +static bool popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { + int offset_x, offset_y; + popup_constraint_offset(popup, &offset_y, &offset_y); - if (!x_constrained && !y_constrained) { - return; + if (!offset_x && !offset_y) { + return true; } - if (x_constrained) { + if (offset_x) { wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); } - if (y_constrained) { + if (offset_y) { wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); } popup->wlr_popup->geometry = wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); - popup_is_constrained(popup, &x_constrained, &y_constrained); + popup_constraint_offset(popup, &offset_x, &offset_y); - if (!x_constrained && !y_constrained) { - return; + if (!offset_x && !offset_y) { + // no longer constrained + return true; } - if (x_constrained) { + // revert the positioner back if it didn't fix it and go to the next part + if (offset_x) { wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); } - if (y_constrained) { + if (offset_y) { wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); } popup->wlr_popup->geometry = wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); -} - -static void popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { - struct roots_view *view = popup->view_child.view; - struct wlr_output_layout *layout = view->desktop->layout; - struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; - int popup_width = wlr_popup->geometry.width; - int popup_height = wlr_popup->geometry.height; - - int anchor_lx, anchor_ly; - wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); - - double popup_lx, popup_ly; - popup_get_coords(wlr_popup, &popup_lx, &popup_ly); - popup_lx += view->x; - popup_ly += view->y; - - anchor_lx += popup_lx; - anchor_ly += popup_ly; - - double dest_x = 0, dest_y = 0; - wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, - &dest_x, &dest_y); - struct wlr_output *output = - wlr_output_layout_output_at(layout, dest_x, dest_y); - // XXX: handle empty output layout - assert(output); - - struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + return false; +} - bool x_constrained = popup_lx <= output_box->x || - popup_lx + popup_width >= output_box->x + output_box->width; - bool y_constrained = popup_ly <= output_box->y || - popup_ly + popup_height >= output_box->y + output_box->height; +static bool popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { + int offset_x, offset_y; + popup_constraint_offset(popup, &offset_x, &offset_y); - double popup_ox = popup_lx - output_box->x, - popup_oy = popup_ly - output_box->y; + if (!offset_x && !offset_y) { + return true; + } - if (x_constrained) { - wlr_popup->geometry.x -= popup_width - (output_box->width - popup_ox); + if (offset_x) { + popup->wlr_popup->geometry.x -= offset_x; } - if (y_constrained) { - wlr_popup->geometry.y -= popup_height - (output_box->height - popup_oy); + if (offset_y) { + popup->wlr_popup->geometry.y -= abs(offset_y); } -} - -static void popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { - struct roots_view *view = popup->view_child.view; - struct wlr_output_layout *layout = view->desktop->layout; - struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; - int popup_width = wlr_popup->geometry.width; - int popup_height = wlr_popup->geometry.height; - int anchor_lx, anchor_ly; - wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); - - double popup_lx, popup_ly; - popup_get_coords(wlr_popup, &popup_lx, &popup_ly); - popup_lx += view->x; - popup_ly += view->y; + popup_constraint_offset(popup, &offset_y, &offset_y); - anchor_lx += popup_lx; - anchor_ly += popup_ly; + return !offset_x && !offset_y; +} - double dest_x = 0, dest_y = 0; - wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly, - &dest_x, &dest_y); +static bool popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { + int offset_x, offset_y; + popup_constraint_offset(popup, &offset_x, &offset_y); - struct wlr_output *output = - wlr_output_layout_output_at(layout, dest_x, dest_y); - // XXX: handle empty output layout - assert(output); + if (!offset_x && !offset_y) { + return true; + } - struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); + if (offset_x) { + popup->wlr_popup->geometry.width -= offset_x; + } + if (offset_y) { + popup->wlr_popup->geometry.height -= offset_y; + } - bool x_constrained = popup_lx <= output_box->x || - popup_lx + popup_width >= output_box->x + output_box->width; - bool y_constrained = popup_ly <= output_box->y || - popup_ly + popup_height >= output_box->y + output_box->height; + popup_constraint_offset(popup, &offset_y, &offset_y); - double popup_ox = popup_lx - output_box->x, popup_oy = popup_ly - output_box->y; + return !offset_x && !offset_y; - if (x_constrained) { - wlr_popup->geometry.width = output_box->x + output_box->width - popup_ox; - } - if (y_constrained) { - wlr_popup->geometry.height = output_box->y + output_box->height - popup_oy; - } } static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { -- cgit v1.2.3 From e2c4e1ef541f825eeb804d0873d305213c3fbb82 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 12:12:00 -0400 Subject: fix xdg-positioner left constrain bug --- rootston/xdg_shell_v6.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 5fa016a0..1e85a933 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -94,21 +94,21 @@ static void popup_constraint_offset(struct roots_xdg_popup_v6 *popup, assert(output); struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); - bool x_constrained = popup_lx <= output_box->x || - popup_lx + popup_width >= output_box->x + output_box->width; - bool y_constrained = popup_ly <= output_box->y || - popup_ly + popup_height >= output_box->y + output_box->height; *offset_x = *offset_y = 0; double popup_ox = popup_lx - output_box->x; double popup_oy = popup_ly - output_box->y; - if (x_constrained) { + if (popup_lx < output_box->x) { + *offset_x = output_box->x - popup_lx; + } else if (popup_lx + popup_width > output_box->x + output_box->width) { *offset_x = popup_width - (output_box->width - popup_ox); } - if (y_constrained) { + if (popup_ly < output_box->y) { + *offset_y = output_box->y - popup_ly; + } else if (popup_ly + popup_height > output_box->y + output_box->height) { *offset_y = popup_height - (output_box->height - popup_oy); } } @@ -161,10 +161,10 @@ static bool popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { } if (offset_x) { - popup->wlr_popup->geometry.x -= offset_x; + popup->wlr_popup->geometry.x += offset_x; } if (offset_y) { - popup->wlr_popup->geometry.y -= abs(offset_y); + popup->wlr_popup->geometry.y += offset_y; } popup_constraint_offset(popup, &offset_y, &offset_y); -- cgit v1.2.3 From c5cd8050986ad71e954e054445c42120e5868700 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 12:46:41 -0400 Subject: positioner rootston cleanup and bugfix --- rootston/xdg_shell_v6.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 1e85a933..9bcdb4c9 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -97,19 +97,16 @@ static void popup_constraint_offset(struct roots_xdg_popup_v6 *popup, *offset_x = *offset_y = 0; - double popup_ox = popup_lx - output_box->x; - double popup_oy = popup_ly - output_box->y; - if (popup_lx < output_box->x) { *offset_x = output_box->x - popup_lx; } else if (popup_lx + popup_width > output_box->x + output_box->width) { - *offset_x = popup_width - (output_box->width - popup_ox); + *offset_x = output_box->x + output_box->width - (popup_lx + popup_width); } if (popup_ly < output_box->y) { *offset_y = output_box->y - popup_ly; } else if (popup_ly + popup_height > output_box->y + output_box->height) { - *offset_y = popup_height - (output_box->height - popup_oy); + *offset_y = output_box->y + output_box->height - (popup_ly + popup_height); } } @@ -163,6 +160,7 @@ static bool popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { if (offset_x) { popup->wlr_popup->geometry.x += offset_x; } + if (offset_y) { popup->wlr_popup->geometry.y += offset_y; } -- cgit v1.2.3 From dbffda7549de4dba6b595e9bcaaef1628463315f Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 16:27:08 -0400 Subject: xdg-positioner wlr abstractions --- include/wlr/types/wlr_xdg_shell_v6.h | 31 ++++++- rootston/xdg_shell_v6.c | 134 +++------------------------- types/wlr_xdg_shell_v6.c | 165 ++++++++++++++++++++++++++--------- 3 files changed, 167 insertions(+), 163 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index e2a58669..0ab57108 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -302,18 +302,45 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at( struct wlr_xdg_surface_v6 *surface, double sx, double sy, double *popup_sx, double *popup_sy); +/** + * Get the geometry for this positioner based on the anchor rect, gravity, and + * size of this positioner. + */ struct wlr_box wlr_xdg_positioner_v6_get_geometry( struct wlr_xdg_positioner_v6_attributes *positioner); /** - * Get the anchor point for this popup in the root parent's coordinate system. + * Get the anchor point for this popup in the toplevel parent's coordinate system. */ void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, - int *root_sx, int *root_sy); + int *toplevel_sx, int *toplevel_sy); + +/** + * Convert the given coordinates in the popup coordinate system to the toplevel + * surface coordinate system. + */ +void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup, + int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy); + +/** + * Set the geometry of this popup to unconstrain it according to its + * xdg-positioner rules. The box should be in the popup's toplevel + * parent surface coordinate system. + */ +void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box); +/** + Invert the right/left anchor and gravity for this positioner. This can be + used to "flip" the positioner around the anchor rect in the x direction. + */ void wlr_positioner_v6_invert_x( struct wlr_xdg_positioner_v6_attributes *positioner); +/** + Invert the top/bottom anchor and gravity for this positioner. This can be + used to "flip" the positioner around the anchor rect in the y direction. + */ void wlr_positioner_v6_invert_y( struct wlr_xdg_positioner_v6_attributes *positioner); diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 9bcdb4c9..22309e8e 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -50,34 +50,17 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) { popup_create(popup->view_child.view, wlr_popup); } -static void popup_get_coords(struct wlr_xdg_popup_v6 *popup, - double *sx, double *sy) { - struct wlr_xdg_surface_v6 *parent = popup->parent; - double popup_sx = popup->geometry.x; - double popup_sy = popup->geometry.y; - while (parent->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { - popup_sx += parent->popup->geometry.x; - popup_sy += parent->popup->geometry.y; - parent = parent->popup->parent; - } - - *sx = popup_sx + parent->geometry.x; - *sy = popup_sy + parent->geometry.y; -} - -static void popup_constraint_offset(struct roots_xdg_popup_v6 *popup, - int *offset_x, int *offset_y) { +static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { struct roots_view *view = popup->view_child.view; struct wlr_output_layout *layout = view->desktop->layout; struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; - int popup_width = wlr_popup->geometry.width; - int popup_height = wlr_popup->geometry.height; int anchor_lx, anchor_ly; wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly); - double popup_lx, popup_ly; - popup_get_coords(wlr_popup, &popup_lx, &popup_ly); + int popup_lx, popup_ly; + wlr_xdg_popup_v6_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x, + wlr_popup->geometry.y, &popup_lx, &popup_ly); popup_lx += view->x; popup_ly += view->y; @@ -93,108 +76,17 @@ static void popup_constraint_offset(struct roots_xdg_popup_v6 *popup, // XXX: handle empty output layout assert(output); - struct wlr_box *output_box = wlr_output_layout_get_box(layout, output); - - *offset_x = *offset_y = 0; - - if (popup_lx < output_box->x) { - *offset_x = output_box->x - popup_lx; - } else if (popup_lx + popup_width > output_box->x + output_box->width) { - *offset_x = output_box->x + output_box->width - (popup_lx + popup_width); - } - - if (popup_ly < output_box->y) { - *offset_y = output_box->y - popup_ly; - } else if (popup_ly + popup_height > output_box->y + output_box->height) { - *offset_y = output_box->y + output_box->height - (popup_ly + popup_height); - } -} - -static bool popup_unconstrain_flip(struct roots_xdg_popup_v6 *popup) { - int offset_x, offset_y; - popup_constraint_offset(popup, &offset_y, &offset_y); - - if (!offset_x && !offset_y) { - return true; - } - - if (offset_x) { - wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); - } - if (offset_y) { - wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); - } - - popup->wlr_popup->geometry = - wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); - - popup_constraint_offset(popup, &offset_x, &offset_y); - - if (!offset_x && !offset_y) { - // no longer constrained - return true; - } - - // revert the positioner back if it didn't fix it and go to the next part - if (offset_x) { - wlr_positioner_v6_invert_x(&popup->wlr_popup->positioner); - } - if (offset_y) { - wlr_positioner_v6_invert_y(&popup->wlr_popup->positioner); - } + int width = 0, height = 0; + wlr_output_effective_resolution(output, &width, &height); - popup->wlr_popup->geometry = - wlr_xdg_positioner_v6_get_geometry(&popup->wlr_popup->positioner); + struct wlr_box toplevel_box = { + .x = output->lx - view->x, + .y = output->ly - view->y, + .width = width, + .height = height + }; - return false; -} - -static bool popup_unconstrain_slide(struct roots_xdg_popup_v6 *popup) { - int offset_x, offset_y; - popup_constraint_offset(popup, &offset_x, &offset_y); - - if (!offset_x && !offset_y) { - return true; - } - - if (offset_x) { - popup->wlr_popup->geometry.x += offset_x; - } - - if (offset_y) { - popup->wlr_popup->geometry.y += offset_y; - } - - popup_constraint_offset(popup, &offset_y, &offset_y); - - return !offset_x && !offset_y; -} - -static bool popup_unconstrain_resize(struct roots_xdg_popup_v6 *popup) { - int offset_x, offset_y; - popup_constraint_offset(popup, &offset_x, &offset_y); - - if (!offset_x && !offset_y) { - return true; - } - - if (offset_x) { - popup->wlr_popup->geometry.width -= offset_x; - } - if (offset_y) { - popup->wlr_popup->geometry.height -= offset_y; - } - - popup_constraint_offset(popup, &offset_y, &offset_y); - - return !offset_x && !offset_y; - -} - -static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { - popup_unconstrain_flip(popup); - popup_unconstrain_slide(popup); - popup_unconstrain_resize(popup); + wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &toplevel_box); } static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 0a8bbadf..0cf215ab 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -1674,48 +1674,133 @@ void wlr_xdg_popup_v6_get_anchor_point(struct wlr_xdg_popup_v6 *popup, *root_sx = sx; *root_sy = sy; +} - /* - // XXX: THIS IS WILL WORK WITH XDG SHELL STABLE - switch (popup->positioner.anchor) { - case WLR_POSITIONER_ANCHOR_NONE: - sx = (rect.x + rect.width) / 2; - sy = (rect.y + rect.height) / 2; - break; - case WLR_POSITIONER_ANCHOR_TOP: - sx = (rect.x + rect.width) / 2; - sy = rect.y; - break; - case WLR_POSITIONER_ANCHOR_BOTTOM: - sx = (rect.x + rect.width) / 2; - sy = rect.y + rect.height; - break; - case WLR_POSITIONER_ANCHOR_LEFT: - sx = rect.x; - sy = (rect.y + rect.height) / 2; - break; - case WLR_POSITIONER_ANCHOR_RIGHT: - sx = rect.x + rect.width; - sy = (rect.y + rect.height) / 2; - break; - case WLR_POSITIONER_ANCHOR_TOP_LEFT: - sx = rect.x; - sy = rect.y; - break; - case WLR_POSITIONER_ANCHOR_BOTTOM_LEFT: - sx = rect.x; - sy = rect.y + rect.height; - break; - case WLR_POSITIONER_ANCHOR_TOP_RIGHT: - sx = rect.x + rect.width; - sy = rect.y; - break; - case WLR_POSITIONER_ANCHOR_BOTTOM_RIGHT: - sx = rect.x + rect.width; - sy = rect.y + rect.height; - break; +void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup, + int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy) { + struct wlr_xdg_surface_v6 *parent = popup->parent; + while (parent->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { + popup_sx += parent->popup->geometry.x; + popup_sy += parent->popup->geometry.y; + parent = parent->popup->parent; + } + + *toplevel_sx = popup_sx + parent->geometry.x; + *toplevel_sy = popup_sy + parent->geometry.y; + +} + +static void wlr_xdg_popup_v6_box_constraints(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box, int *offset_x, int *offset_y) { + int popup_width = popup->geometry.width; + int popup_height = popup->geometry.height; + int anchor_sx = 0, anchor_sy = 0; + wlr_xdg_popup_v6_get_anchor_point(popup, &anchor_sx, &anchor_sy); + int popup_sx = 0, popup_sy = 0; + wlr_xdg_popup_v6_get_toplevel_coords(popup, popup->geometry.x, + popup->geometry.y, &popup_sx, &popup_sy); + *offset_x = 0, *offset_y = 0; + + if (popup_sx < toplevel_box->x) { + *offset_x = toplevel_box->x - popup_sx; + } else if (popup_sx + popup_width > toplevel_box->x + toplevel_box->width) { + *offset_x = toplevel_box->x + toplevel_box->width - (popup_sx + popup_width); + } + + if (popup_sy < toplevel_box->y) { + *offset_y = toplevel_box->y - popup_sy; + } else if (popup_sy + popup_height > toplevel_box->y + toplevel_box->height) { + *offset_y = toplevel_box->y + toplevel_box->height - (popup_sy + popup_height); + } +} + +static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box) { + int offset_x = 0, offset_y = 0; + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_y, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + if (offset_x) { + wlr_positioner_v6_invert_x(&popup->positioner); + } + if (offset_y) { + wlr_positioner_v6_invert_y(&popup->positioner); + } + + popup->geometry = + wlr_xdg_positioner_v6_get_geometry(&popup->positioner); + + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + // no longer constrained + return true; } - */ + + // revert the positioner back if it didn't fix it and go to the next part + if (offset_x) { + wlr_positioner_v6_invert_x(&popup->positioner); + } + if (offset_y) { + wlr_positioner_v6_invert_y(&popup->positioner); + } + + popup->geometry = + wlr_xdg_positioner_v6_get_geometry(&popup->positioner); + + return false; +} + +static bool wlr_xdg_popup_v6_unconstrain_slide(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box) { + int offset_x, offset_y; + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + if (offset_x) { + popup->geometry.x += offset_x; + } + + if (offset_y) { + popup->geometry.y += offset_y; + } + + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + + return !offset_x && !offset_y; +} + +static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box) { + int offset_x, offset_y; + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + + if (!offset_x && !offset_y) { + return true; + } + + if (offset_x) { + popup->geometry.width -= offset_x; + } + if (offset_y) { + popup->geometry.height -= offset_y; + } + + wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_y, &offset_y); + + return !offset_x && !offset_y; +} + +void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup, + struct wlr_box *toplevel_box) { + wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_box); + wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_box); } void wlr_positioner_v6_invert_x(struct wlr_xdg_positioner_v6_attributes *positioner) { -- cgit v1.2.3 From 0bfcce50a9e3fe8e06d225c69a686041311ae484 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 16:55:16 -0400 Subject: xdg-positioner: honor constraint flags --- rootston/xdg_shell_v6.c | 3 +++ types/wlr_xdg_shell_v6.c | 53 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 12 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 22309e8e..9062995d 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -51,6 +51,9 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) { } static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { + // get the output of the popup's positioner anchor point and convert it to + // the toplevel parent's coordinate system and then pass it to + // wlr_xdg_popup_v6_unconstrain_from_box struct roots_view *view = popup->view_child.view; struct wlr_output_layout *layout = view->desktop->layout; struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 0cf215ab..9b700b55 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -1723,28 +1723,34 @@ static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup, return true; } - if (offset_x) { + bool flip_x = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X); + + bool flip_y = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y); + + if (flip_x) { wlr_positioner_v6_invert_x(&popup->positioner); } - if (offset_y) { + if (flip_y) { wlr_positioner_v6_invert_y(&popup->positioner); } popup->geometry = wlr_xdg_positioner_v6_get_geometry(&popup->positioner); - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); - if (!offset_x && !offset_y) { // no longer constrained return true; } // revert the positioner back if it didn't fix it and go to the next part - if (offset_x) { + if (flip_x) { wlr_positioner_v6_invert_x(&popup->positioner); } - if (offset_y) { + if (flip_y) { wlr_positioner_v6_invert_y(&popup->positioner); } @@ -1763,11 +1769,19 @@ static bool wlr_xdg_popup_v6_unconstrain_slide(struct wlr_xdg_popup_v6 *popup, return true; } - if (offset_x) { + bool slide_x = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X); + + bool slide_y = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y); + + if (slide_x) { popup->geometry.x += offset_x; } - if (offset_y) { + if (slide_y) { popup->geometry.y += offset_y; } @@ -1785,10 +1799,18 @@ static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup, return true; } - if (offset_x) { + bool resize_x = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X); + + bool resize_y = offset_x && + (popup->positioner.constraint_adjustment & + WLR_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y); + + if (resize_x) { popup->geometry.width -= offset_x; } - if (offset_y) { + if (resize_y) { popup->geometry.height -= offset_y; } @@ -1799,8 +1821,15 @@ static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup, void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup, struct wlr_box *toplevel_box) { - wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_box); - wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_box); + if (wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_box)) { + return; + } + if (wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_box)) { + return; + } + if (wlr_xdg_popup_v6_unconstrain_resize(popup, toplevel_box)) { + return; + } } void wlr_positioner_v6_invert_x(struct wlr_xdg_positioner_v6_attributes *positioner) { -- cgit v1.2.3 From 67c8aec77f27aa08528a69894a045a48d67bd658 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 18:36:48 -0400 Subject: popup constraint handle empty output layout --- rootston/xdg_shell_v6.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 9062995d..fe63e697 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -76,8 +76,10 @@ static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { struct wlr_output *output = wlr_output_layout_output_at(layout, dest_x, dest_y); - // XXX: handle empty output layout - assert(output); + + if (output == NULL) { + return; + } int width = 0, height = 0; wlr_output_effective_resolution(output, &width, &height); -- cgit v1.2.3 From 71da20dbdefd137d53bbbdb7bfd6f242c1698548 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 20:51:25 -0400 Subject: add comment for output box in toplevel coords --- rootston/xdg_shell_v6.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index fe63e697..295d9ff4 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -84,14 +84,16 @@ static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { int width = 0, height = 0; wlr_output_effective_resolution(output, &width, &height); - struct wlr_box toplevel_box = { + // the output box expressed in the coordinate system of the toplevel parent + // of the popup + struct wlr_box output_box_toplevel = { .x = output->lx - view->x, .y = output->ly - view->y, .width = width, .height = height }; - wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &toplevel_box); + wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &output_box_toplevel); } static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, -- cgit v1.2.3 From 27f450ac0eb254dad03c11b14d4785c16dac0c51 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 22:26:56 -0400 Subject: add todo for rotated unconstrained popup --- rootston/xdg_shell_v6.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'rootston') diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 295d9ff4..0aca9638 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -54,6 +54,12 @@ static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { // get the output of the popup's positioner anchor point and convert it to // the toplevel parent's coordinate system and then pass it to // wlr_xdg_popup_v6_unconstrain_from_box + + // TODO: unconstrain popups for rotated windows + if (popup->view_child.view->rotation != 0.0) { + return; + } + struct roots_view *view = popup->view_child.view; struct wlr_output_layout *layout = view->desktop->layout; struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup; -- cgit v1.2.3 From 2e63d1a0ca01d71de58988593860741b835ba8bb Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 28 Mar 2018 23:24:39 -0400 Subject: toplevel_box to toplevel_sx_box --- include/wlr/types/wlr_xdg_shell_v6.h | 6 +-- rootston/xdg_shell_v6.c | 4 +- types/wlr_xdg_shell_v6.c | 84 +++++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 39 deletions(-) (limited to 'rootston') diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 04c7e450..d01240eb 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -269,11 +269,11 @@ void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup, /** * Set the geometry of this popup to unconstrain it according to its - * xdg-positioner rules. The box should be in the popup's toplevel - * parent surface coordinate system. + * xdg-positioner rules. The box should be in the popup's root toplevel parent + * surface coordinate system. */ void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box); + struct wlr_box *toplevel_sx_box); /** Invert the right/left anchor and gravity for this positioner. This can be diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 0aca9638..39e8a4b7 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -92,14 +92,14 @@ static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) { // the output box expressed in the coordinate system of the toplevel parent // of the popup - struct wlr_box output_box_toplevel = { + struct wlr_box output_toplevel_sx_box = { .x = output->lx - view->x, .y = output->ly - view->y, .width = width, .height = height }; - wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &output_box_toplevel); + wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &output_toplevel_sx_box); } static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view, diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index 44bd8d9a..64d44f22 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -97,8 +97,8 @@ static void xdg_keyboard_grab_enter(struct wlr_seat_keyboard_grab *grab, // keyboard focus should remain on the popup } -static void xdg_keyboard_grab_key(struct wlr_seat_keyboard_grab *grab, uint32_t time, - uint32_t key, uint32_t state) { +static void xdg_keyboard_grab_key(struct wlr_seat_keyboard_grab *grab, + uint32_t time, uint32_t key, uint32_t state) { wlr_seat_keyboard_send_key(grab->seat, time, key, state); } @@ -425,7 +425,8 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client, positioner, xdg_positioner_destroy); } -struct wlr_box wlr_xdg_positioner_v6_get_geometry(struct wlr_xdg_positioner_v6 *positioner) { +struct wlr_box wlr_xdg_positioner_v6_get_geometry( + struct wlr_xdg_positioner_v6 *positioner) { struct wlr_box geometry = { .x = positioner->offset.x, .y = positioner->offset.y, @@ -582,7 +583,8 @@ static void xdg_surface_handle_get_popup(struct wl_client *client, struct wlr_xdg_positioner_v6_resource *positioner = xdg_positioner_from_resource(positioner_resource); - if (positioner->attrs.size.width == 0 || positioner->attrs.anchor_rect.width == 0) { + if (positioner->attrs.size.width == 0 || + positioner->attrs.anchor_rect.width == 0) { wl_resource_post_error(resource, ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER, "positioner object is not complete"); @@ -1089,7 +1091,8 @@ static void wlr_xdg_toplevel_v6_send_configure( if (surface->toplevel->server_pending.maximized) { s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { - wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel"); + wlr_log(L_ERROR, + "Could not allocate state for maximized xdg_toplevel"); goto error_out; } *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED; @@ -1097,7 +1100,8 @@ static void wlr_xdg_toplevel_v6_send_configure( if (surface->toplevel->server_pending.fullscreen) { s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { - wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel"); + wlr_log(L_ERROR, + "Could not allocate state for fullscreen xdg_toplevel"); goto error_out; } *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN; @@ -1105,7 +1109,8 @@ static void wlr_xdg_toplevel_v6_send_configure( if (surface->toplevel->server_pending.resizing) { s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { - wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel"); + wlr_log(L_ERROR, + "Could not allocate state for resizing xdg_toplevel"); goto error_out; } *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING; @@ -1113,7 +1118,8 @@ static void wlr_xdg_toplevel_v6_send_configure( if (surface->toplevel->server_pending.activated) { s = wl_array_add(&states, sizeof(uint32_t)); if (!s) { - wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel"); + wlr_log(L_ERROR, + "Could not allocate state for activated xdg_toplevel"); goto error_out; } *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED; @@ -1688,7 +1694,7 @@ void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup, } static void wlr_xdg_popup_v6_box_constraints(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box, int *offset_x, int *offset_y) { + struct wlr_box *toplevel_sx_box, int *offset_x, int *offset_y) { int popup_width = popup->geometry.width; int popup_height = popup->geometry.height; int anchor_sx = 0, anchor_sy = 0; @@ -1698,23 +1704,28 @@ static void wlr_xdg_popup_v6_box_constraints(struct wlr_xdg_popup_v6 *popup, popup->geometry.y, &popup_sx, &popup_sy); *offset_x = 0, *offset_y = 0; - if (popup_sx < toplevel_box->x) { - *offset_x = toplevel_box->x - popup_sx; - } else if (popup_sx + popup_width > toplevel_box->x + toplevel_box->width) { - *offset_x = toplevel_box->x + toplevel_box->width - (popup_sx + popup_width); + if (popup_sx < toplevel_sx_box->x) { + *offset_x = toplevel_sx_box->x - popup_sx; + } else if (popup_sx + popup_width > + toplevel_sx_box->x + toplevel_sx_box->width) { + *offset_x = toplevel_sx_box->x + toplevel_sx_box->width - + (popup_sx + popup_width); } - if (popup_sy < toplevel_box->y) { - *offset_y = toplevel_box->y - popup_sy; - } else if (popup_sy + popup_height > toplevel_box->y + toplevel_box->height) { - *offset_y = toplevel_box->y + toplevel_box->height - (popup_sy + popup_height); + if (popup_sy < toplevel_sx_box->y) { + *offset_y = toplevel_sx_box->y - popup_sy; + } else if (popup_sy + popup_height > + toplevel_sx_box->y + toplevel_sx_box->height) { + *offset_y = toplevel_sx_box->y + toplevel_sx_box->height - + (popup_sy + popup_height); } } static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box) { + struct wlr_box *toplevel_sx_box) { int offset_x = 0, offset_y = 0; - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); if (!offset_x && !offset_y) { return true; @@ -1738,7 +1749,8 @@ static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup, popup->geometry = wlr_xdg_positioner_v6_get_geometry(&popup->positioner); - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); if (!offset_x && !offset_y) { // no longer constrained @@ -1760,9 +1772,10 @@ static bool wlr_xdg_popup_v6_unconstrain_flip(struct wlr_xdg_popup_v6 *popup, } static bool wlr_xdg_popup_v6_unconstrain_slide(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box) { + struct wlr_box *toplevel_sx_box) { int offset_x = 0, offset_y = 0; - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); if (!offset_x && !offset_y) { return true; @@ -1788,22 +1801,24 @@ static bool wlr_xdg_popup_v6_unconstrain_slide(struct wlr_xdg_popup_v6 *popup, wlr_xdg_popup_v6_get_toplevel_coords(popup, popup->geometry.x, popup->geometry.y, &toplevel_x, &toplevel_y); - if (slide_x && toplevel_x < toplevel_box->x) { - popup->geometry.x += toplevel_box->x - toplevel_x; + if (slide_x && toplevel_x < toplevel_sx_box->x) { + popup->geometry.x += toplevel_sx_box->x - toplevel_x; } - if (slide_y && toplevel_y < toplevel_box->y) { - popup->geometry.y += toplevel_box->y - toplevel_y; + if (slide_y && toplevel_y < toplevel_sx_box->y) { + popup->geometry.y += toplevel_sx_box->y - toplevel_y; } - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); return !offset_x && !offset_y; } static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box) { + struct wlr_box *toplevel_sx_box) { int offset_x, offset_y; - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_x, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_x, &offset_y); if (!offset_x && !offset_y) { return true; @@ -1824,20 +1839,21 @@ static bool wlr_xdg_popup_v6_unconstrain_resize(struct wlr_xdg_popup_v6 *popup, popup->geometry.height -= offset_y; } - wlr_xdg_popup_v6_box_constraints(popup, toplevel_box, &offset_y, &offset_y); + wlr_xdg_popup_v6_box_constraints(popup, toplevel_sx_box, + &offset_y, &offset_y); return !offset_x && !offset_y; } void wlr_xdg_popup_v6_unconstrain_from_box(struct wlr_xdg_popup_v6 *popup, - struct wlr_box *toplevel_box) { - if (wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_box)) { + struct wlr_box *toplevel_sx_box) { + if (wlr_xdg_popup_v6_unconstrain_flip(popup, toplevel_sx_box)) { return; } - if (wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_box)) { + if (wlr_xdg_popup_v6_unconstrain_slide(popup, toplevel_sx_box)) { return; } - if (wlr_xdg_popup_v6_unconstrain_resize(popup, toplevel_box)) { + if (wlr_xdg_popup_v6_unconstrain_resize(popup, toplevel_sx_box)) { return; } } -- cgit v1.2.3