diff --git a/Makefile b/Makefile index 63b52f0..85be3d8 100644 --- a/Makefile +++ b/Makefile @@ -55,8 +55,11 @@ install: dwl mkdir -p $(DESTDIR)$(MANDIR)/man1 cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 + mkdir -p $(DESTDIR)$(DATADIR)/wayland-sessions + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 + rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop .SUFFIXES: .c .o .c.o: diff --git a/README.md b/README.md index 05f149c..1ac5b4b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # dwl - dwm for Wayland -Join us on our [Discord server] or at [#dwl] on irc.libera.chat. +Join us on our IRC channel: [#dwl on Libera Chat] +Or on our [Discord server]. dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is intended to fill the same space in the Wayland world that dwm does in X11, @@ -143,7 +144,7 @@ inspiration, and to the various contributors to the project, including: [Discord server]: https://discord.gg/jJxZnrGPWN -[#dwl]: https://web.libera.chat/?channels=#dwl +[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl [Wayland]: https://wayland.freedesktop.org/ [wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/ [wlroots-next branch]: https://github.com/djpohly/dwl/tree/wlroots-next diff --git a/config.def.h b/config.def.h index 447ba00..1677f6f 100644 --- a/config.def.h +++ b/config.def.h @@ -8,7 +8,8 @@ static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0}; static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* tagging - tagcount must be no greater than 31 */ -static const int tagcount = 9; +#define TAGCOUNT (9) +static const int tagcount = TAGCOUNT; static const Rule rules[] = { /* app_id title tags mask isfloating monitor */ diff --git a/config.mk b/config.mk index f50156f..4bc9b9d 100644 --- a/config.mk +++ b/config.mk @@ -6,6 +6,7 @@ PKG_CONFIG = pkg-config # paths PREFIX = /usr/local MANDIR = $(PREFIX)/share/man +DATADIR = $(PREFIX)/share XWAYLAND = XLIBS = diff --git a/dwl.1 b/dwl.1 index cae1036..6f164e6 100644 --- a/dwl.1 +++ b/dwl.1 @@ -101,7 +101,7 @@ These environment variables are used by A directory where temporary user files, such as the Wayland socket, are stored. .It Ev XDG_CONFIG_DIR -A directory containung configuration of various programs and +A directory containing configuration of various programs and libraries, including libxkbcommon. .It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET Tell how to connect to an underlying X11 or Wayland server. diff --git a/dwl.c b/dwl.c index 91abe11..120ac1c 100644 --- a/dwl.c +++ b/dwl.c @@ -323,7 +323,7 @@ static void urgent(struct wl_listener *listener, void *data); static void view(const Arg *arg); static void virtualkeyboard(struct wl_listener *listener, void *data); static Monitor *xytomon(double x, double y); -static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface, +static void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny); static void zoom(const Arg *arg); @@ -750,12 +750,6 @@ void commitnotify(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, commit); - struct wlr_box box = {0}; - client_get_geometry(c, &box); - - if (c->mon && !wlr_box_empty(&box) && (box.width != c->geom.width - 2 * c->bw - || box.height != c->geom.height - 2 * c->bw)) - c->isfloating ? resize(c, c->geom, 1) : arrange(c->mon); /* mark a pending resize as completed */ if (c->resize && c->resize <= c->surface.xdg->current.configure_serial) @@ -1120,15 +1114,16 @@ destroylocksurface(struct wl_listener *listener, void *data) m->lock_surface = NULL; wl_list_remove(&m->destroy_lock_surface.link); - if (lock_surface->surface == seat->keyboard_state.focused_surface) { - if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { - surface = wl_container_of(cur_lock->surfaces.next, surface, link); - client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); - } else if (!locked) { - focusclient(focustop(selmon), 1); - } else { - wlr_seat_keyboard_clear_focus(seat); - } + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; + + if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { + surface = wl_container_of(cur_lock->surfaces.next, surface, link); + client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); + } else if (!locked) { + focusclient(focustop(selmon), 1); + } else { + wlr_seat_keyboard_clear_focus(seat); } } @@ -1438,12 +1433,13 @@ keypress(struct wl_listener *listener, void *data) wl_event_source_timer_update(kb->key_repeat_source, 0); } - if (!handled) { - /* Pass unhandled keycodes along to the client. */ - wlr_seat_set_keyboard(seat, kb->wlr_keyboard); - wlr_seat_keyboard_notify_key(seat, event->time_msec, - event->keycode, event->state); - } + if (handled) + return; + + /* Pass unhandled keycodes along to the client. */ + wlr_seat_set_keyboard(seat, kb->wlr_keyboard); + wlr_seat_keyboard_notify_key(seat, event->time_msec, + event->keycode, event->state); } void @@ -1469,13 +1465,14 @@ keyrepeat(void *data) { Keyboard *kb = data; int i; - if (kb->nsyms && kb->wlr_keyboard->repeat_info.rate > 0) { - wl_event_source_timer_update(kb->key_repeat_source, - 1000 / kb->wlr_keyboard->repeat_info.rate); + if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0) + return 0; - for (i = 0; i < kb->nsyms; i++) - keybinding(kb->mods, kb->keysyms[i]); - } + wl_event_source_timer_update(kb->key_repeat_source, + 1000 / kb->wlr_keyboard->repeat_info.rate); + + for (i = 0; i < kb->nsyms; i++) + keybinding(kb->mods, kb->keysyms[i]); return 0; } @@ -1516,7 +1513,6 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, map); - wlr_surface_send_enter(l->layer_surface->surface, l->mon->wlr_output); motionnotify(0); } @@ -2030,6 +2026,8 @@ void setfloating(Client *c, int floating) { c->isfloating = floating; + if (!c->mon) + return; wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]); arrange(c->mon); printstatus(); @@ -2118,17 +2116,15 @@ setmon(Client *c, Monitor *m, uint32_t newtags) c->mon = m; c->prev = c->geom; - /* TODO leave/enter is not optimal but works */ - if (oldmon) { - wlr_surface_send_leave(client_surface(c), oldmon->wlr_output); + /* Scene graph sends surface leave/enter events on move and resize */ + if (oldmon) arrange(oldmon); - } if (m) { /* Make sure window actually overlaps with the monitor */ resize(c, c->geom, 0); - wlr_surface_send_enter(client_surface(c), m->wlr_output); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfloating(c, c->isfloating); } focusclient(focustop(selmon), 1); } @@ -2378,11 +2374,12 @@ void tag(const Arg *arg) { Client *sel = focustop(selmon); - if (sel && arg->ui & TAGMASK) { - sel->tags = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!sel || (arg->ui & TAGMASK) == 0) + return; + + sel->tags = arg->ui & TAGMASK; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2452,11 +2449,12 @@ toggletag(const Arg *arg) if (!sel) return; newtags = sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - sel->tags = newtags; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!newtags) + return; + + sel->tags = newtags; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2465,11 +2463,12 @@ toggleview(const Arg *arg) { uint32_t newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0; - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focusclient(focustop(selmon), 1); - arrange(selmon); - } + if (!newtagset) + return; + + selmon->tagset[selmon->seltags] = newtagset; + focusclient(focustop(selmon), 1); + arrange(selmon); printstatus(); } @@ -2625,10 +2624,11 @@ urgent(struct wl_listener *listener, void *data) struct wlr_xdg_activation_v1_request_activate_event *event = data; Client *c = NULL; toplevel_from_wlr_surface(event->surface, &c, NULL); - if (c && c != focustop(selmon)) { - c->isurgent = 1; - printstatus(); - } + if (!c || c == focustop(selmon)) + return; + + c->isurgent = 1; + printstatus(); } void @@ -2658,7 +2658,7 @@ xytomon(double x, double y) return o ? o->data : NULL; } -struct wlr_scene_node * +void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, LayerSurface **pl, double *nx, double *ny) { @@ -2687,7 +2687,6 @@ xytonode(double x, double y, struct wlr_surface **psurface, if (psurface) *psurface = surface; if (pc) *pc = c; if (pl) *pl = l; - return node; } void @@ -2806,10 +2805,11 @@ void sethints(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, set_hints); - if (c != focustop(selmon)) { - c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); - printstatus(); - } + if (c == focustop(selmon)) + return; + + c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); + printstatus(); } void diff --git a/dwl.desktop b/dwl.desktop new file mode 100644 index 0000000..e1380f7 --- /dev/null +++ b/dwl.desktop @@ -0,0 +1,5 @@ +[Desktop Entry] +Name=dwl +Comment=dwm for Wayland +Exec=dwl +Type=Application