layouts: tile and floating
Behavior's still a little wonky but positioning is there.
This commit is contained in:
		
							
								
								
									
										19
									
								
								config.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								config.h
									
									
									
									
									
								
							| @@ -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 */ | ||||
|   | ||||
							
								
								
									
										99
									
								
								dwl.c
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								dwl.c
									
									
									
									
									
								
							| @@ -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,9 +178,17 @@ 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) | ||||
| { | ||||
| @@ -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); | ||||
| @@ -733,6 +782,14 @@ rendermon(struct wl_listener *listener, void *data) | ||||
| 	wlr_output_commit(m->wlr_output); | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| @@ -936,6 +993,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) | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user