wmfs: NEW IMPORTANT FEATURE: Add multi-head support #1

This commit is contained in:
Martin Duquesnoy 2008-11-30 03:01:30 +01:00
parent 3f22499bd2
commit 8f5fee389d
16 changed files with 431 additions and 272 deletions

View File

@ -38,6 +38,7 @@ set(wmfs_src
src/init.c
src/layout.c
src/mouse.c
src/screen.c
src/tag.c
src/util.c
src/wmfs.c)
@ -78,7 +79,8 @@ set(LIBRARIES_TO_LINK
${FREETYPE_LIBRARIES}
${X11_LIBRARIES}
confuse
Xft)
Xft
Xinerama)
target_link_libraries(wmfs ${LIBRARIES_TO_LINK})

View File

@ -249,7 +249,8 @@ barwin_refresh_color(BarWindow *bw)
void
barwin_refresh(BarWindow *bw)
{
CHECK(bw);
if(!bw || !bw->dr || !bw->win)
return;
XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0);

View File

@ -107,7 +107,6 @@ uicb_client_prev(uicb_t cmd)
client_focus(c);
client_raise(c);
}
arrange();
return;
}
@ -131,7 +130,6 @@ uicb_client_next(uicb_t cmd)
client_focus(c);
client_raise(c);
}
arrange();
return;
}
@ -150,7 +148,7 @@ client_focus(Client *c)
mouse_grabbuttons(sel, False);
}
selbytag[seltag] = sel = c;
sel = c;
if(c)
{
@ -168,8 +166,8 @@ client_focus(Client *c)
return;
}
/* The following function are the same point :
* find a client membere with a Window {{{
/* The following function have the same point :
* find a client member with a Window {{{
*/
/* Get Client with a window */
@ -227,6 +225,7 @@ client_focus(Client *c)
return c;
}
/* }}} */
/** Get a client name
@ -266,7 +265,7 @@ client_hide(Client *c)
Bool
ishide(Client *c)
{
if(c->tag && c->tag == seltag)
if(c->tag && c->tag == seltag[screen_get_sel()])
return False;
return True;
}
@ -360,11 +359,12 @@ client_manage(Window w, XWindowAttributes *wa)
c = emalloc(1, sizeof(Client));
c->win = w;
c->screen = screen_get_sel();
c->ogeo.x = c->geo.x = wa->x;
c->ogeo.y = c->geo.y = wa->y + sgeo.y;
c->ogeo.y = c->geo.y = wa->y + TBARH + INFOBARH;
c->ogeo.width = c->geo.width = wa->width;
c->ogeo.height = c->geo.height = wa->height;
c->tag = seltag;
c->tag = seltag[c->screen];
at.event_mask = PropertyChangeMask;
frame_create(c);
@ -399,6 +399,8 @@ client_moveresize(Client *c, XRectangle geo, bool r)
{
CHECK(c);
int i;
/* Resize hints {{{ */
if(r)
{
@ -452,6 +454,13 @@ client_moveresize(Client *c, XRectangle geo, bool r)
|| c->geo.height != geo.height)
{
c->geo = geo;
/* Set the client screen */
for(i = 0; i < screen_count(); ++i)
if(geo.x >= screen_get_geo(i).x
&& geo.x < screen_get_geo(i).x + screen_get_geo(i).width)
c->screen = i;
frame_moveresize(c, geo);
XMoveResizeWindow(dpy, c->win, BORDH, BORDH + TBARH, geo.width, geo.height);
XSync(dpy, False);

View File

@ -484,10 +484,18 @@ init_conf(void)
}
}
seltag = 1;
prevtag = 0;
for(i = 0; i < conf.ntag; ++i)
tags[i + 1] = conf.tag[i];
seltag = emalloc(screen_count(), sizeof(int));
//tags = emalloc(screen_count(), sizeof(Tag*));
for(j = 0; j < screen_count(); ++j)
{
//tags[j] = emalloc(conf.ntag, sizeof(Tag));
seltag[j] = 1;
for(i = 0; i < conf.ntag; ++i)
tags[j][i + 1] = conf.tag[i];
}
/* keybind */
conf.nkeybind = cfg_size(cfg_keys, "key");

View File

