From b36af57fb090e3adaebbfd0156044f3aef81506c Mon Sep 17 00:00:00 2001 From: Martin Duquesnoy Date: Thu, 2 Jun 2011 23:54:03 +0200 Subject: [PATCH] Split: Begin to set split mode --- src/client.c | 33 ++++++++++++--------- src/config.c | 1 + src/ewmh.c | 2 +- src/layout.c | 35 ++++++++++++++++------ src/mouse.c | 2 +- src/split.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/structs.h | 8 +++++ src/tag.c | 24 +++++++++++++-- src/wmfs.h | 4 +++ 9 files changed, 162 insertions(+), 28 deletions(-) diff --git a/src/client.c b/src/client.c index 45a57a5..5548832 100644 --- a/src/client.c +++ b/src/client.c @@ -39,15 +39,15 @@ client_focus(c); \ } while(/* CONSTCOND */ 0) \ -#define CLIENT_ACTION_LIST(A, L) \ -void \ -uicb_client_##A##_##L(uicb_t cmd) \ -{ \ - Client *c; \ - (void)cmd; \ - \ - if((c = client_get_##L())) \ - client_##A(c); \ +#define CLIENT_ACTION_LIST(A, L) \ +void \ +uicb_client_##A##_##L(uicb_t cmd) \ +{ \ + Client *c; \ + (void)cmd; \ + \ + if((c = client_get_##L())) \ + client_##A(c); \ } #define CLIENT_ACTION_DIR(A, D) \ @@ -235,7 +235,7 @@ client_above(Client *c) client_moveresize(c, geo, (tags[c->screen][c->tag].flags & ResizeHintFlag)); client_raise(c); - tags[c->screen][c->tag].layout.func(c->screen); + layout_func(c->screen, c->tag); return; } @@ -648,7 +648,7 @@ client_set_rules(Client *c) } if(!conf.rule[i].ignoretags) - tags[c->screen][c->tag].layout.func(c->screen); + layout_func(c->screen, c->tag); if(conf.rule[i].follow_client) seltag[c->screen] = c->tag; @@ -786,6 +786,8 @@ client_manage(Window w, XWindowAttributes *wa, Bool ar) ewmh_get_client_list(); ewmh_manage_window_type(c); + split_set_current(c, NULL); + if(ar) arrange(c->screen, True); @@ -1182,13 +1184,16 @@ client_unmanage(Client *c) ewmh_get_client_list(); if(c->flags & TileFlag) + { tags[c->screen][c->tag].flags |= CleanFactFlag; + split_set_current(NULL, c); + } if(c->tag == MAXTAG + 1) { for(i = 0; i < conf.ntag[c->screen]; i++) tags[c->screen][i].flags |= RequestUpdateFlag; - tags[c->screen][seltag[c->screen]].layout.func(c->screen); + layout_func(c->screen, seltag[c->screen]); } else { @@ -1201,12 +1206,12 @@ client_unmanage(Client *c) } else if(tags[i][seltag[i]].tagad & TagFlag(c->tag)) { - tags[i][seltag[i]].layout.func(c->screen); + layout_func(i, seltag[i]); break; } if(b) - tags[c->screen][c->tag].layout.func(c->screen); + layout_func(c->screen, c->tag); else { tags[c->screen][c->tag].flags |= RequestUpdateFlag; diff --git a/src/config.c b/src/config.c index 419fd95..5f22aeb 100644 --- a/src/config.c +++ b/src/config.c @@ -108,6 +108,7 @@ const func_name_list_t func_list[] = {"check_clist", uicb_checkclist }, {"toggle_tagautohide", uicb_toggle_tagautohide }, {"toggle_tag_expose", uicb_tag_toggle_expose}, + {"split_toggle", uicb_split_toggle }, /*{"split_client_vertical", uicb_split_client_vertical }, {"split_client_horizontal", uicb_split_client_horizontal }, */ {NULL, NULL} diff --git a/src/ewmh.c b/src/ewmh.c index e9f6787..a9d4945 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -423,7 +423,7 @@ ewmh_manage_window_type(Client *c) c->flags &= ~(TileFlag | MaxFlag | LMaxFlag); client_moveresize(c, c->ogeo, True); client_focus(c); - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); } } XFree(data); diff --git a/src/layout.c b/src/layout.c index 19a62bf..aeadb9f 100644 --- a/src/layout.c +++ b/src/layout.c @@ -54,7 +54,7 @@ arrange(int screen, Bool update_layout) if(tags[screen][seltag[screen]].layout.func) { if(update_layout) - tags[screen][seltag[screen]].layout.func(screen); + layout_func(screen, seltag[screen]); infobar_draw(screen); } @@ -62,6 +62,19 @@ arrange(int screen, Bool update_layout) return; } +/** Apply layout function +*/ +void +layout_func(int screen, int tag) +{ + if(tags[screen][tag].flags & SplitFlag) + split_apply_current(screen, tag); + else + tags[screen][tag].layout.func(screen); + + return; +} + /** The free layout function */ void @@ -117,7 +130,7 @@ layoutswitch(Bool b) ewmh_update_current_tag_prop(); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); infobar_draw(selscreen); return; @@ -205,7 +218,7 @@ uicb_set_mwfact(uicb_t cmd) return; tags[selscreen][seltag[selscreen]].mwfact += c; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); ewmh_update_current_tag_prop(); @@ -231,7 +244,7 @@ uicb_set_nmaster(uicb_t cmd) tags[selscreen][seltag[selscreen]].nmaster += n; tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); ewmh_update_current_tag_prop(); @@ -720,8 +733,8 @@ uicb_togglefree(uicb_t cmd) if(sel->flags & FreeFlag) { + split_set_current(NULL, sel); sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag); - client_moveresize(sel, sel->free_geo, True); client_raise(sel); } @@ -729,12 +742,13 @@ uicb_togglefree(uicb_t cmd) { sel->free_geo = sel->geo; sel->ogeo = sel->geo; + split_set_current(sel, NULL); } client_update_attributes(sel); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); return; } @@ -759,6 +773,7 @@ uicb_togglemax(uicb_t cmd) sel->free_geo = sel->geo; sel->flags &= ~(TileFlag | FreeFlag); + split_set_current(NULL, sel); client_maximize(sel); XRaiseWindow(dpy, sel->frame); } @@ -769,7 +784,9 @@ uicb_togglemax(uicb_t cmd) client_moveresize(sel, sel->geo, True); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + + split_set_current(sel, NULL); + layout_func(selscreen, seltag[selscreen]); } return; @@ -819,7 +836,7 @@ uicb_toggle_abovefc(uicb_t cmd) } tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); } client_focus(sel); @@ -871,7 +888,7 @@ layout_set_client_master(Client *c) client_attach(c); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag; - tags[selscreen][seltag[selscreen]].layout.func(selscreen); + layout_func(selscreen, seltag[selscreen]); return; } diff --git a/src/mouse.c b/src/mouse.c index 73679ed..09d0f2c 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -52,7 +52,7 @@ mouse_dragborder(XRectangle geo, GC g) static void mouse_cfactor_border(Client *c, int f[4], GC g) { - int e; + int e; mouse_dragborder(cfactor_geo(c->wrgeo, f, &e), g); diff --git a/src/split.c b/src/split.c index 32bdc7e..5af57ca 100644 --- a/src/split.c +++ b/src/split.c @@ -62,6 +62,67 @@ _split_check_row(XRectangle g1, XRectangle g2, Position p) return (g1.x >= g2.x && (g1.x + g1.width) <= (g2.x + g2.width)); } +/** Set layout current clients to split/unsplit + */ +void +split_set_current(Client *nc, Client *ghost) +{ + if(nc && (tags[nc->screen][nc->tag].flags & SplitFlag)) + { + tags[nc->screen][nc->tag].layout.nc = nc; + tags[nc->screen][nc->tag].layout.flags |= IntegrationFlag; + } + + if(ghost && (tags[ghost->screen][ghost->tag].flags & SplitFlag)) + { + tags[ghost->screen][ghost->tag].layout.ghost = *ghost; + tags[ghost->screen][ghost->tag].layout.flags |= ArrangeFlag; + } + + return; +} + +/** Apply current operation about split +*/ +void +split_apply_current(int screen, int tag) +{ + Client *c; + + /* Need to use split geo */ + if(tags[screen][tag].layout.flags & UseGeoFlag) + { + for(c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next)) + { + cfactor_clean(c); + client_moveresize(c, (c->pgeo = c->split_geo), (tags[screen][tag].flags & ResizeHintFlag)); + } + + tags[screen][tag].layout.flags &= ~UseGeoFlag; + tags[screen][tag].flags &= ~CleanFactFlag; + } + + /* Integrate in split mode */ + if(tags[screen][tag].layout.flags & IntegrationFlag) + { + if(tags[screen][tag].layout.nc == (c = sel) + || c->screen != screen || c->tag != tag) + c = client_get_next(); + + split_client_integrate(tags[screen][tag].layout.nc, c, screen, tag); + tags[screen][tag].layout.flags &= ~IntegrationFlag; + } + + /* Remove from split mode */ + if(tags[screen][tag].layout.flags & ArrangeFlag) + { + split_arrange_closed(&tags[screen][tag].layout.ghost); + tags[screen][tag].layout.flags &= ~ArrangeFlag; + } + + return; +} + /** Store split geos of clients */ void @@ -255,7 +316,8 @@ split_client_integrate(Client *c, Client *sc, int screen, int tag) Bool b = True; XRectangle g; - if(!c || c->flags & FreeFlag) + if(!c || c->flags & FreeFlag + || !(tags[screen][tag].flags & SplitFlag)) return; if(!sc || sc->screen != screen || sc->tag != tag) @@ -293,4 +355,21 @@ split_client_integrate(Client *c, Client *sc, int screen, int tag) return; } +/** Toggle split mode +*/ +void +uicb_split_toggle(uicb_t cmd) +{ + (void)cmd; + + if((tags[selscreen][seltag[selscreen]].flags ^= SplitFlag) & SplitFlag) + split_store_geo(selscreen, seltag[selscreen]); + + layout_func(selscreen, seltag[selscreen]); + + return; +} + + + diff --git a/src/structs.h b/src/structs.h index 7e151ba..18dcf65 100644 --- a/src/structs.h +++ b/src/structs.h @@ -54,6 +54,11 @@ #define FLayFlag (1 << 11) #define DockFlag (1 << 12) +/* Layout flags definition */ +#define IntegrationFlag (1 << 1) +#define ArrangeFlag (1 << 2) +#define UseGeoFlag (1 << 3) + /* Tag flags definition */ #define TagUrgentFlag (1 << 1) #define ResizeHintFlag (1 << 2) @@ -267,6 +272,9 @@ typedef struct typedef struct { Bool splitusegeo; + uint flags; /* Flags blibli */ + Client *nc; /* New client needing integration */ + Client ghost; /* Ghost client to arrange split */ char *symbol; char *type; void (*func)(int screen); diff --git a/src/tag.c b/src/tag.c index dcd7614..2532bb3 100644 --- a/src/tag.c +++ b/src/tag.c @@ -106,7 +106,7 @@ tag_set(int tag) if(tags[selscreen][tag].flags & RequestUpdateFlag) { - tags[selscreen][tag].layout.func(selscreen); + layout_func(selscreen, tag); tags[selscreen][tag].flags &= ~RequestUpdateFlag; } @@ -148,12 +148,22 @@ tag_transfert(Client *c, int tag) s = c->screen; + tags[c->screen][c->tag].flags |= CleanFactFlag; + cfactor_clean(c); + + /* Case of tag in split mode */ + if(tags[c->screen][c->tag].flags & SplitFlag) + split_arrange_closed(c); + + if(tags[selscreen][tag].flags & SplitFlag) + split_client_integrate(c, NULL, selscreen, tag); + + /* Set new location */ c->tag = tag; c->screen = selscreen; if(s != c->screen) arrange(s, True); - arrange(c->screen, True); client_focus_next(c); @@ -500,11 +510,21 @@ tag_additional(int sc, int tag, int adtag) || adtag < 1 || adtag > conf.ntag[sc] || adtag == seltag[sc]) return; + if(tags[sc][tag].flags & SplitFlag) + return; + tags[sc][tag].tagad ^= TagFlag(adtag); tags[sc][adtag].flags |= RequestUpdateFlag; tags[sc][tag].flags |= CleanFactFlag; tags[sc][adtag].flags |= CleanFactFlag; + if(tags[sc][adtag].flags & SplitFlag) + { + tags[sc][adtag].layout.flags |= UseGeoFlag; + tags[sc][adtag].flags |= CleanFactFlag; + split_apply_current(sc, adtag); + } + arrange(sc, True); return; diff --git a/src/wmfs.h b/src/wmfs.h index 81ac378..0ee8552 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -357,6 +357,7 @@ void systray_update(void); /* layout.c */ void arrange(int screen, Bool update_layout); +void layout_func(int screen, int tag); Client *tiled_client(int screen, Client *c); void freelayout(int screen); void layoutswitch(Bool b); @@ -398,10 +399,13 @@ void getinfo(char *info); /* split.c */ void split_store_geo(int screen, int tag); +void split_set_current(Client *nc, Client *ghost); +void split_apply_current(int screen, int tag); void split_arrange_closed(Client *ghost); XRectangle split_client(Client *c, Bool p); void split_client_fill(Client *c, XRectangle geo); void split_client_integrate(Client *c, Client *sc, int screen, int tag); +void uicb_split_toggle(uicb_t cmd); /* viwmfs.c */ void viwmfs(int argc, char **argv);