Merge pull request #2 from djpohly/master

Merge
This commit is contained in:
Bonicgamer 2020-08-26 14:24:21 -04:00 committed by GitHub
commit 45a2e25d6d
Failed to generate hash of commit
2 changed files with 103 additions and 80 deletions

View file

@ -51,6 +51,9 @@ static const int repeat_delay = 600;
{ MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */ /* commands */
static const char *termcmd[] = { "alacritty", NULL }; static const char *termcmd[] = { "alacritty", NULL };

180
dwl.c
View file

@ -17,6 +17,7 @@
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h> #include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.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_input_device.h>
#include <wlr/types/wlr_keyboard.h> #include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_matrix.h>
@ -40,6 +41,8 @@
#endif #endif
/* macros */ /* 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 MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B))
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
@ -55,9 +58,9 @@
/* enums */ /* enums */
enum { CurNormal, CurMove, CurResize }; /* cursor */ enum { CurNormal, CurMove, CurResize }; /* cursor */
#ifdef XWAYLAND
enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
#ifdef XWAYLAND
enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */ enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */
#endif #endif
@ -177,6 +180,7 @@ static void arrange(Monitor *m);
static void axisnotify(struct wl_listener *listener, void *data); static void axisnotify(struct wl_listener *listener, void *data);
static void buttonpress(struct wl_listener *listener, void *data); static void buttonpress(struct wl_listener *listener, void *data);
static void chvt(const Arg *arg); static void chvt(const Arg *arg);
static void cleanup(void);
static void cleanupkeyboard(struct wl_listener *listener, void *data); static void cleanupkeyboard(struct wl_listener *listener, void *data);
static void cleanupmon(struct wl_listener *listener, void *data); static void cleanupmon(struct wl_listener *listener, void *data);
static void commitnotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data);
@ -224,6 +228,7 @@ static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg); static void setmfact(const Arg *arg);
static void setmon(Client *c, Monitor *m, unsigned int newtags); static void setmon(Client *c, Monitor *m, unsigned int newtags);
static void setup(void); static void setup(void);
static void sigchld(int unused);
static void spawn(const Arg *arg); static void spawn(const Arg *arg);
static void tag(const Arg *arg); static void tag(const Arg *arg);
static void tagmon(const Arg *arg); static void tagmon(const Arg *arg);
@ -286,6 +291,7 @@ static Atom getatom(xcb_connection_t *xc, const char *name);
static void renderindependents(struct wlr_output *output, struct timespec *now); static void renderindependents(struct wlr_output *output, struct timespec *now);
static void updatewindowtype(Client *c); static void updatewindowtype(Client *c);
static void xwaylandready(struct wl_listener *listener, void *data); static void xwaylandready(struct wl_listener *listener, void *data);
static Client *xytoindependent(double x, double y);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready}; static struct wl_listener xwayland_ready = {.notify = xwaylandready};
static struct wlr_xwayland *xwayland; static struct wlr_xwayland *xwayland;
@ -327,8 +333,8 @@ applyrules(Client *c)
/* rule matching */ /* rule matching */
c->isfloating = 0; c->isfloating = 0;
#ifdef XWAYLAND #ifdef XWAYLAND
updatewindowtype(c);
if (c->type != XDGShell) { if (c->type != XDGShell) {
updatewindowtype(c);
appid = c->surface.xwayland->class; appid = c->surface.xwayland->class;
title = c->surface.xwayland->title; title = c->surface.xwayland->title;
} else } else
@ -427,10 +433,21 @@ buttonpress(struct wl_listener *listener, void *data)
void void
chvt(const Arg *arg) chvt(const Arg *arg)
{ {
struct wlr_session *s = wlr_backend_get_session(backend); wlr_session_change_vt(wlr_backend_get_session(backend), arg->ui);
if (!s) }
return;
wlr_session_change_vt(s, arg->ui); void
cleanup(void)
{
#ifdef XWAYLAND
wlr_xwayland_destroy(xwayland);
#endif
wl_display_destroy_clients(dpy);
wl_display_destroy(dpy);
wlr_xcursor_manager_destroy(cursor_mgr);
wlr_cursor_destroy(cursor);
wlr_output_layout_destroy(output_layout);
} }
void void
@ -971,7 +988,16 @@ motionnotify(uint32_t time)
return; return;
} }
#ifdef XWAYLAND
/* Find an independent under the pointer and send the event along. */
if ((c = xytoindependent(cursor->x, cursor->y))) {
surface = wlr_surface_surface_at(c->surface.xwayland->surface,
cursor->x - c->surface.xwayland->x - c->bw,
cursor->y - c->surface.xwayland->y - c->bw, &sx, &sy);
/* Otherwise, find the client under the pointer and send the event along. */ /* Otherwise, find the client under the pointer and send the event along. */
} else
#endif
if ((c = xytoclient(cursor->x, cursor->y))) { if ((c = xytoclient(cursor->x, cursor->y))) {
#ifdef XWAYLAND #ifdef XWAYLAND
if (c->type != XDGShell) if (c->type != XDGShell)
@ -1060,6 +1086,12 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
/* Otherwise, let the client know that the mouse cursor has entered one /* Otherwise, let the client know that the mouse cursor has entered one
* of its surfaces, and make keyboard focus follow if desired. */ * of its surfaces, and make keyboard focus follow if desired. */
wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
#if XWAYLAND
if (c->type == X11Unmanaged)
return;
#endif
if (sloppyfocus) if (sloppyfocus)
focusclient(selclient(), c, 0); focusclient(selclient(), c, 0);
} }
@ -1266,20 +1298,13 @@ run(char *startup_cmd)
/* Add a Unix socket to the Wayland display. */ /* Add a Unix socket to the Wayland display. */
const char *socket = wl_display_add_socket_auto(dpy); const char *socket = wl_display_add_socket_auto(dpy);
if (!socket) { if (!socket)
perror("startup: display_add_socket_auto"); BARF("startup: display_add_socket_auto");
wlr_backend_destroy(backend);
exit(EXIT_FAILURE);
}
/* Start the backend. This will enumerate outputs and inputs, become the DRM /* Start the backend. This will enumerate outputs and inputs, become the DRM
* master, etc */ * master, etc */
if (!wlr_backend_start(backend)) { if (!wlr_backend_start(backend))
perror("startup: backend_start"); BARF("startup: backend_start");
wlr_backend_destroy(backend);
wl_display_destroy(dpy);
exit(EXIT_FAILURE);
}
/* Now that outputs are initialized, choose initial selmon based on /* Now that outputs are initialized, choose initial selmon based on
* cursor position, and set default cursor image */ * cursor position, and set default cursor image */
@ -1297,24 +1322,17 @@ run(char *startup_cmd)
setenv("WAYLAND_DISPLAY", socket, 1); setenv("WAYLAND_DISPLAY", socket, 1);
if (startup_cmd) { if (startup_cmd) {
startup_pid = fork(); startup_pid = fork();
if (startup_pid < 0) { if (startup_pid < 0)
perror("startup: fork"); EBARF("startup: fork");
wl_display_destroy(dpy);
exit(EXIT_FAILURE);
}
if (startup_pid == 0) { if (startup_pid == 0) {
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL); execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL);
perror("startup: execl"); EBARF("startup: execl");
wl_display_destroy(dpy);
exit(EXIT_FAILURE);
} }
} }
/* Run the Wayland event loop. This does not return until you exit the /* Run the Wayland event loop. This does not return until you exit the
* compositor. Starting the backend rigged up all of the necessary event * compositor. Starting the backend rigged up all of the necessary event
* loop configuration to listen to libinput events, DRM events, generate * loop configuration to listen to libinput events, DRM events, generate
* frame events at the refresh rate, and so on. */ * frame events at the refresh rate, and so on. */
wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s",
socket);
wl_display_run(dpy); wl_display_run(dpy);
if (startup_cmd) { if (startup_cmd) {
@ -1445,6 +1463,13 @@ setsel(struct wl_listener *listener, void *data)
void void
setup(void) setup(void)
{ {
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
dpy = wl_display_create();
/* clean up child processes immediately */
sigchld(0);
/* The backend is a wlroots feature which abstracts the underlying input and /* The backend is a wlroots feature which abstracts the underlying input and
* output hardware. The autocreate option will choose the most suitable * output hardware. The autocreate option will choose the most suitable
* backend based on the current environment, such as opening an X11 window * backend based on the current environment, such as opening an X11 window
@ -1453,7 +1478,8 @@ setup(void)
* backend uses the renderer, for example, to fall back to software cursors * backend uses the renderer, for example, to fall back to software cursors
* if the backend does not support hardware cursors (some older GPUs * if the backend does not support hardware cursors (some older GPUs
* don't). */ * don't). */
backend = wlr_backend_autocreate(dpy, NULL); if (!(backend = wlr_backend_autocreate(dpy, NULL)))
BARF("couldn't create backend");
/* If we don't provide a renderer, autocreate makes a GLES2 renderer for us. /* If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
* The renderer is responsible for defining the various pixel formats it * The renderer is responsible for defining the various pixel formats it
@ -1471,6 +1497,7 @@ setup(void)
wlr_export_dmabuf_manager_v1_create(dpy); wlr_export_dmabuf_manager_v1_create(dpy);
wlr_screencopy_manager_v1_create(dpy); wlr_screencopy_manager_v1_create(dpy);
wlr_data_device_manager_create(dpy); wlr_data_device_manager_create(dpy);
wlr_gamma_control_manager_v1_create(dpy);
wlr_primary_selection_v1_device_manager_create(dpy); wlr_primary_selection_v1_device_manager_create(dpy);
wlr_viewporter_create(dpy); wlr_viewporter_create(dpy);
@ -1566,15 +1593,22 @@ setup(void)
#endif #endif
} }
void
sigchld(int unused)
{
if (signal(SIGCHLD, sigchld) == SIG_ERR)
EBARF("can't install SIGCHLD handler");
while (0 < waitpid(-1, NULL, WNOHANG))
;
}
void void
spawn(const Arg *arg) spawn(const Arg *arg)
{ {
if (fork() == 0) { if (fork() == 0) {
setsid(); setsid();
execvp(((char **)arg->v)[0], (char **)arg->v); execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwl: execvp %s", ((char **)arg->v)[0]); EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]);
perror(" failed");
exit(EXIT_FAILURE);
} }
} }
@ -1827,14 +1861,12 @@ void
updatewindowtype(Client *c) updatewindowtype(Client *c)
{ {
size_t i; size_t i;
for (i = 0; i < c->surface.xwayland->window_type_len; i++)
if (c->type != XDGShell) if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] ||
for (i = 0; i < c->surface.xwayland->window_type_len; i++) c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] ||
if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] || c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] ||
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] || c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] || c->isfloating = 1;
c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility])
c->isfloating = 1;
} }
void void
@ -1859,65 +1891,53 @@ xwaylandready(struct wl_listener *listener, void *data)
xcb_disconnect(xc); xcb_disconnect(xc);
} }
Client *
xytoindependent(double x, double y)
{
/* Find the topmost visible independent at point (x, y).
* For independents, the most recently created can be used as the "top".
* We rely on the X11 convention of unmapping unmanaged when the "owning"
* client loses focus, which ensures that unmanaged are only visible on
* the current tag. */
Client *c;
struct wlr_box geom;
wl_list_for_each_reverse(c, &independents, link) {
geom.x = c->surface.xwayland->x;
geom.y = c->surface.xwayland->y;
geom.width = c->surface.xwayland->width;
geom.height = c->surface.xwayland->height;
if (wlr_box_contains_point(&geom, x, y))
return c;
}
return NULL;
}
#endif #endif
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *startup_cmd = NULL; char *startup_cmd = NULL;
enum wlr_log_importance loglevel = WLR_ERROR;
int c; int c;
while ((c = getopt(argc, argv, "qvds:h")) != -1) {
switch (c) { while ((c = getopt(argc, argv, "s:h")) != -1) {
case 'q': if (c == 's')
loglevel = WLR_SILENT;
break;
case 'v':
loglevel = WLR_INFO;
break;
case 'd':
loglevel = WLR_DEBUG;
break;
case 's':
startup_cmd = optarg; startup_cmd = optarg;
break; else
default:
goto usage; goto usage;
}
} }
if (optind < argc) if (optind < argc)
goto usage; goto usage;
wlr_log_init(loglevel, NULL);
// Wayland requires XDG_RUNTIME_DIR for creating its communications // Wayland requires XDG_RUNTIME_DIR for creating its communications
// socket // socket
if (!getenv("XDG_RUNTIME_DIR")) { if (!getenv("XDG_RUNTIME_DIR"))
fprintf(stderr, "XDG_RUNTIME_DIR must be set\n"); BARF("XDG_RUNTIME_DIR must be set");
exit(EXIT_FAILURE);
}
/* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */
dpy = wl_display_create();
setup(); setup();
run(startup_cmd); run(startup_cmd);
cleanup();
/* Once wl_display_run returns, we shut down the server. */
#ifdef XWAYLAND
wlr_xwayland_destroy(xwayland);
#endif
wl_display_destroy_clients(dpy);
wl_display_destroy(dpy);
wlr_xcursor_manager_destroy(cursor_mgr);
wlr_cursor_destroy(cursor);
wlr_output_layout_destroy(output_layout);
return EXIT_SUCCESS; return EXIT_SUCCESS;
usage: usage:
printf("Usage: %s [-qvd] [-s startup command]\n", argv[0]); BARF("Usage: %s [-s startup command]", argv[0]);
return EXIT_FAILURE;
} }