656 lines
18 KiB
C
656 lines
18 KiB
C
#ifdef HAVE_LAYERSHELL
|
|
#include <hikari/layer_shell.h>
|
|
|
|
#ifndef NDEBUG
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
#include <wlr/types/wlr_seat.h>
|
|
#include <wlr/types/wlr_xdg_shell.h>
|
|
|
|
#include <hikari/memory.h>
|
|
#include <hikari/output.h>
|
|
#include <hikari/server.h>
|
|
|
|
static void
|
|
map_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
unmap_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
commit_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
destroy_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
new_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
for_each_surface(struct hikari_view_interface *view_interface,
|
|
void (*func)(struct wlr_surface *, int, int, void *),
|
|
void *data);
|
|
|
|
static struct wlr_surface *
|
|
surface_at(struct hikari_view_interface *view_interface,
|
|
double ox,
|
|
double oy,
|
|
double *sx,
|
|
double *sy);
|
|
|
|
static void
|
|
focus(struct hikari_view_interface *view_interface);
|
|
|
|
static void
|
|
calculate_geometry(struct hikari_layer *layer);
|
|
|
|
static void
|
|
init_layer_popup(struct hikari_layer_popup *layer_popup,
|
|
struct hikari_layer *parent,
|
|
struct wlr_xdg_popup *popup);
|
|
|
|
static void
|
|
init_popup_popup(struct hikari_layer_popup *layer_popup,
|
|
struct hikari_layer_popup *parent,
|
|
struct wlr_xdg_popup *popup);
|
|
|
|
static void
|
|
fini_popup(struct hikari_layer_popup *layer_popup);
|
|
|
|
static void
|
|
commit_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
destroy_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
map_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
unmap_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
destroy_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static void
|
|
new_popup_popup_handler(struct wl_listener *listener, void *data);
|
|
|
|
static struct hikari_layer *
|
|
get_layer(struct hikari_layer_popup *popup);
|
|
|
|
static void
|
|
apply_layer_state(struct wlr_box *usable_area,
|
|
uint32_t anchor,
|
|
int32_t exclusive,
|
|
int32_t margin_top,
|
|
int32_t margin_right,
|
|
int32_t margin_bottom,
|
|
int32_t margin_left)
|
|
{
|
|
if (exclusive <= 0) {
|
|
return;
|
|
}
|
|
struct {
|
|
uint32_t anchors;
|
|
int *positive_axis;
|
|
int *negative_axis;
|
|
int margin;
|
|
} edges[] = {
|
|
{
|
|
.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
|
|
.positive_axis = &usable_area->y,
|
|
.negative_axis = &usable_area->height,
|
|
.margin = margin_top,
|
|
},
|
|
{
|
|
.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
.positive_axis = NULL,
|
|
.negative_axis = &usable_area->height,
|
|
.margin = margin_bottom,
|
|
},
|
|
{
|
|
.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
.positive_axis = &usable_area->x,
|
|
.negative_axis = &usable_area->width,
|
|
.margin = margin_left,
|
|
},
|
|
{
|
|
.anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
|
|
.positive_axis = NULL,
|
|
.negative_axis = &usable_area->width,
|
|
.margin = margin_right,
|
|
},
|
|
};
|
|
for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
|
|
if ((anchor & edges[i].anchors) == edges[i].anchors &&
|
|
exclusive + edges[i].margin > 0) {
|
|
if (edges[i].positive_axis) {
|
|
*edges[i].positive_axis += exclusive + edges[i].margin;
|
|
}
|
|
if (edges[i].negative_axis) {
|
|
*edges[i].negative_axis -= exclusive + edges[i].margin;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
calculate_exclusive(struct hikari_output *output)
|
|
{
|
|
struct wlr_box usable_area = { 0 };
|
|
|
|
wlr_output_effective_resolution(
|
|
output->output, &usable_area.width, &usable_area.height);
|
|
struct hikari_layer *layer;
|
|
wl_list_for_each (
|
|
layer, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], layer_surfaces) {
|
|
struct wlr_layer_surface_v1 *wlr_layer = layer->surface;
|
|
struct wlr_layer_surface_v1_state *state = &wlr_layer->current;
|
|
|
|
apply_layer_state(&usable_area,
|
|
state->anchor,
|
|
state->exclusive_zone,
|
|
state->margin.top,
|
|
state->margin.right,
|
|
state->margin.bottom,
|
|
state->margin.left);
|
|
}
|
|
|
|
output->usable_area = usable_area;
|
|
}
|
|
|
|
void
|
|
hikari_layer_init(
|
|
struct hikari_layer *layer, struct wlr_layer_surface_v1 *wlr_layer_surface)
|
|
{
|
|
#ifndef NDEBUG
|
|
printf("LAYER INIT %p\n", layer);
|
|
#endif
|
|
|
|
struct hikari_output *output = hikari_server.workspace->output;
|
|
|
|
layer->view_interface.surface_at = surface_at;
|
|
layer->view_interface.focus = focus;
|
|
layer->view_interface.for_each_surface = for_each_surface;
|
|
layer->output = output;
|
|
layer->layer = wlr_layer_surface->client_pending.layer;
|
|
layer->surface = wlr_layer_surface;
|
|
|
|
wlr_layer_surface->output = output->output;
|
|
|
|
layer->commit.notify = commit_handler;
|
|
wl_signal_add(&wlr_layer_surface->surface->events.commit, &layer->commit);
|
|
|
|
layer->destroy.notify = destroy_handler;
|
|
wl_signal_add(&wlr_layer_surface->surface->events.destroy, &layer->destroy);
|
|
|
|
layer->map.notify = map_handler;
|
|
wl_signal_add(&wlr_layer_surface->events.map, &layer->map);
|
|
|
|
layer->unmap.notify = unmap_handler;
|
|
wl_signal_add(&wlr_layer_surface->events.unmap, &layer->unmap);
|
|
|
|
layer->new_popup.notify = new_popup_handler;
|
|
wl_signal_add(&wlr_layer_surface->events.new_popup, &layer->new_popup);
|
|
|
|
wl_list_insert(&output->layers[layer->layer], &layer->layer_surfaces);
|
|
|
|
calculate_geometry(layer);
|
|
}
|
|
|
|
void
|
|
hikari_layer_fini(struct hikari_layer *layer)
|
|
{
|
|
wl_list_remove(&layer->layer_surfaces);
|
|
|
|
wl_list_remove(&layer->commit.link);
|
|
wl_list_remove(&layer->destroy.link);
|
|
wl_list_remove(&layer->map.link);
|
|
wl_list_remove(&layer->unmap.link);
|
|
wl_list_remove(&layer->new_popup.link);
|
|
}
|
|
|
|
static void
|
|
popup_unconstrain(struct hikari_layer_popup *layer_popup)
|
|
{
|
|
struct hikari_layer *layer = get_layer(layer_popup);
|
|
struct hikari_output *output = layer->output;
|
|
|
|
struct wlr_box box = { .x = -layer->geometry.x,
|
|
.y = -layer->geometry.y,
|
|
.width = output->geometry.width,
|
|
.height = output->geometry.height };
|
|
|
|
wlr_xdg_popup_unconstrain_from_box(layer_popup->popup, &box);
|
|
}
|
|
|
|
static void
|
|
init_popup(
|
|
struct hikari_layer_popup *layer_popup, struct wlr_xdg_popup *wlr_popup)
|
|
{
|
|
layer_popup->popup = wlr_popup;
|
|
|
|
layer_popup->commit.notify = commit_popup_handler;
|
|
wl_signal_add(&wlr_popup->base->surface->events.commit, &layer_popup->commit);
|
|
|
|
layer_popup->map.notify = map_popup_handler;
|
|
wl_signal_add(&wlr_popup->base->events.map, &layer_popup->map);
|
|
|
|
layer_popup->unmap.notify = unmap_popup_handler;
|
|
wl_signal_add(&wlr_popup->base->events.unmap, &layer_popup->unmap);
|
|
|
|
layer_popup->destroy.notify = destroy_popup_handler;
|
|
wl_signal_add(&wlr_popup->base->events.destroy, &layer_popup->destroy);
|
|
|
|
layer_popup->new_popup.notify = new_popup_popup_handler;
|
|
wl_signal_add(&wlr_popup->base->events.new_popup, &layer_popup->new_popup);
|
|
|
|
popup_unconstrain(layer_popup);
|
|
}
|
|
|
|
static struct hikari_layer *
|
|
get_layer(struct hikari_layer_popup *layer_popup)
|
|
{
|
|
struct hikari_layer_popup *current = layer_popup;
|
|
for (;;) {
|
|
switch (current->parent.type) {
|
|
case HIKARI_LAYER_NODE_TYPE_LAYER:
|
|
return current->parent.node.layer;
|
|
break;
|
|
|
|
case HIKARI_LAYER_NODE_TYPE_POPUP:
|
|
current = current->parent.node.popup;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
damage(struct hikari_layer *layer, bool whole)
|
|
{
|
|
struct wlr_surface *surface = layer->surface->surface;
|
|
|
|
if (whole) {
|
|
struct wlr_box geometry = { .x = layer->geometry.x,
|
|
.y = layer->geometry.y,
|
|
.width = surface->current.width,
|
|
.height = surface->current.height };
|
|
|
|
hikari_output_add_damage(layer->output, &geometry);
|
|
} else {
|
|
pixman_region32_t damage;
|
|
pixman_region32_init(&damage);
|
|
wlr_surface_get_effective_damage(surface, &damage);
|
|
pixman_region32_translate(&damage, layer->geometry.x, layer->geometry.y);
|
|
wlr_output_damage_add(layer->output->damage, &damage);
|
|
pixman_region32_fini(&damage);
|
|
}
|
|
}
|
|
|
|
static void
|
|
damage_popup(struct hikari_layer_popup *layer_popup, bool whole)
|
|
{
|
|
struct wlr_xdg_popup *popup = layer_popup->popup;
|
|
struct wlr_surface *surface = popup->base->surface;
|
|
|
|
int popup_sx = popup->geometry.x - popup->base->geometry.x;
|
|
int popup_sy = popup->geometry.y - popup->base->geometry.y;
|
|
int ox = popup_sx, oy = popup_sy;
|
|
|
|
struct hikari_layer *layer;
|
|
struct hikari_layer_popup *current = layer_popup;
|
|
for (;;) {
|
|
switch (current->parent.type) {
|
|
case HIKARI_LAYER_NODE_TYPE_LAYER:
|
|
layer = current->parent.node.layer;
|
|
ox += layer->geometry.x;
|
|
oy += layer->geometry.y;
|
|
goto done;
|
|
|
|
case HIKARI_LAYER_NODE_TYPE_POPUP:
|
|
current = current->parent.node.popup;
|
|
ox += current->popup->geometry.x;
|
|
oy += current->popup->geometry.y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
done:
|
|
|
|
assert(layer != NULL);
|
|
|
|
struct hikari_output *output = layer->output;
|
|
|
|
if (whole) {
|
|
struct wlr_box geometry = { .x = ox,
|
|
.y = oy,
|
|
.width = surface->current.width,
|
|
.height = surface->current.height };
|
|
|
|
hikari_output_add_damage(output, &geometry);
|
|
} else {
|
|
pixman_region32_t damage;
|
|
pixman_region32_init(&damage);
|
|
wlr_surface_get_effective_damage(surface, &damage);
|
|
pixman_region32_translate(&damage, ox, oy);
|
|
wlr_output_damage_add(layer->output->damage, &damage);
|
|
pixman_region32_fini(&damage);
|
|
}
|
|
}
|
|
|
|
static void
|
|
commit_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer *layer = wl_container_of(listener, layer, commit);
|
|
struct wlr_box old_geometry = layer->geometry;
|
|
struct hikari_output *output = layer->output;
|
|
|
|
calculate_exclusive(layer->output);
|
|
calculate_geometry(layer);
|
|
|
|
enum zwlr_layer_shell_v1_layer current_layer = layer->surface->current.layer;
|
|
bool updated_geometry =
|
|
memcmp(&old_geometry, &layer->geometry, sizeof(struct wlr_box)) != 0;
|
|
bool changed_layer = layer->layer != current_layer;
|
|
|
|
if (changed_layer) {
|
|
wl_list_remove(&layer->layer_surfaces);
|
|
wl_list_insert(&output->layers[current_layer], &layer->layer_surfaces);
|
|
layer->layer = current_layer;
|
|
}
|
|
|
|
if (updated_geometry || changed_layer) {
|
|
hikari_output_add_damage(output, &old_geometry);
|
|
hikari_output_add_damage(output, &layer->geometry);
|
|
} else {
|
|
damage(layer, false);
|
|
}
|
|
}
|
|
|
|
static void
|
|
destroy_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer *layer = wl_container_of(listener, layer, destroy);
|
|
|
|
#ifndef NDEBUG
|
|
printf("LAYER DESTROY %p\n", layer);
|
|
#endif
|
|
|
|
hikari_layer_fini(layer);
|
|
|
|
calculate_exclusive(layer->output);
|
|
|
|
hikari_free(layer);
|
|
}
|
|
|
|
static void
|
|
map_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer *layer = wl_container_of(listener, layer, map);
|
|
|
|
#ifndef NDEBUG
|
|
printf("LAYER MAP %p\n", layer);
|
|
#endif
|
|
|
|
damage(layer, true);
|
|
}
|
|
|
|
static void
|
|
unmap_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer *layer = wl_container_of(listener, layer, unmap);
|
|
|
|
#ifndef NDEBUG
|
|
printf("LAYER UNMAP %p\n", layer);
|
|
#endif
|
|
|
|
damage(layer, true);
|
|
}
|
|
|
|
static void
|
|
calculate_geometry(struct hikari_layer *layer)
|
|
{
|
|
struct hikari_output *output = layer->output;
|
|
struct wlr_layer_surface_v1_state *state = &layer->surface->current;
|
|
|
|
struct wlr_box geometry = { .x = 0,
|
|
.y = 0,
|
|
.width = state->desired_width,
|
|
.height = state->desired_height };
|
|
|
|
struct wlr_box bounds = { .x = 0,
|
|
.y = 0,
|
|
.width = output->geometry.width,
|
|
.height = output->geometry.height };
|
|
|
|
const uint32_t both_horiz =
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
|
if ((state->anchor & both_horiz) && geometry.width == 0) {
|
|
geometry.x = bounds.x;
|
|
geometry.width = bounds.width;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
|
|
geometry.x = bounds.x;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
|
|
geometry.x = bounds.x + (bounds.width - geometry.width);
|
|
} else {
|
|
geometry.x = bounds.x + ((bounds.width / 2) - (geometry.width / 2));
|
|
}
|
|
|
|
const uint32_t both_vert =
|
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
|
if ((state->anchor & both_vert) && geometry.height == 0) {
|
|
geometry.y = bounds.y;
|
|
geometry.height = bounds.height;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
|
|
geometry.y = bounds.y;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
|
|
geometry.y = bounds.y + (bounds.height - geometry.height);
|
|
} else {
|
|
geometry.y = bounds.y + ((bounds.height / 2) - (geometry.height / 2));
|
|
}
|
|
|
|
if ((state->anchor & both_horiz) == both_horiz) {
|
|
geometry.x += state->margin.left;
|
|
geometry.width -= state->margin.left + state->margin.right;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
|
|
geometry.x += state->margin.left;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
|
|
geometry.x -= state->margin.right;
|
|
}
|
|
if ((state->anchor & both_vert) == both_vert) {
|
|
geometry.y += state->margin.top;
|
|
geometry.height -= state->margin.top + state->margin.bottom;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
|
|
geometry.y += state->margin.top;
|
|
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
|
|
geometry.y -= state->margin.bottom;
|
|
}
|
|
|
|
layer->geometry = geometry;
|
|
|
|
wlr_layer_surface_v1_configure(
|
|
layer->surface, geometry.width, geometry.height);
|
|
}
|
|
|
|
static void
|
|
destroy_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer_popup *layer_popup =
|
|
wl_container_of(listener, layer_popup, destroy);
|
|
|
|
#ifndef NDEBUG
|
|
printf("DESTROY LAYER POPUP %p\n", layer_popup);
|
|
#endif
|
|
|
|
fini_popup(layer_popup);
|
|
|
|
hikari_free(layer_popup);
|
|
}
|
|
|
|
static void
|
|
map_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer_popup *layer_popup =
|
|
wl_container_of(listener, layer_popup, map);
|
|
|
|
#ifndef NDEBUG
|
|
printf("MAP LAYER POPUP %p\n", layer_popup);
|
|
#endif
|
|
|
|
damage_popup(layer_popup, true);
|
|
}
|
|
|
|
static void
|
|
unmap_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer_popup *layer_popup =
|
|
wl_container_of(listener, layer_popup, unmap);
|
|
|
|
#ifndef NDEBUG
|
|
printf("UNMAP LAYER POPUP %p\n", layer_popup);
|
|
#endif
|
|
|
|
damage_popup(layer_popup, true);
|
|
}
|
|
|
|
static void
|
|
commit_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer_popup *layer_popup =
|
|
wl_container_of(listener, layer_popup, commit);
|
|
|
|
damage_popup(layer_popup, false);
|
|
}
|
|
|
|
static void
|
|
new_popup_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer_popup *layer_popup =
|
|
wl_container_of(listener, layer_popup, commit);
|
|
|
|
#ifndef NDEBUG
|
|
printf("NEW LAYER POPUP POPUP %p\n", layer_popup);
|
|
#endif
|
|
|
|
struct hikari_layer_popup *parent = layer_popup->parent.node.popup;
|
|
struct wlr_xdg_popup *wlr_popup = data;
|
|
|
|
struct hikari_layer_popup *layer_popup_popup =
|
|
hikari_malloc(sizeof(struct hikari_layer_popup));
|
|
|
|
init_popup_popup(layer_popup_popup, parent, wlr_popup);
|
|
}
|
|
|
|
static void
|
|
new_popup_handler(struct wl_listener *listener, void *data)
|
|
{
|
|
struct hikari_layer *layer = wl_container_of(listener, layer, new_popup);
|
|
|
|
#ifndef NDEBUG
|
|
printf("NEW LAYER POPUP\n");
|
|
#endif
|
|
|
|
struct hikari_layer_popup *layer_popup =
|
|
hikari_malloc(sizeof(struct hikari_layer_popup));
|
|
|
|
struct wlr_xdg_popup *wlr_popup = data;
|
|
|
|
init_layer_popup(layer_popup, layer, wlr_popup);
|
|
}
|
|
|
|
static void
|
|
focus(struct hikari_view_interface *view_interface)
|
|
{
|
|
struct hikari_layer *layer = (struct hikari_layer *)view_interface;
|
|
struct wlr_layer_surface_v1_state *state = &layer->surface->current;
|
|
|
|
if (state->keyboard_interactive) {
|
|
struct hikari_workspace *workspace = hikari_server.workspace;
|
|
struct hikari_view *focus_view = workspace->focus_view;
|
|
|
|
if (focus_view != NULL) {
|
|
hikari_workspace_focus_view(workspace, NULL);
|
|
}
|
|
|
|
struct wlr_seat *seat = hikari_server.seat;
|
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);
|
|
|
|
wlr_seat_keyboard_notify_enter(seat,
|
|
layer->surface->surface,
|
|
keyboard->keycodes,
|
|
keyboard->num_keycodes,
|
|
&keyboard->modifiers);
|
|
}
|
|
}
|
|
|
|
static void
|
|
for_each_surface(struct hikari_view_interface *view_interface,
|
|
void (*func)(struct wlr_surface *, int, int, void *),
|
|
void *data)
|
|
{
|
|
struct hikari_layer *layer = (struct hikari_layer *)view_interface;
|
|
|
|
wlr_layer_surface_v1_for_each_surface(layer->surface, func, data);
|
|
}
|
|
|
|
static struct wlr_surface *
|
|
surface_at(struct hikari_view_interface *view_interface,
|
|
double ox,
|
|
double oy,
|
|
double *sx,
|
|
double *sy)
|
|
{
|
|
struct hikari_layer *layer = (struct hikari_layer *)view_interface;
|
|
|
|
double x = ox - layer->geometry.x;
|
|
double y = oy - layer->geometry.y;
|
|
|
|
struct wlr_surface *surface =
|
|
wlr_layer_surface_v1_surface_at(layer->surface, x, y, sx, sy);
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void
|
|
init_layer_popup(struct hikari_layer_popup *layer_popup,
|
|
struct hikari_layer *parent,
|
|
struct wlr_xdg_popup *wlr_popup)
|
|
{
|
|
layer_popup->parent.type = HIKARI_LAYER_NODE_TYPE_LAYER;
|
|
layer_popup->parent.node.layer = parent;
|
|
|
|
init_popup(layer_popup, wlr_popup);
|
|
}
|
|
|
|
static void
|
|
init_popup_popup(struct hikari_layer_popup *layer_popup,
|
|
struct hikari_layer_popup *parent,
|
|
struct wlr_xdg_popup *wlr_popup)
|
|
{
|
|
layer_popup->parent.type = HIKARI_LAYER_NODE_TYPE_POPUP;
|
|
layer_popup->parent.node.popup = parent;
|
|
|
|
init_popup(layer_popup, wlr_popup);
|
|
}
|
|
|
|
static void
|
|
fini_popup(struct hikari_layer_popup *layer_popup)
|
|
{
|
|
wl_list_remove(&layer_popup->commit.link);
|
|
wl_list_remove(&layer_popup->destroy.link);
|
|
wl_list_remove(&layer_popup->map.link);
|
|
wl_list_remove(&layer_popup->unmap.link);
|
|
wl_list_remove(&layer_popup->new_popup.link);
|
|
}
|
|
|
|
#endif
|