#include "dwm.h" #define WLR_EDGE_ALL WLR_EDGE_TOP|WLR_EDGE_BOTTOM|WLR_EDGE_LEFT|WLR_EDGE_RIGHT /* local callbacks */ static void map(struct wl_listener *ev, void *arg); static void unmap(struct wl_listener *ev, void *arg); static void delete(struct wl_listener *ev, void *arg); /* globals */ static char *broken = ""; // ----------------------------------------------------------------------- // methods void applybounds(Client *c, struct wlr_box *bbox) { c->dim.width = MAX(1, c->dim.width); c->dim.height = MAX(1, c->dim.height); if (c->dim.x >= bbox->x + bbox->width) c->dim.x = bbox->x + bbox->width - c->dim.width; if (c->dim.y >= bbox->y + bbox->height) c->dim.y = bbox->y + bbox->height - c->dim.height; if (c->dim.x + c->dim.width + 2 * c->bw <= bbox->x) c->dim.x = bbox->x; if (c->dim.y + c->dim.height + 2 * c->bw <= bbox->y) c->dim.y = bbox->y; } void applyrules(Client *c) { char *id, *title; uint i, newtags = 0; const Rule *r; Monitor *m, *it; m = monitor; /* rule matching */ c->floating = 0; if (!(id = c->surf->toplevel->app_id)) id = broken; if (!(title = c->surf->toplevel->title)) title = broken; for (r = apprules; r < arrend(apprules); r++) { if ((!r->title || strstr(title, r->title)) && (!r->id || strstr(id, r->id))) { c->floating = r->floating; newtags |= r->tags; i = 0; wl_list_for_each(it, &dwm.odevs, link) if (r->monitor == i++) m = it; } } setmonitor(c, m, newtags); } void resize(Client *c, int x, int y, int w, int h, int interact) { struct wlr_box *bbox; bbox = interact ? &dwm.dim : &c->m->area.win; c->dim.x = x; c->dim.y = y; c->dim.width = w; c->dim.height = h; applybounds(c, bbox); /* wlroots makes this a no-op if size hasn't changed */ wlr_xdg_toplevel_set_size(c->surf, c->dim.width - 2*c->bw - gapwidth, c->dim.height - 2*c->bw - gapwidth); } Client * getclient(void) { Client *c; c = wl_container_of(dwm.focus.next, c, link.focus); if (wl_list_empty(&dwm.focus) || !VISIBLEON(c, monitor)) return nil; return c; } Client * clientat(double x, double y) { Client *c; wl_list_for_each(c, &dwm.stack, link.stack) if (VISIBLEON(c, c->m) && wlr_box_contains_point(&c->dim, x, y)) return c; return nil; } Client * lastfocus(void) { Client *c; wl_list_for_each(c, &dwm.focus, link.focus) if (VISIBLEON(c, monitor)) return c; return nil; } void setfocus(Client *c, struct wlr_surface *surf, int lift) { struct wlr_surface *prev_surface; struct wlr_xdg_surface *prev; struct wlr_keyboard *kb; if (c) { if (!surf) surf = c->surf->surface; monitor = c->m; } prev_surface = dwm.seat->keyboard_state.focused_surface; if (prev_surface == surf) return; if (prev_surface) { prev = wlr_xdg_surface_from_wlr_surface(dwm.seat->keyboard_state.focused_surface); wlr_xdg_toplevel_set_activated(prev, 0); } kb = wlr_seat_get_keyboard(dwm.seat); wlr_seat_keyboard_notify_enter(dwm.seat, surf, kb->keycodes, kb->num_keycodes, &kb->modifiers); if (c) { wl_list_remove(&c->link.focus); wl_list_insert(&dwm.focus, &c->link.focus); if (lift) { wl_list_remove(&c->link.stack); wl_list_insert(&dwm.stack, &c->link.stack); } wlr_xdg_toplevel_set_activated(c->surf, 1); } } void setfloating(Client *c, int f) { if (c->floating == f) return; c->floating = f; arrange(c->m); } void pointerfocus(Client *c, struct wlr_surface *surf, double sx, double sy, uint32 time) { if (c && !surf) surf = c->surf->surface; if (surf && surf == dwm.seat->pointer_state.focused_surface) { wlr_seat_pointer_notify_motion(dwm.seat, time, sx, sy); return; } wlr_seat_pointer_notify_enter(dwm.seat, surf, sx, sy); /* If keyboard focus follows mouse, enforce that */ if (sloppyfocus && surf) setfocus(c, surf, 0); } // ----------------------------------------------------------------------- // callback function implementations /* xdg-surfaces */ void ev·newclient(struct wl_listener *ev, void *arg) { Client *c; struct wlr_xdg_surface *surf; surf = arg; if (surf->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) return; c = surf->data = calloc(1, sizeof(*c)); c->surf = surf; c->bw = borderwidth; wlr_xdg_toplevel_set_tiled(surf, WLR_EDGE_ALL); /* install callbacks */ c->ev.map.notify = map; c->ev.unmap.notify = unmap; c->ev.free.notify = delete; wl_signal_add(&surf->events.map, &c->ev.map); wl_signal_add(&surf->events.unmap, &c->ev.unmap); wl_signal_add(&surf->events.destroy, &c->ev.free); } static void map(struct wl_listener *ev, void *arg) { Client *c; c = wl_container_of(ev, c, ev.map); wl_list_insert(&dwm.tiles, &c->link.tiles); wl_list_insert(&dwm.focus, &c->link.focus); wl_list_insert(&dwm.stack, &c->link.stack); wlr_xdg_surface_get_geometry(c->surf, &c->dim); c->dim.width += 2 * c->bw; c->dim.height += 2 * c->bw; applyrules(c); } static void unmap(struct wl_listener *ev, void *arg) { Monitor *m; Client *c; c = wl_container_of(ev, c, ev.unmap); m = c->m; setmonitor(c, nil, 0); wl_list_remove(&c->link.tiles); wl_list_remove(&c->link.stack); wl_list_remove(&c->link.focus); c->surf = nil; arrange(m); } static void delete(struct wl_listener *ev, void *arg) { Client *c; c = wl_container_of(ev, c, ev.free); free(c); }