aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/desktop.c23
-rw-r--r--rootston/layer_shell.c78
-rw-r--r--rootston/output.c6
-rw-r--r--rootston/xdg_shell.c56
4 files changed, 158 insertions, 5 deletions
diff --git a/rootston/desktop.c b/rootston/desktop.c
index 0949b5db..6ac665bc 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -641,11 +641,24 @@ static struct wlr_surface *layer_surface_at(struct roots_output *output,
struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
struct roots_layer_surface *roots_surface;
wl_list_for_each_reverse(roots_surface, layer, link) {
- struct wlr_surface *wlr_surface =
- roots_surface->layer_surface->surface;
- double _sx = ox - roots_surface->geo.x;
- double _sy = oy - roots_surface->geo.y;
- // TODO: Test popups/subsurfaces
+ struct wlr_surface *wlr_surface;
+ double _sx, _sy;
+ struct wlr_xdg_popup *popup;
+ wl_list_for_each(popup, &roots_surface->layer_surface->popups, link) {
+ wlr_surface = popup->base->surface;
+ _sx = ox - roots_surface->geo.x - popup->geometry.x;
+ _sy = oy - roots_surface->geo.y - popup->geometry.y;
+ if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) {
+ *sx = _sx;
+ *sy = _sy;
+ return wlr_surface;
+ }
+ // TODO: popups can have popups
+ }
+ // TODO: Test subsurfaces
+ wlr_surface = roots_surface->layer_surface->surface;
+ _sx = ox - roots_surface->geo.x;
+ _sy = oy - roots_surface->geo.y;
if (wlr_surface_point_accepts_input(wlr_surface, _sx, _sy)) {
*sx = _sx;
*sy = _sy;
diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c
index b6f7ba4c..071467e0 100644
--- a/rootston/layer_shell.c
+++ b/rootston/layer_shell.c
@@ -292,6 +292,82 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
unmap(layer->layer_surface);
}
+static void popup_handle_map(struct wl_listener *listener, void *data) {
+ struct roots_layer_popup *popup = wl_container_of(listener, popup, map);
+ struct roots_layer_surface *layer = popup->parent;
+ struct wlr_output *wlr_output = layer->layer_surface->output;
+ struct roots_output *output = wlr_output->data;
+ struct wlr_box geom;
+ memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box));
+ geom.x += layer->geo.x;
+ geom.y += layer->geo.y;
+ wlr_output_damage_add_box(output->damage, &geom);
+}
+
+static void popup_handle_unmap(struct wl_listener *listener, void *data) {
+ struct roots_layer_popup *popup = wl_container_of(listener, popup, unmap);
+ struct roots_layer_surface *layer = popup->parent;
+ struct wlr_output *wlr_output = layer->layer_surface->output;
+ struct roots_output *output = wlr_output->data;
+ struct wlr_box geom;
+ memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box));
+ geom.x += layer->geo.x;
+ geom.y += layer->geo.y;
+ wlr_output_damage_add_box(output->damage, &geom);
+}
+
+static void popup_handle_commit(struct wl_listener *listener, void *data) {
+ struct roots_layer_popup *popup = wl_container_of(listener, popup, commit);
+ struct roots_layer_surface *layer = popup->parent;
+ struct wlr_output *wlr_output = layer->layer_surface->output;
+ struct roots_output *output = wlr_output->data;
+ struct wlr_box geom;
+ memcpy(&geom, &popup->wlr_popup->geometry, sizeof(struct wlr_box));
+ geom.x += layer->geo.x;
+ geom.y += layer->geo.y;
+ wlr_output_damage_add_box(output->damage, &geom);
+}
+
+static void popup_handle_destroy(struct wl_listener *listener, void *data) {
+ struct roots_layer_popup *popup =
+ wl_container_of(listener, popup, destroy);
+
+ wl_list_remove(&popup->map.link);
+ wl_list_remove(&popup->unmap.link);
+ wl_list_remove(&popup->destroy.link);
+ wl_list_remove(&popup->commit.link);
+ free(popup);
+}
+
+static struct roots_layer_popup *popup_create(struct roots_layer_surface *parent,
+ struct wlr_xdg_popup *wlr_popup) {
+ struct roots_layer_popup *popup =
+ calloc(1, sizeof(struct roots_layer_popup));
+ if (popup == NULL) {
+ return NULL;
+ }
+ popup->wlr_popup = wlr_popup;
+ popup->parent = parent;
+ popup->map.notify = popup_handle_map;
+ wl_signal_add(&wlr_popup->base->events.map, &popup->map);
+ popup->unmap.notify = popup_handle_unmap;
+ wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
+ popup->destroy.notify = popup_handle_destroy;
+ wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
+ popup->commit.notify = popup_handle_commit;
+ wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
+ /* TODO: popups can have popups, see xdg_shell::popup_create */
+
+ return popup;
+}
+
+static void handle_new_popup(struct wl_listener *listener, void *data) {
+ struct roots_layer_surface *roots_layer_surface =
+ wl_container_of(listener, roots_layer_surface, new_popup);
+ struct wlr_xdg_popup *wlr_popup = data;
+ popup_create(roots_layer_surface, wlr_popup);
+}
+
void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
struct wlr_layer_surface *layer_surface = data;
struct roots_desktop *desktop =
@@ -338,6 +414,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
wl_signal_add(&layer_surface->events.map, &roots_surface->map);
roots_surface->unmap.notify = handle_unmap;
wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap);
+ roots_surface->new_popup.notify = handle_new_popup;
+ wl_signal_add(&layer_surface->events.new_popup, &roots_surface->new_popup);
// TODO: Listen for subsurfaces
roots_surface->layer_surface = layer_surface;
diff --git a/rootston/output.c b/rootston/output.c
index 791b2819..225b7213 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -366,6 +366,8 @@ static void render_layer(struct roots_output *output,
roots_surface->geo.x + output_layout_box->x,
roots_surface->geo.y + output_layout_box->y,
0, &data->layout, render_surface, data);
+
+ wlr_layer_surface_for_each_surface(layer, render_surface, data);
}
}
@@ -377,6 +379,10 @@ static void layers_send_done(
wl_list_for_each(roots_surface, &output->layers[i], link) {
struct wlr_layer_surface *layer = roots_surface->layer_surface;
wlr_surface_send_frame_done(layer->surface, when);
+ struct wlr_xdg_popup *popup;
+ wl_list_for_each(popup, &roots_surface->layer_surface->popups, link) {
+ wlr_surface_send_frame_done(popup->base->surface, when);
+ }
}
}
}
diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c
index 927bd018..bd670a87 100644
--- a/rootston/xdg_shell.c
+++ b/rootston/xdg_shell.c
@@ -48,6 +48,59 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
popup_create(popup->view_child.view, wlr_popup);
}
+static void popup_unconstrain(struct roots_xdg_popup *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 *wlr_popup = popup->wlr_popup;
+
+ int anchor_lx, anchor_ly;
+ wlr_xdg_popup_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly);
+
+ int popup_lx, popup_ly;
+ wlr_xdg_popup_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;
+
+ 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);
+
+ if (output == NULL) {
+ return;
+ }
+
+ int width = 0, height = 0;
+ wlr_output_effective_resolution(output, &width, &height);
+
+ // the output box expressed in the coordinate system of the toplevel parent
+ // of the popup
+ struct wlr_box output_toplevel_sx_box = {
+ .x = output->lx - view->x,
+ .y = output->ly - view->y,
+ .width = width,
+ .height = height
+ };
+
+ wlr_xdg_popup_unconstrain_from_box(
+ popup->wlr_popup, &output_toplevel_sx_box);
+}
+
static struct roots_xdg_popup *popup_create(struct roots_view *view,
struct wlr_xdg_popup *wlr_popup) {
struct roots_xdg_popup *popup =
@@ -66,6 +119,9 @@ static struct roots_xdg_popup *popup_create(struct roots_view *view,
wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
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;
}