Merge branch 'master' of github.com:seanpringle/xoat

Conflicts:
	config.h
This commit is contained in:
Sean Pringle
2012-12-16 14:17:28 +10:00
8 changed files with 66 additions and 112 deletions

View File

@@ -113,44 +113,16 @@ void action_fullscreen(void *data, int num, client *cli)
client_raise_family(cli);
}
void action_above(void *data, int num, client *cli)
void action_maximize_vert(void *data, int num, client *cli)
{
if (!cli) return;
client_toggle_state(cli, atoms[_NET_WM_STATE_ABOVE]);
client_update_border(cli);
client_raise_family(cli);
cli->maxv = client_toggle_state(cli, atoms[_NET_WM_STATE_MAXIMIZE_VERT]);
client_place_spot(cli, cli->spot, cli->monitor, 1);
}
void action_snapshot(void *data, int num, client *cli)
void action_maximize_horz(void *data, int num, client *cli)
{
int i; client *c; STACK_FREE(&snapshot);
for_windows(i, c) if (c->manage && c->class)
snapshot.clients[snapshot.depth++] = window_build_client(c->window);
if (!cli) return;
cli->maxh = client_toggle_state(cli, atoms[_NET_WM_STATE_MAXIMIZE_HORZ]);
client_place_spot(cli, cli->spot, cli->monitor, 1);
}
void action_rollback(void *data, int num, client *cli)
{
int i; client *c = NULL, *s, *a = NULL;
for (i = snapshot.depth-1; i > -1; i--)
{
if ((s = snapshot.clients[i]) && (c = window_build_client(s->window))
&& c->class && !strcmp(s->class, c->class) && c->visible && c->manage)
{
client_place_spot(c, s->spot, s->monitor, 1);
client_raise_family(c);
if (s->spot == current_spot && s->monitor == current_mon)
{
client_free(a);
a = c; c = NULL;
}
}
client_free(c);
c = NULL;
}
if (a)
{
client_set_focus(a);
client_free(a);
}
}

3
atom.c
View File

@@ -49,7 +49,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
X(_NET_WM_WINDOW_TYPE_DIALOG),\
X(_NET_WM_STATE),\
X(_NET_WM_STATE_FULLSCREEN),\
X(_NET_WM_STATE_ABOVE),\
X(_NET_WM_STATE_MAXIMIZE_VERT),\
X(_NET_WM_STATE_MAXIMIZE_HORZ),\
X(_NET_WM_STATE_DEMANDS_ATTENTION),\
X(WM_NAME),\
X(WM_DELETE_WINDOW),\

View File

@@ -46,7 +46,6 @@ int client_toggle_state(client *c, Atom state)
}
SETPROP_ATOM(c->window, atoms[_NET_WM_STATE], c->states, j);
if (state == atoms[_NET_WM_STATE_FULLSCREEN]) c->full = rc;
if (state == atoms[_NET_WM_STATE_ABOVE]) c->above = rc;
if (state == atoms[_NET_WM_STATE_DEMANDS_ATTENTION]) c->urgent = rc;
return rc;
}
@@ -71,6 +70,7 @@ client* window_build_client(Window win)
&& c->type != atoms[_NET_WM_WINDOW_TYPE_SPLASH]
? 1:0;
// detect our own title bars
for_monitors(i, m) for_spots(j)
if (m->bars[j] && m->bars[j]->window == c->window)
{ c->ours = 1; c->manage = 0; break; }
@@ -93,9 +93,23 @@ client* window_build_client(Window win)
{
if (!GETPROP_ATOM(c->window, atoms[_NET_WM_STATE], c->states, ATOMLIST))
memset(c->states, 0, sizeof(Atom) * ATOMLIST);
c->urgent = client_has_state(c, atoms[_NET_WM_STATE_DEMANDS_ATTENTION]);
c->full = client_has_state(c, atoms[_NET_WM_STATE_FULLSCREEN]);
c->above = client_has_state(c, atoms[_NET_WM_STATE_ABOVE]);
c->maxv = client_has_state(c, atoms[_NET_WM_STATE_MAXIMIZE_VERT]);
c->maxh = client_has_state(c, atoms[_NET_WM_STATE_MAXIMIZE_HORZ]);
// _NET_WM_STATE_MAXIMIZE_VERT may apply to spot2 windows. Detect...
if (c->maxv && c->type != atoms[_NET_WM_WINDOW_TYPE_DIALOG]
&& INTERSECT(m->spots[SPOT2].x, m->spots[SPOT2].y, m->spots[SPOT2].w, m->spots[SPOT2].h,
c->attr.x + c->attr.width/10, c->attr.y + c->attr.height/10, c->attr.width - c->attr.width/10, c->attr.height - c->attr.height/10))
c->spot = SPOT2;
// _NET_WM_STATE_MAXIMIZE_HORZ may apply to spot3 windows. Detect...
if (c->maxh && c->type != atoms[_NET_WM_WINDOW_TYPE_DIALOG]
&& INTERSECT(m->spots[SPOT3].x, m->spots[SPOT3].y, m->spots[SPOT3].w, m->spots[SPOT3].h,
c->attr.x + c->attr.width/10, c->attr.y + c->attr.height/10, c->attr.width - c->attr.width/10, c->attr.height - c->attr.height/10))
c->spot = SPOT3;
if ((hints = XGetWMHints(display, c->window)))
{
@@ -126,7 +140,7 @@ void client_free(client *c)
void client_update_border(client *c)
{
XColor color; Colormap map = DefaultColormap(display, DefaultScreen(display));
char *colorname = c->window == current ? BORDER_FOCUS: (c->urgent ? BORDER_URGENT: (c->above ? BORDER_ABOVE: BORDER_BLUR));
char *colorname = c->window == current ? BORDER_FOCUS: (c->urgent ? BORDER_URGENT: BORDER_BLUR);
XSetWindowBorder(display, c->window, XAllocNamedColor(display, map, colorname, &color, &color) ? color.pixel: None);
XSetWindowBorderWidth(display, c->window, c->full ? 0: BORDER);
}
@@ -181,6 +195,19 @@ void client_place_spot(client *c, int spot, int mon, int force)
XMoveResizeWindow(display, c->window, m->x, m->y, m->w, m->h);
return;
}
else
// _NET_WM_STATE_MAXIMIZE_VERT may apply to a window in spot2
if (c->maxv && spot == SPOT2)
{
h = m->h - y;
}
else
// _NET_WM_STATE_MAXIMIZE_HORZ may apply to a window in spot3
if (c->maxh && spot == SPOT3)
{
w = m->w;
}
w -= BORDER*2; h -= BORDER*2;
int sw = w, sh = h; long sr; XSizeHints size;
@@ -240,16 +267,23 @@ void client_raise_family(client *c)
for_windows(i, o) if (o->type == atoms[_NET_WM_WINDOW_TYPE_DOCK])
client_stack_family(o, &raise);
// above only counts for fullscreen windows
if (c->full) for_windows(i, o) if (o->above)
client_stack_family(o, &raise);
while (c->transient && (o = window_build_client(c->transient)))
c = family.clients[family.depth++] = o;
client_stack_family(c, &raise);
if (!c->full)
{
// raise spot's title bar in case some other fullscreen or max v/h window has obscured
monitor *m = &monitors[c->monitor];
raise.windows[raise.depth] = m->bars[c->spot]->window;
raise.clients[raise.depth] = NULL;
raise.depth++;
}
XRaiseWindow(display, raise.windows[0]);
XRestackWindows(display, raise.windows, raise.depth);
STACK_FREE(&family);
}

View File

@@ -4,11 +4,10 @@
#define BORDER_BLUR "Dark Gray"
#define BORDER_FOCUS "Royal Blue"
#define BORDER_URGENT "Red"
#define BORDER_ABOVE "Dark Green"
#define GAP 2
// Title bar xft font
#define TITLE "sans:size=10"
#define TITLE "sans:size=8"
#define TITLE_BLUR "Black"
#define TITLE_FOCUS "White"
#define TITLE_ELLIPSIS 30
@@ -51,19 +50,6 @@
// If spot is not current, window won't steal focus.
//#define SPOT_START SPOT1
// If on multi-head, place windows on monitor N.
// (0-based index, same order as xrandr list)
//#define MONITOR_START 0
// If on multi-head, place windows on monitor holding current window.
#define MONITOR_START MONITOR_CURRENT
// Should new windows be automatically focused, or ignored until focused manually?
// IGNORE means new windows only steal focus if they obscure the current window.
// STEAL means new windows always steal focus.
//#define FOCUS_START FOCUS_IGNORE
#define FOCUS_START FOCUS_STEAL
// Available actions...
// action_move .num = SPOT1/2/3
// action_focus .num = SPOT1/2/3
@@ -71,15 +57,13 @@
// action_focus_direction .num = UP/DOWN/LEFT/RIGHT
// action_close
// action_cycle
// action_other
// action_command
// action_find_or_start
// action_move_monitor
// action_focus_monitor
// action_fullscreen
// action_above
// action_snapshot
// action_rollback
// action_maximize_vert
// action_maximize_horz
// If you use "AnyModifier" place those keys at the end of the array.
binding keys[] = {
@@ -118,9 +102,8 @@ binding keys[] = {
// Toggle current window full screen.
{ .mod = Mod4Mask, .key = XK_f, .act = action_fullscreen },
// Toggle current window above.
{ .mod = Mod4Mask, .key = XK_a, .act = action_above },
{ .mod = Mod4Mask, .key = XK_v, .act = action_maximize_vert },
{ .mod = Mod4Mask, .key = XK_h, .act = action_maximize_horz },
// Switch focus between monitors.
{ .mod = Mod4Mask, .key = XK_Next, .act = action_focus_monitor, .num = +1 },
@@ -133,10 +116,6 @@ binding keys[] = {
// Launcher
{ .mod = Mod4Mask, .key = XK_x, .act = action_command, .data = "dmenu_run" },
// Snapshot state
{ .mod = Mod4Mask, .key = XK_s, .act = action_snapshot },
{ .mod = Mod4Mask, .key = XK_r, .act = action_rollback },
// Find or start apps by WM_CLASS (lower case match).
// 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 = "xterm" },

View File

@@ -73,8 +73,7 @@ void map_request(XEvent *e)
client *c = window_build_client(e->xmaprequest.window);
if (c && c->manage)
{
c->monitor = MONITOR_START == MONITOR_CURRENT ? current_mon: MONITOR_START;
c->monitor = MIN(nmonitors-1, MAX(0, c->monitor));
c->monitor = current_mon;
monitor *m = &monitors[c->monitor];
int i, spot = SPOT_START == SPOT_CURRENT ? current_spot: SPOT_START;
@@ -99,9 +98,7 @@ void map_notify(XEvent *e)
{
client_raise_family(c);
client_update_border(c);
// if no current window, or new window has opened in the current spot, focus it
if (FOCUS_START == FOCUS_STEAL || !(a = window_build_client(current)) || (a && a->spot == c->spot))
client_set_focus(c);
client_set_focus(c);
client_free(a);
ewmh_client_list();
update_bars();

21
xoat.1
View File

@@ -72,11 +72,6 @@ While in fullscreen mode, an window is considered to be in tile 1.
.RS
.RE
.TP
.B Mod4-a
Toggle state above (only placed above fullscreen windows).
.RS
.RE
.TP
.B Mod4-Next (Page Down)
Focus next monitor.
.RS
@@ -97,25 +92,13 @@ Move window to previous monitor.
.RS
.RE
.TP
.B Shift-Mod4-x
.B Mod4-x
Launch dmenu_run
.RS
.RE
.TP
.B F1
Launch urxvt
.RS
.RE
.TP
.B Mod4-s
Snapshot current window positions and stacking order.
.RS
.RE
.TP
.B Mod4-r
Rollback to snapshot.
Windows closed since the snapshot will not be reopened.
Newer windows not in the snapshot will be lowered.
Launch xterm
.RS
.RE
.SH OPTIONS

11
xoat.c
View File

@@ -57,9 +57,7 @@ Display *display;
#define STACK 64
#define MONITORS 3
#define ATOMLIST 10
enum { MONITOR_CURRENT=-1 };
enum { SPOT1=1, SPOT2, SPOT3, SPOT_CURRENT, SPOT_SMART, SPOT1_LEFT, SPOT1_RIGHT };
enum { FOCUS_IGNORE=1, FOCUS_STEAL, };
enum { LEFT=1, RIGHT, UP, DOWN };
typedef struct {
@@ -77,7 +75,7 @@ typedef struct {
XWindowAttributes attr;
Window transient, leader;
Atom type, states[ATOMLIST+1];
short monitor, visible, manage, input, urgent, full, above, ours;
short monitor, visible, manage, input, urgent, full, ours, maxv, maxh;
unsigned long spot;
char *class;
} client;
@@ -110,9 +108,8 @@ void action_find_or_start(void*, int, client*);
void action_move_monitor(void*, int, client*);
void action_focus_monitor(void*, int, client*);
void action_fullscreen(void*, int, client*);
void action_above(void*, int, client*);
void action_snapshot(void*, int, client*);
void action_rollback(void*, int, client*);
void action_maximize_vert(void*, int, client*);
void action_maximize_horz(void*, int, client*);
#include "config.h"
@@ -147,7 +144,7 @@ monitor monitors[MONITORS];
int nmonitors = 1;
short current_spot, current_mon;
Window root, ewmh, current = None;
stack windows, snapshot;
stack windows;
static int (*xerror)(Display *, XErrorEvent *);
void catch_exit(int sig)

13
xoat.md
View File

@@ -53,9 +53,6 @@ Mod4-Escape
Mod4-f
: Toggle state fullscreen. While in fullscreen mode, an window is considered to be in tile 1.
Mod4-a
: Toggle state above (only placed above fullscreen windows).
Mod4-Next (Page Down)
: Focus next monitor.
@@ -68,17 +65,11 @@ Shift-Mod4-Next
Shift-Mod4-Prior
: Move window to previous monitor.
Shift-Mod4-x
Mod4-x
: Launch dmenu_run
F1
: Launch urxvt
Mod4-s
: Snapshot current window positions and stacking order.
Mod4-r
: Rollback to snapshot. Windows closed since the snapshot will not be reopened. Newer windows not in the snapshot will be lowered.
: Launch xterm
# OPTIONS