aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/dwm/client.c
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-06-04 19:10:07 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-06-04 19:10:07 -0700
commit0a8f62d8c7116be9e344f351df679599908fb29c (patch)
treebcf7fcf995b4cb97cec0b947e2b299d6bcc8ae1d /sys/cmd/dwm/client.c
parentea50cbe1bf103372a3461c80cb172f4fb4167088 (diff)
refactored
Diffstat (limited to 'sys/cmd/dwm/client.c')
-rw-r--r--sys/cmd/dwm/client.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/sys/cmd/dwm/client.c b/sys/cmd/dwm/client.c
new file mode 100644
index 0000000..cc9730b
--- /dev/null
+++ b/sys/cmd/dwm/client.c
@@ -0,0 +1,254 @@
+#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 = "<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);
+}