summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonardo Hernández Hernández <leohdz172@protonmail.com>2022-04-08 21:12:32 -0500
committerLeonardo Hernández Hernández <leohdz172@protonmail.com>2022-04-08 21:12:32 -0500
commit29a2b647b27e5314fa1b9cb6158eb95cfb0bc405 (patch)
treec41b9bbe262c40b67cc4aab3afe0ab7f3b467097
parentdd0b8e4c371841761818b1182fcea1e8bd495676 (diff)
parentc00697e6438164e08baacc309b3dcdb727053aeb (diff)
Merge remote-tracking branch 'djpohly/main' into HEAD
-rw-r--r--Makefile12
-rw-r--r--README.md4
-rw-r--r--config.def.h13
-rw-r--r--dwl.c327
-rw-r--r--util.c35
-rw-r--r--util.h4
6 files changed, 230 insertions, 165 deletions
diff --git a/Makefile b/Makefile
index 536454f..48a0aa7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
include config.mk
-CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99
+CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 -pedantic
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
@@ -15,11 +15,11 @@ clean:
rm -f dwl *.o *-protocol.h *-protocol.c
install: dwl
- install -Dm755 dwl $(PREFIX)/bin/dwl
- install -Dm644 dwl.1 $(MANDIR)/man1/dwl.1
+ install -Dm755 dwl $(DESTDIR)$(PREFIX)/bin/dwl
+ install -Dm644 dwl.1 $(DESTDIR)$(MANDIR)/man1/dwl.1
uninstall:
- rm -f $(PREFIX)/bin/dwl $(MANDIR)/man1/dwl.1
+ rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1
.PHONY: all clean install uninstall
@@ -59,6 +59,6 @@ idle-protocol.o: idle-protocol.h
config.h: | config.def.h
cp config.def.h $@
-dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h
+dwl.o: config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h idle-protocol.h util.h
-dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o
+dwl: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o idle-protocol.o util.o
diff --git a/README.md b/README.md
index 13a0000..72488e3 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,10 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s
- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. Providing a built-in status bar is an exception to this goal, to avoid dependencies on font rendering and/or drawing libraries when an external bar could work well.
- Configurable multi-monitor layout support, including position and rotation
- Configurable HiDPI/multi-DPI support
+- Idle-inhibit protocol which lets applications such as mpv disable idle monitoring
- Provide information to external status bars via stdout/stdin
- Urgency hints via xdg-activate protocol
+- Support screen lockers via input-inhibitor protocol
- Various Wayland protocols
- XWayland support as provided by wlroots (can be enabled in `config.mk`)
- Zero flickering - Wayland users naturally expect that "every frame is perfect"
@@ -25,8 +27,6 @@ dwl is not meant to provide every feature under the sun. Instead, like dwm, it s
Features under consideration (possibly as patches) are:
- Protocols made trivial by wlroots
-- Implement the input-inhibitor protocol to support screen lockers (see https://github.com/djpohly/dwl/pull/132)
-- Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring (see https://github.com/djpohly/dwl/pull/133)
- Implement the text-input and input-method protocols to support IME once ibus implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and https://github.com/djpohly/dwl/pull/12)
Feature *non-goals* for the main codebase include:
diff --git a/config.def.h b/config.def.h
index 9bdf8b5..190b0da 100644
--- a/config.def.h
+++ b/config.def.h
@@ -13,8 +13,8 @@ static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */
/* examples:
{ "Gimp", NULL, 0, 1, -1 },
- { "firefox", NULL, 1 << 8, 0, -1 },
*/
+ { "firefox", NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
@@ -25,16 +25,14 @@ static const Layout layouts[] = {
{ "[M]", monocle },
};
-/* monitors
- * The order in which monitors are defined determines their position.
- * Non-configured monitors are always added to the left. */
+/* monitors */
static const MonitorRule monrules[] = {
- /* name mfact nmaster scale layout rotate/reflect x y */
+ /* name mfact nmaster scale layout rotate/reflect */
/* example of a HiDPI laptop monitor:
- { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 },
+ { "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL },
*/
/* defaults */
- { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, 0, 0 },
+ { NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL },
};
/* keyboard */
@@ -43,6 +41,7 @@ static const struct xkb_rule_names xkb_rules = {
/* example:
.options = "ctrl:nocaps",
*/
+ .options = "",
};
static const int repeat_rate = 25;
diff --git a/dwl.c b/dwl.c
index ae5ed93..dd62956 100644
--- a/dwl.c
+++ b/dwl.c
@@ -3,6 +3,7 @@
*/
#define _POSIX_C_SOURCE 200809L
#include <getopt.h>
+#include <libinput.h>
#include <linux/input-event-codes.h>
#include <signal.h>
#include <stdio.h>
@@ -10,9 +11,9 @@
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
-#include <libinput.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
+#include <wlr/backend/libinput.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
@@ -21,11 +22,12 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
-#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
+#include <wlr/types/wlr_idle_inhibit_v1.h>
+#include <wlr/types/wlr_input_device.h>
+#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_keyboard.h>
-#include <wlr/types/wlr_matrix.h>
+#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output_management_v1.h>
@@ -33,10 +35,10 @@
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_primary_selection_v1.h>
-#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_scene.h>
-#include <wlr/types/wlr_server_decoration.h>
+#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_seat.h>
+#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
@@ -45,7 +47,6 @@
#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
-#include <wlr/backend/libinput.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h>
#ifdef XWAYLAND
@@ -53,9 +54,9 @@
#include <wlr/xwayland.h>
#endif
+#include "util.h"
+
/* macros */
-#define BARF(fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0)
-#define EBARF(fmt, ...) BARF(fmt ": %s", ##__VA_ARGS__, strerror(errno))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
@@ -139,6 +140,7 @@ typedef struct {
typedef struct {
/* Must be first */
unsigned int type; /* LayerShell */
+ int mapped;
struct wlr_scene_node *scene;
struct wlr_scene_layer_surface_v1 *scene_layer;
struct wl_list link;
@@ -180,8 +182,6 @@ typedef struct {
float scale;
const Layout *lt;
enum wl_output_transform rr;
- int x;
- int y;
} MonitorRule;
typedef struct {
@@ -208,12 +208,14 @@ static void cleanupmon(struct wl_listener *listener, void *data);
static void closemon(Monitor *m);
static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
static void commitnotify(struct wl_listener *listener, void *data);
+static void createidleinhibitor(struct wl_listener *listener, void *data);
static void createkeyboard(struct wlr_keyboard *keyboard);
+static void createlayersurface(struct wl_listener *listener, void *data);
static void createmon(struct wl_listener *listener, void *data);
static void createnotify(struct wl_listener *listener, void *data);
-static void createlayersurface(struct wl_listener *listener, void *data);
static void createpointer(struct wlr_pointer *pointer);
static void cursorframe(struct wl_listener *listener, void *data);
+static void destroyidleinhibitor(struct wl_listener *listener, void *data);
static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static Monitor *dirtomon(enum wlr_direction dir);
@@ -221,8 +223,8 @@ static void dragicondestroy(struct wl_listener *listener, void *data);
static void focusclient(Client *c, int lift);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
-static void fullscreennotify(struct wl_listener *listener, void *data);
static Client *focustop(Monitor *m);
+static void fullscreennotify(struct wl_listener *listener, void *data);
static void incnmaster(const Arg *arg);
static void inputdevice(struct wl_listener *listener, void *data);
static int keybinding(uint32_t mods, xkb_keysym_t sym);
@@ -250,13 +252,13 @@ static void resize(Client *c, int x, int y, int w, int h, int interact);
static void run(char *startup_cmd);
static Client *selclient(void);
static void setcursor(struct wl_listener *listener, void *data);
-static void setpsel(struct wl_listener *listener, void *data);
-static void setsel(struct wl_listener *listener, void *data);
static void setfloating(Client *c, int floating);
static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setmon(Client *c, Monitor *m, unsigned int newtags);
+static void setpsel(struct wl_listener *listener, void *data);
+static void setsel(struct wl_listener *listener, void *data);
static void setup(void);
static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);
@@ -275,9 +277,9 @@ static void updatetitle(struct wl_listener *listener, void *data);
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,
Client **pc, LayerSurface **pl, double *nx, double *ny);
-static Monitor *xytomon(double x, double y);
static void zoom(const Arg *arg);
/* variables */
@@ -295,6 +297,8 @@ static struct wlr_xdg_activation_v1 *activation;
static struct wl_list clients; /* tiling order */
static struct wl_list fstack; /* focus order */
static struct wlr_idle *idle;
+static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr;
+static struct wlr_input_inhibit_manager *input_inhibit_mgr;
static struct wlr_layer_shell_v1 *layer_shell;
static struct wlr_output_manager_v1 *output_mgr;
static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
@@ -319,6 +323,8 @@ static struct wl_listener cursor_button = {.notify = buttonpress};
static struct wl_listener cursor_frame = {.notify = cursorframe};
static struct wl_listener cursor_motion = {.notify = motionrelative};
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
+static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor};
+static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor};
static struct wl_listener layout_change = {.notify = updatemons};
static struct wl_listener new_input = {.notify = inputdevice};
static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard};
@@ -620,9 +626,14 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
wlr_scene_node_reparent(layersurface->scene,
layers[wlr_layer_surface->current.layer]);
- if (!wlr_output)
+ if (!wlr_output || !(m = wlr_output->data))
return;
- m = wlr_output->data;
+
+ if (wlr_layer_surface->current.committed == 0
+ && layersurface->mapped == wlr_layer_surface->mapped)
+ return;
+
+ layersurface->mapped = wlr_layer_surface->mapped;
if (layers[wlr_layer_surface->current.layer] != layersurface->scene) {
wl_list_remove(&layersurface->link);
@@ -643,13 +654,20 @@ commitnotify(struct wl_listener *listener, void *data)
}
void
+createidleinhibitor(struct wl_listener *listener, void *data)
+{
+ struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
+ wl_signal_add(&idle_inhibitor->events.destroy, &idle_inhibitor_destroy);
+
+ wlr_idle_set_enabled(idle, seat, 0);
+}
+
+void
createkeyboard(struct wlr_keyboard *keyboard)
{
struct xkb_context *context;
struct xkb_keymap *keymap;
- Keyboard *kb = keyboard->data = calloc(1, sizeof(*kb));
- if (!kb)
- EBARF("createkeyboard: calloc");
+ Keyboard *kb = keyboard->data = ecalloc(1, sizeof(*kb));
kb->wlr_keyboard = keyboard;
/* Prepare an XKB keymap and assign it to the keyboard. */
@@ -674,15 +692,59 @@ createkeyboard(struct wlr_keyboard *keyboard)
}
void
+createlayersurface(struct wl_listener *listener, void *data)
+{
+ struct wlr_layer_surface_v1 *wlr_layer_surface = data;
+ LayerSurface *layersurface;
+ Monitor *m;
+ struct wlr_layer_surface_v1_state old_state;
+
+ if (!wlr_layer_surface->output) {
+ wlr_layer_surface->output = selmon->wlr_output;
+ }
+
+ layersurface = ecalloc(1, sizeof(LayerSurface));
+ layersurface->type = LayerShell;
+ LISTEN(&wlr_layer_surface->surface->events.commit,
+ &layersurface->surface_commit, commitlayersurfacenotify);
+ LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy,
+ destroylayersurfacenotify);
+ LISTEN(&wlr_layer_surface->events.map, &layersurface->map,
+ maplayersurfacenotify);
+ LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap,
+ unmaplayersurfacenotify);
+
+ layersurface->layer_surface = wlr_layer_surface;
+ wlr_layer_surface->data = layersurface;
+ m = wlr_layer_surface->output->data;
+
+ layersurface->scene_layer = wlr_scene_layer_surface_v1_create(
+ layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
+ layersurface->scene = wlr_layer_surface->surface->data =
+ layersurface->scene_layer->node;
+
+ layersurface->scene->data = layersurface;
+
+ wl_list_insert(&m->layers[wlr_layer_surface->pending.layer],
+ &layersurface->link);
+
+ /* Temporarily set the layer's current state to pending
+ * so that we can easily arrange it
+ */
+ old_state = wlr_layer_surface->current;
+ wlr_layer_surface->current = wlr_layer_surface->pending;
+ arrangelayers(m);
+ wlr_layer_surface->current = old_state;
+}
+
+void
createmon(struct wl_listener *listener, void *data)
{
/* This event is raised by the backend when a new output (aka a display or
* monitor) becomes available. */
struct wlr_output *wlr_output = data;
const MonitorRule *r;
- Monitor *m = wlr_output->data = calloc(1, sizeof(*m));
- if (!m)
- EBARF("createmon: calloc");
+ Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
m->wlr_output = wlr_output;
wlr_output_init_render(wlr_output, alloc, drw);
@@ -767,9 +829,7 @@ createnotify(struct wl_listener *listener, void *data)
return;
/* Allocate a Client for this surface */
- c = xdg_surface->data = calloc(1, sizeof(*c));
- if (!c)
- EBARF("createnotify: calloc");
+ c = xdg_surface->data = ecalloc(1, sizeof(*c));
c->surface.xdg = xdg_surface;
c->bw = borderpx;
@@ -784,53 +844,6 @@ createnotify(struct wl_listener *listener, void *data)
}
void
-createlayersurface(struct wl_listener *listener, void *data)
-{
- struct wlr_layer_surface_v1 *wlr_layer_surface = data;
- LayerSurface *layersurface;
- Monitor *m;
- struct wlr_layer_surface_v1_state old_state;
-
- if (!wlr_layer_surface->output) {
- wlr_layer_surface->output = selmon->wlr_output;
- }
-
- layersurface = calloc(1, sizeof(LayerSurface));
- if (!layersurface)
- EBARF("layersurface: calloc");
- layersurface->type = LayerShell;
- LISTEN(&wlr_layer_surface->surface->events.commit,
- &layersurface->surface_commit, commitlayersurfacenotify);
- LISTEN(&wlr_layer_surface->events.destroy, &layersurface->destroy,
- destroylayersurfacenotify);
- LISTEN(&wlr_layer_surface->events.map, &layersurface->map,
- maplayersurfacenotify);
- LISTEN(&wlr_layer_surface->events.unmap, &layersurface->unmap,
- unmaplayersurfacenotify);
-
- layersurface->layer_surface = wlr_layer_surface;
- wlr_layer_surface->data = layersurface;
- m = wlr_layer_surface->output->data;
-
- layersurface->scene_layer = wlr_scene_layer_surface_v1_create(
- layers[wlr_layer_surface->pending.layer], wlr_layer_surface);
- layersurface->scene = wlr_layer_surface->surface->data =
- layersurface->scene_layer->node;
- layersurface->scene->data = layersurface;
-
- wl_list_insert(&m->layers[wlr_layer_surface->pending.layer],
- &layersurface->link);
-
- /* Temporarily set the layer's current state to pending
- * so that we can easily arrange it
- */
- old_state = wlr_layer_surface->current;
- wlr_layer_surface->current = wlr_layer_surface->pending;
- arrangelayers(m);
- wlr_layer_surface->current = old_state;
-}
-
-void
createpointer(struct wlr_pointer *pointer)
{
if (wlr_input_device_is_libinput(&pointer->base)) {
@@ -863,6 +876,14 @@ cursorframe(struct wl_listener *listener, void *data)
}
void
+destroyidleinhibitor(struct wl_listener *listener, void *data)
+{
+ /* I've been testing and at this point the inhibitor has not yet been
+ * removed from the list, checking if it has at least one item. */
+ wlr_idle_set_enabled(idle, seat, wl_list_length(&idle_inhibit_mgr->inhibitors) <= 1);
+}
+
+void
destroylayersurfacenotify(struct wl_listener *listener, void *data)
{
LayerSurface *layersurface = wl_container_of(listener, layersurface, destroy);
@@ -903,57 +924,6 @@ destroynotify(struct wl_listener *listener, void *data)
free(c);
}
-void
-dragicondestroy(struct wl_listener *listener, void *data)
-{
- struct wlr_drag_icon *icon = data;
- wlr_scene_node_destroy(icon->data);
- // Focus enter isn't sent during drag, so refocus the focused node.
- focusclient(selclient(), 1);
- motionnotify(0);
-}
-
-void
-togglefullscreen(const Arg *arg)
-{
- Client *sel = selclient();
- if (sel)
- setfullscreen(sel, !sel->isfullscreen);
-}
-
-void
-setfullscreen(Client *c, int fullscreen)
-{
- c->isfullscreen = fullscreen;
- c->bw = fullscreen ? 0 : borderpx;
- client_set_fullscreen(c, fullscreen);
-
- if (fullscreen) {
- c->prev = c->geom;
- resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0);
- } else {
- /* restore previous size instead of arrange for floating windows since
- * client positions are set by the user and cannot be recalculated */
- resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0);
- }
- arrange(c->mon);
- printstatus();
-}
-
-void
-fullscreennotify(struct wl_listener *listener, void *data)
-{
- Client *c = wl_container_of(listener, c, fullscreen);
- int fullscreen = client_wants_fullscreen(c);
-
- if (!c->mon) {
- /* if the client is not mapped yet, let mapnotify() call setfullscreen() */
- c->isfullscreen = fullscreen;
- return;
- }
- setfullscreen(c, fullscreen);
-}
-
Monitor *
dirtomon(enum wlr_direction dir)
{
@@ -969,6 +939,16 @@ dirtomon(enum wlr_direction dir)
}
void
+dragicondestroy(struct wl_listener *listener, void *data)
+{
+ struct wlr_drag_icon *icon = data;
+ wlr_scene_node_destroy(icon->data);
+ // Focus enter isn't sent during drag, so refocus the focused node.
+ focusclient(selclient(), 1);
+ motionnotify(0);
+}
+
+void
focusclient(Client *c, int lift)
{
struct wlr_surface *old = seat->keyboard_state.focused_surface;
@@ -1021,6 +1001,7 @@ focusclient(Client *c, int lift)
}
printstatus();
+ wlr_idle_set_enabled(idle, seat, wl_list_empty(&idle_inhibit_mgr->inhibitors));
if (!c) {
/* With no client, all we have left is to clear focus */
@@ -1083,6 +1064,20 @@ focustop(Monitor *m)
}
void
+fullscreennotify(struct wl_listener *listener, void *data)
+{
+ Client *c = wl_container_of(listener, c, fullscreen);
+ int fullscreen = client_wants_fullscreen(c);
+
+ if (!c->mon) {
+ /* if the client is not mapped yet, let mapnotify() call setfullscreen() */
+ c->isfullscreen = fullscreen;
+ return;
+ }
+ setfullscreen(c, fullscreen);
+}
+
+void
incnmaster(const Arg *arg)
{
selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
@@ -1159,8 +1154,10 @@ keypress(struct wl_listener *listener, void *data)
wlr_idle_notify_activity(idle, seat);
- /* On _press_, attempt to process a compositor keybinding. */
- if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
+ /* On _press_ if there is no active screen locker,
+ * attempt to process a compositor keybinding. */
+ if (!input_inhibit_mgr->active_inhibitor
+ && event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
for (i = 0; i < nsyms; i++)
handled = keybinding(mods, syms[i]) || handled;
@@ -1591,22 +1588,22 @@ run(char *startup_cmd)
/* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(dpy);
if (!socket)
- BARF("startup: display_add_socket_auto");
+ die("startup: display_add_socket_auto");
setenv("WAYLAND_DISPLAY", socket, 1);
/* Now that the socket exists, run the startup command */
if (startup_cmd) {
int piperw[2];
- pipe(piperw);
- startup_pid = fork();
- if (startup_pid < 0)
- EBARF("startup: fork");
+ if (pipe(piperw) < 0)
+ die("startup: pipe:");
+ if ((startup_pid = fork()) < 0)
+ die("startup: fork:");
if (startup_pid == 0) {
dup2(piperw[0], STDIN_FILENO);
close(piperw[0]);
close(piperw[1]);
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
- EBARF("startup: execl");
+ die("startup: execl:");
}
dup2(piperw[1], STDOUT_FILENO);
close(piperw[1]);
@@ -1619,7 +1616,7 @@ run(char *startup_cmd)
/* Start the backend. This will enumerate outputs and inputs, become the DRM
* master, etc */
if (!wlr_backend_start(backend))
- BARF("startup: backend_start");
+ die("startup: backend_start");
/* Now that outputs are initialized, choose initial selmon based on
* cursor position, and set default cursor image */
@@ -1682,6 +1679,25 @@ setfloating(Client *c, int floating)
}
void
+setfullscreen(Client *c, int fullscreen)
+{
+ c->isfullscreen = fullscreen;
+ c->bw = fullscreen ? 0 : borderpx;
+ client_set_fullscreen(c, fullscreen);
+
+ if (fullscreen) {
+ c->prev = c->geom;
+ resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0);
+ } else {
+ /* restore previous size instead of arrange for floating windows since
+ * client positions are set by the user and cannot be recalculated */
+ resize(c, c->prev.x, c->prev.y, c->prev.width, c->prev.height, 0);
+ }
+ arrange(c->mon);
+ printstatus();
+}
+
+void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
@@ -1779,7 +1795,7 @@ setup(void)
* if the backend does not support hardware cursors (some older GPUs
* don't). */
if (!(backend = wlr_backend_autocreate(dpy)))
- BARF("couldn't create backend");
+ die("couldn't create backend");
/* Initialize the scene graph used to lay out windows */
scene = wlr_scene_create();
@@ -1793,12 +1809,12 @@ setup(void)
/* Create a renderer with the default implementation */
if (!(drw = wlr_renderer_autocreate(backend)))
- BARF("couldn't create renderer");
+ die("couldn't create renderer");
wlr_renderer_init_wl_display(drw, dpy);
/* Create a default allocator */
if (!(alloc = wlr_allocator_autocreate(backend, drw)))
- BARF("couldn't create allocator");
+ die("couldn't create allocator");
/* This creates some hands-off wlroots interfaces. The compositor is
* necessary for clients to allocate surfaces and the data device manager
@@ -1842,12 +1858,17 @@ setup(void)
idle = wlr_idle_create(dpy);
+ idle_inhibit_mgr = wlr_idle_inhibit_v1_create(dpy);
+ wl_signal_add(&idle_inhibit_mgr->events.new_inhibitor, &idle_inhibitor_create);
+
layer_shell = wlr_layer_shell_v1_create(dpy);
wl_signal_add(&layer_shell->events.new_surface, &new_layer_shell_surface);
xdg_shell = wlr_xdg_shell_create(dpy);
wl_signal_add(&xdg_shell->events.new_surface, &new_xdg_surface);
+ input_inhibit_mgr = wlr_input_inhibit_manager_create(dpy);
+
/* Use decoration protocols to negotiate server-side decorations */
wlr_server_decoration_manager_set_default_mode(
wlr_server_decoration_manager_create(dpy),
@@ -1933,7 +1954,7 @@ spawn(const Arg *arg)
dup2(STDERR_FILENO, STDOUT_FILENO);
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
- EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]);
+ die("dwl: execvp %s failed:", ((char **)arg->v)[0]);
}
}
@@ -2014,6 +2035,14 @@ togglefloating(const Arg *arg)
}
void
+togglefullscreen(const Arg *arg)
+{
+ Client *sel = selclient();
+ if (sel)
+ setfullscreen(sel, !sel->isfullscreen);
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;
@@ -2167,6 +2196,13 @@ virtualkeyboard(struct wl_listener *listener, void *data)
createkeyboard(device->keyboard);
}
+Monitor *
+xytomon(double x, double y)
+{
+ struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
+ return o ? o->data : NULL;
+}
+
struct wlr_scene_node *
xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny)
@@ -2200,13 +2236,6 @@ xytonode(double x, double y, struct wlr_surface **psurface,
return node;
}
-Monitor *
-xytomon(double x, double y)
-{
- struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
- return o ? o->data : NULL;
-}
-
void
zoom(const Arg *arg)
{
@@ -2269,9 +2298,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
setfullscreen(c, 0);
/* Allocate a Client for this surface */
- c = xwayland_surface->data = calloc(1, sizeof(*c));
- if (!c)
- EBARF("createnotifyx11: calloc");
+ c = xwayland_surface->data = ecalloc(1, sizeof(*c));
c->surface.xwayland = xwayland_surface;
c->type = xwayland_surface->override_redirect ? X11Unmanaged : X11Managed;
c->bw = borderpx;
@@ -2370,12 +2397,12 @@ main(int argc, char *argv[])
/* Wayland requires XDG_RUNTIME_DIR for creating its communications socket */
if (!getenv("XDG_RUNTIME_DIR"))
- BARF("XDG_RUNTIME_DIR must be set");
+ die("XDG_RUNTIME_DIR must be set");
setup();
run(startup_cmd);
cleanup();
return EXIT_SUCCESS;
usage:
- BARF("Usage: %s [-s startup command]", argv[0]);
+ die("Usage: %s [-s startup command]", argv[0]);
}
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..932f89b
--- /dev/null
+++ b/util.c
@@ -0,0 +1,35 @@
+/* See LICENSE.dwm file for copyright and license details. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void *
+ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ if (!(p = calloc(nmemb, size)))
+ die("calloc:");
+ return p;
+}
+
+void
+die(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ } else {
+ fputc('\n', stderr);
+ }
+
+ exit(1);
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..4c94117
--- /dev/null
+++ b/util.h
@@ -0,0 +1,4 @@
+/* See LICENSE.dwm file for copyright and license details. */
+
+void die(const char *fmt, ...);
+void *ecalloc(size_t nmemb, size_t size);