support spot layouts and proportions per-monitor
This commit is contained in:
41
config.h
41
config.h
@@ -27,32 +27,28 @@
|
|||||||
// | | |
|
// | | |
|
||||||
// | | 3 |
|
// | | 3 |
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
|
|
||||||
// Actually, there are a few layout choices, but only at build time.
|
// Actually, there are a few layout choices, but only at build time.
|
||||||
|
|
||||||
// The layout can be flipped so SPOT1 is on the right.
|
// .spot_start = SMART|CURRENT|SPOT1|SPOT2|SPOT3
|
||||||
// If you do this, review the directional move/focus key bindings too.
|
// SMART: Make new windows go to the spot of best fit.
|
||||||
#define SPOT1_ALIGN SPOT1_LEFT
|
// Works best when apps remember or specify their size.
|
||||||
//#define SPOT1_ALIGN SPOT1_RIGHT
|
// CURRENT: New windows open in the focused spot.
|
||||||
|
|
||||||
// Width of SPOT1 as percentage of screen width.
|
// .spot1_align = LEFT|RIGHT
|
||||||
#define SPOT1_WIDTH_PCT 67
|
// The layout can be flipped so SPOT1 is on the right.
|
||||||
|
// If you do this, review the directional move/focus key bindings too.
|
||||||
|
|
||||||
// Height of SPOT2 as percentage of screen height.
|
// .spot1_width_pct = N
|
||||||
#define SPOT2_HEIGHT_PCT 67
|
// Width of SPOT1 as percentage of screen width.
|
||||||
|
|
||||||
// Make new windows go to the same spot as the current window.
|
// .spot1_height_pct = N
|
||||||
// This implies auto-raise and focus stealing.
|
// Height of SPOT2 as percentage of screen height.
|
||||||
//#define SPOT_START SPOT_CURRENT
|
|
||||||
|
|
||||||
// Make new windows go to the spot of best fit.
|
layout layouts[] = {
|
||||||
// Works best when apps remember or specify their size.
|
// Look at xrandr output to determine your monitor order.
|
||||||
// If spot is not current, window won't steal focus.
|
{ .spot_start = SMART, .spot1_align = LEFT, .spot1_width_pct = 66, .spot2_height_pct = 66 }, // primary monitor
|
||||||
#define SPOT_START SPOT_SMART
|
{ .spot_start = SMART, .spot1_align = RIGHT, .spot1_width_pct = 60, .spot2_height_pct = 66 }, // secondary monitor, etc...
|
||||||
|
};
|
||||||
// Make all new windows go to a specific spot.
|
|
||||||
// If spot is not current, window won't steal focus.
|
|
||||||
//#define SPOT_START SPOT1
|
|
||||||
|
|
||||||
// Available actions...
|
// Available actions...
|
||||||
// action_move .num = SPOT1/2/3
|
// action_move .num = SPOT1/2/3
|
||||||
@@ -128,7 +124,8 @@ binding keys[] = {
|
|||||||
// Only works for apps that use some form of their binary name as their class...
|
// Only works for apps that use some form of their binary name as their class...
|
||||||
{ .mod = AnyModifier, .key = XK_F1, .act = action_find_or_start, .data = "konsole" },
|
{ .mod = AnyModifier, .key = XK_F1, .act = action_find_or_start, .data = "konsole" },
|
||||||
{ .mod = AnyModifier, .key = XK_F2, .act = action_find_or_start, .data = "chromium" },
|
{ .mod = AnyModifier, .key = XK_F2, .act = action_find_or_start, .data = "chromium" },
|
||||||
{ .mod = AnyModifier, .key = XK_F3, .act = action_find_or_start, .data = "thunar" },
|
{ .mod = AnyModifier, .key = XK_F3, .act = action_find_or_start, .data = "pcmanfm" },
|
||||||
|
{ .mod = AnyModifier, .key = XK_F4, .act = action_find_or_start, .data = "sublime-text" },
|
||||||
|
|
||||||
{ .mod = AnyModifier, .key = XK_Menu, .act = action_command, .data = "xowl" },
|
{ .mod = AnyModifier, .key = XK_Print, .act = action_command, .data = "xowl" },
|
||||||
};
|
};
|
||||||
|
|||||||
11
event.c
11
event.c
@@ -75,12 +75,15 @@ void map_request(XEvent *e)
|
|||||||
{
|
{
|
||||||
c->monitor = current_mon;
|
c->monitor = current_mon;
|
||||||
monitor *m = &monitors[c->monitor];
|
monitor *m = &monitors[c->monitor];
|
||||||
|
int spot = have_layout(c->monitor) ? layouts[c->monitor].spot_start: SMART;
|
||||||
|
|
||||||
int i, spot = SPOT_START == SPOT_CURRENT ? current_spot: SPOT_START;
|
if (spot == CURRENT)
|
||||||
|
|
||||||
if (SPOT_START == SPOT_SMART) // find spot of best fit
|
|
||||||
{
|
{
|
||||||
spot = SPOT1; for_spots_rev(i)
|
spot = current_spot;
|
||||||
|
}
|
||||||
|
if (spot == SMART) // find spot of best fit
|
||||||
|
{
|
||||||
|
int i; spot = SPOT1; for_spots_rev(i)
|
||||||
if (c->attr.width <= m->spots[i].w && c->attr.height <= m->spots[i].h)
|
if (c->attr.width <= m->spots[i].w && c->attr.height <= m->spots[i].h)
|
||||||
{ spot = i; break; }
|
{ spot = i; break; }
|
||||||
}
|
}
|
||||||
|
|||||||
22
setup.c
22
setup.c
@@ -105,20 +105,26 @@ void setup()
|
|||||||
for_monitors(i, m)
|
for_monitors(i, m)
|
||||||
{
|
{
|
||||||
int x = m->x, y = m->y, w = m->w, h = m->h;
|
int x = m->x, y = m->y, w = m->w, h = m->h;
|
||||||
|
|
||||||
|
// determine spot layout for this monitor
|
||||||
|
int spot1_align = have_layout(i) ? layouts[i].spot1_align : LEFT ;
|
||||||
|
int spot1_width_pct = have_layout(i) ? layouts[i].spot1_width_pct : 66;
|
||||||
|
int spot2_height_pct = have_layout(i) ? layouts[i].spot2_height_pct : 66;
|
||||||
|
|
||||||
// monitor rotated?
|
// monitor rotated?
|
||||||
if (m->w < m->h)
|
if (m->w < m->h)
|
||||||
{
|
{
|
||||||
int height_spot1 = (double)h / 100 * MIN(90, MAX(10, SPOT1_WIDTH_PCT));
|
int height_spot1 = (double)h / 100 * MIN(90, MAX(10, spot1_width_pct));
|
||||||
int width_spot2 = (double)w / 100 * MIN(90, MAX(10, SPOT2_HEIGHT_PCT));
|
int width_spot2 = (double)w / 100 * MIN(90, MAX(10, spot2_height_pct));
|
||||||
for_spots(j)
|
for_spots(j)
|
||||||
{
|
{
|
||||||
m->spots[j].x = x;
|
m->spots[j].x = x;
|
||||||
m->spots[j].y = SPOT1_ALIGN == SPOT1_LEFT ? y: y + h - height_spot1;
|
m->spots[j].y = spot1_align == LEFT ? y: y + h - height_spot1;
|
||||||
m->spots[j].w = w;
|
m->spots[j].w = w;
|
||||||
m->spots[j].h = height_spot1;
|
m->spots[j].h = height_spot1;
|
||||||
if (j == SPOT1) continue;
|
if (j == SPOT1) continue;
|
||||||
|
|
||||||
m->spots[j].y = SPOT1_ALIGN == SPOT1_LEFT ? y + height_spot1 + GAP: y;
|
m->spots[j].y = spot1_align == LEFT ? y + height_spot1 + GAP: y;
|
||||||
m->spots[j].h = h - height_spot1 - GAP;
|
m->spots[j].h = h - height_spot1 - GAP;
|
||||||
m->spots[j].w = w - width_spot2 - GAP;
|
m->spots[j].w = w - width_spot2 - GAP;
|
||||||
if (j == SPOT3) continue;
|
if (j == SPOT3) continue;
|
||||||
@@ -129,17 +135,17 @@ void setup()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// normal wide screen
|
// normal wide screen
|
||||||
int width_spot1 = (double)w / 100 * MIN(90, MAX(10, SPOT1_WIDTH_PCT));
|
int width_spot1 = (double)w / 100 * MIN(90, MAX(10, spot1_width_pct));
|
||||||
int height_spot2 = (double)h / 100 * MIN(90, MAX(10, SPOT2_HEIGHT_PCT));
|
int height_spot2 = (double)h / 100 * MIN(90, MAX(10, spot2_height_pct));
|
||||||
for_spots(j)
|
for_spots(j)
|
||||||
{
|
{
|
||||||
m->spots[j].x = SPOT1_ALIGN == SPOT1_LEFT ? x: x + w - width_spot1;
|
m->spots[j].x = spot1_align == LEFT ? x: x + w - width_spot1;
|
||||||
m->spots[j].y = y;
|
m->spots[j].y = y;
|
||||||
m->spots[j].w = width_spot1;
|
m->spots[j].w = width_spot1;
|
||||||
m->spots[j].h = h;
|
m->spots[j].h = h;
|
||||||
if (j == SPOT1) continue;
|
if (j == SPOT1) continue;
|
||||||
|
|
||||||
m->spots[j].x = SPOT1_ALIGN == SPOT1_LEFT ? x + width_spot1 + GAP: x;
|
m->spots[j].x = spot1_align == LEFT ? x + width_spot1 + GAP: x;
|
||||||
m->spots[j].w = w - width_spot1 - GAP;
|
m->spots[j].w = w - width_spot1 - GAP;
|
||||||
m->spots[j].h = height_spot2;
|
m->spots[j].h = height_spot2;
|
||||||
if (j == SPOT2) continue;
|
if (j == SPOT2) continue;
|
||||||
|
|||||||
10
spot.c
10
spot.c
@@ -115,18 +115,20 @@ Window spot_try_focus_top_window(int spot, int mon, Window except)
|
|||||||
int spot_choose_by_direction(int spot, int mon, int dir)
|
int spot_choose_by_direction(int spot, int mon, int dir)
|
||||||
{
|
{
|
||||||
monitor *m = &monitors[mon];
|
monitor *m = &monitors[mon];
|
||||||
|
int spot1_align = have_layout(mon) ? layouts[mon].spot1_align : LEFT ;
|
||||||
|
|
||||||
if (m->w < m->h) // rotated?
|
if (m->w < m->h) // rotated?
|
||||||
{
|
{
|
||||||
if (dir == LEFT) return SPOT3;
|
if (dir == LEFT) return SPOT3;
|
||||||
if (dir == RIGHT) return SPOT2;
|
if (dir == RIGHT) return SPOT2;
|
||||||
if (dir == UP) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT1: SPOT2;
|
if (dir == UP) return spot1_align == LEFT ? SPOT1: SPOT2;
|
||||||
if (dir == DOWN) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT2: SPOT1;
|
if (dir == DOWN) return spot1_align == LEFT ? SPOT2: SPOT1;
|
||||||
return spot;
|
return spot;
|
||||||
}
|
}
|
||||||
if (dir == UP) return SPOT2;
|
if (dir == UP) return SPOT2;
|
||||||
if (dir == DOWN) return SPOT3;
|
if (dir == DOWN) return SPOT3;
|
||||||
if (dir == LEFT) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT1: SPOT2;
|
if (dir == LEFT) return spot1_align == LEFT ? SPOT1: SPOT2;
|
||||||
if (dir == RIGHT) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT2: SPOT1;
|
if (dir == RIGHT) return spot1_align == LEFT ? SPOT2: SPOT1;
|
||||||
return spot;
|
return spot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
xoat.c
8
xoat.c
@@ -57,7 +57,7 @@ Display *display;
|
|||||||
#define STACK 64
|
#define STACK 64
|
||||||
#define MONITORS 3
|
#define MONITORS 3
|
||||||
#define ATOMLIST 10
|
#define ATOMLIST 10
|
||||||
enum { SPOT1=1, SPOT2, SPOT3, SPOT_CURRENT, SPOT_SMART, SPOT1_LEFT, SPOT1_RIGHT };
|
enum { SPOT1=1, SPOT2, SPOT3, CURRENT, SMART };
|
||||||
enum { LEFT=1, RIGHT, UP, DOWN };
|
enum { LEFT=1, RIGHT, UP, DOWN };
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -94,6 +94,12 @@ typedef struct {
|
|||||||
int num;
|
int num;
|
||||||
} binding;
|
} binding;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short spot_start, spot1_align, spot1_width_pct, spot2_height_pct;
|
||||||
|
} layout;
|
||||||
|
|
||||||
|
#define have_layout(i) (sizeof(layouts) / sizeof(layout) > (i))
|
||||||
|
|
||||||
client* window_build_client(Window);
|
client* window_build_client(Window);
|
||||||
void client_free(client*);
|
void client_free(client*);
|
||||||
void action_move(void*, int, client*);
|
void action_move(void*, int, client*);
|
||||||
|
|||||||
Reference in New Issue
Block a user