diff options
Diffstat (limited to '')
| -rw-r--r-- | config.h | 19 | ||||
| -rw-r--r-- | dwl.c | 99 | 
2 files changed, 109 insertions, 9 deletions
| @@ -1,14 +1,21 @@  /* appearance */  static const float rootcolor[]      = {0.3, 0.3, 0.3, 1.0}; +/* layout(s) */ +static const Layout layouts[] = { +	/* symbol     arrange function */ +	{ "[]=",      tile }, +	{ "><>",      NULL },    /* no layout function means floating behavior */ +}; +  /* monitors */  static const MonitorRule monrules[] = { -	/* name     scale */ -	{ "X11-1",    1 }, -	{ "eDP-1",    2 }, -	{ "HDMI-A-1", 1 }, -	/* defaults */ -	{ NULL,       1 }, +	/* name       mfact nmaster scale layout */ +	{ "X11-1",    0.5,  1,      1,    &layouts[0] }, +	{ "eDP-1",    0.5,  1,      2,    &layouts[0] }, +	{ "HDMI-A-1", 0.5,  1,      1,    &layouts[0] }, +	/* defaults (required) */ +	{ NULL,       0.5,  1,      1,    &layouts[0] },  };  /* keyboard */ @@ -29,7 +29,10 @@  #include <wlr/util/log.h>  #include <xkbcommon/xkbcommon.h> +/* macros */ +#define MIN(A, B)               ((A) < (B) ? (A) : (B))  #define CLEANMASK(mask)         (mask & ~WLR_MODIFIER_CAPS) +#define VISIBLEON(C, M)         ((C)->mon == (M))  #define LENGTH(X)               (sizeof X / sizeof X[0])  /* enums */ @@ -49,6 +52,7 @@ typedef struct {  	const Arg arg;  } Button; +typedef struct Monitor Monitor;  typedef struct {  	struct wl_list link;  	struct wlr_xdg_surface *xdg_surface; @@ -57,7 +61,8 @@ typedef struct {  	struct wl_listener destroy;  	struct wl_listener request_move;  	struct wl_listener request_resize; -	int x, y; +	Monitor *mon; +	int x, y; /* layout-relative */  } Client;  typedef struct { @@ -76,14 +81,28 @@ typedef struct {  } Keyboard;  typedef struct { +	const char *symbol; +	void (*arrange)(Monitor *); +} Layout; + +struct Monitor {  	struct wl_list link;  	struct wlr_output *wlr_output;  	struct wl_listener frame; -} Monitor; +	struct wlr_box *geom; /* layout-relative */ +	int wx, wy, ww, wh; /* layout-relative */ +	const Layout *lt[2]; +	unsigned int sellt; +	double mfact; +	int nmaster; +};  typedef struct {  	const char *name; +	float mfact; +	int nmaster;  	float scale; +	const Layout *lt;  } MonitorRule;  /* Used to move all of the data necessary to render a surface from the top-level @@ -91,10 +110,11 @@ typedef struct {  struct render_data {  	struct wlr_output *output;  	struct timespec *when; -	int x, y; +	int x, y; /* layout-relative */  };  /* function declarations */ +static void arrange(Monitor *m);  static void axisnotify(struct wl_listener *listener, void *data);  static void buttonpress(struct wl_listener *listener, void *data);  static void createkeyboard(struct wlr_input_device *device); @@ -118,11 +138,13 @@ static void moveresize(Client *c, unsigned int mode);  static void quit(const Arg *arg);  static void render(struct wlr_surface *surface, int sx, int sy, void *data);  static void rendermon(struct wl_listener *listener, void *data); +static void resize(Client *c, int x, int y, int w, int h);  static void resizemouse(const Arg *arg);  static void run(char *startup_cmd);  static void setcursor(struct wl_listener *listener, void *data);  static void setup(void);  static void spawn(const Arg *arg); +static void tile(Monitor *m);  static void unmapnotify(struct wl_listener *listener, void *data);  static Client * xytoclient(double x, double y,  		struct wlr_surface **surface, double *sx, double *sy); @@ -156,10 +178,18 @@ static int grab_width, grab_height;  static struct wlr_output_layout *output_layout;  static struct wl_list mons;  static struct wl_listener new_output; +static Monitor *selmon;  #include "config.h"  void +arrange(Monitor *m) +{ +	if (m->lt[m->sellt]->arrange) +		m->lt[m->sellt]->arrange(m); +} + +void  axisnotify(struct wl_listener *listener, void *data)  {  	/* This event is forwarded by the cursor when a pointer emits an axis event, @@ -259,7 +289,10 @@ createmon(struct wl_listener *listener, void *data)  	for (i = 0; i < LENGTH(monrules); i++) {  		if (!monrules[i].name ||  				!strcmp(wlr_output->name, monrules[i].name)) { +			m->mfact = monrules[i].mfact; +			m->nmaster = monrules[i].nmaster;  			wlr_output_set_scale(wlr_output, monrules[i].scale); +			m->lt[0] = m->lt[1] = monrules[i].lt;  			break;  		}  	} @@ -268,6 +301,9 @@ createmon(struct wl_listener *listener, void *data)  	wl_signal_add(&wlr_output->events.frame, &m->frame);  	wl_list_insert(&mons, &m->link); +	if (!selmon) +		selmon = m; +  	/* Adds this to the output layout. The add_auto function arranges outputs  	 * from left-to-right in the order they appear. A more sophisticated  	 * compositor would let the user configure the arrangement of outputs in the @@ -294,6 +330,9 @@ createnotify(struct wl_listener *listener, void *data)  	Client *c = calloc(1, sizeof(*c));  	c->xdg_surface = xdg_surface; +	/* Tell the client not to try anything fancy */ +	wlr_xdg_toplevel_set_tiled(c->xdg_surface, true); +  	/* Listen to the various events it can emit */  	c->map.notify = maprequest;  	wl_signal_add(&xdg_surface->events.map, &c->map); @@ -487,6 +526,7 @@ maprequest(struct wl_listener *listener, void *data)  	Client *c = wl_container_of(listener, c, map);  	/* Insert this client into the list and focus it. */ +	c->mon = selmon;  	wl_list_insert(&clients, &c->link);  	focus(c, c->xdg_surface->surface);  } @@ -699,6 +739,15 @@ rendermon(struct wl_listener *listener, void *data)  	if (!wlr_output_attach_render(m->wlr_output, NULL)) {  		return;  	} +	/* Get effective monitor geometry and window area */ +	m->geom = wlr_output_layout_get_box(output_layout, m->wlr_output); +	m->wx = m->geom->x; +	m->wy = m->geom->y; +	m->ww = m->geom->width; +	m->wh = m->geom->height; + +	arrange(m); +  	/* Begin the renderer (calls glViewport and some other GL sanity checks) */  	wlr_renderer_begin(renderer, m->wlr_output->width, m->wlr_output->height);  	wlr_renderer_clear(renderer, rootcolor); @@ -734,6 +783,14 @@ rendermon(struct wl_listener *listener, void *data)  }  void +resize(Client *c, int x, int y, int w, int h) +{ +	c->x = x; +	c->y = y; +	wlr_xdg_toplevel_set_size(c->xdg_surface, w, h); +} + +void  resizemouse(const Arg *arg)  {  	double sx, sy; @@ -937,6 +994,42 @@ spawn(const Arg *arg)  }  void +tile(Monitor *m) +{ +	unsigned int i, n = 0, h, mw, my, ty; +	Client *c; +	struct wlr_box ca; + +	wl_list_for_each(c, &clients, link) { +		if (VISIBLEON(c, m)) +			n++; +	} +	if (n == 0) +		return; + +	if (n > m->nmaster) +		mw = m->nmaster ? m->ww * m->mfact : 0; +	else +		mw = m->ww; +	i = my = ty = 0; +	wl_list_for_each(c, &clients, link) { +		if (!VISIBLEON(c, m)) +			continue; +		wlr_xdg_surface_get_geometry(c->xdg_surface, &ca); +		if (i < m->nmaster) { +			h = (m->wh - my) / (MIN(n, m->nmaster) - i); +			resize(c, m->wx, m->wy + my, mw, h); +			my += ca.height; +		} else { +			h = (m->wh - ty) / (n - i); +			resize(c, m->wx + mw, m->wy + ty, m->ww - mw, h); +			ty += ca.height; +		} +		i++; +	} +} + +void  unmapnotify(struct wl_listener *listener, void *data)  {  	/* Called when the surface is unmapped, and should no longer be shown. */ | 
