diff --git a/cmd/wm/client.c b/cmd/wm/client.c index 0745416c..cd72ab76 100644 --- a/cmd/wm/client.c +++ b/cmd/wm/client.c @@ -108,6 +108,7 @@ update_client_grab(Client *c, Bool is_sel) if(is_sel) { ungrab_mouse(c->framewin, AnyModifier, AnyButton); grab_mouse(c->framewin, def.mod, Button1); + grab_mouse(c->framewin, def.mod, Button2); grab_mouse(c->framewin, def.mod, Button3); } else @@ -540,6 +541,41 @@ select_client(Client *c, char *arg) flush_masked_events(EnterWindowMask); } +void +swap_clients(Client *c, XPoint *pt) +{ + + unsigned int i, j; + Frame *f1 = c->frame.data[c->sel], *f2 = nil; + + for(i = 1; i < view.data[sel]->area.size; i++) { + Area *a = view.data[sel]->area.data[i]; + if(blitz_ispointinrect(pt->x, pt->y, &a->rect)) { + for(j = 0; j < a->frame.size; j++) { + if(blitz_ispointinrect(pt->x, pt->y, &a->frame.data[j]->rect)) { + f2 = a->frame.data[j]; + break; + } + } + break; + } + } + + if(!f2 || f1 == f2 || !idx_of_area(f1->area)) + return; + + f1->client = f2->client; + f2->client = c; + f1->client->frame.data[f1->client->sel] = f1; + f2->client->frame.data[f2->client->sel] = f2; + + arrange_column(f1->area, False); + if(f1->area != f2->area) + arrange_column(f2->area, False); + focus_client(c, True); + flush_masked_events(EnterWindowMask); +} + void swap_client(Client *c, char *arg) { diff --git a/cmd/wm/event.c b/cmd/wm/event.c index ac588c80..017f0df1 100644 --- a/cmd/wm/event.c +++ b/cmd/wm/event.c @@ -99,14 +99,24 @@ handle_buttonpress(XEvent *e) if(ev->state & def.mod) { if((ev->button == Button1 || ev->button == Button3)) focus(c, True); - if(ev->button == Button1) - do_mouse_move(c, ev); - else if (ev->button == Button3) { - BlitzAlign align = blitz_align_of_rect(&c->rect, ev->x, ev->y); - if(align != CENTER) - do_mouse_resize(c, ev, align); - else - do_mouse_move(c, ev); + switch(ev->button) { + case Button1: + do_mouse_move(c, ev, False); + break; + case Button2: + if(idx_of_area(c->frame.data[c->sel]->area)) + do_mouse_move(c, ev, True); + break; + case Button3: + { + BlitzAlign align = blitz_align_of_rect(&c->rect, ev->x, ev->y); + if(align != CENTER) + do_mouse_resize(c, ev, align); + else + do_mouse_move(c, ev, False); + } + default: + break; } } else if(ev->button == Button1) diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c index 6e06cb42..c05ad515 100644 --- a/cmd/wm/fs.c +++ b/cmd/wm/fs.c @@ -1369,6 +1369,7 @@ xwrite(IXPConn *c, Fcall *fcall) else cl = client.data[i1]; cext_strlcpy(cl->tags, buf, sizeof(cl->tags)); + cext_trim(cl->tags, " \t"); update_views(); draw_client(cl); break; diff --git a/cmd/wm/mouse.c b/cmd/wm/mouse.c index 4049686d..6ce65387 100644 --- a/cmd/wm/mouse.c +++ b/cmd/wm/mouse.c @@ -199,7 +199,7 @@ draw_pseudo_border(XRectangle * r) } void -do_mouse_move(Client *c, XButtonPressedEvent *e) +do_mouse_move(Client *c, XButtonPressedEvent *e, Bool swap) { int px = 0, py = 0, wex, wey, ex, ey, first = 1, i; Window dummy; @@ -236,8 +236,12 @@ do_mouse_move(Client *c, XButtonPressedEvent *e) case ButtonRelease: if(!first) { draw_pseudo_border(&frect); - if(idx_of_area(f->area)) - resize_column(c, &frect, &pt); + if(idx_of_area(f->area)) { + if(swap) + swap_clients(c, &pt); + else + resize_column(c, &frect, &pt); + } else resize_client(c, &frect, False); } diff --git a/cmd/wm/rule.c b/cmd/wm/rule.c index c37381a1..381fda78 100644 --- a/cmd/wm/rule.c +++ b/cmd/wm/rule.c @@ -114,6 +114,7 @@ update_rules() Rule *rul = cext_emallocz(sizeof(Rule)); rul->is_valid = !regcomp(&rul->regex, regex, 0); cext_strlcpy(rul->tags, tags, sizeof(rul->tags)); + cext_trim(rul->tags, " \t"); cext_vattach(vector_of_rules(&rule), rul); } else @@ -122,8 +123,6 @@ update_rules() mode = IGNORE; } else { - if(*p == ' ' || *p == '\t') - continue; /* skip whitespaces */ *t = *p; t++; } diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h index fa3f2cb3..e77269c7 100644 --- a/cmd/wm/wm.h +++ b/cmd/wm/wm.h @@ -229,6 +229,7 @@ void select_client(Client *c, char *arg); void send_client_to(Client *c, char *arg); void resize_all_clients(); void swap_client(Client *c, char *arg); +void swap_clients(Client *c, XPoint *pt); Client *sel_client(); int idx_of_client_id(unsigned short id); Client *client_of_win(Window w); @@ -270,7 +271,7 @@ unsigned long mod_key_of_str(char *val); /* mouse.c */ void do_mouse_resize(Client *c, XButtonPressedEvent *e, BlitzAlign align); -void do_mouse_move(Client *c, XButtonPressedEvent *e); +void do_mouse_move(Client *c, XButtonPressedEvent *e, Bool swap); void grab_mouse(Window w, unsigned long mod, unsigned int button); void ungrab_mouse(Window w, unsigned long mod, unsigned int button); diff --git a/libcext/Makefile b/libcext/Makefile index 992163b3..b4f623c2 100644 --- a/libcext/Makefile +++ b/libcext/Makefile @@ -3,7 +3,7 @@ include ../config.mk -SRC = emallocz.c estrdup.c strlcat.c strlcpy.c strtonum.c tokenize.c vector.c +SRC = emallocz.c estrdup.c strlcat.c strlcpy.c strtonum.c tokenize.c trim.c vector.c OBJ = ${SRC:.c=.o} diff --git a/libcext/cext.h b/libcext/cext.h index dbd6ec9e..fed476ec 100644 --- a/libcext/cext.h +++ b/libcext/cext.h @@ -28,6 +28,9 @@ long long cext_strtonum(const char *numstr, long long minval, /* tokenize.c */ unsigned int cext_tokenize(char **result, unsigned int reslen, char *str, char delim); +/* trim.c */ +void cext_trim(char *str, const char *chars); + /* vector.c */ #define VECTOR(name, type) \ typedef struct { \ diff --git a/libcext/trim.c b/libcext/trim.c new file mode 100644 index 00000000..ad1148e1 --- /dev/null +++ b/libcext/trim.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) MMVI Anselm R. Garbe + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "cext.h" + +/* + * Removes all characters in chars from str. + */ +void +cext_trim(char *str, const char *chars) +{ + const char *cp; + char *sp, *sn; + + for(cp = chars; *cp; cp++) { + for(sp = sn = str; *sn; sn++) { + if(*sn != *cp) + *(sp++) = *sn; + } + *sp = 0; + } +} diff --git a/rc/wmiirc b/rc/wmiirc index 1993417b..42923136 100644 --- a/rc/wmiirc +++ b/rc/wmiirc @@ -82,6 +82,8 @@ $MODKEY-9 $MODKEY-Return $MODKEY-Shift-$LEFT $MODKEY-Shift-$RIGHT +$MODKEY-Shift-$UP +$MODKEY-Shift-$DOWN $MODKEY-Shift-space $MODKEY-Shift-c $MODKEY-Shift-t @@ -149,6 +151,10 @@ do xwrite /view/sel/sel/ctl sendto prev;; $MODKEY-Shift-$RIGHT) xwrite /view/sel/sel/ctl sendto next;; + $MODKEY-Shift-$DOWN) + xwrite /view/sel/sel/ctl swap down;; + $MODKEY-Shift-$UP) + xwrite /view/sel/sel/ctl swap up;; $MODKEY-Shift-space) xwrite /view/sel/sel/ctl sendto toggle;; $MODKEY-Shift-c)