From 0a8f62d8c7116be9e344f351df679599908fb29c Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 4 Jun 2020 19:10:07 -0700 Subject: refactored --- sys/cmd/dwm/layer.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 sys/cmd/dwm/layer.c (limited to 'sys/cmd/dwm/layer.c') diff --git a/sys/cmd/dwm/layer.c b/sys/cmd/dwm/layer.c new file mode 100644 index 0000000..4c1ddcb --- /dev/null +++ b/sys/cmd/dwm/layer.c @@ -0,0 +1,329 @@ +#include "dwm.h" + +/* local callbacks */ +static void delete(struct wl_listener *ev, void *arg); +static void map(struct wl_listener *ev, void *arg); +static void unmap(struct wl_listener *ev, void *arg); +static void commit(struct wl_listener *ev, void *arg); +static void detach(struct wl_listener *ev, void *arg); + +// ----------------------------------------------------------------------- +// methods + +static +void +applyexclusive(struct wlr_box *area, uint32 anchor, int ex, int32 mt, int32 mr, int32 mb, int32 ml) +{ + if (ex <= 0) + return; + struct { + uint32 singular_anchor; + uint32 anchor_triplet; + int *positive_axis; + int *negative_axis; + int margin; + } edges[] = { + // Top + { + .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, + .anchor_triplet = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, + .positive_axis = &area->y, + .negative_axis = &area->height, + .margin = mt, + }, + // Bottom + { + .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .anchor_triplet = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = NULL, + .negative_axis = &area->height, + .margin = mb, + }, + // Left + { + .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT, + .anchor_triplet = + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = &area->x, + .negative_axis = &area->width, + .margin = ml, + }, + // Right + { + .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT, + .anchor_triplet = + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, + .positive_axis = NULL, + .negative_axis = &area->width, + .margin = mr, + }, + }; + for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { + if ((anchor == edges[i].singular_anchor || anchor == edges[i].anchor_triplet) + && ex + edges[i].margin > 0) { + if (edges[i].positive_axis) { + *edges[i].positive_axis += ex + edges[i].margin; + } + if (edges[i].negative_axis) { + *edges[i].negative_axis -= ex + edges[i].margin; + } + break; + } + } +} + +static +void +arrangelayer(Monitor *m, struct wl_list *layers, struct wlr_box *area, int ex) +{ + Layer *l; + uint32 horiz, vert; + struct wlr_box fullarea; + struct wlr_box box; + struct wlr_layer_surface_v1 *layer; + struct wlr_layer_surface_v1_state *state; + + wlr_output_effective_resolution(m->dev, &fullarea.width, &fullarea.height); + wl_list_for_each(l, layers, link) { + layer = l->surf; + state = &layer->current; + + if (ex != (state->exclusive_zone > 0)) + continue; + + struct wlr_box bounds; + if (state->exclusive_zone == -1) + bounds = fullarea; + else + bounds = *area; + + box = (struct wlr_box){ + .width = state->desired_width, + .height = state->desired_height + }; + + // Horizontal axis + horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if ((state->anchor & horiz) && box.width == 0) { + box.x = bounds.x; + box.width = bounds.width; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x = bounds.x; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x = bounds.x + (bounds.width - box.width); + } else { + box.x = bounds.x + ((bounds.width / 2) - (box.width / 2)); + } + // Vertical axis + vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + if ((state->anchor & vert) && box.height == 0) { + box.y = bounds.y; + box.height = bounds.height; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y = bounds.y; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y = bounds.y + (bounds.height - box.height); + } else { + box.y = bounds.y + ((bounds.height / 2) - (box.height / 2)); + } + // Margin + if ((state->anchor & horiz) == horiz) { + box.x += state->margin.left; + box.width -= state->margin.left + state->margin.right; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) { + box.x += state->margin.left; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + box.x -= state->margin.right; + } + if ((state->anchor & vert) == vert) { + box.y += state->margin.top; + box.height -= state->margin.top + state->margin.bottom; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) { + box.y += state->margin.top; + } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + box.y -= state->margin.bottom; + } + if (box.width < 0 || box.height < 0) { + // TODO: Bubble up a protocol error? + wlr_layer_surface_v1_close(layer); + continue; + } + l->dim= box; + applyexclusive(area, state->anchor, state->exclusive_zone, + state->margin.top, state->margin.right, state->margin.bottom, state->margin.left); + + wlr_layer_surface_v1_configure(layer, box.width, box.height); + } +} + +void +arrangelayers(Monitor *m) +{ + int i; + Layer *it, *top; + struct wlr_box area; + + wlr_output_effective_resolution(m->dev, &area.width, &area.height); + + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 1); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 1); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 1); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 1); + + if (memcmp(&area, &m->area.win, sizeof(struct wlr_box)) != 0) { + memcpy(&m->area.win, &area, sizeof(struct wlr_box)); + arrange(m); + } + + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &area, 0); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &area, 0); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &area, 0); + arrangelayer(m, &m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &area, 0); + + uint32 layers[] = { + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + }; + + top = nil; + for (i = 0; i < arrlen(layers); i++) { + wl_list_for_each_reverse(it, &m->layers[layers[i]], link) { + if (it->surf->current.keyboard_interactive && it->surf->mapped) { + top = it; + break; + } + } + if (top) + break; + } + /* TODO: set focus here? */ +} + + +// ----------------------------------------------------------------------- +// implementations + +void +ev·newlayershell(struct wl_listener *ev, void *arg) +{ + Monitor *m; + Layer *layer; + struct wlr_layer_surface_v1 *surf; + struct wlr_layer_surface_v1_state old; + + surf = arg; + if (!surf->output) + surf->output = monitor->dev; + + layer = surf->data = calloc(1, sizeof(*layer)); + layer->surf = surf; + + /* install callbacks */ + layer->ev.free.notify = delete; + layer->ev.map.notify = map; + layer->ev.unmap.notify = unmap; + layer->ev.commit.notify = commit; + layer->ev.detach.notify = detach; + + wl_signal_add(&surf->events.destroy, &layer->ev.free); + wl_signal_add(&surf->events.map, &layer->ev.map); + wl_signal_add(&surf->events.unmap, &layer->ev.unmap); + wl_signal_add(&surf->surface->events.commit, &layer->ev.commit); + wl_signal_add(&monitor->sig.kill, &layer->ev.detach); + + m = surf->output->data; + wl_list_insert(&m->layers[surf->client_pending.layer], &layer->link); + + /* song and dance: set as pending, arrange, then reset */ + old = surf->current; + surf->current = surf->client_pending; + arrangelayers(m); +} + +static +void +delete(struct wl_listener *ev, void *arg) +{ + Layer *l; + + l = wl_container_of(ev, l, ev.map); + + wl_list_remove(&l->link); + wl_list_remove(&l->ev.free.link); + wl_list_remove(&l->ev.map.link); + wl_list_remove(&l->ev.unmap.link); + wl_list_remove(&l->ev.detach.link); + wl_list_remove(&l->ev.commit.link); + + free(l); +} + +static +void +detach(struct wl_listener *ev, void *arg) +{ + /* no op */ +} + + +static +void +map(struct wl_listener *ev, void *arg) +{ + Layer *l; + Monitor *m; + + l = wl_container_of(ev, l, ev.map); + m = l->surf->output->data; + /* TODO: damage */ + wlr_surface_send_enter(l->surf->surface, l->surf->output); + /* TODO: cursor */ +} + +static +void +unmap(struct wl_listener *ev, void *arg) +{ + /* TODO: fill in */ +} + +static +void +commit(struct wl_listener *ev, void *arg) +{ + Layer *l; + Monitor *m; + char newdim, newlayer; + struct wlr_box old; + struct wlr_layer_surface_v1 *surf; + struct wlr_output *dev; + + l = wl_container_of(ev, l, ev.commit); + surf = l->surf; + dev = surf->output; + + m = dev->data; + old = l->dim; + arrangelayers(m); + + newdim = memcmp(&old, &l->dim, sizeof(struct wlr_box)) != 0; + newlayer = l->z != surf->current.layer; + + if (newdim) { + wl_list_remove(&l->link); + wl_list_insert(&m->layers[surf->current.layer], &l->link); + l->z = surf->current.layer; + } +} -- cgit v1.2.1