From 0de1e0a6d233000d01b69f46f07ecd0e37eac0df Mon Sep 17 00:00:00 2001 From: Sean Pringle Date: Sat, 8 Jun 2013 23:55:26 +1000 Subject: [PATCH] support spot layouts and proportions per-monitor --- config.h | 41 +++++++++++++++++++---------------------- event.c | 11 +++++++---- setup.c | 22 ++++++++++++++-------- spot.c | 10 ++++++---- xoat.c | 8 +++++++- 5 files changed, 53 insertions(+), 39 deletions(-) diff --git a/config.h b/config.h index 5b2990b..527efc1 100644 --- a/config.h +++ b/config.h @@ -27,32 +27,28 @@ // | | | // | | 3 | // ------------------------------- - // Actually, there are a few layout choices, but only at build time. -// The layout can be flipped so SPOT1 is on the right. -// If you do this, review the directional move/focus key bindings too. -#define SPOT1_ALIGN SPOT1_LEFT -//#define SPOT1_ALIGN SPOT1_RIGHT +// .spot_start = SMART|CURRENT|SPOT1|SPOT2|SPOT3 +// SMART: Make new windows go to the spot of best fit. +// Works best when apps remember or specify their size. +// CURRENT: New windows open in the focused spot. -// Width of SPOT1 as percentage of screen width. -#define SPOT1_WIDTH_PCT 67 +// .spot1_align = LEFT|RIGHT +// 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. -#define SPOT2_HEIGHT_PCT 67 +// .spot1_width_pct = N +// Width of SPOT1 as percentage of screen width. -// Make new windows go to the same spot as the current window. -// This implies auto-raise and focus stealing. -//#define SPOT_START SPOT_CURRENT +// .spot1_height_pct = N +// Height of SPOT2 as percentage of screen height. -// Make new windows go to the spot of best fit. -// Works best when apps remember or specify their size. -// If spot is not current, window won't steal focus. -#define SPOT_START SPOT_SMART - -// Make all new windows go to a specific spot. -// If spot is not current, window won't steal focus. -//#define SPOT_START SPOT1 +layout layouts[] = { + // Look at xrandr output to determine your monitor order. + { .spot_start = SMART, .spot1_align = LEFT, .spot1_width_pct = 66, .spot2_height_pct = 66 }, // primary monitor + { .spot_start = SMART, .spot1_align = RIGHT, .spot1_width_pct = 60, .spot2_height_pct = 66 }, // secondary monitor, etc... +}; // Available actions... // 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... { .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_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" }, }; diff --git a/event.c b/event.c index e4bee6d..5ef28cd 100644 --- a/event.c +++ b/event.c @@ -75,12 +75,15 @@ void map_request(XEvent *e) { c->monitor = current_mon; 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_START == SPOT_SMART) // find spot of best fit + if (spot == CURRENT) { - 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) { spot = i; break; } } diff --git a/setup.c b/setup.c index d986d61..997b74d 100644 --- a/setup.c +++ b/setup.c @@ -105,20 +105,26 @@ void setup() for_monitors(i, m) { 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? if (m->w < m->h) { - 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 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)); for_spots(j) { 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].h = height_spot1; 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].w = w - width_spot2 - GAP; if (j == SPOT3) continue; @@ -129,17 +135,17 @@ void setup() continue; } // normal wide screen - 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 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)); 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].w = width_spot1; m->spots[j].h = h; 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].h = height_spot2; if (j == SPOT2) continue; diff --git a/spot.c b/spot.c index 15c4796..7cf7ef3 100644 --- a/spot.c +++ b/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) { monitor *m = &monitors[mon]; + int spot1_align = have_layout(mon) ? layouts[mon].spot1_align : LEFT ; + if (m->w < m->h) // rotated? { if (dir == LEFT) return SPOT3; if (dir == RIGHT) return SPOT2; - if (dir == UP) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT1: SPOT2; - if (dir == DOWN) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT2: SPOT1; + if (dir == UP) return spot1_align == LEFT ? SPOT1: SPOT2; + if (dir == DOWN) return spot1_align == LEFT ? SPOT2: SPOT1; return spot; } if (dir == UP) return SPOT2; if (dir == DOWN) return SPOT3; - if (dir == LEFT) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT1: SPOT2; - if (dir == RIGHT) return SPOT1_ALIGN == SPOT1_LEFT ? SPOT2: SPOT1; + if (dir == LEFT) return spot1_align == LEFT ? SPOT1: SPOT2; + if (dir == RIGHT) return spot1_align == LEFT ? SPOT2: SPOT1; return spot; } diff --git a/xoat.c b/xoat.c index aa1e4d0..2cd9d8e 100644 --- a/xoat.c +++ b/xoat.c @@ -57,7 +57,7 @@ Display *display; #define STACK 64 #define MONITORS 3 #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 }; typedef struct { @@ -94,6 +94,12 @@ typedef struct { int num; } 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); void client_free(client*); void action_move(void*, int, client*);