Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3a72cd924c | ||
|
2a9404ac2a | ||
|
3c83e0cfb8 | ||
|
e73ea679f4 | ||
|
db647f2df6 | ||
|
cd3d0a102f | ||
|
38ba6d2277 | ||
|
c2b53c2d8d | ||
|
ecc60878b3 | ||
|
43b6e804cf | ||
|
fba820d5f6 | ||
|
1fa72b0772 | ||
|
7cee5060bc | ||
|
2144546192 | ||
|
15f5d31f98 | ||
|
5b51bb82e2 | ||
|
f5e7caac00 | ||
|
593b7eec3c | ||
|
b063dd89c3 | ||
|
fd498e1910 | ||
|
02eed717ca | ||
|
2d71c9b9ff | ||
|
87b16e6095 | ||
|
c1eb2b49cd | ||
|
e8192b4fc9 | ||
|
4798450944 | ||
|
a1e24075d8 | ||
|
27598bd04a | ||
|
3868217466 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -2,7 +2,7 @@
|
||||
name: Bug report
|
||||
about: Something in dwl isn't working correctly
|
||||
title: ''
|
||||
labels: 'Type: bug'
|
||||
labels: 'A: bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
2
.github/ISSUE_TEMPLATE/enhancement-idea.md
vendored
2
.github/ISSUE_TEMPLATE/enhancement-idea.md
vendored
@@ -2,7 +2,7 @@
|
||||
name: Enhancement idea
|
||||
about: Suggest a feature or improvement
|
||||
title: ''
|
||||
labels: 'Type: enhancement'
|
||||
labels: 'A: enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
@@ -11,7 +11,7 @@ dwl is a compact, hackable compositor for Wayland based on [wlroots](https://git
|
||||
|
||||
dwl is not meant to provide every feature under the sun. Instead, like dwm, it sticks to features which are necessary, simple, and straightforward to implement given the base on which it is built. Implemented default features are:
|
||||
|
||||
- Any features provided by dwm/Xlib: simple window borders, tags, keybindings, client rules, mouse move/resize. The built-in status bar is an exception to avoid taking a dependency on FreeType or Pango and increasing the SLOC
|
||||
- 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
|
||||
- Various Wayland protocols
|
||||
@@ -21,7 +21,7 @@ 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
|
||||
- Communication from the compositor to status bars. A straightforward possibility would be to use stdout or a provided file descriptor.
|
||||
- Provide information to external status bars via stdout or another file descriptor
|
||||
- Implement the input-inhibitor protocol to support screen lockers
|
||||
- Implement the idle-inhibit protocol which lets applications such as mpv disable idle monitoring
|
||||
- Layer shell popups (used by Waybar)
|
||||
@@ -37,7 +37,7 @@ Feature *non-goals* include:
|
||||
|
||||
## Building dwl
|
||||
|
||||
dwl has only two dependencies: wlroots 0.12 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next).
|
||||
dwl has only two dependencies: wlroots 0.13 and wayland-protocols. Simply install these and run `make`. If you wish to build against a Git version of wlroots, check out the [wlroots-next branch](https://github.com/djpohly/dwl/tree/wlroots-next).
|
||||
|
||||
To enable XWayland, you should also install xorg-xwayland and uncomment its flag in `config.mk`.
|
||||
|
||||
|
@@ -49,7 +49,7 @@ static const int repeat_delay = 600;
|
||||
|
||||
/* Trackpad */
|
||||
static const int tap_to_click = 1;
|
||||
static const int natural_scrolling = 1;
|
||||
static const int natural_scrolling = 0;
|
||||
|
||||
#define MODKEY WLR_MODIFIER_ALT
|
||||
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||
@@ -62,11 +62,13 @@ static const int natural_scrolling = 1;
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
|
||||
/* commands */
|
||||
static const char *termcmd[] = { "alacritty", NULL };
|
||||
static const char *termcmd[] = { "alacritty", NULL };
|
||||
static const char *menucmd[] = { "bemenu-run", NULL };
|
||||
|
||||
static const Key keys[] = {
|
||||
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||
@@ -99,6 +101,8 @@ static const Key keys[] = {
|
||||
TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||
TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} },
|
||||
|
||||
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
|
||||
#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
|
||||
CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
|
||||
|
90
dwl.c
90
dwl.c
@@ -175,7 +175,6 @@ struct Monitor {
|
||||
unsigned int tagset[2];
|
||||
double mfact;
|
||||
int nmaster;
|
||||
Client *fullscreenclient;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -249,7 +248,6 @@ static void keypressmod(struct wl_listener *listener, void *data);
|
||||
static void killclient(const Arg *arg);
|
||||
static void maplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||
static void mapnotify(struct wl_listener *listener, void *data);
|
||||
static void maximizeclient(Client *c);
|
||||
static void monocle(Monitor *m);
|
||||
static void motionabsolute(struct wl_listener *listener, void *data);
|
||||
static void motionnotify(uint32_t time);
|
||||
@@ -260,6 +258,7 @@ static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int
|
||||
static void outputmgrtest(struct wl_listener *listener, void *data);
|
||||
static void pointerfocus(Client *c, struct wlr_surface *surface,
|
||||
double sx, double sy, uint32_t time);
|
||||
static void printstatus(void);
|
||||
static void quit(const Arg *arg);
|
||||
static void render(struct wlr_surface *surface, int sx, int sy, void *data);
|
||||
static void renderclients(Monitor *m, struct timespec *now);
|
||||
@@ -484,8 +483,6 @@ arrange(Monitor *m)
|
||||
{
|
||||
if (m->lt[m->sellt]->arrange)
|
||||
m->lt[m->sellt]->arrange(m);
|
||||
else if (m->fullscreenclient)
|
||||
maximizeclient(m->fullscreenclient);
|
||||
/* TODO recheck pointer focus here... or in resize()? */
|
||||
}
|
||||
|
||||
@@ -884,9 +881,6 @@ createnotify(struct wl_listener *listener, void *data)
|
||||
|
||||
if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
return;
|
||||
wl_list_for_each(c, &clients, link)
|
||||
if (c->isfullscreen && VISIBLEON(c, c->mon))
|
||||
setfullscreen(c, 0);
|
||||
|
||||
/* Allocate a Client for this surface */
|
||||
c = xdg_surface->data = calloc(1, sizeof(*c));
|
||||
@@ -1041,14 +1035,8 @@ void
|
||||
togglefullscreen(const Arg *arg)
|
||||
{
|
||||
Client *sel = selclient();
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
void
|
||||
maximizeclient(Client *c)
|
||||
{
|
||||
resize(c, c->mon->m.x, c->mon->m.y, c->mon->m.width, c->mon->m.height, 0);
|
||||
/* used for fullscreen clients */
|
||||
if (sel)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1063,13 +1051,11 @@ setfullscreen(Client *c, int fullscreen)
|
||||
c->prevy = c->geom.y;
|
||||
c->prevheight = c->geom.height;
|
||||
c->prevwidth = c->geom.width;
|
||||
c->mon->fullscreenclient = c;
|
||||
maximizeclient(c);
|
||||
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->prevx, c->prevy, c->prevwidth, c->prevheight, 0);
|
||||
c->mon->fullscreenclient = NULL;
|
||||
arrange(c->mon);
|
||||
}
|
||||
}
|
||||
@@ -1116,6 +1102,7 @@ focusclient(Client *c, int lift)
|
||||
wl_list_insert(&fstack, &c->flink);
|
||||
selmon = c->mon;
|
||||
}
|
||||
printstatus();
|
||||
|
||||
/* Deactivate old client if focus is changing */
|
||||
if (old && (!c || client_surface(c) != old)) {
|
||||
@@ -1284,7 +1271,7 @@ keypress(struct wl_listener *listener, void *data)
|
||||
wlr_idle_notify_activity(idle, seat);
|
||||
|
||||
/* On _press_, attempt to process a compositor keybinding. */
|
||||
if (event->state == WLR_KEY_PRESSED)
|
||||
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
for (i = 0; i < nsyms; i++)
|
||||
handled = keybinding(mods, syms[i]) || handled;
|
||||
|
||||
@@ -1335,7 +1322,7 @@ void
|
||||
mapnotify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||
Client *c = wl_container_of(listener, c, map), *oldfocus = selclient();
|
||||
Client *c = wl_container_of(listener, c, map);
|
||||
|
||||
if (client_is_unmanaged(c)) {
|
||||
/* Insert this independent into independents lists. */
|
||||
@@ -1354,14 +1341,6 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||
|
||||
/* Set initial monitor, tags, floating status, and focus */
|
||||
applyrules(c);
|
||||
|
||||
if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus
|
||||
&& !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) {
|
||||
maximizeclient(c->mon->fullscreenclient);
|
||||
focusclient(c->mon->fullscreenclient, 1);
|
||||
/* give the focus back the fullscreen client on that monitor if exists,
|
||||
* is focused and the new client isn't floating */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1370,12 +1349,9 @@ monocle(Monitor *m)
|
||||
Client *c;
|
||||
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating)
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (c->isfullscreen)
|
||||
maximizeclient(c);
|
||||
else
|
||||
resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0);
|
||||
resize(c, m->w.x, m->w.y, m->w.width, m->w.height, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1478,8 +1454,7 @@ motionrelative(struct wl_listener *listener, void *data)
|
||||
void
|
||||
moveresize(const Arg *arg)
|
||||
{
|
||||
grabc = xytoclient(cursor->x, cursor->y);
|
||||
if (!grabc)
|
||||
if (cursor_mode != CurNormal || !(grabc = xytoclient(cursor->x, cursor->y)))
|
||||
return;
|
||||
|
||||
/* Float the window and tell motionnotify to grab it */
|
||||
@@ -1602,6 +1577,31 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||
focusclient(c, 0);
|
||||
}
|
||||
|
||||
void
|
||||
printstatus(void)
|
||||
{
|
||||
Monitor *m = NULL;
|
||||
Client *c = NULL;
|
||||
unsigned int activetags;
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
activetags=0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (c->mon == m)
|
||||
activetags |= c->tags;
|
||||
}
|
||||
if (focustop(m))
|
||||
printf("%s title %s\n", m->wlr_output->name, client_get_title(focustop(m)));
|
||||
else
|
||||
printf("%s title \n", m->wlr_output->name);
|
||||
|
||||
printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
|
||||
printf("%s tags %u %u\n", m->wlr_output->name, activetags, m->tagset[m->seltags]);
|
||||
printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void
|
||||
quit(const Arg *arg)
|
||||
{
|
||||
@@ -1844,6 +1844,7 @@ run(char *startup_cmd)
|
||||
if (startup_pid < 0)
|
||||
EBARF("startup: fork");
|
||||
if (startup_pid == 0) {
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
|
||||
EBARF("startup: execl");
|
||||
}
|
||||
@@ -1914,6 +1915,7 @@ setlayout(const Arg *arg)
|
||||
selmon->lt[selmon->sellt] = (Layout *)arg->v;
|
||||
/* TODO change layout symbol? */
|
||||
arrange(selmon);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
/* arg > 1.0 will set mfact absolutely */
|
||||
@@ -1995,7 +1997,7 @@ setup(void)
|
||||
* backend uses the renderer, for example, to fall back to software cursors
|
||||
* if the backend does not support hardware cursors (some older GPUs
|
||||
* don't). */
|
||||
if (!(backend = wlr_backend_autocreate(dpy, NULL)))
|
||||
if (!(backend = wlr_backend_autocreate(dpy)))
|
||||
BARF("couldn't create backend");
|
||||
|
||||
/* If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
|
||||
@@ -2139,6 +2141,11 @@ setup(void)
|
||||
void
|
||||
sigchld(int unused)
|
||||
{
|
||||
/* We should be able to remove this function in favor of a simple
|
||||
* signal(SIGCHLD, SIG_IGN);
|
||||
* but the Xwayland implementation in wlroots currently prevents us from
|
||||
* setting our own disposition for SIGCHLD.
|
||||
*/
|
||||
if (signal(SIGCHLD, sigchld) == SIG_ERR)
|
||||
EBARF("can't install SIGCHLD handler");
|
||||
while (0 < waitpid(-1, NULL, WNOHANG))
|
||||
@@ -2149,6 +2156,7 @@ void
|
||||
spawn(const Arg *arg)
|
||||
{
|
||||
if (fork() == 0) {
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
setsid();
|
||||
execvp(((char **)arg->v)[0], (char **)arg->v);
|
||||
EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]);
|
||||
@@ -2164,6 +2172,7 @@ tag(const Arg *arg)
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(selmon);
|
||||
}
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2193,11 +2202,9 @@ tile(Monitor *m)
|
||||
mw = m->w.width;
|
||||
i = my = ty = 0;
|
||||
wl_list_for_each(c, &clients, link) {
|
||||
if (!VISIBLEON(c, m) || c->isfloating)
|
||||
if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||
continue;
|
||||
if (c->isfullscreen)
|
||||
maximizeclient(c);
|
||||
else if (i < m->nmaster) {
|
||||
if (i < m->nmaster) {
|
||||
h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
|
||||
resize(c, m->w.x, m->w.y + my, mw, h, 0);
|
||||
my += c->geom.height;
|
||||
@@ -2233,6 +2240,7 @@ toggletag(const Arg *arg)
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(selmon);
|
||||
}
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2245,6 +2253,7 @@ toggleview(const Arg *arg)
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(selmon);
|
||||
}
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2325,6 +2334,7 @@ view(const Arg *arg)
|
||||
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
||||
focusclient(focustop(selmon), 1);
|
||||
arrange(selmon);
|
||||
printstatus();
|
||||
}
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user