Branch for wmfs2
This commit is contained in:
parent
c03f051f3a
commit
4418cf6bbb
68
Makefile.in
Normal file
68
Makefile.in
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
PROG=wmfs
|
||||||
|
|
||||||
|
# wmfs version
|
||||||
|
VERSION=$(shell scripts/setlocalversion)
|
||||||
|
|
||||||
|
SRCS= \
|
||||||
|
src/barwin.c \
|
||||||
|
src/config.c \
|
||||||
|
src/client.c \
|
||||||
|
src/event.c \
|
||||||
|
src/ewmh.c \
|
||||||
|
src/infobar.c \
|
||||||
|
src/layout.c \
|
||||||
|
src/parse_api.c \
|
||||||
|
src/parse.c \
|
||||||
|
src/screen.c \
|
||||||
|
src/tag.c \
|
||||||
|
src/util.c \
|
||||||
|
src/wmfs.c
|
||||||
|
|
||||||
|
|
||||||
|
# flags
|
||||||
|
CFLAGS+= -DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\"
|
||||||
|
CFLAGS+= -DWMFS_VERSION=\"${VERSION}\"
|
||||||
|
CFLAGS+= -Wall -Wextra
|
||||||
|
|
||||||
|
OBJS= ${SRCS:.c=.o}
|
||||||
|
|
||||||
|
all: ${PROG}
|
||||||
|
|
||||||
|
${PROG}: ${OBJS}
|
||||||
|
${CC} -o $@ ${OBJS} ${LDFLAGS}
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} -c ${CFLAGS} $< -o $@
|
||||||
|
|
||||||
|
.PHONY: all clean distclean install uninstall dist
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f ${OBJS} wmfs
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -f Makefile
|
||||||
|
|
||||||
|
install: all
|
||||||
|
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
|
install ${PROG} ${DESTDIR}${PREFIX}/bin
|
||||||
|
@echo installing xsession file to ${DESTDIR}${PREFIX}/share/xsessions
|
||||||
|
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
|
||||||
|
install -m 644 wmfs.desktop ${DESTDIR}${PREFIX}/share/xsessions/
|
||||||
|
@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/
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/bin/wmfs
|
||||||
|
@echo removing xsession file from ${DESTDIR}${PREFIX}/share/xsessions
|
||||||
|
rm -f ${DESTDIR}${PREFIX}/share/xsessions/wmfs.desktop
|
||||||
|
@echo removing config file from ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
|
||||||
|
rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc
|
||||||
|
rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
|
||||||
|
|
||||||
|
dist:
|
||||||
|
@echo "Generate wmfs-`date +%Y%m`.tar.gz"
|
||||||
|
git archive --format=tar --prefix=wmfs-`date +%Y%m`/ master | gzip -c > wmfs-`date +%Y%m`.tar.gz
|
||||||
|
|
||||||
91
configure
vendored
Executable file
91
configure
vendored
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
LIBS="x11"
|
||||||
|
USE_XINERAMA="xinerama"
|
||||||
|
USE_XRANDR="xrandr"
|
||||||
|
USE_IMLIB2="imlib2"
|
||||||
|
USE_XFT="xft freetype2"
|
||||||
|
OS=`uname -s`
|
||||||
|
PREFIX=/usr/local
|
||||||
|
MANPREFIX="$PREFIX/man"
|
||||||
|
XDG_CONFIG_DIR="$PREFIX/etc/xdg"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
--without-xinerama)
|
||||||
|
USE_XINERAMA=""; shift;;
|
||||||
|
--prefix)
|
||||||
|
[ -z "$2" ] && echo "Missing argument" && exit 1
|
||||||
|
PREFIX=$2; shift 2;;
|
||||||
|
--xdg-config-dir)
|
||||||
|
[ -z "$2" ] && echo "Missing argument" && exit 1
|
||||||
|
XDG_CONFIG_DIR=$2; shift 2;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: ./configure [options]
|
||||||
|
--without-xinerama : compile without xinerama support
|
||||||
|
--prefix DIRECTORY : install binary with specified prefix (default $PREFIX)
|
||||||
|
--xdg-config-dir DIRECTORY : install configuration to specified directory (default $XDG_CONFIG_DIR)"
|
||||||
|
exit 0;;
|
||||||
|
*) break;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
LIBS="$LIBS $USE_XINERAMA"
|
||||||
|
|
||||||
|
which pkg-config >/dev/null 2>&1
|
||||||
|
|
||||||
|
if [ $? -eq 0 ];
|
||||||
|
then
|
||||||
|
CFLAGS=`pkg-config --cflags-only-I $LIBS`
|
||||||
|
LDFLAGS=`pkg-config --libs $LIBS`
|
||||||
|
else
|
||||||
|
# Try to use some known paths
|
||||||
|
case $OS in
|
||||||
|
FreeBSD)
|
||||||
|
CFLAGS="-I/usr/local/include"
|
||||||
|
LDFLAGS="-L/usr/local/lib";;
|
||||||
|
OpenBSD)
|
||||||
|
CFLAGS="-I/usr/X11R6/include -I/usr/local/include"
|
||||||
|
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
|
||||||
|
NetBSD)
|
||||||
|
CFLAGS="-I/usr/X11R7/include -I/usr/local/include"
|
||||||
|
LDFLAGS="-L/usr/X11R7/lib -L/usr/local/lib";;
|
||||||
|
Linux)
|
||||||
|
CFLAGS=""
|
||||||
|
LDFLAGS=""
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "No default CFLAGS and LDFLAGS found for your OS, feel free to contribute or install pkg-config :)"
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
LDFLAGS="$LDFLAGS -lX11"
|
||||||
|
|
||||||
|
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
|
||||||
|
|
||||||
|
cat > Makefile << EOF
|
||||||
|
PREFIX=$PREFIX
|
||||||
|
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
|
||||||
|
MANPREFIX=$MANPREFIX
|
||||||
|
|
||||||
|
CFLAGS+=$CFLAGS
|
||||||
|
LDFLAGS+=$LDFLAGS
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat Makefile.in >> Makefile
|
||||||
|
|
||||||
|
echo "Compilation resume:
|
||||||
|
OS=$OS
|
||||||
|
CFLAGS=$CFLAGS
|
||||||
|
LDFLAGS=$LDFLAGS
|
||||||
|
PREFIX=$PREFIX
|
||||||
|
MANPREFIX=$MANPREFIX
|
||||||
|
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
|
||||||
|
|
||||||
|
You can run 'make' now :-)
|
||||||
|
"
|
||||||
272
hftsniff.c
272
hftsniff.c
@ -1,272 +0,0 @@
|
|||||||
/******
|
|
||||||
* HFTSniff simple sniffer using pcap
|
|
||||||
* xorg62@gmail.com
|
|
||||||
******/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <pcap.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/if_ether.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
/* Macros */
|
|
||||||
#define LEN(x) (sizeof(x) / sizeof(*x))
|
|
||||||
|
|
||||||
/* Using ANSI escape codes to use bold in simple text mode */
|
|
||||||
#define IP_SRCDEST(src, psrc, dest, pdest) \
|
|
||||||
do { \
|
|
||||||
printf("%s:\e[1m%d\e[0m ==> %s:\e[1m%d\e[0m\n", \
|
|
||||||
src, psrc, dest, pdest); \
|
|
||||||
} while(/* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
#define DISP_PROTO(s) \
|
|
||||||
do { \
|
|
||||||
printf("( \e[1m%s\e[0m ) ", s); \
|
|
||||||
} while(/* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
#define DISP_PAYLOAD(p, l) \
|
|
||||||
do { \
|
|
||||||
int i = 0; \
|
|
||||||
for(; i < (l) && (p); ++i, ++(p)) \
|
|
||||||
if(isprint(*(p))) \
|
|
||||||
putchar((char)*(p)); \
|
|
||||||
} while(/* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
#define BYE(s, er) \
|
|
||||||
do { \
|
|
||||||
fprintf(stderr, s": (%s)\n", er); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
} while(/* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
#define PKT_ERROR(r, s, a) \
|
|
||||||
do { \
|
|
||||||
fprintf(stderr, " PKT_ERROR: %s (%u)\n", s, a); \
|
|
||||||
return r; \
|
|
||||||
} while(/* CONSTCOND */ 0); \
|
|
||||||
|
|
||||||
/* Option const */
|
|
||||||
#define FILTER "ip"
|
|
||||||
#define TIMEOUT (10)
|
|
||||||
#define SNAPLEN (SHRT_MAX)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ethernet packet format
|
|
||||||
*/
|
|
||||||
#define ETHERNET_SIZE (14)
|
|
||||||
#define ETHERNET_ALEN (6)
|
|
||||||
|
|
||||||
struct ethernet_header
|
|
||||||
{
|
|
||||||
unsigned char ether_dhost[ETHERNET_ALEN]; /* Destination ethernet address */
|
|
||||||
unsigned char ether_shost[ETHERNET_ALEN]; /* Source ethernet adress */
|
|
||||||
unsigned short ether_type; /* Packet type, id field */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ip packet format (tcpdump way)
|
|
||||||
*/
|
|
||||||
#define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
|
|
||||||
#define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
|
|
||||||
|
|
||||||
#define IP_DF (0x4000) /* Dont fragment flag */
|
|
||||||
#define IP_MF (0x2000) /* More fragments flag */
|
|
||||||
#define IP_OFFMASK (0x1fff) /* Mask for fragmenting bits */
|
|
||||||
|
|
||||||
struct ip_header
|
|
||||||
{
|
|
||||||
unsigned char ip_vhl; /* Header length, version */
|
|
||||||
unsigned char ip_tos; /* Type of service */
|
|
||||||
unsigned short ip_len; /* Total length */
|
|
||||||
unsigned short ip_id; /* Identification */
|
|
||||||
unsigned short ip_off; /* Fragment offset field */
|
|
||||||
unsigned char ip_ttl; /* Time to live */
|
|
||||||
unsigned char ip_p; /* Protocol */
|
|
||||||
unsigned short ip_sum; /* Checksum */
|
|
||||||
struct in_addr ip_src, ip_dst; /* Source and dest address */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TCP packet format
|
|
||||||
*/
|
|
||||||
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
|
|
||||||
|
|
||||||
#define TH_FIN (0x01)
|
|
||||||
#define TH_SYN (0x02)
|
|
||||||
#define TH_RST (0x04)
|
|
||||||
#define TH_PUSH (0x08)
|
|
||||||
#define TH_ACK (0x10)
|
|
||||||
#define TH_URG (0x20)
|
|
||||||
#define TH_ECE (0x40)
|
|
||||||
#define TH_CWR (0x80)
|
|
||||||
#define TH_FLAGS (0xf7) /* TH_* */
|
|
||||||
|
|
||||||
struct tcp_header
|
|
||||||
{
|
|
||||||
unsigned short th_sport; /* Source port */
|
|
||||||
unsigned short th_dport; /* Destination port */
|
|
||||||
unsigned int th_seq; /* Sequence number */
|
|
||||||
unsigned int th_ack; /* Acknowledgement number */
|
|
||||||
unsigned char th_offx2; /* Data offset, rsvd */
|
|
||||||
unsigned char th_flags; /* Flags bitfield */
|
|
||||||
unsigned short th_win; /* Window */
|
|
||||||
unsigned short th_sum; /* Checksum */
|
|
||||||
unsigned short th_urp; /* Urgent pointer */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Function protos */
|
|
||||||
int pkt_tcp_handle(void *, void *);
|
|
||||||
|
|
||||||
|
|
||||||
/* Usefull things */
|
|
||||||
const struct
|
|
||||||
{
|
|
||||||
unsigned int p;
|
|
||||||
int (*f)(void *, void*);
|
|
||||||
char name[32];
|
|
||||||
} protos[] =
|
|
||||||
{
|
|
||||||
{ IPPROTO_IP, NULL, "IP" }, /* _IP 0 */
|
|
||||||
{ IPPROTO_ICMP, NULL, "ICMP" }, /* _ICMP 1 */
|
|
||||||
{ IPPROTO_TCP, pkt_tcp_handle, "TCP" }, /* _TCP 6 */
|
|
||||||
{ IPPROTO_UDP, NULL, "UDP" }, /* _UDP 17 */
|
|
||||||
{ -1, NULL, ""}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* As defined in man: */
|
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle TCP packets
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkt_tcp_handle(void *pkt, void *prev_pkt)
|
|
||||||
{
|
|
||||||
const struct tcp_header *tcp;
|
|
||||||
const struct ip_header *ip;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
ip = (struct ip_header*)prev_pkt;
|
|
||||||
tcp = (struct tcp_header*)(pkt + ETHERNET_SIZE + (IP_HL(ip) << 2));
|
|
||||||
|
|
||||||
if((len = TH_OFF(tcp) << 2) < 20)
|
|
||||||
PKT_ERROR(0, "Invalid IP header length:", len);
|
|
||||||
|
|
||||||
IP_SRCDEST(inet_ntoa(ip->ip_src), ntohs(tcp->th_sport), /* src */
|
|
||||||
inet_ntoa(ip->ip_dst), ntohs(tcp->th_dport)); /* dest */
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle every packet, point it to corresponding pkt_proto_handle
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pkt_handle(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet)
|
|
||||||
{
|
|
||||||
struct ethernet_header *eth;
|
|
||||||
struct ip_header *ip;
|
|
||||||
const unsigned char *payload;
|
|
||||||
int len, plen, paylen, i = 0;
|
|
||||||
bool pfound = false;
|
|
||||||
|
|
||||||
/* Translate ethernet pkt */
|
|
||||||
eth = (struct ethernet_header*)packet;
|
|
||||||
|
|
||||||
/* Translate ip pkt */
|
|
||||||
ip = (struct ip_header*)(packet + ETHERNET_SIZE);
|
|
||||||
|
|
||||||
/* Check ipv4 */
|
|
||||||
if((len = IP_HL(ip) << 2) < 20)
|
|
||||||
PKT_ERROR(, "Invalid IP header length:", len);
|
|
||||||
|
|
||||||
/* Protocol */
|
|
||||||
for(; i < LEN(protos); ++i)
|
|
||||||
if(ip->ip_p == protos[i].p)
|
|
||||||
{
|
|
||||||
DISP_PROTO(protos[i].name);
|
|
||||||
|
|
||||||
if(protos[i].f)
|
|
||||||
plen = protos[i].f((void*)packet, (void*)ip);
|
|
||||||
|
|
||||||
pfound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unknown protocol */
|
|
||||||
if(!pfound)
|
|
||||||
{
|
|
||||||
DISP_PROTO("unknown");
|
|
||||||
IP_SRCDEST(inet_ntoa(ip->ip_src), -1, /* src */
|
|
||||||
inet_ntoa(ip->ip_dst), -1); /* dest */
|
|
||||||
|
|
||||||
|
|
||||||
puts("\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get / Display payload */
|
|
||||||
payload = (unsigned char*)(packet + ETHERNET_SIZE + len + plen);
|
|
||||||
|
|
||||||
if((paylen = ntohs(ip->ip_len) - (len + plen)) > 0)
|
|
||||||
DISP_PAYLOAD(payload, paylen);
|
|
||||||
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *dev;
|
|
||||||
bpf_u_int32 mask;
|
|
||||||
bpf_u_int32 netip;
|
|
||||||
pcap_t *descr;
|
|
||||||
struct bpf_program bpf;
|
|
||||||
|
|
||||||
if(argc < 2)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s usage: %s <interface>\n", argv[0], argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find adress & mask */
|
|
||||||
if(pcap_lookupnet(argv[1], &netip, &mask, errbuf) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't find Adress or Mask: (%s)\n", errbuf);
|
|
||||||
netip = mask = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open device and reaaad */
|
|
||||||
if(!(descr = pcap_open_live(argv[1], SNAPLEN, true, TIMEOUT, errbuf)))
|
|
||||||
BYE("Fail at opening and reading device", errbuf);
|
|
||||||
|
|
||||||
/* Check if packet is from ethernet device */
|
|
||||||
if(pcap_datalink(descr) != DLT_EN10MB)
|
|
||||||
BYE("Device is not an Ethernet", dev);
|
|
||||||
|
|
||||||
/* Parse & set pcap with option expression */
|
|
||||||
if(pcap_compile(descr, &bpf, FILTER, 0, netip) < 0)
|
|
||||||
BYE("Option parse error", pcap_geterr(descr));
|
|
||||||
|
|
||||||
if(pcap_setfilter(descr, &bpf) < 0)
|
|
||||||
BYE("Can't use option", pcap_geterr(descr));
|
|
||||||
|
|
||||||
printf("%d\n", 1<<1);
|
|
||||||
pcap_loop(descr, 10, pkt_handle, NULL);
|
|
||||||
|
|
||||||
pcap_freecode(&bpf);
|
|
||||||
pcap_close(descr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
75
scripts/setlocalversion
Executable file
75
scripts/setlocalversion
Executable file
@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Print additional version information for non-release trees.
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 [srctree]" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd "${1:-.}" || usage
|
||||||
|
|
||||||
|
# Check for git and a git repo.
|
||||||
|
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
|
||||||
|
# Do we have an untagged version?
|
||||||
|
if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
|
||||||
|
if tag=`git describe 2>/dev/null`; then
|
||||||
|
echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
|
||||||
|
else
|
||||||
|
printf '%s%s' -g $head
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Is this git on svn?
|
||||||
|
if git config --get svn-remote.svn.url >/dev/null; then
|
||||||
|
printf -- '-svn%s' "`git svn find-rev $head`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Are there uncommitted changes?
|
||||||
|
git update-index --refresh --unmerged > /dev/null
|
||||||
|
if git diff-index --name-only HEAD | grep -v "^scripts/package" \
|
||||||
|
| read dummy; then
|
||||||
|
printf '%s' -dirty
|
||||||
|
fi
|
||||||
|
|
||||||
|
# All done with git
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for mercurial and a mercurial repo.
|
||||||
|
if hgid=`hg id 2>/dev/null`; then
|
||||||
|
tag=`printf '%s' "$hgid" | cut -d' ' -f2`
|
||||||
|
|
||||||
|
# Do we have an untagged version?
|
||||||
|
if [ -z "$tag" -o "$tag" = tip ]; then
|
||||||
|
id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
|
||||||
|
printf '%s%s' -hg "$id"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Are there uncommitted changes?
|
||||||
|
# These are represented by + after the changeset id.
|
||||||
|
case "$hgid" in
|
||||||
|
*+|*+\ *) printf '%s' -dirty ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# All done with mercurial
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for svn and a svn repo.
|
||||||
|
if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
|
||||||
|
rev=`echo $rev | awk '{print $NF}'`
|
||||||
|
changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
|
||||||
|
|
||||||
|
# Are there uncommitted changes?
|
||||||
|
if [ $changes != 0 ]; then
|
||||||
|
printf -- '-svn%s%s' "$rev" -dirty
|
||||||
|
else
|
||||||
|
printf -- '-svn%s' "$rev"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# All done with svn
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# default version
|
||||||
|
printf -- '-%s' "`date +%Y%m`"
|
||||||
11
scripts/status.sh
Executable file
11
scripts/status.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#WMFS status.sh example file
|
||||||
|
#Will be executed if put in ~/.config/wmfs/
|
||||||
|
#Timing adjustable in wmfsrc (misc -> status_timing)
|
||||||
|
|
||||||
|
statustext()
|
||||||
|
{
|
||||||
|
wmfs -s "`date`"
|
||||||
|
}
|
||||||
|
|
||||||
|
while true; do statustext; sleep 10; done
|
||||||
@ -1 +0,0 @@
|
|||||||
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "barwin.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/** Create a barwin
|
|
||||||
* \param parent Parent window of the BarWindow
|
|
||||||
* \param x X position
|
|
||||||
* \param y Y position
|
|
||||||
* \param w barwin Width
|
|
||||||
* \param h barwin Height
|
|
||||||
* \param color barwin color
|
|
||||||
* \param entermask bool for know if the EnterMask mask is needed
|
|
||||||
* \return The BarWindow pointer
|
|
||||||
*/
|
|
||||||
struct barwin*
|
|
||||||
barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool entermask)
|
|
||||||
{
|
|
||||||
struct barwin *b = (struct barwin*)xcalloc(1, sizeof(struct barwin));
|
|
||||||
XSetWindowAttributes at =
|
|
||||||
{
|
|
||||||
.override_redirect = True,
|
|
||||||
.background_pixmap = ParentRelative,
|
|
||||||
.event_mask = BARWIN_MASK
|
|
||||||
};
|
|
||||||
|
|
||||||
if(entermask)
|
|
||||||
at.event_mask |= BARWIN_ENTERMASK;
|
|
||||||
|
|
||||||
/* Create window */
|
|
||||||
b->win = XCreateWindow(W->dpy, parent,
|
|
||||||
x, y, w, h,
|
|
||||||
0, W->xdepth,
|
|
||||||
CopyFromParent,
|
|
||||||
DefaultVisual(W->dpy, W->xscreen),
|
|
||||||
BARWIN_WINCW,
|
|
||||||
&at);
|
|
||||||
|
|
||||||
b->dr = XCreatePixmap(W->dpy, parent, w, h, W->xdepth);
|
|
||||||
|
|
||||||
/* Property */
|
|
||||||
b->geo.x = x;
|
|
||||||
b->geo.y = y;
|
|
||||||
b->geo.w = w;
|
|
||||||
b->geo.h = h;
|
|
||||||
b->bg = bg;
|
|
||||||
b->fg = fg;
|
|
||||||
|
|
||||||
SLIST_INIT(&b->mousebinds);
|
|
||||||
|
|
||||||
/* Attach */
|
|
||||||
SLIST_INSERT_HEAD(&W->h.barwin, b, next);
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a barwin
|
|
||||||
* \param bw barwin pointer
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
barwin_remove(struct barwin *b)
|
|
||||||
{
|
|
||||||
SLIST_REMOVE(&W->h.barwin, b, barwin, next);
|
|
||||||
|
|
||||||
XSelectInput(W->dpy, b->win, NoEventMask);
|
|
||||||
XDestroyWindow(W->dpy, b->win);
|
|
||||||
XFreePixmap(W->dpy, b->dr);
|
|
||||||
|
|
||||||
/* Free mousebinds */
|
|
||||||
FREE_LIST(mousebind, b->mousebinds);
|
|
||||||
|
|
||||||
free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Resize a barwin
|
|
||||||
* \param bw barwin pointer
|
|
||||||
* \param w Width
|
|
||||||
* \param h Height
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
barwin_resize(struct barwin *b, int w, int h)
|
|
||||||
{
|
|
||||||
/* Frame */
|
|
||||||
XFreePixmap(W->dpy, b->dr);
|
|
||||||
|
|
||||||
b->dr = XCreatePixmap(W->dpy, W->root, w, h, W->xdepth);
|
|
||||||
|
|
||||||
b->geo.w = w;
|
|
||||||
b->geo.h = h;
|
|
||||||
|
|
||||||
XResizeWindow(W->dpy, b->win, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
barwin_mousebind_new(struct barwin *b, unsigned int button, bool u, struct geo a, void (*func)(Uicb), Uicb cmd)
|
|
||||||
{
|
|
||||||
struct mousebind *m = (struct mousebind*)xcalloc(1, sizeof(struct mousebind));
|
|
||||||
|
|
||||||
m->button = button;
|
|
||||||
m->use_area = u;
|
|
||||||
m->area = a;
|
|
||||||
m->func = func;
|
|
||||||
|
|
||||||
m->cmd = (cmd ? xstrdup(cmd) : NULL);
|
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(&b->mousebinds, m, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Refresh the barwin Color
|
|
||||||
* \param bw barwin pointer
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
barwin_refresh_color(struct barwin *b)
|
|
||||||
{
|
|
||||||
XSetForeground(W->dpy, W->gc, b->bg);
|
|
||||||
XFillRectangle(W->dpy, b->dr, W->gc, 0, 0, b->geo.w, b->geo.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BARWIN_H
|
|
||||||
#define BARWIN_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
#define BARWIN_MASK \
|
|
||||||
(SubstructureRedirectMask | SubstructureNotifyMask \
|
|
||||||
| ButtonMask | MouseMask | ExposureMask | VisibilityChangeMask \
|
|
||||||
| StructureNotifyMask | SubstructureRedirectMask)
|
|
||||||
|
|
||||||
#define BARWIN_ENTERMASK (EnterWindowMask | LeaveWindowMask | FocusChangeMask)
|
|
||||||
#define BARWIN_WINCW (CWOverrideRedirect | CWBackPixmap | CWEventMask)
|
|
||||||
|
|
||||||
#define barwin_delete_subwin(b) XDestroySubwindows(W->dpy, b->win)
|
|
||||||
#define barwin_map_subwin(b) XMapSubwindows(W->dpy, b->win)
|
|
||||||
#define barwin_unmap_subwin(b) XUnmapSubwindows(W->dpy, b->win)
|
|
||||||
#define barwin_refresh(b) XCopyArea(W->dpy, b->dr, b->win, W->gc, 0, 0, b->geo.w, b->geo.h, 0, 0)
|
|
||||||
#define barwin_map(b) XMapWindow(W->dpy, b->win);
|
|
||||||
#define barwin_unmap(b) XUnmapWindow(W->dpy, b->win);
|
|
||||||
|
|
||||||
struct barwin* barwin_new(Window parent, int x, int y, int w, int h, Color fg, Color bg, bool entermask);
|
|
||||||
void barwin_remove(struct barwin *b);
|
|
||||||
void barwin_resize(struct barwin *b, int w, int h);
|
|
||||||
void barwin_mousebind_new(struct barwin *b, unsigned int button, bool u, struct geo a, void (*func)(Uicb), Uicb cmd);
|
|
||||||
void barwin_refresh_color(struct barwin *b);
|
|
||||||
|
|
||||||
#endif /* BARWIN_H */
|
|
||||||
@ -1,430 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "barwin.h"
|
|
||||||
#include "ewmh.h"
|
|
||||||
#include "layout.h"
|
|
||||||
#include "draw.h"
|
|
||||||
|
|
||||||
#define CLIENT_MOUSE_MOD Mod1Mask
|
|
||||||
|
|
||||||
#define CLIENT_RESIZE_DIR(D) \
|
|
||||||
void uicb_client_resize_##D(Uicb cmd) \
|
|
||||||
{ \
|
|
||||||
if(W->client) \
|
|
||||||
client_fac_resize(W->client, D, ATOI(cmd)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CLIENT_ACTION_DIR(A, D) \
|
|
||||||
void uicb_client_##A##_##D(Uicb cmd) \
|
|
||||||
{ \
|
|
||||||
(void)cmd; \
|
|
||||||
struct client *c; \
|
|
||||||
if(W->client && (c = client_next_with_pos(W->client, D))) \
|
|
||||||
client_##A(c); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CLIENT_ACTION_LIST(A, L) \
|
|
||||||
void uicb_client_##A##_##L(Uicb cmd) \
|
|
||||||
{ \
|
|
||||||
(void)cmd; \
|
|
||||||
struct client *c; \
|
|
||||||
if(W->client && (c = client_##L(W->client))) \
|
|
||||||
client_##A(c); \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* uicb_client_resize_dir() */
|
|
||||||
CLIENT_RESIZE_DIR(Right)
|
|
||||||
CLIENT_RESIZE_DIR(Left)
|
|
||||||
CLIENT_RESIZE_DIR(Top)
|
|
||||||
CLIENT_RESIZE_DIR(Bottom)
|
|
||||||
|
|
||||||
/* uicb_client_focus_dir() */
|
|
||||||
CLIENT_ACTION_DIR(focus, Right)
|
|
||||||
CLIENT_ACTION_DIR(focus, Left)
|
|
||||||
CLIENT_ACTION_DIR(focus, Top)
|
|
||||||
CLIENT_ACTION_DIR(focus, Bottom)
|
|
||||||
|
|
||||||
/* uicb_client_swapsel_dir() */
|
|
||||||
#define client_swapsel(c) client_swap(W->client, c)
|
|
||||||
CLIENT_ACTION_DIR(swapsel, Right)
|
|
||||||
CLIENT_ACTION_DIR(swapsel, Left)
|
|
||||||
CLIENT_ACTION_DIR(swapsel, Top)
|
|
||||||
CLIENT_ACTION_DIR(swapsel, Bottom)
|
|
||||||
|
|
||||||
/* uicb_client_focus_next/prev() */
|
|
||||||
CLIENT_ACTION_LIST(focus, next)
|
|
||||||
CLIENT_ACTION_LIST(focus, prev)
|
|
||||||
|
|
||||||
/* uicb_client_swapsel_next/prev() */
|
|
||||||
CLIENT_ACTION_LIST(swapsel, next)
|
|
||||||
CLIENT_ACTION_LIST(swapsel, prev)
|
|
||||||
|
|
||||||
/** Send a ConfigureRequest event to the struct client
|
|
||||||
* \param c struct client pointer
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
client_configure(struct client *c)
|
|
||||||
{
|
|
||||||
XConfigureEvent ev =
|
|
||||||
{
|
|
||||||
.type = ConfigureNotify,
|
|
||||||
.event = c->win,
|
|
||||||
.window = c->win,
|
|
||||||
.x = c->geo.x,
|
|
||||||
.y = c->geo.y,
|
|
||||||
.width = c->geo.w,
|
|
||||||
.height = c->geo.h,
|
|
||||||
.above = None,
|
|
||||||
.border_width = 0,
|
|
||||||
.override_redirect = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
XSendEvent(W->dpy, c->win, False, StructureNotifyMask, (XEvent *)&ev);
|
|
||||||
XSync(W->dpy, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct client*
|
|
||||||
client_gb_win(Window w)
|
|
||||||
{
|
|
||||||
struct client *c = SLIST_FIRST(&W->h.client);
|
|
||||||
|
|
||||||
while(c && c->win != w)
|
|
||||||
c = SLIST_NEXT(c, next);
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline struct client*
|
|
||||||
client_gb_pos(struct tag *t, int x, int y)
|
|
||||||
{
|
|
||||||
struct client *c = SLIST_FIRST(&t->clients);
|
|
||||||
|
|
||||||
while(c)
|
|
||||||
{
|
|
||||||
if(INAREA(x, y, c->geo))
|
|
||||||
return c;
|
|
||||||
|
|
||||||
c = SLIST_NEXT(c, tnext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get client left/right/top/bottom of selected client
|
|
||||||
*\param bc Base client
|
|
||||||
*\param pos Position
|
|
||||||
*\return Client found or NULL
|
|
||||||
*/
|
|
||||||
struct client*
|
|
||||||
client_next_with_pos(struct client *bc, Position p)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
int x, y;
|
|
||||||
const static char scanfac[PositionLast] = { +10, -10, 0, 0 };
|
|
||||||
Position ip = Bottom - p;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set start place of pointer (edge with position
|
|
||||||
* of base client) for faster scanning.
|
|
||||||
*/
|
|
||||||
x = bc->geo.x + ((p == Right) ? bc->geo.w : 0);
|
|
||||||
y = bc->geo.y + ((p == Bottom) ? bc->geo.h : 0);
|
|
||||||
y += ((LDIR(p)) ? (bc->geo.h >> 1) : 0);
|
|
||||||
x += ((p > Left) ? (bc->geo.w >> 1) : 0);
|
|
||||||
|
|
||||||
/* Scan in right direction to next(p) physical client */
|
|
||||||
while((c = client_gb_pos(bc->tag, x, y)) == bc)
|
|
||||||
{
|
|
||||||
x += scanfac[p];
|
|
||||||
y += scanfac[ip];
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_swap(struct client *c1, struct client *c2)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
struct geo g;
|
|
||||||
|
|
||||||
if(c1 == c2 || !c1 || !c2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
t = c1->tag;
|
|
||||||
g = c1->geo;
|
|
||||||
|
|
||||||
swap_ptr((void**)&c1->screen, (void**)&c2->screen);
|
|
||||||
|
|
||||||
tag_client(c2->tag, c1);
|
|
||||||
tag_client(t, c2);
|
|
||||||
|
|
||||||
client_moveresize(c1, c2->geo);
|
|
||||||
client_moveresize(c2, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
client_grabbuttons(struct client *c, bool focused)
|
|
||||||
{
|
|
||||||
XUngrabButton(W->dpy, AnyButton, AnyModifier, c->win);
|
|
||||||
|
|
||||||
if(focused)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while(i++ != Button5)
|
|
||||||
{
|
|
||||||
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD, c->win, False,
|
|
||||||
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
||||||
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | LockMask, c->win, False,
|
|
||||||
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
||||||
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | W->numlockmask, c->win, False,
|
|
||||||
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
||||||
XGrabButton(W->dpy, i, CLIENT_MOUSE_MOD | LockMask | W->numlockmask, c->win, False,
|
|
||||||
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XGrabButton(W->dpy, AnyButton, AnyModifier, c->win, False,
|
|
||||||
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
client_draw_bord(struct client *c)
|
|
||||||
{
|
|
||||||
struct geo g = { 0, 0, c->screen->ugeo.w, c->screen->ugeo.h };
|
|
||||||
|
|
||||||
draw_rect(c->tag->frame, g, THEME_DEFAULT->client_n.bg);
|
|
||||||
|
|
||||||
/* Selected client's border */
|
|
||||||
if(W->client)
|
|
||||||
draw_rect(W->client->tag->frame, W->client->tag->sel->geo, THEME_DEFAULT->client_s.bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
client_focus(struct client *c)
|
|
||||||
{
|
|
||||||
/* Unfocus selected */
|
|
||||||
if(W->client && W->client != c)
|
|
||||||
client_grabbuttons(W->client, false);
|
|
||||||
|
|
||||||
/* Focus c */
|
|
||||||
if((W->client = c))
|
|
||||||
{
|
|
||||||
c->tag->sel = c;
|
|
||||||
|
|
||||||
client_draw_bord(c);
|
|
||||||
client_grabbuttons(c, true);
|
|
||||||
|
|
||||||
XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
W->client = W->screen->seltag->sel = NULL;
|
|
||||||
XSetInputFocus(W->dpy, W->root, RevertToPointerRoot, CurrentTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a client name
|
|
||||||
* \param c struct client pointer
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
client_get_name(struct client *c)
|
|
||||||
{
|
|
||||||
Atom rt;
|
|
||||||
int rf;
|
|
||||||
unsigned long ir, il;
|
|
||||||
|
|
||||||
/* This one instead XFetchName for utf8 name support */
|
|
||||||
if(XGetWindowProperty(W->dpy, c->win, ATOM("_NET_WM_NAME"), 0, 4096,
|
|
||||||
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, (unsigned char**)&c->title) != Success)
|
|
||||||
XGetWindowProperty(W->dpy, c->win, ATOM("WM_NAME"), 0, 4096,
|
|
||||||
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, (unsigned char**)&c->title);
|
|
||||||
|
|
||||||
/* Still no title... */
|
|
||||||
if(!c->title)
|
|
||||||
XFetchName(W->dpy, c->win, &(c->title));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Close a client
|
|
||||||
* \param c struct client pointer
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
client_close(struct client *c)
|
|
||||||
{
|
|
||||||
int proto;
|
|
||||||
XEvent ev;
|
|
||||||
Atom *atom = NULL;
|
|
||||||
|
|
||||||
/* Event will call client_remove */
|
|
||||||
if(XGetWMProtocols(W->dpy, c->win, &atom, &proto) && atom)
|
|
||||||
{
|
|
||||||
while(proto--)
|
|
||||||
if(atom[proto] == ATOM("WM_DELETE_WINDOW"))
|
|
||||||
{
|
|
||||||
ev.type = ClientMessage;
|
|
||||||
ev.xclient.window = c->win;
|
|
||||||
ev.xclient.message_type = ATOM("WM_PROTOCOLS");
|
|
||||||
ev.xclient.format = 32;
|
|
||||||
ev.xclient.data.l[0] = ATOM("WM_DELETE_WINDOW");
|
|
||||||
ev.xclient.data.l[1] = CurrentTime;
|
|
||||||
|
|
||||||
XSendEvent(W->dpy, c->win, False, NoEventMask, &ev);
|
|
||||||
XFree(atom);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XKillClient(W->dpy, c->win);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_client_close(Uicb cmd)
|
|
||||||
{
|
|
||||||
if(W->client)
|
|
||||||
client_close(W->client);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct client*
|
|
||||||
client_new(Window w, XWindowAttributes *wa)
|
|
||||||
{
|
|
||||||
struct client *c = xcalloc(1, sizeof(struct client));
|
|
||||||
|
|
||||||
/* C attributes */
|
|
||||||
c->win = w;
|
|
||||||
c->screen = W->screen;
|
|
||||||
c->flags = 0;
|
|
||||||
c->tag = NULL;
|
|
||||||
|
|
||||||
/* struct geometry */
|
|
||||||
c->geo.x = wa->x;
|
|
||||||
c->geo.y = wa->y;
|
|
||||||
c->geo.w = wa->width;
|
|
||||||
c->geo.h = wa->height;
|
|
||||||
c->tgeo = c->wgeo = c->geo;
|
|
||||||
|
|
||||||
/* Set tag */
|
|
||||||
tag_client(W->screen->seltag, c);
|
|
||||||
|
|
||||||
/* X window attributes */
|
|
||||||
XSelectInput(W->dpy, w, EnterWindowMask | LeaveWindowMask | StructureNotifyMask | PropertyChangeMask);
|
|
||||||
XSetWindowBorderWidth(W->dpy, w, 0);
|
|
||||||
client_grabbuttons(c, false);
|
|
||||||
|
|
||||||
/* Attach */
|
|
||||||
SLIST_INSERT_HEAD(&W->h.client, c, next);
|
|
||||||
|
|
||||||
/* Map */
|
|
||||||
WIN_STATE(w, Map);
|
|
||||||
ewmh_set_wm_state(w, NormalState);
|
|
||||||
|
|
||||||
client_get_name(c);
|
|
||||||
client_focus(c);
|
|
||||||
client_configure(c);
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_moveresize(struct client *c, struct geo g)
|
|
||||||
{
|
|
||||||
int bord = THEME_DEFAULT->client_border_width;
|
|
||||||
|
|
||||||
c->geo = g;
|
|
||||||
|
|
||||||
/* Window geo */
|
|
||||||
c->wgeo.x = g.x + bord;
|
|
||||||
c->wgeo.y = g.y + bord ;
|
|
||||||
c->wgeo.w = g.w - (bord << 1);
|
|
||||||
c->wgeo.h = g.h - (bord << 1);
|
|
||||||
|
|
||||||
XMoveResizeWindow(W->dpy, c->win,
|
|
||||||
c->wgeo.x, c->wgeo.y,
|
|
||||||
c->wgeo.w, c->wgeo.h);
|
|
||||||
|
|
||||||
client_draw_bord(c);
|
|
||||||
client_configure(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_maximize(struct client *c)
|
|
||||||
{
|
|
||||||
c->geo = c->tag->screen->ugeo;
|
|
||||||
|
|
||||||
c->geo.x = c->geo.y = 0; /* Frame x/y, not screen geo */
|
|
||||||
c->geo.w = c->tag->screen->ugeo.w;
|
|
||||||
c->geo.h = c->tag->screen->ugeo.h;
|
|
||||||
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_fac_resize(struct client *c, Position p, int fac)
|
|
||||||
{
|
|
||||||
struct client *gc = client_next_with_pos(c, p);
|
|
||||||
Position rp = RPOS(p);
|
|
||||||
|
|
||||||
if(!gc || gc->screen != c->screen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Check futur size/pos */
|
|
||||||
if(!client_fac_geo(c, p, fac)
|
|
||||||
|| !client_fac_geo(gc, rp, -fac)
|
|
||||||
|| !client_fac_check_row(c, p, fac)
|
|
||||||
|| !client_fac_check_row(gc, rp, -fac))
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
/* Simple resize with only c & gc */
|
|
||||||
if(GEO_CHECK2(c->geo, gc->geo, p))
|
|
||||||
{
|
|
||||||
client_moveresize(c, c->tgeo);
|
|
||||||
client_moveresize(gc, gc->tgeo);
|
|
||||||
}
|
|
||||||
/* Resize with row parents */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client_fac_arrange_row(c, p, fac);
|
|
||||||
client_fac_arrange_row(gc, rp, -fac);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_remove(struct client *c)
|
|
||||||
{
|
|
||||||
XGrabServer(W->dpy);
|
|
||||||
XSetErrorHandler(wmfs_error_handler_dummy);
|
|
||||||
XReparentWindow(W->dpy, c->win, W->root, c->geo.x, c->geo.y);
|
|
||||||
|
|
||||||
/* Remove from global client list */
|
|
||||||
SLIST_REMOVE(&W->h.client, c, client, next);
|
|
||||||
|
|
||||||
tag_client(NULL, c);
|
|
||||||
|
|
||||||
ewmh_set_wm_state(c->win, WithdrawnState);
|
|
||||||
|
|
||||||
XUngrabServer(W->dpy);
|
|
||||||
XSync(W->dpy, False);
|
|
||||||
XSetErrorHandler(wmfs_error_handler);
|
|
||||||
|
|
||||||
free(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_free(void)
|
|
||||||
{
|
|
||||||
FREE_LIST(client, W->h.client);
|
|
||||||
}
|
|
||||||
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CLIENT_H
|
|
||||||
#define CLIENT_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "layout.h"
|
|
||||||
|
|
||||||
void client_configure(struct client *c);
|
|
||||||
struct client *client_gb_win(Window w);
|
|
||||||
inline struct client *client_gb_pos(struct tag *t, int x, int y);
|
|
||||||
struct client *client_next_with_pos(struct client *bc, Position p);
|
|
||||||
void client_swap(struct client *c1, struct client *c2);
|
|
||||||
void client_focus(struct client *c);
|
|
||||||
void client_get_name(struct client *c);
|
|
||||||
void client_close(struct client *c);
|
|
||||||
void uicb_client_close(Uicb cmd);
|
|
||||||
struct client *client_new(Window w, XWindowAttributes *wa);
|
|
||||||
void client_moveresize(struct client *c, struct geo g);
|
|
||||||
void client_maximize(struct client *c);
|
|
||||||
void client_fac_resize(struct client *c, Position p, int fac);
|
|
||||||
void client_remove(struct client *c);
|
|
||||||
void client_free(void);
|
|
||||||
|
|
||||||
/* Generated */
|
|
||||||
void uicb_client_resize_Right(Uicb);
|
|
||||||
void uicb_client_resize_Left(Uicb);
|
|
||||||
void uicb_client_resize_Top(Uicb);
|
|
||||||
void uicb_client_resize_Bottom(Uicb);
|
|
||||||
void uicb_client_focus_Right(Uicb);
|
|
||||||
void uicb_client_focus_Left(Uicb);
|
|
||||||
void uicb_client_focus_Top(Uicb);
|
|
||||||
void uicb_client_focus_Bottom(Uicb);
|
|
||||||
void uicb_client_swapsel_Right(Uicb);
|
|
||||||
void uicb_client_swapsel_Left(Uicb);
|
|
||||||
void uicb_client_swapsel_Top(Uicb);
|
|
||||||
void uicb_client_swapsel_Bottom(Uicb);
|
|
||||||
void uicb_client_focus_next(Uicb);
|
|
||||||
void uicb_client_focus_prev(Uicb);
|
|
||||||
void uicb_client_swapsel_next(Uicb);
|
|
||||||
void uicb_client_swapsel_prev(Uicb);
|
|
||||||
|
|
||||||
static inline struct client*
|
|
||||||
client_next(struct client *c)
|
|
||||||
{
|
|
||||||
return (SLIST_NEXT(c, tnext)
|
|
||||||
? SLIST_NEXT(c, tnext)
|
|
||||||
: SLIST_FIRST(&c->tag->clients));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct client*
|
|
||||||
client_prev(struct client *c)
|
|
||||||
{
|
|
||||||
struct client *cc;
|
|
||||||
|
|
||||||
for(cc = SLIST_FIRST(&c->tag->clients);
|
|
||||||
SLIST_NEXT(cc, tnext) && SLIST_NEXT(cc, tnext) != c;
|
|
||||||
cc = SLIST_NEXT(cc, tnext));
|
|
||||||
|
|
||||||
return cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
client_fac_geo(struct client *c, Position p, int fac)
|
|
||||||
{
|
|
||||||
struct geo cg = c->geo;
|
|
||||||
|
|
||||||
switch(p)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case Right:
|
|
||||||
cg.w += fac;
|
|
||||||
break;
|
|
||||||
case Left:
|
|
||||||
cg.x -= fac;
|
|
||||||
cg.w += fac;
|
|
||||||
break;
|
|
||||||
case Top:
|
|
||||||
cg.y -= fac;
|
|
||||||
cg.h += fac;
|
|
||||||
break;
|
|
||||||
case Bottom:
|
|
||||||
cg.h += fac;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for incompatible geo */
|
|
||||||
if(cg.w > c->screen->ugeo.w || cg.h > c->screen->ugeo.h
|
|
||||||
|| cg.w < 5 || cg.h < 5)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Set transformed geo in tmp geo */
|
|
||||||
c->tgeo = cg;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
client_fac_check_row(struct client *c, Position p, int fac)
|
|
||||||
{
|
|
||||||
struct geo g = c->geo;
|
|
||||||
struct client *cc;
|
|
||||||
|
|
||||||
/* Travel clients to search parents of row and check geos */
|
|
||||||
SLIST_FOREACH(cc, &c->tag->clients, tnext)
|
|
||||||
if(GEO_PARENTROW(g, cc->geo, p) && !client_fac_geo(cc, p, fac))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
client_fac_arrange_row(struct client *c, Position p, int fac)
|
|
||||||
{
|
|
||||||
struct geo g = c->geo;
|
|
||||||
struct client *cc;
|
|
||||||
|
|
||||||
/* Travel clients to search row parents and apply fac */
|
|
||||||
SLIST_FOREACH(cc, &c->tag->clients, tnext)
|
|
||||||
if(GEO_PARENTROW(g, cc->geo, p))
|
|
||||||
{
|
|
||||||
client_fac_geo(cc, p, fac);
|
|
||||||
client_moveresize(cc, cc->tgeo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CLIENT_H */
|
|
||||||
@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "parse.h"
|
|
||||||
#include "tag.h"
|
|
||||||
#include "screen.h"
|
|
||||||
#include "infobar.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define CONFIG_DEFAULT_PATH ".config/wmfs/wmfsrc2" /* tmp */
|
|
||||||
|
|
||||||
static void
|
|
||||||
config_theme(void)
|
|
||||||
{
|
|
||||||
struct theme *t, *p = NULL;
|
|
||||||
size_t i, n;
|
|
||||||
struct conf_sec *sec, **ks;
|
|
||||||
|
|
||||||
/* [themes] */
|
|
||||||
sec = fetch_section_first(NULL, "themes");
|
|
||||||
ks = fetch_section(sec, "theme");
|
|
||||||
|
|
||||||
/* No theme section? Make one with default value anyway. */
|
|
||||||
if(!(n = fetch_section_count(ks)))
|
|
||||||
++n;
|
|
||||||
|
|
||||||
SLIST_INIT(&W->h.theme);
|
|
||||||
|
|
||||||
/* [theme]*/
|
|
||||||
for(i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
t = (struct theme*)xcalloc(1, sizeof(struct theme));
|
|
||||||
|
|
||||||
t->name = fetch_opt_first(ks[i], "default", "name").str;
|
|
||||||
|
|
||||||
wmfs_init_font(fetch_opt_first(ks[i], "fixed", "font").str, t);
|
|
||||||
|
|
||||||
/* bars */
|
|
||||||
t->bars.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "bars_fg").str);
|
|
||||||
t->bars.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "bars_bg").str);
|
|
||||||
t->bars_width = fetch_opt_first(ks[i], "12", "bars_width").num;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Elements
|
|
||||||
*/
|
|
||||||
t->tags_n.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_normal_fg").str);
|
|
||||||
t->tags_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_normal_bg").str);
|
|
||||||
t->tags_s.fg = color_atoh(fetch_opt_first(ks[i], "#222222", "tags_sel_fg").str);
|
|
||||||
t->tags_s.bg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "tags_sel_bg").str);
|
|
||||||
t->tags_border_col = color_atoh(fetch_opt_first(ks[i], "#888888", "tags_border_color").str);
|
|
||||||
t->tags_border_width = fetch_opt_first(ks[i], "0", "tags_border_width").num;
|
|
||||||
|
|
||||||
/* Client / frame */
|
|
||||||
t->client_n.fg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "client_normal_fg").str);
|
|
||||||
t->client_n.bg = color_atoh(fetch_opt_first(ks[i], "#222222", "client_normal_bg").str);
|
|
||||||
t->client_s.fg = color_atoh(fetch_opt_first(ks[i], "#222222", "client_sel_fg").str);
|
|
||||||
t->client_s.bg = color_atoh(fetch_opt_first(ks[i], "#CCCCCC", "client_sel_bg").str);
|
|
||||||
t->frame_bg = color_atoh(fetch_opt_first(ks[i], "#555555", "frame_bg").str);
|
|
||||||
t->client_titlebar_width = fetch_opt_first(ks[i], "12", "client_titlebar_width").num;
|
|
||||||
t->client_border_width = fetch_opt_first(ks[i], "1", "client_border_width").num;
|
|
||||||
|
|
||||||
/* insert_tail with SLIST */
|
|
||||||
if(SLIST_EMPTY(&W->h.theme))
|
|
||||||
SLIST_INSERT_HEAD(&W->h.theme, t, next);
|
|
||||||
else
|
|
||||||
SLIST_INSERT_AFTER(p, t, next);
|
|
||||||
|
|
||||||
p = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ks);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
config_bars(void)
|
|
||||||
{
|
|
||||||
struct screen *s;
|
|
||||||
struct theme *t;
|
|
||||||
size_t i, n;
|
|
||||||
struct conf_sec *sec, **ks;
|
|
||||||
int screenid;
|
|
||||||
char *elem;
|
|
||||||
Barpos pos = BarTop;
|
|
||||||
|
|
||||||
/* [bars] */
|
|
||||||
sec = fetch_section_first(NULL, "bars");
|
|
||||||
ks = fetch_section(sec, "bar");
|
|
||||||
n = fetch_section_count(ks);
|
|
||||||
|
|
||||||
/* [bar] */
|
|
||||||
for(i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
elem = fetch_opt_first(ks[i], "", "elements").str;
|
|
||||||
screenid = fetch_opt_first(ks[i], "-1", "screen").num;
|
|
||||||
t = name_to_theme(fetch_opt_first(ks[i], "default", "theme").str);
|
|
||||||
pos = fetch_opt_first(ks[i], "0", "position").num;
|
|
||||||
|
|
||||||
SLIST_FOREACH(s, &W->h.screen, next)
|
|
||||||
if(screenid == s->id || screenid == -1)
|
|
||||||
infobar_new(s, t, pos, elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ks);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
config_tag(void)
|
|
||||||
{
|
|
||||||
struct screen *s;
|
|
||||||
struct tag *t;
|
|
||||||
size_t i, n;
|
|
||||||
struct conf_sec *sec, **ks;
|
|
||||||
char *name;
|
|
||||||
int screenid;
|
|
||||||
|
|
||||||
/* [tags] */
|
|
||||||
sec = fetch_section_first(NULL, "tags");
|
|
||||||
ks = fetch_section(sec, "tag");
|
|
||||||
n = fetch_section_count(ks);
|
|
||||||
|
|
||||||
/* [tag] */
|
|
||||||
for(i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
name = fetch_opt_first(ks[i], "tag", "name").str;
|
|
||||||
screenid = fetch_opt_first(ks[i], "-1", "screen").num;
|
|
||||||
|
|
||||||
SLIST_FOREACH(s, &W->h.screen, next)
|
|
||||||
if(screenid == s->id || screenid == -1)
|
|
||||||
{
|
|
||||||
t = tag_new(s, name);
|
|
||||||
|
|
||||||
/* Set first tag as seltag */
|
|
||||||
if(t == TAILQ_FIRST(&s->tags))
|
|
||||||
s->seltag = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ks);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
config_keybind(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
size_t j, n;
|
|
||||||
struct conf_sec *sec, **ks;
|
|
||||||
struct opt_type *opt;
|
|
||||||
char *cmd;
|
|
||||||
struct keybind *k;
|
|
||||||
|
|
||||||
/* [keys] */
|
|
||||||
sec = fetch_section_first(NULL, "keys");
|
|
||||||
ks = fetch_section(sec, "key");
|
|
||||||
n = fetch_section_count(ks);
|
|
||||||
|
|
||||||
SLIST_INIT(&W->h.keybind);
|
|
||||||
|
|
||||||
/* [key] */
|
|
||||||
for(i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
k = (struct keybind*)xcalloc(1, sizeof(struct keybind));
|
|
||||||
|
|
||||||
/* mod = {} */
|
|
||||||
opt = fetch_opt(ks[i], "", "mod");
|
|
||||||
|
|
||||||
for(j = k->mod = 0; j < fetch_opt_count(opt); ++j)
|
|
||||||
k->mod |= modkey_keysym(opt[j].str);
|
|
||||||
|
|
||||||
free(opt);
|
|
||||||
|
|
||||||
/* key = */
|
|
||||||
k->keysym = XStringToKeysym(fetch_opt_first(ks[i], "None", "key").str);
|
|
||||||
|
|
||||||
/* func = */
|
|
||||||
if(!(k->func = uicb_name_func(fetch_opt_first(ks[i], "", "func").str)))
|
|
||||||
{
|
|
||||||
warnx("configuration: Unknown Function \"%s\".",
|
|
||||||
fetch_opt_first(ks[i], "", "func").str);
|
|
||||||
k->func = uicb_spawn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cmd = */
|
|
||||||
if((cmd = fetch_opt_first(ks[i], "", "cmd").str))
|
|
||||||
k->cmd = xstrdup(cmd);
|
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(&W->h.keybind, k, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
wmfs_grab_keys();
|
|
||||||
|
|
||||||
free(ks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
config_init(void)
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
xasprintf(&path, "%s/"CONFIG_DEFAULT_PATH, getenv("HOME"));
|
|
||||||
|
|
||||||
if(get_conf(path) == -1)
|
|
||||||
errx(1, "parsing configuration file (%s) failed.", path);
|
|
||||||
|
|
||||||
config_theme();
|
|
||||||
config_keybind();
|
|
||||||
config_tag();
|
|
||||||
config_bars();
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
free_conf();
|
|
||||||
}
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_H
|
|
||||||
#define CONFIG_H
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "tag.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#define THEME_DEFAULT (SLIST_FIRST(&W->h.theme))
|
|
||||||
|
|
||||||
static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
|
|
||||||
{
|
|
||||||
/* Sys */
|
|
||||||
{ "spawn", uicb_spawn },
|
|
||||||
{ "quit", uicb_quit },
|
|
||||||
{ "reload", uicb_reload },
|
|
||||||
|
|
||||||
/* Tag */
|
|
||||||
{ "tag_set", uicb_tag_set },
|
|
||||||
{ "tag", uicb_tag_set_with_name },
|
|
||||||
{ "tag_next", uicb_tag_next },
|
|
||||||
{ "tag_prev", uicb_tag_prev },
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
{ "layout_vmirror", uicb_layout_vmirror },
|
|
||||||
{ "layout_hmirror", uicb_layout_hmirror },
|
|
||||||
{ "layout_rotate_left", uicb_layout_rotate_left },
|
|
||||||
{ "layout_rotate_right", uicb_layout_rotate_right },
|
|
||||||
|
|
||||||
/* Client */
|
|
||||||
{ "client_close", uicb_client_close },
|
|
||||||
{ "client_resize_right", uicb_client_resize_Right },
|
|
||||||
{ "client_resize_left", uicb_client_resize_Left },
|
|
||||||
{ "client_resize_top", uicb_client_resize_Top },
|
|
||||||
{ "client_resize_bottom", uicb_client_resize_Bottom },
|
|
||||||
{ "client_focus_right", uicb_client_focus_Right },
|
|
||||||
{ "client_focus_left", uicb_client_focus_Left },
|
|
||||||
{ "client_focus_top", uicb_client_focus_Top },
|
|
||||||
{ "client_focus_bottom", uicb_client_focus_Bottom },
|
|
||||||
{ "client_swap_right", uicb_client_swapsel_Right },
|
|
||||||
{ "client_swap_left", uicb_client_swapsel_Left },
|
|
||||||
{ "client_swap_top", uicb_client_swapsel_Top },
|
|
||||||
{ "client_swap_bottom", uicb_client_swapsel_Bottom },
|
|
||||||
{ "client_focus_next", uicb_client_focus_next },
|
|
||||||
{ "client_focus_prev", uicb_client_focus_prev },
|
|
||||||
{ "client_swap_next", uicb_client_swapsel_next },
|
|
||||||
{ "client_swap_prev", uicb_client_swapsel_prev },
|
|
||||||
{ NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline void*
|
|
||||||
uicb_name_func(Uicb name)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for(; uicb_list[i].func; ++i)
|
|
||||||
if(!strcmp(name, uicb_list[i].name))
|
|
||||||
return uicb_list[i].func;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct { const char *name; KeySym keysym; } key_list[] =
|
|
||||||
{
|
|
||||||
{"Control", ControlMask },
|
|
||||||
{"Shift", ShiftMask },
|
|
||||||
{"Lock", LockMask },
|
|
||||||
{"Alt", Mod1Mask },
|
|
||||||
{"Mod1", Mod1Mask },
|
|
||||||
{"Mod2", Mod2Mask },
|
|
||||||
{"Mod3", Mod3Mask },
|
|
||||||
{"Mod4", Mod4Mask },
|
|
||||||
{"Super", Mod4Mask },
|
|
||||||
{"Home", Mod4Mask },
|
|
||||||
{"Mod5", Mod5Mask },
|
|
||||||
{NULL, NoSymbol }
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline KeySym
|
|
||||||
modkey_keysym(const char *name)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for(; key_list[i].name; ++i)
|
|
||||||
if(!strcmp(name, key_list[i].name))
|
|
||||||
return key_list[i].keysym;
|
|
||||||
|
|
||||||
return NoSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct theme*
|
|
||||||
name_to_theme(const char *name)
|
|
||||||
{
|
|
||||||
struct theme *t;
|
|
||||||
|
|
||||||
SLIST_FOREACH(t, &W->h.theme, next)
|
|
||||||
if(!strcmp(t->name, name))
|
|
||||||
return t;
|
|
||||||
|
|
||||||
return THEME_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void config_init(void);
|
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DRAW_H
|
|
||||||
#define DRAW_H
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
#define TEXTY(t, w) ((t->font.height - t->font.de) + ((w - t->font.height) >> 1))
|
|
||||||
#define PAD (8)
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
draw_text(Drawable d, struct theme *t, int x, int y, Color fg, const char *str)
|
|
||||||
{
|
|
||||||
XSetForeground(W->dpy, W->gc, fg);
|
|
||||||
XmbDrawString(W->dpy, d, t->font.fontset, W->gc, x, y, str, strlen(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
draw_rect(Drawable d, struct geo g, Color bg)
|
|
||||||
{
|
|
||||||
XSetForeground(W->dpy, W->gc, bg);
|
|
||||||
XFillRectangle(W->dpy, d, W->gc, g.x, g.y, g.w, g.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned short
|
|
||||||
draw_textw(struct theme *t, const char *str)
|
|
||||||
{
|
|
||||||
XRectangle r;
|
|
||||||
|
|
||||||
XmbTextExtents(t->font.fontset, str, strlen(str), NULL, &r);
|
|
||||||
|
|
||||||
return r.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* DRAW_H */
|
|
||||||
@ -1,259 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "event.h"
|
|
||||||
#include "ewmh.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "barwin.h"
|
|
||||||
#include "screen.h"
|
|
||||||
|
|
||||||
#define EVDPY(e) (e)->xany.display
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_buttonpress(XEvent *e)
|
|
||||||
{
|
|
||||||
XButtonEvent *ev = &e->xbutton;
|
|
||||||
struct mousebind *m;
|
|
||||||
struct barwin *b;
|
|
||||||
|
|
||||||
screen_update_sel();
|
|
||||||
|
|
||||||
SLIST_FOREACH(b, &W->h.barwin, next)
|
|
||||||
if(b->win == ev->window)
|
|
||||||
{
|
|
||||||
SLIST_FOREACH(m, &b->mousebinds, next)
|
|
||||||
if(m->button == ev->button)
|
|
||||||
if(!m->use_area || (m->use_area && INAREA(ev->x, ev->y, m->area)))
|
|
||||||
if(m->func)
|
|
||||||
m->func(m->cmd);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_enternotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XCrossingEvent *ev = &e->xcrossing;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if((ev->mode != NotifyNormal
|
|
||||||
|| ev->detail == NotifyInferior
|
|
||||||
|| ev->detail == NotifyAncestor)
|
|
||||||
&& ev->window != W->root)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->window)))
|
|
||||||
client_focus(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_clientmessageevent(XEvent *e)
|
|
||||||
{
|
|
||||||
/* XClientMessageEvent *ev = &e->xclient;
|
|
||||||
client *c;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_configureevent(XEvent *e)
|
|
||||||
{
|
|
||||||
XConfigureRequestEvent *ev = &e->xconfigurerequest;
|
|
||||||
XWindowChanges wc;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->window)))
|
|
||||||
{
|
|
||||||
if(ev->value_mask & CWX)
|
|
||||||
c->geo.x = ev->x;
|
|
||||||
if(ev->value_mask & CWY)
|
|
||||||
c->geo.y = ev->y;
|
|
||||||
if(ev->value_mask & CWWidth)
|
|
||||||
c->geo.w = ev->width;
|
|
||||||
if(ev->value_mask & CWHeight)
|
|
||||||
c->geo.h = ev->height;
|
|
||||||
|
|
||||||
client_configure(c);
|
|
||||||
|
|
||||||
XMoveResizeWindow(EVDPY(e), c->win, c->geo.x, c->geo.y, c->geo.w, c->geo.h);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wc.x = ev->x;
|
|
||||||
wc.y = ev->y;
|
|
||||||
wc.width = ev->width;
|
|
||||||
wc.height = ev->height;
|
|
||||||
wc.border_width = ev->border_width;
|
|
||||||
wc.sibling = ev->above;
|
|
||||||
wc.stack_mode = ev->detail;
|
|
||||||
|
|
||||||
XConfigureWindow(EVDPY(e), ev->window, ev->value_mask, &wc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_destroynotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->window)))
|
|
||||||
client_remove(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_focusin(XEvent *e)
|
|
||||||
{
|
|
||||||
if(W->client && e->xfocus.window != W->client->win)
|
|
||||||
client_focus(W->client);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_maprequest(XEvent *e)
|
|
||||||
{
|
|
||||||
XMapRequestEvent *ev = &e->xmaprequest;
|
|
||||||
XWindowAttributes at;
|
|
||||||
|
|
||||||
/* Which windows to manage */
|
|
||||||
if(!XGetWindowAttributes(EVDPY(e), ev->window, &at)
|
|
||||||
|| at.override_redirect)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!client_gb_win(ev->window))
|
|
||||||
client_new(ev->window, &at);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_mappingnotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XMappingEvent *ev = &e->xmapping;
|
|
||||||
XRefreshKeyboardMapping(ev);
|
|
||||||
|
|
||||||
if(ev->request == MappingKeyboard)
|
|
||||||
wmfs_grab_keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_propertynotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XPropertyEvent *ev = &e->xproperty;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if(ev->state == PropertyDelete)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->window)))
|
|
||||||
{
|
|
||||||
switch(ev->atom)
|
|
||||||
{
|
|
||||||
case XA_WM_TRANSIENT_FOR:
|
|
||||||
break;
|
|
||||||
case XA_WM_NORMAL_HINTS:
|
|
||||||
/* client_get_size_hints(c); */
|
|
||||||
break;
|
|
||||||
case XA_WM_HINTS:
|
|
||||||
/*
|
|
||||||
XWMHints *h;
|
|
||||||
|
|
||||||
if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
|
|
||||||
{
|
|
||||||
client_urgent(c, True);
|
|
||||||
XFree(h);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if(ev->atom == XA_WM_NAME || ev->atom == W->net_atom[net_wm_name])
|
|
||||||
client_get_name(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_unmapnotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XUnmapEvent *ev = &e->xunmap;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->window)) && ev->send_event)
|
|
||||||
client_remove(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static void
|
|
||||||
event_motionnotify(XEvent *e)
|
|
||||||
{
|
|
||||||
XMotionEvent *ev = &e->xmotion;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if((c = client_gb_win(ev->subwindow)) && c != c->tag->sel)
|
|
||||||
client_focus(c);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_keypress(XEvent *e)
|
|
||||||
{
|
|
||||||
XKeyPressedEvent *ev = &e->xkey;
|
|
||||||
KeySym keysym = XKeycodeToKeysym(EVDPY(e), (KeyCode)ev->keycode, 0);
|
|
||||||
struct keybind *k;
|
|
||||||
|
|
||||||
screen_update_sel();
|
|
||||||
|
|
||||||
SLIST_FOREACH(k, &W->h.keybind, next)
|
|
||||||
if(k->keysym == keysym && KEYPRESS_MASK(k->mod) == KEYPRESS_MASK(ev->state))
|
|
||||||
if(k->func)
|
|
||||||
k->func(k->cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_expose(XEvent *e)
|
|
||||||
{
|
|
||||||
XExposeEvent *ev = &e->xexpose;
|
|
||||||
struct barwin *b;
|
|
||||||
|
|
||||||
SLIST_FOREACH(b, &W->h.barwin, next)
|
|
||||||
if(b->win == ev->window)
|
|
||||||
{
|
|
||||||
barwin_refresh(b);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
event_dummy(XEvent *e)
|
|
||||||
{
|
|
||||||
/* printf("%d\n", e->type);*/
|
|
||||||
(void)e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
event_init(void)
|
|
||||||
{
|
|
||||||
int i = MAX_EV;
|
|
||||||
|
|
||||||
while(i--)
|
|
||||||
event_handle[i] = event_dummy;
|
|
||||||
|
|
||||||
event_handle[ButtonPress] = event_buttonpress;
|
|
||||||
event_handle[ClientMessage] = event_clientmessageevent;
|
|
||||||
event_handle[ConfigureRequest] = event_configureevent;
|
|
||||||
event_handle[DestroyNotify] = event_destroynotify;
|
|
||||||
event_handle[EnterNotify] = event_enternotify;
|
|
||||||
event_handle[Expose] = event_expose;
|
|
||||||
event_handle[FocusIn] = event_focusin;
|
|
||||||
event_handle[KeyPress] = event_keypress;
|
|
||||||
/*event_handle[MapNotify] = event_mapnotify;*/
|
|
||||||
event_handle[MapRequest] = event_maprequest;
|
|
||||||
event_handle[MappingNotify] = event_mappingnotify;
|
|
||||||
/*event_handle[MotionNotify] = event_motionnotify;*/
|
|
||||||
event_handle[PropertyNotify] = event_propertynotify;
|
|
||||||
/*event_handle[ReparentNotify] = event_reparentnotify;*/
|
|
||||||
/*event_handle[SelectionClear] = event_selectionclearevent;*/
|
|
||||||
event_handle[UnmapNotify] = event_unmapnotify;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EVENT_H
|
|
||||||
#define EVENT_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
#define MAX_EV 256
|
|
||||||
|
|
||||||
#define KEYPRESS_MASK(m) (m & ~(W->numlockmask | LockMask))
|
|
||||||
#define EVENT_HANDLE(e) event_handle[(e)->type](e);
|
|
||||||
|
|
||||||
void event_init(void);
|
|
||||||
|
|
||||||
void (*event_handle[MAX_EV])(XEvent*);
|
|
||||||
|
|
||||||
#endif /* EVENT_H */
|
|
||||||
106
wmfs2/src/ewmh.c
106
wmfs2/src/ewmh.c
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
|
|
||||||
#include "ewmh.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
ewmh_init(void)
|
|
||||||
{
|
|
||||||
int b = 1;
|
|
||||||
|
|
||||||
W->net_atom = xcalloc(net_last, sizeof(Atom));
|
|
||||||
|
|
||||||
/* EWMH hints */
|
|
||||||
W->net_atom[wm_state] = ATOM("WM_STATE");
|
|
||||||
W->net_atom[net_supported] = ATOM("_NET_SUPPORTED");
|
|
||||||
W->net_atom[net_client_list] = ATOM("_NET_CLIENT_LIST");
|
|
||||||
W->net_atom[net_frame_extents] = ATOM("_NET_FRAME_EXTENTS");
|
|
||||||
W->net_atom[net_number_of_desktops] = ATOM("_NET_NUMBER_OF_DESKTOPS");
|
|
||||||
W->net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
|
|
||||||
W->net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
|
|
||||||
W->net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY");
|
|
||||||
W->net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
|
|
||||||
W->net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
|
|
||||||
W->net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
|
|
||||||
W->net_atom[net_wm_pid] = ATOM("_NET_WM_PID");
|
|
||||||
W->net_atom[net_wm_desktop] = ATOM("_NET_WM_DESKTOP");
|
|
||||||
W->net_atom[net_showing_desktop] = ATOM("_NET_SHOWING_DESKTOP");
|
|
||||||
W->net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
|
|
||||||
W->net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
|
|
||||||
W->net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
|
|
||||||
W->net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
|
|
||||||
W->net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
|
|
||||||
W->net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
|
|
||||||
W->net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
|
|
||||||
W->net_atom[net_wm_window_type_dialog] = ATOM("_NET_WM_WINDOW_TYPE_DIALOG");
|
|
||||||
W->net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
|
|
||||||
W->net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
|
|
||||||
W->net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
|
|
||||||
W->net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
|
|
||||||
W->net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
|
|
||||||
W->net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
|
|
||||||
W->net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
|
|
||||||
W->net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
|
|
||||||
W->net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
|
|
||||||
W->net_atom[xembed] = ATOM("_XEMBED");
|
|
||||||
W->net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
|
|
||||||
W->net_atom[manager] = ATOM("MANAGER");
|
|
||||||
W->net_atom[utf8_string] = ATOM("UTF8_STRING");
|
|
||||||
|
|
||||||
/* WMFS hints */
|
|
||||||
W->net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
|
|
||||||
W->net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
|
|
||||||
W->net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
|
|
||||||
W->net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
|
|
||||||
W->net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
|
|
||||||
W->net_atom[wmfs_tag_list] = ATOM("_WMFS_TAG_LIST");
|
|
||||||
W->net_atom[wmfs_current_screen] = ATOM("_WMFS_CURRENT_SCREEN");
|
|
||||||
W->net_atom[wmfs_current_layout] = ATOM("_WMFS_CURRENT_LAYOUT");
|
|
||||||
W->net_atom[wmfs_mwfact] = ATOM("_WMFS_MWFACT");
|
|
||||||
W->net_atom[wmfs_nmaster] = ATOM("_WMFS_NMASTER");
|
|
||||||
W->net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
|
|
||||||
W->net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
|
|
||||||
W->net_atom[wmfs_font] = ATOM("_WMFS_FONT");
|
|
||||||
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[net_supported], XA_ATOM, 32,
|
|
||||||
PropModeReplace, (unsigned char*)W->net_atom, net_last);
|
|
||||||
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[wmfs_running], XA_CARDINAL, 32,
|
|
||||||
PropModeReplace, (unsigned char*)&b, 1);
|
|
||||||
|
|
||||||
/* Set _NET_SUPPORTING_WM_CHECK */
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[net_supporting_wm_check], XA_WINDOW, 32,
|
|
||||||
PropModeReplace, (unsigned char*)&W->root, 1);
|
|
||||||
/*
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_name], W->net_atom[utf8_string], 8,
|
|
||||||
PropModeReplace, (unsigned char*)&rootn, strlen(rootn));
|
|
||||||
|
|
||||||
XChangeProperty(W->dpy, W->root, ATOM("WM_CLASS"), XA_STRING, 8,
|
|
||||||
PropModeReplace, (unsigned char*)&class, strlen(class));
|
|
||||||
|
|
||||||
* Set _NET_WM_PID
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[net_wm_pid], XA_CARDINAL, 32,
|
|
||||||
PropModeReplace, (unsigned char*)&pid, 1);
|
|
||||||
|
|
||||||
* Set _NET_SHOWING_DESKTOP
|
|
||||||
XChangeProperty(W->dpy, W->root, W->net_atom[net_showing_desktop], XA_CARDINAL, 32,
|
|
||||||
PropModeReplace, (unsigned char*)&showing_desk, 1);
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ewmh_set_wm_state(Window w, int state)
|
|
||||||
{
|
|
||||||
unsigned char d[] = { state, None };
|
|
||||||
|
|
||||||
XChangeProperty(W->dpy, w, W->net_atom[wm_state],
|
|
||||||
W->net_atom[wm_state], 32, PropModeReplace, d, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef EWMH_H
|
|
||||||
#define EWMH_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
/* Ewmh hints list */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* ICCCM */
|
|
||||||
wm_state,
|
|
||||||
/* EWMH */
|
|
||||||
net_supported,
|
|
||||||
net_wm_name,
|
|
||||||
net_client_list,
|
|
||||||
net_frame_extents,
|
|
||||||
net_number_of_desktops,
|
|
||||||
net_current_desktop,
|
|
||||||
net_desktop_names,
|
|
||||||
net_desktop_geometry,
|
|
||||||
net_active_window,
|
|
||||||
net_close_window,
|
|
||||||
net_wm_icon_name,
|
|
||||||
net_wm_window_type,
|
|
||||||
net_wm_pid,
|
|
||||||
net_showing_desktop,
|
|
||||||
net_supporting_wm_check,
|
|
||||||
net_wm_window_opacity,
|
|
||||||
net_wm_window_type_normal,
|
|
||||||
net_wm_window_type_dock,
|
|
||||||
net_wm_window_type_splash,
|
|
||||||
net_wm_window_type_dialog,
|
|
||||||
net_wm_desktop,
|
|
||||||
net_wm_icon,
|
|
||||||
net_wm_state,
|
|
||||||
net_wm_state_fullscreen,
|
|
||||||
net_wm_state_sticky,
|
|
||||||
net_wm_state_demands_attention,
|
|
||||||
net_wm_system_tray_opcode,
|
|
||||||
net_system_tray_message_data,
|
|
||||||
net_system_tray_s,
|
|
||||||
net_system_tray_visual,
|
|
||||||
net_system_tray_orientation,
|
|
||||||
xembed,
|
|
||||||
xembedinfo,
|
|
||||||
manager,
|
|
||||||
utf8_string,
|
|
||||||
/* WMFS HINTS */
|
|
||||||
wmfs_running,
|
|
||||||
wmfs_update_hints,
|
|
||||||
wmfs_current_tag,
|
|
||||||
wmfs_current_screen,
|
|
||||||
wmfs_current_layout,
|
|
||||||
wmfs_tag_list,
|
|
||||||
wmfs_mwfact,
|
|
||||||
wmfs_nmaster,
|
|
||||||
wmfs_set_screen,
|
|
||||||
wmfs_screen_count,
|
|
||||||
wmfs_function,
|
|
||||||
wmfs_cmd,
|
|
||||||
wmfs_font,
|
|
||||||
wmfs_statustext,
|
|
||||||
net_last
|
|
||||||
};
|
|
||||||
|
|
||||||
void ewmh_init(void);
|
|
||||||
void ewmh_set_wm_state(Window w, int state);
|
|
||||||
|
|
||||||
#endif /* EWMH_H */
|
|
||||||
@ -1,246 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "draw.h"
|
|
||||||
#include "infobar.h"
|
|
||||||
#include "barwin.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "tag.h"
|
|
||||||
|
|
||||||
static void infobar_elem_tag_init(struct element *e);
|
|
||||||
static void infobar_elem_tag_update(struct element *e);
|
|
||||||
|
|
||||||
const struct elem_funcs
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
void (*func_init)(struct element *e);
|
|
||||||
void (*func_update)(struct element *e);
|
|
||||||
} elem_funcs[] =
|
|
||||||
{
|
|
||||||
{ 't', infobar_elem_tag_init, infobar_elem_tag_update },
|
|
||||||
|
|
||||||
/* { 'l', infobar_elem_layout_init, infobar_elem_layout_update },
|
|
||||||
{ 's', infobar_elem_selbar_init, infobar_elem_selbar_update },
|
|
||||||
{ 'S', infobar_elem_status_init, infobar_elem_status_update },*/
|
|
||||||
|
|
||||||
{ '\0', NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
infobar_elem_tag_init(struct element *e)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
struct barwin *b, *prev = NULL;
|
|
||||||
struct geo g = { 0, 0, 0, 0 };
|
|
||||||
int s, j;
|
|
||||||
|
|
||||||
infobar_elem_placement(e);
|
|
||||||
|
|
||||||
j = e->geo.x;
|
|
||||||
e->geo.h -= (e->infobar->theme->tags_border_width << 1);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(t, &e->infobar->screen->tags, next)
|
|
||||||
{
|
|
||||||
s = draw_textw(e->infobar->theme, t->name) + PAD;
|
|
||||||
|
|
||||||
/* Init barwin */
|
|
||||||
b = barwin_new(e->infobar->bar->win, j, 0, s, e->geo.h, 0, 0, false);
|
|
||||||
|
|
||||||
/* Set border */
|
|
||||||
if(e->infobar->theme->tags_border_width)
|
|
||||||
{
|
|
||||||
XSetWindowBorder(W->dpy, b->win, e->infobar->theme->tags_border_col);
|
|
||||||
XSetWindowBorderWidth(W->dpy, b->win, e->infobar->theme->tags_border_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
b->ptr = (void*)t;
|
|
||||||
barwin_map(b);
|
|
||||||
|
|
||||||
/* TODO: refer to tag element configuration */
|
|
||||||
barwin_mousebind_new(b, Button1, false, g, uicb_tag_set_with_name, (Uicb)t->name);
|
|
||||||
barwin_mousebind_new(b, Button4, false, g, uicb_tag_next, NULL);
|
|
||||||
barwin_mousebind_new(b, Button5, false, g, uicb_tag_prev, NULL);
|
|
||||||
|
|
||||||
/* insert_tail with SLIST */
|
|
||||||
if(SLIST_EMPTY(&e->bars))
|
|
||||||
SLIST_INSERT_HEAD(&e->bars, b, enext);
|
|
||||||
else
|
|
||||||
SLIST_INSERT_AFTER(prev, b, enext);
|
|
||||||
|
|
||||||
prev = b;
|
|
||||||
j += s;
|
|
||||||
}
|
|
||||||
|
|
||||||
e->infobar->screen->elemupdate |= FLAGINT(ElemTag);
|
|
||||||
|
|
||||||
e->geo.w = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
infobar_elem_tag_update(struct element *e)
|
|
||||||
{
|
|
||||||
struct tag *t, *sel = e->infobar->screen->seltag;
|
|
||||||
struct barwin *b;
|
|
||||||
|
|
||||||
SLIST_FOREACH(b, &e->bars, enext)
|
|
||||||
{
|
|
||||||
t = (struct tag*)b->ptr;
|
|
||||||
|
|
||||||
/* Selected */
|
|
||||||
/* TODO: color from conf */
|
|
||||||
if(t == sel)
|
|
||||||
{
|
|
||||||
b->fg = e->infobar->theme->tags_s.fg;
|
|
||||||
b->bg = e->infobar->theme->tags_s.bg;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b->fg = e->infobar->theme->tags_n.fg;
|
|
||||||
b->bg = e->infobar->theme->tags_n.bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
barwin_refresh_color(b);
|
|
||||||
|
|
||||||
draw_text(b->dr, e->infobar->theme, (PAD >> 1),
|
|
||||||
TEXTY(e->infobar->theme, e->geo.h), b->fg, t->name);
|
|
||||||
|
|
||||||
barwin_refresh(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
infobar_elem_init(struct infobar *i)
|
|
||||||
{
|
|
||||||
struct element *e;
|
|
||||||
int n, j;
|
|
||||||
|
|
||||||
TAILQ_INIT(&i->elements);
|
|
||||||
|
|
||||||
for(n = 0; n < strlen(i->elemorder); ++n)
|
|
||||||
{
|
|
||||||
for(j = 0; j < LEN(elem_funcs); ++j)
|
|
||||||
if(elem_funcs[j].c == i->elemorder[n])
|
|
||||||
{
|
|
||||||
e = xcalloc(1, sizeof(struct element));
|
|
||||||
|
|
||||||
SLIST_INIT(&e->bars);
|
|
||||||
|
|
||||||
e->infobar = i;
|
|
||||||
e->type = j;
|
|
||||||
e->func_init = elem_funcs[j].func_init;
|
|
||||||
e->func_update = elem_funcs[j].func_update;
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&i->elements, e, next);
|
|
||||||
|
|
||||||
e->func_init(e);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
infobar_elem_update(struct infobar *i)
|
|
||||||
{
|
|
||||||
struct element *e;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(e, &i->elements, next)
|
|
||||||
if(i->screen->elemupdate & FLAGINT(e->type))
|
|
||||||
e->func_update(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
infobar_elem_remove(struct element *e)
|
|
||||||
{
|
|
||||||
struct barwin *b;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct infobar*
|
|
||||||
infobar_new(struct screen *s, struct theme *theme, Barpos pos, const char *elem)
|
|
||||||
{
|
|
||||||
bool map;
|
|
||||||
struct infobar *i = (struct infobar*)xcalloc(1, sizeof(struct infobar));
|
|
||||||
|
|
||||||
i->screen = s;
|
|
||||||
i->theme = theme;
|
|
||||||
i->elemorder = xstrdup(elem);
|
|
||||||
|
|
||||||
map = infobar_placement(i, pos);
|
|
||||||
|
|
||||||
/* struct barwin create */
|
|
||||||
i->bar = barwin_new(W->root, i->geo.x, i->geo.y, i->geo.w, i->geo.h,
|
|
||||||
theme->bars.fg, theme->bars.bg, false);
|
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(&s->infobars, i, next);
|
|
||||||
|
|
||||||
/* struct elements */
|
|
||||||
infobar_elem_init(i);
|
|
||||||
|
|
||||||
/* Render, only if pos is Top or Bottom */
|
|
||||||
if(!map)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
barwin_map(i->bar);
|
|
||||||
barwin_map_subwin(i->bar);
|
|
||||||
barwin_refresh_color(i->bar);
|
|
||||||
infobar_refresh(i);
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
infobar_refresh(struct infobar *i)
|
|
||||||
{
|
|
||||||
infobar_elem_update(i);
|
|
||||||
|
|
||||||
barwin_refresh(i->bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
infobar_remove(struct infobar *i)
|
|
||||||
{
|
|
||||||
struct element *e;
|
|
||||||
|
|
||||||
free(i->elemorder);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(e, &i->elements, next)
|
|
||||||
infobar_elem_remove(e);
|
|
||||||
|
|
||||||
barwin_remove(i->bar);
|
|
||||||
|
|
||||||
SLIST_REMOVE(&i->screen->infobars, i, infobar, next);
|
|
||||||
|
|
||||||
free(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
infobar_free(struct screen *s)
|
|
||||||
{
|
|
||||||
struct infobar *i;
|
|
||||||
|
|
||||||
while(!SLIST_EMPTY(&s->infobars))
|
|
||||||
{
|
|
||||||
i = SLIST_FIRST(&s->infobars);
|
|
||||||
|
|
||||||
/* SLIST_REMOVE is done by infobar_remove */
|
|
||||||
infobar_remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INFOBAR_H
|
|
||||||
#define INFOBAR_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "draw.h"
|
|
||||||
#include "tag.h"
|
|
||||||
|
|
||||||
enum { ElemTag = 0, ElemLayout, ElemSelbar, ElemStatus, ElemCustom, ElemLast };
|
|
||||||
|
|
||||||
struct infobar *infobar_new(struct screen *s, struct theme *theme, Barpos pos, const char *elem);
|
|
||||||
void infobar_elem_update(struct infobar *i);
|
|
||||||
void infobar_refresh(struct infobar *i);
|
|
||||||
void infobar_remove(struct infobar *i);
|
|
||||||
void infobar_free(struct screen *s);
|
|
||||||
|
|
||||||
/* Basic placement of elements */
|
|
||||||
static inline void
|
|
||||||
infobar_elem_placement(struct element *e)
|
|
||||||
{
|
|
||||||
struct element *p = TAILQ_PREV(e, esub, next);
|
|
||||||
|
|
||||||
e->geo.y = e->geo.w = 0;
|
|
||||||
e->geo.h = e->infobar->geo.h;
|
|
||||||
e->geo.x = (p ? p->geo.x + p->geo.w + PAD : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bars placement management and usable space management */
|
|
||||||
static inline bool
|
|
||||||
infobar_placement(struct infobar *i, Barpos p)
|
|
||||||
{
|
|
||||||
i->pos = p;
|
|
||||||
i->geo = i->screen->ugeo;
|
|
||||||
i->geo.h = i->theme->bars_width;
|
|
||||||
|
|
||||||
switch(p)
|
|
||||||
{
|
|
||||||
case BarTop:
|
|
||||||
i->screen->ugeo.y += i->geo.h;
|
|
||||||
i->screen->ugeo.h -= i->geo.h;
|
|
||||||
break;
|
|
||||||
case BarBottom:
|
|
||||||
i->geo.y = (i->screen->ugeo.y + i->screen->ugeo.h) - i->geo.h;
|
|
||||||
i->screen->ugeo.h -= i->geo.h;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case BarHide:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tag_update_frame_geo(i->screen);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
infobar_elem_screen_update(struct screen *s, int addf)
|
|
||||||
{
|
|
||||||
struct infobar *i;
|
|
||||||
|
|
||||||
s->elemupdate |= FLAGINT(addf);
|
|
||||||
|
|
||||||
SLIST_FOREACH(i, &s->infobars, next)
|
|
||||||
infobar_elem_update(i);
|
|
||||||
|
|
||||||
s->elemupdate &= ~FLAGINT(ElemTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* INFOBAR_H */
|
|
||||||
@ -1,312 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "layout.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static struct geo
|
|
||||||
layout_split(struct client *c, bool vertical)
|
|
||||||
{
|
|
||||||
struct geo og, geo;
|
|
||||||
|
|
||||||
geo = og = c->geo;
|
|
||||||
|
|
||||||
if(vertical)
|
|
||||||
{
|
|
||||||
c->geo.w >>= 1;
|
|
||||||
geo.x = c->geo.x + c->geo.w;
|
|
||||||
geo.w >>= 1;
|
|
||||||
|
|
||||||
/* Remainder */
|
|
||||||
geo.w += (og.x + og.w) - (geo.x + geo.w);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c->geo.h >>= 1;
|
|
||||||
geo.y = c->geo.y + c->geo.h;
|
|
||||||
geo.h >>= 1;
|
|
||||||
|
|
||||||
/* Remainder */
|
|
||||||
geo.h += (og.y + og.h) - (geo.y + geo.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
|
|
||||||
return geo;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
layout_split_arrange_size(struct geo g, struct client *c, Position p)
|
|
||||||
{
|
|
||||||
if(LDIR(p))
|
|
||||||
{
|
|
||||||
c->geo.w += g.w;
|
|
||||||
|
|
||||||
if(p == Right)
|
|
||||||
c->geo.x = g.x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c->geo.h += g.h;
|
|
||||||
|
|
||||||
if(p == Bottom)
|
|
||||||
c->geo.y = g.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
layout_split_check_row_dir(struct client *c, struct client *g, Position p)
|
|
||||||
{
|
|
||||||
struct geo cgeo = c->geo;
|
|
||||||
struct client *cc;
|
|
||||||
int s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w);
|
|
||||||
|
|
||||||
SLIST_FOREACH(cc, &c->tag->clients, tnext)
|
|
||||||
if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p))
|
|
||||||
&& GEO_CHECK_ROW(cc->geo, g->geo, p))
|
|
||||||
{
|
|
||||||
s += (LDIR(p) ? cc->geo.h : cc->geo.w);
|
|
||||||
|
|
||||||
if(s == cs)
|
|
||||||
return true;
|
|
||||||
if(s > cs)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use ghost client properties to fix holes in tile
|
|
||||||
*
|
|
||||||
* ~ .--. ~ ~
|
|
||||||
*_____ ~ /xx \ ~ ~
|
|
||||||
* |>>| ~\O _ (____ ~
|
|
||||||
* | |__.| .--'-==~ ~
|
|
||||||
* |>>'---\ '. ~ , ~
|
|
||||||
*__|__| '. '-.___.-'/ ~
|
|
||||||
* '-.__ _.' ~
|
|
||||||
* ````` ~
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
layout_split_arrange_closed(struct client *ghost)
|
|
||||||
{
|
|
||||||
struct client *c, *cc;
|
|
||||||
struct geo g;
|
|
||||||
bool b = false;
|
|
||||||
Position p;
|
|
||||||
|
|
||||||
|
|
||||||
/* 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) /* Check every direction */
|
|
||||||
{
|
|
||||||
if((c = client_next_with_pos(ghost, p)))
|
|
||||||
if(GEO_CHECK2(ghost->geo, c->geo, p))
|
|
||||||
{
|
|
||||||
layout_split_arrange_size(ghost->geo, c, p);
|
|
||||||
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_next_with_pos(ghost, p))
|
|
||||||
&& layout_split_check_row_dir(c, ghost, p))
|
|
||||||
{
|
|
||||||
g = c->geo;
|
|
||||||
SLIST_FOREACH(cc, &c->tag->clients, tnext)
|
|
||||||
if(GEO_PARENTROW(g, cc->geo, RPOS(p))
|
|
||||||
&& GEO_CHECK_ROW(cc->geo, ghost->geo, p))
|
|
||||||
{
|
|
||||||
layout_split_arrange_size(ghost->geo, cc, p);
|
|
||||||
b = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Integrate a client in split layout: split sc and fill c in new geo */
|
|
||||||
void
|
|
||||||
layout_split_integrate(struct client *c, struct client *sc)
|
|
||||||
{
|
|
||||||
struct geo g;
|
|
||||||
|
|
||||||
/* No sc */
|
|
||||||
if(!sc || sc == c || sc->tag != c->tag)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Not even a first client in list, then
|
|
||||||
* maximize the lonely client
|
|
||||||
*/
|
|
||||||
if(!(sc = SLIST_FIRST(&c->tag->clients)))
|
|
||||||
{
|
|
||||||
client_maximize(c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g = layout_split(sc, (sc->geo.h < sc->geo.w));
|
|
||||||
client_moveresize(c, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Arrange inter-clients holes:
|
|
||||||
* ___________ ___________
|
|
||||||
* | || | -> | | |
|
|
||||||
* | A || B | -> | A >| B |
|
|
||||||
* | || | -> | >| |
|
|
||||||
* |_____||____| -> |______|____|
|
|
||||||
* ^ void
|
|
||||||
*
|
|
||||||
* and client-screen edge holes
|
|
||||||
* ___________ ___________
|
|
||||||
* | | || -> | | |
|
|
||||||
* | A | B || -> | A | B >|
|
|
||||||
* | | || -> | | >|
|
|
||||||
* |_____|----'| -> |_____|__v__|
|
|
||||||
* ^^^ void
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
layout_fix_hole(struct client *c)
|
|
||||||
{
|
|
||||||
struct client *cr = client_next_with_pos(c, Right);
|
|
||||||
struct client *cb = client_next_with_pos(c, Bottom);
|
|
||||||
|
|
||||||
c->geo.w += (cr ? cr->geo.x : c->screen->ugeo.w) - (c->geo.x + c->geo.w);
|
|
||||||
c->geo.h += (cb ? cb->geo.y : c->screen->ugeo.h) - (c->geo.y + c->geo.h);
|
|
||||||
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Layout rotation: Rotate 90° all client to right or left.
|
|
||||||
* Avoid if(left) condition in layout_rotate loop; use func ptr
|
|
||||||
*
|
|
||||||
* Left rotation
|
|
||||||
* ____________ ____________
|
|
||||||
* | | B | -> | | A |
|
|
||||||
* | A |_______| -> |__|_________|
|
|
||||||
* |____| C | D | -> |_____| B |
|
|
||||||
* |____|___|___| -> |_____|______|
|
|
||||||
*
|
|
||||||
* Right rotation
|
|
||||||
* ____________ ____________
|
|
||||||
* | | B | -> | B |_____|
|
|
||||||
* | A |_______| -> |______|_____|
|
|
||||||
* |____| C | D | -> | A | |
|
|
||||||
* |____|___|___| -> |_________|__|
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
_pos_rotate_left(struct geo *g, struct geo ug, struct geo og)
|
|
||||||
{
|
|
||||||
g->x = (ug.h - (og.y + og.h));
|
|
||||||
g->y = og.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
_pos_rotate_right(struct geo *g, struct geo ug, struct geo og)
|
|
||||||
{
|
|
||||||
g->x = og.y;
|
|
||||||
g->y = (ug.w - (og.x + og.w));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
layout_rotate(struct tag *t, bool left)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
struct geo g;
|
|
||||||
float f1 = (float)t->screen->ugeo.w / (float)t->screen->ugeo.h;
|
|
||||||
float f2 = 1 / f1;
|
|
||||||
void (*pos)(struct geo*, struct geo, struct geo) =
|
|
||||||
(left ? _pos_rotate_left : _pos_rotate_right);
|
|
||||||
|
|
||||||
SLIST_FOREACH(c, &t->clients, tnext)
|
|
||||||
{
|
|
||||||
pos(&g, t->screen->ugeo, c->geo);
|
|
||||||
|
|
||||||
g.x *= f1;
|
|
||||||
g.y *= f2;
|
|
||||||
g.w = c->geo.h * f1;
|
|
||||||
g.h = c->geo.w * f2;
|
|
||||||
|
|
||||||
client_moveresize(c, g);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rotate sometimes do not set back perfect size.. */
|
|
||||||
SLIST_FOREACH(c, &t->clients, tnext)
|
|
||||||
layout_fix_hole(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_layout_rotate_left(Uicb cmd)
|
|
||||||
{
|
|
||||||
layout_rotate(W->screen->seltag, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_layout_rotate_right(Uicb cmd)
|
|
||||||
{
|
|
||||||
layout_rotate(W->screen->seltag, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Really simple functions, don't need static no-uicb backend
|
|
||||||
* so we avoid the use of if(vertical) .. else
|
|
||||||
*
|
|
||||||
* Vertical mirror
|
|
||||||
* ____________ ____________
|
|
||||||
* | | B | -> | B | |
|
|
||||||
* | A |_______| -> |_______| A |
|
|
||||||
* | | C | D | -> | D | C | |
|
|
||||||
* |____|___|___| -> |___|___|____|
|
|
||||||
*
|
|
||||||
* Horizontal mirror
|
|
||||||
* ____________ ____________
|
|
||||||
* | | B | -> | | C | D |
|
|
||||||
* | A |_______| -> | A |___|___|
|
|
||||||
* | | C | D | -> | | B |
|
|
||||||
* |____|___|___| -> |____|_______|
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
uicb_layout_vmirror(Uicb cmd)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext)
|
|
||||||
{
|
|
||||||
c->geo.x = W->screen->ugeo.w - (c->geo.x + c->geo.w);
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_layout_hmirror(Uicb cmd)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext)
|
|
||||||
{
|
|
||||||
c->geo.y = W->screen->ugeo.h - (c->geo.y + c->geo.h);
|
|
||||||
client_moveresize(c, c->geo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LAYOUT_H
|
|
||||||
#define LAYOUT_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
/* Check lateral direction (if p is Right or Left) */
|
|
||||||
#define LDIR(P) (P < Top)
|
|
||||||
|
|
||||||
/* Reverse position */
|
|
||||||
#define RPOS(P) (P & 1 ? P - 1 : P + 1)
|
|
||||||
|
|
||||||
/* geo comparaison */
|
|
||||||
#define GEO_CHECK2(g1, g2, p) (LDIR(p) ? ((g1).h == (g2).h) : ((g1).w == (g2).w))
|
|
||||||
#define GEO_CHECK_ROW(g1, g2, p) \
|
|
||||||
(LDIR(p) \
|
|
||||||
? ((g1).y >= (g2).y && ((g1).y + (g1).h) <= ((g2).y + (g2).h)) \
|
|
||||||
: ((g1).x >= (g2).x && ((g1).x + (g1).w) <= ((g2).x + (g2).w)))
|
|
||||||
#define GEO_PARENTROW(g1, g2, p) \
|
|
||||||
(LDIR(p) \
|
|
||||||
? (p == Left ? ((g1).x == (g2).x) : ((g1).x + (g1).w == (g2).x + (g2).w)) \
|
|
||||||
: (p == Top ? ((g1).y == (g2).y) : ((g1).y + (g1).h == (g2).y + (g2).h)))
|
|
||||||
|
|
||||||
|
|
||||||
/* Debug */
|
|
||||||
#define DGEO(G) printf(": %d %d %d %d\n", G.x, G.y, G.w, G.h)
|
|
||||||
|
|
||||||
void layout_split_integrate(struct client *c, struct client *sc);
|
|
||||||
void layout_split_arrange_closed(struct client *ghost);
|
|
||||||
void uicb_layout_vmirror(Uicb cmd);
|
|
||||||
void uicb_layout_hmirror(Uicb cmd);
|
|
||||||
void uicb_layout_rotate_left(Uicb cmd);
|
|
||||||
void uicb_layout_rotate_right(Uicb cmd);
|
|
||||||
|
|
||||||
#endif /* LAYOUT_H */
|
|
||||||
|
|
||||||
@ -1,693 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
|
||||||
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
#ifndef _BSD_SOURCE
|
|
||||||
#define _BSD_SOURCE
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <err.h>
|
|
||||||
|
|
||||||
#include "parse.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern char *__progname;
|
|
||||||
|
|
||||||
enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE };
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static const struct
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
enum keyword_t type;
|
|
||||||
} kw_t_name[] =
|
|
||||||
{
|
|
||||||
{"SEC_START", SEC_START},
|
|
||||||
{"SEC_END", SEC_END},
|
|
||||||
{"INCLUDE", INCLUDE},
|
|
||||||
{"WORD", WORD},
|
|
||||||
{"EQUAL", EQUAL},
|
|
||||||
{"LIST_START", LIST_START},
|
|
||||||
{"LIST_END", LIST_END},
|
|
||||||
{"NONE", NONE},
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct files
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
struct files *parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct keyword
|
|
||||||
{
|
|
||||||
enum keyword_t type;
|
|
||||||
/* if WORD */
|
|
||||||
int line;
|
|
||||||
struct files *file;
|
|
||||||
char *name;
|
|
||||||
struct keyword *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct state
|
|
||||||
{
|
|
||||||
bool quote;
|
|
||||||
bool comment;
|
|
||||||
char quote_char;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TO REMOVE (use a identifier for config and fallback XDG in api functions) */
|
|
||||||
TAILQ_HEAD(, conf_sec) config;
|
|
||||||
static struct keyword *keywords = NULL;
|
|
||||||
|
|
||||||
static struct keyword *
|
|
||||||
push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offset, struct files *file, int line)
|
|
||||||
{
|
|
||||||
struct keyword *kw;
|
|
||||||
#ifdef DEBUG
|
|
||||||
int i = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(type == WORD && *offset == 0)
|
|
||||||
return tail;
|
|
||||||
|
|
||||||
kw = xcalloc(1, sizeof(*kw));
|
|
||||||
kw->type = type;
|
|
||||||
kw->line = line;
|
|
||||||
kw->file = file;
|
|
||||||
kw->next = NULL;
|
|
||||||
|
|
||||||
if(*offset)
|
|
||||||
{
|
|
||||||
buf[*offset] = '\0';
|
|
||||||
|
|
||||||
if(!strcmp(buf, INCLUDE_CMD))
|
|
||||||
kw->type = INCLUDE;
|
|
||||||
else
|
|
||||||
kw->name = strdup(buf);
|
|
||||||
|
|
||||||
*offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
kw->name = NULL;
|
|
||||||
|
|
||||||
if(tail)
|
|
||||||
tail->next = kw;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
for(i = 0; kw_t_name[i].type != NONE; ++i)
|
|
||||||
if(kw_t_name[i].type == kw->type)
|
|
||||||
warnx("%s %s %s:%d\n", kw_t_name[i].name,
|
|
||||||
(kw->name) ? kw->name : "",
|
|
||||||
kw->file->name, kw->line);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return kw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
syntax(struct keyword *kw, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:", __progname);
|
|
||||||
|
|
||||||
if(kw && kw->file && kw->file->name)
|
|
||||||
fprintf(stderr, "%s:%d", kw->file->name, kw->line);
|
|
||||||
|
|
||||||
if(kw && kw->name)
|
|
||||||
fprintf(stderr, ", near '%s'", kw->name);
|
|
||||||
fprintf(stderr, ": ");
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define PUSH_KEYWORD(type) tail = push_keyword(tail, type, bufname, &j, file, line)
|
|
||||||
static struct keyword *
|
|
||||||
parse_keywords(const char *filename)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct stat st;
|
|
||||||
char *buf;
|
|
||||||
struct keyword *head = NULL;
|
|
||||||
struct keyword *tail = NULL;
|
|
||||||
struct files *file;
|
|
||||||
enum keyword_t type; /* keyword type to push */
|
|
||||||
struct state s = { false, false, '\0'};
|
|
||||||
char *bufname;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
size_t i, j;
|
|
||||||
int line;
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
|
|
||||||
if((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1)
|
|
||||||
{
|
|
||||||
warn("%s", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!st.st_size)
|
|
||||||
{
|
|
||||||
warnx("%s: empty file", filename);
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!realpath(filename, path))
|
|
||||||
{
|
|
||||||
warn("%s", filename);
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = xmalloc(1, st.st_size + 1);
|
|
||||||
|
|
||||||
if(read(fd, buf, st.st_size) == -1)
|
|
||||||
{
|
|
||||||
warn("%s", filename);
|
|
||||||
free(buf);
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[st.st_size] = '\0';
|
|
||||||
|
|
||||||
file = xcalloc(1, sizeof(*file));
|
|
||||||
bufname = xcalloc(BUFSIZ, sizeof(*bufname));
|
|
||||||
file->name = strdup(path);
|
|
||||||
file->parent = NULL;
|
|
||||||
|
|
||||||
for(i = j = 0, line = 1; i < (size_t)st.st_size; ++i)
|
|
||||||
{
|
|
||||||
if(!head && tail)
|
|
||||||
head = tail;
|
|
||||||
|
|
||||||
if(buf[i] == '\n' && s.comment)
|
|
||||||
{
|
|
||||||
line++;
|
|
||||||
s.comment = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == '#' && !s.quote)
|
|
||||||
{
|
|
||||||
s.comment = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s.comment)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* end of quotted string */
|
|
||||||
if(s.quote && buf[i] == s.quote_char)
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
s.quote = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!s.quote)
|
|
||||||
{
|
|
||||||
if((buf[i] == '"' || buf[i] == '\''))
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
/* begin quotted string */
|
|
||||||
s.quote_char = buf[i];
|
|
||||||
s.quote = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == '[')
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
|
|
||||||
if(buf[i + 1] == '/')
|
|
||||||
{
|
|
||||||
i += 2;
|
|
||||||
type = SEC_END;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
type = SEC_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get section name */
|
|
||||||
while(buf[i] != ']')
|
|
||||||
{
|
|
||||||
if(i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1))
|
|
||||||
{
|
|
||||||
bufname[j] = '\0';
|
|
||||||
syntax(NULL, "word too long in %s:%d near '%s'",
|
|
||||||
file->name, line, bufname);
|
|
||||||
error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bufname[j++] = buf[i++];
|
|
||||||
}
|
|
||||||
PUSH_KEYWORD(type);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == '{')
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
PUSH_KEYWORD(LIST_START);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == '}')
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
PUSH_KEYWORD(LIST_END);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == ',')
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(buf[i] == '=')
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
PUSH_KEYWORD(EQUAL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(strchr("\t\n ", buf[i]))
|
|
||||||
{
|
|
||||||
PUSH_KEYWORD(WORD);
|
|
||||||
|
|
||||||
if(buf[i] == '\n')
|
|
||||||
++line;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(j >= (BUFSIZ - 1))
|
|
||||||
{
|
|
||||||
bufname[j] = '\0';
|
|
||||||
syntax(NULL, "word too long in %s:%d near '%s'",
|
|
||||||
file->name, line, bufname);
|
|
||||||
error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufname[j++] = buf[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
free(bufname);
|
|
||||||
close(fd);
|
|
||||||
warnx("%s read", file->name);
|
|
||||||
|
|
||||||
return (error ? NULL: head);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* return NULL on failure and head->next if
|
|
||||||
* no config found (of file doesn't exist)
|
|
||||||
* NOTE to devs: head->name is the file to include
|
|
||||||
*/
|
|
||||||
static struct keyword *
|
|
||||||
include(struct keyword *head)
|
|
||||||
{
|
|
||||||
struct keyword *kw;
|
|
||||||
struct keyword *tail;
|
|
||||||
struct files *file;
|
|
||||||
struct passwd *user;
|
|
||||||
char *filename = NULL;
|
|
||||||
char *base = NULL;
|
|
||||||
|
|
||||||
head = head->next;
|
|
||||||
|
|
||||||
if(!head || head->type != WORD)
|
|
||||||
{
|
|
||||||
syntax(head, "missing filename to include");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* replace ~ by user directory */
|
|
||||||
if(head->name && head->name[0] == '~')
|
|
||||||
{
|
|
||||||
if((user = getpwuid(getuid())) && user->pw_dir)
|
|
||||||
xasprintf(&filename, "%s%s", user->pw_dir, head->name + 1);
|
|
||||||
else if(getenv("HOME"))
|
|
||||||
xasprintf(&filename, "%s%s", getenv("HOME"), head->name + 1);
|
|
||||||
else /* to warning ? */
|
|
||||||
filename = head->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relative path from parent file */
|
|
||||||
else if(head->name && head->name[0] != '/')
|
|
||||||
{
|
|
||||||
base = strdup(head->file->name);
|
|
||||||
xasprintf(&filename, "%s/%s", dirname(base), head->name);
|
|
||||||
free(base);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
filename = head->name;
|
|
||||||
|
|
||||||
if(!(kw = parse_keywords(filename)))
|
|
||||||
{
|
|
||||||
warnx("no config found in include file %s", head->name);
|
|
||||||
|
|
||||||
if(filename != head->name)
|
|
||||||
free(filename);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kw->file->parent = head->file;
|
|
||||||
|
|
||||||
/* detect circular include */
|
|
||||||
for(file = kw->file->parent; file != NULL; file = file->parent)
|
|
||||||
if(!strcmp(file->name, kw->file->name))
|
|
||||||
{
|
|
||||||
syntax(kw, "circular include of %s", kw->file->name);
|
|
||||||
|
|
||||||
if(filename != head->name)
|
|
||||||
free(filename);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(filename != head->name)
|
|
||||||
free(filename);
|
|
||||||
|
|
||||||
head = head->next;
|
|
||||||
|
|
||||||
if(kw)
|
|
||||||
{
|
|
||||||
for(tail = kw; tail->next; tail = tail->next);
|
|
||||||
tail->next = head;
|
|
||||||
}
|
|
||||||
|
|
||||||
return kw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
free_opt(struct conf_opt *o)
|
|
||||||
{
|
|
||||||
free(o);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct conf_opt *
|
|
||||||
get_option(struct keyword **head)
|
|
||||||
{
|
|
||||||
struct conf_opt *o;
|
|
||||||
size_t j = 0;
|
|
||||||
struct keyword *kw = *head;
|
|
||||||
|
|
||||||
o = xcalloc(1, sizeof(*o));
|
|
||||||
o->name = kw->name;
|
|
||||||
o->used = false;
|
|
||||||
o->line = kw->line;
|
|
||||||
o->filename = kw->file->name;
|
|
||||||
|
|
||||||
kw = kw->next;
|
|
||||||
|
|
||||||
if(kw->type != EQUAL)
|
|
||||||
{
|
|
||||||
syntax(kw, "missing '=' here");
|
|
||||||
return free_opt(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(kw = kw->next))
|
|
||||||
{
|
|
||||||
syntax(kw, "missing value");
|
|
||||||
return free_opt(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(kw->type)
|
|
||||||
{
|
|
||||||
case INCLUDE:
|
|
||||||
if(!(kw = include(kw)))
|
|
||||||
return free_opt(o);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WORD:
|
|
||||||
o->val[0] = kw->name;
|
|
||||||
o->val[1] = NULL;
|
|
||||||
kw = kw->next;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LIST_START:
|
|
||||||
kw = kw->next;
|
|
||||||
|
|
||||||
while(kw && kw->type != LIST_END)
|
|
||||||
{
|
|
||||||
switch(kw->type)
|
|
||||||
{
|
|
||||||
case WORD:
|
|
||||||
if(j >= (PARSE_MAX_LIST - 1))
|
|
||||||
{
|
|
||||||
syntax(kw, "too much values in list");
|
|
||||||
return free_opt(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
o->val[j++] = kw->name;
|
|
||||||
kw = kw->next;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INCLUDE:
|
|
||||||
if(!(kw = include(kw)))
|
|
||||||
return free_opt(o);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syntax(kw, "declaration into a list");
|
|
||||||
return free_opt(o);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!kw)
|
|
||||||
{
|
|
||||||
syntax(kw, "list unclosed");
|
|
||||||
return free_opt(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
kw = kw->next;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syntax(kw, "missing value");
|
|
||||||
return free_opt(o);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*head = kw;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
free_sec(struct conf_sec *sec)
|
|
||||||
{
|
|
||||||
struct conf_opt *o;
|
|
||||||
struct conf_sec *s;
|
|
||||||
|
|
||||||
if(sec)
|
|
||||||
{
|
|
||||||
while(!SLIST_EMPTY(&sec->optlist))
|
|
||||||
{
|
|
||||||
o = SLIST_FIRST(&sec->optlist);
|
|
||||||
SLIST_REMOVE_HEAD(&sec->optlist, entry);
|
|
||||||
free_opt(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(!TAILQ_EMPTY(&sec->sub))
|
|
||||||
{
|
|
||||||
s = TAILQ_FIRST(&sec->sub);
|
|
||||||
TAILQ_REMOVE(&sec->sub, s, entry);
|
|
||||||
free_sec(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct conf_sec *
|
|
||||||
get_section(struct keyword **head)
|
|
||||||
{
|
|
||||||
struct conf_sec *s;
|
|
||||||
struct conf_opt *o;
|
|
||||||
struct conf_sec *sub;
|
|
||||||
struct keyword *kw = *head;
|
|
||||||
|
|
||||||
s = xcalloc(1, sizeof(*s));
|
|
||||||
s->name = kw->name;
|
|
||||||
|
|
||||||
TAILQ_INIT(&s->sub);
|
|
||||||
SLIST_INIT(&s->optlist);
|
|
||||||
|
|
||||||
kw = kw->next;
|
|
||||||
|
|
||||||
while(kw && kw->type != SEC_END)
|
|
||||||
{
|
|
||||||
switch(kw->type)
|
|
||||||
{
|
|
||||||
case INCLUDE:
|
|
||||||
if(!(kw = include(kw)))
|
|
||||||
return free_sec(s);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEC_START:
|
|
||||||
if(!(sub = get_section(&kw)))
|
|
||||||
return free_sec(s);
|
|
||||||
TAILQ_INSERT_TAIL(&s->sub, sub, entry);
|
|
||||||
++s->nsub;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WORD:
|
|
||||||
if(!(o = get_option(&kw)))
|
|
||||||
return free_sec(s);
|
|
||||||
SLIST_INSERT_HEAD(&s->optlist, o, entry);
|
|
||||||
++s->nopt;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syntax(kw, "syntax error");
|
|
||||||
return free_sec(s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!kw || strcmp(kw->name, s->name))
|
|
||||||
{
|
|
||||||
syntax(kw, "missing end section %s", s->name);
|
|
||||||
return free_sec(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
kw = kw->next;
|
|
||||||
*head = kw;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
free_conf(void)
|
|
||||||
{
|
|
||||||
struct conf_sec *s;
|
|
||||||
struct keyword *kw, *nkw;
|
|
||||||
struct files **f = NULL;
|
|
||||||
int i, nf = 0;
|
|
||||||
|
|
||||||
while(!TAILQ_EMPTY(&config))
|
|
||||||
{
|
|
||||||
s = TAILQ_FIRST(&config);
|
|
||||||
TAILQ_REMOVE(&config, s, entry);
|
|
||||||
free_sec(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
kw = keywords;
|
|
||||||
|
|
||||||
while(kw)
|
|
||||||
{
|
|
||||||
nkw = kw->next;
|
|
||||||
|
|
||||||
free(kw->name);
|
|
||||||
|
|
||||||
for(i = 0; i < nf; ++i)
|
|
||||||
if(f[i] == kw->file)
|
|
||||||
{
|
|
||||||
if(!(f = realloc(f, sizeof(*f) * (++i))))
|
|
||||||
err(EXIT_FAILURE, "realloc");
|
|
||||||
|
|
||||||
f[i - 1] = kw->file;
|
|
||||||
}
|
|
||||||
|
|
||||||
kw = nkw;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nf > 0)
|
|
||||||
{
|
|
||||||
for(i = 0; i < nf; ++i)
|
|
||||||
{
|
|
||||||
free(f[i]->name);
|
|
||||||
free(f[i]);
|
|
||||||
}
|
|
||||||
free(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_conf(const char *filename)
|
|
||||||
{
|
|
||||||
struct conf_sec *s;
|
|
||||||
struct keyword *head, *kw;
|
|
||||||
|
|
||||||
head = kw = parse_keywords(filename);
|
|
||||||
|
|
||||||
if(!head)
|
|
||||||
return -1; /* TODO ERREUR */
|
|
||||||
|
|
||||||
keywords = head;
|
|
||||||
|
|
||||||
TAILQ_INIT(&config);
|
|
||||||
|
|
||||||
while(kw)
|
|
||||||
{
|
|
||||||
switch(kw->type)
|
|
||||||
{
|
|
||||||
case INCLUDE:
|
|
||||||
if(!(kw = include(kw)))
|
|
||||||
return free_conf();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SEC_START:
|
|
||||||
if(!(s = get_section(&kw)))
|
|
||||||
return free_conf();
|
|
||||||
TAILQ_INSERT_TAIL(&config, s, entry);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
syntax(kw, "out of any section");
|
|
||||||
return free_conf();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
|
||||||
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PARSE_H
|
|
||||||
#define PARSE_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
#define INCLUDE_CMD "@include"
|
|
||||||
#define PARSE_MAX_LIST 32
|
|
||||||
|
|
||||||
struct conf_opt
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
char *val[PARSE_MAX_LIST];
|
|
||||||
size_t nval;
|
|
||||||
bool used;
|
|
||||||
int line;
|
|
||||||
char *filename;
|
|
||||||
SLIST_ENTRY(conf_opt) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct conf_sec
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
SLIST_HEAD(, conf_opt) optlist;
|
|
||||||
TAILQ_HEAD(cshead, conf_sec) sub;
|
|
||||||
size_t nopt;
|
|
||||||
size_t nsub;
|
|
||||||
TAILQ_ENTRY(conf_sec) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct opt_type
|
|
||||||
{
|
|
||||||
long int num;
|
|
||||||
float fnum;
|
|
||||||
bool boolean;
|
|
||||||
char *str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create config from file
|
|
||||||
* return -1 on failure
|
|
||||||
*/
|
|
||||||
int get_conf(const char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print unused option name from section s (and subsections).
|
|
||||||
* If s == NULL print unused option name for all config struct.
|
|
||||||
*/
|
|
||||||
void print_unused(struct conf_sec *s);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free the config struct.
|
|
||||||
* WARNING: This make all string
|
|
||||||
* returned by fetch_(opt|section)(_first) unusable.
|
|
||||||
*/
|
|
||||||
int free_conf(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get all subsection matching the given name on the given
|
|
||||||
* section.
|
|
||||||
* If section == NULL, return subsections from root section.
|
|
||||||
* Return a NULL terminated array.
|
|
||||||
* Subsections are returned in order as they are in config file
|
|
||||||
* WARNING : This MUST be free() after use.
|
|
||||||
*/
|
|
||||||
struct conf_sec **fetch_section(struct conf_sec *, char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get first subsection matching the given name
|
|
||||||
* on the given section. (first found on the file)
|
|
||||||
*/
|
|
||||||
struct conf_sec *fetch_section_first(struct conf_sec *, char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count member of a conf_sec **
|
|
||||||
*/
|
|
||||||
size_t fetch_section_count(struct conf_sec **);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return all options matching the given name on the given subsection.
|
|
||||||
* If none match or section == NULL return opt_type build with the
|
|
||||||
* given default param.
|
|
||||||
* WARNING: This MUST be free() after use.
|
|
||||||
* WARNING: The string member is directly taken from the config struct.
|
|
||||||
* WARNING: Returned in reverse order as they are in config file.
|
|
||||||
* (I think the last option MUST overwrite all others)
|
|
||||||
*/
|
|
||||||
struct opt_type fetch_opt_first(struct conf_sec *, char *, char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get first (last in config file) option matching the given name
|
|
||||||
* on the given section.
|
|
||||||
* WARNING: The string member is directly taken from the config struct.
|
|
||||||
*/
|
|
||||||
struct opt_type *fetch_opt(struct conf_sec *, char *, char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count member of a opt_type *
|
|
||||||
*/
|
|
||||||
size_t fetch_opt_count(struct opt_type *);
|
|
||||||
|
|
||||||
#endif /* PARSE_H */
|
|
||||||
@ -1,214 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
|
||||||
* Copyright (c) 2011 Martin Duquesnoy <xorg62@gmail.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BSD_SOURCE
|
|
||||||
#define _BSD_SOURCE
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <err.h>
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "parse.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern TAILQ_HEAD(, conf_sec) config;
|
|
||||||
|
|
||||||
static const struct opt_type opt_type_null = { 0, 0, false, NULL };
|
|
||||||
|
|
||||||
static struct opt_type
|
|
||||||
string_to_opt(char *s)
|
|
||||||
{
|
|
||||||
struct opt_type ret = opt_type_null;
|
|
||||||
|
|
||||||
if(!s || !strlen(s))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret.num = strtol(s, (char**)NULL, 10);
|
|
||||||
ret.fnum = strtod(s, NULL);
|
|
||||||
|
|
||||||
ret.boolean = (!strcmp(s, "true")
|
|
||||||
|| !strcmp(s, "true")
|
|
||||||
|| !strcmp(s, "TRUE")
|
|
||||||
|| !strcmp(s, "1"));
|
|
||||||
|
|
||||||
ret.str = s;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
print_unused(struct conf_sec *sec)
|
|
||||||
{
|
|
||||||
struct conf_sec *s;
|
|
||||||
struct conf_opt *o;
|
|
||||||
|
|
||||||
if(!sec)
|
|
||||||
{
|
|
||||||
TAILQ_FOREACH(s, &config, entry)
|
|
||||||
print_unused(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLIST_FOREACH(o, &sec->optlist, entry)
|
|
||||||
if(!o->used)
|
|
||||||
warnx("%s:%d, unused param %s", o->filename, o->line, o->name);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(s, &sec->sub, entry)
|
|
||||||
if(!TAILQ_EMPTY(&s->sub))
|
|
||||||
print_unused(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct conf_sec **
|
|
||||||
fetch_section(struct conf_sec *s, char *name)
|
|
||||||
{
|
|
||||||
struct conf_sec **ret;
|
|
||||||
struct conf_sec *sec;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
if(!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if(!s)
|
|
||||||
{
|
|
||||||
ret = xcalloc(2, sizeof(struct conf_sec *));
|
|
||||||
|
|
||||||
TAILQ_FOREACH(sec, &config, entry)
|
|
||||||
if(!strcmp(sec->name, name))
|
|
||||||
{
|
|
||||||
ret[0] = sec;
|
|
||||||
ret[1] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = xcalloc(s->nsub + 1, sizeof(struct conf_sec *));
|
|
||||||
|
|
||||||
TAILQ_FOREACH(sec, &s->sub, entry)
|
|
||||||
if(!strcmp(sec->name, name) && i < s->nsub)
|
|
||||||
ret[i++] = sec;
|
|
||||||
|
|
||||||
ret[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct conf_sec *
|
|
||||||
fetch_section_first(struct conf_sec *s, char *name)
|
|
||||||
{
|
|
||||||
struct conf_sec *sec, *ret = NULL;
|
|
||||||
TAILQ_HEAD(cshead, conf_sec) *head =
|
|
||||||
(s
|
|
||||||
? (struct cshead*)&s->sub
|
|
||||||
: (struct cshead*)&config);
|
|
||||||
|
|
||||||
if(!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(sec, head, entry)
|
|
||||||
if(sec->name && !strcmp(sec->name, name))
|
|
||||||
{
|
|
||||||
ret = sec;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
fetch_section_count(struct conf_sec **s)
|
|
||||||
{
|
|
||||||
size_t ret = 0;
|
|
||||||
|
|
||||||
while(s[ret])
|
|
||||||
++ret;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct opt_type *
|
|
||||||
fetch_opt(struct conf_sec *s, char *dfl, char *name)
|
|
||||||
{
|
|
||||||
struct conf_opt *o;
|
|
||||||
struct opt_type *ret;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
if(!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ret = xcalloc(10, sizeof(struct opt_type));
|
|
||||||
|
|
||||||
if(s)
|
|
||||||
{
|
|
||||||
SLIST_FOREACH(o, &s->optlist, entry)
|
|
||||||
if(!strcmp(o->name, name))
|
|
||||||
{
|
|
||||||
while(o->val[i])
|
|
||||||
{
|
|
||||||
o->used = true;
|
|
||||||
ret[i] = string_to_opt(o->val[i]);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret[i] = opt_type_null;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret[0] = string_to_opt(dfl);
|
|
||||||
ret[1] = opt_type_null;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct opt_type
|
|
||||||
fetch_opt_first(struct conf_sec *s, char *dfl, char *name)
|
|
||||||
{
|
|
||||||
struct conf_opt *o;
|
|
||||||
|
|
||||||
if(!name)
|
|
||||||
return opt_type_null;
|
|
||||||
else if(s)
|
|
||||||
{
|
|
||||||
SLIST_FOREACH(o, &s->optlist, entry)
|
|
||||||
if(!strcmp(o->name, name))
|
|
||||||
{
|
|
||||||
o->used = true;
|
|
||||||
|
|
||||||
return string_to_opt(o->val[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string_to_opt(dfl);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
fetch_opt_count(struct opt_type *o)
|
|
||||||
{
|
|
||||||
size_t ret = 0;
|
|
||||||
|
|
||||||
while(o[ret].str)
|
|
||||||
++ret;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HAVE_XINERAMA
|
|
||||||
|
|
||||||
#ifdef HAVE_XINERAMA
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
|
||||||
#endif /* HAVE_XINERAMA */
|
|
||||||
|
|
||||||
#include "screen.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "tag.h"
|
|
||||||
#include "infobar.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
static struct screen*
|
|
||||||
screen_new(struct geo *g, int id)
|
|
||||||
{
|
|
||||||
struct screen *s = (struct screen*)xcalloc(1, sizeof(struct screen));
|
|
||||||
|
|
||||||
s->geo = s->ugeo = *g;
|
|
||||||
s->seltag = NULL;
|
|
||||||
s->id = id;
|
|
||||||
|
|
||||||
TAILQ_INIT(&s->tags);
|
|
||||||
SLIST_INIT(&s->infobars);
|
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(&W->h.screen, s, next);
|
|
||||||
|
|
||||||
/* Set as selected screen */
|
|
||||||
W->screen = s;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
screen_init(void)
|
|
||||||
{
|
|
||||||
struct geo g;
|
|
||||||
|
|
||||||
SLIST_INIT(&W->h.screen);
|
|
||||||
|
|
||||||
#ifdef HAVE_XINERAMA
|
|
||||||
XineramaScreenInfo *xsi;
|
|
||||||
int i, n = 0;
|
|
||||||
|
|
||||||
if(XineramaIsActive(W->dpy))
|
|
||||||
{
|
|
||||||
xsi = XineramaQueryScreens(W->dpy, &n);
|
|
||||||
|
|
||||||
for(i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
g.x = xsi[i].x_org;
|
|
||||||
g.y = xsi[i].y_org;
|
|
||||||
g.w = xsi[i].width;
|
|
||||||
g.h = xsi[i].height;
|
|
||||||
|
|
||||||
screen_new(&g, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(xsi);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* HAVE_XINERAMA */
|
|
||||||
{
|
|
||||||
g.x = g.y = 0;
|
|
||||||
g.w = DisplayWidth(W->dpy, W->xscreen);
|
|
||||||
g.h = DisplayHeight(W->dpy, W->xscreen);
|
|
||||||
|
|
||||||
screen_new(&g, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update selected screen with mouse location
|
|
||||||
*/
|
|
||||||
struct screen*
|
|
||||||
screen_update_sel(void)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XINERAMA
|
|
||||||
if(XineramaIsActive(W->dpy))
|
|
||||||
{
|
|
||||||
struct screen *s;
|
|
||||||
Window w;
|
|
||||||
int d, x, y;
|
|
||||||
|
|
||||||
XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d);
|
|
||||||
|
|
||||||
SLIST_FOREACH(s, &W->h.screen, next)
|
|
||||||
if(INAREA(x, y, s->geo))
|
|
||||||
break;
|
|
||||||
|
|
||||||
return (W->screen = s);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_XINERAMA */
|
|
||||||
|
|
||||||
return W->screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
screen_free(void)
|
|
||||||
{
|
|
||||||
struct screen *s;
|
|
||||||
|
|
||||||
while(!SLIST_EMPTY(&W->h.screen))
|
|
||||||
{
|
|
||||||
s = SLIST_FIRST(&W->h.screen);
|
|
||||||
SLIST_REMOVE_HEAD(&W->h.screen, next);
|
|
||||||
|
|
||||||
infobar_free(s);
|
|
||||||
tag_free(s);
|
|
||||||
free(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SCREEN_H
|
|
||||||
#define SCREEN_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
static inline struct screen*
|
|
||||||
screen_gb_id(int id)
|
|
||||||
{
|
|
||||||
struct screen *s;
|
|
||||||
|
|
||||||
SLIST_FOREACH(s, &W->h.screen, next)
|
|
||||||
if(s->id == id)
|
|
||||||
return s;
|
|
||||||
|
|
||||||
return SLIST_FIRST(&W->h.screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void screen_init(void);
|
|
||||||
struct screen* screen_update_sel(void);
|
|
||||||
void screen_free(void);
|
|
||||||
|
|
||||||
#endif /* SCREEN_H */
|
|
||||||
198
wmfs2/src/tag.c
198
wmfs2/src/tag.c
@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <X11/Xutil.h> /* IconicState / NormalState */
|
|
||||||
|
|
||||||
#include "tag.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "infobar.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "barwin.h"
|
|
||||||
#include "ewmh.h"
|
|
||||||
#include "layout.h"
|
|
||||||
|
|
||||||
struct tag*
|
|
||||||
tag_new(struct screen *s, char *name)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
XSetWindowAttributes at =
|
|
||||||
{
|
|
||||||
.background_pixel = THEME_DEFAULT->frame_bg,
|
|
||||||
.override_redirect = true,
|
|
||||||
.background_pixmap = ParentRelative,
|
|
||||||
.event_mask = BARWIN_MASK
|
|
||||||
};
|
|
||||||
|
|
||||||
t = xcalloc(1, sizeof(struct tag));
|
|
||||||
|
|
||||||
t->screen = s;
|
|
||||||
t->name = xstrdup(name);
|
|
||||||
t->flags = 0;
|
|
||||||
t->sel = NULL;
|
|
||||||
|
|
||||||
/* Frame window */
|
|
||||||
t->frame = XCreateWindow(W->dpy, W->root,
|
|
||||||
s->ugeo.x, s->ugeo.y,
|
|
||||||
s->ugeo.w, s->ugeo.h,
|
|
||||||
0, CopyFromParent,
|
|
||||||
InputOutput,
|
|
||||||
CopyFromParent,
|
|
||||||
(CWOverrideRedirect | CWBackPixmap
|
|
||||||
| CWBackPixel | CWEventMask),
|
|
||||||
&at);
|
|
||||||
|
|
||||||
SLIST_INIT(&t->clients);
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&s->tags, t, next);
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tag_screen(struct screen *s, struct tag *t)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
/* Unmap previous tag's frame */
|
|
||||||
WIN_STATE(s->seltag->frame, Unmap);
|
|
||||||
SLIST_FOREACH(c, &s->seltag->clients, tnext)
|
|
||||||
ewmh_set_wm_state(c->win, IconicState);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map selected tag's frame, only if there is
|
|
||||||
* clients in t
|
|
||||||
*/
|
|
||||||
if(!SLIST_EMPTY(&t->clients))
|
|
||||||
{
|
|
||||||
WIN_STATE(t->frame, Map);
|
|
||||||
SLIST_FOREACH(c, &t->clients, tnext)
|
|
||||||
ewmh_set_wm_state(c->win, NormalState);
|
|
||||||
|
|
||||||
client_focus(t->sel);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->seltag = t;
|
|
||||||
|
|
||||||
infobar_elem_screen_update(s, ElemTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set t to NULL to untag c from c->tag */
|
|
||||||
void
|
|
||||||
tag_client(struct tag *t, struct client *c)
|
|
||||||
{
|
|
||||||
/* Remove client from its previous tag */
|
|
||||||
if(c->tag)
|
|
||||||
{
|
|
||||||
if(c->tag == t)
|
|
||||||
return;
|
|
||||||
|
|
||||||
layout_split_arrange_closed(c);
|
|
||||||
|
|
||||||
SLIST_REMOVE(&c->tag->clients, c, client, tnext);
|
|
||||||
|
|
||||||
if(c->tag->sel == c || W->client == c)
|
|
||||||
client_focus(client_next(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Case of client removing: umap frame if empty
|
|
||||||
*/
|
|
||||||
if(!t)
|
|
||||||
{
|
|
||||||
/* Unmap frame if tag is now empty */
|
|
||||||
if(SLIST_EMPTY(&c->tag->clients))
|
|
||||||
WIN_STATE(c->tag->frame, Unmap);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reparent client win in frame win */
|
|
||||||
XReparentWindow(W->dpy, c->win, t->frame, 0, 0);
|
|
||||||
|
|
||||||
/* Map frame if tag was empty */
|
|
||||||
if(SLIST_EMPTY(&t->clients))
|
|
||||||
WIN_STATE(t->frame, Map);
|
|
||||||
|
|
||||||
c->tag = t;
|
|
||||||
|
|
||||||
layout_split_integrate(c, t->sel);
|
|
||||||
|
|
||||||
/* Insert in new tag list */
|
|
||||||
SLIST_INSERT_HEAD(&t->clients, c, tnext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_tag_set(Uicb cmd)
|
|
||||||
{
|
|
||||||
int i = 0, n = ATOI(cmd);
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(t, &W->screen->tags, next)
|
|
||||||
if(++i == n)
|
|
||||||
{
|
|
||||||
tag_screen(W->screen, t);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_tag_set_with_name(Uicb cmd)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(t, &W->screen->tags, next)
|
|
||||||
if(!strcmp(cmd, t->name))
|
|
||||||
{
|
|
||||||
tag_screen(W->screen, t);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_tag_next(Uicb cmd)
|
|
||||||
{
|
|
||||||
(void)cmd;
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
if((t = TAILQ_NEXT(W->screen->seltag, next)))
|
|
||||||
tag_screen(W->screen, t);
|
|
||||||
else if( /* CIRCULAR OPTION */ 1)
|
|
||||||
tag_screen(W->screen, TAILQ_FIRST(&W->screen->tags));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_tag_prev(Uicb cmd)
|
|
||||||
{
|
|
||||||
(void)cmd;
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
if((t = TAILQ_PREV(W->screen->seltag, tsub, next)))
|
|
||||||
tag_screen(W->screen, t);
|
|
||||||
else if( /* CIRCULAR OPTION */ 1)
|
|
||||||
tag_screen(W->screen, TAILQ_LAST(&W->screen->tags, tsub));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tag_remove(struct tag *t)
|
|
||||||
{
|
|
||||||
free(t->name);
|
|
||||||
|
|
||||||
XDestroyWindow(W->dpy, t->frame);
|
|
||||||
|
|
||||||
free(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tag_free(struct screen *s)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(t, &s->tags, next)
|
|
||||||
{
|
|
||||||
TAILQ_REMOVE(&s->tags, t, next);
|
|
||||||
tag_remove(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TAG_H
|
|
||||||
#define TAG_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
struct tag *tag_new(struct screen *s, char *name);
|
|
||||||
void tag_screen(struct screen *s, struct tag *t);
|
|
||||||
void tag_client(struct tag *t, struct client *c);
|
|
||||||
void tag_free(struct screen *s);
|
|
||||||
void uicb_tag_set(Uicb cmd);
|
|
||||||
void uicb_tag_set_with_name(Uicb cmd);
|
|
||||||
void uicb_tag_next(Uicb cmd);
|
|
||||||
void uicb_tag_prev(Uicb cmd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update frames size with screen usable geo
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
tag_update_frame_geo(struct screen *s)
|
|
||||||
{
|
|
||||||
struct tag *t;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(t, &s->tags, next)
|
|
||||||
XMoveResizeWindow(W->dpy,
|
|
||||||
t->frame,
|
|
||||||
s->ugeo.x,
|
|
||||||
s->ugeo.y,
|
|
||||||
s->ugeo.w,
|
|
||||||
s->ugeo.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* TAG_H */
|
|
||||||
128
wmfs2/src/util.c
128
wmfs2/src/util.c
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _GNU_SOURCE /* vasprintf() */
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/** malloc with error support and size_t overflow protection
|
|
||||||
* \param nmemb number of objects
|
|
||||||
* \param size size of single object
|
|
||||||
* \return non null void pointer
|
|
||||||
*/
|
|
||||||
void*
|
|
||||||
xmalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
if(SIZE_MAX / nmemb < size)
|
|
||||||
err(EXIT_FAILURE, "xmalloc(%zu, %zu), "
|
|
||||||
"size_t overflow detected", nmemb, size);
|
|
||||||
|
|
||||||
if((ret = malloc(nmemb * size)) == NULL)
|
|
||||||
err(EXIT_FAILURE, "malloc(%zu)", nmemb * size);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** calloc with error support
|
|
||||||
* \param nmemb Number of objects
|
|
||||||
* \param size size of single object
|
|
||||||
* \return non null void pointer
|
|
||||||
*/
|
|
||||||
void*
|
|
||||||
xcalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
if((ret = calloc(nmemb, size)) == NULL)
|
|
||||||
err(EXIT_FAILURE, "calloc(%zu * %zu)", nmemb, size);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** asprintf wrapper
|
|
||||||
* \param strp target string
|
|
||||||
* \param fmt format
|
|
||||||
* \return non zero integer
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xasprintf(char **strp, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
ret = vasprintf(strp, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if (ret == -1)
|
|
||||||
err(EXIT_FAILURE, "asprintf(%s)", fmt);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** strdup with error support
|
|
||||||
* \param str char pointer
|
|
||||||
* \retun non null void pointer
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
xstrdup(const char *str)
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
if (str == NULL || (ret = strdup(str)) == NULL)
|
|
||||||
err(EXIT_FAILURE, "strdup(%s)", str);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Execute a system command
|
|
||||||
* \param cmd Command
|
|
||||||
* \return child pid
|
|
||||||
*/
|
|
||||||
pid_t
|
|
||||||
spawn(const char *format, ...)
|
|
||||||
{
|
|
||||||
char *sh = NULL;
|
|
||||||
char cmd[512];
|
|
||||||
va_list ap;
|
|
||||||
pid_t pid;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
len = vsnprintf(cmd, sizeof(cmd), format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (len >= sizeof(cmd))
|
|
||||||
{
|
|
||||||
warnx("command too long (> 512 bytes)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(sh = getenv("SHELL")))
|
|
||||||
sh = "/bin/sh";
|
|
||||||
|
|
||||||
if((pid = fork()) == 0)
|
|
||||||
{
|
|
||||||
setsid();
|
|
||||||
if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
|
|
||||||
warn("execl(sh -c %s)", cmd);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
else if (pid == -1)
|
|
||||||
warn("fork");
|
|
||||||
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_spawn(Uicb cmd)
|
|
||||||
{
|
|
||||||
spawn("%s", cmd);
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTIL_H
|
|
||||||
#define UTIL_H
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
|
|
||||||
/* Todo FREE_LIST(type, head, function_remove) */
|
|
||||||
#define FREE_LIST(type, head) \
|
|
||||||
do { \
|
|
||||||
struct type *Z; \
|
|
||||||
while(!SLIST_EMPTY(&head)) { \
|
|
||||||
Z = SLIST_FIRST(&head); \
|
|
||||||
SLIST_REMOVE_HEAD(&head, next); \
|
|
||||||
free(Z); /* function_remove(t)*/ \
|
|
||||||
} \
|
|
||||||
} while(/* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
/* t is Map or Unmap */
|
|
||||||
#define WIN_STATE(w, t) do { \
|
|
||||||
X##t##Subwindows(W->dpy, w); \
|
|
||||||
X##t##Window(W->dpy, w); \
|
|
||||||
} while( /* CONSTCOND */ 0);
|
|
||||||
|
|
||||||
|
|
||||||
#define ATOM(a) XInternAtom(W->dpy, (a), False)
|
|
||||||
#define LEN(x) (sizeof(x) / sizeof(*x))
|
|
||||||
#define FLAGINT(i) (1 << i)
|
|
||||||
#define ATOI(s) strtol(s, NULL, 10)
|
|
||||||
#define ABS(j) (j < 0 ? -j : j)
|
|
||||||
#define INAREA(i, j, a) ((i) >= (a).x && (i) <= (a).x + (a).w && (j) >= (a).y && (j) <= (a).y + (a).h)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "#RRGGBB" -> 0xRRGGBB
|
|
||||||
*/
|
|
||||||
static inline Color
|
|
||||||
color_atoh(const char *col)
|
|
||||||
{
|
|
||||||
int shift = (col[0] == '#');
|
|
||||||
|
|
||||||
return (Color)strtol(col + shift, NULL, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
swap_ptr(void **x, void **y)
|
|
||||||
{
|
|
||||||
void *t = *x;
|
|
||||||
|
|
||||||
*x = *y;
|
|
||||||
*y = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *xmalloc(size_t nmemb, size_t size);
|
|
||||||
void *xcalloc(size_t nmemb, size_t size);
|
|
||||||
int xasprintf(char **strp, const char *fmt, ...);
|
|
||||||
char *xstrdup(const char *str);
|
|
||||||
pid_t spawn(const char *format, ...);
|
|
||||||
void uicb_spawn(Uicb cmd);
|
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
|
||||||
344
wmfs2/src/wmfs.c
344
wmfs2/src/wmfs.c
@ -1,344 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <X11/keysym.h>
|
|
||||||
#include <X11/cursorfont.h>
|
|
||||||
|
|
||||||
#include "wmfs.h"
|
|
||||||
#include "event.h"
|
|
||||||
#include "ewmh.h"
|
|
||||||
#include "screen.h"
|
|
||||||
#include "infobar.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
wmfs_error_handler(Display *d, XErrorEvent *event)
|
|
||||||
{
|
|
||||||
char mess[256];
|
|
||||||
|
|
||||||
/* Check if there is another WM running */
|
|
||||||
if(event->error_code == BadAccess
|
|
||||||
&& W->root == event->resourceid)
|
|
||||||
errx(EXIT_FAILURE, "Another Window Manager is already running.");
|
|
||||||
|
|
||||||
/* Ignore focus change error for unmapped client
|
|
||||||
* 42 = X_SetInputFocus
|
|
||||||
* 28 = X_GrabButton
|
|
||||||
*/
|
|
||||||
if(client_gb_win(event->resourceid))
|
|
||||||
if(event->error_code == BadWindow
|
|
||||||
|| event->request_code == 42
|
|
||||||
|| event->request_code == 28)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
if(XGetErrorText(d, event->error_code, mess, 128))
|
|
||||||
warnx("%s(%d) opcodes %d/%d\n resource #%lx\n",
|
|
||||||
mess,
|
|
||||||
event->error_code,
|
|
||||||
event->request_code,
|
|
||||||
event->minor_code,
|
|
||||||
event->resourceid);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
wmfs_error_handler_dummy(Display *d, XErrorEvent *event)
|
|
||||||
{
|
|
||||||
(void)d;
|
|
||||||
(void)event;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wmfs_numlockmask(void)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
XModifierKeymap *mm = XGetModifierMapping(W->dpy);
|
|
||||||
|
|
||||||
for(i = 0; i < 8; i++)
|
|
||||||
for(j = 0; j < mm->max_keypermod; ++j)
|
|
||||||
if(mm->modifiermap[i * mm->max_keypermod + j]
|
|
||||||
== XKeysymToKeycode(W->dpy, XK_Num_Lock))
|
|
||||||
W->numlockmask = (1 << i);
|
|
||||||
|
|
||||||
XFreeModifiermap(mm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wmfs_init_font(char *font, struct theme *t)
|
|
||||||
{
|
|
||||||
XFontStruct **xfs = NULL;
|
|
||||||
char **misschar, **names, *defstring;
|
|
||||||
int d;
|
|
||||||
|
|
||||||
if(!(t->font.fontset = XCreateFontSet(W->dpy, font, &misschar, &d, &defstring)))
|
|
||||||
{
|
|
||||||
warnx("Can't load font '%s'", font);
|
|
||||||
t->font.fontset = XCreateFontSet(W->dpy, "fixed", &misschar, &d, &defstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
XExtentsOfFontSet(t->font.fontset);
|
|
||||||
XFontsOfFontSet(t->font.fontset, &xfs, &names);
|
|
||||||
|
|
||||||
t->font.as = xfs[0]->max_bounds.ascent;
|
|
||||||
t->font.de = xfs[0]->max_bounds.descent;
|
|
||||||
t->font.width = xfs[0]->max_bounds.width;
|
|
||||||
|
|
||||||
t->font.height = t->font.as + t->font.de;
|
|
||||||
|
|
||||||
if(misschar)
|
|
||||||
XFreeStringList(misschar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wmfs_xinit(void)
|
|
||||||
{
|
|
||||||
XSetWindowAttributes at =
|
|
||||||
{
|
|
||||||
.event_mask = (KeyMask | ButtonMask | MouseMask
|
|
||||||
| PropertyChangeMask | SubstructureRedirectMask
|
|
||||||
| SubstructureNotifyMask | StructureNotifyMask),
|
|
||||||
.cursor = XCreateFontCursor(W->dpy, XC_left_ptr)
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* X Error handler
|
|
||||||
*/
|
|
||||||
XSetErrorHandler(wmfs_error_handler);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* X var
|
|
||||||
*/
|
|
||||||
W->xscreen = DefaultScreen(W->dpy);
|
|
||||||
W->xdepth = DefaultDepth(W->dpy, W->xscreen);
|
|
||||||
W->gc = DefaultGC(W->dpy, W->xscreen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keys
|
|
||||||
*/
|
|
||||||
wmfs_numlockmask();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Root window/cursor
|
|
||||||
*/
|
|
||||||
W->root = RootWindow(W->dpy, W->xscreen);
|
|
||||||
XChangeWindowAttributes(W->dpy, W->root, CWEventMask | CWCursor, &at);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Locale (font encode)
|
|
||||||
*/
|
|
||||||
setlocale(LC_CTYPE, "");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Barwin linked list
|
|
||||||
*/
|
|
||||||
SLIST_INIT(&W->h.barwin);
|
|
||||||
|
|
||||||
W->running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wmfs_grab_keys(void)
|
|
||||||
{
|
|
||||||
KeyCode c;
|
|
||||||
struct keybind *k;
|
|
||||||
|
|
||||||
wmfs_numlockmask();
|
|
||||||
|
|
||||||
XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root);
|
|
||||||
|
|
||||||
SLIST_FOREACH(k, &W->h.keybind, next)
|
|
||||||
if((c = XKeysymToKeycode(W->dpy, k->keysym)))
|
|
||||||
{
|
|
||||||
XGrabKey(W->dpy, c, k->mod, W->root, True, GrabModeAsync, GrabModeAsync);
|
|
||||||
XGrabKey(W->dpy, c, k->mod | LockMask, W->root, True, GrabModeAsync, GrabModeAsync);
|
|
||||||
XGrabKey(W->dpy, c, k->mod | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
|
|
||||||
XGrabKey(W->dpy, c, k->mod | LockMask | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Scan if there are windows on X
|
|
||||||
* for manage it
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
wmfs_scan(void)
|
|
||||||
{
|
|
||||||
int i, n;
|
|
||||||
XWindowAttributes wa;
|
|
||||||
Window usl, usl2, *w = NULL;
|
|
||||||
|
|
||||||
SLIST_INIT(&W->h.client);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Atom rt;
|
|
||||||
int s, rf, tag = -1, screen = -1, flags = -1, i;
|
|
||||||
ulong ir, il;
|
|
||||||
uchar *ret;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(XQueryTree(W->dpy, W->root, &usl, &usl2, &w, (unsigned int*)&n))
|
|
||||||
for(i = n - 1; i != -1; --i)
|
|
||||||
{
|
|
||||||
XGetWindowAttributes(W->dpy, w[i], &wa);
|
|
||||||
|
|
||||||
if(!wa.override_redirect && wa.map_state == IsViewable)
|
|
||||||
{/*
|
|
||||||
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
|
|
||||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
|
||||||
{
|
|
||||||
tag = *ret;
|
|
||||||
XFree(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32,
|
|
||||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
|
||||||
{
|
|
||||||
screen = *ret;
|
|
||||||
XFree(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_FLAGS"), 0, 32,
|
|
||||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
|
||||||
{
|
|
||||||
flags = *ret;
|
|
||||||
XFree(ret);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*c = */ client_new(w[i], &wa);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(tag != -1)
|
|
||||||
c->tag = tag;
|
|
||||||
if(screen != -1)
|
|
||||||
c->screen = screen;
|
|
||||||
if(flags != -1)
|
|
||||||
c->flags = flags;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wmfs_loop(void)
|
|
||||||
{
|
|
||||||
XEvent ev;
|
|
||||||
|
|
||||||
while(XPending(W->dpy))
|
|
||||||
while(W->running && !XNextEvent(W->dpy, &ev))
|
|
||||||
EVENT_HANDLE(&ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
wmfs_init(void)
|
|
||||||
{
|
|
||||||
wmfs_xinit();
|
|
||||||
ewmh_init();
|
|
||||||
screen_init();
|
|
||||||
event_init();
|
|
||||||
config_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wmfs_quit(void)
|
|
||||||
{
|
|
||||||
struct keybind *k;
|
|
||||||
struct theme *t;
|
|
||||||
|
|
||||||
/* Will free:
|
|
||||||
*
|
|
||||||
* Screens -> tags
|
|
||||||
* -> Infobars -> Elements
|
|
||||||
*/
|
|
||||||
screen_free();
|
|
||||||
|
|
||||||
XCloseDisplay(W->dpy);
|
|
||||||
|
|
||||||
/* Conf stuffs */
|
|
||||||
while(!SLIST_EMPTY(&W->h.keybind))
|
|
||||||
{
|
|
||||||
k = SLIST_FIRST(&W->h.keybind);
|
|
||||||
SLIST_REMOVE_HEAD(&W->h.keybind, next);
|
|
||||||
free((void*)k->cmd);
|
|
||||||
free(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(!SLIST_EMPTY(&W->h.theme))
|
|
||||||
{
|
|
||||||
t = SLIST_FIRST(&W->h.theme);
|
|
||||||
SLIST_REMOVE_HEAD(&W->h.theme, next);
|
|
||||||
XFreeFontSet(W->dpy, t->font.fontset);
|
|
||||||
free(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(W->net_atom);
|
|
||||||
free(W);
|
|
||||||
|
|
||||||
W->running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reload WMFS binary
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
uicb_reload(Uicb cmd)
|
|
||||||
{
|
|
||||||
(void)cmd;
|
|
||||||
/* TODO */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
uicb_quit(Uicb cmd)
|
|
||||||
{
|
|
||||||
(void)cmd;
|
|
||||||
W->running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
W = (struct wmfs*)xcalloc(1, sizeof(struct wmfs));
|
|
||||||
|
|
||||||
|
|
||||||
/* Get X display */
|
|
||||||
if(!(W->dpy = XOpenDisplay(NULL)))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s: Can't open X server\n", argv[0]);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Opt */
|
|
||||||
/*
|
|
||||||
int i;
|
|
||||||
while((i = getopt(argc, argv, "hviC:")) != -1)
|
|
||||||
{
|
|
||||||
switch(i)
|
|
||||||
{
|
|
||||||
case 'h':
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Core */
|
|
||||||
wmfs_init();
|
|
||||||
wmfs_scan();
|
|
||||||
|
|
||||||
wmfs_loop();
|
|
||||||
|
|
||||||
wmfs_quit();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
210
wmfs2/src/wmfs.h
210
wmfs2/src/wmfs.h
@ -1,210 +0,0 @@
|
|||||||
/*
|
|
||||||
* wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
|
|
||||||
* For license, see COPYING.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef WMFS_H
|
|
||||||
#define WMFS_H
|
|
||||||
|
|
||||||
/* Standard */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include <err.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
/* Xlib */
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
|
|
||||||
/* Local */
|
|
||||||
|
|
||||||
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
|
|
||||||
#define MouseMask (ButtonMask | PointerMotionMask)
|
|
||||||
#define KeyMask (KeyPressMask | KeyReleaseMask)
|
|
||||||
|
|
||||||
typedef unsigned int Flags;
|
|
||||||
typedef unsigned int Color;
|
|
||||||
typedef const char* Uicb;
|
|
||||||
typedef enum { BarTop = 0, BarBottom, BarHide, BarLast } Barpos;
|
|
||||||
typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structures
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct geo
|
|
||||||
{
|
|
||||||
int x, y, w, h;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct barwin
|
|
||||||
{
|
|
||||||
struct geo geo;
|
|
||||||
Window win;
|
|
||||||
Drawable dr;
|
|
||||||
Color fg, bg;
|
|
||||||
void *ptr; /* Special cases */
|
|
||||||
SLIST_HEAD(, mousebind) mousebinds;
|
|
||||||
SLIST_ENTRY(barwin) next; /* global barwin */
|
|
||||||
SLIST_ENTRY(barwin) enext; /* element barwin */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct element
|
|
||||||
{
|
|
||||||
struct geo geo;
|
|
||||||
struct infobar *infobar;
|
|
||||||
int type;
|
|
||||||
void (*func_init)(struct element *e);
|
|
||||||
void (*func_update)(struct element *e);
|
|
||||||
SLIST_HEAD(, barwin) bars;
|
|
||||||
TAILQ_ENTRY(element) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct infobar
|
|
||||||
{
|
|
||||||
struct barwin *bar;
|
|
||||||
struct geo geo;
|
|
||||||
struct screen *screen;
|
|
||||||
struct theme *theme;
|
|
||||||
char *elemorder;
|
|
||||||
Barpos pos;
|
|
||||||
TAILQ_HEAD(esub, element) elements;
|
|
||||||
SLIST_ENTRY(infobar) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct screen
|
|
||||||
{
|
|
||||||
struct geo geo, ugeo;
|
|
||||||
struct tag *seltag;
|
|
||||||
int id;
|
|
||||||
Flags elemupdate;
|
|
||||||
TAILQ_HEAD(tsub, tag) tags;
|
|
||||||
SLIST_HEAD(, infobar) infobars;
|
|
||||||
SLIST_ENTRY(screen) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tag
|
|
||||||
{
|
|
||||||
struct screen *screen;
|
|
||||||
struct client *sel;
|
|
||||||
char *name;
|
|
||||||
Flags flags;
|
|
||||||
Window frame;
|
|
||||||
SLIST_HEAD(, client) clients;
|
|
||||||
TAILQ_ENTRY(tag) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct client
|
|
||||||
{
|
|
||||||
struct tag *tag;
|
|
||||||
struct screen *screen;
|
|
||||||
struct barwin *titlebar;
|
|
||||||
struct geo geo, tgeo, wgeo;
|
|
||||||
char *title;
|
|
||||||
Flags flags;
|
|
||||||
Window win;
|
|
||||||
SLIST_ENTRY(client) next; /* Global list */
|
|
||||||
SLIST_ENTRY(client) tnext; /* struct tag list */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct keybind
|
|
||||||
{
|
|
||||||
unsigned int mod;
|
|
||||||
void (*func)(Uicb);
|
|
||||||
Uicb cmd;
|
|
||||||
KeySym keysym;
|
|
||||||
SLIST_ENTRY(keybind) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mousebind
|
|
||||||
{
|
|
||||||
struct geo area;
|
|
||||||
int button;
|
|
||||||
bool use_area;
|
|
||||||
void (*func)(Uicb);
|
|
||||||
Uicb cmd;
|
|
||||||
SLIST_ENTRY(mousebind) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct colpair
|
|
||||||
{
|
|
||||||
Color fg, bg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct theme
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
/* Font */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int as, de, width, height;
|
|
||||||
XFontSet fontset;
|
|
||||||
} font;
|
|
||||||
|
|
||||||
/* Bars */
|
|
||||||
struct colpair bars;
|
|
||||||
int bars_width;
|
|
||||||
|
|
||||||
/* struct elements */
|
|
||||||
struct colpair tags_n, tags_s; /* normal / selected */
|
|
||||||
int tags_border_width;
|
|
||||||
Color tags_border_col;
|
|
||||||
|
|
||||||
/* client / frame */
|
|
||||||
struct colpair client_n, client_s;
|
|
||||||
Color frame_bg;
|
|
||||||
int client_titlebar_width;
|
|
||||||
int client_border_width;
|
|
||||||
|
|
||||||
SLIST_ENTRY(theme) next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wmfs
|
|
||||||
{
|
|
||||||
/* X11 stuffs */
|
|
||||||
Display *dpy;
|
|
||||||
Window root;
|
|
||||||
int xscreen, xdepth;
|
|
||||||
Flags numlockmask;
|
|
||||||
GC gc;
|
|
||||||
Atom *net_atom;
|
|
||||||
bool running;
|
|
||||||
|
|
||||||
/* Lists heads */
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
SLIST_HEAD(, screen) screen;
|
|
||||||
SLIST_HEAD(, client) client;
|
|
||||||
SLIST_HEAD(, keybind) keybind;
|
|
||||||
SLIST_HEAD(, barwin) barwin;
|
|
||||||
SLIST_HEAD(, theme) theme;
|
|
||||||
} h;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Selected screen, client
|
|
||||||
*/
|
|
||||||
struct screen *screen;
|
|
||||||
struct client *client;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
int wmfs_error_handler(Display *d, XErrorEvent *event);
|
|
||||||
int wmfs_error_handler_dummy(Display *d, XErrorEvent *event);
|
|
||||||
void wmfs_grab_keys(void);
|
|
||||||
void wmfs_numlockmask(void);
|
|
||||||
void wmfs_init_font(char *font, struct theme *t);
|
|
||||||
void wmfs_quit(void);
|
|
||||||
void uicb_reload(Uicb cmd);
|
|
||||||
void uicb_quit(Uicb cmd);
|
|
||||||
|
|
||||||
|
|
||||||
/* Single global variable */
|
|
||||||
struct wmfs *W;
|
|
||||||
|
|
||||||
#endif /* WMFS_H */
|
|
||||||
149
wmfs2/wmfsrc2
149
wmfs2/wmfsrc2
@ -1,149 +0,0 @@
|
|||||||
#
|
|
||||||
# WMFS2 configuration file
|
|
||||||
#
|
|
||||||
|
|
||||||
[themes]
|
|
||||||
|
|
||||||
|
|
||||||
[theme]
|
|
||||||
# name = "default"
|
|
||||||
|
|
||||||
font = "fixed"
|
|
||||||
|
|
||||||
# Bars
|
|
||||||
bars_width = 14
|
|
||||||
bars_fg = "#CCCCCC"
|
|
||||||
bars_bg = "#222222"
|
|
||||||
|
|
||||||
# Element tags
|
|
||||||
tags_normal_fg = "#CCCCCC"
|
|
||||||
tags_normal_bg = "#222222"
|
|
||||||
tags_sel_fg = "#222222"
|
|
||||||
tags_sel_bg = "#CCCCCC"
|
|
||||||
tags_border_color = "#888888"
|
|
||||||
tags_border_width = 1
|
|
||||||
|
|
||||||
# Frame / Client
|
|
||||||
client_normal_fg = "#CCCCCC"
|
|
||||||
client_normal_bg = "#222222"
|
|
||||||
client_sel_fg = "#222222"
|
|
||||||
client_sel_bg = "#CCCCCC"
|
|
||||||
frame_bg = "#555555"
|
|
||||||
client_titlebar_width = 12 #useless for now
|
|
||||||
client_border_width = 1
|
|
||||||
|
|
||||||
[/theme]
|
|
||||||
|
|
||||||
[theme]
|
|
||||||
name = "perso"
|
|
||||||
|
|
||||||
font = "-*-fixed-bold"
|
|
||||||
|
|
||||||
bars_width = 20
|
|
||||||
bars_fg = "#222222"
|
|
||||||
bars_bg = "#CCCCCC"
|
|
||||||
|
|
||||||
tags_sel_bg = "#33AA33"
|
|
||||||
tags_normal_fg = "#AA3333"
|
|
||||||
|
|
||||||
[/theme]
|
|
||||||
|
|
||||||
[/themes]
|
|
||||||
|
|
||||||
[bars]
|
|
||||||
|
|
||||||
# Position:
|
|
||||||
# 0 Top
|
|
||||||
# 1 Bottom
|
|
||||||
# 2 Hide
|
|
||||||
|
|
||||||
# Element type:
|
|
||||||
# t Tags
|
|
||||||
# S Statustext
|
|
||||||
|
|
||||||
[bar]
|
|
||||||
position = 1
|
|
||||||
screen = 0
|
|
||||||
elements = "t"
|
|
||||||
theme = "perso"
|
|
||||||
[/bar]
|
|
||||||
|
|
||||||
[bar]
|
|
||||||
position = 1
|
|
||||||
screen = 0
|
|
||||||
elements = "t"
|
|
||||||
theme = "default"
|
|
||||||
[/bar]
|
|
||||||
|
|
||||||
[bar]
|
|
||||||
screen = 1
|
|
||||||
elements = "t"
|
|
||||||
theme = "perso"
|
|
||||||
[/bar]
|
|
||||||
[bar]
|
|
||||||
screen = 1
|
|
||||||
elements = "t"
|
|
||||||
theme = "default"
|
|
||||||
[/bar]
|
|
||||||
|
|
||||||
|
|
||||||
[/bars]
|
|
||||||
|
|
||||||
[tags]
|
|
||||||
|
|
||||||
[tag] screen = 0 name = "one" [/tag]
|
|
||||||
[tag] screen = 0 name = "two" [/tag]
|
|
||||||
[tag] screen = 0 name = "three" [/tag]
|
|
||||||
|
|
||||||
[tag] screen = 1 name = "four" [/tag]
|
|
||||||
[tag] screen = 1 name = "five" [/tag]
|
|
||||||
|
|
||||||
[tag] name = "universal tag" [/tag]
|
|
||||||
|
|
||||||
[/tags]
|
|
||||||
|
|
||||||
[keys]
|
|
||||||
|
|
||||||
[key] mod = {"Super"} key = "Return" func = "spawn" cmd = "xterm" [/key]
|
|
||||||
[key] mod = {"Control","Alt"} key = "q" func = "quit" [/key]
|
|
||||||
[key] mod = {"Super"} key = "1" func = "tag_set" cmd = "1" [/key]
|
|
||||||
[key] mod = {"Super"} key = "2" func = "tag_set" cmd = "2" [/key]
|
|
||||||
[key] mod = {"Super"} key = "3" func = "tag_set" cmd = "3" [/key]
|
|
||||||
[key] mod = {"Super"} key = "s" func = "tag_next" [/key]
|
|
||||||
[key] mod = {"Super"} key = "a" func = "tag_prev" [/key]
|
|
||||||
[key] mod = {"Super"} key = "z" func = "tag" cmd = "tag2" [/key]
|
|
||||||
|
|
||||||
[key] mod = {"Super"} key = "q" func = "client_close" [/key]
|
|
||||||
|
|
||||||
# Focus next / prev client
|
|
||||||
[key] mod = { "Alt" } key = "Tab" func = "client_focus_next" [/key][key] mod = { "Alt", "Shift" } key = "Tab" func = "client_focus_prev" [/key]
|
|
||||||
|
|
||||||
# Focus next client with direction
|
|
||||||
[key] mod = {"Alt"} key = "h" func = "client_focus_left" [/key]
|
|
||||||
[key] mod = {"Alt"} key = "l" func = "client_focus_right" [/key]
|
|
||||||
[key] mod = {"Alt"} key = "k" func = "client_focus_top" [/key]
|
|
||||||
[key] mod = {"Alt"} key = "j" func = "client_focus_bottom" [/key]
|
|
||||||
|
|
||||||
# swap next client with direction:
|
|
||||||
[key] mod = {"Control", "Shift"} key = "h" func = "client_swap_left" [/key]
|
|
||||||
[key] mod = {"Control", "Shift"} key = "l" func = "client_swap_right" [/key]
|
|
||||||
[key] mod = {"Control", "Shift"} key = "k" func = "client_swap_top" [/key]
|
|
||||||
[key] mod = {"Control", "Shift"} key = "j" func = "client_swap_bottom" [/key]
|
|
||||||
|
|
||||||
# Resize selected tiled client with direction
|
|
||||||
[key] mod = {"Super"} key = "h" func = "client_resize_left" cmd = "20" [/key]
|
|
||||||
[key] mod = {"Super"} key = "l" func = "client_resize_left" cmd = "-20" [/key]
|
|
||||||
[key] mod = {"Super"} key = "k" func = "client_resize_top" cmd = "20" [/key]
|
|
||||||
[key] mod = {"Super"} key = "j" func = "client_resize_top" cmd = "-20" [/key]
|
|
||||||
[key] mod = {"Super", "Control"} key = "h" func = "client_resize_right" cmd = "-20" [/key]
|
|
||||||
[key] mod = {"Super", "Control"} key = "l" func = "client_resize_right" cmd = "20" [/key]
|
|
||||||
[key] mod = {"Super", "Control"} key = "k" func = "client_resize_bottom" cmd = "-20" [/key]
|
|
||||||
[key] mod = {"Super", "Control"} key = "j" func = "client_resize_bottom" cmd = "20" [/key]
|
|
||||||
|
|
||||||
# Layout manipulation
|
|
||||||
[key] mod = {"Super"} key = "m" func = "layout_vmirror" [/key]
|
|
||||||
[key] mod = {"Super", "Shift"} key = "m" func = "layout_hmirror" [/key]
|
|
||||||
[key] mod = {"Super"} key = "r" func = "layout_rotate_right" [/key]
|
|
||||||
[key] mod = {"Super", "Shift"} key = "r" func = "layout_rotate_left" [/key]
|
|
||||||
|
|
||||||
[/keys]
|
|
||||||
Loading…
x
Reference in New Issue
Block a user