Merge remote-tracking branch 'djpohly/main' into HEAD

This commit is contained in:
Leonardo Hernández Hernández 2022-04-08 21:12:32 -05:00
commit 29a2b647b2
No known key found for this signature in database
GPG key ID: E538897EE11B9624
6 changed files with 230 additions and 165 deletions

View file

@ -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

View file

@ -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:

View file

@ -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;

327
dwl.c
View file

@ -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);
@ -642,14 +653,21 @@ commitnotify(struct wl_listener *listener, void *data)
c->resize = 0;
}
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. */
@ -673,6 +691,52 @@ createkeyboard(struct wlr_keyboard *keyboard)
wl_list_insert(&keyboards, &kb->link);
}
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)
{
@ -680,9 +744,7 @@ createmon(struct wl_listener *listener, void *data)
* 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;
@ -783,53 +843,6 @@ createnotify(struct wl_listener *listener, void *data)
c->isfullscreen = 0;
}
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)
{
@ -862,6 +875,14 @@ cursorframe(struct wl_listener *listener, void *data)
wlr_seat_pointer_notify_frame(seat);
}
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)
{
@ -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)
{
@ -968,6 +938,16 @@ dirtomon(enum wlr_direction dir)
return selmon;
}
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)
{
@ -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 */
@ -1082,6 +1063,20 @@ focustop(Monitor *m)
return NULL;
}
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)
{
@ -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 */
@ -1681,6 +1678,25 @@ setfloating(Client *c, int floating)
printstatus();
}
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)
{
@ -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]);
}
}
@ -2013,6 +2034,14 @@ togglefloating(const Arg *arg)
setfloating(sel, !sel->isfloating);
}
void
togglefullscreen(const Arg *arg)
{
Client *sel = selclient();
if (sel)
setfullscreen(sel, !sel->isfullscreen);
}
void
toggletag(const Arg *arg)
{
@ -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]);
}

35
util.c Normal file
View file

@ -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);
}

4
util.h Normal file
View file

@ -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);