@ -42,6 +42,8 @@ buttonpress(XButtonEvent *ev)
int i;
char s[6];
screen_get_sel();
/* Titlebar */
if((c = client_gb_titlebar(ev->window)))
for(i = 0; i < conf.titlebar.nmouse; ++i)
@ -63,7 +65,7 @@ buttonpress(XButtonEvent *ev)
/* Root */
if(ev->window == root)
for(i = 0; i < conf.root.nmouse; ++i)
if(conf.root.mouse[i].tag == seltag
if(conf.root.mouse[i].tag == seltag[selscreen]
|| conf.root.mouse[i].tag < 0)
if(ev->button == conf.root.mouse[i].button)
if(conf.root.mouse[i].func)
@ -73,7 +75,7 @@ buttonpress(XButtonEvent *ev)
for(i = 1; i < conf.ntag + 1; ++i)
{
ITOA(s, i);
if(ev->window == infobar->tags[i]->win)
if(ev->window == infobar[screen_get_sel()].tags[i]->win)
{
if(ev->button == Button1)
uicb_tag(s);
@ -87,7 +89,7 @@ buttonpress(XButtonEvent *ev)
}
/* Layout button */
if(ev->window == infobar->layout_button->win)
if(ev->window == infobar[screen_get_sel()].layout_button->win)
{
if(ev->button == Button1
|| ev->button == Button4)
@ -202,18 +204,21 @@ void
expose(XExposeEvent *ev)
{
Client *c;
int i;
int i, sc;
if(ev->count == 0
&& (ev->window == infobar->bar->win))
barwin_refresh(infobar->bar);
for(i = 1; i < conf.ntag + 1; ++i)
if(ev->window == infobar->tags[i]->win)
barwin_refresh(infobar->tags[i]);
for(sc = 0; sc > screen_count(); ++sc)
{
if(ev->window == infobar[sc].bar->win)
barwin_refresh(infobar[sc].bar);
if(ev->window == infobar->layout_button->win)
barwin_refresh(infobar->layout_button);
for(i = 1; i < conf.ntag + 1; ++i)
if(ev->window == infobar[sc].tags[i]->win)
barwin_refresh(infobar[sc].tags[i]);
if(ev->window == infobar[sc].layout_button->win)
barwin_refresh(infobar[sc].layout_button);
}
if((c = client_gb_titlebar(ev->window)))
frame_update(c);
@ -239,25 +244,17 @@ focusin(XFocusChangeEvent *ev)
void
grabkeys(void)
{
uint i, j;
uint i;
KeyCode code;
uint ml[] =
{
LockMask,
numlockmask,
scrolllockmask,
numlockmask|scrolllockmask,
LockMask|scrolllockmask,
LockMask|numlockmask,
LockMask|numlockmask|scrolllockmask
};
XUngrabKey(dpy, AnyKey, AnyModifier, root);
for(i = 0; i < conf.nkeybind; ++i)
{
code = XKeysymToKeycode(dpy, keys[i].keysym);
for(j = 0; j < (sizeof ml / sizeof ml[0]); ++j)
XGrabKey(dpy, code, keys[i].mod|ml[j], root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod|LockMask|numlockmask, root, True, GrabModeAsync, GrabModeAsync);
}
return;
@ -275,8 +272,8 @@ keypress(XKeyPressedEvent *ev)
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < conf.nkeybind; ++i)
if(keysym == keys[i].keysym
&& (keys[i].mod & ~(numlockmask | LockMask | scrolllockmask))
== (ev->state & ~(numlockmask | LockMask | scrolllockmask))
&& (keys[i].mod & ~(numlockmask | LockMask))
== (ev->state & ~(numlockmask | LockMask))
&& keys[i].func)
keys[i].func(keys[i].cmd);
@ -372,6 +369,7 @@ unmapnotify(XUnmapEvent *ev)
void
getevent(XEvent ev)
{
int st;
switch (ev.type)

View File

@ -87,7 +87,7 @@ frame_create(Client *c)
CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, color_enlight(c->colors.frame), &at);
CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, color_enlight(c->colors.frame), &at);
CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, SHADC, &at);
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at);
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at);
/* Reparent window with the frame */
XReparentWindow(dpy, c->win, c->frame, BORDH, BORDH + TBARH);
@ -122,6 +122,8 @@ frame_delete(Client *c)
void
frame_moveresize(Client *c, XRectangle geo)
{
CHECK(c);
c->frame_geo.x = (geo.x) ? geo.x - BORDH : c->frame_geo.x;
c->frame_geo.y = (geo.y) ? geo.y - TBARH : c->frame_geo.y;
c->frame_geo.width = (geo.width) ? FRAMEW(geo.width) : c->frame_geo.width;
@ -157,6 +159,8 @@ frame_moveresize(Client *c, XRectangle geo)
void
frame_update(Client *c)
{
CHECK(c);
if(TBARH)
{
c->titlebar->color = c->colors.frame;
@ -179,6 +183,7 @@ frame_update(Client *c)
if(TBARH && (TBARH + BORDH + 1) > font->height)
{
draw_text(c->titlebar->dr,
(c->frame_geo.width / 2) - (textw(c->title) / 2),
(font->height - (font->descent)) + (((TBARH + BORDH) - font->height) / 2),

View File

@ -37,61 +37,68 @@
void
infobar_init(void)
{
int i, j = 0;
int sc, i, j;
if(!infobar)
infobar = emalloc(1, sizeof(InfoBar));
infobar->geo.height = font->height * 1.5;
infobar->geo.y = (conf.bartop) ? 0 : MAXH - infobar->geo.height;
infobar = emalloc(screen_count(), sizeof(InfoBar));
/* Create infobar barwindow */
infobar->bar = barwin_create(root, 0, infobar->geo.y, MAXW, infobar->geo.height, conf.colors.bar, False);
/* Create tags window */
for(i = 1; i < conf.ntag + 1; ++i)
for(sc = 0; sc < screen_count(); ++sc)
{
infobar->tags[i] = barwin_create(infobar->bar->win, j, 0, textw(tags[i].name) + PAD,
infobar->geo.height, conf.colors.bar, False);
j += textw(tags[i].name) + PAD;
barwin_map_subwin(infobar->tags[i]);
j = 0;
infobar[sc].geo.height = INFOBARH;
infobar[sc].geo.y = (conf.bartop)
? screen_get_geo(sc).y - INFOBARH - TBARH
: screen_get_geo(sc).height - infobar[sc].geo.height;
/* Create infobar barwindow */
infobar[sc].bar = barwin_create(root, screen_get_geo(sc).x - BORDH, infobar[sc].geo.y,
screen_get_geo(sc).width, infobar[sc].geo.height, conf.colors.bar, False);
/* Create tags window */
for(i = 1; i < conf.ntag + 1; ++i)
{
infobar[sc].tags[i] = barwin_create(infobar[sc].bar->win, j, 0, textw(tags[sc][i].name) + PAD,
infobar[sc].geo.height, conf.colors.bar, False);
j += textw(tags[sc][i].name) + PAD;
barwin_map_subwin(infobar[sc].tags[i]);
}
/* Create layout switch & layout type switch barwindow */
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, j + PAD / 2, 0,
textw(tags[sc][seltag[sc]].layout.symbol) + PAD,
infobar[sc].geo.height, conf.colors.layout_bg, False);
/* Map/Refresh all */
barwin_map(infobar[sc].bar);
barwin_map_subwin(infobar[sc].bar);
barwin_map_subwin(infobar[sc].layout_button);
barwin_refresh_color(infobar[sc].bar);
barwin_refresh(infobar[sc].bar);
strcpy(infobar[sc].statustext, "WMFS-" WMFS_VERSION);
infobar_draw(sc);
}
/* Create layout switch & layout type switch barwindow */
infobar->layout_button = barwin_create(infobar->bar->win, j + PAD / 2, 0,
textw(tags[seltag].layout.symbol) + PAD,
infobar->geo.height, conf.colors.layout_bg, False);
/* Map/Refresh all */
barwin_map(infobar->bar);
barwin_map_subwin(infobar->bar);
barwin_map_subwin(infobar->layout_button);
barwin_refresh_color(infobar->bar);
barwin_refresh(infobar->bar);
strcpy(infobar->statustext, "WMFS-" WMFS_VERSION);
infobar_draw();
return;
}
/** Draw the Infobar
*/
void
infobar_draw(void)
infobar_draw(int sc)
{
infobar_draw_taglist();
infobar_draw_layout();
barwin_refresh_color(infobar->bar);
infobar_draw_taglist(sc);
infobar_draw_layout(sc);
barwin_refresh_color(infobar[sc].bar);
/* Draw status text */
draw_text(infobar->bar->dr,
(MAXW - SHADH) - textw(infobar->statustext),
draw_text(infobar[sc].bar->dr,
(MAXW - SHADH) - textw(infobar[sc].statustext),
font->height,
conf.colors.text, 0,
infobar->statustext);
infobar[sc].statustext);
barwin_refresh(infobar->bar);
barwin_refresh(infobar[sc].bar);
return;
}
@ -99,13 +106,13 @@ infobar_draw(void)
/** Draw the layout button in the InfoBar
*/
void
infobar_draw_layout(void)
infobar_draw_layout(int sc)
{
barwin_resize(infobar->layout_button, textw(tags[seltag].layout.symbol) + PAD, infobar->geo.height);
barwin_refresh_color(infobar->layout_button);
draw_text(infobar->layout_button->dr, PAD / 2, font->height,
conf.colors.layout_fg, 0, tags[seltag].layout.symbol);
barwin_refresh(infobar->layout_button);
barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height);
barwin_refresh_color(infobar[sc].layout_button);
draw_text(infobar[sc].layout_button->dr, PAD / 2, font->height,
conf.colors.layout_fg, 0, tags[sc][seltag[sc]].layout.symbol);
barwin_refresh(infobar[sc].layout_button);
return;
}
@ -113,18 +120,17 @@ infobar_draw_layout(void)
/** Draw the taglist in the InfoBar
*/
void
infobar_draw_taglist(void)
infobar_draw_taglist(int sc)
{
int i;
for(i = 1; i < conf.ntag + 1; ++i)
{
infobar->tags[i]->color = ((i == seltag) ? conf.colors.tagselbg : conf.colors.bar);
barwin_refresh_color(infobar->tags[i]);
draw_text(infobar->tags[i]->dr, PAD / 2, font->height,
((i == seltag) ? conf.colors.tagselfg : conf.colors.text),
0, tags[i].name);
barwin_refresh(infobar->tags[i]);
infobar[sc].tags[i]->color = ((i == seltag[sc]) ? conf.colors.tagselbg : conf.colors.bar);
barwin_refresh_color(infobar[sc].tags[i]);
draw_text(infobar[sc].tags[i]->dr, PAD / 2, font->height,
((i == seltag[sc]) ? conf.colors.tagselfg : conf.colors.text), 0, tags[sc][i].name);
barwin_refresh(infobar[sc].tags[i]);
}
return;
@ -135,17 +141,20 @@ infobar_draw_taglist(void)
void
infobar_destroy(void)
{
int i;
int sc, i;
barwin_delete(infobar->bar);
barwin_delete(infobar->layout_button);
barwin_delete_subwin(infobar->layout_button);
for(i = 1; i < conf.ntag + 1; ++i)
for(sc = 0; sc < screen_count(); ++sc)
{
barwin_delete_subwin(infobar->tags[i]);
barwin_delete(infobar->tags[i]);
barwin_delete(infobar[sc].layout_button);
barwin_delete_subwin(infobar[sc].layout_button);
for(i = 1; i < conf.ntag + 1; ++i)
{
barwin_delete_subwin(infobar[sc].tags[i]);
barwin_delete(infobar[sc].tags[i]);
}
barwin_delete_subwin(infobar[sc].bar);
barwin_delete(infobar[sc].bar);
}
barwin_delete_subwin(infobar->bar);
return;
}
@ -157,16 +166,18 @@ infobar_destroy(void)
void
uicb_infobar_togglepos(uicb_t cmd)
{
XRectangle sg = screen_get_geo(screen_get_sel());
conf.bartop = !conf.bartop;
if(conf.bartop)
sgeo.y = infobar->geo.height + TBARH;
sg.y = infobar[selscreen].geo.height + TBARH;
else
sgeo.y = TBARH;
sg.y = TBARH;
infobar->geo.y = (conf.bartop) ? 0 : MAXH - infobar->geo.height;
barwin_move(infobar->bar, 0, infobar->geo.y);
infobar_draw();
infobar[selscreen].geo.y = (conf.bartop) ? sg.y : MAXH - infobar[selscreen].geo.height;
barwin_move(infobar[selscreen].bar, sg.y, infobar[selscreen].geo.y);
infobar_draw(selscreen);
arrange();
return;

View File

@ -46,7 +46,7 @@ init(void)
init_root();
init_atom();
infobar_init();
init_geometry();
screen_init();
grabkeys();
/* Warning about font */
@ -91,14 +91,10 @@ init_key(void)
for(i = 0; i < 8; i++)
for(j = 0; j < modmap->max_keypermod; ++j)
{
if(modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
if(modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Scroll_Lock))
scrolllockmask = (1 << i);
}
XFreeModifiermap(modmap);
return;
@ -113,9 +109,10 @@ init_root(void)
root = RootWindow(dpy, screen);
at.event_mask = KeyMask | ButtonPressMask | ButtonReleaseMask |
SubstructureRedirectMask | SubstructureNotifyMask |
EnterWindowMask | LeaveWindowMask | StructureNotifyMask ;
at.event_mask = KeyMask|ButtonMask|MouseMask
|SubstructureRedirectMask|SubstructureNotifyMask
|EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
at.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &at);
if(conf.root.background_command)
@ -142,21 +139,3 @@ init_atom(void)
return;
}
/** Init screen geometry
*/
void
init_geometry(void)
{
sgeo.x = BORDH;
sgeo.y = infobar->geo.height;
if(conf.bartop)
sgeo.y += TBARH;
else
sgeo.y = TBARH;
sgeo.width = MAXW;
sgeo.height = MAXH - infobar->geo.height - TBARH;
return;
}

View File

@ -39,20 +39,22 @@ arrange(void)
{
Client *c;
screen_get_sel();
for(c = clients; c; c = c->next)
if(!ishide(c))
client_unhide(c);
else
client_hide(c);
if(c->screen == selscreen)
{
if(!ishide(c))
client_unhide(c);
else
client_hide(c);
}
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].layout.func();
if(selbytag[seltag] != NULL)
client_focus(selbytag[seltag]);
else
client_focus(NULL);
client_focus(NULL);
infobar_draw();
infobar_draw(selscreen);
return;
}
@ -67,7 +69,7 @@ freelayout(void)
for(c = clients; c; c = c->next)
{
if(!ishide(c))
if(!ishide(c) && c->screen == screen_get_sel())
{
if(c->tile || c->lmax)
{
@ -92,15 +94,17 @@ layoutswitch(Bool b)
{
int i;
screen_get_sel();
for(i = 0; i < conf.nlayout; ++i)
{
if(tags[seltag].layout.symbol == conf.layout[i].symbol
&& tags[seltag].layout.func == conf.layout[i].func)
if(tags[selscreen][seltag[selscreen]].layout.symbol == conf.layout[i].symbol
&& tags[selscreen][seltag[selscreen]].layout.func == conf.layout[i].func)
{
if(b)
tags[seltag].layout = conf.layout[(i + 1) % conf.nlayout];
tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + 1) % conf.nlayout];
else
tags[seltag].layout = conf.layout[(i + conf.nlayout - 1) % conf.nlayout];
tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + conf.nlayout - 1) % conf.nlayout];
break;
}
}
@ -138,6 +142,7 @@ maxlayout(void)
{
Client *c;
XRectangle geo;
XRectangle sg = screen_get_geo(screen_get_sel());
for(c = nexttiled(clients); c; c = nexttiled(c->next))
{
@ -148,9 +153,10 @@ maxlayout(void)
c->ogeo.width = c->geo.width;
c->ogeo.height = c->geo.height;
geo.x = sgeo.x; geo.y = sgeo.y;
geo.width = sgeo.width - BORDH * 2;
geo.height = sgeo.height - BORDH * 2;
geo.x = sg.x;
geo.y = sg.y;
geo.width = sg.width - BORDH * 2;
geo.height = sg.height - BORDH * 2;
client_moveresize(c, geo, False);
}
@ -166,7 +172,7 @@ maxlayout(void)
Client*
nexttiled(Client *c)
{
for(; c && (c->max || c->free || ishide(c)); c = c->next);
for(; c && (c->max || c->free || c->screen != screen_get_sel() || ishide(c)); c = c->next);
return c;
}
@ -179,14 +185,16 @@ uicb_set_mwfact(uicb_t cmd)
{
double c;
screen_get_sel();
CHECK((sscanf(cmd, "%lf", &c)));
if(tags[seltag].mwfact + c > 0.95
|| tags[seltag].mwfact + c < 0.05)
if(tags[selscreen][seltag[selscreen]].mwfact + c > 0.95
|| tags[selscreen][seltag[selscreen]].mwfact + c < 0.05)
return;
tags[seltag].mwfact += c;
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].mwfact += c;
tags[selscreen][seltag[selscreen]].layout.func();
return;
}
@ -200,14 +208,16 @@ uicb_set_nmaster(uicb_t cmd)
int nc, n = atoi(cmd);
Client *c;
screen_get_sel();
for(nc = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++nc);
if(!nc || tags[seltag].nmaster + n == 0
|| tags[seltag].nmaster + n > nc)
if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0
|| tags[selscreen][seltag[selscreen]].nmaster + n > nc)
return;
tags[seltag].nmaster += n;
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].nmaster += n;
tags[selscreen][seltag[selscreen]].layout.func();
return;
}
@ -218,7 +228,8 @@ void
grid(void)
{
Client *c;
XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0};
XRectangle sg = screen_get_geo(screen_get_sel());
XRectangle cgeo = {sg.x, sg.y, 0, 0};
unsigned int i, n, cols, rows, cpcols = 0;
unsigned int border = BORDH * 2;
@ -242,19 +253,19 @@ grid(void)
c->ogeo.width = c->geo.width; c->ogeo.height = c->geo.height;
++cpcols;
cgeo.width = (sgeo.width / cols) - border;
cgeo.height = (sgeo.height / rows) - border;
cgeo.width = (sg.width / cols) - border;
cgeo.height = (sg.height / rows) - border;
/* Last row's and last client remainder */
if(cpcols == rows || i + 1 == n)
cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border;
cgeo.height = sg.y + sg.height - cgeo.y - border;
/* Last column's client remainder */
if(i >= rows * (cols - 1))
cgeo.width = sgeo.width - cgeo.x - BORDH;
cgeo.width = sg.width - (cgeo.x - (sg.x - border));
/* Resize */
client_moveresize(c, cgeo, tags[seltag].resizehint);
client_moveresize(c, cgeo, tags[selscreen][seltag[selscreen]].resizehint);
/* Set all the other size with current client info */
cgeo.y = c->geo.y + c->geo.height + border + TBARH;
@ -262,7 +273,7 @@ grid(void)
{
cpcols = 0;
cgeo.x = c->geo.x + c->geo.width + border;
cgeo.y = sgeo.y;
cgeo.y = sg.y;
}
}
@ -276,9 +287,10 @@ void
multi_tile(Position type)
{
Client *c;
XRectangle mastergeo = {sgeo.x, sgeo.y, 0, 0};
XRectangle cgeo = {sgeo.x, sgeo.y, 0, 0};
uint i , n, tilesize, mwfact, nmaster = tags[seltag].nmaster;
XRectangle sg = screen_get_geo(screen_get_sel());
XRectangle mastergeo = {sg.x, sg.y, 0, 0};
XRectangle cgeo = {sg.x, sg.y, 0, 0};
uint i , n, tilesize, mwfact, nmaster = tags[selscreen][seltag[selscreen]].nmaster;
uint border = BORDH * 2;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), ++n);
@ -289,32 +301,32 @@ multi_tile(Position type)
/* SET MWFACT */
mwfact = (type == Top || type == Bottom)
? tags[seltag].mwfact * sgeo.height
: tags[seltag].mwfact * sgeo.width;
? tags[selscreen][seltag[selscreen]].mwfact * sg.height
: tags[selscreen][seltag[selscreen]].mwfact * sg.width;
/* MASTER SIZE */
if(type == Top || type == Bottom)
{
if(type == Top)
mastergeo.y = (n <= nmaster) ? sgeo.y : sgeo.y + (sgeo.height - mwfact) - border;
mastergeo.width = (sgeo.width / nmaster) - (border * 2);
mastergeo.height = (n <= nmaster) ? sgeo.height - border : mwfact;
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - border;
mastergeo.width = (sg.width / nmaster) - (border * 2);
mastergeo.height = (n <= nmaster) ? sg.height - border : mwfact;
}
else
{
if(type == Left)
mastergeo.x = (n <= nmaster) ? sgeo.x : sgeo.width - mwfact - BORDH;
mastergeo.width = (n <= nmaster) ? sgeo.width - border : mwfact;
mastergeo.height = (sgeo.height / nmaster) - border;
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - border;
mastergeo.width = (n <= nmaster) ? sg.width - border : mwfact;
mastergeo.height = (sg.height / nmaster) - border;
}
/* TILED SIZE */
if(n > nmaster)
{
if(type == Top || type == Bottom)
tilesize = sgeo.width / (n - nmaster) - border;
tilesize = sg.width / (n - nmaster) - border;
else
tilesize = sgeo.height / (n - nmaster) - border;
tilesize = sg.height / (n - nmaster) - border;
}
@ -350,17 +362,17 @@ multi_tile(Position type)
{
case Top:
case Left:
cgeo.y = sgeo.y;
cgeo.x = sgeo.x;
cgeo.y = sg.y;
cgeo.x = sg.x;
break;
case Bottom:
cgeo.y += mastergeo.height + TBARH + border;
cgeo.x = sgeo.x;
cgeo.x = sg.x;
break;
default:
case Right:
cgeo.x += mastergeo.width + border;
cgeo.y = sgeo.y;
cgeo.y = sg.y;
break;
}
}
@ -368,11 +380,11 @@ multi_tile(Position type)
{
cgeo.width = tilesize;
cgeo.width -= border;
cgeo.height = sgeo.height - mastergeo.height - TBARH - border*2;
cgeo.height = sg.height - mastergeo.height - TBARH - border*2;
}
else
{
cgeo.width = sgeo.width - mastergeo.width - border*2;
cgeo.width = sg.width - mastergeo.width - border*2;
cgeo.height = tilesize;
cgeo.height -= border + TBARH;
}
@ -382,13 +394,13 @@ multi_tile(Position type)
if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
{
if(type == Top || type == Bottom)
cgeo.width = sgeo.width - cgeo.x - BORDH;
cgeo.width = sg.width - (cgeo.x - (sg.x - border));
else
cgeo.height = (sgeo.y + sgeo.height) - cgeo.y - border;
cgeo.height = (sg.y + sg.height) - cgeo.y - border;
}
/* Magic instant */
client_moveresize(c, cgeo, tags[seltag].resizehint);
client_moveresize(c, cgeo, tags[selscreen][seltag[selscreen]].resizehint);
/* Set the position of the next client */
if(type == Top || type == Bottom)
@ -449,6 +461,8 @@ uicb_tile_switch(uicb_t cmd)
{
Client *c;
screen_get_sel();
if(!sel || sel->hint || !sel->tile)
return;
if((c = sel) == nexttiled(clients))
@ -456,7 +470,7 @@ uicb_tile_switch(uicb_t cmd)
client_detach(c);
client_attach(c);
client_focus(c);
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].layout.func();
return;
}
@ -469,12 +483,14 @@ uicb_togglefree(uicb_t cmd)
{
CHECK(sel);
screen_get_sel();
sel->free = !sel->free;
sel->tile = False;
sel->max = False;
sel->lmax = False;
client_moveresize(sel, sel->ogeo, True);
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].layout.func();
return;
}
@ -486,6 +502,7 @@ void
uicb_togglemax(uicb_t cmd)
{
XRectangle geo;
XRectangle sg = screen_get_geo(screen_get_sel());
if(!sel || ishide(sel) || sel->hint)
return;
@ -496,9 +513,10 @@ uicb_togglemax(uicb_t cmd)
sel->ogeo.width = sel->geo.width;
sel->ogeo.height = sel->geo.height;
geo.x = sgeo.x; geo.y = sgeo.y;
geo.width = sgeo.width - BORDH * 2;
geo.height = sgeo.height - BORDH * 2;
geo.x = sg.x;
geo.y = sg.y;
geo.width = sg.width - BORDH * 2;
geo.height = sg.height - BORDH * 2;
client_moveresize(sel, geo, False);
client_raise(sel);

View File

@ -40,7 +40,7 @@ mouse_move(Client *c)
{
int ocx = c->geo.x;
int ocy = c->geo.y;
int mx, my, dint;
int mx = 0, my = 0, dint;
uint duint;
Window dw;
XRectangle geo;
@ -57,7 +57,7 @@ mouse_move(Client *c)
for(;;)
{
XMaskEvent(dpy, MouseMask | ExposureMask | SubstructureRedirectMask, &ev);
XMaskEvent(dpy, ButtonMask | MouseMask | ExposureMask | SubstructureRedirectMask, &ev);
if(ev.type == ButtonRelease)
{
@ -89,9 +89,10 @@ mouse_resize(Client *c)
{
int ocx = c->geo.x;
int ocy = c->geo.y;
int my = sgeo.y, mx = 0;
double fy, fx, mwf;
XRectangle geo;
XRectangle sg = screen_get_geo(screen_get_sel());
int my = sg.y, mx = 0;
XEvent ev;
if(c->max || c->lmax)
@ -107,21 +108,21 @@ mouse_resize(Client *c)
/* Warp pointer for mwfact resize {{{ */
if(c->tile)
{
if(tags[seltag].layout.func == tile)
mx = tags[seltag].mwfact * sgeo.width;
else if(tags[seltag].layout.func == tile_left)
mx = sgeo.width - (tags[seltag].mwfact * sgeo.width);
else if(tags[seltag].layout.func == tile_top)
if(tags[selscreen][seltag[selscreen]].layout.func == tile)
mx = tags[selscreen][seltag[selscreen]].mwfact * sg.width;
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left)
mx = sg.width - (tags[selscreen][seltag[selscreen]].mwfact * sg.width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top)
{
mx = ev.xmotion.x_root;
my = sgeo.height - (tags[seltag].mwfact * sgeo.height);
mx = sg.width / 2;
my = sg.height - (tags[selscreen][seltag[selscreen]].mwfact * sg.height);
}
else if(tags[seltag].layout.func == tile_bottom)
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_bottom)
{
mx = ev.xmotion.x_root;
my = tags[seltag].mwfact * sgeo.height;
mx = sg.width / 2;
my = tags[selscreen][seltag[selscreen]].mwfact * sg.height;
}
XWarpPointer(dpy, None, root, 0, 0, 0, 0, mx, my);
XWarpPointer(dpy, None, root, 0, 0, 0, 0, sg.x + mx, sg.y + my);
}
/* }}} */
@ -148,22 +149,22 @@ mouse_resize(Client *c)
}
else
{
fy = (round(((ev.xmotion.y * 50) / sgeo.height))) / 50;
fx = (round(((ev.xmotion.x * 50) / sgeo.width))) / 50;
fy = (round(((ev.xmotion.y * 50) / sg.height))) / 50;
fx = (round(((ev.xmotion.x * 50) / sg.width))) / 50;
if(tags[seltag].layout.func == tile)
mwf = fx;
else if(tags[seltag].layout.func == tile_left)
mwf = 1 - fx;
else if(tags[seltag].layout.func == tile_top)
if(tags[selscreen][seltag[selscreen]].layout.func == tile)
mwf = sg.x + fx;
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left)
mwf = 1 - (sg.x + fx);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top)
mwf = 1 - fy;
else if(tags[seltag].layout.func == tile_bottom)
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_bottom)
mwf = fy;
else
mwf = tags[seltag].mwfact;
mwf = tags[selscreen][seltag[selscreen]].mwfact;
tags[seltag].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf);
tags[seltag].layout.func();
tags[selscreen][seltag[selscreen]].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf);
tags[selscreen][seltag[selscreen]].layout.func();
}
if(!c->tile)
@ -184,27 +185,22 @@ mouse_resize(Client *c)
void
mouse_grabbuttons(Client *c, Bool focused)
{
int i, j;
uint mod = conf.client.mod;
uint bl[] = {Button1, Button2, Button3, Button4, Button5};
uint ml[] =
{
mod, mod|LockMask,
mod|numlockmask,
mod|scrolllockmask,
mod|numlockmask|scrolllockmask,
mod|LockMask|scrolllockmask,
mod|LockMask|numlockmask,
mod|LockMask|numlockmask|scrolllockmask
};
int i;
uint but[] = {Button1, Button2, Button3, Button4, Button5};
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused)
for(i = 0; i < (sizeof bl / sizeof bl[0]); ++i)
for(j = 0; j < (sizeof ml / sizeof ml[0]); ++j)
XGrabButton(dpy, bl[i], ml[j], c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
for(i = 0; i < (sizeof but / sizeof but[0]); ++i)
{
XGrabButton(dpy, but[i], conf.client.mod, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
}
else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);

118
src/screen.c Normal file
View File

@ -0,0 +1,118 @@
/*
* screen.c
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
/** Count the screens
*\return the number of screen
*/
int
screen_count(void)
{
int n = 0;
if(XineramaIsActive(dpy))
XineramaQueryScreens(dpy, &n);
else
n = ScreenCount(dpy);
return n;
}
/** Get screen geometry by number
*\param s Screen number
*\return XRectangle struct
*/
XRectangle
screen_get_geo(int s)
{
int n = 0;
XineramaScreenInfo *xsi;
XRectangle geo;
if(XineramaIsActive(dpy))
{
xsi = XineramaQueryScreens(dpy, &n);
geo.x = xsi[s].x_org + BORDH;
geo.y = (conf.bartop)
? xsi[s].y_org + INFOBARH + TBARH
: xsi[s].y_org + TBARH;
geo.height = xsi[s].height - INFOBARH - TBARH;
geo.width = xsi[s].width;
efree(xsi);
}
else
{
geo.x = BORDH;
geo.y = (conf.bartop) ? INFOBARH + TBARH : TBARH; ;
geo.height = MAXH - INFOBARH - TBARH;
geo.width = MAXW;
}
return geo;
}
/** Get and set the selected screen
*\return The number of the selected screen
*/
int
screen_get_sel(void)
{
if(XineramaIsActive(dpy))
{
Window w;
uint du;
int x, y, d, i = 0;
XQueryPointer(dpy, root, &w, &w, &x, &y, &d, &d, &du);
for(i = 0; i < screen_count(); ++i)
if(x >= screen_get_geo(i).x
&& x < screen_get_geo(i).x + screen_get_geo(i).width)
selscreen = i;
return selscreen;
}
else
return 0;
}
/** Init screen geometry
*/
void
screen_init(void)
{
screen_get_sel();
return;
}

View File

@ -80,6 +80,8 @@ struct Client
char *title;
/* Tag num */
int tag;
/* Screen */
int screen;
/* Window attribute */
XRectangle geo;
XRectangle frame_geo;

View File

@ -40,24 +40,24 @@ uicb_tag(uicb_t cmd)
{
int tmp = atoi(cmd);
screen_get_sel();
if(!tmp)
tmp = 1;
if(cmd[0] == '+' || cmd[0] == '-')
{
if(tmp + seltag < 1
|| tmp + seltag > conf.ntag)
if(tmp + seltag[selscreen] < 1
|| tmp + seltag[selscreen] > conf.ntag)
return;
prevtag = seltag;
seltag += tmp;
seltag[selscreen] += tmp;
}
else
{
if(tmp == seltag
if(tmp == seltag[selscreen]
|| tmp > conf.ntag)
return;
prevtag = seltag;
seltag = tmp;
seltag[selscreen] = tmp;
}
arrange();
@ -95,15 +95,15 @@ uicb_tagtransfert(uicb_t cmd)
{
int n = atoi(cmd);
if(!sel || n == seltag)
screen_get_sel();
if(!sel || n == seltag[selscreen])
return;
if(!n)
n = 1;
sel->tag = n;
selbytag[n] = sel;
selbytag[seltag] = NULL;
arrange();

View File

@ -69,7 +69,7 @@ getcolor(char *color)
{
XColor xcolor;
if(!XAllocNamedColor(dpy,DefaultColormap(dpy, screen), color, &xcolor, &xcolor))
if(!XAllocNamedColor(dpy, DefaultColormap(dpy, screen), color, &xcolor, &xcolor))
fprintf(stderr,"WMFS Error: cannot allocate color \"%s\"\n", color);
return xcolor.pixel;
}
@ -81,14 +81,13 @@ getcolor(char *color)
ulong
color_enlight(ulong col)
{
ulong ret = col;
if((col + 0x330000) < 0xffffff
&& (col + 0x003300) < 0xffffff
&& (col + 0x000033) < 0xffffff)
ret += 0x333333;
return col + 0x333333;
else
return col;
return ret;
}
/** Get a Window WM State

View File

@ -47,9 +47,15 @@ errorhandler(Display *d, XErrorEvent *event)
}
/* Ignore focus change error for unmapped client */
if((c = client_gb_win(event->resourceid))
&& c->unmapped
&& event->request_code == 42) /* 42: X_SetInputFocus (Xproto.h) */
/* Too lemmy to add Xproto.h so:
* 42 = X_SetInputFocus
* 28 = X_GrabButton
*/
if((c = client_gb_win(event->resourceid)))
if(event->error_code == BadWindow
|| (event->error_code == BadMatch && event->request_code == 42)
|| event->request_code == 28)
return 0;
@ -96,6 +102,8 @@ quit(void)
XFreeCursor(dpy, cursor[CurResize]);
infobar_destroy();
efree(infobar);
efree(seltag);
efree(tags);
efree(keys);
efree(conf.titlebar.mouse);
efree(conf.client.mouse);
@ -112,13 +120,15 @@ void
mainloop(void)
{
fd_set fd;
char sbuf[sizeof infobar->statustext], *p;
int len, r, offset = 0;
int len, r, offset = 0, sc = screen_count() - 1;
char sbuf[sizeof infobar[sc].statustext], *p;
Bool readstdin = True;
XEvent ev;
len = sizeof infobar->statustext - 1;
sbuf[len] = infobar->statustext[len] = '\0';
len = sizeof infobar[sc].statustext - 1;
sbuf[len] = infobar[sc].statustext[len] = '\0';
while(!exiting)
{
@ -137,7 +147,7 @@ mainloop(void)
if(*p == '\n')
{
*p = '\0';
strncpy(infobar->statustext, sbuf, len);
strncpy(infobar[sc].statustext, sbuf, len);
p += r - 1;
for(r = 0; *(p - r) && *(p - r) != '\n'; ++r);
offset = r;
@ -149,10 +159,10 @@ mainloop(void)
}
else
{
strncpy(infobar->statustext, sbuf, strlen(sbuf));
strncpy(infobar[sc].statustext, sbuf, strlen(sbuf));
readstdin = False;
}
infobar_draw();
infobar_draw(screen_get_sel());
}
while(XPending(dpy))
{

View File

@ -50,6 +50,7 @@
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/Xft/Xft.h>
#include <X11/extensions/Xinerama.h>
/* Local headers */
#include "config.h"
@ -67,7 +68,7 @@
#define MAXH DisplayHeight(dpy, screen)
#define MAXW DisplayWidth(dpy, screen)
#define INFOBARH font->height * 1.5
#define SHADH 1
#define SHADC 0x000000 /* 'Cause i don't know how darken a color yet */
#define BORDH conf.client.borderheight
@ -100,9 +101,9 @@ ushort textw(const char *text);
/* infobar.c */
void infobar_init(void);
void infobar_draw(void);
void infobar_draw_layout(void);
void infobar_draw_taglist(void);
void infobar_draw(int sc);
void infobar_draw_layout(int sc);
void infobar_draw_taglist(int sc);
void infobar_destroy(void);
void uicb_infobar_togglepos(uicb_t cmd);
@ -180,6 +181,12 @@ void uicb_tag_next(uicb_t);
void uicb_tag_prev(uicb_t);
void uicb_tagtransfert(uicb_t);
/* screen */
int screen_count(void);
XRectangle screen_get_geo(int s);
int screen_get_sel(void);
void screen_init(void);
/* layout.c */
void arrange(void);
void freelayout(void);
@ -226,8 +233,8 @@ void uicb_reload(uicb_t cmd);
Display *dpy;
GC gc;
Window root;
XRectangle sgeo;
int screen;
int selscreen;
Conf conf;
Key *keys;
Bool exiting;
@ -242,19 +249,15 @@ XftFont *font;
/* InfoBar */
InfoBar *infobar;
Tag tags[MAXTAG];
int taglen[MAXTAG];
int seltag;
int prevtag;
Tag tags[32][MAXTAG];
int *seltag;
/* Important Client */
Client *clients;
Client *sel;
Client *selbytag[MAXTAG];
/* Other */
uint numlockmask;
uint scrolllockmask;
Variable confvar[256];
#endif /* WMFS_H */