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/output.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 sys/cmd/dwm/output.c (limited to 'sys/cmd/dwm/output.c') diff --git a/sys/cmd/dwm/output.c b/sys/cmd/dwm/output.c new file mode 100644 index 0000000..918d9a6 --- /dev/null +++ b/sys/cmd/dwm/output.c @@ -0,0 +1,257 @@ +#include "dwm.h" + +/* local callbacks */ +static void delete(struct wl_listener *ev, void *arg); +static void draw(struct wl_listener *ev, void *arg); + +/* global variables */ +Monitor *monitor = nil; + +// ----------------------------------------------------------------------- +// methods + +void +damageat(Monitor* m, double x, double y) +{ + /* TODO: don't damage the whole screen */ + wlr_output_damage_add_whole(&m->damage); +} + +void +arrange(Monitor *m) +{ + m->area.all = *wlr_output_layout_get_box(dwm.layout, m->dev); + m->area.win = m->area.all; + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +setmonitor(Client *c, Monitor *m, uint newtags) +{ + int hadfocus; + Monitor *old; + + old = c->m; + if (old == m) + return; + + hadfocus = (c == getclient()); + + c->m = m; + if (old) { + wlr_surface_send_leave(c->surf->surface, old->dev); + arrange(old); + } + + if (m) { + applybounds(c, &m->area.all); + wlr_surface_send_enter(c->surf->surface, m->dev); + c->tags = newtags ? newtags : m->tagset[m->seltags]; + arrange(m); + } + + if (hadfocus || (c == getclient())) + setfocus(lastfocus(), nil, 1); +} + +Monitor* +getmonitor(int dir) +{ + Monitor *m; + + if (dir > 0) { + if (monitor->link.next == &dwm.odevs) + return wl_container_of(dwm.odevs.next, m, link); + return wl_container_of(monitor->link.next, m, link); + } + if (monitor->link.prev == &dwm.odevs) + return wl_container_of(dwm.odevs.prev, m, link); + return wl_container_of(monitor->link.prev, m, link); +} + +Monitor * +monitorat(double x, double y) +{ + struct wlr_output *dev; + + dev = wlr_output_layout_output_at(dwm.layout, x, y); + return dev ? dev->data : nil; +} + +// ----------------------------------------------------------------------- +// callback function implementations +void +ev·newmonitor(struct wl_listener *ev, void *arg) +{ + Monitor *m; + const MonitorRule *r; + struct wlr_output *dev; + struct wlr_output_mode *mode; + + dev = arg; + wlr_output_set_mode(dev, wlr_output_preferred_mode(dev)); + + m = dev->data = calloc(1, sizeof(*m)); + m->dev = dev; + m->tagset[0] = m->tagset[1] = 1; + /* look for rules to apply */ + for (r = monitorrules; r < arrend(monitorrules); r++) { + if (!r->name || strstr(dev->name, r->name)) { + m->mfact = r->mfact; + m->nmaster = r->nmaster; + wlr_output_set_scale(dev, r->scale); + wlr_xcursor_manager_load(mouse.manager, r->scale); + m->lt[0] = m->lt[1] = r->lt; + wlr_output_set_transform(dev, r->rr); + break; + } + } + + /* install callbacks */ + m->ev.draw.notify = draw; + m->ev.free.notify = delete; + + wl_signal_add(&dev->events.frame, &m->ev.draw); + wl_signal_add(&dev->events.destroy, &m->ev.free); + + wl_list_insert(&dwm.odevs, &m->link); + + wl_list_init(&m->layers[0]); + wl_list_init(&m->layers[1]); + wl_list_init(&m->layers[2]); + wl_list_init(&m->layers[3]); + + wlr_output_enable(dev, 1); + if (!wlr_output_commit(dev)) + return; + + wl_signal_init(&m->sig.kill); + + wlr_output_layout_add_auto(dwm.layout, dev); + dwm.dim = *wlr_output_layout_get_box(dwm.layout, nil); +} + +static +void +delete(struct wl_listener *ev, void *arg) +{ + Monitor *m; + + m = wl_container_of(ev, m, ev.free); + wl_signal_emit(&m->sig.kill, m); + + wl_list_remove(&m->link); + wl_list_remove(&m->ev.draw.link); + wl_list_remove(&m->ev.free.link); + + free(m); +} + +static +void +render(struct wlr_surface *surf, int sx, int sy, void *arg) +{ + Payload *data; + double x, y; + float mtx[9]; + struct wlr_box box; + struct wlr_output *dev; + struct wlr_texture *tex; + enum wl_output_transform transform; + + data = arg; + dev = data->dev; + + tex = wlr_surface_get_texture(surf); + if (!tex) + return; + + /* convert to device local coord */ + wlr_output_layout_output_coords(dwm.layout, dev, &x, &y); + + box.x = x + data->x + sx; + box.y = y + data->y + sy; + box.width = surf->current.width; + box.height = surf->current.height; + scale(&box, dev->scale); + + /* orthographic projection */ + transform = wlr_output_transform_invert(surf->current.transform); + wlr_matrix_project_box(mtx, &box, transform, 0, dev->transform_matrix); + + /* render with GPU */ + wlr_render_texture_with_matrix(dwm.draw, tex, mtx, 1); + + /* notify the client we are done */ + wlr_surface_send_frame_done(surf, data->now); +} + +static +void +renderclients(Monitor *m, struct timespec *now) +{ + Client *c; + double x, y; + int i, w, h; + Payload data; + struct wlr_box *borders; + + wl_list_for_each_reverse(c, &dwm.stack, link.stack) { + if (!VISIBLEON(c, c->m) || !wlr_output_layout_intersects(dwm.layout, m->dev, &c->dim)) + continue; + + x = c->dim.x; + y = c->dim.y; + + wlr_output_layout_output_coords(dwm.layout, m->dev, &x, &y); + + w = c->surf->surface->current.width; + h = c->surf->surface->current.height; + + borders = (struct wlr_box[4]) { + {x, y, w + 2 * c->bw, c->bw}, /* top */ + {x, y + c->bw, c->bw, h}, /* left */ + {x + c->bw + w, y + c->bw, c->bw, h}, /* right */ + {x, y + c->bw + h, w + 2 * c->bw, c->bw}, /* bottom */ + }; + for (i = 0; i < 4; i++) { + scale(&borders[i], m->dev->scale); + wlr_render_rect(dwm.draw, &borders[i], bordercolor, m->dev->transform_matrix); + } + + data.dev = m->dev; + data.now = now; + data.x = c->dim.x + c->bw; + data.y = c->dim.y + c->bw; + + wlr_xdg_surface_for_each_surface(c->surf, render, &data); + } +} + +static +void +draw(struct wl_listener *ev, void *arg) +{ + int w, h; + Monitor *m; + struct timespec now; + + m = wl_container_of(ev, m, ev.draw); + + if (!wlr_output_attach_render(m->dev, nil)) + return; + + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_output_effective_resolution(m->dev, &w, &h); + + wlr_renderer_begin(dwm.draw, w, h); + wlr_renderer_clear(dwm.draw, rootcolor); + + renderclients(m, &now); + + wlr_output_render_software_cursors(m->dev, nil); + + wlr_renderer_end(dwm.draw); + wlr_output_commit(m->dev); +} -- cgit v1.2.1