6XZIQSMIVP2GZ5S3UCKEVNDSLTHSQEVSXLV4UIFF3G3SRCGJPXYAC
ZOOCZQBGZ4PCOU54EPPUPWNOIFWCM5RMZ4EFL2WFR7LFJTAMHZGAC
S7RXJJZG4IEIVLPHEWFT5M2T3SRRO5US5SYBPXSYSWJJLXAKNNPAC
D425ND7AT3F7QJ3CCSESMVDOC3J5C5P32M5SJDBHECZJXLHNQ2FAC
7B74AT3BXYB7PVW4F6SGQNPMHOU5TEV5TZ54CG6VSQI46XSEKWXQC
J6OSBEBQXZR5JZ5TOCCUPELBPUVEQULGCXURXLPY7WFYTDEQOU2AC
7XCGFU3GX4TQXZBOU7GFAQ62EEOTVRNWFYQGI3XULFPSUKDZ2EYAC
O5JVMDEEKP334BAYMJ6HHXROW4X4WC24JHCYZTKJRQE5UGYXV7YQC
Z53RRSEGCT3PGEZNNSAREB3WVYOHCTDXXPNAKOWWGCEYW4G2QC4QC
E7UO6NRGXFDMBU3BSJYRDNOA3Y7VHD7NWPHI5PHCPHQF6ZNOPZLQC
}
void
run(char *startup_cmd)
{
pid_t startup_pid = -1;
/* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(wl_display);
if (!socket) {
wlr_backend_destroy(backend);
exit(1);
}
/* Start the backend. This will enumerate outputs and inputs, become the DRM
* master, etc */
if (!wlr_backend_start(backend)) {
wlr_backend_destroy(backend);
wl_display_destroy(wl_display);
exit(1);
}
/* Set the WAYLAND_DISPLAY environment variable to our socket and run the
* startup command if requested. */
setenv("WAYLAND_DISPLAY", socket, true);
if (startup_cmd) {
startup_pid = fork();
if (startup_pid < 0) {
perror("startup: fork");
wl_display_destroy(wl_display);
exit(1);
}
if (startup_pid == 0) {
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL);
perror("startup: execl");
wl_display_destroy(wl_display);
exit(1);
}
}
/* Run the Wayland event loop. This does not return until you exit the
* compositor. Starting the backend rigged up all of the necessary event
* loop configuration to listen to libinput events, DRM events, generate
* frame events at the refresh rate, and so on. */
wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s",
socket);
wl_display_run(wl_display);
if (startup_cmd) {
kill(startup_pid, SIGTERM);
waitpid(startup_pid, NULL, 0);
}
if (fork() == 0) {
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwl: execvp %s", ((char **)arg->v)[0]);
perror(" failed");
exit(EXIT_FAILURE);
}
}
void
unmapnotify(struct wl_listener *listener, void *data)
{
/* Called when the surface is unmapped, and should no longer be shown. */
Client *c = wl_container_of(listener, c, unmap);
c->mapped = false;
}
Client *
xytoclient(double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy)
{
/* This iterates over all of our surfaces and attempts to find one under the
* cursor. This relies on clients being ordered from top-to-bottom. */
Client *c;
wl_list_for_each(c, &clients, link) {
if (xytosurface(c, lx, ly, surface, sx, sy)) {
return c;
}
}
return NULL;
}
bool
xytosurface(Client *c, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy)
{
/*
* XDG toplevels may have nested surfaces, such as popup windows for context
* menus or tooltips. This function tests if any of those are underneath the
* coordinates lx and ly (in output Layout Coordinates). If so, it sets the
* surface pointer to that wlr_surface and the sx and sy coordinates to the
* coordinates relative to that surface's top-left corner.
*/
double client_sx = lx - c->x;
double client_sy = ly - c->y;
struct wlr_surface_state *state = &c->xdg_surface->surface->current;
double _sx, _sy;
struct wlr_surface *_surface = NULL;
_surface = wlr_xdg_surface_surface_at(
c->xdg_surface, client_sx, client_sy, &_sx, &_sy);
if (_surface != NULL) {
*sx = _sx;
*sy = _sy;
*surface = _surface;
return true;
}
return false;
}
int
main(int argc, char *argv[])
{
wlr_log_init(WLR_DEBUG, NULL);
char *startup_cmd = NULL;
pid_t startup_pid = -1;
int c;
while ((c = getopt(argc, argv, "s:h")) != -1) {
switch (c) {
case 's':
startup_cmd = optarg;
break;
default:
printf("Usage: %s [-s startup command]\n", argv[0]);
return 0;
}
}
if (optind < argc) {
printf("Usage: %s [-s startup command]\n", argv[0]);
return 0;
}
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
wl_display = wl_display_create();
/* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(wl_display);
if (!socket) {
wlr_backend_destroy(backend);
return 1;
void
spawn(const Arg *arg)
{
if (fork() == 0) {
setsid();
execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwl: execvp %s", ((char **)arg->v)[0]);
perror(" failed");
exit(EXIT_FAILURE);
/* Start the backend. This will enumerate outputs and inputs, become the DRM
* master, etc */
if (!wlr_backend_start(backend)) {
wlr_backend_destroy(backend);
wl_display_destroy(wl_display);
return 1;
}
void
unmapnotify(struct wl_listener *listener, void *data)
{
/* Called when the surface is unmapped, and should no longer be shown. */
Client *c = wl_container_of(listener, c, unmap);
c->mapped = false;
}
/* Set the WAYLAND_DISPLAY environment variable to our socket and run the
* startup command if requested. */
setenv("WAYLAND_DISPLAY", socket, true);
if (startup_cmd) {
startup_pid = fork();
if (startup_pid < 0) {
perror("startup: fork");
wl_display_destroy(wl_display);
return 1;
}
if (startup_pid == 0) {
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL);
perror("startup: execl");
wl_display_destroy(wl_display);
return 1;
Client *
xytoclient(double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy)
{
/* This iterates over all of our surfaces and attempts to find one under the
* cursor. This relies on clients being ordered from top-to-bottom. */
Client *c;
wl_list_for_each(c, &clients, link) {
if (xytosurface(c, lx, ly, surface, sx, sy)) {
return c;
/* Run the Wayland event loop. This does not return until you exit the
* compositor. Starting the backend rigged up all of the necessary event
* loop configuration to listen to libinput events, DRM events, generate
* frame events at the refresh rate, and so on. */
wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s",
socket);
wl_display_run(wl_display);
return NULL;
}
bool
xytosurface(Client *c, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy)
{
/*
* XDG toplevels may have nested surfaces, such as popup windows for context
* menus or tooltips. This function tests if any of those are underneath the
* coordinates lx and ly (in output Layout Coordinates). If so, it sets the
* surface pointer to that wlr_surface and the sx and sy coordinates to the
* coordinates relative to that surface's top-left corner.
*/
double client_sx = lx - c->x;
double client_sy = ly - c->y;
struct wlr_surface_state *state = &c->xdg_surface->surface->current;
double _sx, _sy;
struct wlr_surface *_surface = NULL;
_surface = wlr_xdg_surface_surface_at(
c->xdg_surface, client_sx, client_sy, &_sx, &_sy);
if (_surface != NULL) {
*sx = _sx;
*sy = _sy;
*surface = _surface;
return true;
}
return false;
}
int
main(int argc, char *argv[])
{
wlr_log_init(WLR_DEBUG, NULL);
char *startup_cmd = NULL;
if (startup_cmd) {
kill(startup_pid, SIGTERM);
waitpid(startup_pid, NULL, 0);
int c;
while ((c = getopt(argc, argv, "s:h")) != -1) {
switch (c) {
case 's':
startup_cmd = optarg;
break;
default:
printf("Usage: %s [-s startup command]\n", argv[0]);
return 0;
}
}
if (optind < argc) {
printf("Usage: %s [-s startup command]\n", argv[0]);
return 0;