diff --git a/Makefile.in b/Makefile.in index f79f9e0..cb03d17 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,6 +57,9 @@ install: all @echo installing default config file to ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/ mkdir -p ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/ install -m 444 wmfsrc ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/ + @echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1/ + mkdir -p ${DESTDIR}${MANPREFIX}/man1/ + install -m 644 wmfs.1 ${DESTDIR}${MANPREFIX}/man1/wmfs.1 uninstall: @echo removing executable file from ${DESTDIR}${PREFIX}/bin @@ -65,6 +68,8 @@ uninstall: @echo removing config file from ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/ rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/ + @echo removing manual pages from ${DESTDIR}${MANPREFIX}/man1 + rm -f ${DESTDIR}${MANPREFIX}/man1/wmfs.1 dist: @echo "Generate wmfs-`date +%Y%m`.tar.gz" diff --git a/debian/wmfs.1 b/debian/wmfs.1 index ee54d00..970a259 100644 --- a/debian/wmfs.1 +++ b/debian/wmfs.1 @@ -1,29 +1,626 @@ -.TH WMFS: "1" "January 2012" "Window Manager From Scratch" "User Commands" -.SH NAME +.\" title: wmfs +.\" dev: xorg62 +.\" man: arpinux +.\" +.TH "WMFS" "1" "2012/02/08" "wmfs" "manual of wmfs" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" wmfs \- Window Manager From Scratch -.SH DESCRIPTION -usage: wmfs [\-hv] [\-c ] -.TP -\fB\-h\fR -Show this page -.TP +.SH "SYNOPSIS" +\fBwmfs\fR [\fB\-hv\fR] [\fB\-C \fR] [\fB\-c \fR] +.sp +.SH "DESCRIPTION" +\fBWMFS\fR is a lightweight and highly configurable tiling window manager for X written in C\&. +.sp +.SH "OPTIONS" +.PP +\fB\-C \fR +.RS 4 +Load a configuration file\&. +.RE +.PP +\fB\-c \fR +.RS 4 +Execute an uicb function to control WMFS\&. +.RE +.PP \fB\-v\fR -Show WMFS version -.TP -\fB\-c\fR -Execute a specified UICB function -.TP -\fB\-C\fR -Launch WMFS with a specified configuration file -.TP +.RS 4 +Print version information to standard output, then exit\&. +.RE +.PP \fB\-h\fR -Show this page -.TP -\fB\-v\fR -Show WMFS version -.TP -\fB\-c\fR -Execute a specified UICB function -.TP -\fB\-C\fR -Launch WMFS with a specified configuration file +.RS 4 +Print help information, then exit\&. +.RE +.SH "DEFAULT KEY BINDINGS" +.PP +\fBControl\-Alt + r\fR +.RS 4 +Reload WMFS binary +.RE +.PP +\fBSuper + Return\fR +.RS 4 +Run a terminal (urxvt by default) +.RE +.PP +\fBSuper + q\fR +.RS 4 +Quit the selected client +.RE +.PP +\fBControl\-Alt + q\fR +.RS 4 +Exit WMFS +.RE +.PP +\fBSuper + f \fR +.RS 4 +Toggle free the selected client +.RE +.PP +\fBAlt + Tab\fR +.RS 4 +Give the focus to the next client +.RE +.PP +\fBAlt\-Shift + Tab\fR +.RS 4 +Give the focus to the previous client +.RE +.PP +\fBAlt + h\fR +.RS 4 +Give the focus to the client on the left +.RE +.PP +\fBAlt + l\fR +.RS 4 +Give the focus to the client on the right +.RE +.PP +\fBAlt + k\fR +.RS 4 +Give the focus to the client on the top +.RE +.PP +\fBAlt + j\fR +.RS 4 +Give the focus to the client on the bottom +.RE +.PP +\fBSuper + Tab\fR +.RS 4 +Give the focus to the next tabbed client +.RE +.PP +\fBSuper\-Shift + Tab\fR +.RS 4 +Give the focus to the previous tabbed client +.RE +.PP +\fBControl\-Shift + h\fR +.RS 4 +Swap with the client on the left +.RE +.PP +\fBControl\-Shift + l\fR +.RS 4 +Swap with the client on the right +.RE +.PP +\fBControl\-Shift + k\fR +.RS 4 +Swap with the client on the top +.RE +.PP +\fBControl\-Shift + j\fR +.RS 4 +Swap with the client on the bottom +.RE +.PP +\fBAlt\-Shift + h\fR +.RS 4 +Tab in the client on the left +.RE +.PP +\fBAlt\-Shift + l\fR +.RS 4 +Tab in the client on the right +.RE +.PP +\fBAlt\-Shift + k\fR +.RS 4 +Tab in the client on the top +.RE +.PP +\fBAlt\-Shift + j\fR +.RS 4 +Tab in the client on the bottom +.RE +.PP +\fBAlt\-Shift + u\fR +.RS 4 +Untab the client +.RE +.PP +\fBSuper + h\fR +.RS 4 +Increase the client to the left +.RE +.PP +\fBSuper + l\fR +.RS 4 +Decrease the client from the left +.RE +.PP +\fBSuper + k\fR +.RS 4 +Increase the client to the top +.RE +.PP +\fBSuper + j\fR +.RS 4 +Decrease the client from the top +.RE +.PP +\fBSuper\-Control + h\fR +.RS 4 +Decrease the client from the right +.RE +.PP +\fBSuper\-Control + l\fR +.RS 4 +Increase the client to the right +.RE +.PP +\fBSuper\-Control + k\fR +.RS 4 +Decrease the client from the bottom +.RE +.PP +\fBSuper\-Control + j\fR +.RS 4 +Increase the client to the bottom +.RE +.PP +\fBControl + Right\fR +.RS 4 +Next tag +.RE +.PP +\fBControl + Left\fR +.RS 4 +Previous tag +.RE +.PP +\fBControl + Up\fR +.RS 4 +Next screen +.RE +.PP +\fBControl + Down\fR +.RS 4 +Previous screen +.RE +.PP +\fBSuper + m\fR +.RS 4 +Vertical mirror layout +.RE +.PP +\fBSuper\-Shift + m\fR +.RS 4 +Horizontal mirror layout +.RE +.PP +\fBSuper + r\fR +.RS 4 +Rotate layout right +.RE +.PP +\fBSuper\-Shift + r\fR +.RS 4 +Rotate layout left +.RE +.PP +\fBSuper\-Control\-Alt + h\fR +.RS 4 +Integrate client in left layout +.RE +.PP +\fBSuper\-Control\-Alt + j\fR +.RS 4 +Integrate client in bottom layout +.RE +.PP +\fBSuper\-Control\-Alt + k\fR +.RS 4 +Integrate client in top layout +.RE +.PP +\fBSuper\-Control\-Alt + l\fR +.RS 4 +Integrate client in right layout +.RE +.PP +\fBSuper + o\fR +.RS 4 +Restore previous layout +.RE +.PP +\fBSuper\-Shift + o\fR +.RS 4 +Restore next layout +.RE +.PP +\fBSuper + p\fR +.RS 4 +Make a launcher in the statusbar to run an unix command\fR +.RE +.PP +\fBSuper + F[1\&.\&.9]\fR +.RS 4 +Change tag view +.RE +.PP +\fBSuper\-Shift + F[1\&.\&.9]\fR +.RS 4 +Transfert the selected client to the wanted tag +.RE +.PP +\fBSuper + -\fR +.RS 4 +Delete current tag\fR +.RE +.PP +\fBSuper\-Shift + -\fR +.RS 4 +Add current tag\fR +.RE +.SH "CONFIGURATION" +WMFS is configured by \fI$HOME/\&.config/wmfs/wmfsrc\fR\&. +.RE +.PP +\fB\ include\fR +wmfsrc supports ”@include” to split configuration file by section\&. +.RS 2 +\fB\ Usage:\fR "@include ~/.config/wmfs/wmfs_themes"\&. +.RE +.PP +\fB\ [themes]\fR +wmfsrc supports themes for client and statusbar\&. +.RS 2 +\fB Misc\fR +.RS 2 +\fB\ name\fR +theme name: will be used in next sections\&. +.PP +\fB\ font\fR +theme font: in XLFD format\&. +.PP +.RE +\fB\ Bars\fR +.RS 2 +\fB\ bars_width\fR +bar height in pixels\&. +.PP +\fB\ bars_fg/bg\fR +statusbar text/background color\&. +.PP +.RE +\fB\ Tags\fR +.RS 2 +\fB\ tags_normal_fg/bg\fR +normal tag text/button color\&. +.PP +\fB\ tags_normal_statusline\fR +normal tag statusline\&. +.PP +\fB\ tags_sel_fg/bg\fR +selected tag text/button color\&. +.PP +\fB\ tags_sel_statusline\fR +selected tag statusline\&. +.PP +\fB\ tags_occupied_fg/bg\fR +occupied tag text/button color\&. +.PP +\fB\ tags_occupied_statusline\fR +occupied tag statusline\&. +.PP +\fB\ tags_urgent_fg/bg\fR +urgent tag text/button color\&. +.PP +\fB\ tags_urgent_statusline\fR +urgent tag statusline\&. +.PP +\fB\ tags_border_color\fR +tag button border color\&. +.PP +\fB\ tags_border_width\fR +tag button border width\&. +.PP +.RE +\fB\ Clients\fR +.RS 2 +\fB\ client_normal_fg/bg\fR +normal client titlebar text/background color\&. +.PP +\fB\ client_normal_statusline\fR +normal client statusline\&. +.PP +\fB\ client_sel_fg/bg\fR +selected client titlebar text/background color\&. +.PP +\fB\ client_sel_statusline\fR +selected client statusline\&. +.PP +\fB\ frame_bg\fR +client border color\&. +.PP +\fB\ client_titlebar_width\fR +client titlebar height in pixels\&. +.PP +\fB\ client_border_width\fR +client border height in pixels\&. +.RE +.PP +.RE +\fB\ [bars]\fR +.RS 2 +\fB\ position\fR +statusbar position on screen: 0=Top; 1=Bottom, 2=Hide\&. +.PP +\fB\ screen\fR +screen to display statusbar(start ar 0), set to\fB -1\fR to display on every screen\&. +.PP +\fB\ elements\fR +t=Tags, s=Statustext, y=Systray, l=Launcher\&. +.PP +\fB\ theme\fR +names of the statusbar theme\&. +.RE +.PP +.RE +\fB\ [tags]\fR +.RS 2 +\fB\ screen\fR +screen to display tag. use no screen option or screen =\fB -1\fR to set tag on each screen\&. +.PP +\fB\ name\fR +display tagname\&. +.PP +\fB\ statusline\fR +draw a custom statusline in the specific tag (can display any sequences)\&. +.PP +\fB\ mousebinds\fR +mouse actions on the tag buttons\&. +.RE +.PP +.RE +\fB\ [client]\fR +.RS 2 +\fB\ theme\fR +apply theme to client by default\&. +.PP +\fB\ key_modifier\fR +key modifier to perform actions on clients\&. +.PP +\fB\ mousebinds\fR +mouse actions on client\&. +.RE +.PP +.RE +\fB\ [rules]\fR +specific rules for clients: to identify an application, use xprop\&. +.RS 2 +\fB\ instance\fR +first part of WM_CLASS\&. +.PP +\fB\ class\fR +second part of WM_CLASS\&. +.PP +\fB\ role\fR +WM_WINDOW_ROLE\&. +.PP +\fB\ name\fR +_NET_WM_NAME\&. +.PP +\fB\ theme\fR +apply theme to client\&. +.PP +\fB\ tag\fR +set tag to client(start at 0)\&. +.PP +\fB\ screen\fR +display client on a specific screen\&. +.PP +\fB\ free\fR +client in auto-free mode (true/false)\&. +.PP +\fB\ tab\fR +open client in a tab (true/false)\&. +.RE +.PP +.RE +\fB\ [launchers]\fR +.RS 2 +\fB\ name\fR +launcher-name, will be used in the [keys] section\&. +.PP +\fB\ prompt\fR +display text at the beginning of the prompt\&. +.PP +\fB\ command\fR +command used by the launcher. can be an uicb function or an uicb function + extension\&. +.RE +.PP +.RE +\fB\ [keys]\fR +.RS 2 +each line is contained within\fB\ [key]...[/key]\fR +.PP +\fB\ mod\fR +key modifier (Alt, Control, Shift, Super)\&. +.PP +\fB\ key\fR +key to press\&. +.PP +\fB\ func\fR +uicb function to launch\&. +.PP +\fB\ cmd\fR +if\fB\ func = "spawn"\fR set the external command to launch\&. +.sp +.SH "UICB Functions" +UICB functions list. for “User Interface Call Backs”\&. +.PP +\fB\ usage in the wmfsrc:\fR func = "tag_next"\fB\ or\fR func = "spawn" cmd = "urxvt -e vim"\&. +.RE +\fB\ usage in the status.sh:\fR wmfs -c status " ^s[;;next](1;tag_next)"\&. +.RE +\fB\ usage in your terminal:\fR wmfs -c tag_next\&. +.PP +\fB\ spawn\fR +launch a command. ex: func = "spawn" cmd = "urxvtc -e screen irssi"\&. +.PP +\fB\ quit\fR +quit wmfs\&. +.PP +\fB\ reload\fR +reload wmfs\&. +.PP +\fB\ tag_set\fR +set tag by number\&. +.PP +\fB\ tag\fR +set tag by name\&. +.PP +\fB\ tag_next/prev\fR +set next/previous tag\&. +.PP +\fB\ tag_client\fR +tag the client\&. +.PP +\fB\ tag_move_client_next/prev\fR +tag the client with next/previous tag\&. +.PP +\fB\ tag_click\fR +display tag with a clic on tag button\&. +.PP +\fB\ tag_new/del\fR +add/delete a tag\&. +.PP +\fB\ layout_vmirror\fR +vertical mirror tiling\&. +.PP +\fB\ layout_hmirror\fR +horizontal mirror tiling\&. +.PP +\fB\ layout_rotate_left\fR +tiling rotate anti/clockwise\&. +.PP +\fB\ layout_prev_set\fR +back to previous set layout\&. +.PP +\fB\ layout_next_set\fR +go to next set layout\&. +.PP +\fB\ layout_integrate_left/right/top/bottom\fR +client integration in the client zone by direction\&. +.PP +\fB\ client_close\fR +close the client\&. +.PP +\fB\ client_resize_right/left/top/bottom\fR +resize client with direction\&. +.PP +\fB\ client_focus_right/left/top/bottom\fR +focus client with direction\&. +.PP +\fB\ client_tab_right/left/top/bottom\fR +tab client with direction\&. +.PP +\fB\ client_swap_right/left/top/bottom\fR +swap client with direction\&. +.PP +\fB\ client_focus_next/prev\fR +move focus to the next/previous client\&. +.PP +\fB\ client_swap_next/prev\fR +swap with the next/previous client\&. +.PP +\fB\ client_untab\fR +untab the client\&. +.PP +\fB\ client_focus_next_tab\fR +move focus to next tab-client\&. +.PP +\fB\ client_focus_prev_tab\fR +move focus to previous tab-client\&. +.PP +\fB\ client_focus_click\fR +give focus to client with a clic\&. +.PP +\fB\ client_toggle_free\fR +togle free the client\&. +.PP +\fB\ client_tab_next_opened\fR +open the client in a tab\&. +.PP +\fB\ status\fR +display the argument text in the statusbar\&. +.PP +\fB\ status_surface\fR +display a surface. can contain sequences\&. +.PP +\fB\ mouse_resize\fR +resize the client\&. +.PP +\fB\ mouse_move\fR +move the client\&. +.PP +\fB\ mouse_swap\fR +swap the client\&. +.PP +\fB\ mouse_tab\fR +tab the client\&. +.PP +\fB\ screen_next/prev\fR +go to next/previous screen\&. +.PP +\fB\ screen_move_client_next/prev\fR +move the client to next/previous screen\&. +.PP +\fB\ launcher\fR +native prompt. ex:\fB\ func = "launcher" cmd = "exec"\fR display the “exec” launcher\&. +.RE +.PP +.sp +.SH "BUGS" +WMFS isn\'t stable for now\&. So it certainly contains some bugs\&. +.sp +.SH "AUTHORS" +Martin Duquesnoy <\fIxorg62@gmail\&.com\fR\&[1]>\&. +.sp +.SH "WWW" +Main site: \fIhttps://github\&.com/xorg62/wmfs\fR +.PP +Wiki: \fIhttps://github\&.com/xorg62/wmfs/wiki\fR +.PP +Bug tracker: \fIhttps://github\&.com/xorg62/wmfs/issues\fR +.sp +.SH "COPYING" +WMFS is under the BSD license\&. See COPYING for more information\&. +.sp +.SH "NOTES" +.IP " 1." 4 +xorg62@gmail.com +.RS 4 +\%mailto:xorg62@gmail.com +.RE diff --git a/scripts/keybind_help.sh b/scripts/keybind_help.sh new file mode 100755 index 0000000..59dcf3b --- /dev/null +++ b/scripts/keybind_help.sh @@ -0,0 +1,64 @@ +#! /bin/sh +# simple help script for WMFS2 by arpinux +# default keybinds list + +xpos="5" +ypos="5" +width="350" +height="730" +bg="#222222" +fg="#7D7D7D" +l01="^s[80;12;$bg;WMFS² Keybinds Help]" +l03="^s[15;35;$fg;launch terminal:]^s[190;35;$fg;Super + Return]" +l04="^s[15;50;$fg;launch prompt:]^s[190;50;$fg;Super + p]" +l05="^s[15;65;$fg;close client:]^s[190;65;$fg;Super + q]" +l06="^s[15;80;$fg;reload wmfs:]^s[190;80;$fg;Control + Alt + r]" +l07="^s[15;95;$fg;quit wmfs:]^s[190;95;$fg;Control + Alt + q]" + +l08="^s[15;115;$fg;next client:]^s[190;115;$fg;Alt + Tab]" +l09="^s[15;130;$fg;prev client:]^s[190;130;$fg;Alt + Shift + Tab]" +l10="^s[15;145;$fg;next tabbed client:]^s[190;145;$fg;Super + Tab]" +l11="^s[15;160;$fg;prev tabbed client:]^s[190;160;$fg;Super + Shift + Tab]" +l12="^s[15;175;$fg;left client:]^s[190;175;$fg;Alt + h]" +l13="^s[15;190;$fg;right client:]^s[190;190;$fg;Alt + l]" +l14="^s[15;205;$fg;top client:]^s[190;205;$fg;Alt + k]" +l15="^s[15;220;$fg;bottom client:]^s[190;220;$fg;Alt + j]" +l16="^s[15;235;$fg;swap client left:]^s[190;235;$fg;Control + Shift + h]" +l17="^s[15;250;$fg;swap client right:]^s[190;250;$fg;Control + Shift + l]" +l18="^s[15;265;$fg;swap client top:]^s[190;265;$fg;Control + Shift + k]" +l19="^s[15;280;$fg;swap client bottom:]^s[190;280;$fg;Control + Shift + j]" +l20="^s[15;295;$fg;tab client left:]^s[190;295;$fg;Alt + Shift + h]" +l21="^s[15;310;$fg;tab client right:]^s[190;310;$fg;Alt + Shift + l]" +l22="^s[15;325;$fg;tab client top:]^s[190;325;$fg;Alt + Shift + k]" +l23="^s[15;340;$fg;tab client bottom:]^s[190;340;$fg;Alt + Shift + j]" +l24="^s[15;355;$fg;untab client:]^s[190;355;$fg;Alt + Shift + u]" + +l25="^s[15;375;$fg;increase client on left:]^s[190;375;$fg;Super + h]" +l26="^s[15;390;$fg;decrease client from left:]^s[190;390;$fg;Super + l]" +l27="^s[15;405;$fg;increase client on top:]^s[190;405;$fg;Super + k]" +l28="^s[15;420;$fg;decrease client from top:]^s[190;420;$fg;Super + j]" +l29="^s[15;435;$fg;decrease client from right:]^s[190;435;$fg;Super + Control + h]" +l30="^s[15;450;$fg;increase client on right:]^s[190;450;$fg;Super + Control + l]" +l31="^s[15;465;$fg;decrease client from bottom:]^s[190;465;$fg;Super + Control + k]" +l32="^s[15;480;$fg;increase client to bottom:]^s[190;480;$fg;Super + Control + j]" +l33="^s[15;495;$fg;integrate client to left:]^s[190;495;$fg;Super + Control + Alt + h]" +l34="^s[15;510;$fg;integrate client to right:]^s[190;510;$fg;Super + Control + Alt + l]" +l35="^s[15;525;$fg;integrate client to top:]^s[190;525;$fg;Super + Control + Alt + k]" +l36="^s[15;540;$fg;integrate client to bottom:]^s[190;540;$fg;Super + Control + Alt + j]" + +l37="^s[15;560;$fg;horizontal layout:]^s[190;560;$fg;Super + Shift + m]" +l38="^s[15;575;$fg;vertical layout:]^s[190;575;$fg;Super + m]" +l39="^s[15;590;$fg;layout rotate right:]^s[190;590;$fg;Super + r]" +l40="^s[15;605;$fg;layout rotate left:]^s[190;605;$fg;Super + Shift + r]" +l41="^s[15;620;$fg;toggle client free:]^s[190;620;$fg;Super + f]" + +l42="^s[15;640;$fg;prev/next tag:]^s[190;640;$fg;Control + Left/Right]" +l43="^s[15;655;$fg;prev/next screen:]^s[190;655;$fg;Control + Up/Down]" +l44="^s[15;670;$fg;set tag (x):]^s[190;670;$fg;Super + F(x)]" +l45="^s[15;685;$fg;tag client with (x):]^s[190;685;$fg;Super + Shift + F(x)]" +l46="^s[15;700;$fg;add tag:]^s[190;700;$fg;Super + -]" +l47="^s[15;715;$fg;delete tag:]^s[190;715;$fg;Super + Shift + -]" + +frame="^R[0;0;350;15;$fg] ^R[0;728;350;2;$fg] ^R[0;0;2;730;$fg] ^R[348;0;2;730;$fg]" + +wmfs -c status_surface "$xpos,$ypos,$width,$height,$bg $frame $l01 $l03 $l04 $l05 $l06 $l07 $l08 $l09 $l10 $l11 $l12 $l13 $l14 $l15 $l16 $l17 $l18 $l19 $l20 $l21 $l22 $l23 $l24 $l25 $l26 $l27 $l28 $l29 $l30 $l31 $l32 $l33 $l34 $l35 $l36 $l37 $l38 $l39 $l40 $l41 $l42 $l43 $l44 $l45 $l46 $l47" diff --git a/src/client.c b/src/client.c index 745ddd3..3221322 100644 --- a/src/client.c +++ b/src/client.c @@ -626,6 +626,8 @@ client_focus(struct client *c) } XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(W->dpy, W->root, W->net_atom[net_active_window], XA_WINDOW, 32, + PropModeReplace, (unsigned char *)&c->win, 1); } else { @@ -875,20 +877,21 @@ client_apply_rule(struct client *c) c->theme = r->theme; + /* free = false for originally free client */ if(r->flags & RULE_FREE) c->flags |= CLIENT_FREE; - /* free = false for originally free client */ else c->flags &= ~CLIENT_FREE; + /* Free rule is not compatible with tab rule */ + if(r->flags & RULE_TAB) + W->flags ^= WMFS_TABNOC; /* < can be disable by client_tab_next_opened */ /* TODO - if(r->flags & RULE_MAX) - {} - if(r->flags & RULE_IGNORE_TAG) {} */ + c->flags |= CLIENT_RULED; } flags = 0; @@ -969,6 +972,8 @@ client_new(Window w, XWindowAttributes *wa, bool scan) ewmh_manage_window_type(c); } + ewmh_get_client_list(); + return c; } @@ -1407,6 +1412,8 @@ client_remove(struct client *c) XSetErrorHandler(wmfs_error_handler); free(c); + + ewmh_get_client_list(); } void @@ -1431,6 +1438,14 @@ uicb_client_toggle_free(Uicb cmd) } } +void +uicb_client_tab_next_opened(Uicb cmd) +{ + (void)cmd; + + W->flags ^= WMFS_TABNOC; +} + void client_free(void) { diff --git a/src/client.h b/src/client.h index 7ef4d75..8502ec9 100644 --- a/src/client.h +++ b/src/client.h @@ -58,6 +58,7 @@ void client_update_props(struct client *c, Flags f); void client_fac_hint(struct client *c); void uicb_client_untab(Uicb cmd); void uicb_client_toggle_free(Uicb cmd); +void uicb_client_tab_next_opened(Uicb cmd); /* Generated */ void uicb_client_resize_Right(Uicb); diff --git a/src/config.c b/src/config.c index 4fb9480..2d73209 100644 --- a/src/config.c +++ b/src/config.c @@ -177,9 +177,10 @@ static void config_tag(void) { struct screen *s; + struct tag *t; size_t i, n; struct conf_sec *sec, **ks, **mb; - char *name; + char *name, *tmp; int screenid; /* [tags] */ @@ -202,7 +203,14 @@ config_tag(void) SLIST_FOREACH(s, &W->h.screen, next) if(screenid == s->id || screenid == -1) - tag_new(s, name); + { + t = tag_new(s, name); + + t->statusctx = status_new_ctx(NULL, NULL); + ISTRDUP(t->statusctx.status, fetch_opt_first(ks[i], "", "statusline").str); + if(t->statusctx.status) + status_parse(&t->statusctx); + } } /* If no tag at all on a screen, add one anyway */ @@ -264,7 +272,7 @@ config_rule(void) r->tag = fetch_opt_first(ks[i], "-1", "tag").num; FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "free").boolean, RULE_FREE); - FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "max").boolean, RULE_MAX); + FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "tab").boolean, RULE_TAB); FLAGAPPLY(r->flags, fetch_opt_first(ks[i], "false", "ignore_tag").boolean, RULE_IGNORE_TAG); if((tn = fetch_opt_first(ks[i], "", "theme").str)) diff --git a/src/config.h b/src/config.h index 2570f7e..0c10e19 100644 --- a/src/config.h +++ b/src/config.h @@ -38,6 +38,8 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] = { "tag_move_client_next", uicb_tag_move_client_next }, { "tag_move_client_prev", uicb_tag_move_client_prev }, { "tag_click", uicb_tag_click }, + { "tag_new", uicb_tag_new }, + { "tag_del", uicb_tag_del }, /* Layout */ { "layout_vmirror", uicb_layout_vmirror }, @@ -78,9 +80,11 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] = { "client_focus_prev_tab", uicb_client_focus_prev_tab }, { "client_focus_click", uicb_client_focus_click }, { "client_toggle_free", uicb_client_toggle_free }, + { "client_tab_next_opened", uicb_client_tab_next_opened }, /* Status */ - { "status" , uicb_status }, + { "status" , uicb_status }, + { "status_surface", uicb_status_surface }, /* Mouse */ { "mouse_resize", uicb_mouse_resize }, diff --git a/src/draw.h b/src/draw.h index e6fb6d2..f67b7aa 100644 --- a/src/draw.h +++ b/src/draw.h @@ -83,6 +83,12 @@ draw_reversed_rect(Drawable dr, struct client *c, bool t) g->h - (i << 1)); } +static inline void +draw_line(Drawable d, int x1, int y1, int x2, int y2) +{ + XDrawLine(W->dpy, d, W->gc, x1, y1, x2, y2); +} + static inline unsigned short draw_textw(struct theme *t, const char *str) { diff --git a/src/event.c b/src/event.c index 3676945..bc41670 100644 --- a/src/event.c +++ b/src/event.c @@ -29,6 +29,7 @@ event_buttonpress(XEvent *e) struct barwin *b; screen_update_sel(); + status_flush_surface(); SLIST_FOREACH(b, &W->h.barwin, next) if(b->win == ev->window) @@ -325,6 +326,7 @@ event_keypress(XEvent *e) struct keybind *k; screen_update_sel(); + status_flush_surface(); SLIST_FOREACH(k, &W->h.keybind, next) if(k->keysym == keysym && KEYPRESS_MASK(k->mod) == KEYPRESS_MASK(ev->state)) diff --git a/src/ewmh.c b/src/ewmh.c index 8ea12ee..b14739e 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -111,6 +111,31 @@ ewmh_set_wm_state(Window w, int state) W->net_atom[wm_state], 32, PropModeReplace, d, 2); } +/* + * _NET_CLIENT_LIST + */ +void +ewmh_get_client_list(void) +{ + Window *list; + struct client *c; + int win_n = 0; + + SLIST_FOREACH(c, &W->h.client, next) + ++win_n; + + list = xcalloc(win_n, sizeof(Window)); + + win_n = 0; + SLIST_FOREACH(c, &W->h.client, next) + list[win_n++] = c->win; + + XChangeProperty(W->dpy, W->root, W->net_atom[net_client_list], XA_WINDOW, 32, + PropModeReplace, (unsigned char *)list, win_n); + + XFree(list); +} + /* * Get xembed state */ @@ -168,30 +193,29 @@ void ewmh_manage_state(long data[], struct client *c) { /* _NET_WM_STATE_FULLSCREEN */ - if(data[1] == (long)W->net_atom[net_wm_state_fullscreen]) + if(data[1] == (long)W->net_atom[net_wm_state_fullscreen] + || data[2] == (long)W->net_atom[net_wm_state_fullscreen]) { if(data[0] == _NET_WM_STATE_ADD || (data[0] == _NET_WM_STATE_TOGGLE && !(c->flags & CLIENT_FULLSCREEN))) { c->flags |= CLIENT_FULLSCREEN; + XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, + (unsigned char*)&W->net_atom[net_wm_state_fullscreen], 1); XReparentWindow(W->dpy, c->win, W->root, c->screen->geo.x, c->screen->geo.y); XResizeWindow(W->dpy, c->win, c->screen->geo.w, c->screen->geo.h); - XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, - (unsigned char*)&W->net_atom[net_wm_state_fullscreen], true); client_focus(c); XRaiseWindow(W->dpy, c->win); } - else if(data[0] == _NET_WM_STATE_REMOVE - || (data[0] == _NET_WM_STATE_TOGGLE && c->flags & CLIENT_FULLSCREEN)) + else { c->flags &= ~CLIENT_FULLSCREEN; - - XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y); XChangeProperty(W->dpy, c->win, W->net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, - (unsigned char*)&W->net_atom[net_wm_state_fullscreen], false); + (unsigned char*)0, 0); + XReparentWindow(W->dpy, c->win, c->frame, c->wgeo.x, c->wgeo.y); client_moveresize(c, &c->geo); } diff --git a/src/ewmh.h b/src/ewmh.h index e7aa2b0..5540979 100644 --- a/src/ewmh.h +++ b/src/ewmh.h @@ -118,6 +118,7 @@ ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, lon void ewmh_init(void); void ewmh_set_wm_state(Window w, int state); +void ewmh_get_client_list(void); long ewmh_get_xembed_state(Window win); void ewmh_update_wmfs_props(void); void ewmh_manage_state(long data[], struct client *c); diff --git a/src/infobar.c b/src/infobar.c index 8389eb1..c679e76 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -12,6 +12,14 @@ #include "status.h" #include "systray.h" +#define ELEM_FREE_BARWIN(e) \ + while(!SLIST_EMPTY(&e->bars)) \ + { \ + b = SLIST_FIRST(&e->bars); \ + SLIST_REMOVE_HEAD(&e->bars, enext); \ + barwin_remove(b); \ + } + static void infobar_elem_tag_init(struct element *e); static void infobar_elem_tag_update(struct element *e); static void infobar_elem_status_init(struct element *e); @@ -53,9 +61,16 @@ infobar_elem_tag_init(struct element *e) e->geo.h -= (e->infobar->theme->tags_border_width << 1); e->statusctx = &e->infobar->theme->tags_n_sl; + e->statusctx->flags |= STATUS_BLOCK_REFRESH; - if(SLIST_EMPTY(&e->bars)) + if(SLIST_EMPTY(&e->bars) || (e->infobar->screen->flags & SCREEN_TAG_UPDATE)) { + if((e->infobar->screen->flags & SCREEN_TAG_UPDATE)) + { + ELEM_FREE_BARWIN(e); + SLIST_INIT(&e->bars); + } + TAILQ_FOREACH(t, &e->infobar->screen->tags, next) { s = draw_textw(e->infobar->theme, t->name) + PAD; @@ -63,6 +78,10 @@ infobar_elem_tag_init(struct element *e) /* Init barwin */ b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false); + /* Status doesn't have theme yet */ + t->statusctx.theme = e->infobar->theme; + t->statusctx.flags |= STATUS_BLOCK_REFRESH; + /* Set border */ if(e->infobar->theme->tags_border_width) { @@ -140,6 +159,10 @@ infobar_elem_tag_update(struct element *e) status_copy_mousebind(e->statusctx); status_render(e->statusctx); + t->statusctx.barwin = b; + status_copy_mousebind(&t->statusctx); + status_render(&t->statusctx); + draw_text(b->dr, e->infobar->theme, (PAD >> 1), TEXTY(e->infobar->theme, e->geo.h), b->fg, t->name); @@ -380,12 +403,7 @@ infobar_elem_remove(struct element *e) TAILQ_REMOVE(&e->infobar->elements, e, next); - while(!SLIST_EMPTY(&e->bars)) - { - b = SLIST_FIRST(&e->bars); - SLIST_REMOVE_HEAD(&e->bars, enext); - barwin_remove(b); - } + ELEM_FREE_BARWIN(e); free(e); } diff --git a/src/layout.c b/src/layout.c index 9ae7a0d..036359b 100644 --- a/src/layout.c +++ b/src/layout.c @@ -389,10 +389,19 @@ layout_split_integrate(struct client *c, struct client *sc) { client_maximize(c); c->flags |= CLIENT_TILED; + W->flags &= ~WMFS_TABNOC; return; } } + /* Tab Next Opened Client */ + if(W->flags & WMFS_TABNOC) + { + W->flags ^= WMFS_TABNOC; + _client_tab(c, sc); + return; + } + c->flags |= CLIENT_TILED; g = layout_split(sc, (sc->geo.h < sc->geo.w)); diff --git a/src/layout.h b/src/layout.h index 0bae14c..2d00652 100644 --- a/src/layout.h +++ b/src/layout.h @@ -7,6 +7,7 @@ #define LAYOUT_H #include "wmfs.h" +#include "client.h" /* Check lateral direction (if p is Right or Left) */ #define LDIR(P) (P < Top) diff --git a/src/mouse.c b/src/mouse.c index a6e79f1..544b4fa 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -26,7 +26,7 @@ mouse_resize(struct client *c) int d, u, ox, oy, ix, iy; int mx, my; - XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u); + XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (unsigned int *)&u); XGrabServer(W->dpy); if(c->flags & CLIENT_FREE) diff --git a/src/screen.c b/src/screen.c index e0a3979..c5e7f15 100644 --- a/src/screen.c +++ b/src/screen.c @@ -21,6 +21,7 @@ screen_new(struct geo *g, int id) s->geo = s->ugeo = *g; s->seltag = NULL; s->id = id; + s->flags = 0; TAILQ_INIT(&s->tags); SLIST_INIT(&s->infobars); diff --git a/src/status.c b/src/status.c index c8ee6ec..a8e98b8 100644 --- a/src/status.c +++ b/src/status.c @@ -40,10 +40,26 @@ status_new_ctx(struct barwin *b, struct theme *t) struct status_ctx ctx = { .barwin = b, .theme = t }; SLIST_INIT(&ctx.statushead); + SLIST_INIT(&ctx.gcache); return ctx; } +static void +status_gcache_free(struct status_ctx *ctx) +{ + struct status_gcache *gc; + + while(!SLIST_EMPTY(&ctx->gcache)) + { + gc = SLIST_FIRST(&ctx->gcache); + SLIST_REMOVE_HEAD(&ctx->gcache, next); + free(gc->datas); + free(gc->name); + free(gc); + } +} + void status_free_ctx(struct status_ctx *ctx) { @@ -53,6 +69,62 @@ status_free_ctx(struct status_ctx *ctx) SLIST_INIT(&ctx->barwin->statusmousebinds); status_flush_list(ctx); + status_gcache_free(ctx); + +} + +static void +status_graph_draw(struct status_ctx *ctx, struct status_seq *sq, struct status_gcache *gc) +{ + int i, j, y; + int ys = sq->geo.y + sq->geo.h - 1; + + XSetForeground(W->dpy, W->gc, sq->color2); + + for(i = sq->geo.x + sq->geo.w - 1, j = gc->ndata - 1; + j >= 0 && i >= sq->geo.x; + --j, --i) + { + /* You divided by zero didn't you? */ + if(gc->datas[j]) + { + y = ys - (sq->geo.h / ((float)sq->data[2] / (float)gc->datas[j])) + 1; + draw_line(ctx->barwin->dr, i, y, i, ys); + } + } +} + +static void +status_graph_process(struct status_ctx *ctx, struct status_seq *sq, char *name) +{ + int j; + struct status_gcache *gc; + + /* Graph already exist and have a cache */ + SLIST_FOREACH(gc, &ctx->gcache, next) + if(!strcmp(name, gc->name)) + { + /* shift buffer to remove unused old value */ + if(gc->ndata > (sq->geo.w << 1)) + for(gc->ndata /= 2, j = 0; + j < gc->ndata; + gc->datas[j] = gc->datas[j + gc->ndata], ++j); + + gc->datas[gc->ndata++] = sq->data[1]; + status_graph_draw(ctx, sq, gc); + return; + } + + /* No? Make a cache for it */ + gc = xcalloc(1, sizeof(struct status_gcache)); + gc->name = xstrdup(name); + gc->ndata = 1; + gc->datas = xcalloc(sq->geo.w + sq->geo.w, sizeof(int)); + gc->datas[0] = sq->data[1]; + + SLIST_INSERT_HEAD(&ctx->gcache, gc, next); + + status_graph_draw(ctx, sq, gc); } /* Parse mousebind sequence next normal sequence: \[](button;func;cmd) */ @@ -90,9 +162,9 @@ void status_parse(struct status_ctx *ctx) { struct status_seq *sq, *prev = NULL; - int i, shift = 0; + int i, tmp, shift = 0; char *dstr = xstrdup(ctx->status), *sauv = dstr; - char type, *p, *pp, *end, *arg[6] = { NULL }; + char type, *p, *pp, *end, *arg[10] = { NULL }; for(; *dstr; ++dstr) { @@ -107,7 +179,7 @@ status_parse(struct status_ctx *ctx) while(*(end - 1) == '\\') end = strchr(end + 1, ']'); - if(!(strchr("sRi", *p)) || !end) + if(!(strchr("sRpPig", *p)) || !end) continue; /* Then parse & list it */ @@ -144,6 +216,49 @@ status_parse(struct status_ctx *ctx) break; + /* + * Progress bar sequence: \p[left/right;w;h;bord;val;valmax;bg;fg] OR x;y + * Position bar sequence: \P[left/right;w;h;tickbord;val;valmax;bg;fg] OR x;y + */ + case 'p': + case 'P': + i = parse_args(p + 2, ';', ']', 9, arg); + STATUS_CHECK_ARGS(i, 7, 8, dstr, end); + sq = status_new_seq(type, i, 7, arg, &shift); + + sq->geo.w = ATOI(arg[1 + shift]); + sq->geo.h = ATOI(arg[2 + shift]); + + sq->data[0] = ATOI(arg[3 + shift]); /* Border */ + sq->data[1] = ((tmp = ATOI(arg[4 + shift])) ? tmp : 1); /* Value */ + sq->data[2] = ATOI(arg[5 + shift]); /* Value Max */ + + sq->color = color_atoh(arg[6 + shift]); + sq->color2 = color_atoh(arg[7 + shift]); + + break; + + /* + * Graph sequence: \g[left/right;w;h;val;valmax;bg;fg;name] OR x;y + */ + case 'g': + i = parse_args(p + 2, ';', ']', 9, arg); + STATUS_CHECK_ARGS(i, 7, 8, dstr, end); + sq = status_new_seq(type, i, 7, arg, &shift); + + sq->geo.w = ATOI(arg[1 + shift]); + sq->geo.h = ATOI(arg[2 + shift]); + + sq->data[1] = ATOI(arg[3 + shift]); /* Value */ + sq->data[2] = ATOI(arg[4 + shift]); /* Value Max */ + + sq->color = color_atoh(arg[5 + shift]); + sq->color2 = color_atoh(arg[6 + shift]); + + sq->str = xstrdup(arg[7 + shift]); + + break; + /* * Image sequence: \i[left/right;w;h;/path/img] OR \i[x;y;w;h;/path/img] */ @@ -161,7 +276,7 @@ status_parse(struct status_ctx *ctx) #endif /* HAVE_IMLIB2 */ } - if (sq->align == Right) + if(sq->align == Right) SLIST_INSERT_HEAD(&ctx->statushead, sq, next); else SLIST_INSERT_TAIL(&ctx->statushead, sq, next, prev); @@ -195,11 +310,21 @@ status_parse(struct status_ctx *ctx) sq->geo.x = ctx->barwin->geo.w - right - sq->geo.w; \ right += sq->geo.w; \ } + +#define STORE_MOUSEBIND() \ + if(!SLIST_EMPTY(&sq->mousebinds)) \ + SLIST_FOREACH(m, &sq->mousebinds, snext) \ + m->area = sq->geo; + +#define NOALIGN_Y() \ + if(sq->align != NoAlign) \ + sq->geo.y = (ctx->barwin->geo.h >> 1) - (sq->geo.h >> 1); static void status_apply_list(struct status_ctx *ctx) { struct status_seq *sq; struct mousebind *m; + struct geo g; int left = 0, right = 0, w, h; SLIST_FOREACH(sq, &ctx->statushead, next) @@ -229,16 +354,71 @@ status_apply_list(struct status_ctx *ctx) /* Rectangle */ case 'R': - if(sq->align != NoAlign) - sq->geo.y = (ctx->barwin->geo.h >> 1) - (sq->geo.h >> 1); - + NOALIGN_Y(); STATUS_ALIGN(sq->align); draw_rect(ctx->barwin->dr, &sq->geo, sq->color); - if(!SLIST_EMPTY(&sq->mousebinds)) - SLIST_FOREACH(m, &sq->mousebinds, snext) - m->area = sq->geo; + STORE_MOUSEBIND(); + + break; + + /* Progress */ + case 'p': + NOALIGN_Y(); + STATUS_ALIGN(sq->align); + + draw_rect(ctx->barwin->dr, &sq->geo, sq->color); + + /* Progress bar geo */ + g.x = sq->geo.x + sq->data[0]; + g.y = sq->geo.y + sq->data[0]; + g.w = sq->geo.w - sq->data[0] - sq->data[0]; + g.h = sq->geo.h - sq->data[0] - sq->data[0]; + + if(sq->geo.w > sq->geo.h) + g.w /= ((float)sq->data[2] / (float)sq->data[1]); + else + { + g.y += g.h; + g.h /= ((float)sq->data[2] / (float)sq->data[1]); + g.y -= g.h; + } + + draw_rect(ctx->barwin->dr, &g, sq->color2); + + STORE_MOUSEBIND(); + + break; + + /* Position */ + case 'P': + NOALIGN_Y(); + STATUS_ALIGN(sq->align); + + draw_rect(ctx->barwin->dr, &sq->geo, sq->color); + + g.x = sq->geo.x + ((sq->geo.w - sq->data[0]) / ((float)sq->data[2] / (float)sq->data[1])); + g.y = sq->geo.y; + g.w = sq->data[0]; + g.h = sq->geo.h; + + draw_rect(ctx->barwin->dr, &g, sq->color2); + + STORE_MOUSEBIND(); + + break; + + /* Graph */ + case 'g': + NOALIGN_Y(); + STATUS_ALIGN(sq->align); + + draw_rect(ctx->barwin->dr, &sq->geo, sq->color); + + status_graph_process(ctx, sq, sq->str); + + STORE_MOUSEBIND(); break; @@ -256,12 +436,8 @@ status_apply_list(struct status_ctx *ctx) sq->geo.y = (ctx->barwin->geo.h >> 1) - (sq->geo.h >> 1); STATUS_ALIGN(sq->align); - draw_image(ctx->barwin->dr, &sq->geo); - - if(!SLIST_EMPTY(&sq->mousebinds)) - SLIST_FOREACH(m, &sq->mousebinds, snext) - m->area = sq->geo; + STORE_MOUSEBIND(); break; #endif /* HAVE_IMLIB2 */ @@ -277,7 +453,8 @@ status_render(struct status_ctx *ctx) if(!ctx->status) return; - barwin_refresh_color(ctx->barwin); + if(!(ctx->flags & STATUS_BLOCK_REFRESH)) + barwin_refresh_color(ctx->barwin); /* Use simple text instead sequence if no sequence found */ if(SLIST_EMPTY(&ctx->statushead)) @@ -351,6 +528,78 @@ status_manage(struct status_ctx *ctx) status_copy_mousebind(ctx); } +void +status_flush_surface(void) +{ + struct barwin *b; + + while(!SLIST_EMPTY(&W->h.vbarwin)) + { + b = SLIST_FIRST(&W->h.vbarwin); + SLIST_REMOVE_HEAD(&W->h.vbarwin, vnext); + barwin_remove(b); + } +} + +static void +status_surface(int x, int y, int w, int h, Color bg, char *status) +{ + struct barwin *b; + struct screen *s; + struct status_ctx ctx; + int d; + + if(!status) + return; + + if(x + y < 0) + XQueryPointer(W->dpy, W->root, (Window*)&d, (Window*)&d, &x, &y, &d, &d, (unsigned int *)&d); + + s = screen_gb_geo(x, y); + + if(x + w > s->geo.x + s->geo.w) + x -= w; + if(y + h > s->geo.y + s->geo.h) + y -= h; + + b = barwin_new(W->root, x, y, w, h, 0, bg, false); + barwin_map(b); + + /* Use client theme */ + ctx = status_new_ctx(b, W->ctheme); + ctx.status = xstrdup(status); + + SLIST_INSERT_HEAD(&W->h.vbarwin, b, vnext); + + status_manage(&ctx); + status_free_ctx(&ctx); +} + +void +uicb_status_surface(Uicb cmd) +{ + char *p, *ccmd = xstrdup(cmd); + int s, w, h, x = -1, y = -1; + Color bg; + + if(!ccmd || !(p = strchr(ccmd, ' '))) + return; + + *p = '\0'; + ++p; + + if(!(((s = sscanf(ccmd, "%d,%d,#%x", &w, &h, &bg)) == 3) + || (s = sscanf(ccmd, "%d,%d,%d,%d,#%x", &x, &y, &w, &h, &bg)) == 5)) + { + free(ccmd); + return; + } + + status_surface(x, y, w, h, bg, p); + + free(ccmd); +} + /* Syntax: " " */ void uicb_status(Uicb cmd) diff --git a/src/status.h b/src/status.h index ada712a..24acdeb 100644 --- a/src/status.h +++ b/src/status.h @@ -16,6 +16,8 @@ void status_copy_mousebind(struct status_ctx *ctx); void status_parse(struct status_ctx *ctx); void status_render(struct status_ctx *ctx); void status_manage(struct status_ctx *ctx); +void status_flush_surface(void); void uicb_status(Uicb cmd); +void uicb_status_surface(Uicb cmd); #endif /* STATUS_H */ diff --git a/src/systray.c b/src/systray.c index e6c2b88..2ebae5b 100644 --- a/src/systray.c +++ b/src/systray.c @@ -72,7 +72,7 @@ systray_add(Window win) s->geo.h = W->systray.barwin->geo.h; s->geo.w = W->systray.barwin->geo.h + SYSTRAY_SPACING; - ewmh_set_wm_state(s->win, WithdrawnState); + ewmh_set_wm_state(s->win, NormalState); XSelectInput(W->dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask); XReparentWindow(W->dpy, s->win, W->systray.win, 0, 0); diff --git a/src/tag.c b/src/tag.c index 4fd04c3..0db54ff 100644 --- a/src/tag.c +++ b/src/tag.c @@ -22,7 +22,6 @@ tag_new(struct screen *s, char *name) t = xcalloc(1, sizeof(struct tag)); t->screen = s; - t->name = xstrdup(name); t->flags = 0; t->id = 0; t->sel = NULL; @@ -31,6 +30,11 @@ tag_new(struct screen *s, char *name) if((l = TAILQ_LAST(&s->tags, tsub))) t->id = l->id + 1; + if(!name || !strlen(name)) + xasprintf(&t->name, "%d", t->id + 1); + else + t->name = xstrdup(name); + SLIST_INIT(&t->clients); TAILQ_INIT(&t->sets); @@ -42,7 +46,7 @@ tag_new(struct screen *s, char *name) void tag_screen(struct screen *s, struct tag *t) { - if(t == s->seltag) + if(t == s->seltag && TAILQ_NEXT(TAILQ_FIRST(&s->tags), next)) t = t->prev; if(!t) @@ -88,6 +92,8 @@ tag_client(struct tag *t, struct client *c) c->flags &= ~CLIENT_RULED; + infobar_elem_screen_update(c->screen, ElemTag); + /* Client remove */ if(!t) return; @@ -100,10 +106,6 @@ tag_client(struct tag *t, struct client *c) SLIST_INSERT_HEAD(&t->clients, c, tnext); - infobar_elem_screen_update(t->screen, ElemTag); - - layout_client(c); - if(c->flags & CLIENT_TABMASTER && c->prevtag) { struct client *cc; @@ -116,6 +118,8 @@ tag_client(struct tag *t, struct client *c) } } + layout_client(c); + if(t != c->screen->seltag || c->flags & CLIENT_TABBED) client_unmap(c); } @@ -177,7 +181,7 @@ uicb_tag_client(Uicb cmd) struct tag *t; int id = ATOI(cmd); - if((t = tag_gb_id(W->screen, id))) + if(W->client && (t = tag_gb_id(W->screen, id))) tag_client(t, W->client); } @@ -187,6 +191,9 @@ uicb_tag_move_client_next(Uicb cmd) (void)cmd; struct tag *t; + if(!W->client) + return; + if((t = TAILQ_NEXT(W->screen->seltag, next))) tag_client(t, W->client); else if( /* CIRCULAR OPTION */ 1) @@ -199,6 +206,9 @@ uicb_tag_move_client_prev(Uicb cmd) (void)cmd; struct tag *t; + if(!W->client) + return; + if((t = TAILQ_PREV(W->screen->seltag, tsub, next))) tag_client(t, W->client); else if( /* CIRCULAR OPTION */ 1) @@ -219,6 +229,8 @@ uicb_tag_click(Uicb cmd) static void tag_remove(struct tag *t) { + TAILQ_REMOVE(&t->screen->tags, t, next); + free(t->name); layout_free_set(t); @@ -226,14 +238,49 @@ tag_remove(struct tag *t) free(t); } +void +uicb_tag_new(Uicb cmd) +{ + struct screen *s = W->screen; + struct infobar *i; + + tag_new(s, (char*)cmd); + + s->flags |= SCREEN_TAG_UPDATE; + + SLIST_FOREACH(i, &s->infobars, next) + infobar_elem_reinit(i); + + s->flags ^= SCREEN_TAG_UPDATE; +} + +void +uicb_tag_del(Uicb cmd) +{ + struct infobar *i; + struct tag *t = W->screen->seltag; + (void)cmd; + + if(SLIST_EMPTY(&t->clients) + && TAILQ_NEXT(TAILQ_FIRST(&W->screen->tags), next)) + { + tag_screen(W->screen, TAILQ_NEXT(t, next)); + tag_remove(t); + + W->screen->flags |= SCREEN_TAG_UPDATE; + + SLIST_FOREACH(i, &W->screen->infobars, next) + infobar_elem_reinit(i); + + W->screen->flags ^= SCREEN_TAG_UPDATE; + } +} + void tag_free(struct screen *s) { struct tag *t; TAILQ_FOREACH(t, &s->tags, next) - { - TAILQ_REMOVE(&s->tags, t, next); tag_remove(t); - } } diff --git a/src/tag.h b/src/tag.h index c7f604d..89a25ba 100644 --- a/src/tag.h +++ b/src/tag.h @@ -32,5 +32,7 @@ void uicb_tag_client(Uicb cmd); void uicb_tag_move_client_next(Uicb cmd); void uicb_tag_move_client_prev(Uicb cmd); void uicb_tag_click(Uicb cmd); +void uicb_tag_new(Uicb cmd); +void uicb_tag_del(Uicb cmd); #endif /* TAG_H */ diff --git a/src/util.c b/src/util.c index e20c684..07a8d9d 100644 --- a/src/util.c +++ b/src/util.c @@ -149,7 +149,7 @@ parse_args(char *str, char delim, char end, int narg, char *args[]) int i = 0; for(args[0] = str; *str && (*str != end || *(str - 1) == '\\') && i < narg; ++str) - if(*str == delim) + if(*str == delim && i < narg - 1) { *str = '\0'; args[++i] = ++str; diff --git a/src/wmfs.c b/src/wmfs.c index 51d6adf..39682e1 100644 --- a/src/wmfs.c +++ b/src/wmfs.c @@ -160,6 +160,7 @@ wmfs_xinit(void) * Barwin linked list */ SLIST_INIT(&W->h.barwin); + SLIST_INIT(&W->h.vbarwin); /* * Optional dep init diff --git a/src/wmfs.h b/src/wmfs.h index 8a72310..84d25f9 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -95,15 +95,17 @@ struct barwin SLIST_HEAD(, mousebind) statusmousebinds; SLIST_ENTRY(barwin) next; /* global barwin */ SLIST_ENTRY(barwin) enext; /* element barwin */ + SLIST_ENTRY(barwin) vnext; /* volatile barwin */ }; struct status_seq { struct geo geo; enum position align; + int data[4]; char type; char *str; - Color color; + Color color, color2; SLIST_HEAD(, mousebind) mousebinds; SLIST_ENTRY(status_seq) next; }; @@ -112,11 +114,22 @@ struct status_ctx { struct barwin *barwin; struct theme *theme; +#define STATUS_BLOCK_REFRESH 0x01 + Flags flags; char *status; bool update; + SLIST_HEAD(, status_gcache) gcache; SLIST_HEAD(, status_seq) statushead; }; +struct status_gcache +{ + char *name; + int *datas; + int ndata; + SLIST_ENTRY(status_gcache) next; +}; + struct element { struct geo geo; @@ -149,6 +162,8 @@ struct screen { struct geo geo, ugeo; struct tag *seltag; +#define SCREEN_TAG_UPDATE 0x01 + Flags flags; int id; TAILQ_HEAD(tsub, tag) tags; SLIST_HEAD(, infobar) infobars; @@ -163,6 +178,7 @@ struct tag struct client *sel; struct client *prevsel; struct tag *prev; + struct status_ctx statusctx; char *name; int id; #define TAG_URGENT 0x01 @@ -274,7 +290,7 @@ struct rule char *name; int tag, screen; #define RULE_FREE 0x01 -#define RULE_MAX 0x02 +#define RULE_TAB 0x02 #define RULE_IGNORE_TAG 0x04 Flags flags; SLIST_ENTRY(rule) next; @@ -325,6 +341,7 @@ struct wmfs #define WMFS_LOG 0x10 #define WMFS_LAUNCHER 0x20 #define WMFS_SIGCHLD 0x40 +#define WMFS_TABNOC 0x80 /* tab next opened client */ Flags flags; GC gc, rgc; Atom *net_atom; @@ -347,6 +364,7 @@ struct wmfs SLIST_HEAD(, rule) rule; SLIST_HEAD(, mousebind) mousebind; SLIST_HEAD(, launcher) launcher; + SLIST_HEAD(, barwin) vbarwin; } h; /* diff --git a/wmfs.1 b/wmfs.1 new file mode 100644 index 0000000..0b289a3 --- /dev/null +++ b/wmfs.1 @@ -0,0 +1,679 @@ +.\" title: wmfs +.\" dev: xorg62 +.\" man: arpinux +.\" +.TH "WMFS" "1" "2012/02/08" "wmfs" "manual of wmfs" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +wmfs \- Window Manager From Scratch +.SH "SYNOPSIS" +\fBwmfs\fR [\fB\-hv\fR] [\fB\-C \fR] [\fB\-c \fR] +.sp +.SH "DESCRIPTION" +\fBWMFS\fR is a lightweight and highly configurable tiling window manager for X written in C\&. +.sp +.SH "OPTIONS" +.PP +\fB\-C \fR +.RS 4 +Load a configuration file\&. +.RE +.PP +\fB\-c \fR +.RS 4 +Execute an uicb function to control WMFS\&. +.RE +.PP +\fB\-v\fR +.RS 4 +Print version information to standard output, then exit\&. +.RE +.PP +\fB\-h\fR +.RS 4 +Print help information, then exit\&. +.RE +.SH "DEFAULT KEY BINDINGS" +.PP +\fBControl\-Alt + r\fR +.RS 4 +Reload WMFS binary +.RE +.PP +\fBSuper + Return\fR +.RS 4 +Run a terminal (urxvt by default) +.RE +.PP +\fBSuper + q\fR +.RS 4 +Quit the selected client +.RE +.PP +\fBControl\-Alt + q\fR +.RS 4 +Exit WMFS +.RE +.PP +\fBSuper + f \fR +.RS 4 +Toggle free the selected client +.RE +.PP +\fBAlt + Tab\fR +.RS 4 +Give the focus to the next client +.RE +.PP +\fBAlt\-Shift + Tab\fR +.RS 4 +Give the focus to the previous client +.RE +.PP +\fBAlt + h\fR +.RS 4 +Give the focus to the client on the left +.RE +.PP +\fBAlt + l\fR +.RS 4 +Give the focus to the client on the right +.RE +.PP +\fBAlt + k\fR +.RS 4 +Give the focus to the client on the top +.RE +.PP +\fBAlt + j\fR +.RS 4 +Give the focus to the client on the bottom +.RE +.PP +\fBSuper + Tab\fR +.RS 4 +Give the focus to the next tabbed client +.RE +.PP +\fBSuper\-Shift + Tab\fR +.RS 4 +Give the focus to the previous tabbed client +.RE +.PP +\fBControl\-Shift + h\fR +.RS 4 +Swap with the client on the left +.RE +.PP +\fBControl\-Shift + l\fR +.RS 4 +Swap with the client on the right +.RE +.PP +\fBControl\-Shift + k\fR +.RS 4 +Swap with the client on the top +.RE +.PP +\fBControl\-Shift + j\fR +.RS 4 +Swap with the client on the bottom +.RE +.PP +\fBAlt\-Shift + h\fR +.RS 4 +Tab in the client on the left +.RE +.PP +\fBAlt\-Shift + l\fR +.RS 4 +Tab in the client on the right +.RE +.PP +\fBAlt\-Shift + k\fR +.RS 4 +Tab in the client on the top +.RE +.PP +\fBAlt\-Shift + j\fR +.RS 4 +Tab in the client on the bottom +.RE +.PP +\fBAlt\-Shift + u\fR +.RS 4 +Untab the client +.RE +.PP +\fBSuper + h\fR +.RS 4 +Increase the client to the left +.RE +.PP +\fBSuper + l\fR +.RS 4 +Decrease the client from the left +.RE +.PP +\fBSuper + k\fR +.RS 4 +Increase the client to the top +.RE +.PP +\fBSuper + j\fR +.RS 4 +Decrease the client from the top +.RE +.PP +\fBSuper\-Control + h\fR +.RS 4 +Decrease the client from the right +.RE +.PP +\fBSuper\-Control + l\fR +.RS 4 +Increase the client to the right +.RE +.PP +\fBSuper\-Control + k\fR +.RS 4 +Decrease the client from the bottom +.RE +.PP +\fBSuper\-Control + j\fR +.RS 4 +Increase the client to the bottom +.RE +.PP +\fBControl + Right\fR +.RS 4 +Next tag +.RE +.PP +\fBControl + Left\fR +.RS 4 +Previous tag +.RE +.PP +\fBControl + Up\fR +.RS 4 +Next screen +.RE +.PP +\fBControl + Down\fR +.RS 4 +Previous screen +.RE +.PP +\fBSuper + m\fR +.RS 4 +Vertical mirror layout +.RE +.PP +\fBSuper\-Shift + m\fR +.RS 4 +Horizontal mirror layout +.RE +.PP +\fBSuper + r\fR +.RS 4 +Rotate layout right +.RE +.PP +\fBSuper\-Shift + r\fR +.RS 4 +Rotate layout left +.RE +.PP +\fBSuper\-Control\-Alt + h\fR +.RS 4 +Integrate client in left layout +.RE +.PP +\fBSuper\-Control\-Alt + j\fR +.RS 4 +Integrate client in bottom layout +.RE +.PP +\fBSuper\-Control\-Alt + k\fR +.RS 4 +Integrate client in top layout +.RE +.PP +\fBSuper\-Control\-Alt + l\fR +.RS 4 +Integrate client in right layout +.RE +.PP +\fBSuper + o\fR +.RS 4 +Restore previous layout +.RE +.PP +\fBSuper\-Shift + o\fR +.RS 4 +Restore next layout +.RE +.PP +\fBSuper + p\fR +.RS 4 +Make a launcher in the statusbar to run an unix command\fR +.RE +.PP +\fBSuper + F[1\&.\&.9]\fR +.RS 4 +Change tag view +.RE +.PP +\fBSuper\-Shift + F[1\&.\&.9]\fR +.RS 4 +Transfert the selected client to the wanted tag +.RE +.PP +\fBSuper + -\fR +.RS 4 +Delete current tag\fR +.RE +.PP +\fBSuper\-Shift + -\fR +.RS 4 +Add current tag\fR +.RE +.SH "CONFIGURATION" +WMFS is configured by \fI$HOME/\&.config/wmfs/wmfsrc\fR\&. +.RE +.PP +\fB\ include\fR +wmfsrc supports ”@include” to split configuration file by section\&. +.RS 2 +\fB\ Usage:\fR "@include ~/.config/wmfs/wmfs_themes"\&. +.RE +.PP +\fB\ [themes]\fR +wmfsrc supports themes for client and statusbar\&. +.RS 2 +\fB Misc\fR +.RS 2 +\fB\ name\fR +theme name: will be used in next sections\&. +.PP +\fB\ font\fR +theme font: in XLFD format\&. +.PP +.RE +\fB\ Bars\fR +.RS 2 +\fB\ bars_width\fR +bar height in pixels\&. +.PP +\fB\ bars_fg/bg\fR +statusbar text/background color\&. +.PP +.RE +\fB\ Tags\fR +.RS 2 +\fB\ tags_normal_fg/bg\fR +normal tag text/button color\&. +.PP +\fB\ tags_normal_statusline\fR +normal tag statusline\&. +.PP +\fB\ tags_sel_fg/bg\fR +selected tag text/button color\&. +.PP +\fB\ tags_sel_statusline\fR +selected tag statusline\&. +.PP +\fB\ tags_occupied_fg/bg\fR +occupied tag text/button color\&. +.PP +\fB\ tags_occupied_statusline\fR +occupied tag statusline\&. +.PP +\fB\ tags_urgent_fg/bg\fR +urgent tag text/button color\&. +.PP +\fB\ tags_urgent_statusline\fR +urgent tag statusline\&. +.PP +\fB\ tags_border_color\fR +tag button border color\&. +.PP +\fB\ tags_border_width\fR +tag button border width\&. +.PP +.RE +\fB\ Clients\fR +.RS 2 +\fB\ client_normal_fg/bg\fR +normal client titlebar text/background color\&. +.PP +\fB\ client_normal_statusline\fR +normal client statusline\&. +.PP +\fB\ client_sel_fg/bg\fR +selected client titlebar text/background color\&. +.PP +\fB\ client_sel_statusline\fR +selected client statusline\&. +.PP +\fB\ frame_bg\fR +client border color\&. +.PP +\fB\ client_titlebar_width\fR +client titlebar height in pixels\&. +.PP +\fB\ client_border_width\fR +client border height in pixels\&. +.RE +.PP +.RE +\fB\ [bars]\fR +.RS 2 +\fB\ position\fR +statusbar position on screen: 0=Top; 1=Bottom, 2=Hide\&. +.PP +\fB\ screen\fR +screen to display statusbar(start ar 0), set to\fB -1\fR to display on every screen\&. +.PP +\fB\ elements\fR +t=Tags, s=Statustext, y=Systray, l=Launcher\&. +.PP +\fB\ theme\fR +names of the statusbar theme\&. +.RE +.PP +.RE +\fB\ [tags]\fR +.RS 2 +\fB\ screen\fR +screen to display tag. use no screen option or screen =\fB -1\fR to set tag on each screen\&. +.PP +\fB\ name\fR +display tagname\&. +.PP +\fB\ statusline\fR +draw a custom statusline in the specific tag (can display any sequences)\&. +.PP +\fB\ mousebinds\fR +mouse actions on the tag buttons\&. +.RE +.PP +.RE +\fB\ [client]\fR +.RS 2 +\fB\ theme\fR +apply theme to client by default\&. +.PP +\fB\ key_modifier\fR +key modifier to perform actions on clients\&. +.PP +\fB\ mousebinds\fR +mouse actions on client\&. +.RE +.PP +.RE +\fB\ [rules]\fR +specific rules for clients: to identify an application, use xprop\&. +.RS 2 +\fB\ instance\fR +first part of WM_CLASS\&. +.PP +\fB\ class\fR +second part of WM_CLASS\&. +.PP +\fB\ role\fR +WM_WINDOW_ROLE\&. +.PP +\fB\ name\fR +_NET_WM_NAME\&. +.PP +\fB\ theme\fR +apply theme to client\&. +.PP +\fB\ tag\fR +set tag to client(start at 0)\&. +.PP +\fB\ screen\fR +display client on a specific screen\&. +.PP +\fB\ free\fR +client in auto-free mode (true/false)\&. +.PP +\fB\ tab\fR +open client in a tab (true/false)\&. +.RE +.PP +.RE +\fB\ [launchers]\fR +.RS 2 +\fB\ name\fR +launcher-name, will be used in the [keys] section\&. +.PP +\fB\ prompt\fR +display text at the beginning of the prompt\&. +.PP +\fB\ command\fR +command used by the launcher. can be an uicb function or an uicb function + extension\&. +.RE +.PP +.RE +\fB\ [keys]\fR +.RS 2 +each line is contained within\fB\ [key]...[/key]\fR +.PP +\fB\ mod\fR +key modifier (Alt, Control, Shift, Super)\&. +.PP +\fB\ key\fR +key to press\&. +.PP +\fB\ func\fR +uicb function to launch\&. +.PP +\fB\ cmd\fR +if\fB\ func = "spawn"\fR set the external command to launch\&. +.sp +.SH "STATUS" +statusbars, tags, surfaces and titlebars support sequences to display text, images bars and graphs through the\fB\ wmfs -c status\fR command. +.PP +\fB\ Syntax\fR +.PP +.RS 4 +\fB\ position:\fR “left/right” (relative) or “x;y” (absolute)\&. +.PP +\fB\ dimension:\fR “ww;hh” for width;height of the rectangle or the image, to display an image at its original size, set it to “0;0”\&. +.PP +\fB\ color:\fR ”#rrggbb”\&. +.PP +\fB\ imagepath:\fR absolute path for the image\&. +.PP +\fB\ border:\fR width of the progressbar border in pixels\&. +.PP +\fB\ curser:\fR width of the curser in the positionbar\&. +.PP +\fB\ value:\fR a variable, to draw progressbar\&. +.PP +\fB\ valuemax:\fR maximum value of the ‘value’ used in the progressbar\&. +.RE +.PP +\fB\ basic usage\fR +wmfs -c status " TEXT visible on 'barname'"\&. +.PP +\fB\ display colors\fR +wmfs -c status " ^s[;;]"\&. +.PP +\fB\ display rectangles\fR +wmfs -c status " ^R[;;]"\&. +.PP +\fB\ display images\fR +wmfs -c status " ^i[;;]"\&. +.PP +\fB\ display progressbars\fR +wmfs -c status " ^p[;;;;;;]"\&. +.PP +\fB\ display positionbars\fR +wmfs -c status " ^P[;;;;;;]"\&. +.PP +\fB\ display graph\fR +wmfs -c status " ^g[;;;;;;]"\&. +.RE +.PP +\fB\ mousebinds\fR +sequences supports mousebinds with format\fB\ (;)\fR or\fB\ (;;)\fR +.RE +.PP +\fB\ surfaces\fR +you can display popups from the statusbar with the mousebind\fB\ (;status_surface;,, )\fR +.PP +.sp +.SH "UICB Functions" +UICB functions list. for “User Interface Call Backs”\&. +.PP +\fB\ usage in the wmfsrc:\fR func = "tag_next"\fB\ or\fR func = "spawn" cmd = "urxvt -e vim"\&. +.RE +\fB\ usage in the status.sh:\fR wmfs -c status " ^s[;;next](1;tag_next)"\&. +.RE +\fB\ usage in your terminal:\fR wmfs -c tag_next\&. +.PP +\fB\ spawn\fR +launch a command. ex: func = "spawn" cmd = "urxvtc -e screen irssi"\&. +.PP +\fB\ quit\fR +quit wmfs\&. +.PP +\fB\ reload\fR +reload wmfs\&. +.PP +\fB\ tag_set\fR +set tag by number\&. +.PP +\fB\ tag\fR +set tag by name\&. +.PP +\fB\ tag_next/prev\fR +set next/previous tag\&. +.PP +\fB\ tag_client\fR +tag the client\&. +.PP +\fB\ tag_move_client_next/prev\fR +tag the client with next/previous tag\&. +.PP +\fB\ tag_click\fR +display tag with a clic on tag button\&. +.PP +\fB\ tag_new/del\fR +add/delete a tag\&. +.PP +\fB\ layout_vmirror\fR +vertical mirror tiling\&. +.PP +\fB\ layout_hmirror\fR +horizontal mirror tiling\&. +.PP +\fB\ layout_rotate_left\fR +tiling rotate anti/clockwise\&. +.PP +\fB\ layout_prev_set\fR +back to previous set layout\&. +.PP +\fB\ layout_next_set\fR +go to next set layout\&. +.PP +\fB\ layout_integrate_left/right/top/bottom\fR +client integration in the client zone by direction\&. +.PP +\fB\ client_close\fR +close the client\&. +.PP +\fB\ client_resize_right/left/top/bottom\fR +resize client with direction\&. +.PP +\fB\ client_focus_right/left/top/bottom\fR +focus client with direction\&. +.PP +\fB\ client_tab_right/left/top/bottom\fR +tab client with direction\&. +.PP +\fB\ client_swap_right/left/top/bottom\fR +swap client with direction\&. +.PP +\fB\ client_focus_next/prev\fR +move focus to the next/previous client\&. +.PP +\fB\ client_swap_next/prev\fR +swap with the next/previous client\&. +.PP +\fB\ client_untab\fR +untab the client\&. +.PP +\fB\ client_focus_next_tab\fR +move focus to next tab-client\&. +.PP +\fB\ client_focus_prev_tab\fR +move focus to previous tab-client\&. +.PP +\fB\ client_focus_click\fR +give focus to client with a clic\&. +.PP +\fB\ client_toggle_free\fR +togle free the client\&. +.PP +\fB\ client_tab_next_opened\fR +open the client in a tab\&. +.PP +\fB\ status\fR +display the argument text in the statusbar\&. +.PP +\fB\ status_surface\fR +display a surface. can contain sequences\&. +.PP +\fB\ mouse_resize\fR +resize the client\&. +.PP +\fB\ mouse_move\fR +move the client\&. +.PP +\fB\ mouse_swap\fR +swap the client\&. +.PP +\fB\ mouse_tab\fR +tab the client\&. +.PP +\fB\ screen_next/prev\fR +go to next/previous screen\&. +.PP +\fB\ screen_move_client_next/prev\fR +move the client to next/previous screen\&. +.PP +\fB\ launcher\fR +native prompt. ex:\fB\ func = "launcher" cmd = "exec"\fR display the “exec” launcher\&. +.RE +.PP +.sp +.SH "BUGS" +WMFS isn\'t stable for now\&. So it certainly contains some bugs\&. +.sp +.SH "AUTHORS" +Martin Duquesnoy <\fIxorg62@gmail\&.com\fR\&[1]>\&. +.sp +.SH "WWW" +Main site: \fIhttps://github\&.com/xorg62/wmfs\fR +.PP +Wiki: \fIhttps://github\&.com/xorg62/wmfs/wiki\fR +.PP +Bug tracker: \fIhttps://github\&.com/xorg62/wmfs/issues\fR +.sp +.SH "COPYING" +WMFS is under the BSD license\&. See COPYING for more information\&. +.sp +.SH "NOTES" +.IP " 1." 4 +xorg62@gmail.com +.RS 4 +\%mailto:xorg62@gmail.com +.RE diff --git a/wmfsrc b/wmfsrc index 5bc139c..f43cf57 100644 --- a/wmfsrc +++ b/wmfsrc @@ -30,7 +30,7 @@ tags_occupied_fg = "#AABBAA" tags_occupied_bg = "#445544" - tags_occupied_statusline = "\R[0;0;3;3;#AABBAA]" + tags_occupied_statusline = "\R[0;0;100;1;#AABBAA]" tags_urgent_fg = "#223322" tags_urgent_bg = "#CC5544" @@ -93,6 +93,7 @@ [tag] screen = -1 name = "1" + # statusline="" [/tag] [tag] name = "2" [/tag] @@ -137,7 +138,7 @@ screen = 0 free = false - max = false + tab = false ignore_tag = false [/rule] @@ -185,6 +186,9 @@ [key] mod = {"Super", "Shift"} key = "F7" func = "tag_client" cmd = "6" [/key] [key] mod = {"Super", "Shift"} key = "F8" func = "tag_client" cmd = "7" [/key] + [key] mod = {"Super"} key = "minus" func = "tag_del" [/key] + [key] mod = {"Super", "Shift"} key = "minus" func = "tag_new" [/key] + # tag function: cmd = nameofthetag #[key] mod = {"Super"} key = "z" func = "tag" cmd = "2" [/key] @@ -230,6 +234,7 @@ [key] mod = {"Alt", "Shift"} key = "k" func = "client_tab_top" [/key] [key] mod = {"Alt", "Shift"} key = "j" func = "client_tab_bottom" [/key] [key] mod = {"Alt", "Shift"} key = "u" func = "client_untab" [/key] + [key] mod = {"Super"} key = "t" func = "client_tab_next_opened" [/key] # Layout manipulation [key] mod = {"Super"} key = "m" func = "layout_vmirror" [/key]