layouts: tile and floating
Behavior's still a little wonky but positioning is there.
This commit is contained in:
parent
6f9f1b9e05
commit
3707e0115a
19
config.h
19
config.h
|
@ -1,14 +1,21 @@
|
||||||
/* appearance */
|
/* appearance */
|
||||||
static const float rootcolor[] = {0.3, 0.3, 0.3, 1.0};
|
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 */
|
/* monitors */
|
||||||
static const MonitorRule monrules[] = {
|
static const MonitorRule monrules[] = {
|
||||||
/* name scale */
|
/* name mfact nmaster scale layout */
|
||||||
{ "X11-1", 1 },
|
{ "X11-1", 0.5, 1, 1, &layouts[0] },
|
||||||
{ "eDP-1", 2 },
|
{ "eDP-1", 0.5, 1, 2, &layouts[0] },
|
||||||
{ "HDMI-A-1", 1 },
|
{ "HDMI-A-1", 0.5, 1, 1, &layouts[0] },
|
||||||
/* defaults */
|
/* defaults (required) */
|
||||||
{ NULL, 1 },
|
{ NULL, 0.5, 1, 1, &layouts[0] },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* keyboard */
|
/* keyboard */
|
||||||
|
|
99
dwl.c
99
dwl.c
|
@ -29,7 +29,10 @@
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
/* macros */
|
||||||
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
|
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
|
||||||
|
#define VISIBLEON(C, M) ((C)->mon == (M))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
|
|
||||||
/* enums */
|
/* enums */
|
||||||
|
@ -49,6 +52,7 @@ typedef struct {
|
||||||
const Arg arg;
|
const Arg arg;
|
||||||
} Button;
|
} Button;
|
||||||
|
|
||||||
|
typedef struct Monitor Monitor;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wlr_xdg_surface *xdg_surface;
|
struct wlr_xdg_surface *xdg_surface;
|
||||||
|
@ -57,7 +61,8 @@ typedef struct {
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener request_move;
|
struct wl_listener request_move;
|
||||||
struct wl_listener request_resize;
|
struct wl_listener request_resize;
|
||||||
int x, y;
|
Monitor *mon;
|
||||||
|
int x, y; /* layout-relative */
|
||||||
} Client;
|
} Client;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -76,14 +81,28 @@ typedef struct {
|
||||||
} Keyboard;
|
} Keyboard;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
const char *symbol;
|
||||||
|
void (*arrange)(Monitor *);
|
||||||
|
} Layout;
|
||||||
|
|
||||||
|
struct Monitor {
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
struct wlr_output *wlr_output;
|
struct wlr_output *wlr_output;
|
||||||
struct wl_listener frame;
|
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 {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
float mfact;
|
||||||
|
int nmaster;
|
||||||
float scale;
|
float scale;
|
||||||
|
const Layout *lt;
|
||||||
} MonitorRule;
|
} MonitorRule;
|
||||||
|
|
||||||
/* Used to move all of the data necessary to render a surface from the top-level
|
/* 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 render_data {
|
||||||
struct wlr_output *output;
|
struct wlr_output *output;
|
||||||
struct timespec *when;
|
struct timespec *when;
|
||||||
int x, y;
|
int x, y; /* layout-relative */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function declarations */
|
/* function declarations */
|
||||||
|
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 createkeyboard(struct wlr_input_device *device);
|
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 quit(const Arg *arg);
|
||||||
static void render(struct wlr_surface *surface, int sx, int sy, void *data);
|
static void render(struct wlr_surface *surface, int sx, int sy, void *data);
|
||||||
static void rendermon(struct wl_listener *listener, 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 resizemouse(const Arg *arg);
|
||||||
static void run(char *startup_cmd);
|
static void run(char *startup_cmd);
|
||||||
static void setcursor(struct wl_listener *listener, void *data);
|
static void setcursor(struct wl_listener *listener, void *data);
|
||||||
static void setup(void);
|
static void setup(void);
|
||||||
static void spawn(const Arg *arg);
|
static void spawn(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
static void unmapnotify(struct wl_listener *listener, void *data);
|
static void unmapnotify(struct wl_listener *listener, void *data);
|
||||||
static Client * xytoclient(double x, double y,
|
static Client * xytoclient(double x, double y,
|
||||||
struct wlr_surface **surface, double *sx, double *sy);
|
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 wlr_output_layout *output_layout;
|
||||||
static struct wl_list mons;
|
static struct wl_list mons;
|
||||||
static struct wl_listener new_output;
|
static struct wl_listener new_output;
|
||||||
|
static Monitor *selmon;
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
arrange(Monitor *m)
|
||||||
|
{
|
||||||
|
if (m->lt[m->sellt]->arrange)
|
||||||
|
m->lt[m->sellt]->arrange(m);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
axisnotify(struct wl_listener *listener, void *data)
|
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++) {
|
for (i = 0; i < LENGTH(monrules); i++) {
|
||||||
if (!monrules[i].name ||
|
if (!monrules[i].name ||
|
||||||
!strcmp(wlr_output->name, 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);
|
wlr_output_set_scale(wlr_output, monrules[i].scale);
|
||||||
|
m->lt[0] = m->lt[1] = monrules[i].lt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,6 +301,9 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
wl_signal_add(&wlr_output->events.frame, &m->frame);
|
wl_signal_add(&wlr_output->events.frame, &m->frame);
|
||||||
wl_list_insert(&mons, &m->link);
|
wl_list_insert(&mons, &m->link);
|
||||||
|
|
||||||
|
if (!selmon)
|
||||||
|
selmon = m;
|
||||||
|
|
||||||
/* Adds this to the output layout. The add_auto function arranges outputs
|
/* Adds this to the output layout. The add_auto function arranges outputs
|
||||||
* from left-to-right in the order they appear. A more sophisticated
|
* from left-to-right in the order they appear. A more sophisticated
|
||||||
* compositor would let the user configure the arrangement of outputs in the
|
* 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));
|
Client *c = calloc(1, sizeof(*c));
|
||||||
c->xdg_surface = xdg_surface;
|
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 */
|
/* Listen to the various events it can emit */
|
||||||
c->map.notify = maprequest;
|
c->map.notify = maprequest;
|
||||||
wl_signal_add(&xdg_surface->events.map, &c->map);
|
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);
|
Client *c = wl_container_of(listener, c, map);
|
||||||
|
|
||||||
/* Insert this client into the list and focus it. */
|
/* Insert this client into the list and focus it. */
|
||||||
|
c->mon = selmon;
|
||||||
wl_list_insert(&clients, &c->link);
|
wl_list_insert(&clients, &c->link);
|
||||||
focus(c, c->xdg_surface->surface);
|
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)) {
|
if (!wlr_output_attach_render(m->wlr_output, NULL)) {
|
||||||
return;
|
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) */
|
/* 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_begin(renderer, m->wlr_output->width, m->wlr_output->height);
|
||||||
wlr_renderer_clear(renderer, rootcolor);
|
wlr_renderer_clear(renderer, rootcolor);
|
||||||
|
@ -733,6 +782,14 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
wlr_output_commit(m->wlr_output);
|
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
|
void
|
||||||
resizemouse(const Arg *arg)
|
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
|
void
|
||||||
unmapnotify(struct wl_listener *listener, void *data)
|
unmapnotify(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue