Alopex

Check-in [98c7a5cf7f]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:testing multi-monitor
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | master
Files: files | file ages | folders
SHA3-256: 98c7a5cf7f471e4e61efd23bc18ce13f64ffdca6ad87cbb5fe17bf4849a346de
User & Date: jesse@mccluresk9.com 2014-03-07 18:49:39
Context
2014-03-07
21:12
fixed bar bg for multimonitor check-in: 92daba635d user: jesse@mccluresk9.com tags: trunk, master
18:49
testing multi-monitor check-in: 98c7a5cf7f user: jesse@mccluresk9.com tags: trunk, master
2014-02-19
21:34
ridiculous work around for SDL games check-in: 726de2392a user: jesse@mccluresk9.com tags: trunk, master
Changes

Changes to Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13

PROG     =  alopex
VER      =  4.0a
CC       ?= gcc
CFLAGS   += `pkg-config --cflags x11 cairo freetype2 xinerama`
LDLIBS   += `pkg-config --libs x11 cairo freetype2 xinerama`
PREFIX   ?= /usr
MODULES  =  actions alopex atoms config draw tile xlib
HEADERS  =  alopex.h actions.h
MANPAGES =  alopex.1
VPATH    =  src:doc

${PROG}: ${MODULES:%=%.o}




|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

PROG     =  alopex
VER      =  4.0a
CC       ?= gcc
CFLAGS   += $(shell pkg-config --cflags x11 cairo freetype2 xinerama)
LDLIBS   += $(shell pkg-config --libs x11 cairo freetype2 xinerama)
PREFIX   ?= /usr
MODULES  =  actions alopex atoms config draw tile xlib
HEADERS  =  alopex.h actions.h
MANPAGES =  alopex.1
VPATH    =  src:doc

${PROG}: ${MODULES:%=%.o}

Changes to TODO.

1
2
3

add None option for keybinding modifiers.
add option for fixed-color tag icons

|
<
1
2


Multimonitor wallpaper

Changes to src/actions.c.

170
171
172
173
174
175
176
177
178
179
180
181
182
183

















184
185
186
187

188
189
190

191
192
193
194
195
196
197

int monitor(const char *s) {
	int n1, n2, n3, n4;
	if (*s == 'm') { /* margins */
		if (s[1] == 'r')
			m->margin = conf.margin;
		else {
			sscanf(s,"%d,%d,%d,%d", &n1, &n2, &n3, &n4);
			m->margin.top = n1;
			m->margin.bottom = n2;
			m->margin.left = n3;
			m->margin.right = n4;
		}
	}

















	else { /* focus another monitor */
		/* TODO needs testing */
		int n;
		if (!(n=atoi(s))) return 1;

		Monitor *M;
		for (M = mons; n > 1 && M; n--, M = M->next);
		if (M) m = M;

	}
	return 0;
}

int move(Client *t, const char *s) {
	Client *c, *a, *b;
	if (!(c=winmarks[1])) return 1;







|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
>

<
<
>







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201



202
203


204
205
206
207
208
209
210
211

int monitor(const char *s) {
	int n1, n2, n3, n4;
	if (*s == 'm') { /* margins */
		if (s[1] == 'r')
			m->margin = conf.margin;
		else {
			sscanf(s,"m%d,%d,%d,%d", &n1, &n2, &n3, &n4);
			m->margin.top = n1;
			m->margin.bottom = n2;
			m->margin.left = n3;
			m->margin.right = n4;
		}
	}
	else if (*s == 's') { /* swap tags */
		sscanf(s,"s%d,%d", &n1, &n2);
		Monitor *M, *a = NULL, *b = NULL;
		for (M = mons, n3 = 1; M; n3++, M = M->next) {
			if (n1 == n3) a = M;
			else if (n2 == n3) b = M;
		}
		if (a && b) {
			n4 = a->tags;
			a->tags = b->tags;
			b->tags = n4;
		}
	}
	else if (*s == 'c') { /* cycle through monitors */
		m = m->next;
		if (!m) m = mons;
	}
	else { /* focus another monitor */



		n1 = atoi(s);
		Monitor *M;


		for (M = mons; n1 > 0 && M; n1--, M = M->next) m = M;
	}
	return 0;
}

int move(Client *t, const char *s) {
	Client *c, *a, *b;
	if (!(c=winmarks[1])) return 1;

Changes to src/draw.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

int draw_bar_sub(Monitor *M, Container *C, Bar *S, int x, Bool bg) {
	if (C->bar->opts & BAR_HIDE) return 0;
	if (S->w < 1) return 0;
	cairo_rectangle(C->bar->ctx, x, 0, S->w, C->bar->h);
	cairo_clip(C->bar->ctx);
	if (bg) { /* draw background as needed */
		int y = (C->bar->opts & BAR_BOTTOM ? C->y+C->h : C->y-C->bar->h);
		if (C->top)
			cairo_set_source_surface(C->bar->ctx, M->bg, -C->x, -y);
		else
			cairo_set_source_surface(C->bar->ctx, M->bg, -C->x, 0);
		cairo_paint(C->bar->ctx);
	}
	round_rect(C->bar, x, 0, S->w, S->h, StatusOffset,
			StatusBackground, StatusBorder, StatusText);
	cairo_set_source_surface(C->bar->ctx, S->buf, x, 0);
	cairo_paint(C->bar->ctx);
	cairo_reset_clip(C->bar->ctx);







|

|

|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

int draw_bar_sub(Monitor *M, Container *C, Bar *S, int x, Bool bg) {
	if (C->bar->opts & BAR_HIDE) return 0;
	if (S->w < 1) return 0;
	cairo_rectangle(C->bar->ctx, x, 0, S->w, C->bar->h);
	cairo_clip(C->bar->ctx);
	if (bg) { /* draw background as needed */
		int y = M->y - (C->bar->opts & BAR_BOTTOM ? C->y+C->h : C->y-C->bar->h);
		if (C->top)
			cairo_set_source_surface(C->bar->ctx, M->bg, M->x - C->x, y);
		else
			cairo_set_source_surface(C->bar->ctx, M->bg, M->x - C->x, 0);
		cairo_paint(C->bar->ctx);
	}
	round_rect(C->bar, x, 0, S->w, S->h, StatusOffset,
			StatusBackground, StatusBorder, StatusText);
	cairo_set_source_surface(C->bar->ctx, S->buf, x, 0);
	cairo_paint(C->bar->ctx);
	cairo_reset_clip(C->bar->ctx);

Changes to src/tile.c.

14
15
16
17
18
19
20

21


22
23
24
25
26
27
28
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101



102
103
104
105
106
107
108
		winmarks[0] = winmarks[1];
		winmarks[1] = NULL;
	}
	Monitor *M;
	Container *C;
	Client *c, *pc, *t;
	int num, cn, numC, ord;

	for (M = mons; M; M = M->next) {


		/* calculate how many containers will be used: */
		if (M->mode == MONOCLE) {
			M->focus = M->container;
			numC = 0;
			M->occ = 0;
			for (c = clients; c; c = c->next) {
				M->occ |= (c->tags & 0xFFFF);
................................................................................
			C->w = M->w;
			XMoveResizeWindow(dpy, C->win, C->x, C->y, C->w, C->bar->h);
			cairo_set_source_surface(C->bar->ctx, M->bg, -C->x, -C->y);
			cairo_paint(C->bar->ctx);
		}
		/* sort floating windows */
		// TODO: needs testing
		for (c = clients; c; c = c->next)
			if (!(M->tags & c->tags)) purgatory(c->win);
		for (c = clients; c; c = c->next) {
			if (!(M->tags & c->tags)) continue;
			else if (c->flags & WIN_FULL_TEST) {
				if ( !winmarks[1] || !(winmarks[1]->flags & WIN_FULL_TEST) )
					winmarks[1] = c;
				XMoveResizeWindow(dpy, c->win, M->x, M->y, M->w, M->h);
			}
			else if (c->flags & WIN_FLOAT)
				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
		}
		if (!M->focus) M->focus = M->container;
	}



	draw_bars(False);
	set_focus();
	return 0;
}


int resize_container(Monitor *M, Container *C, int numC, int ord) {







>

>
>







 







<
<












>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
84
85
86
87
88
89
90


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		winmarks[0] = winmarks[1];
		winmarks[1] = NULL;
	}
	Monitor *M;
	Container *C;
	Client *c, *pc, *t;
	int num, cn, numC, ord;
	int mview = 0;
	for (M = mons; M; M = M->next) {
		M->tags &= ~mview;
		mview |= M->tags;
		/* calculate how many containers will be used: */
		if (M->mode == MONOCLE) {
			M->focus = M->container;
			numC = 0;
			M->occ = 0;
			for (c = clients; c; c = c->next) {
				M->occ |= (c->tags & 0xFFFF);
................................................................................
			C->w = M->w;
			XMoveResizeWindow(dpy, C->win, C->x, C->y, C->w, C->bar->h);
			cairo_set_source_surface(C->bar->ctx, M->bg, -C->x, -C->y);
			cairo_paint(C->bar->ctx);
		}
		/* sort floating windows */
		// TODO: needs testing


		for (c = clients; c; c = c->next) {
			if (!(M->tags & c->tags)) continue;
			else if (c->flags & WIN_FULL_TEST) {
				if ( !winmarks[1] || !(winmarks[1]->flags & WIN_FULL_TEST) )
					winmarks[1] = c;
				XMoveResizeWindow(dpy, c->win, M->x, M->y, M->w, M->h);
			}
			else if (c->flags & WIN_FLOAT)
				XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
		}
		if (!M->focus) M->focus = M->container;
	}
	for (c = clients; c; c = c->next) {
		if (!(c->tags & mview)) purgatory(c->win);
	}
	draw_bars(False);
	set_focus();
	return 0;
}


int resize_container(Monitor *M, Container *C, int numC, int ord) {

Changes to src/xlib.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
485
486
487
488
489
490
491



492





493
494
495
496
497
498
499
...
543
544
545
546
547
548
549
550








551
552
553
554
555
556
557

#include "alopex.h"
#include "actions.h"

#define SELECT_EVENTS	\
	ExposureMask | FocusChangeMask | ButtonReleaseMask | \
	SubstructureNotifyMask | SubstructureRedirectMask | \
	StructureNotifyMask | PropertyChangeMask

#define GRABMODE	GrabModeAsync, GrabModeAsync
#define GRABMODE2	ButtonPressMask, GrabModeAsync, GrabModeAsync, \
	None, None

extern int config_init(const char *);
extern int config_free();
................................................................................
		ctx = cairo_create(M->bg);
		cairo_scale(ctx, M->w / (float) imgw, M->h / (float) imgh);
		cairo_set_source_surface(ctx, src, 0, 0);
		cairo_paint(ctx);
		cairo_destroy(ctx);
		/* paint root pixmap */
		cairo_save(rctx);
		cairo_scale(rctx, M->w / (float) imgw, M->h / (float) imgh);
		cairo_translate(rctx, M->x, M->y);

		cairo_set_source_surface(rctx, src, 0, 0);
		cairo_paint(rctx);
		cairo_restore(rctx);
		Container *C;
		cairo_surface_t *t;
		for (j = 0; j < ncounts; j++) {
			C = &M->container[j];
			if (j < ncounts - 1) C->next = &M->container[j+1];
			C->n = counts[j];
			C->nn = C->n;
			C->bar = calloc(1, sizeof(Bar));
			C->bar->opts = conf.bar_opts;
			C->bar->w = mons[i].w;
			C->bar->h = conf.bar_opts & BAR_HEIGHT;
			C->bar->buf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
					C->bar->w, C->bar->h);
			C->bar->ctx = cairo_create(C->bar->buf);
			cairo_set_font_face(C->bar->ctx, conf.font);
			cairo_set_font_size(C->bar->ctx, conf.font_size);
			C->win = XCreateSimpleWindow(dpy,root,0,0,M->w,C->bar->h,0,0,0);
................................................................................
		wc.sibling = e->above; wc.stack_mode = e->detail;
		XConfigureWindow(dpy, e->window, e->value_mask, &wc);
		XFlush(dpy);
	}
}

void enternotify(XEvent *ev) {



	// TODO check monitors





	if (!conf.focus_follow) return;
	Client *c = wintoclient(ev->xcrossing.window);
	if (!c) return;
	Container *C;
	for (C = m->container; C; C = C->next)
		if (C->top && C->top == c) m->focus = C;
	tile();
................................................................................
	c = calloc(1, sizeof(Client));
	c->win = e->window;
// check for fullscreen
	get_hints(c);
	get_icon(c);
	get_name(c);
	apply_rules(c);
	if (!c->tags && !(c->tags=m->tags)) c->tags = m->tags = 1;








	if (XGetTransientForHint(dpy, c->win, &c->parent))
		c->flags |= WIN_TRANS;
	else
		c->parent = e->parent;
	c->x = wa.x; c->y = wa.y; c->w = wa.width; c->h = wa.height;
	if (c->w == m->w && c->h == m->h) c->flags |= WIN_FULL;
	XSelectInput(dpy, c->win, PropertyChangeMask | EnterWindowMask);







|







 







<

>












|







 







>
>
>
|
>
>
>
>
>







 







|
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

#include "alopex.h"
#include "actions.h"

#define SELECT_EVENTS	\
	ExposureMask | FocusChangeMask | ButtonReleaseMask | \
	SubstructureNotifyMask | SubstructureRedirectMask | \
	StructureNotifyMask | PropertyChangeMask | EnterWindowMask

#define GRABMODE	GrabModeAsync, GrabModeAsync
#define GRABMODE2	ButtonPressMask, GrabModeAsync, GrabModeAsync, \
	None, None

extern int config_init(const char *);
extern int config_free();
................................................................................
		ctx = cairo_create(M->bg);
		cairo_scale(ctx, M->w / (float) imgw, M->h / (float) imgh);
		cairo_set_source_surface(ctx, src, 0, 0);
		cairo_paint(ctx);
		cairo_destroy(ctx);
		/* paint root pixmap */
		cairo_save(rctx);

		cairo_translate(rctx, M->x, M->y);
		cairo_scale(rctx, M->w / (float) imgw, M->h / (float) imgh);
		cairo_set_source_surface(rctx, src, 0, 0);
		cairo_paint(rctx);
		cairo_restore(rctx);
		Container *C;
		cairo_surface_t *t;
		for (j = 0; j < ncounts; j++) {
			C = &M->container[j];
			if (j < ncounts - 1) C->next = &M->container[j+1];
			C->n = counts[j];
			C->nn = C->n;
			C->bar = calloc(1, sizeof(Bar));
			C->bar->opts = conf.bar_opts;
			C->bar->w = M->w;
			C->bar->h = conf.bar_opts & BAR_HEIGHT;
			C->bar->buf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
					C->bar->w, C->bar->h);
			C->bar->ctx = cairo_create(C->bar->buf);
			cairo_set_font_face(C->bar->ctx, conf.font);
			cairo_set_font_size(C->bar->ctx, conf.font_size);
			C->win = XCreateSimpleWindow(dpy,root,0,0,M->w,C->bar->h,0,0,0);
................................................................................
		wc.sibling = e->above; wc.stack_mode = e->detail;
		XConfigureWindow(dpy, e->window, e->value_mask, &wc);
		XFlush(dpy);
	}
}

void enternotify(XEvent *ev) {
	if (mons->next) {
		int x = ev->xcrossing.x_root;
		int y = ev->xcrossing.y_root;
		Monitor *M;
		for (M = mons; M; M = M->next) {
			if (M->x < x && M->x + M->w > x && M->y < y && M->y + M->h > y)
				m = M;
		}
	}
	if (!conf.focus_follow) return;
	Client *c = wintoclient(ev->xcrossing.window);
	if (!c) return;
	Container *C;
	for (C = m->container; C; C = C->next)
		if (C->top && C->top == c) m->focus = C;
	tile();
................................................................................
	c = calloc(1, sizeof(Client));
	c->win = e->window;
// check for fullscreen
	get_hints(c);
	get_icon(c);
	get_name(c);
	apply_rules(c);
	if (!c->tags && !(c->tags=m->tags)) {
		Monitor *M;
		int i, tags = 0;
		for (M = mons; M; M = M->next) tags |= M->tags;
fprintf(stderr,"ADD TAG tags=%X\n",tags);
		for (i = 0; ((1<<i) & tags) && i < 9; i++)
fprintf(stderr," -- %d\n",i);
		c->tags = m->tags = (1<<i);
	}
	if (XGetTransientForHint(dpy, c->win, &c->parent))
		c->flags |= WIN_TRANS;
	else
		c->parent = e->parent;
	c->x = wa.x; c->y = wa.y; c->w = wa.width; c->h = wa.height;
	if (c->w == m->w && c->h == m->h) c->flags |= WIN_FULL;
	XSelectInput(dpy, c->win, PropertyChangeMask | EnterWindowMask);