/** Max layout function */ void maxlayout(int screen) { Client *c; int i; for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { c->flags &= ~TileFlag; c->flags |= LMaxFlag; client_maximize(c); } ewmh_update_current_tag_prop(); return; }
/** Set the client as master * \param c Client */ void layout_set_client_master(Client *c) { screen_get_sel(); if(!c || (c->flags & HintFlag) || !(c->flags & TileFlag) || (c->flags & FSSFlag)) return; if(c == tiled_client(selscreen, clients)) CHECK((c = tiled_client(selscreen, c->next))); client_detach(c); client_attach(c); tags[selscreen][seltag[selscreen]].layout.func(selscreen); return; }
/** Set the nmaster * \param cmd Nmaster (string) */ void uicb_set_nmaster(uicb_t cmd) { int nc, n = atoi(cmd); Client *c; screen_get_sel(); for(nc = 0, c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next), ++nc); if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0 || tags[selscreen][seltag[selscreen]].nmaster + n > nc) return; tags[selscreen][seltag[selscreen]].nmaster += n; tags[selscreen][seltag[selscreen]].layout.func(selscreen); ewmh_update_current_tag_prop(); return; }
/** Check if row direction is available to resize from it *\param c Client pointer *\param g Client pointer *\param p Position *\return True if available */ static bool _split_check_row_dir(Client *c, Client *g, Position p) { int s = 0, cs; Geo cgeo = c->frame_geo; Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients)); cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width); for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next))) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p)) && SPLIT_CHECK_ROW(cc->frame_geo, g->frame_geo, p)) { s += (LDIR(p) ? cc->frame_geo.height : cc->frame_geo.width); if(s == cs) return True; if(s > cs) return False; } return False; }
/** Arrange clients after a client close *\param ghost Ghost client */ void split_arrange_closed(Client *ghost) { Position p; bool b = False; Geo cgeo; Client *c, *cc; int screen = ghost->screen; int tag = (ghost->tag ? ghost->tag : seltag[screen]); /* Use ghost client properties to fix holes in tile * .--. ~ ~ * /xx \ ~ ~ * ~~\O _ (____ ~ * __.| .--'-==~ ~ * '---\ '. ~ , ~ * '. '-.___.-'/ ~ * '-.__ _.' ~ * ````` ~ */ /* Search for single parent for easy resize * Example case: * ___________ ___________ * | | B | -> -> | | | * | A |_____| -> Close -> | A | B | * | | C | -> C -> | |v v v| * |_____|_____| -> -> |_____|_____| */ for(p = Right; p < Center; ++p) if((c = client_get_next_with_direction(ghost, p))) if(CFACTOR_CHECK2(ghost->frame_geo, c->frame_geo, p)) { _split_arrange_size(ghost->wrgeo, &c->wrgeo, p); cfactor_clean(c); client_moveresize(c, (c->pgeo = c->wrgeo), (tags[screen][tag].flags & ResizeHintFlag)); return; } /* Check row parents for full resize * Example case: * ___________ ___________ * | | B | -> -> | << B | * | A |_____| -> Close -> |___________| * | | C | -> A -> | << C | * |_____|_____| -> -> |___________| */ for(p = Right; p < Center && !b; ++p) if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p)) { for(cgeo = c->frame_geo, cc = tiled_client(c->screen, SLIST_FIRST(&clients)); cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next))) if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p)) && SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p)) { _split_arrange_size(ghost->wrgeo, &cc->wrgeo, p); cfactor_clean(cc); client_moveresize(cc, (cc->pgeo = cc->wrgeo), (tags[screen][tag].flags & ResizeHintFlag)); b = True; } } return; }
/** Mirror layout function * \param screen Screen to execute this function * \param horizont To specify the mirror mode (vertical/horizontal) */ static void mirror(int screen, Bool horizontal) { Client *c; XRectangle sg = sgeo[screen]; XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height}; XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height}; XRectangle nextg[2]; uint i, n, tilesize = 0, mwfact; uint nmaster = tags[screen][seltag[screen]].nmaster; int pa, imp; Bool isp = 0; memset(nextg, 0, sizeof(nextg)); for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); /* Fix nmaster */ nmaster = (n < nmaster) ? n : nmaster; imp = ((n - (nmaster - 1)) / 2); pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1); /* Set mwfact */ if(tags[screen][seltag[screen]].mwfact < 0.55) tags[screen][seltag[screen]].mwfact = 0.55; mwfact = tags[screen][seltag[screen]].mwfact * ((horizontal) ? sg.height : sg.width); /* Master size */ if(horizontal) { mastergeo.width = (sg.width / nmaster) - (BORDH * 2); mastergeo.height -= BORDH; } else { mastergeo.width -= BORDH * 2; mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2)); } if(n == nmaster + 1) { if(horizontal) { mastergeo.height = mwfact - ((BORDH * 2) + TBARH); tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH); } else { mastergeo.width = mwfact - (BORDH * 3); tilesize = (sg.width - mastergeo.width) - (BORDH * 4); } } if(n > nmaster + 1) { if(horizontal) { mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH; mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2)); tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2)); } else { mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH; mastergeo.width = ((2 * mwfact - sg.width) - (BORDH * 4)); tilesize = (mwfact - mastergeo.width) - (BORDH * 5); } } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; if(i < nmaster) { cgeo = mastergeo; /* Master remainder */ if(i + 1 == nmaster) { if(horizontal) cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); else cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); } } else { if(horizontal) cgeo.height = tilesize; else cgeo.width = tilesize; if((i + nmaster) % 2) { isp = 1; if(horizontal) { cgeo.y = sg.y; cgeo.width = (sg.width / pa) - (BORDH * 2); } else { cgeo.x = sg.x; cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2)); } } else { isp = 0; if(horizontal) { cgeo.y = (sg.y + mwfact) - BORDH; cgeo.width = (sg.width / imp) - (BORDH * 2); } else { cgeo.x = (sg.x + mwfact) - BORDH; cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2)); } } /* Remainder */ if(i + 1 == n || i + 1 == n - 1) { if(horizontal) cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); else cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); } } client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); if(i >= nmaster) nextg[!isp] = c->geo; /* Next y/x position */ if(i >= nmaster - 1) { if(horizontal) { if(i == nmaster || i == nmaster - 1) cgeo.x = sg.x; else cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2; } else { if(i == nmaster || i == nmaster - 1) cgeo.y = sg.y; else cgeo.y = nextg[isp].y + nextg[isp].height + BORDH + TBARH; } } else if (i <= nmaster - 1) { if(horizontal) mastergeo.x = c->geo.x + c->geo.width + BORDH * 2; else mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH; } } ewmh_update_current_tag_prop(); return; }
/** Multi tile function * \param type Postion type { Top, Bottom, Left, Right } */ static void multi_tile(int screen, Position type) { Client *c; XRectangle sg = sgeo[screen]; XRectangle mastergeo = {sg.x, sg.y, 0, 0}; XRectangle cgeo = {sg.x, sg.y, 0, 0}; uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster; for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); /* FIX NMASTER */ nmaster = (n < nmaster) ? n : nmaster; /* SET MWFACT */ mwfact = (type == Top || type == Bottom) ? tags[screen][seltag[screen]].mwfact * sg.height : tags[screen][seltag[screen]].mwfact * sg.width; /* MASTER SIZE */ if(type == Top || type == Bottom) { if(type == Top) mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH; mastergeo.width = (sg.width / nmaster) - (BORDH * 4); mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact; } else { if(type == Left) mastergeo.x = (n <= nmaster) ? (uint)sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2); mastergeo.width = (n <= nmaster) ? (uint)(sg.width - (BORDH * 2)) : mwfact; mastergeo.height = (sg.height / nmaster) - BORDH; } /* TILED SIZE */ if(n > nmaster) { if(type == Top || type == Bottom) tilesize = sg.width / (n - nmaster) - (BORDH * 4); else tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH); } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; /* MASTER */ if(i < nmaster) { cgeo.width = mastergeo.width; cgeo.height = mastergeo.height; if(type == Top || type == Bottom) cgeo.y = mastergeo.y; else { cgeo.x = mastergeo.x; cgeo.height -= (TBARH + BORDH); } } /* TILED */ else { if(i == nmaster) { switch(type) { case Top: case Left: cgeo.y = sg.y; cgeo.x = sg.x; break; case Bottom: cgeo.y += mastergeo.height + TBARH + BORDH; cgeo.x = sg.x; break; default: case Right: cgeo.x += mastergeo.width + (BORDH * 2); cgeo.y = sg.y; break; } } if(type == Top || type == Bottom) { cgeo.width = tilesize; cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2); } else { cgeo.width = sg.width - mastergeo.width - (BORDH * 4); cgeo.height = tilesize; } } /* REMAINDER */ if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster)) { if(type == Top || type == Bottom) cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2))); else cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH; } /* Magic instant */ client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); /* Set the position of the next client */ if(type == Top || type == Bottom) cgeo.x = c->geo.x + c->geo.width + (BORDH * 2); else cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH; } ewmh_update_current_tag_prop(); return; }
/** Grid layout function */ static void grid(int screen, Bool horizontal) { Client *c; XRectangle sg = sgeo[screen]; XRectangle cgeo = {sg.x, sg.y, 0, 0}; unsigned int i, n, temp, cols, rows, cpcols = 0; for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); CHECK(n); for(rows = 0; rows <= n / 2; ++rows) if(rows * rows >= n) break; cols = (rows && ((rows - 1) * rows) >= n) ? rows - 1 : rows; if(!horizontal) { temp = cols; cols = rows; rows = temp; } for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) { /* Set client property */ c->flags &= ~(MaxFlag | LMaxFlag); c->flags |= TileFlag; ++cpcols; cgeo.width = (sg.width / cols) - (BORDH * 2); cgeo.height = (sg.height / rows) - BORDH; /* Last row's and last client remainder */ if(cpcols == rows || i + 1 == n) cgeo.height = sg.y + sg.height - cgeo.y - BORDH; /* Last column's client remainder */ if(i >= rows * (cols - 1)) cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2))); /* Resize */ client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint); /* Set all the other size with current client info */ cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH; if(cpcols + 1 > rows) { cpcols = 0; cgeo.x = c->geo.x + c->geo.width + (BORDH * 2); cgeo.y = sg.y; } } ewmh_update_current_tag_prop(); return; }