Compare commits
446 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e8634fbe4 | ||
|
|
df4e32f4f9 | ||
|
|
6372f3974c | ||
|
|
703974cb00 | ||
|
|
4064cbdfd9 | ||
|
|
a7f9bf65ff | ||
|
|
79928efd35 | ||
|
|
b1a52a3a6b | ||
|
|
41c4570dcf | ||
|
|
5ece3a6e55 | ||
|
|
4d39413f56 | ||
|
|
8bc30628c3 | ||
|
|
041e9ec20d | ||
|
|
1e35777c18 | ||
|
|
3ca201c42a | ||
|
|
34f2cb5b03 | ||
|
|
946e4c1606 | ||
|
|
6291639b24 | ||
|
|
6a0eedb63c | ||
|
|
22c9eee9af | ||
|
|
7d66c50676 | ||
|
|
9766392332 | ||
|
|
d79404f5ee | ||
|
|
f5134bd6b3 | ||
|
|
d213d13784 | ||
|
|
57019236aa | ||
|
|
ac00fefaa9 | ||
|
|
ddcdf6ce83 | ||
|
|
9235775dd2 | ||
|
|
971fb3240a | ||
|
|
bd1575e1b2 | ||
|
|
83d2da9da6 | ||
|
|
3be59059f4 | ||
|
|
891ba6d866 | ||
|
|
5729fe95fb | ||
|
|
43686dc82c | ||
|
|
d1f400e940 | ||
|
|
16120744a8 | ||
|
|
e2942ec597 | ||
|
|
bf26e8c22e | ||
|
|
4898e07e5e | ||
|
|
ff7853738f | ||
|
|
7180d733bd | ||
|
|
325f115c09 | ||
|
|
f48b9651c9 | ||
|
|
dcf3979c00 | ||
|
|
db98e3978b | ||
|
|
3cc68b6872 | ||
|
|
45e796406b | ||
|
|
f91699d6bc | ||
|
|
7d391f47f5 | ||
|
|
aa3f2b7fd0 | ||
|
|
2e4c8bd202 | ||
|
|
741002b724 | ||
|
|
c8e5ac4619 | ||
|
|
07ad0c6263 | ||
|
|
41cc6944ae | ||
|
|
48e226f5ae | ||
|
|
3652a4060c | ||
|
|
b4e33395b3 | ||
|
|
d0bb69150a | ||
|
|
7e0436ffdc | ||
|
|
c8c210bcac | ||
|
|
993b408262 | ||
|
|
f51d943bd9 | ||
|
|
56b6b467ee | ||
|
|
7ac4bf32c2 | ||
|
|
b5f24e042f | ||
|
|
a5432919ca | ||
|
|
c174e69b64 | ||
|
|
209f9a09a4 | ||
|
|
c5dfeb9878 | ||
|
|
3abfe9d7bb | ||
|
|
27c4c260c6 | ||
|
|
8ea76e1167 | ||
|
|
6ec79f626e | ||
|
|
2320e8586c | ||
|
|
c317afc79d | ||
|
|
056cb5daf6 | ||
|
|
7bb0fdcbad | ||
|
|
2273ccc5d5 | ||
|
|
18e97d3e1e | ||
|
|
9de133dac7 | ||
|
|
b1d4e2a403 | ||
|
|
8e6cea6d05 | ||
|
|
03c41f9b3b | ||
|
|
42a0612664 | ||
|
|
fb1627e8cc | ||
|
|
c8eb002768 | ||
|
|
0d0c3af47b | ||
|
|
5b5dd104d9 | ||
|
|
0a2c1f9d13 | ||
|
|
c817b7277b | ||
|
|
99e85cbfc2 | ||
|
|
a1ad5685f9 | ||
|
|
abf71d99b9 | ||
|
|
1460229397 | ||
|
|
47a68568fe | ||
|
|
a0fd6a77cc | ||
|
|
ef6b057234 | ||
|
|
e32726f008 | ||
|
|
74bbf0bd04 | ||
|
|
b85b6bd687 | ||
|
|
bf16b4a2e7 | ||
|
|
f2bd808b86 | ||
|
|
f2734a5f2b | ||
|
|
b4fb75806a | ||
|
|
dbe7588c0a | ||
|
|
dae3019185 | ||
|
|
3f461810d2 | ||
|
|
0a708c8dda | ||
|
|
6072c2d811 | ||
|
|
ce3813608c | ||
|
|
6c332c9ea5 | ||
|
|
d606f999f9 | ||
|
|
87575a019d | ||
|
|
6882cfb986 | ||
|
|
9e457b3832 | ||
|
|
c8a74878a1 | ||
|
|
d0058146dd | ||
|
|
77e458048d | ||
|
|
f6206d65b1 | ||
|
|
c90a5743b3 | ||
|
|
3459ed0b20 | ||
|
|
3cf93a0961 | ||
|
|
719654fcbc | ||
|
|
e053d41a3d | ||
|
|
1170a6afbc | ||
|
|
a42237aab7 | ||
|
|
f5f2d8c7de | ||
|
|
bc31510d64 | ||
|
|
f928497e70 | ||
|
|
daeffb324e | ||
|
|
d75746bcf4 | ||
|
|
82b17ea02f | ||
|
|
19ecd89d89 | ||
|
|
c7b2d98303 | ||
|
|
546366b282 | ||
|
|
20c99826ce | ||
|
|
eda1bfdfec | ||
|
|
22295948ec | ||
|
|
c2664e8e85 | ||
|
|
e5b2a9e058 | ||
|
|
b6c557a8ee | ||
|
|
14f12edf25 | ||
|
|
3d6f8da805 | ||
|
|
40b4662ff8 | ||
|
|
8d71b8c2a8 | ||
|
|
31899139e4 | ||
|
|
61a1e18a59 | ||
|
|
3d3dbf589f | ||
|
|
6912599c72 | ||
|
|
1294d7e35c | ||
|
|
6bd0175db0 | ||
|
|
2d9baf78c5 | ||
|
|
b7ded56ef9 | ||
|
|
7f96a338c6 | ||
|
|
bfc56f8c37 | ||
|
|
d8e2d54d8e | ||
|
|
7096101651 | ||
|
|
103c86db03 | ||
|
|
01bd4cc265 | ||
|
|
f6ad74273c | ||
|
|
c3cf9d64b3 | ||
|
|
26dde34d5c | ||
|
|
9ff9c81441 | ||
|
|
66d1b9b2fb | ||
|
|
6ac65840c0 | ||
|
|
7c9e560236 | ||
|
|
5a05594092 | ||
|
|
eb567d9936 | ||
|
|
b055908080 | ||
|
|
2614c61657 | ||
|
|
52e53c7415 | ||
|
|
e01bb5c3b0 | ||
|
|
a1de32cac7 | ||
|
|
57f8768228 | ||
|
|
f3c0f5492a | ||
|
|
7db51713e5 | ||
|
|
20756b30cd | ||
|
|
d242ab880a | ||
|
|
658e26bd49 | ||
|
|
464f06c5c1 | ||
|
|
a0e5ddc45a | ||
|
|
2a9d024784 | ||
|
|
6b788edc38 | ||
|
|
8f8d47dc23 | ||
|
|
3a021bf026 | ||
|
|
1ec6d90c1e | ||
|
|
b91db6b431 | ||
|
|
c6469260de | ||
|
|
5aeeae4198 | ||
|
|
3841e55f82 | ||
|
|
4a3952f54f | ||
|
|
8816bd6753 | ||
|
|
3366ec835f | ||
|
|
839ebeaf2b | ||
|
|
36aa4ce43a | ||
|
|
4f1742eef9 | ||
|
|
fd9cedd695 | ||
|
|
3644bc736b | ||
|
|
1eeb5e167e | ||
|
|
a1d134a1b7 | ||
|
|
52bfa713df | ||
|
|
3b60e23f9f | ||
|
|
59d9dcdc93 | ||
|
|
9055a55d58 | ||
|
|
e254f76211 | ||
|
|
e6db51d8fd | ||
|
|
ce4575ee04 | ||
|
|
e9b409b564 | ||
|
|
578b62ec09 | ||
|
|
4f42436098 | ||
|
|
dce3b8eb3c | ||
|
|
ce8238fb20 | ||
|
|
e9ffab7d62 | ||
|
|
cf565c9b57 | ||
|
|
179c94f26f | ||
|
|
5017c4ced5 | ||
|
|
7b0113ab6e | ||
|
|
dc2e571e5e | ||
|
|
5d9ad3e1db | ||
|
|
695cf69790 | ||
|
|
86b20ba799 | ||
|
|
ec2c2f6337 | ||
|
|
5d7f4a2382 | ||
|
|
d8d09f9e1a | ||
|
|
a496d77f9e | ||
|
|
7a1bfb48f5 | ||
|
|
3e71c420d6 | ||
|
|
0eab6d1a92 | ||
|
|
c63a9af492 | ||
|
|
0c38afdb35 | ||
|
|
19f9a35685 | ||
|
|
ed390279f5 | ||
|
|
6d99de883c | ||
|
|
7abc282d21 | ||
|
|
ed254ea417 | ||
|
|
f2e9c1fd02 | ||
|
|
36ca03f8f3 | ||
|
|
00638264d3 | ||
|
|
6a420e2934 | ||
|
|
132f7d1da4 | ||
|
|
4a1ab8ef79 | ||
|
|
61015e2567 | ||
|
|
5742ed4fca | ||
|
|
872d9cb348 | ||
|
|
2292ab97d1 | ||
|
|
3b81cacaac | ||
|
|
0270a28181 | ||
|
|
e6fc0a4976 | ||
|
|
374abb0e26 | ||
|
|
1d5792b278 | ||
|
|
461b45545a | ||
|
|
4cf2b8bf8f | ||
|
|
cc10d56359 | ||
|
|
1094861b49 | ||
|
|
fdb1d2c748 | ||
|
|
908978cca1 | ||
|
|
b3325867ed | ||
|
|
d32ee3295e | ||
|
|
910421c41c | ||
|
|
46d212297a | ||
|
|
bf9e9ca578 | ||
|
|
ce652d29e4 | ||
|
|
00e4e9975e | ||
|
|
aa04eab011 | ||
|
|
afdda3b95a | ||
|
|
2522b21ab3 | ||
|
|
8aeded6cd6 | ||
|
|
9a3b06c645 | ||
|
|
89b115e850 | ||
|
|
e71f85ff26 | ||
|
|
253d50762b | ||
|
|
e17f36f24f | ||
|
|
6d720d9848 | ||
|
|
414273fff9 | ||
|
|
cee16d6f7f | ||
|
|
fb0ddc6b73 | ||
|
|
8062f4a42a | ||
|
|
c6f0204901 | ||
|
|
a90f4ee7ce | ||
|
|
fb97d95787 | ||
|
|
6e05fd498d | ||
|
|
f683022678 | ||
|
|
32b3120fbd | ||
|
|
470606af1b | ||
|
|
12fc01b824 | ||
|
|
9067f3cb66 | ||
|
|
2040385af6 | ||
|
|
510cb29e9f | ||
|
|
32686569c4 | ||
|
|
faab6d946e | ||
|
|
d49ebaa57e | ||
|
|
5d1aaa1363 | ||
|
|
5dd811b91e | ||
|
|
a0a53f3af2 | ||
|
|
6ecc58bdb1 | ||
|
|
c524326714 | ||
|
|
c886edb19d | ||
|
|
995c4e94e7 | ||
|
|
d3207be191 | ||
|
|
1cc8506610 | ||
|
|
4b692b7a0f | ||
|
|
6d1bd844f7 | ||
|
|
1d9bb77d83 | ||
|
|
d24e5e911f | ||
|
|
07db3fafbd | ||
|
|
d38e7598a4 | ||
|
|
add85a7509 | ||
|
|
f9157a4dda | ||
|
|
f8115d686d | ||
|
|
236b86ff0a | ||
|
|
46608a14be | ||
|
|
0e8ffff152 | ||
|
|
52dba6418e | ||
|
|
e6b26eafc2 | ||
|
|
a635e7c2d6 | ||
|
|
5271222e38 | ||
|
|
7119d3cc25 | ||
|
|
c81312feff | ||
|
|
fe22703fea | ||
|
|
2da44ff4d8 | ||
|
|
892b705f95 | ||
|
|
feadae05c8 | ||
|
|
ba841c74b3 | ||
|
|
129a21bada | ||
|
|
dd3d490c39 | ||
|
|
f8a3cc0e0e | ||
|
|
de672fc7ad | ||
|
|
06d014722f | ||
|
|
5ccc31f7ec | ||
|
|
37d6d105d8 | ||
|
|
3e2d4a6a01 | ||
|
|
eb16ebfb7f | ||
|
|
d0d62c798b | ||
|
|
0f25f75f0d | ||
|
|
8c0e37cb38 | ||
|
|
3811d61858 | ||
|
|
84f6aa31d0 | ||
|
|
5875af2949 | ||
|
|
49b9a08fab | ||
|
|
c7824780fa | ||
|
|
b472a08490 | ||
|
|
55e74cd849 | ||
|
|
8e3e10f041 | ||
|
|
d5e1f1da78 | ||
|
|
aca9e78491 | ||
|
|
18b702c112 | ||
|
|
7f7bbd1f09 | ||
|
|
d6c2902d77 | ||
|
|
c8bb465bb0 | ||
|
|
891760bfac | ||
|
|
657dc33d63 | ||
|
|
5363a7a8a9 | ||
|
|
3274e3f4ad | ||
|
|
fb905b55c5 | ||
|
|
41bf8e2052 | ||
|
|
5c5e137fdd | ||
|
|
9f7f4c40e4 | ||
|
|
8975e04777 | ||
|
|
d37dc481a1 | ||
|
|
77d95275f0 | ||
|
|
81e6a63c1f | ||
|
|
0d9f8d887d | ||
|
|
9a38a64ced | ||
|
|
b4705bbaa7 | ||
|
|
005f06c15e | ||
|
|
761afe51a0 | ||
|
|
9b33623d33 | ||
|
|
6f2d6385ac | ||
|
|
a713e34b87 | ||
|
|
db90cf65c9 | ||
|
|
1ddc714196 | ||
|
|
611a5fc38d | ||
|
|
b0b74b46eb | ||
|
|
b31d54b7e6 | ||
|
|
7908d3075c | ||
|
|
cf652aab50 | ||
|
|
914b9f11c9 | ||
|
|
dcb48cc2c5 | ||
|
|
9c693212bb | ||
|
|
d525e3ace1 | ||
|
|
0bed70e52c | ||
|
|
61858bbe64 | ||
|
|
f6486d803c | ||
|
|
8b16176edc | ||
|
|
4138894db1 | ||
|
|
8a45d219bd | ||
|
|
b4c326ebaf | ||
|
|
c5c307deea | ||
|
|
590acffb62 | ||
|
|
a0258c13d0 | ||
|
|
466ebca9ea | ||
|
|
fbb36877dc | ||
|
|
ffaa243644 | ||
|
|
87a41561e7 | ||
|
|
5c439c245c | ||
|
|
e920b99951 | ||
|
|
22b405cba8 | ||
|
|
6f82c73409 | ||
|
|
b38db34de5 | ||
|
|
8c24370a9f | ||
|
|
fb8daed2b5 | ||
|
|
ee13255297 | ||
|
|
9c154fd0f3 | ||
|
|
b5dd942fd1 | ||
|
|
321669eb3a | ||
|
|
aa9609b5cf | ||
|
|
09418c6dd7 | ||
|
|
0ce0d1a352 | ||
|
|
c350bb45d0 | ||
|
|
06a9c44792 | ||
|
|
c5da009b7a | ||
|
|
23b0539686 | ||
|
|
8a236cc7ac | ||
|
|
4199b7bb50 | ||
|
|
842bc7d3ce | ||
|
|
fab6a9f584 | ||
|
|
7a714c03a9 | ||
|
|
2e0b050be3 | ||
|
|
ade723b6bc | ||
|
|
2b7d1c115d | ||
|
|
7e44e4b314 | ||
|
|
77cb589f03 | ||
|
|
56079ebdfe | ||
|
|
881ac9f68f | ||
|
|
55fa590785 | ||
|
|
a164eb8f7c | ||
|
|
888b2a7467 | ||
|
|
6f1624f43b | ||
|
|
04bef9a4b8 | ||
|
|
344d80206c | ||
|
|
c6b97b7892 | ||
|
|
6c0a0b62b6 | ||
|
|
bc94d42372 | ||
|
|
f4d683f17f | ||
|
|
d8afcfa013 | ||
|
|
af0d459b4c | ||
|
|
b766375db8 | ||
|
|
26498dc07b | ||
|
|
000a1f4c3d | ||
|
|
f0daf5ba20 | ||
|
|
250518c2a4 | ||
|
|
7acf0139d4 | ||
|
|
e4bbe15fc4 |
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,17 +1,9 @@
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
cmake_uninstall.cmake
|
||||
Makefile
|
||||
*.o
|
||||
.*.sw?
|
||||
wmfs
|
||||
src/config.h
|
||||
changelog
|
||||
config.h
|
||||
#*
|
||||
\#*
|
||||
build/
|
||||
doc/
|
||||
wmfs.doxygen
|
||||
wmfsrc
|
||||
Makefile
|
||||
wmfs.1.gz
|
||||
tags
|
||||
*.patch
|
||||
|
||||
262
CMakeLists.txt
262
CMakeLists.txt
@@ -1,262 +0,0 @@
|
||||
# -*- mode: cmake -*-
|
||||
#Cmakelists.txt
|
||||
# Minimum version of CMake
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(VERSION 2.6)
|
||||
endif()
|
||||
|
||||
CONFIGURE_FILE(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
ADD_CUSTOM_TARGET(uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
|
||||
# Source and build dirs
|
||||
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Project name - wmfs
|
||||
set(PROJECT_NAME wmfs)
|
||||
project(${PROJECT_NAME} C)
|
||||
|
||||
# Definition of the wmfs source
|
||||
set(wmfs_src
|
||||
src/confparse/util.c
|
||||
src/confparse/confparse.c
|
||||
src/barwin.c
|
||||
src/client.c
|
||||
src/config.c
|
||||
src/
|
||||
src/draw.c
|
||||
src/event.c
|
||||
src/ewmh.c
|
||||
src/frame.c
|
||||
src/getinfo.c
|
||||
src/infobar.c
|
||||
src/init.c
|
||||
src/launcher.c
|
||||
src/layout.c
|
||||
src/menu.c
|
||||
src/mouse.c
|
||||
src/screen.c
|
||||
src/tag.c
|
||||
src/util.c
|
||||
src/viwmfs.c
|
||||
src/wmfs.c)
|
||||
|
||||
# Set the executable from the wmfs_src
|
||||
add_executable(wmfs ${wmfs_src})
|
||||
|
||||
# Set the version
|
||||
set(VERSION "WMFS-201001")
|
||||
|
||||
# FLAGS
|
||||
set(CFLAGS "-g -Wall -ansi")
|
||||
set(CMAKE_C_FLAGS ${CFLAGS})
|
||||
|
||||
# Linker FLAGS
|
||||
|
||||
set(DEFAULT_LDFLAGS "-L /usr/local/lib -lpthread")
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES NetBSD)
|
||||
message("-- NetBSD system found - Using /usr/pkg/lib for linker")
|
||||
set(LDFLAGS "${DEFAULT_LDFLAGS} -L /usr/pkg/lib")
|
||||
else(CMAKE_SYSTEM_NAME MATCHES NetBSD)
|
||||
set(LDFLAGS ${DEFAULT_LDFLAGS})
|
||||
endif(CMAKE_SYSTEM_NAME MATCHES NetBSD)
|
||||
|
||||
set_target_properties(wmfs PROPERTIES LINK_FLAGS ${LDFLAGS})
|
||||
# Includes dir for libs in build_dir
|
||||
include_directories(
|
||||
${BUILD_DIR}/src
|
||||
)
|
||||
|
||||
# Package find
|
||||
find_package(Freetype)
|
||||
if(FREETYPE_FOUND)
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS})
|
||||
else (FREETYPE_FOUND)
|
||||
message(FATAL_ERROR "Could not find Freetype")
|
||||
endif (FREETYPE_FOUND)
|
||||
|
||||
find_package(X11)
|
||||
if(X11_FOUND)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
else (X11_FOUND)
|
||||
message(FATAL_ERROR "Could not find X11")
|
||||
endif (X11_FOUND)
|
||||
|
||||
# Link Libraries
|
||||
set(LIBRARIES_TO_LINK
|
||||
${FREETYPE_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
Xft)
|
||||
|
||||
# Includes
|
||||
include(FindDoxygen)
|
||||
include(FindPkgConfig)
|
||||
|
||||
# Use pkgconfig to get required libraries
|
||||
pkg_check_modules(WMFS_REQUIRED REQUIRED
|
||||
x11
|
||||
freetype2
|
||||
xft)
|
||||
|
||||
# Check for xinerama
|
||||
pkg_check_modules(HAVE_XINERAMA xinerama)
|
||||
if(HAVE_XINERAMA_FOUND)
|
||||
set(WMFS_HAVE_XINERAMA "#define HAVE_XINERAMA")
|
||||
set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xinerama)
|
||||
else()
|
||||
set(WMFS_HAVE_XINERAMA "")
|
||||
endif()
|
||||
|
||||
# Check for xrandr
|
||||
pkg_check_modules(HAVE_XRANDR xrandr)
|
||||
if(HAVE_XRANDR_FOUND)
|
||||
set(WMFS_HAVE_XRANDR "#define HAVE_XRANDR")
|
||||
set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xrandr)
|
||||
else()
|
||||
set(WMFS_HAVE_XRANDR "")
|
||||
endif()
|
||||
|
||||
target_link_libraries(wmfs ${LIBRARIES_TO_LINK})
|
||||
|
||||
# Messages
|
||||
message("Project version: ${VERSION}")
|
||||
message("Using these CFLAGS: ${CFLAGS}")
|
||||
message("Using these LDFLAGS: ${LDFLAGS}")
|
||||
message("Linking with theses libraries : ${LIBRARIES_TO_LINK}")
|
||||
|
||||
# Generating man page
|
||||
find_program(GZIP_EXECUTABLE gzip)
|
||||
if(NOT GZIP_EXECUTABLE)
|
||||
message(STATUS "Looking for gzip -- not found")
|
||||
message(STATUS "Could not generating man page")
|
||||
else()
|
||||
message(STATUS "Looking for gzip -- ${GZIP_EXECUTABLE}")
|
||||
message(STATUS "Generating man page")
|
||||
set(WMFS_MAN1_FILES ${BUILD_DIR}/wmfs.1.gz)
|
||||
execute_process(
|
||||
COMMAND ${GZIP_EXECUTABLE} -c wmfs.1
|
||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
||||
OUTPUT_FILE ${WMFS_MAN1_FILES})
|
||||
endif()
|
||||
|
||||
# Generating CHANGELOG
|
||||
find_program(GIT_EXECUTABLE git)
|
||||
if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE)
|
||||
message(STATUS "Looking for git -- ${GIT_EXECUTABLE}")
|
||||
message(STATUS "Git dir -- Generating changelog...")
|
||||
set(PROJECT_CHANGELOG ${SOURCE_DIR}/changelog)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} log
|
||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
||||
OUTPUT_FILE ${PROJECT_CHANGELOG})
|
||||
else()
|
||||
message(STATUS "Looking for git -- not found")
|
||||
message(STATUS "Could not generating changelog")
|
||||
endif()
|
||||
|
||||
# sets
|
||||
# {{{ Install path and configuration variables
|
||||
if(DEFINED PREFIX)
|
||||
set(PREFIX ${PREFIX} CACHE PATH "install prefix")
|
||||
set(CMAKE_INSTALL_PREFIX ${PREFIX})
|
||||
else()
|
||||
set(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "install prefix")
|
||||
endif()
|
||||
|
||||
#If a sysconfdir is specified, use it instead
|
||||
#of the default configuration dir.
|
||||
if(DEFINED SYSCONFDIR)
|
||||
set(SYSCONFDIR ${SYSCONFDIR} CACHE PATH "config directory")
|
||||
else()
|
||||
set(SYSCONFDIR /etc CACHE PATH "config directory")
|
||||
endif()
|
||||
|
||||
#If an XDG Config Dir is specificed, use it instead
|
||||
#of the default XDG configuration dir.
|
||||
if(DEFINED XDG_CONFIG_DIR)
|
||||
set(XDG_CONFIG_DIR ${XDG_CONFIG_SYS} CACHE PATH "xdg config directory")
|
||||
else()
|
||||
set(XDG_CONFIG_DIR ${SYSCONFDIR}/xdg CACHE PATH "xdg config directory")
|
||||
endif()
|
||||
|
||||
# setting WMFS_XSESSION_PATH
|
||||
if(DEFINED WMFS_XSESSION_PATH)
|
||||
set(WMFS_XSESSION_PATH ${WMFS_XSESSION_PATH} CACHE PATH "wmfs xsessions directory")
|
||||
else()
|
||||
set(WMFS_XSESSION_PATH ${PREFIX}/share/xsessions CACHE PATH "wmfs xsessions directory")
|
||||
endif()
|
||||
|
||||
if(DEFINED WMFS_MAN_PATH)
|
||||
set(WMFS_MAN_PATH ${WMFS_MAN_PATH} CACHE PATH "wmfs manpage directory")
|
||||
else()
|
||||
set(WMFS_MAN_PATH ${PREFIX}/share/man CACHE PATH "wmfs manpage directory")
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_EXECUTABLE)
|
||||
add_custom_target(doc
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${SOURCE_DIR}/wmfs.doxygen
|
||||
WORKING_DIRECTORY ${BUILD_DIR})
|
||||
endif()
|
||||
|
||||
find_program(URXVT_EXECUTABLE urxvt)
|
||||
if(URXVT_EXECUTABLE)
|
||||
set(WMFS_TERM urxvt)
|
||||
else()
|
||||
set(WMFS_TERM xterm)
|
||||
endif()
|
||||
|
||||
# Remplace strings in configs
|
||||
set(WMFS_VERSION ${VERSION})
|
||||
set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(WMFS_COMPILE_BY $ENV{USER})
|
||||
set(WMFS_COMPILE_FLAGS ${CFLAGS})
|
||||
set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK})
|
||||
set(WMFS_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_NAME})
|
||||
set(WMFS_SOURCE_DIR ${SOURCE_DIR})
|
||||
|
||||
# Configure files
|
||||
set(wmfs_configure_files
|
||||
src/config.h.in
|
||||
wmfs.doxygen.in
|
||||
wmfsrc.in)
|
||||
|
||||
macro(a_configure_file file)
|
||||
string(REGEX REPLACE ".in\$" "" outfile ${file})
|
||||
message(STATUS "Configuring ${outfile}")
|
||||
configure_file(${SOURCE_DIR}/${file}
|
||||
${SOURCE_DIR}/${outfile}
|
||||
ESCAPE_QUOTE
|
||||
@ONLY)
|
||||
endmacro()
|
||||
|
||||
foreach(file ${wmfs_configure_files})
|
||||
a_configure_file(${file})
|
||||
endforeach()
|
||||
|
||||
set(PROJECT_DATA_PATH share/${PROJECT_NAME})
|
||||
set(PROJECT_TODO ${SOURCE_DIR}/TODO)
|
||||
set(PROJECT_README ${SOURCE_DIR}/README)
|
||||
set(PROJECT_DEFAULT_CONF ${SOURCE_DIR}/wmfsrc)
|
||||
|
||||
# installs
|
||||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
|
||||
|
||||
if(WMFS_MAN1_FILES)
|
||||
install(FILES ${WMFS_MAN1_FILES} DESTINATION ${WMFS_MAN_PATH}/man1)
|
||||
endif()
|
||||
|
||||
if(PROJECT_CHANGELOG)
|
||||
install(FILES ${PROJECT_CHANGELOG} DESTINATION ${PROJECT_DATA_PATH})
|
||||
endif()
|
||||
|
||||
install(FILES ${PROJECT_TODO} ${PROJECT_README}
|
||||
${PROJECT_DEFAULT_CONF} DESTINATION ${PROJECT_DATA_PATH})
|
||||
install(FILES ${PROJECT_DEFAULT_CONF} DESTINATION ${WMFS_SYSCONFDIR})
|
||||
install(FILES "wmfs.desktop" DESTINATION ${WMFS_XSESSION_PATH})
|
||||
86
Makefile.in
Normal file
86
Makefile.in
Normal file
@@ -0,0 +1,86 @@
|
||||
PROG=wmfs
|
||||
MAN=wmfs.1
|
||||
|
||||
# wmfs version
|
||||
VERSION= 201011
|
||||
|
||||
SRCS= \
|
||||
src/barwin.c \
|
||||
src/client.c \
|
||||
src/config.c \
|
||||
src/draw.c \
|
||||
src/event.c \
|
||||
src/ewmh.c \
|
||||
src/frame.c \
|
||||
src/getinfo.c \
|
||||
src/infobar.c \
|
||||
src/init.c \
|
||||
src/launcher.c \
|
||||
src/layout.c \
|
||||
src/menu.c \
|
||||
src/mouse.c \
|
||||
src/parse_api.c \
|
||||
src/parse.c \
|
||||
src/screen.c \
|
||||
src/status.c \
|
||||
src/systray.c \
|
||||
src/tag.c \
|
||||
src/util.c \
|
||||
src/viwmfs.c \
|
||||
src/color.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} ${MAN}.gz
|
||||
|
||||
${PROG}: ${OBJS} src/structs.h src/wmfs.h src/parse.h
|
||||
${CC} -o $@ ${OBJS} ${LDFLAGS}
|
||||
|
||||
${MAN}.gz: ${MAN}
|
||||
gzip -cn -9 ${MAN} > $@
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f ${OBJS} wmfs ${MAN}.gz
|
||||
|
||||
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 manual page to ${DESTDIR}${MANPREFIX}/man1
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
install -m 644 ${MAN}.gz ${DESTDIR}${MANPREFIX}/man1/
|
||||
@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 manual page from ${DESTDIR}${MANPREFIX}/man1
|
||||
rm -f ${DESTDIR}${MANPREFIX}/man1/wmfs.1.gz
|
||||
@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/
|
||||
|
||||
|
||||
|
||||
.PHONY: all clean distclean install uninstall
|
||||
|
||||
32
README
32
README
@@ -4,33 +4,35 @@ WMFS Window Manager.
|
||||
|
||||
A highly configurable and manageable tiling Window Manager created from scratch
|
||||
|
||||
AUTHORS :
|
||||
Martin Duquesnoy <xorg62@gmail.com>
|
||||
AUTHORS : (in order of commits and > 5 commits)
|
||||
- Martin Duquesnoy <xorg62@gmail.com>
|
||||
- Philippe Pepiot <phil@philpep.org>
|
||||
- Marc Lagrange <markocpc@gmail.com>
|
||||
- OldMan <tele-post@mail.ru>
|
||||
- Raphael Khaiat <raphael@khaiat.org>
|
||||
- Tomáš Chvátal <scarabeus@gentoo.org>
|
||||
- David Delassus <linkdd@ydb.me>
|
||||
|
||||
|
||||
LICENSE : BSD
|
||||
|
||||
REQUIREMENT :
|
||||
- freetype2
|
||||
- libxinerama (optional)
|
||||
- libxrandr (optional)
|
||||
- libxft
|
||||
- libx11
|
||||
- CMake >= 2.6
|
||||
- libxinerama (optional)
|
||||
- libxrandr (optional)
|
||||
- imlib2 (optional)
|
||||
|
||||
OS :
|
||||
- GNU/Linux : Supported.
|
||||
- FreeBSD : Supported.
|
||||
- FreeBSD/OpenBSD/NetBSD : Supported.
|
||||
|
||||
INSTALL :
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make
|
||||
- sudo make install
|
||||
- sudo make uninstall # if you would to remove it.
|
||||
|
||||
If you have doxygen installed you can generate doxygen documentation via custom target 'make doc' in the build dir.
|
||||
./configure [--without-imlib2|--without-xrandr|--without-xinerama] (./configure -h)
|
||||
make
|
||||
sudo make install
|
||||
|
||||
DISTROS :
|
||||
- wmfs port for FreeBSD at x11-wm/wmfs
|
||||
- wmfs is available with AUR in ArchLinux
|
||||
- wmfs is available with AUR in ArchLinux (wmfs or wmfs-git)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
|
||||
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
STRING(REGEX REPLACE "\n" ";" files "${files}")
|
||||
FOREACH(file ${files})
|
||||
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
|
||||
IF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
EXEC_PROGRAM(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
IF(NOT "${rm_retval}" STREQUAL 0)
|
||||
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
|
||||
ENDIF(NOT "${rm_retval}" STREQUAL 0)
|
||||
ELSE(EXISTS "$ENV{DESTDIR}${file}")
|
||||
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
|
||||
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
|
||||
ENDFOREACH(file)
|
||||
105
configure
vendored
Executable file
105
configure
vendored
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/bin/sh
|
||||
|
||||
LIBS="x11 xft freetype2"
|
||||
USE_XINERAMA="xinerama"
|
||||
USE_XRANDR="xrandr"
|
||||
USE_IMLIB2="imlib2"
|
||||
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;;
|
||||
--without-xrandr)
|
||||
USE_XRANDR=""; shift;;
|
||||
--without-imlib2)
|
||||
USE_IMLIB2=""; 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;;
|
||||
--man-prefix)
|
||||
[ -z "$2" ] && echo "Missing argument" && exit 1
|
||||
MANPREFIX=$2; shift 2;;
|
||||
--help|-h)
|
||||
echo "Usage: ./configure [options]
|
||||
--without-imlib2 : compile without imlib2 support
|
||||
--without-xrandr : compile without xrandr support
|
||||
--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)
|
||||
--man-prefix DIRECTORY : install man page to specified prefix (default $MANPREFIX)"
|
||||
exit 0;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
LIBS="$LIBS $USE_XINERAMA $USE_XRANDR $USE_IMLIB2"
|
||||
|
||||
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 -I/usr/local/include/freetype2"
|
||||
LDFLAGS="-L/usr/local/lib";;
|
||||
OpenBSD)
|
||||
CFLAGS="-I/usr/X11R6/include -I/usr/X11R6/include/freetype2 -I/usr/local/include"
|
||||
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
|
||||
NetBSD)
|
||||
CFLAGS="-I/usr/X11R7/include -I/usr/X11R7/include/freetype2 -I/usr/local/include"
|
||||
LDFLAGS="-L/usr/X11R7/lib -L/usr/local/lib";;
|
||||
Linux)
|
||||
CFLAGS="-I/usr/include/freetype2"
|
||||
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 -lXft -lfreetype"
|
||||
|
||||
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
|
||||
[ -n "$USE_XRANDR" ] && LDFLAGS="$LDFLAGS -lXrandr"
|
||||
[ -n "$USE_IMLIB2" ] && LDFLAGS="$LDFLAGS -lImlib2"
|
||||
fi
|
||||
|
||||
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
|
||||
[ -n "$USE_XRANDR" ] && CFLAGS="$CFLAGS -DHAVE_XRANDR"
|
||||
[ -n "$USE_IMLIB2" ] && CFLAGS="$CFLAGS -DHAVE_IMLIB"
|
||||
|
||||
LDFLAGS="$LDFLAGS -lpthread"
|
||||
|
||||
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 :-)
|
||||
"
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
statustext()
|
||||
{
|
||||
local DATE=`date`
|
||||
|
||||
wmfs -s "$DATE"
|
||||
wmfs -s "`date`"
|
||||
}
|
||||
|
||||
statustext
|
||||
|
||||
70
src/barwin.c
70
src/barwin.c
@@ -58,7 +58,7 @@ barwin_create(Window parent,
|
||||
BarWindow *bw;
|
||||
|
||||
/* Allocate memory */
|
||||
bw = emalloc(1, sizeof(BarWindow));
|
||||
bw = zcalloc(sizeof(*bw));
|
||||
|
||||
/* Barwin attributes */
|
||||
at.override_redirect = True;
|
||||
@@ -67,6 +67,7 @@ barwin_create(Window parent,
|
||||
|ButtonMask|MouseMask
|
||||
|ExposureMask|VisibilityChangeMask
|
||||
|StructureNotifyMask|SubstructureRedirectMask;
|
||||
|
||||
if(entermask)
|
||||
at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask;
|
||||
|
||||
@@ -80,11 +81,13 @@ barwin_create(Window parent,
|
||||
if(border)
|
||||
{
|
||||
bw->bord = True;
|
||||
bw->border.light = color_shade(bg, conf.colors.bar_light_shade);
|
||||
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
|
||||
|
||||
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(bg), &at);
|
||||
CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, color_enlight(bg), &at);
|
||||
CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, SHADC, &at);
|
||||
CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, SHADC, &at);
|
||||
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, bg, &at);
|
||||
CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, bg, &at);
|
||||
CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, bg, &at);
|
||||
CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, bg, &at);
|
||||
}
|
||||
|
||||
/* Property */
|
||||
@@ -94,8 +97,6 @@ barwin_create(Window parent,
|
||||
bw->geo.height = h;
|
||||
bw->bg = bg;
|
||||
bw->fg = fg;
|
||||
bw->border.light = color_enlight(bg);
|
||||
bw->border.dark = SHADC;
|
||||
bw->stipple = stipple;
|
||||
bw->stipple_color = -1;
|
||||
|
||||
@@ -107,18 +108,58 @@ barwin_create(Window parent,
|
||||
void
|
||||
barwin_draw_text(BarWindow *bw, int x, int y, char *text)
|
||||
{
|
||||
if(!text)
|
||||
return;
|
||||
|
||||
/* Background color of the text if there is stipple */
|
||||
if(bw->stipple)
|
||||
draw_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg);
|
||||
|
||||
/* Draw text */
|
||||
draw_text(bw->dr, x, y, bw->fg, 0, text);
|
||||
draw_text(bw->dr, x, y, bw->fg, text);
|
||||
|
||||
barwin_refresh(bw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw text in a Barwindow
|
||||
*/
|
||||
void
|
||||
barwin_draw_image_ofset_text(BarWindow *bw, int x, int y, char *text, int x_image_ofset, int y_image_ofset)
|
||||
{
|
||||
if(!text)
|
||||
return;
|
||||
|
||||
/* Background color of the text if there is stipple */
|
||||
if(bw->stipple)
|
||||
draw_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg);
|
||||
|
||||
/* Draw text */
|
||||
draw_image_ofset_text(bw->dr, x, y, bw->fg, text, x_image_ofset, y_image_ofset);
|
||||
|
||||
barwin_refresh(bw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
barwin_color_set(BarWindow *bw, uint bg, char *fg)
|
||||
{
|
||||
CHECK(bw);
|
||||
|
||||
bw->bg = bg;
|
||||
bw->fg = fg;
|
||||
|
||||
if(bw->bord)
|
||||
{
|
||||
bw->border.light = color_shade(bg, conf.colors.bar_light_shade);
|
||||
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Delete a BarWindow
|
||||
* \param bw BarWindow pointer
|
||||
*/
|
||||
@@ -214,12 +255,10 @@ barwin_unmap_subwin(BarWindow *bw)
|
||||
void
|
||||
barwin_move(BarWindow *bw, int x, int y)
|
||||
{
|
||||
CHECK(bw);
|
||||
if(!bw || (bw->geo.x == x && bw->geo.y == y))
|
||||
return;
|
||||
|
||||
bw->geo.x = x;
|
||||
bw->geo.y = y;
|
||||
|
||||
XMoveWindow(dpy, bw->win, x, y);
|
||||
XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -232,7 +271,8 @@ barwin_move(BarWindow *bw, int x, int y)
|
||||
void
|
||||
barwin_resize(BarWindow *bw, uint w, uint h)
|
||||
{
|
||||
CHECK(bw);
|
||||
if(!bw || (bw->geo.width == w && bw->geo.height == h))
|
||||
return;
|
||||
|
||||
bw->geo.width = w;
|
||||
bw->geo.height = h;
|
||||
@@ -270,7 +310,7 @@ barwin_refresh_color(BarWindow *bw)
|
||||
|
||||
if(bw->stipple)
|
||||
{
|
||||
XSetForeground(dpy, gc_stipple, ((bw->stipple_color != -1) ? bw->stipple_color : getcolor(bw->fg)));
|
||||
XSetForeground(dpy, gc_stipple, ((bw->stipple_color != (uint)-1) ? (long)bw->stipple_color : getcolor(bw->fg)));
|
||||
XFillRectangle(dpy, bw->dr, gc_stipple, 3, 2, bw->geo.width - 6, bw->geo.height - 4);
|
||||
}
|
||||
|
||||
|
||||
738
src/client.c
738
src/client.c
File diff suppressed because it is too large
Load Diff
223
src/color.c
Normal file
223
src/color.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* color.c
|
||||
* Copyright © 2011 Brian Mock <mock.brian@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
/** Clamp a number x within the range [a, b].
|
||||
* \param x the number which to clamp
|
||||
* \param a the lowest possible value
|
||||
* \param b the highest possible value
|
||||
* \return the clamped number
|
||||
*/
|
||||
static double
|
||||
color_clamp(double x, double a, double b)
|
||||
{
|
||||
if(x < a)
|
||||
return a;
|
||||
else if(x > b)
|
||||
return b;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Pack a triplet of RGB values into a single uint
|
||||
* \param r the red value
|
||||
* \param g the green value
|
||||
* \param b the blue value
|
||||
* \return the packed RGB value
|
||||
*/
|
||||
static uint
|
||||
color_pack_rgb(uint r, uint g, uint b)
|
||||
{
|
||||
return (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
/** Unpack an RGB uint into three separate values
|
||||
* \param rgb the packed color
|
||||
* \param r a pointer to a uint where the red value will be stored
|
||||
* \param g a pointer to a uint where the green value will be stored
|
||||
* \param b a pointer to a uint where the blue value will be stored
|
||||
*/
|
||||
static void
|
||||
color_unpack_rgb(uint rgb, uint *r, uint *g, uint *b)
|
||||
{
|
||||
*r = (rgb >> 16) & 0xFF;
|
||||
*g = (rgb >> 8) & 0xFF;
|
||||
*b = rgb & 0xFF;
|
||||
}
|
||||
|
||||
/** Convert unpacked RGB values into HSL, storing in the doubles referenced
|
||||
* by the pointers h, s, l
|
||||
*/
|
||||
static void
|
||||
color_rgb_to_hsl(uint xr, uint xg, uint xb, double *h, double *s, double *l)
|
||||
{
|
||||
double r = xr/255.0;
|
||||
double g = xg/255.0;
|
||||
double b = xb/255.0;
|
||||
|
||||
double v;
|
||||
double m;
|
||||
double vm;
|
||||
double r2, g2, b2;
|
||||
|
||||
*h = 0;
|
||||
*s = 0;
|
||||
*l = 0;
|
||||
|
||||
/* v is max(r, g, b)
|
||||
* m is min(r, g, b)
|
||||
*/
|
||||
v = r > g ? r : g;
|
||||
v = v > b ? v : b;
|
||||
m = r < g ? r : g;
|
||||
m = m < b ? m : b;
|
||||
|
||||
*l = (m + v)/2.0;
|
||||
|
||||
if(*l <= 0.0)
|
||||
return;
|
||||
|
||||
vm = v - m;
|
||||
*s = vm;
|
||||
|
||||
if(*s > 0.0)
|
||||
*s /= (*l <= 0.5) ? (v + m) : (2.0 - v - m);
|
||||
else
|
||||
return;
|
||||
|
||||
r2 = (v - r)/vm;
|
||||
g2 = (v - g)/vm;
|
||||
b2 = (v - b)/vm;
|
||||
|
||||
if(r == v)
|
||||
*h = (g == m ? 5.0 + b2 : 1.0 - g2);
|
||||
else if(g == v)
|
||||
*h = (b == m ? 1.0 + r2 : 3.0 - b2);
|
||||
else
|
||||
*h = (r == m ? 3.0 + g2 : 5.0 - r2);
|
||||
|
||||
*h /= 6.0;
|
||||
}
|
||||
|
||||
/** Convert h, s, l values to RGB and store them in the three uint
|
||||
* referenced by the last three parameters.
|
||||
*/
|
||||
static void
|
||||
color_hsl_to_rgb(double h, double sl, double l, uint *rx, uint *gx, uint *bx)
|
||||
{
|
||||
double v;
|
||||
double r,g,b;
|
||||
|
||||
r = l;
|
||||
g = l;
|
||||
b = l;
|
||||
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
|
||||
if(v > 0)
|
||||
{
|
||||
double m;
|
||||
double sv;
|
||||
int sextant;
|
||||
double fract, vsf, mid1, mid2;
|
||||
|
||||
m = l + l - v;
|
||||
sv = (v - m ) / v;
|
||||
h *= 6.0;
|
||||
sextant = (int) h;
|
||||
fract = h - sextant;
|
||||
vsf = v * sv * fract;
|
||||
mid1 = m + vsf;
|
||||
mid2 = v - vsf;
|
||||
switch(sextant)
|
||||
{
|
||||
case 0:
|
||||
r = v;
|
||||
g = mid1;
|
||||
b = m;
|
||||
break;
|
||||
case 1:
|
||||
r = mid2;
|
||||
g = v;
|
||||
b = m;
|
||||
break;
|
||||
case 2:
|
||||
r = m;
|
||||
g = v;
|
||||
b = mid1;
|
||||
break;
|
||||
case 3:
|
||||
r = m;
|
||||
g = mid2;
|
||||
b = v;
|
||||
break;
|
||||
case 4:
|
||||
r = mid1;
|
||||
g = m;
|
||||
b = v;
|
||||
break;
|
||||
case 5:
|
||||
r = v;
|
||||
g = m;
|
||||
b = mid2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*rx = r * 255.0;
|
||||
*gx = g * 255.0;
|
||||
*bx = b * 255.0;
|
||||
}
|
||||
|
||||
/** Shades a color by the amount. This works by converting a packed RGB
|
||||
* color to HSL, adding the amount to the lightness,
|
||||
* and then converting back to RGB. 1.0 is max lightness, 0.0 is min lightness.
|
||||
* \param shadeVal the amount to shade the lightness by.
|
||||
* \return the shaded color
|
||||
*/
|
||||
uint
|
||||
color_shade(uint rgb, double shadeVal)
|
||||
{
|
||||
uint r, g, b;
|
||||
double h, s, l;
|
||||
|
||||
color_unpack_rgb(rgb, &r, &g, &b);
|
||||
color_rgb_to_hsl(r, g, b, &h, &s, &l);
|
||||
|
||||
l += shadeVal;
|
||||
|
||||
l = color_clamp(l, 0, 1);
|
||||
|
||||
color_hsl_to_rgb(h, s, l, &r, &g, &b);
|
||||
rgb = color_pack_rgb(r, g, b);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
789
src/config.c
789
src/config.c
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* config.h
|
||||
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
#define WMFS_VERSION "@WMFS_VERSION@"
|
||||
#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@"
|
||||
#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@"
|
||||
#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@"
|
||||
#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@"
|
||||
#define XDG_CONFIG_DIR "@XDG_CONFIG_DIR@"
|
||||
@WMFS_HAVE_XINERAMA@
|
||||
@WMFS_HAVE_XRANDR@
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
@@ -1,289 +0,0 @@
|
||||
/*
|
||||
* confparse.c
|
||||
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "confparse.h"
|
||||
|
||||
char*
|
||||
file_to_str(char *path)
|
||||
{
|
||||
char *buf, *ret, *p, *c;
|
||||
int fd, i;
|
||||
struct stat st;
|
||||
Bool is_char = False;
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
if (!(fd = open(path, O_RDONLY)))
|
||||
{
|
||||
warn("%s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the file size */
|
||||
stat(path, &st);
|
||||
|
||||
/* Bufferize file */
|
||||
if((buf = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET)) == (char*) MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
/* Copy buffer without comments in return value */
|
||||
ret = emalloc(strlen(buf) + 1, sizeof(char));
|
||||
|
||||
for(p = buf, i = 0; *p != '\0'; p++)
|
||||
{
|
||||
if(!is_char && (c = strchr("\"'", *p)))
|
||||
is_char = !is_char;
|
||||
else if (is_char && *p == *c)
|
||||
is_char = !is_char;
|
||||
|
||||
if(*p == COMMENT_CHAR && !is_char)
|
||||
{
|
||||
if(!(p = strchr(p, '\n')))
|
||||
break;
|
||||
ret[i++] = '\n';
|
||||
}
|
||||
else
|
||||
ret[i++] = *p;
|
||||
}
|
||||
ret[i++] = '\0';
|
||||
|
||||
/* Unmap buffer, thanks linkdd. */
|
||||
munmap(buf, st.st_size);
|
||||
close(fd);
|
||||
|
||||
warnx("%s read.", path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char*
|
||||
get_sec(char *src, char *name)
|
||||
{
|
||||
char *ret = NULL, *start, *end, *p;
|
||||
char **sec;
|
||||
size_t len;
|
||||
|
||||
if(!src)
|
||||
return NULL;
|
||||
|
||||
if(!name)
|
||||
return src;
|
||||
|
||||
sec = secname(name);
|
||||
len = strlen(sec[SecStart]);
|
||||
|
||||
/* Find start section pointer */
|
||||
for(start = src; *start != '\0'; start++)
|
||||
{
|
||||
if( (p = strchr("\"'", *start)) )
|
||||
while (*(++start) && *start != *p);
|
||||
|
||||
if(!strncmp(start, sec[SecStart], len))
|
||||
break;
|
||||
}
|
||||
|
||||
if(*start != '\0')
|
||||
{
|
||||
/* Here is_char == False */
|
||||
start += len;
|
||||
/* Find end section pointer */
|
||||
for(end = start; *end != '\0'; end++)
|
||||
{
|
||||
if( (p = strchr("\"'", *start)) )
|
||||
while (*(++start) && *start != *p);
|
||||
|
||||
if(!strncmp(end, sec[SecEnd], len+1))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate and set ret */
|
||||
if(end != '\0')
|
||||
{
|
||||
len = end - start;
|
||||
ret = emalloc(len + 1, sizeof(char));
|
||||
memcpy(ret, start, len);
|
||||
ret[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
free_secname(sec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char*
|
||||
get_nsec(char *src, char *name, int n)
|
||||
{
|
||||
int i;
|
||||
char *ret, *buf, **sec;
|
||||
|
||||
if(!src || !strlen(src))
|
||||
return NULL;
|
||||
|
||||
if(!name)
|
||||
return src;
|
||||
|
||||
if(!n)
|
||||
return get_sec(src, name);
|
||||
|
||||
sec = secname(name);
|
||||
|
||||
buf = _strdup(sauv_delimc);
|
||||
|
||||
for(i = 0; i < n && (buf = strstr(buf, sec[SecStart])); ++i, buf += strlen(sec[SecStart]));
|
||||
|
||||
ret = get_sec(src + strlen(src) - strlen(buf), name);
|
||||
|
||||
free_secname(sec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
get_size_sec(char *src, char *name)
|
||||
{
|
||||
int ret;
|
||||
char **sec, *buf;
|
||||
|
||||
if(!src || !name)
|
||||
return 0;
|
||||
|
||||
sec = secname(name);
|
||||
|
||||
buf = _strdup(sauv_secc);
|
||||
|
||||
for(ret = 0; (buf = strstr(buf, sec[SecStart])); ++ret, buf += strlen(sec[SecStart]));
|
||||
|
||||
free_secname(sec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
opt_type
|
||||
get_opt(char *src, char *def, char *name)
|
||||
{
|
||||
int i;
|
||||
char *p = NULL, *p2 = NULL;
|
||||
opt_type ret = null_opt_type;
|
||||
|
||||
if(!src || !name)
|
||||
return (def) ? str_to_opt(def) : ret;
|
||||
|
||||
if((p = opt_srch(sauv_secc, name)))
|
||||
{
|
||||
for(i = 0; p[i] && p[i] != '\n'; ++i);
|
||||
p[i] = '\0';
|
||||
|
||||
p2 = _strdup(p + strlen(name));
|
||||
|
||||
if((p = strchr(p, '=')) && !is_in_delimiter(p, 0))
|
||||
{
|
||||
for(i = 0; p2[i] && p2[i] != '='; ++i);
|
||||
p2[i] = '\0';
|
||||
|
||||
/* Check if there is anything else that spaces
|
||||
* between option name and '=' */
|
||||
for(i = 0; i < strlen(p2); ++i)
|
||||
if(p2[i] != ' ')
|
||||
{
|
||||
warnx("Configuration warning: Missing '=' after option: '%s'"
|
||||
" and before expression: '%s'\n", name, p2);
|
||||
return str_to_opt(def);
|
||||
}
|
||||
|
||||
ret = str_to_opt(clean_value(++p));
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret.str)
|
||||
ret = str_to_opt(def);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* option = {val1, val2, val3} */
|
||||
opt_type*
|
||||
get_list_opt(char *src, char *def, char *name, int *n)
|
||||
{
|
||||
int i, j;
|
||||
char *p, *p2;
|
||||
opt_type *ret;
|
||||
|
||||
if(!src || !name)
|
||||
return NULL;
|
||||
|
||||
*n = 0;
|
||||
|
||||
if(!(p = get_opt(src, def, name).str))
|
||||
return NULL;
|
||||
|
||||
for(i = 0; p[i] && (p[i] != LIST_DEL_E || is_in_delimiter(p, i)); ++i);
|
||||
p[i + 1] = '\0';
|
||||
|
||||
/* Syntax of list {val1, val2, ..., valx} */
|
||||
if(*p != LIST_DEL_S || *(p + strlen(p) - 1) != LIST_DEL_E)
|
||||
return NULL;
|
||||
|
||||
/* Erase ( ) */
|
||||
++p;
|
||||
*(p + strlen(p) - 1) = '\0';
|
||||
|
||||
/* > 1 value in list */
|
||||
if(strchr(p, ','))
|
||||
{
|
||||
/* Count ',' */
|
||||
for(i = 0, *n = 1; i < strlen(p); ++i)
|
||||
if(p[i] == ',' && !is_in_delimiter(p, i))
|
||||
++(*n);
|
||||
|
||||
ret = emalloc(*n, sizeof(opt_type));
|
||||
|
||||
p2 = _strdup(p);
|
||||
|
||||
/* Set all value in return array */
|
||||
for(i = j = 0; i < *n; ++i, p2 += ++j)
|
||||
{
|
||||
for(j = 0; j < strlen(p2) && (p2[j] != ',' || is_in_delimiter(p2, j)); ++j);
|
||||
p2[j] = '\0';
|
||||
|
||||
ret[i] = str_to_opt(clean_value(p2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = emalloc((*n = 1), sizeof(opt_type));
|
||||
*ret = str_to_opt(clean_value(p));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* confparse.h
|
||||
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CONFPARSE_H
|
||||
#define CONFPARSE_H
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../wmfs.h"
|
||||
|
||||
/* Section delimiter */
|
||||
#define SEC_DEL_S '['
|
||||
#define SEC_DEL_E ']'
|
||||
|
||||
/* List delimiter */
|
||||
#define LIST_DEL_S '{'
|
||||
#define LIST_DEL_E '}'
|
||||
|
||||
/* Comment character */
|
||||
#define COMMENT_CHAR '#'
|
||||
|
||||
enum { SecStart, SecEnd, SecLast };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
long int num;
|
||||
float fnum;
|
||||
Bool bool;
|
||||
char *str;
|
||||
} opt_type;
|
||||
|
||||
/* util.c */
|
||||
char *erase_delim_content(char *buf);
|
||||
Bool is_in_delimiter(char *buf, int p);
|
||||
char *erase_sec_content(char *buf);
|
||||
char *opt_srch(char *buf, char *opt);
|
||||
opt_type str_to_opt(char *str);
|
||||
char *clean_value(char *str);
|
||||
void cfg_set_sauv(char *str);
|
||||
char **secname(char *name);
|
||||
void free_secname(char **secname);
|
||||
|
||||
/* confparse.c */
|
||||
char *file_to_str(char *path);
|
||||
char *get_sec(char *src, char *name);
|
||||
char *get_nsec(char *src, char *name, int n);
|
||||
int get_size_sec(char *src, char *name);
|
||||
opt_type get_opt(char *src, char *def, char *name);
|
||||
opt_type *get_list_opt(char *src, char *def, char *name, int *n);
|
||||
|
||||
static const opt_type null_opt_type = {0, 0, 0, NULL};
|
||||
|
||||
char *sauv_delimc;
|
||||
char *sauv_secc;
|
||||
|
||||
#endif /* CONFPARSE_H */
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* confparse/util.c
|
||||
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "confparse.h"
|
||||
|
||||
char*
|
||||
erase_delim_content(char *buf)
|
||||
{
|
||||
int i, j;
|
||||
char *str, c;
|
||||
|
||||
if(!buf || !(str = _strdup(buf)))
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < strlen(str); ++i)
|
||||
if(strchr("\"'", (c = str[i])))
|
||||
{
|
||||
for(*(str + (j = i)) = ' '; str[j] && str[j] != c; str[j++] = ' ');
|
||||
str[j] = ' ';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Erase all content of all delimiters, put it
|
||||
* int str, and check if buf[p] is in an delimiter. */
|
||||
Bool
|
||||
is_in_delimiter(char *buf, int p)
|
||||
{
|
||||
if(*(erase_delim_content(buf) + p) != buf[p])
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
char*
|
||||
erase_sec_content(char *buf)
|
||||
{
|
||||
int i, j;
|
||||
char *p, *str, *name, *ret;
|
||||
char **sec;
|
||||
|
||||
if(!buf || !(str = _strdup(sauv_delimc)))
|
||||
return NULL;
|
||||
|
||||
ret = _strdup(buf);
|
||||
|
||||
for(i = 1, name = _strdup(str + i); strchr(str + i, SEC_DEL_S); ++i, name = _strdup(str + i))
|
||||
{
|
||||
for(; str[i] && str[i] != SEC_DEL_S; ++i);
|
||||
for(j = 0; str[i] && str[i] != SEC_DEL_E; name[j++] = str[i++]);
|
||||
++name;
|
||||
name[j - 1] = '\0';
|
||||
|
||||
if(*name == '/')
|
||||
continue;
|
||||
|
||||
sec = secname(name);
|
||||
|
||||
if((p = strstr(str + i, sec[SecEnd])))
|
||||
for(++i; i < strlen(ret) - strlen(p); ret[i++] = ' ');
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
free_secname(sec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* To get the RIGHT name of an option; if option needed is
|
||||
* pwet and there is tagadapwettagada in the configuration,
|
||||
* with strstr(), the name will matchs */
|
||||
char*
|
||||
opt_srch(char *buf, char *opt)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if(!buf || !opt)
|
||||
return NULL;
|
||||
|
||||
if((p = strstr(sauv_delimc /*erase_delim_content(buf)*/, opt)))
|
||||
if((*(p + strlen(opt)) == ' ' || *(p + strlen(opt)) == '=')
|
||||
&& (*(p - 1) == ' ' || *(p - 1) == '\n' || *(p - 1) == '\t' || !(*(p - 1))))
|
||||
return _strdup(buf + (strlen(buf) - strlen(p)));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opt_type
|
||||
str_to_opt(char *str)
|
||||
{
|
||||
opt_type ret = null_opt_type;
|
||||
|
||||
if(!strlen(str))
|
||||
return ret;
|
||||
|
||||
/* Integer */
|
||||
ret.num = atoi(str);
|
||||
|
||||
/* Float */
|
||||
sscanf(str, "%f", &ret.fnum);
|
||||
|
||||
/* Boolean */
|
||||
if(strstr(str, "true") || strstr(str, "True")
|
||||
|| strstr(str, "TRUE") || strstr(str, "1"))
|
||||
ret.bool = True;
|
||||
|
||||
/* String */
|
||||
ret.str = _strdup(str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char*
|
||||
clean_value(char *str)
|
||||
{
|
||||
int i;
|
||||
char c, *p;
|
||||
|
||||
if(!str || !(p = _strdup(str)))
|
||||
return NULL;
|
||||
|
||||
/* Remove useless spaces */
|
||||
for(; *p == ' '; ++p);
|
||||
for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0');
|
||||
|
||||
/* For string delimiter (" or ') */
|
||||
if(((c = *p) == '"' || (c = *p) == '\'') && strchr(p + 1, c))
|
||||
{
|
||||
for(++p, i = 0; p[i] && p[i] != c; ++i);
|
||||
p[i] = '\0';
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
cfg_set_sauv(char *str)
|
||||
{
|
||||
if(!str)
|
||||
{
|
||||
sauv_delimc = NULL;
|
||||
sauv_secc = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sauv_delimc = erase_delim_content(_strdup(str));
|
||||
sauv_secc = erase_sec_content(_strdup(str));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char**
|
||||
secname(char *name)
|
||||
{
|
||||
char **ret = NULL;
|
||||
|
||||
if(!name)
|
||||
return NULL;
|
||||
|
||||
ret = emalloc(SecLast, sizeof(char*));
|
||||
|
||||
/* Len of name + '[' + ']' + '\0' */
|
||||
ret[SecStart] = emalloc(strlen(name) + 3, sizeof(char));
|
||||
|
||||
/* Len of name + '[' + '/' + ']' + '\0' */
|
||||
ret[SecEnd] = emalloc(strlen(name) + 4, sizeof(char));
|
||||
|
||||
sprintf(ret[SecStart], "%c%s%c", SEC_DEL_S, name, SEC_DEL_E);
|
||||
sprintf(ret[SecEnd], "%c/%s%c", SEC_DEL_S, name, SEC_DEL_E);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
free_secname(char **secname)
|
||||
{
|
||||
if(!secname || LEN(secname) != SecLast)
|
||||
return;
|
||||
|
||||
if(secname[SecStart])
|
||||
free(secname[SecStart]);
|
||||
if(secname[SecEnd])
|
||||
free(secname[SecEnd]);
|
||||
|
||||
free(secname);
|
||||
|
||||
return;
|
||||
}
|
||||
138
src/draw.c
138
src/draw.c
@@ -32,6 +32,53 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
/** Draw an image in a drawable
|
||||
* \param dr Drawable
|
||||
* \param x X position
|
||||
* \param y Y position
|
||||
* \param name Path of the image
|
||||
*/
|
||||
static void draw_image(Drawable dr, int x, int y, int w, int h, char *name)
|
||||
{
|
||||
Imlib_Image image;
|
||||
|
||||
if(!name)
|
||||
return;
|
||||
|
||||
imlib_set_cache_size(2048 * 1024);
|
||||
imlib_context_set_display(dpy);
|
||||
imlib_context_set_visual(DefaultVisual(dpy, DefaultScreen(dpy)));
|
||||
imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy)));
|
||||
imlib_context_set_drawable(dr);
|
||||
|
||||
image = imlib_load_image(patht(name));
|
||||
imlib_context_set_image(image);
|
||||
|
||||
if(w <= 0)
|
||||
w = imlib_image_get_width();
|
||||
|
||||
if(h <= 0)
|
||||
h = imlib_image_get_height();
|
||||
|
||||
if(image)
|
||||
{
|
||||
imlib_render_image_on_drawable_at_size(x, y, w, h);
|
||||
imlib_free_image();
|
||||
}
|
||||
else
|
||||
warnx("Can't draw image: '%s'", name);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
void
|
||||
draw_text(Drawable d, int x, int y, char* fg, char *str)
|
||||
{
|
||||
draw_image_ofset_text(d, x, y, fg, str, 0, 0);
|
||||
}
|
||||
|
||||
/** Draw a string in a Drawable
|
||||
* \param d Drawable
|
||||
* \param x X position
|
||||
@@ -41,10 +88,40 @@
|
||||
* \param str String that will be draw
|
||||
*/
|
||||
void
|
||||
draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
|
||||
draw_image_ofset_text(Drawable d, int x, int y, char* fg, char *str, int x_image_ofset, int y_image_ofset)
|
||||
{
|
||||
XftColor xftcolor;
|
||||
XftDraw *xftd;
|
||||
#ifdef HAVE_IMLIB
|
||||
char *ostr = NULL;
|
||||
int i, ni, sw = 0;
|
||||
ImageAttr im[128];
|
||||
size_t textlen;
|
||||
#else
|
||||
(void)x_image_ofset;
|
||||
(void)y_image_ofset;
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
if(!str)
|
||||
return;
|
||||
|
||||
/* To draw image everywhere we can draw text */
|
||||
#ifdef HAVE_IMLIB
|
||||
|
||||
ostr = xstrdup(str);
|
||||
textlen = strlen(ostr);
|
||||
|
||||
if(strstr(str, "i["))
|
||||
{
|
||||
ni = parse_image_block(im, str);
|
||||
|
||||
if(infobar[conf.systray.screen].bar && d == infobar[conf.systray.screen].bar->dr)
|
||||
sw = systray_get_width();
|
||||
|
||||
for(i = 0; i < ni; ++i)
|
||||
draw_image(d, x_image_ofset + im[i].x - sw, y_image_ofset + im[i].y, im[i].w, im[i].h, im[i].name);
|
||||
}
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
/* Transform X Drawable -> Xft Drawable */
|
||||
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
|
||||
@@ -60,6 +137,13 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
|
||||
|
||||
XftDrawDestroy(xftd);
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
if(strstr(ostr, "i["))
|
||||
strncpy(str, ostr, textlen);
|
||||
|
||||
free(ostr);
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,21 +166,67 @@ draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw a Graph in a drawable
|
||||
* \param dr Drawable
|
||||
* \param x X position
|
||||
* \param y Y position
|
||||
* \param w Width
|
||||
* \param h Height
|
||||
* \param color Color of the graph
|
||||
* \param data Array of bytes that will be draw
|
||||
*/
|
||||
void
|
||||
draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data)
|
||||
{
|
||||
uint i;
|
||||
|
||||
XSetForeground(dpy, gc, color);
|
||||
|
||||
for(i = 0; i < w; ++i)
|
||||
{
|
||||
XRectangle r = { (x + i), (y + h - data[i]), 1, data[i] };
|
||||
|
||||
XFillRectangles(dpy, dr, gc, &r, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Calculates the text's size relatively to the font
|
||||
* \param text Text string
|
||||
* \return final text width
|
||||
*/
|
||||
ushort
|
||||
textw(const char *text)
|
||||
textw(char *text)
|
||||
{
|
||||
XGlyphInfo gl;
|
||||
#ifdef HAVE_IMLIB
|
||||
char *ostr = NULL;
|
||||
ImageAttr im[128];
|
||||
size_t textlen;
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
if(!text)
|
||||
return 0;
|
||||
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
|
||||
ostr = xstrdup(text);
|
||||
textlen = strlen(ostr);
|
||||
|
||||
if(strstr(text, "i["))
|
||||
parse_image_block(im, text);
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
XftTextExtentsUtf8(dpy, font, (FcChar8 *)text, strlen(text), &gl);
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
if(strstr(ostr, "i["))
|
||||
strncpy(text, ostr, textlen);
|
||||
|
||||
free(ostr);
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
return gl.width + font->descent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
322
src/event.c
322
src/event.c
@@ -35,7 +35,7 @@
|
||||
/** ButtonPress handle event
|
||||
* \param ev XButtonEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
buttonpress(XButtonEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
@@ -49,6 +49,8 @@ buttonpress(XButtonEvent *ev)
|
||||
{
|
||||
client_focus(c);
|
||||
client_raise(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Titlebar */
|
||||
@@ -63,7 +65,10 @@ buttonpress(XButtonEvent *ev)
|
||||
for(i = 0; i < conf.titlebar.button[n].nmouse; ++i)
|
||||
if(ev->button == conf.titlebar.button[n].mouse[i].button)
|
||||
if(conf.titlebar.button[n].mouse[i].func)
|
||||
{
|
||||
client_focus(c);
|
||||
conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd);
|
||||
}
|
||||
|
||||
/* Frame Resize Area */
|
||||
if((c = client_gb_resize(ev->window)))
|
||||
@@ -75,6 +80,7 @@ buttonpress(XButtonEvent *ev)
|
||||
if(ev->button == conf.client.mouse[i].button)
|
||||
if(conf.client.mouse[i].func)
|
||||
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
|
||||
|
||||
/* Root */
|
||||
if(ev->window == ROOT)
|
||||
for(i = 0; i < conf.root.nmouse; ++i)
|
||||
@@ -96,16 +102,36 @@ buttonpress(XButtonEvent *ev)
|
||||
if(conf.bars.mouse[j].func)
|
||||
conf.bars.mouse[j].func(conf.bars.mouse[j].cmd);
|
||||
|
||||
/* Selbar */
|
||||
if(conf.bars.selbar && ev->window == infobar[selscreen].selbar->win)
|
||||
for(i = 0; i < conf.selbar.nmouse; ++i)
|
||||
if(conf.selbar.mouse[i].tag == seltag[conf.selbar.mouse[i].screen]
|
||||
|| conf.selbar.mouse[i].tag < 0)
|
||||
if(ev->button == conf.selbar.mouse[i].button)
|
||||
if(conf.selbar.mouse[i].func)
|
||||
conf.selbar.mouse[i].func(conf.selbar.mouse[i].cmd);
|
||||
|
||||
/* Tags */
|
||||
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
|
||||
if(ev->window == infobar[selscreen].tags[i]->win)
|
||||
switch(ev->button)
|
||||
{
|
||||
case Button1: tag_set(i); break;
|
||||
case Button3: tag_transfert(sel, i); break;
|
||||
case Button4: tag_set(seltag[selscreen] + 1); break;
|
||||
case Button5: tag_set(seltag[selscreen] - 1); break;
|
||||
}
|
||||
{
|
||||
for(j = 0; j < tags[selscreen][i].nmouse; ++j)
|
||||
if(ev->button == tags[selscreen][i].mouse[j].button)
|
||||
if(tags[selscreen][i].mouse[j].func)
|
||||
tags[selscreen][i].mouse[j].func(tags[selscreen][i].mouse[j].cmd);
|
||||
|
||||
/* Mouse button action on tag */
|
||||
if(ev->button == conf.mouse_tag_action[TagSel])
|
||||
tag_set(i);
|
||||
else if(ev->button == conf.mouse_tag_action[TagTransfert])
|
||||
tag_transfert(sel, i);
|
||||
else if(ev->button == conf.mouse_tag_action[TagAdd])
|
||||
tag_additional(selscreen, seltag[selscreen], i);
|
||||
else if(ev->button == conf.mouse_tag_action[TagNext])
|
||||
tag_set(seltag[selscreen] + 1);
|
||||
else if(ev->button == conf.mouse_tag_action[TagPrev])
|
||||
tag_set(seltag[selscreen] - 1);
|
||||
}
|
||||
|
||||
/* Layout button */
|
||||
if(ev->window == infobar[selscreen].layout_button->win && conf.nlayout > 1)
|
||||
@@ -136,11 +162,12 @@ buttonpress(XButtonEvent *ev)
|
||||
/* ClientMessage handle event
|
||||
*\param ev XClientMessageEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
clientmessageevent(XClientMessageEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
int i, mess_t = 0;
|
||||
Systray *sy;
|
||||
int s, i, mess_t = 0;
|
||||
Atom rt;
|
||||
int rf;
|
||||
ulong ir, il;
|
||||
@@ -151,7 +178,9 @@ clientmessageevent(XClientMessageEvent *ev)
|
||||
if(ev->format != 32)
|
||||
return;
|
||||
|
||||
for(i = 0; i < net_last + screen_count(); ++i)
|
||||
s = screen_count();
|
||||
|
||||
for(i = 0; i < net_last + s; ++i)
|
||||
if(net_atom[i] == ev->message_type)
|
||||
mess_t = i;
|
||||
|
||||
@@ -166,13 +195,33 @@ clientmessageevent(XClientMessageEvent *ev)
|
||||
/* Manage _WMFS_SET_SCREEN */
|
||||
if(mess_t == wmfs_set_screen
|
||||
&& ev->data.l[0] >= 0
|
||||
&& ev->data.l[0] <= screen_count())
|
||||
&& ev->data.l[0] <= s)
|
||||
screen_set_sel((int)(ev->data.l[0]));
|
||||
|
||||
/* Manage _NET_ACTIVE_WINDOW */
|
||||
else if(mess_t == net_active_window)
|
||||
{
|
||||
if((c = client_gb_win(ev->window)))
|
||||
client_focus(c);
|
||||
else if((sy = systray_find(ev->data.l[0])))
|
||||
XSetInputFocus(dpy, sy->win, RevertToNone, CurrentTime);
|
||||
}
|
||||
}
|
||||
else if(ev->window == traywin)
|
||||
{
|
||||
/* Manage _NET_WM_SYSTEM_TRAY_OPCODE */
|
||||
if(mess_t == net_wm_system_tray_opcode)
|
||||
{
|
||||
if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
|
||||
{
|
||||
systray_add(ev->data.l[2]);
|
||||
systray_update();
|
||||
}
|
||||
else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
|
||||
if((sy = systray_find(ev->data.l[2])))
|
||||
ewmh_send_message(sy->win, sy->win, "_XEMBED",
|
||||
XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Manage _NET_WM_STATE */
|
||||
@@ -187,7 +236,7 @@ clientmessageevent(XClientMessageEvent *ev)
|
||||
|
||||
/* Manage _NET_WM_DESKTOP */
|
||||
if(mess_t == net_wm_desktop)
|
||||
if((c = client_gb_win(ev->window)))
|
||||
if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF)
|
||||
tag_transfert(c, ev->data.l[0]);
|
||||
|
||||
/* Manage _WMFS_STATUSTEXT_x */
|
||||
@@ -196,7 +245,7 @@ clientmessageevent(XClientMessageEvent *ev)
|
||||
if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096,
|
||||
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
|
||||
{
|
||||
infobar_draw_statustext(mess_t - wmfs_statustext, (char*)ret);
|
||||
statustext_handle(mess_t - wmfs_statustext, (char*)ret);
|
||||
XFree(ret);
|
||||
}
|
||||
}
|
||||
@@ -226,22 +275,21 @@ clientmessageevent(XClientMessageEvent *ev)
|
||||
ewmh_get_client_list();
|
||||
ewmh_get_desktop_names();
|
||||
ewmh_set_desktop_geometry();
|
||||
ewmh_set_workarea();
|
||||
screen_count();
|
||||
screen_get_sel();
|
||||
}
|
||||
|
||||
if(mess_t == wmfs_update_status
|
||||
&& estatus)
|
||||
spawn(status_path);
|
||||
spawn(conf.status_path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** ConfigureRequest & ConfigureNotify handle events
|
||||
* \param ev XEvent pointer
|
||||
/** ConfigureRequesthandle events
|
||||
* \param ev XConfigureRequestEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
configureevent(XConfigureRequestEvent *ev)
|
||||
{
|
||||
XWindowChanges wc;
|
||||
@@ -251,7 +299,6 @@ configureevent(XConfigureRequestEvent *ev)
|
||||
if((c = client_gb_win(ev->window))
|
||||
|| (c = client_gb_win(ev->window)))
|
||||
{
|
||||
CHECK(!(c->flags & TileFlag));
|
||||
CHECK(!(c->flags & LMaxFlag));
|
||||
CHECK(!(c->flags & MaxFlag));
|
||||
CHECK(!(c->flags & FSSFlag));
|
||||
@@ -268,8 +315,13 @@ configureevent(XConfigureRequestEvent *ev)
|
||||
if(ev->value_mask & CWHeight)
|
||||
c->geo.height = ev->height;
|
||||
|
||||
if(c->flags & FreeFlag)
|
||||
if(c->flags & FreeFlag || !(c->flags & (TileFlag | LMaxFlag)))
|
||||
client_moveresize(c, c->geo, False);
|
||||
else
|
||||
{
|
||||
client_configure(c);
|
||||
arrange(c->screen, True);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -290,16 +342,23 @@ configureevent(XConfigureRequestEvent *ev)
|
||||
/** DestroyNotify handle event
|
||||
* \param ev XDestroyWindowEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
destroynotify(XDestroyWindowEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
Systray *s;
|
||||
|
||||
if((c = client_gb_win(ev->window)))
|
||||
{
|
||||
client_unmanage(c);
|
||||
XSetErrorHandler(errorhandler);
|
||||
}
|
||||
else if((s = systray_find(ev->window)))
|
||||
{
|
||||
setwinstate(s->win, WithdrawnState);
|
||||
systray_del(s);
|
||||
systray_update();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -307,7 +366,7 @@ destroynotify(XDestroyWindowEvent *ev)
|
||||
/** EnterNotify handle event
|
||||
* \param ev XCrossingEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
enternotify(XCrossingEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
@@ -318,6 +377,10 @@ enternotify(XCrossingEvent *ev)
|
||||
&& ev->window != ROOT)
|
||||
return;
|
||||
|
||||
/* Don't handle EnterNotify event if it's about systray */
|
||||
if(systray_find(ev->window) || ev->window == traywin)
|
||||
return;
|
||||
|
||||
if(conf.focus_fmouse)
|
||||
{
|
||||
if((c = client_gb_win(ev->window))
|
||||
@@ -336,7 +399,7 @@ enternotify(XCrossingEvent *ev)
|
||||
/** ExposeEvent handle event
|
||||
* \param ev XExposeEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
expose(XExposeEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
@@ -349,6 +412,8 @@ expose(XExposeEvent *ev)
|
||||
barwin_refresh(infobar[sc].bar);
|
||||
if(ev->window == infobar[sc].layout_button->win)
|
||||
barwin_refresh(infobar[sc].layout_button);
|
||||
if(conf.bars.selbar && ev->window == infobar[sc].selbar->win)
|
||||
barwin_refresh(infobar[sc].selbar);
|
||||
for(i = 1; i < conf.ntag[sc] + 1; ++i)
|
||||
if(ev->window == infobar[sc].tags[i]->win)
|
||||
barwin_refresh(infobar[sc].tags[i]);
|
||||
@@ -365,7 +430,7 @@ expose(XExposeEvent *ev)
|
||||
* \param ev XFocusChangeEvent pointer
|
||||
* \return
|
||||
*/
|
||||
void
|
||||
static void
|
||||
focusin(XFocusChangeEvent *ev)
|
||||
{
|
||||
if(sel && ev->window != sel->win)
|
||||
@@ -374,34 +439,13 @@ focusin(XFocusChangeEvent *ev)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Key grabbing function
|
||||
*/
|
||||
void
|
||||
grabkeys(void)
|
||||
{
|
||||
uint i;
|
||||
KeyCode code;
|
||||
|
||||
XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
|
||||
for(i = 0; i < conf.nkeybind; ++i)
|
||||
{
|
||||
code = XKeysymToKeycode(dpy, keys[i].keysym);
|
||||
XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** KeyPress handle event
|
||||
* \param ev XKeyPressedEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
keypress(XKeyPressedEvent *ev)
|
||||
{
|
||||
uint i;
|
||||
int i;
|
||||
KeySym keysym;
|
||||
|
||||
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
||||
@@ -415,31 +459,61 @@ keypress(XKeyPressedEvent *ev)
|
||||
return;
|
||||
}
|
||||
|
||||
/** MapNotify handle event
|
||||
/** MappingNotify handle event
|
||||
* \param ev XMappingEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mappingnotify(XMappingEvent *ev)
|
||||
{
|
||||
XRefreshKeyboardMapping(ev);
|
||||
|
||||
if(ev->request == MappingKeyboard)
|
||||
grabkeys();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** MapNotify handle event
|
||||
* \param ev XMapEvent pointer
|
||||
*/
|
||||
static void
|
||||
mapnotify(XMapEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
Systray *s;
|
||||
|
||||
if(ev->window != ev->event && !ev->send_event)
|
||||
return;
|
||||
|
||||
if((c = client_gb_win(ev->window)))
|
||||
setwinstate(c->win, NormalState);
|
||||
else if((s = systray_find(ev->window)))
|
||||
{
|
||||
setwinstate(s->win, NormalState);
|
||||
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** MapRequest handle event
|
||||
* \param ev XMapRequestEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
maprequest(XMapRequestEvent *ev)
|
||||
{
|
||||
XWindowAttributes at;
|
||||
Client *c;
|
||||
Systray *s;
|
||||
|
||||
CHECK(XGetWindowAttributes(dpy, ev->window, &at));
|
||||
CHECK(!at.override_redirect);
|
||||
|
||||
if(!(c = client_gb_win(ev->window)))
|
||||
if((s = systray_find(ev->window)))
|
||||
{
|
||||
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
|
||||
systray_update();
|
||||
}
|
||||
else if(!client_gb_win(ev->window))
|
||||
client_manage(ev->window, &at, True);
|
||||
|
||||
return;
|
||||
@@ -448,48 +522,91 @@ maprequest(XMapRequestEvent *ev)
|
||||
/** PropertyNotify handle event
|
||||
* \param ev XPropertyEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
propertynotify(XPropertyEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
Systray *s;
|
||||
Window trans;
|
||||
XWMHints *h;
|
||||
|
||||
if(ev->state == PropertyDelete)
|
||||
return;
|
||||
|
||||
if((s = systray_find(ev->window)))
|
||||
{
|
||||
systray_state(s);
|
||||
systray_update();
|
||||
}
|
||||
|
||||
if((c = client_gb_win(ev->window)))
|
||||
{
|
||||
switch(ev->atom)
|
||||
{
|
||||
default: break;
|
||||
case XA_WM_TRANSIENT_FOR:
|
||||
XGetTransientForHint(dpy, c->win, &trans);
|
||||
if((c->flags & TileFlag || c->flags & MaxFlag))
|
||||
if(((c->flags & HintFlag && (client_gb_win(trans) != NULL)))
|
||||
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
|
||||
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
|
||||
arrange(c->screen, True);
|
||||
break;
|
||||
case XA_WM_NORMAL_HINTS:
|
||||
client_size_hints(c);
|
||||
break;
|
||||
case XA_WM_HINTS:
|
||||
if((h = XGetWMHints(dpy, c->win)) && (h->flags & XUrgencyHint) && c != sel)
|
||||
{
|
||||
client_urgent(c, True);
|
||||
XFree(h);
|
||||
}
|
||||
break;
|
||||
case XA_WM_NAME:
|
||||
client_get_name(c);
|
||||
break;
|
||||
default:
|
||||
if(ev->atom == net_atom[net_wm_name])
|
||||
client_get_name(c);
|
||||
break;
|
||||
}
|
||||
if(ev->atom == net_atom[net_wm_name])
|
||||
client_get_name(c);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** XReparentEvent handle event
|
||||
* \param ev XReparentEvent pointer
|
||||
*/
|
||||
static void
|
||||
reparentnotify(XReparentEvent *ev)
|
||||
{
|
||||
(void)ev;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** SelectionClearEvent handle event
|
||||
* \param ev XSelectionClearEvent pointer
|
||||
*/
|
||||
static void
|
||||
selectionclearevent(XSelectionClearEvent *ev)
|
||||
{
|
||||
/* Getting selection if lost it */
|
||||
if(ev->window == traywin)
|
||||
systray_acquire();
|
||||
|
||||
systray_update();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** UnmapNotify handle event
|
||||
* \param ev XUnmapEvent pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
unmapnotify(XUnmapEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
Systray *s;
|
||||
|
||||
if((c = client_gb_win(ev->window))
|
||||
&& ev->send_event
|
||||
@@ -499,31 +616,50 @@ unmapnotify(XUnmapEvent *ev)
|
||||
XSetErrorHandler(errorhandler);
|
||||
}
|
||||
|
||||
if((s = systray_find(ev->window)))
|
||||
{
|
||||
systray_del(s);
|
||||
systray_update();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Send a client event
|
||||
*\param data Event data
|
||||
*\param atom_name Event atom name
|
||||
/** XMotionNotify handle event
|
||||
* \param ev XMotionEvent pointer
|
||||
*/
|
||||
void
|
||||
send_client_event(long data[5], char *atom_name)
|
||||
static void
|
||||
motionnotify(XMotionEvent *ev)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
if(!conf.focus_fmouse || !conf.focus_fmov)
|
||||
return;
|
||||
|
||||
if((c = client_gb_win(ev->subwindow)))
|
||||
if (c != sel)
|
||||
client_focus(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Key grabbing function
|
||||
*/
|
||||
void
|
||||
grabkeys(void)
|
||||
{
|
||||
XEvent ev;
|
||||
int i;
|
||||
KeyCode code;
|
||||
|
||||
ev.xclient.type = ClientMessage;
|
||||
ev.xclient.serial = 0;
|
||||
ev.xclient.send_event = True;
|
||||
ev.xclient.message_type = ATOM(atom_name);
|
||||
ev.xclient.window = ROOT;
|
||||
ev.xclient.format = 32;
|
||||
|
||||
for(i = 0; i < 5; ++i, ev.xclient.data.l[i] = data[i]);
|
||||
|
||||
XSendEvent(dpy, ROOT, False, SubstructureRedirectMask | SubstructureNotifyMask, &ev);
|
||||
XSync(dpy, False);
|
||||
|
||||
XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
|
||||
for(i = 0; i < conf.nkeybind; ++i)
|
||||
if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
|
||||
{
|
||||
XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -538,18 +674,22 @@ getevent(XEvent ev)
|
||||
|
||||
switch(ev.type)
|
||||
{
|
||||
case ButtonPress: buttonpress(&ev.xbutton); break;
|
||||
case ClientMessage: clientmessageevent(&ev.xclient); break;
|
||||
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break;
|
||||
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
|
||||
case EnterNotify: enternotify(&ev.xcrossing); break;
|
||||
case Expose: expose(&ev.xexpose); break;
|
||||
case FocusIn: focusin(&ev.xfocus); break;
|
||||
case KeyPress: keypress(&ev.xkey); break;
|
||||
case MapRequest: maprequest(&ev.xmaprequest); break;
|
||||
case MappingNotify: mappingnotify(&ev.xmapping); break;
|
||||
case PropertyNotify: propertynotify(&ev.xproperty); break;
|
||||
case UnmapNotify: unmapnotify(&ev.xunmap); break;
|
||||
case ButtonPress: buttonpress(&ev.xbutton); break;
|
||||
case ClientMessage: clientmessageevent(&ev.xclient); break;
|
||||
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break;
|
||||
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
|
||||
case EnterNotify: enternotify(&ev.xcrossing); break;
|
||||
case Expose: expose(&ev.xexpose); break;
|
||||
case FocusIn: focusin(&ev.xfocus); break;
|
||||
case KeyPress: keypress(&ev.xkey); break;
|
||||
case MapNotify: mapnotify(&ev.xmap); break;
|
||||
case MapRequest: maprequest(&ev.xmaprequest); break;
|
||||
case MappingNotify: mappingnotify(&ev.xmapping); break;
|
||||
case MotionNotify: motionnotify(&ev.xmotion); break;
|
||||
case PropertyNotify: propertynotify(&ev.xproperty); break;
|
||||
case ReparentNotify: reparentnotify(&ev.xreparent); break;
|
||||
case SelectionClear: selectionclearevent(&ev.xselectionclear); break;
|
||||
case UnmapNotify: unmapnotify(&ev.xunmap); break;
|
||||
default:
|
||||
|
||||
#ifdef HAVE_XRANDR
|
||||
@@ -562,13 +702,11 @@ getevent(XEvent ev)
|
||||
/* Reload WMFS to update the screen(s) geometry changement */
|
||||
quit();
|
||||
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
|
||||
execlp(argv_global, argv_global, NULL);
|
||||
execvp(argv_global, all_argv);
|
||||
}
|
||||
#endif /* HAVE_XRANDR */
|
||||
break;
|
||||
}
|
||||
|
||||
wait((int[]){0});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
168
src/ewmh.c
168
src/ewmh.c
@@ -42,12 +42,15 @@
|
||||
void
|
||||
ewmh_init_hints(void)
|
||||
{
|
||||
int i = 1, j, showing_desk = 0;
|
||||
int i = 1, s, j, showing_desk = 0;
|
||||
char root_name[] = WMFS_VERSION;
|
||||
char class[] = "wmfs", st[64];
|
||||
long pid = (long)getpid();
|
||||
char systray_atom[48];
|
||||
|
||||
net_atom = emalloc(net_last + screen_count(), sizeof(Atom));
|
||||
|
||||
s = screen_count();
|
||||
net_atom = xcalloc(net_last + s, sizeof(Atom));
|
||||
|
||||
/* EWMH hints */
|
||||
net_atom[net_supported] = ATOM("_NET_SUPPORTED");
|
||||
@@ -57,7 +60,6 @@ ewmh_init_hints(void)
|
||||
net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
|
||||
net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
|
||||
net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY");
|
||||
net_atom[net_workarea] = ATOM("_NET_WORKAREA");
|
||||
net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
|
||||
net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
|
||||
net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
|
||||
@@ -67,6 +69,7 @@ ewmh_init_hints(void)
|
||||
net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
|
||||
net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
|
||||
net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
|
||||
net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
|
||||
net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
|
||||
net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
|
||||
net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
|
||||
@@ -74,7 +77,19 @@ ewmh_init_hints(void)
|
||||
net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
|
||||
net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
|
||||
net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
|
||||
net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
|
||||
net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
|
||||
net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
|
||||
net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
|
||||
net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
|
||||
|
||||
snprintf(systray_atom, sizeof(systray_atom), "_NET_SYSTEM_TRAY_S%d", 0/*SCREEN*/);
|
||||
net_atom[net_system_tray_s] = ATOM(systray_atom);
|
||||
|
||||
net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
|
||||
net_atom[xembed] = ATOM("_XEMBED");
|
||||
net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
|
||||
net_atom[manager] = ATOM("MANAGER");
|
||||
net_atom[utf8_string] = ATOM("UTF8_STRING");
|
||||
|
||||
/* WMFS hints */
|
||||
@@ -91,16 +106,17 @@ ewmh_init_hints(void)
|
||||
net_atom[wmfs_nmaster] = ATOM("_WMFS_NMASTER");
|
||||
net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
|
||||
net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
|
||||
net_atom[wmfs_font] = ATOM("_WMFS_FONT");
|
||||
|
||||
/* Multi atom _WMFS_STATUSTEXT_<screennum> */
|
||||
for(j = 0; j < screen_count(); ++j)
|
||||
for(j = 0; j < s; ++j)
|
||||
{
|
||||
sprintf(st, "_WMFS_STATUSTEXT_%d", j);
|
||||
net_atom[wmfs_statustext + j] = ATOM(st);
|
||||
}
|
||||
|
||||
XChangeProperty(dpy, ROOT, net_atom[net_supported], XA_ATOM, 32,
|
||||
PropModeReplace, (uchar*)net_atom, net_last + screen_count());
|
||||
PropModeReplace, (uchar*)net_atom, net_last + s);
|
||||
|
||||
XChangeProperty(dpy, ROOT, net_atom[wmfs_running], XA_CARDINAL, 32,
|
||||
PropModeReplace, (uchar*)&i, 1);
|
||||
@@ -126,6 +142,54 @@ ewmh_init_hints(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Send ewmh message
|
||||
*/
|
||||
void
|
||||
ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4)
|
||||
{
|
||||
|
||||
XClientMessageEvent e;
|
||||
|
||||
e.type = ClientMessage;
|
||||
e.message_type = ATOM(atom);
|
||||
e.window = w;
|
||||
e.format = 32;
|
||||
e.data.l[0] = d0;
|
||||
e.data.l[1] = d1;
|
||||
e.data.l[2] = d2;
|
||||
e.data.l[3] = d3;
|
||||
e.data.l[4] = d4;
|
||||
|
||||
XSendEvent(dpy, d, False, StructureNotifyMask, (XEvent*)&e);
|
||||
XSync(dpy, False);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get xembed state
|
||||
*/
|
||||
long
|
||||
ewmh_get_xembed_state(Window win)
|
||||
{
|
||||
Atom rf;
|
||||
int f;
|
||||
ulong n, il;
|
||||
long ret = 0;
|
||||
uchar *data = NULL;
|
||||
|
||||
if(XGetWindowProperty(dpy, win, net_atom[xembedinfo], 0L, 2, False,
|
||||
net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
|
||||
return 0;
|
||||
|
||||
if(rf == net_atom[xembedinfo] && n == 2)
|
||||
ret = (long)data[1];
|
||||
|
||||
if(n && data)
|
||||
XFree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Get the number of desktop (tag)
|
||||
*/
|
||||
void
|
||||
@@ -148,13 +212,11 @@ void
|
||||
ewmh_update_current_tag_prop(void)
|
||||
{
|
||||
int t;
|
||||
char *s = NULL;
|
||||
char s[8] = { 0 };
|
||||
|
||||
screen_get_sel();
|
||||
t = seltag[selscreen] - 1;
|
||||
|
||||
s = emalloc(8, sizeof(char));
|
||||
|
||||
/* Get current desktop (tag) */
|
||||
XChangeProperty(dpy, ROOT, net_atom[net_current_desktop], XA_CARDINAL, 32,
|
||||
PropModeReplace, (uchar*)&t, 1);
|
||||
@@ -179,8 +241,6 @@ ewmh_update_current_tag_prop(void)
|
||||
PropModeReplace, (uchar*)tags[selscreen][seltag[selscreen]].layout.symbol,
|
||||
strlen(tags[selscreen][seltag[selscreen]].layout.symbol));
|
||||
|
||||
free(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -194,7 +254,7 @@ ewmh_get_client_list(void)
|
||||
int win_n;
|
||||
|
||||
for(win_n = 0, c = clients; c; c = c->next, ++win_n);
|
||||
list = emalloc(win_n, sizeof(Window));
|
||||
list = xcalloc(win_n, sizeof(Window));
|
||||
|
||||
for(win_n = 0, c = clients; c; c = c->next, ++win_n)
|
||||
list[win_n] = c->win;
|
||||
@@ -202,7 +262,7 @@ ewmh_get_client_list(void)
|
||||
XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32,
|
||||
PropModeReplace, (uchar *)list, win_n);
|
||||
|
||||
free(list);
|
||||
XFree(list);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -213,15 +273,17 @@ void
|
||||
ewmh_get_desktop_names(void)
|
||||
{
|
||||
char *str = NULL;
|
||||
int s, i, len = 0, pos = 0;
|
||||
int S, s, i = 0, len = 0, pos = 0;
|
||||
|
||||
for(s = 0 ; s < screen_count(); ++s)
|
||||
S = screen_count();
|
||||
|
||||
for(s = 0 ; s < S; ++s)
|
||||
for(i = 1; i < conf.ntag[s] + 1; ++i)
|
||||
len += strlen(tags[s][i].name);
|
||||
|
||||
str = emalloc(len + i + 1, sizeof(char*));
|
||||
str = xcalloc(len + i + 1, sizeof(char*));
|
||||
|
||||
for(s = 0; s < screen_count(); ++s)
|
||||
for(s = 0; s < S; ++s)
|
||||
for(i = 1; i < conf.ntag[s] + 1; ++i, ++pos)
|
||||
{
|
||||
strncpy(str + pos, tags[s][i].name, strlen(tags[s][i].name));
|
||||
@@ -258,54 +320,25 @@ ewmh_set_desktop_geometry(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Manage _NET_WORKAREA
|
||||
*/
|
||||
void
|
||||
ewmh_set_workarea(void)
|
||||
{
|
||||
long *data;
|
||||
int i, j, tag_c = 0, pos = 0;
|
||||
|
||||
for(i = 0; i < screen_count(); ++i)
|
||||
tag_c += conf.ntag[i];
|
||||
|
||||
data = emalloc(tag_c * 4, sizeof(long));
|
||||
|
||||
for(i = 0; i < screen_count(); ++i)
|
||||
for(j = 0; j < conf.ntag[i]; ++j)
|
||||
{
|
||||
data[pos++] = spgeo[i].x;
|
||||
data[pos++] = spgeo[i].y;
|
||||
data[pos++] = spgeo[i].width;
|
||||
data[pos++] = spgeo[i].height;
|
||||
}
|
||||
|
||||
XChangeProperty(dpy, ROOT, net_atom[net_workarea], XA_CARDINAL, 32,
|
||||
PropModeReplace, (uchar*)data, 4 * tag_c);
|
||||
|
||||
free(data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Manage _NET_WM_STATE_* ewmh
|
||||
*/
|
||||
void
|
||||
ewmh_manage_net_wm_state(long data_l[], Client *c)
|
||||
{
|
||||
/* Manage _NET_WM_STATE_FULLSCREEN */
|
||||
if(data_l[1] == net_atom[net_wm_state_fullscreen])
|
||||
if(data_l[1] == (long)net_atom[net_wm_state_fullscreen])
|
||||
{
|
||||
if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag))
|
||||
{
|
||||
c->screen = screen_get_with_geo(c->geo.x, c->geo.y);
|
||||
client_unmap(c);
|
||||
c->flags &= ~UnmapFlag;
|
||||
XMapWindow(dpy, c->win);
|
||||
XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y);
|
||||
XResizeWindow(dpy, c->win,
|
||||
spgeo[c->screen].width,
|
||||
spgeo[c->screen].height);
|
||||
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32,
|
||||
PropModeReplace, (uchar *)&net_atom[net_wm_state_fullscreen], 1);
|
||||
|
||||
c->tmp_geo = c->geo;
|
||||
|
||||
@@ -316,20 +349,29 @@ ewmh_manage_net_wm_state(long data_l[], Client *c)
|
||||
|
||||
client_raise(c);
|
||||
client_focus(c);
|
||||
XUnmapWindow(dpy, c->frame);
|
||||
}
|
||||
else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag))
|
||||
{
|
||||
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)0, 0);
|
||||
c->flags &= ~(FSSFlag | MaxFlag);
|
||||
client_map(c);
|
||||
XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH);
|
||||
client_moveresize(c, c->tmp_geo, False);
|
||||
}
|
||||
}
|
||||
/* Manage _NET_WM_STATE_STICKY */
|
||||
else if(data_l[1] == (long)net_atom[net_wm_state_sticky])
|
||||
{
|
||||
/* == client_ignore_tag */
|
||||
c->tag = MAXTAG + 1;
|
||||
arrange(c->screen, True);
|
||||
}
|
||||
/* Manage _NET_WM_STATE_DEMANDS_ATTENTION */
|
||||
else if(data_l[1] == net_atom[net_wm_state_demands_attention])
|
||||
else if(data_l[1] == (long)net_atom[net_wm_state_demands_attention])
|
||||
{
|
||||
if(data_l[0] == _NET_WM_STATE_ADD)
|
||||
client_focus(c);
|
||||
client_urgent(c, True);
|
||||
if(data_l[0] == _NET_WM_STATE_REMOVE)
|
||||
if(c == sel)
|
||||
client_focus(NULL);
|
||||
@@ -346,9 +388,10 @@ void
|
||||
ewmh_manage_window_type(Client *c)
|
||||
{
|
||||
Atom *atom, rf;
|
||||
int i, f;
|
||||
ulong n, il;
|
||||
int f;
|
||||
ulong n, il, i;
|
||||
uchar *data = NULL;
|
||||
long ldata[5] = { 0 };
|
||||
|
||||
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL,
|
||||
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
|
||||
@@ -371,16 +414,14 @@ ewmh_manage_window_type(Client *c)
|
||||
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
|
||||
XRaiseWindow(dpy, c->win);
|
||||
|
||||
/* This window will not be managed anymore,
|
||||
* so let's detach it. */
|
||||
client_detach(c);
|
||||
c->flags |= DockFlag;
|
||||
}
|
||||
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
|
||||
else if(atom[i] == net_atom[net_wm_window_type_dialog])
|
||||
{
|
||||
c->flags |= FreeFlag;
|
||||
c->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
|
||||
client_moveresize(sel, sel->ogeo, True);
|
||||
client_moveresize(c, c->ogeo, True);
|
||||
client_focus(c);
|
||||
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
|
||||
}
|
||||
@@ -388,6 +429,21 @@ ewmh_manage_window_type(Client *c)
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
/* Get NET_WM_STATE set without sending client message event */
|
||||
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_state], 0L, 0x7FFFFFFFL,
|
||||
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
|
||||
{
|
||||
atom = (Atom*)data;
|
||||
|
||||
for(i = 0; i < n; ++i)
|
||||
{
|
||||
ldata[0] = _NET_WM_STATE_ADD;
|
||||
ldata[1] = atom[i];
|
||||
ewmh_manage_net_wm_state(ldata, c);
|
||||
}
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
85
src/frame.c
85
src/frame.c
@@ -83,7 +83,7 @@ frame_create(Client *c)
|
||||
/* Buttons */
|
||||
if(BUTTONWH >= 1)
|
||||
{
|
||||
c->button = emalloc(conf.titlebar.nbutton, sizeof(Window));
|
||||
c->button = xcalloc(conf.titlebar.nbutton, sizeof(Window));
|
||||
for(i = 0; i < conf.titlebar.nbutton; ++i)
|
||||
{
|
||||
CWIN(c->button[i], c->titlebar->win,
|
||||
@@ -118,10 +118,13 @@ frame_create(Client *c)
|
||||
/* Border (for shadow) */
|
||||
if(conf.client.border_shadow)
|
||||
{
|
||||
CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, color_enlight(c->colors.frame), &at);
|
||||
CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, color_enlight(c->colors.frame), &at);
|
||||
CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, SHADC, &at);
|
||||
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at);
|
||||
c->colors.borddark = color_shade(c->colors.frame, conf.colors.client_dark_shade);
|
||||
c->colors.bordlight = color_shade(c->colors.frame, conf.colors.client_light_shade);
|
||||
|
||||
CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, c->colors.bordlight, &at);
|
||||
CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, c->colors.bordlight, &at);
|
||||
CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, c->colors.borddark, &at);
|
||||
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, c->colors.borddark, &at);
|
||||
}
|
||||
|
||||
/* Reparent window with the frame */
|
||||
@@ -191,6 +194,44 @@ frame_moveresize(Client *c, XRectangle geo)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Update frame colors for focus event
|
||||
*\param c Client pointer
|
||||
*/
|
||||
void
|
||||
frame_update_color(Client *c, Bool focused)
|
||||
{
|
||||
CHECK(c);
|
||||
|
||||
/* Not focused client */
|
||||
if(focused)
|
||||
{
|
||||
c->colors.frame = conf.client.bordernormal;
|
||||
c->colors.fg = conf.titlebar.fg_normal;
|
||||
c->colors.resizecorner = conf.client.resizecorner_normal;
|
||||
|
||||
if(TBARH - BORDH && c->titlebar->stipple)
|
||||
c->titlebar->stipple_color = conf.titlebar.stipple.colors.normal;
|
||||
}
|
||||
/* Focused */
|
||||
else
|
||||
{
|
||||
c->colors.frame = conf.client.borderfocus;
|
||||
c->colors.fg = conf.titlebar.fg_focus;
|
||||
c->colors.resizecorner = conf.client.resizecorner_focus;
|
||||
|
||||
if(TBARH - BORDH && c->titlebar->stipple)
|
||||
c->titlebar->stipple_color = conf.titlebar.stipple.colors.focus;
|
||||
}
|
||||
|
||||
if(conf.client.border_shadow)
|
||||
{
|
||||
c->colors.borddark = color_shade(c->colors.frame, conf.colors.client_dark_shade);
|
||||
c->colors.bordlight = color_shade(c->colors.frame, conf.colors.client_light_shade);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Update the client frame; Set the new color
|
||||
* and the title --> refresh
|
||||
* \param c Client pointer
|
||||
@@ -220,16 +261,28 @@ frame_update(Client *c)
|
||||
{
|
||||
XSetWindowBackground(dpy, c->button[i], c->colors.frame);
|
||||
XClearWindow(dpy, c->button[i]);
|
||||
XSetWindowBorder(dpy, c->button[i], getcolor(c->colors.fg));
|
||||
|
||||
/* Button's lines */
|
||||
if(conf.titlebar.button[i].nlines)
|
||||
if((!conf.titlebar.button[i].flags)
|
||||
|| ((conf.titlebar.button[i].flags & FreeFlag)
|
||||
&& ((c->flags & FreeFlag) || !(c->flags & (TileFlag | LMaxFlag))))
|
||||
|| ((conf.titlebar.button[i].flags & MaxFlag)
|
||||
&& ((c->flags & MaxFlag) || (c->flags & LMaxFlag)))
|
||||
|| ((conf.titlebar.button[i].flags & TileFlag) && (c->flags & TileFlag)))
|
||||
{
|
||||
XSetForeground(dpy, gc, getcolor(c->colors.fg));
|
||||
XDrawSegments(dpy, c->button[i], gc,
|
||||
conf.titlebar.button[i].linecoord,
|
||||
conf.titlebar.button[i].nlines);
|
||||
|
||||
XSetWindowBorder(dpy, c->button[i], getcolor(c->colors.fg));
|
||||
|
||||
/* Button's lines */
|
||||
if(conf.titlebar.button[i].nlines)
|
||||
{
|
||||
XSetForeground(dpy, gc, getcolor(c->colors.fg));
|
||||
XDrawSegments(dpy, c->button[i], gc,
|
||||
conf.titlebar.button[i].linecoord,
|
||||
conf.titlebar.button[i].nlines);
|
||||
}
|
||||
}
|
||||
else
|
||||
XSetWindowBorder(dpy, c->button[i], c->colors.frame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,10 +299,10 @@ frame_update(Client *c)
|
||||
|
||||
if(conf.client.border_shadow)
|
||||
{
|
||||
XSetWindowBackground(dpy, c->left, color_enlight(c->colors.frame));
|
||||
XSetWindowBackground(dpy, c->top, color_enlight(c->colors.frame));
|
||||
XSetWindowBackground(dpy, c->right, SHADC);
|
||||
XSetWindowBackground(dpy, c->bottom, SHADC);
|
||||
XSetWindowBackground(dpy, c->left, c->colors.bordlight);
|
||||
XSetWindowBackground(dpy, c->top, c->colors.bordlight);
|
||||
XSetWindowBackground(dpy, c->right, c->colors.borddark);
|
||||
XSetWindowBackground(dpy, c->bottom, c->colors.borddark);
|
||||
|
||||
XClearWindow(dpy, c->left);
|
||||
XClearWindow(dpy, c->top);
|
||||
|
||||
@@ -42,7 +42,7 @@ uchar *ret;
|
||||
|
||||
/** Get information about tag (current, list, names)
|
||||
*/
|
||||
void
|
||||
static void
|
||||
getinfo_tag(void)
|
||||
{
|
||||
int tag = 0;
|
||||
@@ -60,29 +60,29 @@ getinfo_tag(void)
|
||||
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_CURRENT_TAG"), 0L, 4096,
|
||||
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
tag_name = _strdup((char*)ret);
|
||||
tag_name = xstrdup((char*)ret);
|
||||
XFree(ret);
|
||||
}
|
||||
|
||||
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_TAG_LIST"), 0L, 4096,
|
||||
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
tag_list = _strdup((char*)ret);
|
||||
tag_list = xstrdup((char*)ret);
|
||||
XFree(ret);
|
||||
}
|
||||
|
||||
printf("Current tag: %d - %s\n", tag, tag_name);
|
||||
printf("Tag list: %s\n", tag_list);
|
||||
|
||||
IFREE(tag_name);
|
||||
IFREE(tag_list);
|
||||
free(tag_name);
|
||||
free(tag_list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get information about screens
|
||||
*/
|
||||
void
|
||||
static void
|
||||
getinfo_screen(void)
|
||||
{
|
||||
int screen = 1;
|
||||
@@ -108,7 +108,7 @@ getinfo_screen(void)
|
||||
|
||||
/** Get current layout name
|
||||
*/
|
||||
void
|
||||
static void
|
||||
getinfo_layout(void)
|
||||
{
|
||||
char *layout = NULL;
|
||||
@@ -116,20 +116,20 @@ getinfo_layout(void)
|
||||
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_CURRENT_LAYOUT"), 0L, 4096,
|
||||
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
layout = _strdup((char*)ret);
|
||||
layout = xstrdup((char*)ret);
|
||||
XFree(ret);
|
||||
}
|
||||
|
||||
printf("Current layout: %s\n", layout);
|
||||
|
||||
IFREE(layout);
|
||||
free(layout);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get information about current mwfact
|
||||
*/
|
||||
void
|
||||
static void
|
||||
getinfo_mwfact(void)
|
||||
{
|
||||
char *mwfact = NULL;
|
||||
@@ -137,20 +137,20 @@ getinfo_mwfact(void)
|
||||
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_MWFACT"), 0L, 4096,
|
||||
False, XA_STRING, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
mwfact = _strdup((char*)ret);
|
||||
mwfact = xstrdup((char*)ret);
|
||||
XFree(ret);
|
||||
}
|
||||
|
||||
printf("Current mwfact: %s\n", mwfact);
|
||||
|
||||
IFREE(mwfact);
|
||||
free(mwfact);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Get information about current nmaster
|
||||
*/
|
||||
void
|
||||
static void
|
||||
getinfo_nmaster(void)
|
||||
{
|
||||
int nmaster = 1;
|
||||
@@ -173,14 +173,10 @@ getinfo_nmaster(void)
|
||||
void
|
||||
getinfo(char *info)
|
||||
{
|
||||
long data[5];
|
||||
|
||||
if(!check_wmfs_running())
|
||||
return;
|
||||
|
||||
data[4] = True;
|
||||
|
||||
send_client_event(data, "_WMFS_UPDATE_HINTS");
|
||||
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_HINTS", 0, 0, 0, 0, True);
|
||||
|
||||
if(!strcmp(info, "tag"))
|
||||
getinfo_tag();
|
||||
|
||||
338
src/infobar.c
338
src/infobar.c
@@ -37,12 +37,14 @@
|
||||
void
|
||||
infobar_init(void)
|
||||
{
|
||||
int sc, i, j;
|
||||
int s, sc, i, j = 0;
|
||||
|
||||
s = screen_count();
|
||||
|
||||
if(!infobar)
|
||||
infobar = emalloc(screen_count(), sizeof(InfoBar));
|
||||
infobar = xcalloc(s, sizeof(InfoBar));
|
||||
|
||||
for(sc = 0; sc < screen_count(); ++sc)
|
||||
for(sc = 0; sc < s; ++sc)
|
||||
{
|
||||
j = 0;
|
||||
infobar[sc].geo.height = INFOBARH;
|
||||
@@ -70,41 +72,87 @@ infobar_init(void)
|
||||
sgeo[sc].width, infobar[sc].geo.height,
|
||||
conf.colors.bar, conf.colors.text, False, False, conf.border.bar);
|
||||
|
||||
infobar[sc].tags_board = barwin_create(infobar[sc].bar->win,
|
||||
((conf.layout_placement) ? textw(tags[sc][seltag[sc]].layout.symbol) + PAD * 1.5: 0), 0,
|
||||
textw(tags[sc][0].name) + PAD, /* Base size, will change */
|
||||
infobar[sc].geo.height,
|
||||
conf.colors.bar, conf.colors.text, False, False, False);
|
||||
|
||||
/* Create tags window */
|
||||
for(i = 1; i < conf.ntag[sc] + 1; ++i)
|
||||
{
|
||||
infobar[sc].tags[i] = barwin_create(infobar[sc].bar->win, j, 0,
|
||||
infobar[sc].tags[i] = barwin_create(infobar[sc].tags_board->win, j, 0,
|
||||
textw(tags[sc][i].name) + PAD,
|
||||
infobar[sc].geo.height,
|
||||
conf.colors.bar, conf.colors.text, False, False, conf.border.tag);
|
||||
|
||||
j += textw(tags[sc][i].name) + PAD;
|
||||
|
||||
barwin_resize(infobar[sc].tags_board, j, infobar[sc].geo.height);
|
||||
barwin_map_subwin(infobar[sc].tags[i]);
|
||||
}
|
||||
|
||||
/* Create layout switch barwindow */
|
||||
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, j + PAD / 2, 0,
|
||||
textw(tags[sc][seltag[sc]].layout.symbol) + PAD,
|
||||
infobar[sc].geo.height,
|
||||
conf.colors.layout_bg, conf.colors.layout_fg,
|
||||
False, False, conf.border.layout);
|
||||
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win,
|
||||
((conf.layout_placement) ? 0 : (j + PAD / 2)), 0,
|
||||
((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)),
|
||||
infobar[sc].geo.height,
|
||||
conf.colors.layout_bg, conf.colors.layout_fg,
|
||||
False, False, conf.border.layout);
|
||||
|
||||
/* Selbar */
|
||||
if(conf.bars.selbar)
|
||||
infobar[sc].selbar = barwin_create(infobar[sc].bar->win,
|
||||
((conf.layout_placement)
|
||||
? (j + PAD / 2)
|
||||
: infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + PAD / 2), 1,
|
||||
(sel) ? textw(sel->title) + PAD : 1,
|
||||
infobar[sc].geo.height - 2,
|
||||
conf.selbar.bg, conf.selbar.fg, False, False, False);
|
||||
|
||||
/* Map/Refresh all */
|
||||
barwin_map(infobar[sc].bar);
|
||||
barwin_map_subwin(infobar[sc].bar);
|
||||
|
||||
barwin_map(infobar[sc].tags_board);
|
||||
barwin_map_subwin(infobar[sc].tags_board);
|
||||
|
||||
if(conf.border.layout)
|
||||
barwin_map_subwin(infobar[sc].layout_button);
|
||||
|
||||
if(conf.bars.selbar)
|
||||
barwin_map(infobar[sc].selbar);
|
||||
|
||||
barwin_refresh_color(infobar[sc].bar);
|
||||
barwin_refresh(infobar[sc].bar);
|
||||
|
||||
/* Default statustext is set here */
|
||||
for(i = 0; i < screen_count(); ++i)
|
||||
infobar[i].statustext = _strdup(WMFS_VERSION);
|
||||
infobar[sc].statustext = xstrdup(WMFS_VERSION);
|
||||
|
||||
infobar_draw(sc);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw the layout button in the InfoBar
|
||||
*\param sc Screen number
|
||||
*/
|
||||
static void
|
||||
infobar_draw_layout(int sc)
|
||||
{
|
||||
if(!conf.layout_placement)
|
||||
barwin_move(infobar[sc].layout_button, infobar[sc].tags_board->geo.width + PAD / 2, 0);
|
||||
|
||||
barwin_resize(infobar[sc].layout_button, ((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)), infobar[sc].geo.height);
|
||||
barwin_refresh_color(infobar[sc].layout_button);
|
||||
|
||||
if(tags[sc][seltag[sc]].layout.symbol)
|
||||
barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw the Infobar
|
||||
*\param sc Screen number
|
||||
*/
|
||||
@@ -113,22 +161,55 @@ infobar_draw(int sc)
|
||||
{
|
||||
infobar_draw_taglist(sc);
|
||||
infobar_draw_layout(sc);
|
||||
infobar_draw_selbar(sc);
|
||||
barwin_refresh_color(infobar[sc].bar);
|
||||
infobar_draw_statustext(sc, infobar[sc].statustext);
|
||||
statustext_handle(sc, infobar[sc].statustext);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw the layout button in the InfoBar
|
||||
*\param sc Screen number
|
||||
/** Draw Selbar (selected client title bar in infobar
|
||||
*\param sc Screen Number
|
||||
*/
|
||||
void
|
||||
infobar_draw_layout(int sc)
|
||||
infobar_draw_selbar(int sc)
|
||||
{
|
||||
barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height);
|
||||
barwin_refresh_color(infobar[sc].layout_button);
|
||||
if(tags[sc][seltag[sc]].layout.symbol)
|
||||
barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
|
||||
char *str = NULL;
|
||||
|
||||
if(!conf.bars.selbar)
|
||||
return;
|
||||
|
||||
if(!sel || (sel && sel->screen != sc))
|
||||
{
|
||||
barwin_unmap(infobar[sc].selbar);
|
||||
|
||||
return;
|
||||
}
|
||||
else if(sel && !infobar[sc].selbar->mapped)
|
||||
barwin_map(infobar[sc].selbar);
|
||||
|
||||
if(conf.selbar.maxlength >= 0 && sel)
|
||||
{
|
||||
str = xcalloc(conf.selbar.maxlength + 4, sizeof(char));
|
||||
strncpy(str, sel->title, conf.selbar.maxlength);
|
||||
|
||||
if(strlen(sel->title) > (size_t)conf.selbar.maxlength)
|
||||
strcat(str, "...");
|
||||
}
|
||||
|
||||
barwin_resize(infobar[sc].selbar, textw(str ? str : sel->title) + PAD, infobar[sc].geo.height - 2);
|
||||
|
||||
barwin_move(infobar[sc].selbar,
|
||||
((conf.layout_placement)
|
||||
? (infobar[sc].tags_board->geo.x + infobar[sc].tags_board->geo.width + PAD / 2)
|
||||
: (infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + PAD / 2)), 1);
|
||||
|
||||
barwin_refresh_color(infobar[sc].selbar);
|
||||
barwin_draw_text(infobar[sc].selbar, PAD / 2, FHINFOBAR - 1, ((str) ? str : sel->title));
|
||||
|
||||
barwin_refresh(infobar[sc].selbar);
|
||||
|
||||
free(str);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -139,24 +220,61 @@ infobar_draw_layout(int sc)
|
||||
void
|
||||
infobar_draw_taglist(int sc)
|
||||
{
|
||||
int i;
|
||||
Client *c;
|
||||
int i, x;
|
||||
Client *c = NULL;
|
||||
Bool is_occupied[MAXTAG + 1];
|
||||
|
||||
for(i = 1; i < conf.ntag[sc] + 1; ++i)
|
||||
if(conf.layout_placement)
|
||||
barwin_move(infobar[sc].tags_board, ((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)) + PAD / 2, 0);
|
||||
|
||||
for(i = 0; i < MAXTAG; i++)
|
||||
is_occupied[i] = False;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->screen == sc && c->tag != MAXTAG + 1)
|
||||
is_occupied[c->tag] = True;
|
||||
|
||||
for(i = 1, x = 0; i < conf.ntag[sc] + 1; ++i)
|
||||
{
|
||||
infobar[sc].tags[i]->bg = ((i == seltag[sc]) ? conf.colors.tagselbg : conf.colors.bar);
|
||||
infobar[sc].tags[i]->fg = ((i == seltag[sc]) ? conf.colors.tagselfg : conf.colors.text);
|
||||
/* Autohide tag feature */
|
||||
if(conf.tagautohide)
|
||||
{
|
||||
if(!is_occupied[i] && i != seltag[sc])
|
||||
{
|
||||
barwin_unmap(infobar[sc].tags[i]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!infobar[sc].tags[i]->mapped)
|
||||
barwin_map(infobar[sc].tags[i]);
|
||||
|
||||
barwin_move(infobar[sc].tags[i], x, 0);
|
||||
|
||||
x += infobar[sc].tags[i]->geo.width;
|
||||
|
||||
barwin_resize(infobar[sc].tags_board, x, infobar[sc].geo.height);
|
||||
}
|
||||
|
||||
infobar[sc].tags[i]->bg = tags[sc][i].urgent
|
||||
? conf.colors.tagurbg
|
||||
: ((i == seltag[sc] || tags[sc][seltag[sc]].tagad & TagFlag(i))
|
||||
? conf.colors.tagselbg
|
||||
: (is_occupied[i]
|
||||
? conf.colors.tag_occupied_bg
|
||||
: conf.colors.bar));
|
||||
|
||||
infobar[sc].tags[i]->fg = tags[sc][i].urgent
|
||||
? conf.colors.tagurfg
|
||||
: ((i == seltag[sc] || tags[sc][seltag[sc]].tagad & TagFlag(i))
|
||||
? conf.colors.tagselfg
|
||||
: (is_occupied[i]
|
||||
? conf.colors.tag_occupied_fg
|
||||
: conf.colors.text));
|
||||
|
||||
barwin_color_set(infobar[sc].tags[i], infobar[sc].tags[i]->bg, infobar[sc].tags[i]->fg);
|
||||
barwin_refresh_color(infobar[sc].tags[i]);
|
||||
|
||||
/* Colorize a tag if there are clients in this */
|
||||
for(c = clients; c; c = c->next)
|
||||
{
|
||||
if(c->screen == sc)
|
||||
{
|
||||
infobar[sc].tags[c->tag]->bg = ((c->tag == seltag[sc]) ? conf.colors.tagselbg : conf.colors.tag_occupied_bg);
|
||||
barwin_refresh_color(infobar[sc].tags[i]);
|
||||
}
|
||||
}
|
||||
if(tags[sc][i].name)
|
||||
barwin_draw_text(infobar[sc].tags[i], PAD / 2, FHINFOBAR, tags[sc][i].name);
|
||||
}
|
||||
@@ -164,82 +282,41 @@ infobar_draw_taglist(int sc)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draw text in the statustext and parse color format
|
||||
*\param sc Screen
|
||||
*\param str String
|
||||
/** Update taglist geo
|
||||
*\param sc Screen number
|
||||
*/
|
||||
void
|
||||
infobar_draw_statustext(int sc, char *str)
|
||||
infobar_update_taglist(int sc)
|
||||
{
|
||||
char *buf = NULL;
|
||||
char *strwc = NULL;
|
||||
char col[8] = { 0 };
|
||||
int i, j, c, k = 0;
|
||||
char *lastst;
|
||||
int i, j;
|
||||
|
||||
/* If the str == the current statustext, return (not needed) */
|
||||
if(!str)
|
||||
return;
|
||||
|
||||
barwin_refresh_color(infobar[sc].bar);
|
||||
|
||||
/* save last status text address (for free at the end) */
|
||||
lastst = infobar[sc].statustext;
|
||||
|
||||
infobar[sc].statustext = _strdup(str);
|
||||
strwc = _strdup(str);
|
||||
|
||||
/* Count how many color block there is and make a string without color block (\#....\)*/
|
||||
for(i = j = c = 0; i < strlen(str); ++i, ++j)
|
||||
for(i = 1, j = 0; i < conf.ntag[sc] + 1; ++i)
|
||||
{
|
||||
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
|
||||
/* If the tag i does not exist yet (graphically) or need full update */
|
||||
if(!infobar[sc].tags[i] || infobar[sc].need_update)
|
||||
{
|
||||
++c;
|
||||
i += 8;
|
||||
--j;
|
||||
infobar[sc].tags[i] = barwin_create(infobar[sc].tags_board->win, j, 0,
|
||||
textw(tags[sc][i].name) + PAD,
|
||||
infobar[sc].geo.height,
|
||||
conf.colors.bar, conf.colors.text, False, False, conf.border.tag);
|
||||
|
||||
barwin_map(infobar[sc].tags[i]);
|
||||
barwin_map_subwin(infobar[sc].tags[i]);
|
||||
|
||||
j += textw(tags[sc][i].name) + PAD;
|
||||
|
||||
barwin_resize(infobar[sc].tags_board, j, infobar[sc].geo.height);
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
strwc[j] = str[i];
|
||||
|
||||
barwin_move(infobar[sc].tags[i], j, 0);
|
||||
j += textw(tags[sc][i].name) + PAD;
|
||||
barwin_resize(infobar[sc].tags[i], textw(tags[sc][i].name) + PAD, infobar[sc].geo.height);
|
||||
barwin_resize(infobar[sc].tags_board, j, infobar[sc].geo.height);
|
||||
}
|
||||
|
||||
strwc[j] = '\0';
|
||||
|
||||
/* Draw a first time the statustext for non colorized text */
|
||||
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(strwc),
|
||||
FHINFOBAR, infobar[sc].bar->fg, 0, strwc);
|
||||
|
||||
/* Draw text with its color */
|
||||
if(c)
|
||||
{
|
||||
buf = _strdup(strwc);
|
||||
|
||||
for(i = k; i < strlen(str); ++i, ++k)
|
||||
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
|
||||
{
|
||||
/* Store current color in col[] */
|
||||
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
|
||||
buf += k;
|
||||
|
||||
/* Draw a rectangle with the bar color to draw the text properly */
|
||||
draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
|
||||
0, INFOBARH - (sgeo[sc].width - SHADH) - textw(buf),
|
||||
INFOBARH, conf.colors.bar);
|
||||
|
||||
/* Draw text with its color */
|
||||
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
|
||||
FHINFOBAR, col, 0, buf);
|
||||
|
||||
buf = _strdup(strwc);
|
||||
++i;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
barwin_refresh(infobar[sc].bar);
|
||||
|
||||
free(lastst);
|
||||
free(strwc);
|
||||
infobar[sc].need_update = False;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -255,11 +332,16 @@ infobar_destroy(void)
|
||||
{
|
||||
barwin_delete(infobar[sc].layout_button);
|
||||
barwin_delete_subwin(infobar[sc].layout_button);
|
||||
|
||||
for(i = 1; i < conf.ntag[sc] + 1; ++i)
|
||||
{
|
||||
barwin_delete_subwin(infobar[sc].tags[i]);
|
||||
barwin_delete(infobar[sc].tags[i]);
|
||||
}
|
||||
|
||||
barwin_delete_subwin(infobar[sc].tags_board);
|
||||
barwin_delete(infobar[sc].tags_board);
|
||||
barwin_delete(infobar[sc].selbar);
|
||||
barwin_delete_subwin(infobar[sc].bar);
|
||||
barwin_delete(infobar[sc].bar);
|
||||
}
|
||||
@@ -299,7 +381,6 @@ infobar_set_position(int pos)
|
||||
|
||||
barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
|
||||
infobar_draw(selscreen);
|
||||
ewmh_set_workarea();
|
||||
arrange(selscreen, True);
|
||||
|
||||
return;
|
||||
@@ -311,6 +392,7 @@ infobar_set_position(int pos)
|
||||
void
|
||||
uicb_infobar_togglepos(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
infobar_set_position((tags[selscreen][seltag[selscreen]].barpos
|
||||
@@ -320,3 +402,57 @@ uicb_infobar_togglepos(uicb_t cmd)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Toggle hide/display infobar
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_infobar_toggledisplay(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
int new_pos;
|
||||
|
||||
new_pos = (tags[selscreen][seltag[selscreen]].barpos
|
||||
? 0 : (tags[selscreen][seltag[selscreen]].prev_barpos
|
||||
? tags[selscreen][seltag[selscreen]].prev_barpos : 2
|
||||
));
|
||||
|
||||
tags[selscreen][seltag[selscreen]].prev_barpos = tags[selscreen][seltag[selscreen]].barpos;
|
||||
tags[selscreen][seltag[selscreen]].barpos = new_pos;
|
||||
|
||||
infobar_set_position(new_pos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Toggle the tag_autohide mode
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_toggle_tagautohide(uicb_t cmd)
|
||||
{
|
||||
int i, x;
|
||||
(void)cmd;
|
||||
|
||||
screen_get_sel();
|
||||
conf.tagautohide = !conf.tagautohide;
|
||||
|
||||
if(!conf.tagautohide)
|
||||
{
|
||||
for(i = 1, x = 0; i < conf.ntag[selscreen] + 1; ++i)
|
||||
{
|
||||
if(!infobar[selscreen].tags[i]->mapped)
|
||||
barwin_map(infobar[selscreen].tags[i]);
|
||||
|
||||
barwin_move(infobar[selscreen].tags[i], x, 0);
|
||||
x += infobar[selscreen].tags[i]->geo.width;
|
||||
}
|
||||
|
||||
barwin_resize(infobar[selscreen].tags_board, x, infobar[selscreen].geo.height);
|
||||
}
|
||||
|
||||
infobar_draw(selscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
151
src/init.c
151
src/init.c
@@ -32,32 +32,32 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
/** Init WMFS
|
||||
*/
|
||||
void
|
||||
init(void)
|
||||
{
|
||||
/* First init */
|
||||
ewmh_init_hints();
|
||||
init_layout();
|
||||
init_conf();
|
||||
init_gc();
|
||||
init_font();
|
||||
init_cursor();
|
||||
init_key();
|
||||
init_root();
|
||||
screen_init_geo();
|
||||
infobar_init();
|
||||
init_status();
|
||||
ewmh_update_current_tag_prop();
|
||||
grabkeys();
|
||||
|
||||
return;
|
||||
}
|
||||
const func_name_list_t layout_list[] =
|
||||
{
|
||||
{"tile", tile },
|
||||
{"tile_right", tile },
|
||||
{"tile_left", tile_left },
|
||||
{"tile_top", tile_top },
|
||||
{"tile_bottom", tile_bottom },
|
||||
{"tile_grid", grid_horizontal },
|
||||
{"tile_grid_horizontal", grid_horizontal },
|
||||
{"tile_grid_vertical", grid_vertical },
|
||||
{"grid", grid_horizontal },
|
||||
{"mirror_vertical", mirror_vertical },
|
||||
{"tile_mirror_vertical", mirror_vertical },
|
||||
{"mirror_horizontal", mirror_horizontal },
|
||||
{"tile_mirror_horizontal", mirror_horizontal },
|
||||
{"max", maxlayout },
|
||||
{"maxlayout", maxlayout },
|
||||
{"freelayout", freelayout },
|
||||
{"free", freelayout },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/** Init the font
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_font(void)
|
||||
{
|
||||
font = XftFontOpenName(dpy, SCREEN, conf.font);
|
||||
@@ -68,12 +68,16 @@ init_font(void)
|
||||
font = XftFontOpenName(dpy, SCREEN, "sans-10");
|
||||
}
|
||||
|
||||
/* Set font in _WMFS_FONT for eventual status tools */
|
||||
XChangeProperty(dpy, ROOT, net_atom[wmfs_font], net_atom[utf8_string], 8,
|
||||
PropModeReplace, (uchar*)conf.font, strlen(conf.font));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init the graphic context
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_gc(void)
|
||||
{
|
||||
XGCValues gcv;
|
||||
@@ -100,7 +104,7 @@ init_gc(void)
|
||||
|
||||
/** Init WMFS cursor
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_cursor(void)
|
||||
{
|
||||
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
|
||||
@@ -114,7 +118,7 @@ init_cursor(void)
|
||||
|
||||
/** Init key modifier
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_key(void)
|
||||
{
|
||||
int i, j;
|
||||
@@ -133,7 +137,7 @@ init_key(void)
|
||||
|
||||
/** Init root Window
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_root(void)
|
||||
{
|
||||
XSetWindowAttributes at;
|
||||
@@ -154,75 +158,62 @@ init_root(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init layout
|
||||
*/
|
||||
void
|
||||
init_layout(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
const func_name_list_t layout_list_tmp[] =
|
||||
{
|
||||
{"tile", tile },
|
||||
{"tile_right", tile },
|
||||
{"tile_left", tile_left },
|
||||
{"tile_top", tile_top },
|
||||
{"tile_bottom", tile_bottom },
|
||||
{"tile_grid", grid },
|
||||
{"grid", grid },
|
||||
{"mirror_vertical", mirror_vertical },
|
||||
{"tile_mirror_vertical", mirror_vertical },
|
||||
{"mirror_horizontal", mirror_horizontal },
|
||||
{"tile_mirror_horizontal", mirror_horizontal },
|
||||
{"layer", layer },
|
||||
{"max", maxlayout },
|
||||
{"maxlayout", maxlayout },
|
||||
{"freelayout", freelayout },
|
||||
{"free", freelayout }
|
||||
};
|
||||
|
||||
layout_list = emalloc(LEN(layout_list_tmp), sizeof(func_name_list_t));
|
||||
memset(layout_list, 0, LEN(layout_list_tmp));
|
||||
|
||||
for(i = 0; i < LEN(layout_list_tmp); ++i)
|
||||
layout_list[i] = layout_list_tmp[i];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init statustext shell script
|
||||
*/
|
||||
void
|
||||
static void
|
||||
init_status(void)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *home;
|
||||
|
||||
status_path = emalloc(strlen(getenv("HOME")) + strlen(DEF_STATUS) + 2, sizeof(char));
|
||||
conf.status_pid = -1;
|
||||
estatus = False;
|
||||
|
||||
sprintf(status_path, "%s/"DEF_STATUS, getenv("HOME"));
|
||||
|
||||
if(!(fd = open(status_path, O_RDONLY))
|
||||
|| !fopen(status_path, "r"))
|
||||
if(!conf.status_path)
|
||||
{
|
||||
free(status_path);
|
||||
estatus = False;
|
||||
if(!(home = getenv("HOME")))
|
||||
{
|
||||
warnx("HOME not set, can't launch status.sh");
|
||||
return;
|
||||
}
|
||||
|
||||
conf.status_path = zmalloc(strlen(home) + strlen(DEF_STATUS) + 2);
|
||||
sprintf(conf.status_path, "%s/"DEF_STATUS, home);
|
||||
}
|
||||
|
||||
if (stat(patht(conf.status_path), &st) == -1)
|
||||
{
|
||||
warn("%s", patht(conf.status_path));
|
||||
return;
|
||||
}
|
||||
|
||||
stat(status_path, &st);
|
||||
|
||||
if(st.st_size && st.st_mode & S_IXUSR)
|
||||
{
|
||||
estatus = True;
|
||||
system(status_path);
|
||||
}
|
||||
else
|
||||
warnx("status.sh file present in wmfs directory can't be executed, try 'chmod +x %s'.",
|
||||
status_path);
|
||||
|
||||
close(fd);
|
||||
warnx("status file specified in configuratin (status_path) or present in wmfs directory can't be executed, try 'chmod +x %s'.", patht(conf.status_path));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Init WMFS
|
||||
*/
|
||||
void
|
||||
init(void)
|
||||
{
|
||||
/* First init */
|
||||
ewmh_init_hints();
|
||||
init_conf();
|
||||
init_gc();
|
||||
init_font();
|
||||
init_cursor();
|
||||
init_key();
|
||||
init_root();
|
||||
screen_init_geo();
|
||||
infobar_init();
|
||||
systray_acquire();
|
||||
init_status();
|
||||
ewmh_update_current_tag_prop();
|
||||
grabkeys();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
429
src/launcher.c
429
src/launcher.c
@@ -30,178 +30,8 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* conforming to glib use _GNU_SOURCE for asprintf declaration */
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
|
||||
static char *complete_on_command(char*, size_t);
|
||||
static char *complete_on_files(char*, size_t);
|
||||
|
||||
void
|
||||
launcher_execute(Launcher launcher)
|
||||
{
|
||||
BarWindow *bw;
|
||||
Bool found;
|
||||
Bool lastwastab = False;
|
||||
Bool my_guitar_gently_wheeps = True;
|
||||
char tmp[32] = { 0 };
|
||||
char buf[512] = { 0 };
|
||||
char tmpbuf[512] = { 0 };
|
||||
char *complete;
|
||||
int pos = 0, x;
|
||||
int tabhits = 0;
|
||||
KeySym ks;
|
||||
XEvent ev;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
x = (infobar[selscreen].layout_button->geo.x
|
||||
+ textw(tags[selscreen][seltag[selscreen]].layout.symbol) + PAD);
|
||||
|
||||
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
bw = barwin_create(infobar[selscreen].bar->win, x, 1,
|
||||
infobar[selscreen].bar->geo.width - x - 1,
|
||||
infobar[selscreen].bar->geo.height - 2,
|
||||
infobar[selscreen].bar->bg,
|
||||
infobar[selscreen].bar->fg,
|
||||
False, False, conf.border.bar);
|
||||
|
||||
barwin_map(bw);
|
||||
barwin_refresh_color(bw);
|
||||
|
||||
/* First draw of the cursor */
|
||||
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
|
||||
XDrawLine(dpy, bw->dr, gc, textw(launcher.prompt) + textw(" "),
|
||||
2, textw(launcher.prompt) + textw(" "), INFOBARH - 4);
|
||||
|
||||
barwin_refresh(bw);
|
||||
|
||||
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
|
||||
|
||||
while(my_guitar_gently_wheeps)
|
||||
{
|
||||
if(ev.type == KeyPress)
|
||||
{
|
||||
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
|
||||
|
||||
/* Check Ctrl-c / Ctrl-d */
|
||||
if(ev.xkey.state & ControlMask)
|
||||
if(ks == XK_c || ks == XK_d)
|
||||
ks = XK_Escape;
|
||||
|
||||
/* Check if there is a keypad */
|
||||
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
|
||||
ks = XK_Return;
|
||||
|
||||
switch(ks)
|
||||
{
|
||||
case XK_Return:
|
||||
spawn("%s %s", launcher.command, buf);
|
||||
my_guitar_gently_wheeps = 0;
|
||||
break;
|
||||
case XK_Escape:
|
||||
my_guitar_gently_wheeps = 0;
|
||||
break;
|
||||
case XK_Tab:
|
||||
/*
|
||||
* completion
|
||||
* if there is not space in buffer we
|
||||
* complete the command using complete_on_command.
|
||||
* Else we try to complete on filename using
|
||||
* complete_on_files.
|
||||
*/
|
||||
buf[pos] = '\0';
|
||||
if (lastwastab)
|
||||
tabhits++;
|
||||
else
|
||||
{
|
||||
tabhits = 1;
|
||||
strcpy(tmpbuf, buf);
|
||||
}
|
||||
|
||||
|
||||
if (pos)
|
||||
{
|
||||
if (strchr(tmpbuf, ' '))
|
||||
complete = complete_on_files(tmpbuf, tabhits);
|
||||
else
|
||||
complete = complete_on_command(tmpbuf, tabhits);
|
||||
|
||||
if (complete)
|
||||
{
|
||||
strcpy(buf, tmpbuf);
|
||||
strncat(buf, complete, sizeof(buf));
|
||||
found = True;
|
||||
free(complete);
|
||||
}
|
||||
}
|
||||
|
||||
lastwastab = True;
|
||||
|
||||
/* start a new round of tabbing */
|
||||
if (!found)
|
||||
tabhits = 0;
|
||||
|
||||
pos = strlen(buf);
|
||||
|
||||
break;
|
||||
|
||||
case XK_BackSpace:
|
||||
lastwastab = False;
|
||||
if(pos)
|
||||
buf[--pos] = 0;
|
||||
break;
|
||||
default:
|
||||
lastwastab = False;
|
||||
strncat(buf, tmp, sizeof(buf));
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
|
||||
barwin_refresh_color(bw);
|
||||
|
||||
/* Update cursor position */
|
||||
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
|
||||
XDrawLine(dpy, bw->dr, gc,
|
||||
1 + textw(launcher.prompt) + textw(" ") + textw(buf), 2,
|
||||
1 + textw(launcher.prompt) + textw(" ") + textw(buf), INFOBARH - 4);
|
||||
|
||||
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
|
||||
barwin_draw_text(bw, 1 + textw(launcher.prompt) + textw(" "), FHINFOBAR - 1, buf);
|
||||
barwin_refresh(bw);
|
||||
}
|
||||
else
|
||||
getevent(ev);
|
||||
XNextEvent(dpy, &ev);
|
||||
}
|
||||
|
||||
barwin_unmap(bw);
|
||||
barwin_delete(bw);
|
||||
infobar_draw(selscreen);
|
||||
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
uicb_launcher(uicb_t cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < conf.nlauncher; ++i)
|
||||
if(!strcmp(cmd, conf.launcher[i].name))
|
||||
launcher_execute(conf.launcher[i]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Just search command in PATH.
|
||||
* Return the characters to complete the command.
|
||||
@@ -214,36 +44,50 @@ complete_on_command(char *start, size_t hits)
|
||||
char *ret = NULL;
|
||||
DIR *dir;
|
||||
struct dirent *content;
|
||||
size_t count = 0;
|
||||
|
||||
char **namelist = NULL;
|
||||
int n = 0, i;
|
||||
|
||||
if (!getenv("PATH") || !start || hits <= 0)
|
||||
return NULL;
|
||||
|
||||
path = _strdup(getenv("PATH"));
|
||||
path = xstrdup(getenv("PATH"));
|
||||
dirname = strtok(path, ":");
|
||||
|
||||
/* recursively open PATH */
|
||||
while (dirname)
|
||||
while (dirname != NULL)
|
||||
{
|
||||
if ((dir = opendir(dirname)))
|
||||
{
|
||||
while ((content = readdir(dir)))
|
||||
if (!strncmp(content->d_name, start, strlen(start)) && ++count == hits)
|
||||
{
|
||||
if(strncmp(content->d_name, ".", 1))
|
||||
{
|
||||
ret = _strdup(content->d_name + strlen(start));
|
||||
break;
|
||||
if (!strncmp(content->d_name, start, strlen(start)))
|
||||
{
|
||||
namelist = xrealloc(namelist, ++n, sizeof(*namelist));
|
||||
namelist[n-1] = xstrdup(content->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
dirname = strtok(NULL, ":");
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
if(n > 0)
|
||||
{
|
||||
qsort(namelist, n, sizeof(char *), qsort_string_compare);
|
||||
ret = xstrdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start));
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
free(namelist[i]);
|
||||
|
||||
free(namelist);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -272,14 +116,14 @@ complete_on_files(char *start, size_t hits)
|
||||
* the beginning of file to complete on pointer 'p'.
|
||||
*/
|
||||
if (*(++p) == '\0' || !strrchr(p, '/'))
|
||||
path = _strdup(".");
|
||||
path = xstrdup(".");
|
||||
else
|
||||
{
|
||||
/* remplace ~ by $HOME in dirname */
|
||||
if (!strncmp(p, "~/", 2) && getenv("HOME"))
|
||||
asprintf(&dirname, "%s%s", getenv("HOME"), p+1);
|
||||
xasprintf(&dirname, "%s%s", getenv("HOME"), p+1);
|
||||
else
|
||||
dirname = _strdup(p);
|
||||
dirname = xstrdup(p);
|
||||
|
||||
/* Set p to filename to be complete
|
||||
* and path the directory containing the file
|
||||
@@ -290,11 +134,11 @@ complete_on_files(char *start, size_t hits)
|
||||
if (p != dirname)
|
||||
{
|
||||
*(p++) = '\0';
|
||||
path = _strdup(dirname);
|
||||
path = xstrdup(dirname);
|
||||
}
|
||||
else
|
||||
{
|
||||
path = _strdup("/");
|
||||
path = xstrdup("/");
|
||||
p++;
|
||||
}
|
||||
}
|
||||
@@ -308,19 +152,19 @@ complete_on_files(char *start, size_t hits)
|
||||
if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits)
|
||||
{
|
||||
/* If it's a directory append '/' to the completion */
|
||||
asprintf(&filepath, "%s/%s", path, content->d_name);
|
||||
xasprintf(&filepath, "%s/%s", path, content->d_name);
|
||||
|
||||
if (filepath && stat(filepath, &st) != -1)
|
||||
{
|
||||
if (S_ISDIR(st.st_mode))
|
||||
asprintf(&ret, "%s/", content->d_name + strlen(p));
|
||||
xasprintf(&ret, "%s/", content->d_name + strlen(p));
|
||||
else
|
||||
ret = _strdup(content->d_name + strlen(p));
|
||||
ret = xstrdup(content->d_name + strlen(p));
|
||||
}
|
||||
else
|
||||
warn("%s", filepath);
|
||||
|
||||
IFREE(filepath);
|
||||
free(filepath);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -328,8 +172,211 @@ complete_on_files(char *start, size_t hits)
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
IFREE(dirname);
|
||||
IFREE(path);
|
||||
free(dirname);
|
||||
free(path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
launcher_execute(Launcher *launcher)
|
||||
{
|
||||
BarWindow *bw;
|
||||
Bool found;
|
||||
Bool lastwastab = False;
|
||||
Bool my_guitar_gently_wheeps = True;
|
||||
char tmp[32] = { 0 };
|
||||
char buf[512] = { 0 };
|
||||
char tmpbuf[512] = { 0 };
|
||||
char *complete;
|
||||
int i, pos = 0, histpos = 0, x, w;
|
||||
int tabhits = 0;
|
||||
KeySym ks;
|
||||
XEvent ev;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
x = (conf.layout_placement)
|
||||
? (infobar[selscreen].tags_board->geo.x + infobar[selscreen].tags_board->geo.width)
|
||||
: (infobar[selscreen].layout_button->geo.x + infobar[selscreen].layout_button->geo.width);
|
||||
|
||||
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
w = (launcher->width ? launcher->width : infobar[selscreen].bar->geo.width - x - 1);
|
||||
|
||||
bw = barwin_create(infobar[selscreen].bar->win, x, 1, w,
|
||||
/* infobar[selscreen].bar->geo.width - x - 1, */
|
||||
infobar[selscreen].bar->geo.height - 2,
|
||||
infobar[selscreen].bar->bg,
|
||||
infobar[selscreen].bar->fg,
|
||||
False, False, conf.border.bar);
|
||||
|
||||
barwin_map(bw);
|
||||
barwin_refresh_color(bw);
|
||||
|
||||
/* First draw of the cursor */
|
||||
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
|
||||
|
||||
XDrawLine(dpy, bw->dr, gc,
|
||||
1 + textw(launcher->prompt) + textw(" ") + textw(buf), 2,
|
||||
1 + textw(launcher->prompt) + textw(" ") + textw(buf), INFOBARH - 4);
|
||||
|
||||
barwin_refresh(bw);
|
||||
|
||||
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher->prompt);
|
||||
|
||||
while(my_guitar_gently_wheeps)
|
||||
{
|
||||
if(ev.type == KeyPress)
|
||||
{
|
||||
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
|
||||
|
||||
/* Check Ctrl-c / Ctrl-d */
|
||||
if(ev.xkey.state & ControlMask)
|
||||
{
|
||||
if(ks == XK_c || ks == XK_d)
|
||||
ks = XK_Escape;
|
||||
else if(ks == XK_p)
|
||||
ks = XK_Up;
|
||||
else if(ks == XK_n)
|
||||
ks = XK_Down;
|
||||
}
|
||||
|
||||
/* Check if there is a keypad */
|
||||
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
|
||||
ks = XK_Return;
|
||||
|
||||
switch(ks)
|
||||
{
|
||||
case XK_Up:
|
||||
if(launcher->nhisto)
|
||||
{
|
||||
if(histpos >= (int)launcher->nhisto)
|
||||
histpos = 0;
|
||||
strncpy(buf, launcher->histo[launcher->nhisto - ++histpos], sizeof(buf));
|
||||
pos = strlen(buf);
|
||||
}
|
||||
break;
|
||||
case XK_Down:
|
||||
if(launcher->nhisto && histpos > 0 && histpos < (int)launcher->nhisto)
|
||||
{
|
||||
strncpy(buf, launcher->histo[launcher->nhisto - --histpos], sizeof(buf));
|
||||
pos = strlen(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case XK_Return:
|
||||
spawn("%s %s", launcher->command, buf);
|
||||
/* Histo */
|
||||
if(launcher->nhisto + 1 > HISTOLEN)
|
||||
{
|
||||
for(i = launcher->nhisto - 1; i > 1; --i)
|
||||
strncpy(launcher->histo[i], launcher->histo[i - 1], sizeof(launcher->histo[i]));
|
||||
|
||||
launcher->nhisto = 0;
|
||||
}
|
||||
/* Store in histo array */
|
||||
strncpy(launcher->histo[launcher->nhisto++], buf, sizeof(buf));
|
||||
|
||||
my_guitar_gently_wheeps = 0;
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
my_guitar_gently_wheeps = 0;
|
||||
break;
|
||||
|
||||
case XK_Tab:
|
||||
/*
|
||||
* completion
|
||||
* if there is not space in buffer we
|
||||
* complete the command using complete_on_command.
|
||||
* Else we try to complete on filename using
|
||||
* complete_on_files.
|
||||
*/
|
||||
buf[pos] = '\0';
|
||||
if (lastwastab)
|
||||
tabhits++;
|
||||
else
|
||||
{
|
||||
tabhits = 1;
|
||||
strncpy(tmpbuf, buf, sizeof(tmpbuf));
|
||||
}
|
||||
|
||||
|
||||
if (pos)
|
||||
{
|
||||
if (strchr(tmpbuf, ' '))
|
||||
complete = complete_on_files(tmpbuf, tabhits);
|
||||
else
|
||||
complete = complete_on_command(tmpbuf, tabhits);
|
||||
|
||||
if (complete)
|
||||
{
|
||||
strncpy(buf, tmpbuf, sizeof(buf));
|
||||
strncat(buf, complete, sizeof(buf));
|
||||
found = True;
|
||||
free(complete);
|
||||
}
|
||||
}
|
||||
|
||||
lastwastab = True;
|
||||
|
||||
/* start a new round of tabbing */
|
||||
if (found == False)
|
||||
tabhits = 0;
|
||||
|
||||
pos = strlen(buf);
|
||||
|
||||
break;
|
||||
|
||||
case XK_BackSpace:
|
||||
lastwastab = False;
|
||||
if(pos)
|
||||
buf[--pos] = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
lastwastab = False;
|
||||
strncat(buf, tmp, sizeof(tmp));
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
|
||||
barwin_refresh_color(bw);
|
||||
|
||||
/* Update cursor position */
|
||||
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
|
||||
XDrawLine(dpy, bw->dr, gc,
|
||||
1 + textw(launcher->prompt) + textw(" ") + textw(buf), 2,
|
||||
1 + textw(launcher->prompt) + textw(" ") + textw(buf), INFOBARH - 4);
|
||||
|
||||
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher->prompt);
|
||||
barwin_draw_text(bw, 1 + textw(launcher->prompt) + textw(" "), FHINFOBAR - 1, buf);
|
||||
barwin_refresh(bw);
|
||||
}
|
||||
else
|
||||
getevent(ev);
|
||||
XNextEvent(dpy, &ev);
|
||||
}
|
||||
|
||||
barwin_unmap(bw);
|
||||
barwin_delete(bw);
|
||||
infobar_draw(selscreen);
|
||||
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
uicb_launcher(uicb_t cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < conf.nlauncher; ++i)
|
||||
if(!strcmp(cmd, conf.launcher[i].name))
|
||||
launcher_execute(&conf.launcher[i]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
296
src/layout.c
296
src/layout.c
@@ -39,7 +39,7 @@ arrange(int screen, Bool update_layout)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
if(screen < 0 || screen > screen_count())
|
||||
if(screen < 0 || screen > screen_count() - 1)
|
||||
screen = screen_get_sel();
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
@@ -51,10 +51,13 @@ arrange(int screen, Bool update_layout)
|
||||
client_hide(c);
|
||||
}
|
||||
|
||||
if(update_layout)
|
||||
tags[screen][seltag[screen]].layout.func(screen);
|
||||
if(tags[screen][seltag[screen]].layout.func)
|
||||
{
|
||||
if(update_layout)
|
||||
tags[screen][seltag[screen]].layout.func(screen);
|
||||
|
||||
infobar_draw(screen);
|
||||
infobar_draw(screen);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -65,13 +68,14 @@ void
|
||||
freelayout(int screen)
|
||||
{
|
||||
Client *c;
|
||||
(void)screen;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(!ishide(c, selscreen)
|
||||
&& c->screen == screen_get_sel()
|
||||
&& !(c->flags & MaxFlag))
|
||||
{
|
||||
client_moveresize(c, c->ogeo, True);
|
||||
client_moveresize(c, c->free_geo, True);
|
||||
c->flags &= ~(TileFlag | LMaxFlag);
|
||||
}
|
||||
|
||||
@@ -92,8 +96,11 @@ layoutswitch(Bool b)
|
||||
screen_get_sel();
|
||||
|
||||
if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
|
||||
for(c = clients; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = c->next)
|
||||
for(c = clients; c && (c->tag != (uint)seltag[selscreen] && c->screen != selscreen); c = c->next)
|
||||
{
|
||||
c->ogeo = c->geo;
|
||||
c->free_geo = c->geo;
|
||||
}
|
||||
|
||||
for(i = 0; i < conf.nlayout; ++i)
|
||||
{
|
||||
@@ -121,6 +128,7 @@ layoutswitch(Bool b)
|
||||
void
|
||||
uicb_layout_next(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
layoutswitch(True);
|
||||
|
||||
return;
|
||||
@@ -132,11 +140,33 @@ uicb_layout_next(uicb_t cmd)
|
||||
void
|
||||
uicb_layout_prev(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
layoutswitch(False);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sort all the client that can be
|
||||
* tiled
|
||||
* \param c Client pointer
|
||||
* \return a client pointer
|
||||
*/
|
||||
static Client*
|
||||
tiled_client(int screen, Client *c)
|
||||
{
|
||||
for(;c && ((c->flags & MaxFlag)
|
||||
|| (c->flags & FreeFlag)
|
||||
|| (c->flags & FSSFlag)
|
||||
|| (c->flags & AboveFlag)
|
||||
|| c->screen != screen
|
||||
|| ishide(c, screen)); c = c->next);
|
||||
|
||||
if(c)
|
||||
c->flags |= FLayFlag;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Max layout function
|
||||
*/
|
||||
void
|
||||
@@ -157,24 +187,6 @@ maxlayout(int screen)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sort all the client that can be
|
||||
* tiled
|
||||
* \param c Client pointer
|
||||
* \return a client pointer
|
||||
*/
|
||||
Client*
|
||||
tiled_client(int screen, Client *c)
|
||||
{
|
||||
for(;c && ((c->flags & MaxFlag)
|
||||
|| (c->flags & FreeFlag)
|
||||
|| (c->flags & FSSFlag)
|
||||
|| (c->flags & AboveFlag)
|
||||
|| c->screen != screen
|
||||
|| ishide(c, screen)); c = c->next);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Set the mwfact
|
||||
* \param cmd Mwfact (string)
|
||||
*/
|
||||
@@ -224,52 +236,15 @@ uicb_set_nmaster(uicb_t cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
uicb_set_client_layer(uicb_t cmd)
|
||||
{
|
||||
int n = atoi(cmd);
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
CHECK(sel);
|
||||
|
||||
if(sel->layer + n < 1
|
||||
|| sel->layer + n > tags[selscreen][seltag[selscreen]].layers)
|
||||
return;
|
||||
|
||||
sel->layer += n;
|
||||
|
||||
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
uicb_set_layer(uicb_t cmd)
|
||||
{
|
||||
int n = atoi(cmd);
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
if(tags[selscreen][seltag[selscreen]].layers + n < 1)
|
||||
return;
|
||||
|
||||
tags[selscreen][seltag[selscreen]].layers += n;
|
||||
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** Grid layout function
|
||||
*/
|
||||
void
|
||||
grid(int screen)
|
||||
static void
|
||||
grid(int screen, Bool horizontal)
|
||||
{
|
||||
Client *c;
|
||||
XRectangle sg = sgeo[screen];
|
||||
XRectangle cgeo = {sg.x, sg.y, 0, 0};
|
||||
unsigned int i, n, cols, rows, cpcols = 0;
|
||||
unsigned int i, n, temp, cols, rows, cpcols = 0;
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
@@ -282,6 +257,13 @@ grid(int screen)
|
||||
? rows - 1
|
||||
: rows;
|
||||
|
||||
if(!horizontal)
|
||||
{
|
||||
temp = cols;
|
||||
cols = rows;
|
||||
rows = temp;
|
||||
}
|
||||
|
||||
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
|
||||
{
|
||||
/* Set client property */
|
||||
@@ -321,14 +303,14 @@ grid(int screen)
|
||||
/** Multi tile function
|
||||
* \param type Postion type { Top, Bottom, Left, Right }
|
||||
*/
|
||||
void
|
||||
static void
|
||||
multi_tile(int screen, Position type)
|
||||
{
|
||||
Client *c;
|
||||
XRectangle sg = sgeo[screen];
|
||||
XRectangle mastergeo = {sg.x, sg.y, 0, 0};
|
||||
XRectangle cgeo = {sg.x, sg.y, 0, 0};
|
||||
uint i, n, tilesize, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
|
||||
uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
@@ -345,15 +327,15 @@ multi_tile(int screen, Position type)
|
||||
if(type == Top || type == Bottom)
|
||||
{
|
||||
if(type == Top)
|
||||
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
|
||||
mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH;
|
||||
mastergeo.width = (sg.width / nmaster) - (BORDH * 4);
|
||||
mastergeo.height = (n <= nmaster) ? sg.height - BORDH : mwfact;
|
||||
mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(type == Left)
|
||||
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2);
|
||||
mastergeo.width = (n <= nmaster) ? sg.width - (BORDH * 2) : mwfact;
|
||||
mastergeo.x = (n <= nmaster) ? (uint)sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2);
|
||||
mastergeo.width = (n <= nmaster) ? (uint)(sg.width - (BORDH * 2)) : mwfact;
|
||||
mastergeo.height = (sg.height / nmaster) - BORDH;
|
||||
}
|
||||
|
||||
@@ -451,19 +433,21 @@ multi_tile(int screen, Position type)
|
||||
* \param screen Screen to execute this function
|
||||
* \param horizont To specify the mirror mode (vertical/horizontal)
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mirror(int screen, Bool horizontal)
|
||||
{
|
||||
Client *c;
|
||||
XRectangle sg = sgeo[screen];
|
||||
XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height};
|
||||
XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height};
|
||||
XRectangle nextg[2] = { {0} };
|
||||
uint i, n, tilesize, mwfact;
|
||||
XRectangle nextg[2];
|
||||
uint i, n, tilesize = 0, mwfact;
|
||||
uint nmaster = tags[screen][seltag[screen]].nmaster;
|
||||
int pa, imp;
|
||||
Bool isp = 0;
|
||||
|
||||
memset(nextg, 0, sizeof(nextg));
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
|
||||
@@ -625,72 +609,6 @@ mirror(int screen, Bool horizontal)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Layer layout function
|
||||
*/
|
||||
void
|
||||
layer(int screen)
|
||||
{
|
||||
Client *c;
|
||||
XRectangle geo = { 0 };
|
||||
XRectangle sg = sgeo[screen];
|
||||
int n, i, l = tags[screen][seltag[screen]].layers;
|
||||
int *x = NULL;
|
||||
int *nl = NULL;
|
||||
int *ncl = NULL;
|
||||
|
||||
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
|
||||
CHECK(n);
|
||||
|
||||
x = emalloc(l + 1, sizeof(int));
|
||||
nl = emalloc(l + 1, sizeof(int));
|
||||
ncl = emalloc(l + 1, sizeof(int));
|
||||
|
||||
for(i = 0; i < l + 1; ++i)
|
||||
{
|
||||
x[i] = sg.x;
|
||||
nl[i] = 0;
|
||||
ncl[i] = 0;
|
||||
}
|
||||
|
||||
for(c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next))
|
||||
{
|
||||
for(; c->layer > l; --(c->layer));
|
||||
++nl[c->layer];
|
||||
}
|
||||
|
||||
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
|
||||
{
|
||||
/* Set client property */
|
||||
c->flags &= ~(MaxFlag | LMaxFlag);
|
||||
c->flags |= TileFlag;
|
||||
|
||||
++ncl[c->layer];
|
||||
|
||||
geo.x = x[c->layer];
|
||||
geo.height = (sg.height / l) - (BORDH + TBARH);
|
||||
geo.width = (sg.width / ((nl[c->layer]) ? nl[c->layer] : 1)) - BORDH * 2;
|
||||
geo.y = sg.y + ((geo.height + TBARH + BORDH) * c->layer) - (geo.height + TBARH + BORDH);
|
||||
|
||||
if(c->layer == l)
|
||||
geo.height = (sg.y + sg.height) - geo.y - BORDH;
|
||||
|
||||
if(ncl[c->layer] == nl[c->layer])
|
||||
geo.width = sg.width - (geo.x - (sg.x - (BORDH * 2)));
|
||||
|
||||
client_moveresize(c, geo, False);
|
||||
|
||||
x[c->layer] = geo.x + geo.width + BORDH * 2;
|
||||
}
|
||||
|
||||
free(x);
|
||||
free(nl);
|
||||
free(ncl);
|
||||
|
||||
ewmh_update_current_tag_prop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Tile Right function
|
||||
*/
|
||||
void
|
||||
@@ -751,15 +669,29 @@ mirror_horizontal(int screen)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Horizontal grid function
|
||||
*/
|
||||
void
|
||||
grid_horizontal(int screen)
|
||||
{
|
||||
grid(screen, True);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Vertical grid function
|
||||
*/
|
||||
void
|
||||
grid_vertical(int screen)
|
||||
{
|
||||
grid(screen, False);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Put the selected client to the master postion
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tile_switch(uicb_t cmd)
|
||||
{
|
||||
layout_set_client_master (sel);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Toggle the selected client to free
|
||||
* \param cmd uicb_t type unused
|
||||
@@ -767,6 +699,8 @@ uicb_tile_switch(uicb_t cmd)
|
||||
void
|
||||
uicb_togglefree(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag))
|
||||
return;
|
||||
|
||||
@@ -775,11 +709,14 @@ uicb_togglefree(uicb_t cmd)
|
||||
if((sel->flags & FreeFlag))
|
||||
{
|
||||
sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
|
||||
client_moveresize(sel, sel->ogeo, True);
|
||||
client_moveresize(sel, sel->free_geo, True);
|
||||
client_raise(sel);
|
||||
}
|
||||
else
|
||||
{
|
||||
sel->free_geo = sel->geo;
|
||||
sel->ogeo = sel->geo;
|
||||
}
|
||||
|
||||
client_update_attributes(sel);
|
||||
|
||||
@@ -788,13 +725,14 @@ uicb_togglefree(uicb_t cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** Toggle the selected client to max
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_togglemax(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
if(!sel || ishide(sel, selscreen)
|
||||
|| (sel->flags & HintFlag)|| (sel->flags & FSSFlag))
|
||||
return;
|
||||
@@ -802,13 +740,17 @@ uicb_togglemax(uicb_t cmd)
|
||||
if(!(sel->flags & MaxFlag))
|
||||
{
|
||||
sel->ogeo = sel->geo;
|
||||
sel->free_geo = sel->geo;
|
||||
sel->flags &= ~(TileFlag | FreeFlag);
|
||||
client_maximize(sel);
|
||||
client_raise(sel);
|
||||
XRaiseWindow(dpy, sel->frame);
|
||||
sel->flags |= MaxFlag;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sel->geo = sel->ogeo;
|
||||
client_moveresize(sel, sel->geo, True);
|
||||
sel->flags &= ~MaxFlag;
|
||||
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
|
||||
}
|
||||
@@ -823,6 +765,7 @@ void
|
||||
uicb_toggle_resizehint(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
(void)cmd;
|
||||
|
||||
tags[selscreen][seltag[selscreen]].resizehint = !tags[selscreen][seltag[selscreen]].resizehint;
|
||||
|
||||
@@ -838,6 +781,7 @@ void
|
||||
uicb_toggle_abovefc(uicb_t cmd)
|
||||
{
|
||||
Client *c;
|
||||
(void)cmd;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
@@ -846,7 +790,7 @@ uicb_toggle_abovefc(uicb_t cmd)
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->flags & AboveFlag
|
||||
&& c->screen == selscreen
|
||||
&& c->tag == seltag[selscreen])
|
||||
&& c->tag == (uint)seltag[selscreen])
|
||||
{
|
||||
c->flags &= ~AboveFlag;
|
||||
break;
|
||||
@@ -866,7 +810,7 @@ uicb_toggle_abovefc(uicb_t cmd)
|
||||
void
|
||||
uicb_set_layout(uicb_t cmd)
|
||||
{
|
||||
int i, j, n;
|
||||
size_t i, j, n;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
@@ -874,7 +818,7 @@ uicb_set_layout(uicb_t cmd)
|
||||
for(n = 0; layout_list[n].name != NULL && layout_list[n].func != NULL; ++n);
|
||||
|
||||
for(i = 0; i < n; ++i)
|
||||
if(!strcmp(cmd, _strdup(layout_list[i].name)))
|
||||
if(!strcmp(cmd, xstrdup(layout_list[i].name)))
|
||||
for(j = 0; j < LEN(conf.layout); ++j)
|
||||
if(layout_list[i].func == conf.layout[j].func)
|
||||
tags[selscreen][seltag[selscreen]].layout = conf.layout[j];
|
||||
@@ -901,9 +845,57 @@ layout_set_client_master(Client *c)
|
||||
|
||||
client_detach(c);
|
||||
client_attach(c);
|
||||
client_focus(c);
|
||||
|
||||
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Check the selected client is max
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
Bool
|
||||
uicb_checkmax(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
if(!sel)
|
||||
return False;
|
||||
|
||||
if(sel->flags & MaxFlag)
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/** Check the selected client is free
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
Bool
|
||||
uicb_checkfree(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
if(!sel)
|
||||
return False;
|
||||
|
||||
if(sel->flags & FreeFlag)
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
/** Check layout type
|
||||
* \param cmd uicb_t type layout type
|
||||
*/
|
||||
Bool
|
||||
uicb_checklayout(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
|
||||
if(!strcmp(cmd, tags[selscreen][seltag[selscreen]].layout.type))
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
327
src/menu.c
327
src/menu.c
@@ -32,91 +32,124 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
void
|
||||
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n)
|
||||
static int
|
||||
menu_get_longer_string(MenuItem *mi, int nitem)
|
||||
{
|
||||
int i, w, l = 0;
|
||||
|
||||
/* Item */
|
||||
menu->nitem = nitem;
|
||||
menu->item = emalloc(sizeof(MenuItem), nitem);
|
||||
menu->name = name;
|
||||
for(i = 0; i < nitem; ++i)
|
||||
if((w = textw(mi[i].name)) > l)
|
||||
l = w;
|
||||
|
||||
/* Colors */
|
||||
menu->colors.focus.bg = bg_f;
|
||||
menu->colors.focus.fg = fg_f;
|
||||
menu->colors.normal.bg = bg_n;
|
||||
menu->colors.normal.fg = fg_n;
|
||||
|
||||
return;
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd)
|
||||
static Bool
|
||||
menu_get_checkstring_needed(MenuItem *mi, int nitem)
|
||||
{
|
||||
mi->name = name;
|
||||
mi->func = func;
|
||||
mi->cmd = cmd;
|
||||
|
||||
return;
|
||||
(void)mi;
|
||||
(void)nitem;
|
||||
return True;
|
||||
}
|
||||
|
||||
void
|
||||
menu_draw(Menu menu, int x, int y)
|
||||
static void
|
||||
menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen)
|
||||
{
|
||||
int i, width;
|
||||
XEvent ev;
|
||||
BarWindow *item[menu.nitem];
|
||||
BarWindow *frame;
|
||||
int x;
|
||||
int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3;
|
||||
|
||||
width = menu_get_longer_string(menu.item, menu.nitem);
|
||||
|
||||
/* Frame barwin */
|
||||
frame = barwin_create(ROOT, x, y, width + SHADH, menu.nitem * (INFOBARH - SHADH) + SHADH * 2,
|
||||
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
|
||||
|
||||
barwin_map(frame);
|
||||
barwin_map_subwin(frame);
|
||||
barwin_refresh_color(frame);
|
||||
|
||||
for(i = 0; i < menu.nitem; ++i)
|
||||
switch(menu->align)
|
||||
{
|
||||
item[i] = barwin_create(frame->win,
|
||||
SHADH,
|
||||
(i * (INFOBARH - SHADH) + SHADH),
|
||||
width - SHADH,
|
||||
INFOBARH,
|
||||
menu.colors.normal.bg,
|
||||
menu.colors.normal.fg,
|
||||
True, False, False);
|
||||
case MA_Left:
|
||||
x = chcklen + PAD / 2;
|
||||
break;
|
||||
case MA_Right:
|
||||
x = width - textw(menu->item[item].name) + PAD * 3 / 2;
|
||||
break;
|
||||
default:
|
||||
case MA_Center:
|
||||
x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3;
|
||||
break;
|
||||
}
|
||||
barwin_draw_image_ofset_text(winitem[item], x, FHINFOBAR, menu->item[item].name, chcklen + PAD / 2, 0);
|
||||
|
||||
barwin_map(item[i]);
|
||||
barwin_refresh_color(item[i]);
|
||||
menu_draw_item_name(&menu, i, item);
|
||||
barwin_refresh(item[i]);
|
||||
if(menu->item[item].check)
|
||||
if(menu->item[item].check(menu->item[item].cmd))
|
||||
barwin_draw_image_ofset_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol, PAD / 3, 0);
|
||||
|
||||
if(menu->item[item].submenu)
|
||||
barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static Bool
|
||||
menu_activate_item(Menu *menu, int i)
|
||||
{
|
||||
int j, x, y;
|
||||
int chcklen = 0;
|
||||
if(menu_get_checkstring_needed(menu->item, menu->nitem))
|
||||
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
|
||||
|
||||
if(menu->item[i].submenu)
|
||||
{
|
||||
for(j = 0; j < conf.nmenu; ++j)
|
||||
if(!strcmp(menu->item[i].submenu, conf.menu[j].name))
|
||||
{
|
||||
y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2;
|
||||
x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3;
|
||||
|
||||
menu_draw(conf.menu[j], x, y);
|
||||
|
||||
return True;
|
||||
}
|
||||
}
|
||||
else if(menu->item[i].func)
|
||||
{
|
||||
menu->item[i].func(menu->item[i].cmd);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Select the first item */
|
||||
menu_focus_item(&menu, 0, item);
|
||||
return False;
|
||||
}
|
||||
|
||||
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
static void
|
||||
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
|
||||
{
|
||||
int i;
|
||||
|
||||
while(!menu_manage_event(&ev, &menu, item));
|
||||
int chcklen = 0;
|
||||
if(menu_get_checkstring_needed(menu->item, menu->nitem))
|
||||
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
|
||||
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
menu->focus_item = item;
|
||||
|
||||
for(i = 0; i < menu.nitem; ++i)
|
||||
barwin_delete(item[i]);
|
||||
barwin_delete(frame);
|
||||
if(menu->focus_item > menu->nitem - 1)
|
||||
menu->focus_item = 0;
|
||||
else if(menu->focus_item < 0)
|
||||
menu->focus_item = menu->nitem - 1;
|
||||
|
||||
for(i = 0; i < menu->nitem; ++i)
|
||||
{
|
||||
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
|
||||
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
|
||||
|
||||
barwin_refresh_color(winitem[i]);
|
||||
menu_draw_item_name(menu, i, winitem, chcklen);
|
||||
barwin_refresh(winitem[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Bool
|
||||
static Bool
|
||||
menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
|
||||
{
|
||||
int i, c = 0;
|
||||
KeySym ks;
|
||||
Bool quit = False;
|
||||
char acc = 0;
|
||||
|
||||
switch(ev->type)
|
||||
{
|
||||
@@ -127,12 +160,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
|
||||
{
|
||||
if(ev->xbutton.window == winitem[i]->win
|
||||
&& (ev->xbutton.button == Button1 || ev->xbutton.button == Button2))
|
||||
{
|
||||
if(menu->item[i].func)
|
||||
menu->item[i].func(menu->item[i].cmd);
|
||||
|
||||
quit = True;
|
||||
}
|
||||
quit = menu_activate_item(menu, i);
|
||||
else if(ev->xbutton.window != winitem[i]->win)
|
||||
++c;
|
||||
else if(ev->xbutton.button == Button4)
|
||||
@@ -161,9 +189,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
|
||||
break;
|
||||
|
||||
case XK_Return:
|
||||
if(menu->item[menu->focus_item].func)
|
||||
menu->item[menu->focus_item].func(menu->item[menu->focus_item].cmd);
|
||||
quit = True;
|
||||
quit = menu_activate_item(menu, menu->focus_item);
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
@@ -178,7 +204,20 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
|
||||
/* For focus an item with the mouse */
|
||||
for(i = 0; i < menu->nitem; ++i)
|
||||
if(ev->xcrossing.window == winitem[i]->win)
|
||||
{
|
||||
acc = 1;
|
||||
menu_focus_item(menu, i, winitem);
|
||||
if(menu->item[i].submenu)
|
||||
menu_activate_item(menu, menu->focus_item);
|
||||
}
|
||||
|
||||
if(!acc)
|
||||
{
|
||||
if(ev->xcrossing.window)
|
||||
XSendEvent(dpy, ev->xcrossing.window, False, StructureNotifyMask, ev);
|
||||
|
||||
return True;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -190,57 +229,6 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
|
||||
return quit;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
|
||||
{
|
||||
int i;
|
||||
|
||||
menu->focus_item = item;
|
||||
|
||||
if(menu->focus_item > menu->nitem - 1)
|
||||
menu->focus_item = 0;
|
||||
else if(menu->focus_item < 0)
|
||||
menu->focus_item = menu->nitem - 1;
|
||||
|
||||
for(i = 0; i < menu->nitem; ++i)
|
||||
{
|
||||
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
|
||||
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
|
||||
|
||||
barwin_refresh_color(winitem[i]);
|
||||
menu_draw_item_name(menu, i, winitem);
|
||||
barwin_refresh(winitem[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[])
|
||||
{
|
||||
int width = menu_get_longer_string(menu->item, menu->nitem);
|
||||
|
||||
barwin_draw_text(winitem[item],
|
||||
((width / 2) - (textw(menu->item[item].name) / 2)),
|
||||
FHINFOBAR,
|
||||
menu->item[item].name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
menu_get_longer_string(MenuItem *mt, int nitem)
|
||||
{
|
||||
int i, l = 0;
|
||||
|
||||
for(i = 0; i < nitem; ++i)
|
||||
if(textw(mt[i].name) > l)
|
||||
l = textw(mt[i].name);
|
||||
|
||||
return l + PAD;
|
||||
}
|
||||
|
||||
void
|
||||
uicb_menu(uicb_t cmd)
|
||||
{
|
||||
@@ -254,7 +242,11 @@ uicb_menu(uicb_t cmd)
|
||||
if(!strcmp(cmd, conf.menu[i].name))
|
||||
{
|
||||
if(conf.menu[i].place_at_mouse)
|
||||
{
|
||||
XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&u);
|
||||
conf.menu[i].x = x;
|
||||
conf.menu[i].y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
screen_get_sel();
|
||||
@@ -266,3 +258,102 @@ uicb_menu(uicb_t cmd)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
menu_clear(Menu *menu)
|
||||
{
|
||||
free(menu->item);
|
||||
menu->nitem = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n)
|
||||
{
|
||||
/* Item */
|
||||
menu->nitem = nitem;
|
||||
menu->item = xcalloc(nitem, sizeof(*menu->item));
|
||||
menu->name = name;
|
||||
|
||||
/* Colors */
|
||||
menu->colors.focus.bg = bg_f;
|
||||
menu->colors.focus.fg = fg_f;
|
||||
menu->colors.normal.bg = bg_n;
|
||||
menu->colors.normal.fg = fg_n;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd)
|
||||
{
|
||||
mi->name = name;
|
||||
mi->func = func;
|
||||
mi->cmd = cmd;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
menu_draw(Menu menu, int x, int y)
|
||||
{
|
||||
int i, width, height, out;
|
||||
XEvent ev;
|
||||
BarWindow *item[menu.nitem];
|
||||
BarWindow *frame;
|
||||
|
||||
int chcklen = 0;
|
||||
if(menu_get_checkstring_needed(menu.item, menu.nitem))
|
||||
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
|
||||
|
||||
width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3;
|
||||
height = menu.nitem * (INFOBARH - SHADH);
|
||||
|
||||
/* Frame barwin */
|
||||
screen_get_sel();
|
||||
|
||||
if((out = x + width - MAXW) > 0)
|
||||
x -= out;
|
||||
if((out = y + height - MAXH) > 0)
|
||||
y -= out;
|
||||
|
||||
frame = barwin_create(ROOT, x, y, width + SHADH, height + SHADH * 3,
|
||||
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
|
||||
|
||||
barwin_map(frame);
|
||||
barwin_map_subwin(frame);
|
||||
barwin_refresh_color(frame);
|
||||
|
||||
for(i = 0; i < menu.nitem; ++i)
|
||||
{
|
||||
item[i] = barwin_create(frame->win,
|
||||
SHADH,
|
||||
(i * (INFOBARH - SHADH) + SHADH),
|
||||
width - SHADH,
|
||||
INFOBARH,
|
||||
menu.colors.normal.bg,
|
||||
menu.colors.normal.fg,
|
||||
True, False, False);
|
||||
|
||||
barwin_map(item[i]);
|
||||
barwin_refresh_color(item[i]);
|
||||
menu_draw_item_name(&menu, i, item, chcklen);
|
||||
barwin_refresh(item[i]);
|
||||
}
|
||||
|
||||
/* Select the first item */
|
||||
menu_focus_item(&menu, 0, item);
|
||||
|
||||
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
while(!menu_manage_event(&ev, &menu, item));
|
||||
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
|
||||
for(i = 0; i < menu.nitem; ++i)
|
||||
barwin_delete(item[i]);
|
||||
barwin_delete(frame);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
20
src/mouse.c
20
src/mouse.c
@@ -34,7 +34,7 @@
|
||||
|
||||
/** Draw the border when a client in dragging/resizing with mouse
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mouse_dragborder(XRectangle geo, GC g)
|
||||
{
|
||||
XDrawRectangle(dpy, ROOT, g,
|
||||
@@ -49,11 +49,10 @@ mouse_dragborder(XRectangle geo, GC g)
|
||||
/** Move a client in tile grid with the mouse
|
||||
*\param c Client double pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mouse_move_tile_client(Client **c)
|
||||
{
|
||||
Client *sc;
|
||||
|
||||
Window w;
|
||||
int d;
|
||||
|
||||
@@ -77,7 +76,7 @@ mouse_move_tile_client(Client **c)
|
||||
/** Move a client from one tag to another with dah mouse
|
||||
*\param c client pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mouse_move_tag_client(Client *c)
|
||||
{
|
||||
Window w;
|
||||
@@ -88,7 +87,7 @@ mouse_move_tag_client(Client *c)
|
||||
|
||||
s = c->screen;
|
||||
|
||||
XQueryPointer(dpy, infobar[selscreen].bar->win, &w, &w, &d, &d, &d, &d, (uint*)&d);
|
||||
XQueryPointer(dpy, infobar[selscreen].tags_board->win, &w, &w, &d, &d, &d, &d, (uint*)&d);
|
||||
|
||||
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
|
||||
if(infobar[selscreen].tags[i]->win == w
|
||||
@@ -103,13 +102,15 @@ mouse_move_tag_client(Client *c)
|
||||
arrange(c->screen, True);
|
||||
}
|
||||
|
||||
client_focus_next(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Move the client with the mouse
|
||||
* \param c Client pointer
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mouse_move(Client *c)
|
||||
{
|
||||
int ocx, ocy, mx, my;
|
||||
@@ -248,7 +249,8 @@ mouse_resize(Client *c)
|
||||
{
|
||||
/* To resize MWFACT in tile mode */
|
||||
if((c->flags & TileFlag)
|
||||
&& tags[selscreen][seltag[selscreen]].layout.func != grid)
|
||||
&& tags[selscreen][seltag[selscreen]].layout.func != grid_vertical
|
||||
&& tags[selscreen][seltag[selscreen]].layout.func != grid_horizontal)
|
||||
{
|
||||
if(tags[selscreen][seltag[selscreen]].layout.func == tile)
|
||||
mwf += (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
|
||||
@@ -317,7 +319,7 @@ mouse_resize(Client *c)
|
||||
void
|
||||
mouse_grabbuttons(Client *c, Bool focused)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
uint but[] = {Button1, Button2, Button3, Button4, Button5};
|
||||
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
||||
@@ -346,6 +348,7 @@ mouse_grabbuttons(Client *c, Bool focused)
|
||||
void
|
||||
uicb_mouse_move(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
CHECK(sel);
|
||||
|
||||
mouse_move(sel);
|
||||
@@ -359,6 +362,7 @@ uicb_mouse_move(uicb_t cmd)
|
||||
void
|
||||
uicb_mouse_resize(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
CHECK(sel);
|
||||
|
||||
mouse_resize(sel);
|
||||
|
||||
623
src/parse.c
Normal file
623
src/parse.c
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||
*
|
||||
* 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"
|
||||
|
||||
extern char *__progname;
|
||||
|
||||
enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE };
|
||||
|
||||
#ifdef DEBUG
|
||||
static 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_t quote;
|
||||
bool_t 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 = zcalloc(sizeof(*kw));
|
||||
kw->type = type;
|
||||
kw->line = line;
|
||||
kw->file = file;
|
||||
kw->next = NULL;
|
||||
|
||||
if (*offset != 0) {
|
||||
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_t error = False;
|
||||
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) {
|
||||
warn("%s", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (st.st_size == 0) {
|
||||
warnx("%s: empty file", filename);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!realpath(filename, path)) {
|
||||
warn("%s", filename);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = zmalloc(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 = zcalloc(sizeof(*file));
|
||||
bufname = zcalloc(sizeof(*bufname) * BUFSIZ);
|
||||
file->name = strdup(path);
|
||||
file->parent = NULL;
|
||||
|
||||
for(i = 0, j = 0, line = 1; i < (size_t)st.st_size; i++) {
|
||||
|
||||
if (!head && tail)
|
||||
head = tail;
|
||||
|
||||
if (buf[i] == '\n' && s.comment == True) {
|
||||
line++;
|
||||
s.comment = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf[i] == '#' && s.quote == False) {
|
||||
s.comment = True;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s.comment == True)
|
||||
continue;
|
||||
|
||||
if (s.quote == True && buf[i] == s.quote_char) {
|
||||
/* end of quotted string */
|
||||
PUSH_KEYWORD(WORD);
|
||||
s.quote = False;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s.quote == False) {
|
||||
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;
|
||||
}
|
||||
} /* s.quote == False */
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 = zcalloc(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);
|
||||
}
|
||||
|
||||
kw = kw->next;
|
||||
|
||||
if (!kw) {
|
||||
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 = zcalloc(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;
|
||||
|
||||
kw = head = 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;
|
||||
}
|
||||
|
||||
121
src/parse.h
Normal file
121
src/parse.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||
*
|
||||
* 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"
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define INCLUDE_CMD "@include"
|
||||
#define PARSE_MAX_LIST 32
|
||||
|
||||
#if defined(Bool)
|
||||
#define bool_t Bool
|
||||
#else
|
||||
typedef enum { False, True } bool_t;
|
||||
#endif /* Bool */
|
||||
|
||||
struct conf_opt {
|
||||
char *name;
|
||||
char *val[PARSE_MAX_LIST];
|
||||
size_t nval;
|
||||
bool_t used;
|
||||
int line;
|
||||
char *filename;
|
||||
SLIST_ENTRY(conf_opt) entry;
|
||||
};
|
||||
|
||||
struct conf_sec {
|
||||
char *name;
|
||||
SLIST_HEAD(, conf_opt) optlist;
|
||||
TAILQ_HEAD(, conf_sec) sub;
|
||||
size_t nopt;
|
||||
size_t nsub;
|
||||
TAILQ_ENTRY(conf_sec) entry;
|
||||
};
|
||||
|
||||
struct opt_type {
|
||||
long int num;
|
||||
float fnum;
|
||||
bool_t bool;
|
||||
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 */
|
||||
197
src/parse_api.c
Normal file
197
src/parse_api.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
|
||||
*
|
||||
* 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 "parse.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);
|
||||
|
||||
if (!strcmp(s, "true") || !strcmp(s, "True") ||
|
||||
!strcmp(s, "TRUE") || !strcmp(s, "1"))
|
||||
ret.bool = True;
|
||||
else
|
||||
ret.bool = False;
|
||||
|
||||
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 == False)
|
||||
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;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (!s)
|
||||
{
|
||||
TAILQ_FOREACH(sec, &config, entry)
|
||||
if(sec->name && !strcmp(sec->name, name)) {
|
||||
ret = sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TAILQ_FOREACH(sec, &s->sub, 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;
|
||||
for (ret = 0; 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;
|
||||
for(ret = 0; o[ret].str; ret++);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
44
src/screen.c
44
src/screen.c
@@ -91,6 +91,8 @@ screen_get_geo(int s)
|
||||
|
||||
XFree(xsi);
|
||||
}
|
||||
#else
|
||||
(void)s;
|
||||
#endif /* HAVE_XINERAMA */
|
||||
|
||||
return geo;
|
||||
@@ -123,10 +125,14 @@ screen_set_sel(int screen)
|
||||
if(screen < 0 || screen > screen_count() - 1)
|
||||
screen = 0;
|
||||
|
||||
if(selscreen != screen)
|
||||
prevselscreen = selscreen;
|
||||
|
||||
client_focus(NULL);
|
||||
XWarpPointer(dpy, None, ROOT, 0, 0, 0, 0,
|
||||
sgeo[screen].x + sgeo[screen].width / 2,
|
||||
sgeo[screen].y + sgeo[screen].height / 2);
|
||||
|
||||
selscreen = screen;
|
||||
|
||||
return;
|
||||
@@ -138,6 +144,8 @@ screen_set_sel(int screen)
|
||||
int
|
||||
screen_get_sel(void)
|
||||
{
|
||||
int os = selscreen;
|
||||
|
||||
selscreen = 0;
|
||||
|
||||
#ifdef HAVE_XINERAMA
|
||||
@@ -157,6 +165,9 @@ screen_get_sel(void)
|
||||
XChangeProperty(dpy, ROOT, net_atom[wmfs_current_screen], XA_CARDINAL, 32,
|
||||
PropModeReplace, (uchar*)&selscreen, 1);
|
||||
|
||||
if(os != selscreen && os != prevselscreen)
|
||||
prevselscreen = os;
|
||||
|
||||
return selscreen;
|
||||
}
|
||||
|
||||
@@ -166,11 +177,12 @@ void
|
||||
screen_init_geo(void)
|
||||
{
|
||||
int i;
|
||||
int s = screen_count();
|
||||
|
||||
sgeo = emalloc(screen_count(), sizeof(XRectangle));
|
||||
spgeo = emalloc(screen_count(), sizeof(XRectangle));
|
||||
sgeo = xcalloc(s, sizeof(XRectangle));
|
||||
spgeo = xcalloc(s, sizeof(XRectangle));
|
||||
|
||||
for(i = 0; i < screen_count(); ++i)
|
||||
for(i = 0; i < s; ++i)
|
||||
sgeo[i] = screen_get_geo(i);
|
||||
|
||||
spgeo[0].x = 0;
|
||||
@@ -205,7 +217,6 @@ screen_init_geo(void)
|
||||
#endif /* HAVE_XRANDR */
|
||||
|
||||
ewmh_set_desktop_geometry();
|
||||
ewmh_set_workarea();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -227,11 +238,15 @@ uicb_screen_select(uicb_t cmd)
|
||||
void
|
||||
uicb_screen_next(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1;
|
||||
if(screen_count() > 1)
|
||||
{
|
||||
selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1;
|
||||
|
||||
screen_set_sel(selscreen);
|
||||
screen_set_sel(selscreen);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -242,6 +257,7 @@ uicb_screen_next(uicb_t cmd)
|
||||
void
|
||||
uicb_screen_prev(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
selscreen = (selscreen - 1 < 0) ? screen_count() - 1 : selscreen - 1;
|
||||
@@ -250,3 +266,19 @@ uicb_screen_prev(uicb_t cmd)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Uicb: screen prev sel
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_screen_prev_sel(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
screen_set_sel(prevselscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
242
src/status.c
Normal file
242
src/status.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* status.c
|
||||
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
/** Check rectangles blocks in str and return properties
|
||||
* --> \b[x;y;width;height;#color]\
|
||||
*\param r StatusRec pointer, rectangles properties
|
||||
*\param str String
|
||||
*\return n Length of r
|
||||
*/
|
||||
static int
|
||||
statustext_rectangle(StatusRec *r, char *str)
|
||||
{
|
||||
char as;
|
||||
int n, i, j, k;
|
||||
|
||||
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
|
||||
if(sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c", &r[n].x, &r[n].y, &r[n].w, &r[n].h, &r[n].color, &as) == 6
|
||||
&& as == '\\')
|
||||
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
|
||||
else if(j != i)
|
||||
str[j] = str[i];
|
||||
|
||||
for(k = j; k < i; str[k++] = 0);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Check graphs blocks in str and return properties
|
||||
* --> \g[x;y;width;height;#color;data]\
|
||||
*\param g StatusGraph pointer, graphs properties
|
||||
*\param str String
|
||||
*\return n Length of g
|
||||
*/
|
||||
static int
|
||||
statustext_graph(StatusGraph *g, char *str)
|
||||
{
|
||||
char as, c, *p;
|
||||
int n, i, j, k, m, w;
|
||||
|
||||
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
|
||||
if(sscanf(&str[i], "\\g[%d;%d;%d;%d;#%x;%512[^]]]%c",
|
||||
&g[n].x, &g[n].y, &g[n].w, &g[n].h, &g[n].color, g[n].data, &as) == 7
|
||||
&& as == '\\')
|
||||
{
|
||||
/* data is a list of numbers separated by ';' */
|
||||
w = g[n].w;
|
||||
p = strtok(g[n].data, ";");
|
||||
m = 0;
|
||||
|
||||
while(p && m < w)
|
||||
{
|
||||
c = atoi(p);
|
||||
/* height limits */
|
||||
if(c < 0)
|
||||
c = 0;
|
||||
if(c > (char)g[n].h)
|
||||
c = g[n].h;
|
||||
g[n].data[m] = c;
|
||||
p = strtok(NULL, ";");
|
||||
++m;
|
||||
}
|
||||
|
||||
/* width limits */
|
||||
for(; m < w; ++m)
|
||||
g[n].data[m] = 0;
|
||||
/* data is a array[w] of bytes now */
|
||||
|
||||
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
|
||||
}
|
||||
else if(j != i)
|
||||
str[j] = str[i];
|
||||
|
||||
for(k = j; k < i; str[k++] = 0);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Check text blocks in str and return properties
|
||||
* --> \s[x;y;#color;text]\
|
||||
*\param s StatusText pointer, text properties
|
||||
*\param str String
|
||||
*\return n Length of s
|
||||
*/
|
||||
static int
|
||||
statustext_text(StatusText *s, char *str)
|
||||
{
|
||||
char as;
|
||||
int n, i, j, k;
|
||||
|
||||
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
|
||||
if(sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^]]]%c", &s[n].x, &s[n].y, s[n].color, s[n].text, &as) == 5
|
||||
&& as == '\\')
|
||||
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
|
||||
else if(j != i)
|
||||
str[j] = str[i];
|
||||
|
||||
for(k = j; k < i; str[k++] = 0);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Draw normal text and colored normal text
|
||||
* --> \#color\ text in color
|
||||
*\param sc Screen
|
||||
*\param str String
|
||||
*/
|
||||
static void
|
||||
statustext_normal(int sc, char *str)
|
||||
{
|
||||
char strwc[MAXSTATUS] = { 0 };
|
||||
char buf[MAXSTATUS] = { 0 };
|
||||
char col[8] = { 0 };
|
||||
int n, i, j, k, sw = 0;
|
||||
|
||||
if(sc == conf.systray.screen)
|
||||
sw = systray_get_width();
|
||||
|
||||
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
|
||||
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
|
||||
{
|
||||
++n;
|
||||
i += 8;
|
||||
--j;
|
||||
}
|
||||
else
|
||||
strwc[j] = str[i];
|
||||
|
||||
/* Draw normal text without any blocks */
|
||||
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(strwc) + sw),
|
||||
FHINFOBAR, infobar[sc].bar->fg, strwc);
|
||||
|
||||
if(n)
|
||||
{
|
||||
strncpy(buf, strwc, sizeof(buf));
|
||||
|
||||
for(i = k = 0; i < (int)strlen(str); ++i, ++k)
|
||||
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
|
||||
{
|
||||
/* Store current color in col[] */
|
||||
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
|
||||
|
||||
/* Draw a rectangle with the bar color to draw the text properly */
|
||||
draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(&buf[k]) + sw),
|
||||
0, INFOBARH - (sgeo[sc].width - SHADH) - textw(&buf[k]),
|
||||
INFOBARH, conf.colors.bar);
|
||||
|
||||
/* Draw text with its color */
|
||||
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - (textw(&buf[k]) + sw),
|
||||
FHINFOBAR, col, &buf[k]);
|
||||
|
||||
strncpy(buf, strwc, sizeof(buf));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Handle statustext and draw all things in infobar of specified screen
|
||||
*\param sc Screen number
|
||||
*\param str String
|
||||
*/
|
||||
void
|
||||
statustext_handle(int sc, char *str)
|
||||
{
|
||||
char *lastst;
|
||||
int i, nr, ng, ns, sw = 0;
|
||||
StatusRec r[128];
|
||||
StatusGraph g[128];
|
||||
StatusText s[128];
|
||||
|
||||
/* If the str == the current statustext, return (not needed) */
|
||||
if(!str)
|
||||
return;
|
||||
|
||||
if(sc == conf.systray.screen)
|
||||
sw = systray_get_width();
|
||||
|
||||
barwin_refresh_color(infobar[sc].bar);
|
||||
|
||||
/* save last status text address (for free at the end) */
|
||||
lastst = infobar[sc].statustext;
|
||||
|
||||
infobar[sc].statustext = xstrdup(str);
|
||||
|
||||
/* Store rectangles, located text & images properties. */
|
||||
nr = statustext_rectangle(r, str);
|
||||
ng = statustext_graph(g, str);
|
||||
ns = statustext_text(s, str);
|
||||
|
||||
/* Draw normal text (and possibly colored with \#color\ blocks) */
|
||||
statustext_normal(sc, str);
|
||||
|
||||
/* Draw rectangles with stored properties. */
|
||||
for(i = 0; i < nr; ++i)
|
||||
draw_rectangle(infobar[sc].bar->dr, r[i].x - sw, r[i].y, r[i].w, r[i].h, r[i].color);
|
||||
|
||||
/* Draw graphs with stored properties. */
|
||||
for(i = 0; i < ng; ++i)
|
||||
draw_graph(infobar[sc].bar->dr, g[i].x - sw, g[i].y, g[i].w, g[i].h, g[i].color, g[i].data);
|
||||
|
||||
/* Draw located text with stored properties. */
|
||||
for(i = 0; i < ns; ++i)
|
||||
draw_text(infobar[sc].bar->dr, s[i].x - sw, s[i].y, s[i].color, s[i].text);
|
||||
|
||||
barwin_refresh(infobar[sc].bar);
|
||||
|
||||
free(lastst);
|
||||
|
||||
return;
|
||||
}
|
||||
171
src/structs.h
171
src/structs.h
@@ -38,17 +38,23 @@
|
||||
#define NBUTTON 8
|
||||
#define MAXTAG 36
|
||||
#define NUM_OF_LAYOUT 10
|
||||
#define HISTOLEN 128
|
||||
|
||||
/* Clients flags definition */
|
||||
#define FreeFlag (1 << 1)
|
||||
#define MaxFlag (1 << 2)
|
||||
#define TileFlag (1 << 3)
|
||||
#define HideFlag (1 << 4)
|
||||
#define LMaxFlag (1 << 5)
|
||||
#define UnmapFlag (1 << 6)
|
||||
#define HintFlag (1 << 7)
|
||||
#define FSSFlag (1 << 8)
|
||||
#define AboveFlag (1 << 9)
|
||||
#define FreeFlag (1 << 1)
|
||||
#define MaxFlag (1 << 2)
|
||||
#define TileFlag (1 << 3)
|
||||
#define HideFlag (1 << 4)
|
||||
#define LMaxFlag (1 << 5)
|
||||
#define UnmapFlag (1 << 6)
|
||||
#define HintFlag (1 << 7)
|
||||
#define FSSFlag (1 << 8)
|
||||
#define AboveFlag (1 << 9)
|
||||
#define UrgentFlag (1 << 10)
|
||||
#define FLayFlag (1 << 11)
|
||||
#define DockFlag (1 << 12)
|
||||
|
||||
#define TagFlag(t) (1 << (t))
|
||||
|
||||
/* XEMBED messages */
|
||||
#define XEMBED_MAPPED (1 << 0)
|
||||
@@ -81,13 +87,16 @@ typedef unsigned char uchar;
|
||||
|
||||
/* Enum */
|
||||
enum { CurNormal, CurResize, CurRightResize, CurLeftResize, CurMove, CurLast };
|
||||
enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast };
|
||||
|
||||
/* Menu align */
|
||||
enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 };
|
||||
|
||||
/* Infobar position */
|
||||
enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 };
|
||||
|
||||
typedef enum { Right, Left, Top, Bottom, Center, PositionLast } Position;
|
||||
|
||||
|
||||
/* Ewmh hints list */
|
||||
enum
|
||||
{
|
||||
@@ -99,7 +108,6 @@ enum
|
||||
net_current_desktop,
|
||||
net_desktop_names,
|
||||
net_desktop_geometry,
|
||||
net_workarea,
|
||||
net_active_window,
|
||||
net_close_window,
|
||||
net_wm_icon_name,
|
||||
@@ -107,6 +115,7 @@ enum
|
||||
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,
|
||||
@@ -115,7 +124,16 @@ enum
|
||||
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,
|
||||
@@ -131,6 +149,7 @@ enum
|
||||
wmfs_screen_count,
|
||||
wmfs_function,
|
||||
wmfs_cmd,
|
||||
wmfs_font,
|
||||
wmfs_statustext,
|
||||
net_last
|
||||
};
|
||||
@@ -166,6 +185,7 @@ struct Client
|
||||
char *title;
|
||||
/* Tag num */
|
||||
uint tag;
|
||||
int focusontag;
|
||||
/* Screen */
|
||||
int screen;
|
||||
/* Layer */
|
||||
@@ -176,6 +196,8 @@ struct Client
|
||||
XRectangle frame_geo;
|
||||
/* Old window attribute */
|
||||
XRectangle ogeo;
|
||||
/* Free window attribute */
|
||||
XRectangle free_geo;
|
||||
/* For resizehint usage */
|
||||
int basew, baseh, incw, inch;
|
||||
int maxw, maxh, minw, minh;
|
||||
@@ -194,6 +216,7 @@ struct Client
|
||||
uint frame;
|
||||
char *fg;
|
||||
uint resizecorner;
|
||||
uint bordlight, borddark;
|
||||
} colors;
|
||||
/* Client Information by flags */
|
||||
uint flags;
|
||||
@@ -224,21 +247,32 @@ typedef struct
|
||||
/* InfoBar Struct */
|
||||
typedef struct
|
||||
{
|
||||
BarWindow *bar;
|
||||
BarWindow *bar, *selbar;
|
||||
BarWindow *layout_button;
|
||||
BarWindow *tags[MAXTAG];
|
||||
BarWindow *tags_board, *tags[MAXTAG];
|
||||
XRectangle geo;
|
||||
int position;
|
||||
char *statustext;
|
||||
Bool need_update;
|
||||
} InfoBar;
|
||||
|
||||
/* Layout Structure */
|
||||
typedef struct
|
||||
{
|
||||
char *symbol;
|
||||
char *type;
|
||||
void (*func)(int screen);
|
||||
} Layout;
|
||||
|
||||
/* Systray Structure */
|
||||
typedef struct Systray Systray;
|
||||
struct Systray
|
||||
{
|
||||
Window win;
|
||||
XRectangle geo;
|
||||
Systray *next, *prev;
|
||||
};
|
||||
|
||||
/* Tag Structure */
|
||||
typedef struct
|
||||
{
|
||||
@@ -248,11 +282,17 @@ typedef struct
|
||||
int layers;
|
||||
float mwfact;
|
||||
int nmaster;
|
||||
Bool urgent;
|
||||
Bool resizehint;
|
||||
Bool request_update;
|
||||
Bool abovefc;
|
||||
int barpos;
|
||||
int prev_barpos;
|
||||
Layout layout;
|
||||
uint tagad;
|
||||
MouseBinding *mouse;
|
||||
int nmouse;
|
||||
Bool stay_last;
|
||||
} Tag;
|
||||
|
||||
/* Menu Item Struct */
|
||||
@@ -261,6 +301,8 @@ typedef struct
|
||||
char *name;
|
||||
void (*func)(uicb_t);
|
||||
uicb_t cmd;
|
||||
Bool (*check)(uicb_t);
|
||||
char *submenu;
|
||||
} MenuItem;
|
||||
|
||||
/* Menu Struct */
|
||||
@@ -273,6 +315,7 @@ typedef struct
|
||||
char *name;
|
||||
/* Placement */
|
||||
Bool place_at_mouse;
|
||||
int align;
|
||||
int x, y;
|
||||
/* Color */
|
||||
struct
|
||||
@@ -292,6 +335,9 @@ typedef struct
|
||||
char *name;
|
||||
char *prompt;
|
||||
char *command;
|
||||
char histo[HISTOLEN][512];
|
||||
uint nhisto;
|
||||
int width;
|
||||
} Launcher;
|
||||
|
||||
/* Button struct */
|
||||
@@ -301,6 +347,7 @@ typedef struct
|
||||
XSegment *linecoord;
|
||||
int nlines;
|
||||
int nmouse;
|
||||
uint flags;
|
||||
} Button;
|
||||
|
||||
/* Alias struct */
|
||||
@@ -310,6 +357,20 @@ typedef struct
|
||||
char *content;
|
||||
} Alias;
|
||||
|
||||
/* Rule struct */
|
||||
typedef struct
|
||||
{
|
||||
char *class;
|
||||
char *instance;
|
||||
char *role;
|
||||
int screen;
|
||||
int tag;
|
||||
Bool free;
|
||||
Bool max;
|
||||
Bool ignoretags;
|
||||
Bool follow_client;
|
||||
} Rule;
|
||||
|
||||
/* Configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
@@ -318,11 +379,21 @@ typedef struct
|
||||
|
||||
/* Misc option */
|
||||
char *font;
|
||||
uint opacity;
|
||||
Bool raisefocus;
|
||||
Bool raiseswitch;
|
||||
Bool focus_fmouse;
|
||||
Bool focus_fmov;
|
||||
Bool focus_pclick;
|
||||
Bool ignore_next_client_rules;
|
||||
Bool tagautohide;
|
||||
Bool tagnamecount;
|
||||
Tag default_tag;
|
||||
uint pad;
|
||||
int status_timing;
|
||||
char *status_path;
|
||||
pid_t status_pid;
|
||||
char *autostart_path;
|
||||
char *autostart_command;
|
||||
struct
|
||||
{
|
||||
/*
|
||||
@@ -332,19 +403,35 @@ typedef struct
|
||||
uint bar;
|
||||
char *text;
|
||||
char *tagselfg;
|
||||
char *tagurfg;
|
||||
uint tagurbg;
|
||||
uint tagselbg;
|
||||
uint tag_occupied_bg;
|
||||
char *tag_occupied_fg;
|
||||
uint tagbord;
|
||||
char *layout_fg;
|
||||
uint layout_bg;
|
||||
float client_light_shade;
|
||||
float client_dark_shade;
|
||||
float bar_light_shade;
|
||||
float bar_dark_shade;
|
||||
} colors;
|
||||
struct
|
||||
{
|
||||
int height;
|
||||
MouseBinding *mouse;
|
||||
int nmouse;
|
||||
Bool selbar;
|
||||
} bars;
|
||||
struct
|
||||
{
|
||||
char *fg;
|
||||
uint bg;
|
||||
int maxlength;
|
||||
MouseBinding *mouse;
|
||||
int nmouse;
|
||||
} selbar;
|
||||
struct
|
||||
{
|
||||
char *background_command;
|
||||
MouseBinding *mouse;
|
||||
@@ -355,14 +442,19 @@ typedef struct
|
||||
Bool set_new_win_master;
|
||||
Bool place_at_mouse;
|
||||
Bool border_shadow;
|
||||
Bool new_client_get_mouse;
|
||||
int borderheight;
|
||||
char *autofree, *automax;
|
||||
uint bordernormal;
|
||||
uint borderfocus;
|
||||
uint resizecorner_normal;
|
||||
uint resizecorner_focus;
|
||||
uint mod;
|
||||
uint padding;
|
||||
MouseBinding *mouse;
|
||||
int nmouse;
|
||||
uint default_open_tag;
|
||||
int default_open_screen;
|
||||
} client;
|
||||
struct
|
||||
{
|
||||
@@ -385,20 +477,65 @@ typedef struct
|
||||
Bool tag;
|
||||
Bool layout;
|
||||
} border;
|
||||
struct
|
||||
{
|
||||
Bool active;
|
||||
int screen;
|
||||
int spacing;
|
||||
} systray;
|
||||
Alias alias[256];
|
||||
uint mouse_tag_action[TagActionLast];
|
||||
int layout_button_width;
|
||||
Layout layout[NUM_OF_LAYOUT];
|
||||
Menu *menu;
|
||||
Launcher *launcher;
|
||||
Rule *rule;
|
||||
int *ntag;
|
||||
Bool tag_round;
|
||||
Bool tag_auto_prev;
|
||||
Bool client_round;
|
||||
Bool client_auto_center;
|
||||
Bool client_tile_raise;
|
||||
Bool layout_system; /* Switch: False, Menu: True. */
|
||||
Bool layout_placement; /* Right (normal): False, Left: True. */
|
||||
Bool keep_layout_geo;
|
||||
char *tag_expose_name;
|
||||
char *expose_layout;
|
||||
char *selected_layout_symbol;
|
||||
/* Number of... */
|
||||
int nkeybind;
|
||||
int nlayout;
|
||||
int nmenu;
|
||||
int nlauncher;
|
||||
int nrule;
|
||||
} Conf;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint x, y, w, h;
|
||||
uint color;
|
||||
} StatusRec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint x, y, w, h;
|
||||
uint color;
|
||||
char data[512];
|
||||
} StatusGraph;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint x, y;
|
||||
char color[8];
|
||||
char text[512];
|
||||
} StatusText;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint x, y, w, h;
|
||||
char name[512];
|
||||
} ImageAttr;
|
||||
|
||||
/* Config.c struct */
|
||||
typedef struct
|
||||
{
|
||||
@@ -424,4 +561,10 @@ typedef struct
|
||||
char *uicb;
|
||||
} vicmd_to_uicb;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version;
|
||||
int flags;
|
||||
} xembed_info;
|
||||
|
||||
#endif /* STRUCTS_H */
|
||||
|
||||
234
src/systray.c
Normal file
234
src/systray.c
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* systray.c
|
||||
* Copyright © 2008, 2009, 2010 Martin Duquesnoy <xorg62@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
#define TRAY_DWIDTH (infobar[conf.systray.screen].bar->geo.height + conf.systray.spacing)
|
||||
|
||||
Bool
|
||||
systray_acquire(void)
|
||||
{
|
||||
XSetWindowAttributes wattr;
|
||||
|
||||
if(!conf.systray.active || traywin)
|
||||
return False;
|
||||
|
||||
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != None)
|
||||
{
|
||||
warnx("Can't initialize system tray: owned by another process");
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Init traywin window */
|
||||
wattr.event_mask = ButtonPressMask | ExposureMask;
|
||||
wattr.override_redirect = True;
|
||||
wattr.background_pixmap = ParentRelative;
|
||||
wattr.background_pixel = conf.colors.bar;
|
||||
|
||||
traywin = XCreateSimpleWindow(dpy, infobar[conf.systray.screen].bar->win, -1, -1, 1, 1, 0, 0, conf.colors.bar);
|
||||
|
||||
XChangeWindowAttributes(dpy, traywin, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
|
||||
XSelectInput(dpy, traywin, KeyPressMask | ButtonPressMask);
|
||||
|
||||
XMapRaised(dpy, traywin);
|
||||
|
||||
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], traywin, CurrentTime);
|
||||
|
||||
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != traywin)
|
||||
{
|
||||
systray_freeicons();
|
||||
warnx("System tray: can't get systray manager");
|
||||
return False;
|
||||
}
|
||||
|
||||
ewmh_send_message(ROOT, ROOT, "MANAGER", CurrentTime, net_atom[net_system_tray_s], traywin, 0, 0);
|
||||
|
||||
XSync(dpy, False);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
void
|
||||
systray_add(Window win)
|
||||
{
|
||||
Systray *s;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return;
|
||||
|
||||
s = xcalloc(1, sizeof(Systray));
|
||||
s->win = win;
|
||||
|
||||
s->geo.height = infobar[conf.systray.screen].bar->geo.height;
|
||||
s->geo.width = TRAY_DWIDTH;
|
||||
|
||||
setwinstate(s->win, WithdrawnState);
|
||||
XSelectInput(dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
|
||||
XReparentWindow(dpy, s->win, traywin, 0, 0);
|
||||
|
||||
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, traywin, 0);
|
||||
|
||||
/* Attach */
|
||||
if(trayicons)
|
||||
trayicons->prev = s;
|
||||
|
||||
s->next = trayicons;
|
||||
trayicons = s;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
systray_del(Systray *s)
|
||||
{
|
||||
Systray **ss;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return;
|
||||
|
||||
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next);
|
||||
*ss = s->next;
|
||||
|
||||
free(s);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
systray_state(Systray *s)
|
||||
{
|
||||
long flags;
|
||||
int code = 0;
|
||||
|
||||
if(!(flags = ewmh_get_xembed_state(s->win)) || !conf.systray.active)
|
||||
return;
|
||||
|
||||
if(flags & XEMBED_MAPPED)
|
||||
{
|
||||
code = XEMBED_WINDOW_ACTIVATE;
|
||||
XMapRaised(dpy, s->win);
|
||||
setwinstate(s->win, NormalState);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = XEMBED_WINDOW_DEACTIVATE;
|
||||
XUnmapWindow(dpy, s->win);
|
||||
setwinstate(s->win, WithdrawnState);
|
||||
}
|
||||
|
||||
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, code, 0, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
systray_freeicons(void)
|
||||
{
|
||||
Systray *i;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return;
|
||||
|
||||
for(i = trayicons; i; i = i->next)
|
||||
{
|
||||
XUnmapWindow(dpy, i->win);
|
||||
XReparentWindow(dpy, i->win, ROOT, 0, 0);
|
||||
free(i);
|
||||
}
|
||||
|
||||
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], None, CurrentTime);
|
||||
XDestroyWindow(dpy, traywin);
|
||||
|
||||
XSync(dpy, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Systray*
|
||||
systray_find(Window win)
|
||||
{
|
||||
Systray *i;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return NULL;
|
||||
|
||||
for(i = trayicons; i; i = i->next)
|
||||
if(i->win == win)
|
||||
return i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
systray_get_width(void)
|
||||
{
|
||||
int w = 0;
|
||||
Systray *i;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return 0;
|
||||
|
||||
for(i = trayicons; i; i = i->next)
|
||||
w += i->geo.width + conf.systray.spacing + 1;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
void
|
||||
systray_update(void)
|
||||
{
|
||||
Systray *i;
|
||||
int x = 1;
|
||||
|
||||
if(!conf.systray.active)
|
||||
return;
|
||||
|
||||
if(!trayicons)
|
||||
{
|
||||
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = trayicons; i; i = i->next)
|
||||
{
|
||||
XMapWindow(dpy, i->win);
|
||||
|
||||
XMoveResizeWindow(dpy, i->win, (i->geo.x = x), 0, i->geo.width, i->geo.height);
|
||||
|
||||
x += i->geo.width + conf.systray.spacing;
|
||||
}
|
||||
|
||||
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - x,
|
||||
0, x, infobar[conf.systray.screen].bar->geo.height);
|
||||
|
||||
return;
|
||||
}
|
||||
636
src/tag.c
636
src/tag.c
@@ -28,7 +28,6 @@
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "wmfs.h"
|
||||
@@ -39,37 +38,71 @@
|
||||
void
|
||||
tag_set(int tag)
|
||||
{
|
||||
int otag;
|
||||
Client *c;
|
||||
Bool al = False;
|
||||
int i;
|
||||
|
||||
if(tag < 0 || tag > MAXTAG)
|
||||
return;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
otag = seltag[selscreen];
|
||||
if(seltag[selscreen] != tag)
|
||||
prevseltag[selscreen] = seltag[selscreen];
|
||||
else if(tag == seltag[selscreen] && tag != prevseltag[selscreen] && conf.tag_auto_prev)
|
||||
tag = seltag[selscreen] = prevseltag[selscreen];
|
||||
else
|
||||
seltag[selscreen] = tag;
|
||||
|
||||
if(conf.tag_round)
|
||||
{
|
||||
if(tag <= 0)
|
||||
seltag[selscreen] = conf.ntag[selscreen];
|
||||
else if(tag > conf.ntag[selscreen])
|
||||
else if(tag > conf.ntag[selscreen])
|
||||
seltag[selscreen] = 1;
|
||||
else
|
||||
seltag[selscreen] = tag;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!tag || tag == seltag[selscreen]
|
||||
|| tag > conf.ntag[selscreen])
|
||||
if(!tag || tag > conf.ntag[selscreen])
|
||||
return;
|
||||
|
||||
seltag[selscreen] = tag;
|
||||
}
|
||||
|
||||
ewmh_update_current_tag_prop();
|
||||
|
||||
/* Arrange infobar position */
|
||||
if(tags[selscreen][otag].barpos != tags[selscreen][seltag[selscreen]].barpos)
|
||||
if(tags[selscreen][prevseltag[selscreen]].barpos != tags[selscreen][seltag[selscreen]].barpos
|
||||
|| prevseltag[selscreen] == seltag[selscreen])
|
||||
infobar_set_position(tags[selscreen][seltag[selscreen]].barpos);
|
||||
|
||||
arrange(selscreen, False);
|
||||
/* Check if a layout update is needed with additional tags */
|
||||
if(tags[selscreen][seltag[selscreen]].tagad)
|
||||
al = True;
|
||||
else if(tags[selscreen][seltag[selscreen]].request_update)
|
||||
{
|
||||
al = True;
|
||||
tags[selscreen][seltag[selscreen]].request_update = False;
|
||||
}
|
||||
|
||||
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
|
||||
if(tags[selscreen][i].tagad & TagFlag(seltag[selscreen]))
|
||||
{
|
||||
al = True;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for ignore_tag clients */
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->tag == MAXTAG + 1 && c->screen == selscreen)
|
||||
{
|
||||
al = True;
|
||||
break;
|
||||
}
|
||||
|
||||
arrange(selscreen, al);
|
||||
|
||||
if(tags[selscreen][tag].request_update)
|
||||
{
|
||||
@@ -77,11 +110,17 @@ tag_set(int tag)
|
||||
tags[selscreen][tag].request_update = False;
|
||||
}
|
||||
|
||||
/* To focus the first client in the new tag */
|
||||
/* To focus selected client of the via focusontag option */
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->tag == seltag[selscreen] && c->screen == selscreen)
|
||||
if(c->focusontag == tag && c->screen == selscreen)
|
||||
break;
|
||||
|
||||
/* No focusontag option found on any client, try to find the first of the tag */
|
||||
if(!c)
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->tag == (uint)seltag[selscreen] && c->screen == selscreen)
|
||||
break;
|
||||
|
||||
client_focus((c) ? c : NULL);
|
||||
|
||||
return;
|
||||
@@ -98,16 +137,18 @@ tag_transfert(Client *c, int tag)
|
||||
|
||||
CHECK(c);
|
||||
|
||||
if(!tag)
|
||||
if(tag <= 0)
|
||||
tag = 1;
|
||||
|
||||
if(tag > conf.ntag[selscreen])
|
||||
return;
|
||||
|
||||
c->tag = tag;
|
||||
c->screen = selscreen;
|
||||
|
||||
arrange(c->screen, True);
|
||||
|
||||
if(c == sel)
|
||||
client_focus(NULL);
|
||||
client_focus_next(c);
|
||||
|
||||
client_update_attributes(c);
|
||||
|
||||
@@ -138,6 +179,7 @@ uicb_tag(uicb_t cmd)
|
||||
void
|
||||
uicb_tag_next(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
tag_set(seltag[selscreen] + 1);
|
||||
@@ -151,6 +193,7 @@ uicb_tag_next(uicb_t cmd)
|
||||
void
|
||||
uicb_tag_prev(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
tag_set(seltag[selscreen] - 1);
|
||||
@@ -158,6 +201,192 @@ uicb_tag_prev(uicb_t cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
/** Set the next visible tag
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_next_visible(uicb_t cmd)
|
||||
{
|
||||
int i, tag;
|
||||
Client *c;
|
||||
Bool is_occupied[MAXTAG];
|
||||
(void)cmd;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
if(!conf.tagautohide)
|
||||
{
|
||||
tag_set(seltag[selscreen] + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < MAXTAG; i++)
|
||||
is_occupied[i] = False;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->screen == selscreen)
|
||||
is_occupied[c->tag] = True;
|
||||
|
||||
for(tag = seltag[selscreen] + 1; tag < conf.ntag[selscreen] + 1; ++tag)
|
||||
if(is_occupied[tag])
|
||||
{
|
||||
tag_set(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
if(conf.tag_round)
|
||||
for(tag = 0; tag < seltag[selscreen]; ++tag)
|
||||
if(is_occupied[tag])
|
||||
{
|
||||
tag_set(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Set the prev visible tag
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_prev_visible(uicb_t cmd)
|
||||
{
|
||||
int i, tag;
|
||||
Client *c;
|
||||
Bool is_occupied[MAXTAG];
|
||||
(void)cmd;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
if(!conf.tagautohide)
|
||||
{
|
||||
tag_set(seltag[selscreen] - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < MAXTAG; i++)
|
||||
is_occupied[i] = False;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->screen == selscreen)
|
||||
is_occupied[c->tag] = True;
|
||||
|
||||
for(tag = seltag[selscreen] - 1; tag >= 0; --tag)
|
||||
if(is_occupied[tag])
|
||||
{
|
||||
tag_set(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
if(conf.tag_round)
|
||||
for(tag = conf.ntag[selscreen]; tag > seltag[selscreen]; --tag)
|
||||
if(is_occupied[tag])
|
||||
{
|
||||
tag_set(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Go to the last tag
|
||||
*\param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_last(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
tag_set(conf.ntag[selscreen]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
*\param selscreen int
|
||||
*/
|
||||
static void
|
||||
remove_old_last_tag(int selscreen)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i <= conf.ntag[selscreen]; i++)
|
||||
{
|
||||
if(tags[selscreen][i].stay_last)
|
||||
{
|
||||
tags[selscreen][i].stay_last = False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Swap 2 tags
|
||||
*\param s Screen
|
||||
*\param t1 Tag 1
|
||||
*\param t2 Tag 2
|
||||
*/
|
||||
static void
|
||||
tag_swap(int s, int t1, int t2)
|
||||
{
|
||||
Client *c;
|
||||
Tag t;
|
||||
|
||||
if(t1 > conf.ntag[s] || t1 < 1
|
||||
|| t2 > conf.ntag[s] || t2 < 1 || t1 == t2)
|
||||
return;
|
||||
|
||||
t = tags[s][t1];
|
||||
tags[s][t1] = tags[s][t2];
|
||||
tags[s][t2] = t;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
{
|
||||
if(c->screen == s && c->tag == (uint)t1)
|
||||
c->tag = t2;
|
||||
else if(c->screen == s && c->tag == (uint)t2)
|
||||
c->tag = t1;
|
||||
}
|
||||
|
||||
infobar_update_taglist(s);
|
||||
tag_set(t2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Keep that tag the last one
|
||||
*\param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_stay_last(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
if(tags[selscreen][seltag[selscreen]].stay_last)
|
||||
tags[selscreen][seltag[selscreen]].stay_last = False;
|
||||
|
||||
else
|
||||
{
|
||||
int i;
|
||||
remove_old_last_tag(selscreen);
|
||||
|
||||
for(i = seltag[selscreen]; i <= conf.ntag[selscreen]; i++)
|
||||
{
|
||||
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] + 1);
|
||||
}
|
||||
|
||||
tag_set(conf.ntag[selscreen]);
|
||||
tags[selscreen][seltag[selscreen]].stay_last = True;
|
||||
arrange(selscreen, True);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Transfert the selected client to
|
||||
* the wanted tag
|
||||
* \param cmd Wanted tag, uicb_t type
|
||||
@@ -171,3 +400,384 @@ uicb_tagtransfert(uicb_t cmd)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Set the previous selected tag
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_prev_sel(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
tag_set(prevseltag[selscreen]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Transfert the selected client to the next tag
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tagtransfert_next(uicb_t cmd)
|
||||
{
|
||||
CHECK(sel);
|
||||
int tag = seltag[selscreen] + 1;
|
||||
(void)cmd;
|
||||
|
||||
if(tag > conf.ntag[selscreen])
|
||||
{
|
||||
if(!conf.tag_round)
|
||||
return;
|
||||
tag = 1;
|
||||
}
|
||||
tag_transfert(sel, tag);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Transfert the selected client to the prev tag
|
||||
* \param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tagtransfert_prev(uicb_t cmd)
|
||||
{
|
||||
CHECK(sel);
|
||||
int tag = seltag[selscreen] - 1;
|
||||
(void)cmd;
|
||||
|
||||
if(tag <= 0)
|
||||
{
|
||||
if(!conf.tag_round)
|
||||
return;
|
||||
tag = conf.ntag[selscreen];
|
||||
}
|
||||
tag_transfert(sel, tag);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Go to the current urgent tag
|
||||
*\param cmd uicb_t type unused
|
||||
*/
|
||||
void
|
||||
uicb_tag_urgent(uicb_t cmd)
|
||||
{
|
||||
Client *c;
|
||||
Bool b = False;
|
||||
|
||||
(void)cmd;
|
||||
|
||||
/* Check if there is a urgent client */
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->flags & UrgentFlag)
|
||||
{
|
||||
b = True;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!b)
|
||||
return;
|
||||
|
||||
screen_set_sel(c->screen);
|
||||
tag_set(c->tag);
|
||||
client_focus(c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Add an additional tag to the current tag
|
||||
*\param sc Screen
|
||||
*\param tag Tag where apply additional tag
|
||||
*\param adtag Additional tag to apply in tag
|
||||
*/
|
||||
void
|
||||
tag_additional(int sc, int tag, int adtag)
|
||||
{
|
||||
if(tag < 0 || tag > conf.ntag[sc]
|
||||
|| adtag < 1 || adtag > conf.ntag[sc] || adtag == seltag[sc])
|
||||
return;
|
||||
|
||||
tags[sc][tag].tagad ^= TagFlag(adtag);
|
||||
tags[sc][adtag].request_update = True;
|
||||
arrange(sc, True);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Add an additional tag to the current tag
|
||||
*\param cmd uicb_t
|
||||
*/
|
||||
void
|
||||
uicb_tag_toggle_additional(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
|
||||
tag_additional(selscreen, seltag[selscreen], atoi(cmd));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Swap current tag with a specified tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_swap(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
|
||||
tag_swap(selscreen, seltag[selscreen], atoi(cmd));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Swap current tag with next tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_swap_next(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
/* Check if the next one does have the stay_last bool */
|
||||
if(!tags[selscreen][conf.ntag[selscreen]].stay_last)
|
||||
{
|
||||
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
warnx("The next tag is set to always stay the last one");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Swap current tag with previous tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_swap_previous(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
screen_get_sel();
|
||||
|
||||
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] - 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Adding a tag
|
||||
*\param s Screen number
|
||||
*\param name New tag name
|
||||
*/
|
||||
static void
|
||||
tag_new(int s, char *name)
|
||||
{
|
||||
char * displayedName;
|
||||
int goToTag;
|
||||
|
||||
if(conf.ntag[s] + 1 > MAXTAG)
|
||||
{
|
||||
warnx("Too many tag: Can't create new tag");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++conf.ntag[s];
|
||||
|
||||
/* TODO: memleak here */
|
||||
if(!name || strlen(name) == 0)
|
||||
{
|
||||
if(conf.tagnamecount)
|
||||
{
|
||||
/* displayedName = zmalloc(2); */
|
||||
xasprintf(&displayedName, "[%d]", conf.ntag[s]);
|
||||
}
|
||||
else
|
||||
displayedName = conf.default_tag.name;
|
||||
}
|
||||
else
|
||||
displayedName = xstrdup(name);
|
||||
|
||||
|
||||
Tag t = { displayedName, NULL, 0, 0,
|
||||
conf.default_tag.mwfact, conf.default_tag.nmaster,
|
||||
False, conf.default_tag.resizehint, False, False,
|
||||
conf.default_tag.barpos, conf.default_tag.barpos, conf.default_tag.layout,
|
||||
0, NULL, 0, False };
|
||||
|
||||
tags[s][conf.ntag[s]] = t;
|
||||
|
||||
/* For stay_last_tag */
|
||||
if(tags[s][conf.ntag[s]-1].stay_last)
|
||||
{
|
||||
tag_swap(s, conf.ntag[s], conf.ntag[s]-1);
|
||||
goToTag = conf.ntag[s]-1;
|
||||
}
|
||||
else
|
||||
goToTag = conf.ntag[s];
|
||||
|
||||
infobar_update_taglist(s);
|
||||
infobar_draw(s);
|
||||
tag_set(goToTag);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Adding a tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_new(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
|
||||
tag_new(selscreen, (char*)cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Delete a tag
|
||||
*\param s Screen number
|
||||
*\param tag Tag number
|
||||
*/
|
||||
static void
|
||||
tag_delete(int s, int tag)
|
||||
{
|
||||
Tag t;
|
||||
Client *c;
|
||||
size_t i;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
if(tag < 0 || tag > conf.ntag[s] || conf.ntag[s] == 1)
|
||||
return;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->screen == s && c->tag == (uint)tag)
|
||||
{
|
||||
warnx("Client(s) present in this tag, can't delete it");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
--conf.ntag[s];
|
||||
|
||||
tags[s][tag] = t;
|
||||
infobar[s].tags[tag] = NULL;
|
||||
|
||||
for(i = tag; i < (size_t)conf.ntag[s] + 1; ++i)
|
||||
{
|
||||
/* Set clients tag because of shift */
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->screen == s && c->tag == i + 1)
|
||||
c->tag = i;
|
||||
|
||||
/* shift */
|
||||
tags[s][i] = tags[s][i + 1];
|
||||
}
|
||||
|
||||
infobar[s].need_update = True;
|
||||
infobar_update_taglist(s);
|
||||
infobar_draw(s);
|
||||
|
||||
if(tag == seltag[s])
|
||||
tag_set(tag <= conf.ntag[s] ? tag : conf.ntag[s]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Delete a tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_del(uicb_t cmd)
|
||||
{
|
||||
int n;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
if(cmd == NULL || !(n = atoi(cmd)))
|
||||
n = seltag[selscreen];
|
||||
|
||||
tag_delete(selscreen, n);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Rename the selected tag
|
||||
*\param cmd uicb_t type
|
||||
*/
|
||||
void
|
||||
uicb_tag_rename(uicb_t cmd)
|
||||
{
|
||||
screen_get_sel();
|
||||
char *str;
|
||||
size_t len;
|
||||
|
||||
if(!cmd || !strlen(cmd))
|
||||
return;
|
||||
|
||||
str = tags[selscreen][seltag[selscreen]].name;
|
||||
len = strlen(str);
|
||||
|
||||
/* TODO: if strlen(cmd) > len, the tag name
|
||||
* will be truncated...
|
||||
* We can't do a realloc because if the pointer change
|
||||
* free() on paser will segfault.on free_conf()...
|
||||
*/
|
||||
strncpy(str, cmd, len);
|
||||
|
||||
infobar_update_taglist(selscreen);
|
||||
infobar_draw(selscreen);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
uicb_tag_toggle_expose(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
int i, j;
|
||||
|
||||
screen_get_sel();
|
||||
|
||||
for(i = 1; i <= conf.ntag[selscreen]; i++)
|
||||
{
|
||||
if(strcmp(tags[selscreen][i].name, conf.tag_expose_name) == 0)
|
||||
{
|
||||
if(clients && sel->tag)
|
||||
tag_set(sel->tag);
|
||||
|
||||
tag_delete(selscreen, i);
|
||||
|
||||
for(j = 0; j < conf.ntag[selscreen]; j++)
|
||||
tags[selscreen][j].request_update = True;
|
||||
|
||||
arrange(selscreen, True);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tag_new(selscreen, conf.tag_expose_name);
|
||||
|
||||
for(i = 0; i < conf.nlayout; ++i)
|
||||
{
|
||||
if(strcmp(conf.expose_layout, conf.layout[i].type) == 0)
|
||||
{
|
||||
tags[selscreen][conf.ntag[selscreen]].layout = conf.layout[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 1; i < conf.ntag[selscreen]; ++i)
|
||||
{
|
||||
tags[selscreen][conf.ntag[selscreen]].tagad ^= TagFlag(i);
|
||||
}
|
||||
|
||||
tags[selscreen][conf.ntag[selscreen]].request_update = True;
|
||||
arrange(selscreen, True);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
284
src/util.c
284
src/util.c
@@ -30,24 +30,103 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "wmfs.h"
|
||||
|
||||
/** Calloc with an error message if there is a probleme
|
||||
* \param element Element
|
||||
* \param size Size
|
||||
* \return void pointer
|
||||
*/
|
||||
void*
|
||||
emalloc(uint element, uint size)
|
||||
/** 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 = calloc(element, size);
|
||||
void *ret;
|
||||
|
||||
if(!ret)
|
||||
warn("calloc()");
|
||||
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;
|
||||
}
|
||||
|
||||
/** realloc with error support and size_t overflow check
|
||||
* \param ptr old pointer
|
||||
* \param nmemb number of objects
|
||||
* \param size size of single object
|
||||
* \return non null void pointer
|
||||
*/
|
||||
void *
|
||||
xrealloc(void *ptr, size_t nmemb, size_t size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (SIZE_MAX / nmemb < size)
|
||||
err(EXIT_FAILURE, "xrealloc(%p, %zu, %zu), "
|
||||
"size_t overflow detected", ptr, nmemb, size);
|
||||
|
||||
if ((ret = realloc(ptr, nmemb * size)) == NULL)
|
||||
err(EXIT_FAILURE, "realloc(%p, %zu)", ptr, nmemb * size);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
|
||||
/** Get a color with a string
|
||||
* \param color Color string
|
||||
* \return Color pixel
|
||||
@@ -63,21 +142,6 @@ getcolor(char *color)
|
||||
return xcolor.pixel;
|
||||
}
|
||||
|
||||
/** Enlight an hexadecimal color
|
||||
* \param col Color
|
||||
* \return The clarified color
|
||||
*/
|
||||
ulong
|
||||
color_enlight(ulong col)
|
||||
{
|
||||
if((col + 0x330000) < 0xffffff
|
||||
&& (col + 0x003300) < 0xffffff
|
||||
&& (col + 0x000033) < 0xffffff)
|
||||
return col + 0x333333;
|
||||
else
|
||||
return col;
|
||||
}
|
||||
|
||||
/** Set the window WM State
|
||||
* \param win Window target
|
||||
* \param state WM State
|
||||
@@ -93,25 +157,11 @@ setwinstate(Window win, long state)
|
||||
return;
|
||||
}
|
||||
|
||||
/** My strdup. the strdup of string.h isn't ansi compatible..
|
||||
* Thanks linkdd.
|
||||
* \param str char pointer
|
||||
*/
|
||||
char*
|
||||
_strdup(const char *str)
|
||||
{
|
||||
char *ret = emalloc(strlen(str) + 1, sizeof(char));
|
||||
|
||||
strcpy(ret, str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The following function are for configuration
|
||||
usage. {{{
|
||||
*/
|
||||
void*
|
||||
name_to_func(char *name, func_name_list_t *l)
|
||||
name_to_func(char *name, const func_name_list_t *l)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -150,7 +200,7 @@ char_to_button(char *name, name_to_uint_t blist[])
|
||||
}
|
||||
|
||||
Layout
|
||||
layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[])
|
||||
layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[])
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -160,84 +210,47 @@ layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[])
|
||||
|
||||
return lt[0];
|
||||
}
|
||||
|
||||
char*
|
||||
alias_to_str(char *conf_choice)
|
||||
{
|
||||
int i;
|
||||
char *tmpchar = NULL;
|
||||
|
||||
if(!conf_choice)
|
||||
return 0;
|
||||
|
||||
if(conf.alias)
|
||||
for(i = 0; conf.alias[i].name; i++)
|
||||
if(!strcmp(conf_choice, conf.alias[i].name))
|
||||
tmpchar = conf.alias[i].content;
|
||||
|
||||
if(tmpchar)
|
||||
return _strdup(tmpchar);
|
||||
else
|
||||
return _strdup(conf_choice);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/** Get the mouse pointer position.
|
||||
*/
|
||||
XRectangle
|
||||
get_mouse_pos(void)
|
||||
{
|
||||
Window dum;
|
||||
int d, u;
|
||||
XRectangle ret;
|
||||
|
||||
XQueryPointer(dpy, ROOT, &dum, &dum, (int*)&ret.x, (int*)&ret.y, &d, &d, (uint *)&u);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Execute a sh command
|
||||
* \param cmd Command
|
||||
* \return child pid
|
||||
*/
|
||||
void
|
||||
pid_t
|
||||
spawn(const char *format, ...)
|
||||
{
|
||||
char *sh = NULL;
|
||||
char cmd[512];
|
||||
va_list ap;
|
||||
|
||||
if(strlen(format) > 511)
|
||||
{
|
||||
warnx("spawn(): Error, command too long.");
|
||||
return;
|
||||
}
|
||||
pid_t pid;
|
||||
size_t len;
|
||||
|
||||
va_start(ap, format);
|
||||
vsprintf(cmd, format, ap);
|
||||
len = vsnprintf(cmd, sizeof(cmd), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(!strlen(cmd))
|
||||
return;
|
||||
if (len >= sizeof(cmd))
|
||||
{
|
||||
warnx("command too long (> 512 bytes)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!(sh = getenv("SHELL")))
|
||||
sh = "/bin/sh";
|
||||
|
||||
if(fork() == 0)
|
||||
if((pid = fork()) == 0)
|
||||
{
|
||||
if(fork() == 0)
|
||||
{
|
||||
if(dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
setsid();
|
||||
execl(sh, sh, "-c", cmd, (char*)NULL);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
if(dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
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;
|
||||
return pid;
|
||||
}
|
||||
|
||||
/** Swap two pointer.
|
||||
@@ -262,4 +275,79 @@ void
|
||||
uicb_spawn(uicb_t cmd)
|
||||
{
|
||||
spawn("%s", cmd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
/** Check images blocks in str and return properties
|
||||
* --> \i[x;y;w;h;name]\
|
||||
*\param im ImageAttr pointer, image properties
|
||||
*\param str String
|
||||
*\return n Lenght of i
|
||||
*/
|
||||
int
|
||||
parse_image_block(ImageAttr *im, char *str)
|
||||
{
|
||||
char as;
|
||||
int n, i, j, k;
|
||||
|
||||
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
|
||||
if(sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^]]]%c", &im[n].x, &im[n].y, &im[n].w, &im[n].h, im[n].name, &as) == 6
|
||||
&& as == '\\')
|
||||
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
|
||||
else if(j != i)
|
||||
str[j] = str[i];
|
||||
|
||||
for(k = j; k < i; str[k++] = 0);
|
||||
|
||||
return n;
|
||||
}
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
char*
|
||||
clean_value(char *str)
|
||||
{
|
||||
int i;
|
||||
char c, *p;
|
||||
|
||||
if(!str || !(p = xstrdup(str)))
|
||||
return NULL;
|
||||
|
||||
/* Remove useless spaces */
|
||||
for(; *p == ' '; ++p);
|
||||
for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0');
|
||||
|
||||
/* For string delimiter (" or ') */
|
||||
if(((c = *p) == '"' || (c = *p) == '\'') && strchr(p + 1, c))
|
||||
{
|
||||
for(++p, i = 0; p[i] && p[i] != c; ++i);
|
||||
p[i] = '\0';
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* To use ~/ shortcut.. */
|
||||
char*
|
||||
patht(char *path)
|
||||
{
|
||||
static char ret[512];
|
||||
|
||||
if(!path)
|
||||
return NULL;
|
||||
|
||||
strncpy(ret, path, sizeof(ret));
|
||||
ret[sizeof(ret) - 1] = 0;
|
||||
if(strstr(path, "~/"))
|
||||
snprintf(ret, sizeof(ret), "%s/%s", getenv("HOME"), path + 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
qsort_string_compare (const void * a, const void * b)
|
||||
{
|
||||
return (strcmp(*(char **)a, *(char **)b));
|
||||
}
|
||||
|
||||
|
||||
16
src/viwmfs.c
16
src/viwmfs.c
@@ -32,7 +32,7 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
vicmd_to_uicb vicmd[] =
|
||||
static vicmd_to_uicb vicmd[] =
|
||||
{
|
||||
{"r", "reload"},
|
||||
{"q", "quit"},
|
||||
@@ -49,6 +49,8 @@ vicmd_to_uicb vicmd[] =
|
||||
{"sp", "screen_prev"},
|
||||
{"cc", "client_kill"},
|
||||
{"ct", "tag_transfert"},
|
||||
{"ctn", "tag_transfert_next"},
|
||||
{"ctp", "tag_transfert_prev"},
|
||||
{"cn", "client_next"},
|
||||
{"cp", "client_prev"},
|
||||
{"csn", "client_swap_next"},
|
||||
@@ -60,10 +62,10 @@ vicmd_to_uicb vicmd[] =
|
||||
{"tf", "toggle_free"},
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
viwmfs_help(void)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
char s[20];
|
||||
|
||||
printf("ViWMFS commands list:\n");
|
||||
@@ -83,7 +85,7 @@ viwmfs_help(void)
|
||||
void
|
||||
viwmfs(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
char *cmd, str[256] = { 0 };
|
||||
Bool e;
|
||||
|
||||
@@ -92,7 +94,7 @@ viwmfs(int argc, char **argv)
|
||||
|
||||
if(argc > 3)
|
||||
{
|
||||
for(i = 2; i < argc; ++i)
|
||||
for(i = 2; i < (size_t)argc; ++i)
|
||||
{
|
||||
strcat(str, argv[i]);
|
||||
|
||||
@@ -101,7 +103,7 @@ viwmfs(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
else
|
||||
strcpy(str, argv[2]);
|
||||
strncpy(str, argv[2], sizeof(str));
|
||||
|
||||
if(!strcmp(str, "help"))
|
||||
{
|
||||
@@ -114,7 +116,7 @@ viwmfs(int argc, char **argv)
|
||||
{
|
||||
for(i = 0; i < strlen(str); str[i] = str[i + 1], ++i);
|
||||
|
||||
cmd = _strdup(str);
|
||||
cmd = xstrdup(str);
|
||||
|
||||
for(i = 0; cmd[i] && cmd[i] != ' '; ++i);
|
||||
cmd[i] = '\0';
|
||||
|
||||
238
src/wmfs.c
238
src/wmfs.c
@@ -32,11 +32,13 @@
|
||||
|
||||
#include "wmfs.h"
|
||||
|
||||
static volatile Bool exiting = False, sig_chld = False;
|
||||
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
int
|
||||
errorhandler(Display *d, XErrorEvent *event)
|
||||
{
|
||||
char mess[256];
|
||||
Client *c;
|
||||
|
||||
/* Check if there is another WM running */
|
||||
if(BadAccess == event->error_code
|
||||
@@ -48,7 +50,7 @@ errorhandler(Display *d, XErrorEvent *event)
|
||||
* 42 = X_SetInputFocus
|
||||
* 28 = X_GrabButton
|
||||
*/
|
||||
if((c = client_gb_win(event->resourceid)))
|
||||
if(client_gb_win(event->resourceid))
|
||||
if(event->error_code == BadWindow
|
||||
|| event->request_code == 42
|
||||
|| event->request_code == 28)
|
||||
@@ -68,6 +70,8 @@ errorhandler(Display *d, XErrorEvent *event)
|
||||
int
|
||||
errorhandlerdummy(Display *d, XErrorEvent *event)
|
||||
{
|
||||
(void)d;
|
||||
(void)event;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +81,7 @@ void
|
||||
quit(void)
|
||||
{
|
||||
Client *c;
|
||||
int i;
|
||||
size_t i, len;
|
||||
|
||||
/* Set the silent error handler */
|
||||
XSetErrorHandler(errorhandlerdummy);
|
||||
@@ -89,8 +93,10 @@ quit(void)
|
||||
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
|
||||
}
|
||||
|
||||
IFREE(tags);
|
||||
IFREE(seltag);
|
||||
free(tags);
|
||||
free(seltag);
|
||||
|
||||
systray_freeicons();
|
||||
|
||||
XftFontClose(dpy, font);
|
||||
for(i = 0; i < CurLast; ++i)
|
||||
@@ -98,92 +104,107 @@ quit(void)
|
||||
XFreeGC(dpy, gc_stipple);
|
||||
infobar_destroy();
|
||||
|
||||
IFREE(sgeo);
|
||||
IFREE(spgeo);
|
||||
IFREE(infobar);
|
||||
IFREE(keys);
|
||||
IFREE(func_list);
|
||||
IFREE(layout_list);
|
||||
IFREE(net_atom);
|
||||
free(sgeo);
|
||||
free(spgeo);
|
||||
free(infobar);
|
||||
free(keys);
|
||||
free(net_atom);
|
||||
|
||||
/* Clean conf alloced thing */
|
||||
IFREE(menulayout.item);
|
||||
free(menulayout.item);
|
||||
|
||||
if(conf.menu)
|
||||
{
|
||||
for(i = 0; i < LEN(conf.menu); ++i)
|
||||
IFREE(conf.menu[i].item);
|
||||
IFREE(conf.menu);
|
||||
len = LEN(conf.menu);
|
||||
for(i = 0; i < len; ++i)
|
||||
free(conf.menu[i].item);
|
||||
free(conf.menu);
|
||||
}
|
||||
|
||||
IFREE(conf.launcher);
|
||||
IFREE(conf.ntag);
|
||||
IFREE(conf.titlebar.mouse);
|
||||
for(i = 0; i < conf.titlebar.nbutton; ++i)
|
||||
{
|
||||
IFREE(conf.titlebar.button[i].mouse);
|
||||
IFREE(conf.titlebar.button[i].linecoord);
|
||||
}
|
||||
free(conf.launcher);
|
||||
free(conf.rule);
|
||||
|
||||
IFREE(conf.bars.mouse);
|
||||
IFREE(conf.titlebar.button);
|
||||
IFREE(conf.client.mouse);
|
||||
IFREE(conf.root.mouse);
|
||||
free(conf.bars.mouse);
|
||||
free(conf.selbar.mouse);
|
||||
free(conf.titlebar.button);
|
||||
free(conf.client.mouse);
|
||||
free(conf.root.mouse);
|
||||
|
||||
free_conf();
|
||||
|
||||
XSync(dpy, False);
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
/* kill status script */
|
||||
if (conf.status_pid != (pid_t)-1)
|
||||
kill(conf.status_pid, SIGTERM);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
thread_process(void *arg)
|
||||
static void
|
||||
wait_childs_and_status(void)
|
||||
{
|
||||
XEvent ev;
|
||||
int pid;
|
||||
|
||||
/* X event loop */
|
||||
if(!(int*)arg)
|
||||
{
|
||||
while(!exiting && !XNextEvent(dpy, &ev))
|
||||
getevent(ev);
|
||||
|
||||
pthread_exit(0);
|
||||
pthread_mutex_lock(&mtx);
|
||||
if (sig_chld) {
|
||||
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
|
||||
if (pid == conf.status_pid)
|
||||
conf.status_pid = -1;
|
||||
sig_chld = False;
|
||||
}
|
||||
pthread_mutex_unlock(&mtx);
|
||||
}
|
||||
|
||||
/* Status checking loop with timing */
|
||||
else
|
||||
static void *
|
||||
thread_status(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
int left = conf.status_timing;
|
||||
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
do
|
||||
{
|
||||
while(!exiting)
|
||||
{
|
||||
spawn(status_path);
|
||||
sleep(conf.status_timing);
|
||||
}
|
||||
wait_childs_and_status();
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
pthread_mutex_lock(&mtx);
|
||||
if (conf.status_pid == -1)
|
||||
conf.status_pid = spawn(conf.status_path);
|
||||
pthread_mutex_unlock(&mtx);
|
||||
|
||||
while ((left = sleep(left)) > 0);
|
||||
left = conf.status_timing;
|
||||
|
||||
} while (!exiting);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/** WMFS main loop.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
mainloop(void)
|
||||
{
|
||||
XEvent ev;
|
||||
pthread_t evloop, evstatus;
|
||||
void *ret;
|
||||
pthread_t th_status;
|
||||
|
||||
if(!estatus)
|
||||
while(!exiting && !XNextEvent(dpy, &ev))
|
||||
getevent(ev);
|
||||
else
|
||||
{
|
||||
pthread_create(&evloop, NULL, thread_process, "1");
|
||||
pthread_create(&evstatus, NULL, thread_process, NULL);
|
||||
|
||||
(void)pthread_join(evloop, &ret);
|
||||
(void)pthread_join(evstatus, &ret);
|
||||
if (estatus && conf.status_timing == 0)
|
||||
conf.status_pid = spawn(conf.status_path);
|
||||
else if (estatus && pthread_create(&th_status, NULL, thread_status, NULL) != 0) {
|
||||
warnx("pthread_create");
|
||||
estatus = False;
|
||||
}
|
||||
|
||||
while (!exiting && !XNextEvent(dpy, &ev)) {
|
||||
getevent(ev);
|
||||
wait_childs_and_status();
|
||||
}
|
||||
|
||||
if (estatus)
|
||||
pthread_join(th_status, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,6 +216,7 @@ mainloop(void)
|
||||
void
|
||||
uicb_quit(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
exiting = True;
|
||||
|
||||
return;
|
||||
@@ -203,40 +225,43 @@ uicb_quit(uicb_t cmd)
|
||||
/** Scan if there are windows on X
|
||||
* for manage it
|
||||
*/
|
||||
void
|
||||
static void
|
||||
scan(void)
|
||||
{
|
||||
uint i, n;
|
||||
uint n;
|
||||
XWindowAttributes wa;
|
||||
Window usl, usl2, *w = NULL;
|
||||
Atom rt;
|
||||
int rf, tag = -1, screen = -1, free = -1;
|
||||
int s, rf, tag = -1, screen = -1, free = -1, i;
|
||||
ulong ir, il;
|
||||
uchar *ret;
|
||||
Client *c;
|
||||
|
||||
s = screen_count();
|
||||
|
||||
if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n))
|
||||
for(i = n - 1; i != -1; --i)
|
||||
if(XGetWindowAttributes(dpy, w[i], &wa)
|
||||
&& !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl))
|
||||
&& wa.map_state == IsViewable)
|
||||
{
|
||||
XGetWindowAttributes(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)
|
||||
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)
|
||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
screen = *ret;
|
||||
XFree(ret);
|
||||
}
|
||||
|
||||
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_ISFREE"), 0, 32,
|
||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
|
||||
{
|
||||
free = *ret;
|
||||
XFree(ret);
|
||||
@@ -244,25 +269,26 @@ scan(void)
|
||||
|
||||
c = client_manage(w[i], &wa, False);
|
||||
|
||||
if(tag != -1)
|
||||
if(tag != -1 && tag != MAXTAG + 1)
|
||||
c->tag = tag;
|
||||
if(screen != -1 && screen <= screen_count() - 1)
|
||||
if(screen != -1 && screen <= s - 1)
|
||||
c->screen = screen;
|
||||
if(free != -1)
|
||||
c->flags |= (free) ? FreeFlag : 0;
|
||||
|
||||
client_update_attributes(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set update layout request */
|
||||
for(c = clients; c; c = c->next)
|
||||
{
|
||||
if(c->tag > conf.ntag[c->screen])
|
||||
if(c->tag > (uint)conf.ntag[c->screen])
|
||||
c->tag = conf.ntag[c->screen];
|
||||
tags[c->screen][c->tag].request_update = True;
|
||||
}
|
||||
|
||||
for(i = 0; i < screen_count(); ++i)
|
||||
for(i = 0; i < s; ++i)
|
||||
arrange(i, True);
|
||||
|
||||
XFree(w);
|
||||
@@ -276,11 +302,13 @@ scan(void)
|
||||
void
|
||||
uicb_reload(uicb_t cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
quit();
|
||||
|
||||
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
|
||||
|
||||
execlp(argv_global, argv_global, NULL);
|
||||
/* add -C to always load the same config file */
|
||||
execvp(argv_global, all_argv);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -322,15 +350,11 @@ check_wmfs_running(void)
|
||||
void
|
||||
exec_uicb_function(char *func, char *cmd)
|
||||
{
|
||||
long data[5];
|
||||
|
||||
/* Check if wmfs is running (this function is executed when wmfs
|
||||
is already running normally...) */
|
||||
if(!check_wmfs_running())
|
||||
return;
|
||||
|
||||
data[4] = True;
|
||||
|
||||
XChangeProperty(dpy, ROOT, ATOM("_WMFS_FUNCTION"), ATOM("UTF8_STRING"),
|
||||
8, PropModeReplace, (uchar*)func, strlen(func));
|
||||
|
||||
@@ -340,7 +364,7 @@ exec_uicb_function(char *func, char *cmd)
|
||||
XChangeProperty(dpy, ROOT, ATOM("_WMFS_CMD"), ATOM("UTF8_STRING"),
|
||||
8, PropModeReplace, (uchar*)cmd, strlen(cmd));
|
||||
|
||||
send_client_event(data, "_WMFS_FUNCTION");
|
||||
ewmh_send_message(ROOT, ROOT, "_WMFS_FUNCTION", 0, 0, 0, 0, True);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -348,15 +372,12 @@ exec_uicb_function(char *func, char *cmd)
|
||||
/** Set statustext
|
||||
*\param str Statustext string
|
||||
*/
|
||||
void
|
||||
static void
|
||||
set_statustext(int s, char *str)
|
||||
{
|
||||
int i;
|
||||
long data[5];
|
||||
char atom_name[64];
|
||||
|
||||
data[4] = True;
|
||||
|
||||
if(!str)
|
||||
return;
|
||||
|
||||
@@ -369,7 +390,7 @@ set_statustext(int s, char *str)
|
||||
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
|
||||
8, PropModeReplace, (uchar*)str, strlen(str));
|
||||
|
||||
send_client_event(data, atom_name);
|
||||
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -379,7 +400,7 @@ set_statustext(int s, char *str)
|
||||
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
|
||||
8, PropModeReplace, (uchar*)str, strlen(str));
|
||||
|
||||
send_client_event(data, atom_name);
|
||||
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -387,29 +408,32 @@ set_statustext(int s, char *str)
|
||||
|
||||
/** Update status script by ewmh hint
|
||||
*/
|
||||
void
|
||||
static void
|
||||
update_status(void)
|
||||
{
|
||||
long data[5];
|
||||
|
||||
if(!check_wmfs_running())
|
||||
return;
|
||||
|
||||
data[4] = True;
|
||||
|
||||
send_client_event(data, "_WMFS_UPDATE_STATUS");
|
||||
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_STATUS", 0, 0, 0, 0, True);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** Signal handle function
|
||||
*/
|
||||
void
|
||||
static void
|
||||
signal_handle(int sig)
|
||||
{
|
||||
exiting = True;
|
||||
quit();
|
||||
exit(EXIT_SUCCESS);
|
||||
switch (sig)
|
||||
{
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
exiting = True;
|
||||
break;
|
||||
case SIGCHLD:
|
||||
sig_chld = True;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -424,8 +448,12 @@ main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *ol = "csgVS";
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
struct sigaction sa;
|
||||
|
||||
argv_global = _strdup(argv[0]);
|
||||
argv_global = xstrdup(argv[0]);
|
||||
all_argv = argv;
|
||||
sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME"));
|
||||
|
||||
while((i = getopt(argc, argv, "hviSc:s:g:C:V:")) != -1)
|
||||
@@ -458,11 +486,7 @@ main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
printf("WMFS version : "WMFS_VERSION"\n"
|
||||
" Compilation settings :\n"
|
||||
" - Flags : "WMFS_COMPILE_FLAGS"\n"
|
||||
" - Linked Libs : "WMFS_LINKED_LIBS"\n"
|
||||
" - On "WMFS_COMPILE_MACHINE" by "WMFS_COMPILE_BY".\n");
|
||||
printf("WMFS "WMFS_VERSION"\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
|
||||
@@ -473,11 +497,11 @@ main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
strcpy(conf.confpath, optarg);
|
||||
strncpy(conf.confpath, optarg, sizeof(conf.confpath));
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
exec_uicb_function(argv[2], ((argv[3]) ? argv[3] : NULL));
|
||||
exec_uicb_function(optarg, argv[optind]);
|
||||
XCloseDisplay(dpy);
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
@@ -509,8 +533,12 @@ main(int argc, char **argv)
|
||||
errx(EXIT_FAILURE, "cannot open X server.");
|
||||
|
||||
/* Set signal handler */
|
||||
(void)signal(SIGTERM, &signal_handle);
|
||||
(void)signal(SIGINT, &signal_handle);
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = signal_handle;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGQUIT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
|
||||
/* Check if an other WM is already running; set the error handler */
|
||||
XSetErrorHandler(errorhandler);
|
||||
|
||||
185
src/wmfs.h
185
src/wmfs.h
@@ -38,8 +38,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
#include <dirent.h>
|
||||
@@ -49,14 +52,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xft/Xft.h>
|
||||
|
||||
/* Local headers */
|
||||
#include "confparse/confparse.h"
|
||||
#include "config.h"
|
||||
#include "parse.h"
|
||||
#include "structs.h"
|
||||
|
||||
/* Optional dependencies */
|
||||
@@ -68,6 +71,10 @@
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif /* HAVE_XRANDR */
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
#include <Imlib2.h>
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
/* MACRO */
|
||||
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
|
||||
#define MouseMask (ButtonMask | PointerMotionMask)
|
||||
@@ -79,14 +86,14 @@
|
||||
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font->height * 1.5))
|
||||
#define FHINFOBAR ((font->height - font->descent) + (INFOBARH - font->height) / 2)
|
||||
#define SHADH (1)
|
||||
#define SHADC (0x000000) /* 'Cause i don't know how darken a color yet */
|
||||
#define BORDH conf.client.borderheight
|
||||
#define TBARH ((conf.titlebar.height < BORDH) ? BORDH : conf.titlebar.height)
|
||||
#define RESHW (6 * BORDH)
|
||||
#define RESHW (6 * (BORDH))
|
||||
#define BUTTONWH (TBARH / 2)
|
||||
#define DEF_CONF ".config/wmfs/wmfsrc"
|
||||
#define DEF_STATUS ".config/wmfs/status.sh"
|
||||
#define PAD conf.pad
|
||||
#define MAXSTATUS (4096)
|
||||
|
||||
#define CWIN(win, parent, x, y, w, h, b, mask, col, at) \
|
||||
do { \
|
||||
@@ -100,8 +107,8 @@
|
||||
#define FRAMEH(h) ((h) + (BORDH + TBARH))
|
||||
#define ROUND(x) (float)((x > 0) ? x + (float)0.5 : x - (float)0.5)
|
||||
#define CHECK(x) if(!(x)) return
|
||||
#define IFREE(x) if(x) free(x)
|
||||
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define MAXCLIST (64)
|
||||
|
||||
/* barwin.c */
|
||||
BarWindow *barwin_create(Window parent,
|
||||
@@ -112,6 +119,8 @@ BarWindow *barwin_create(Window parent,
|
||||
Bool stipple,
|
||||
Bool border);
|
||||
void barwin_draw_text(BarWindow *bw, int x, int y, char *text);
|
||||
void barwin_draw_image_ofset_text(BarWindow *bw, int x, int y, char *text, int x_image_ofset, int y_image_ofset);
|
||||
void barwin_color_set(BarWindow *bw, uint bg, char *fg);
|
||||
void barwin_delete(BarWindow *bw);
|
||||
void barwin_delete_subwin(BarWindow *bw);
|
||||
void barwin_map(BarWindow *bw);
|
||||
@@ -124,28 +133,30 @@ void barwin_refresh_color(BarWindow *bw);
|
||||
void barwin_refresh(BarWindow *bw);
|
||||
|
||||
/* draw.c */
|
||||
void draw_text(Drawable d, int x, int y, char* fg, int pad, char *str);
|
||||
void draw_text(Drawable d, int x, int y, char* fg, char *str);
|
||||
void draw_image_ofset_text(Drawable d, int x, int y, char* fg, char *str, int x_image_ofset, int y_image_ofset);
|
||||
void draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color);
|
||||
ushort textw(const char *text);
|
||||
void draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data);
|
||||
|
||||
ushort textw(char *text);
|
||||
|
||||
/* infobar.c */
|
||||
void infobar_init(void);
|
||||
void infobar_draw(int sc);
|
||||
void infobar_draw_layout(int sc);
|
||||
void infobar_draw_selbar(int sc);
|
||||
void infobar_draw_taglist(int sc);
|
||||
void infobar_draw_statustext(int sc, char *str);
|
||||
void infobar_update_taglist(int sc);
|
||||
void infobar_destroy(void);
|
||||
void infobar_set_position(int pos);
|
||||
void uicb_infobar_togglepos(uicb_t);
|
||||
void uicb_infobar_toggledisplay(uicb_t);
|
||||
void uicb_toggle_tagautohide(uicb_t);
|
||||
|
||||
/* client.c */
|
||||
void client_attach(Client *c);
|
||||
void client_configure(Client *c);
|
||||
void client_detach(Client *c);
|
||||
void client_above(Client *c);
|
||||
void client_focus(Client *c);
|
||||
Client* client_get_next(void);
|
||||
Client* client_get_prev(void);
|
||||
/* client_gb_*() {{{ */
|
||||
Client* client_gb_win(Window w);
|
||||
Client* client_gb_frame(Window w);
|
||||
@@ -166,29 +177,41 @@ void client_size_hints(Client *c);
|
||||
void client_swap(Client *c1, Client *c2);
|
||||
void client_raise(Client *c);
|
||||
void client_unhide(Client *c);
|
||||
void client_focus_next(Client *c);
|
||||
void client_unmanage(Client *c);
|
||||
void client_unmap(Client *c);
|
||||
void client_set_wanted_tag(Client *c);
|
||||
void client_update_attributes(Client *c);
|
||||
void client_urgent(Client *c, Bool u);
|
||||
void uicb_client_raise(uicb_t);
|
||||
void uicb_client_next(uicb_t);
|
||||
void uicb_client_prev(uicb_t);
|
||||
void uicb_client_swap_next(uicb_t);
|
||||
void uicb_client_swap_prev(uicb_t);
|
||||
void uicb_client_focus_right(uicb_t cmd);
|
||||
void uicb_client_focus_left(uicb_t cmd);
|
||||
void uicb_client_focus_top(uicb_t cmd);
|
||||
void uicb_client_focus_bottom(uicb_t cmd);
|
||||
void uicb_client_kill(uicb_t);
|
||||
void uicb_client_screen_next(uicb_t);
|
||||
void uicb_client_screen_prev(uicb_t);
|
||||
void uicb_client_screen_set(uicb_t);
|
||||
void uicb_client_move(uicb_t cmd);
|
||||
void uicb_client_resize(uicb_t cmd);
|
||||
void uicb_ignore_next_client_rules(uicb_t cmd);
|
||||
void uicb_clientlist(uicb_t cmd);
|
||||
Bool uicb_checkclist(uicb_t);
|
||||
void uicb_client_ignore_tag(uicb_t);
|
||||
void uicb_client_set_master(uicb_t);
|
||||
|
||||
/* ewmh.c */
|
||||
void ewmh_init_hints(void);
|
||||
void ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4);
|
||||
long ewmh_get_xembed_state(Window win);
|
||||
void ewmh_get_number_of_desktop(void);
|
||||
void ewmh_update_current_tag_prop(void);
|
||||
void ewmh_get_client_list(void);
|
||||
void ewmh_get_desktop_names(void);
|
||||
void ewmh_set_desktop_geometry(void);
|
||||
void ewmh_set_workarea(void);
|
||||
void ewmh_manage_net_wm_state(long data_l[], Client *c);
|
||||
void ewmh_manage_window_type(Client *c);
|
||||
|
||||
@@ -196,70 +219,64 @@ void ewmh_manage_window_type(Client *c);
|
||||
void frame_create(Client *c);
|
||||
void frame_delete(Client *c);
|
||||
void frame_moveresize(Client *c, XRectangle geo);
|
||||
void frame_update_color(Client *c, Bool focused);
|
||||
void frame_update(Client *c);
|
||||
|
||||
/* config.c */
|
||||
void init_conf(void);
|
||||
|
||||
/* color.c */
|
||||
uint color_shade(uint, double);
|
||||
|
||||
/* event.c */
|
||||
void buttonpress(XButtonEvent *ev);
|
||||
void configureevent(XConfigureRequestEvent *ev);
|
||||
void clientmessageevent(XClientMessageEvent *ev);
|
||||
void destroynotify(XDestroyWindowEvent *ev);
|
||||
void enternotify(XCrossingEvent *ev);
|
||||
void expose(XExposeEvent *ev);
|
||||
void focusin(XFocusChangeEvent *ev);
|
||||
void grabkeys(void);
|
||||
void keypress(XKeyPressedEvent *ev);
|
||||
void mappingnotify(XMappingEvent *ev);
|
||||
void maprequest(XMapRequestEvent *ev);
|
||||
void propertynotify(XPropertyEvent *ev);
|
||||
void unmapnotify(XUnmapEvent *ev);
|
||||
void send_client_event(long data[5], char *atom_name);
|
||||
void getevent(XEvent ev);
|
||||
|
||||
/* menu.c */
|
||||
void menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n);
|
||||
void menu_new_item(MenuItem *mi, char *name, void *func, char *cmd);
|
||||
void menu_draw(Menu menu, int x, int y);
|
||||
Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]);
|
||||
void menu_focus_item(Menu *menu, int item, BarWindow *winitem[]);
|
||||
void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[]);
|
||||
int menu_get_longer_string(MenuItem *mt, int nitem);
|
||||
void uicb_menu(uicb_t cmd);
|
||||
void menu_clear(Menu *menu);
|
||||
|
||||
/* launcher.c */
|
||||
void launcher_execute(Launcher launcher);
|
||||
void uicb_launcher(uicb_t);
|
||||
|
||||
/* mouse.c */
|
||||
void mouse_dragborder(XRectangle geo, GC g);
|
||||
void mouse_move_tile_client(Client **c);
|
||||
void mouse_move_tag_client(Client *c);
|
||||
void mouse_move(Client *c);
|
||||
void mouse_resize(Client *c);
|
||||
void mouse_grabbuttons(Client *c, Bool focused);
|
||||
void uicb_mouse_move(uicb_t);
|
||||
void uicb_mouse_resize(uicb_t);
|
||||
|
||||
/* util.c */
|
||||
ulong color_enlight(ulong col);
|
||||
void *emalloc(uint element, uint size);
|
||||
void *xmalloc(size_t, size_t);
|
||||
void *xcalloc(size_t, size_t);
|
||||
void *xrealloc(void *, size_t, size_t);
|
||||
/* simples wrappers for allocating only one object */
|
||||
#define zmalloc(size) xmalloc(1, (size))
|
||||
#define zcalloc(size) xcalloc(1, (size))
|
||||
#define zrealloc(ptr, size) xrealloc((ptr), 1, (size))
|
||||
char *xstrdup(const char *);
|
||||
int xasprintf(char **, const char *, ...);
|
||||
long getcolor(char *color);
|
||||
void setwinstate(Window win, long state);
|
||||
char* _strdup(char const *str);
|
||||
/* Conf usage {{{ */
|
||||
void* name_to_func(char *name, func_name_list_t *l);
|
||||
void* name_to_func(char *name, const func_name_list_t *l);
|
||||
ulong char_to_modkey(char *name, key_name_list_t key_l[]);
|
||||
uint char_to_button(char *name, name_to_uint_t blist[]);
|
||||
Layout layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[]);
|
||||
char* alias_to_str(char *conf_choice);
|
||||
Layout layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[]);
|
||||
/* }}} */
|
||||
XRectangle get_mouse_pos(void);
|
||||
char *char_to_str(const char c);
|
||||
void spawn(const char *str, ...);
|
||||
pid_t spawn(const char *str, ...);
|
||||
void swap_ptr(void **x, void **y);
|
||||
void uicb_spawn(uicb_t);
|
||||
char *clean_value(char *str);
|
||||
char* patht(char *path);
|
||||
int qsort_string_compare (const void * a, const void * b);
|
||||
|
||||
#ifdef HAVE_IMLIB
|
||||
int parse_image_block(ImageAttr *im, char *str);
|
||||
#endif /* HAVE_IMLIB */
|
||||
|
||||
/* tag.c */
|
||||
void tag_set(int tag);
|
||||
@@ -267,7 +284,24 @@ void tag_transfert(Client *c, int tag);
|
||||
void uicb_tag(uicb_t);
|
||||
void uicb_tag_next(uicb_t);
|
||||
void uicb_tag_prev(uicb_t);
|
||||
void uicb_tag_next_visible(uicb_t);
|
||||
void uicb_tag_prev_visible(uicb_t);
|
||||
void uicb_tagtransfert(uicb_t);
|
||||
void uicb_tag_prev_sel(uicb_t);
|
||||
void uicb_tagtransfert_next(uicb_t);
|
||||
void uicb_tagtransfert_prev(uicb_t);
|
||||
void uicb_tag_urgent(uicb_t cmd);
|
||||
void tag_additional(int sc, int tag, int adtag);
|
||||
void uicb_tag_toggle_additional(uicb_t);
|
||||
void uicb_tag_swap(uicb_t);
|
||||
void uicb_tag_swap_next(uicb_t);
|
||||
void uicb_tag_swap_previous(uicb_t);
|
||||
void uicb_tag_new(uicb_t);
|
||||
void uicb_tag_del(uicb_t);
|
||||
void uicb_tag_rename(uicb_t cmd);
|
||||
void uicb_tag_last(uicb_t cmd);
|
||||
void uicb_tag_stay_last(uicb_t cmd);
|
||||
void uicb_tag_toggle_expose(uicb_t cmd);
|
||||
|
||||
/* screen.c */
|
||||
int screen_count(void);
|
||||
@@ -279,22 +313,35 @@ void screen_init_geo(void);
|
||||
void uicb_screen_select(uicb_t);
|
||||
void uicb_screen_next(uicb_t);
|
||||
void uicb_screen_prev(uicb_t);
|
||||
void uicb_screen_prev_sel(uicb_t);
|
||||
|
||||
/* status.c */
|
||||
void statustext_handle(int sc, char *str);
|
||||
|
||||
/* systray.c */
|
||||
Bool systray_acquire(void);
|
||||
void systray_add(Window win);
|
||||
void systray_del(Systray *s);
|
||||
void systray_state(Systray *s);
|
||||
void systray_freeicons(void);
|
||||
Systray* systray_find(Window win);
|
||||
int systray_get_width(void);
|
||||
void systray_update(void);
|
||||
|
||||
/* layout.c */
|
||||
void arrange(int screen, Bool update_layout);
|
||||
void freelayout(int screen);
|
||||
void layoutswitch(Bool b);
|
||||
void maxlayout(int screen);
|
||||
Client *tiled_client(int screen, Client *c);
|
||||
/* tile {{{ */
|
||||
void grid(int screen);
|
||||
void tile(int screen);
|
||||
void tile_left(int screen);
|
||||
void tile_top(int screen);
|
||||
void tile_bottom(int screen);
|
||||
void mirror_vertical(int screen);
|
||||
void mirror_horizontal(int screen);
|
||||
void layer(int screen);
|
||||
void grid_vertical(int screen);
|
||||
void grid_horizontal(int screen);
|
||||
/* }}} */
|
||||
void uicb_togglemax(uicb_t);
|
||||
void uicb_togglefree(uicb_t);
|
||||
@@ -305,27 +352,15 @@ void uicb_set_nmaster(uicb_t);
|
||||
void uicb_set_layout(uicb_t);
|
||||
void uicb_toggle_resizehint(uicb_t);
|
||||
void uicb_toggle_abovefc(uicb_t cmd);
|
||||
void uicb_set_layer(uicb_t cmd);
|
||||
void uicb_set_client_layer(uicb_t cmd);
|
||||
void layout_set_client_master(Client *c);
|
||||
Bool uicb_checkmax(uicb_t);
|
||||
Bool uicb_checkfree(uicb_t);
|
||||
Bool uicb_checklayout(uicb_t);
|
||||
|
||||
/* init.c */
|
||||
void init(void);
|
||||
void init_root(void);
|
||||
void init_layout(void);
|
||||
void init_font(void);
|
||||
void init_gc(void);
|
||||
void init_cursor(void);
|
||||
void init_key(void);
|
||||
void init_geometry(void);
|
||||
void init_status(void);
|
||||
|
||||
/* getinfo.c */
|
||||
void getinfo_tag(void);
|
||||
void getinfo_screen(void);
|
||||
void getinfo_layout(void);
|
||||
void getinfo_mwfact(void);
|
||||
void getinfo_nmaster(void);
|
||||
void getinfo(char *info);
|
||||
|
||||
/* viwmfs.c */
|
||||
@@ -336,12 +371,8 @@ int errorhandler(Display *d, XErrorEvent *event);
|
||||
int errorhandlerdummy(Display *d, XErrorEvent *event);
|
||||
void quit(void);
|
||||
void *thread_process(void *arg);
|
||||
void mainloop(void);
|
||||
void scan(void);
|
||||
Bool check_wmfs_running(void);
|
||||
void exec_uicb_function(char *func, char *cmd);
|
||||
void set_statustext(int s, char *str);
|
||||
void update_status(void);
|
||||
void handle_signal(int signum);
|
||||
void uicb_quit(uicb_t);
|
||||
void uicb_reload(uicb_t);
|
||||
@@ -352,13 +383,15 @@ void uicb_reload(uicb_t);
|
||||
Display *dpy;
|
||||
GC gc, gc_stipple;
|
||||
int selscreen;
|
||||
int prevselscreen;
|
||||
Conf conf;
|
||||
Key *keys;
|
||||
Bool exiting, estatus;
|
||||
Bool estatus;
|
||||
XRectangle *sgeo;
|
||||
XRectangle *spgeo;
|
||||
Cursor cursor[CurLast];
|
||||
char *argv_global, *status_path;
|
||||
char *argv_global;
|
||||
char **all_argv;
|
||||
int xrandr_event;
|
||||
uint timing;
|
||||
|
||||
@@ -367,21 +400,33 @@ XftFont *font;
|
||||
|
||||
/* Atoms list */
|
||||
Atom *net_atom;
|
||||
Atom trayatom;
|
||||
|
||||
/* InfoBar/Tags */
|
||||
InfoBar *infobar;
|
||||
Tag **tags;
|
||||
int *seltag;
|
||||
int *prevseltag;
|
||||
Menu menulayout;
|
||||
|
||||
/* ClientList */
|
||||
Menu clientlist;
|
||||
struct clndx {
|
||||
char key[4];
|
||||
Client *client;
|
||||
} clist_index[MAXCLIST];
|
||||
|
||||
/* Important Client */
|
||||
Client *clients;
|
||||
Client *sel;
|
||||
|
||||
/* Other */
|
||||
func_name_list_t *func_list;
|
||||
func_name_list_t *layout_list;
|
||||
extern const func_name_list_t func_list[];
|
||||
extern const func_name_list_t layout_list[];
|
||||
uint numlockmask;
|
||||
Systray *trayicons;
|
||||
Window traywin;
|
||||
int tray_width;
|
||||
|
||||
#endif /* WMFS_H */
|
||||
|
||||
|
||||
8
wmfs.1
8
wmfs.1
@@ -62,7 +62,7 @@ Print help information, then exit\&.
|
||||
.PP
|
||||
\fB\-i\fR
|
||||
.RS 4
|
||||
Print WMFS informations
|
||||
Print WMFS information
|
||||
.RE
|
||||
.SH "DEFAULT KEY BINDINGS"
|
||||
.PP
|
||||
@@ -143,7 +143,7 @@ Increase the nmaster (+1)\fR
|
||||
.PP
|
||||
\fBAlt\-Shift + d\fR
|
||||
.RS 4
|
||||
Decrease the nmaster (-1)\fR
|
||||
Decrease the nmaster (\-1)\fR
|
||||
.RE
|
||||
.PP
|
||||
\fBAlt + t\fR
|
||||
@@ -163,7 +163,7 @@ Make a launcher in the infobar to run an unix command\fR
|
||||
.PP
|
||||
\fBAlt + Escape\fR
|
||||
.RS 4
|
||||
Set WMFS in ViWMFS mode. (see wmfs -V)\fR
|
||||
Set WMFS in ViWMFS mode. (see wmfs \-V)\fR
|
||||
.RE
|
||||
.PP
|
||||
\fBAlt\-Shift + p\fR
|
||||
@@ -193,7 +193,7 @@ Martin Duquesnoy <\fIxorg62@gmail\&.com\fR\&[1]>\&.
|
||||
Main site: \fIhttp://wmfs\&.info\fR Bug tracker: \fIhttp://bugs\&.wmfs\&.info\fR
|
||||
.sp
|
||||
.SH "COPYING"
|
||||
WMFS is under the BSD license\&. See COPYING for more informations\&.
|
||||
WMFS is under the BSD license\&. See COPYING for more information\&.
|
||||
.sp
|
||||
.SH "NOTES"
|
||||
.IP " 1." 4
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[Desktop Entry]
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Name=wmfs
|
||||
Comment=Window manager from scratch
|
||||
TryExec=wmfs
|
||||
Exec=wmfs
|
||||
Comment=Window Manager From Scratch
|
||||
Exec=ck-launch-session wmfs
|
||||
|
||||
@@ -73,7 +73,7 @@ WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = @SOURCE_DIR@/src
|
||||
INPUT = src
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.h \
|
||||
455
wmfsrc
Normal file
455
wmfsrc
Normal file
@@ -0,0 +1,455 @@
|
||||
#
|
||||
# This is the default wmfs config file, copy it to
|
||||
# ~/.config/wmfs/wmfsrc and edit it.
|
||||
#
|
||||
|
||||
# Include file to split configuration
|
||||
# @include "~/.config/wmfs/menu-wmfsrc"
|
||||
|
||||
[misc]
|
||||
font = "dejavu-10"
|
||||
raisefocus = true
|
||||
raiseswitch = false
|
||||
focus_follow_mouse = true
|
||||
focus_follow_movement = false
|
||||
opacity = 255
|
||||
|
||||
# focus_pointer_click: click on unfocused client area:
|
||||
# true -- default, set focus
|
||||
# false -- click go to client; including dockapps
|
||||
focus_pointer_click = true
|
||||
status_timing = 1 #seconds
|
||||
# status_path = "~/.config/wmfs/status.sh"
|
||||
[/misc]
|
||||
|
||||
[bar]
|
||||
bg = "#191919"
|
||||
fg = "#D4D4D4"
|
||||
border = true
|
||||
#height = "-1"
|
||||
|
||||
light_shade = 0.10
|
||||
dark_shade = -0.10
|
||||
|
||||
[systray]
|
||||
# Enable/disable systray
|
||||
active = true
|
||||
|
||||
# Screen of systray
|
||||
screen = 0
|
||||
|
||||
# Spacing between tray icons
|
||||
spacing = 3
|
||||
[/systray]
|
||||
|
||||
# Remove this section to disable the selbar.
|
||||
[selbar]
|
||||
bg = "#191919"
|
||||
fg = "#D4D4ff"
|
||||
|
||||
# Cut title length
|
||||
# max_length = 25
|
||||
|
||||
[mouse] button = "3" func = "clientlist" [/mouse]
|
||||
[mouse] button = "4" func = "client_next" [/mouse]
|
||||
[mouse] button = "5" func = "client_prev" [/mouse]
|
||||
[/selbar]
|
||||
|
||||
[/bar]
|
||||
|
||||
[layouts]
|
||||
fg = "#191919"
|
||||
bg = "#7E89A2"
|
||||
|
||||
# Border around the layout button.
|
||||
border = true
|
||||
|
||||
# Value menu or switch.
|
||||
system = "menu"
|
||||
|
||||
# Value left or right.
|
||||
placement = "right"
|
||||
|
||||
# Keep layout geo for free layout
|
||||
keep_layout_geo = false
|
||||
|
||||
# Symbol displayed for the selected layout in the list
|
||||
selected_layout_symbol = "*"
|
||||
|
||||
# Width of layout button
|
||||
# layout_button_width = x
|
||||
|
||||
# Tiling layouts.
|
||||
[layout] type = "tile_right" symbol = "RIGHT" [/layout]
|
||||
[layout] type = "tile_left" symbol = "LEFT" [/layout]
|
||||
[layout] type = "tile_top" symbol = "TOP" [/layout]
|
||||
[layout] type = "tile_bottom" symbol = "BOTTOM" [/layout]
|
||||
[layout] type = "tile_grid" symbol = "GRID_H" [/layout]
|
||||
[layout] type = "tile_grid_vertical" symbol = "GRID_V" [/layout]
|
||||
[layout] type = "mirror_vertical" symbol = "MIRROR_V" [/layout]
|
||||
[layout] type = "mirror_horizontal" symbol = "MIRROR_H" [/layout]
|
||||
|
||||
# Other layouts.
|
||||
[layout] type = "max" symbol = "MAX" [/layout]
|
||||
[layout] type = "free" symbol = "FREE" [/layout]
|
||||
|
||||
[/layouts]
|
||||
|
||||
[tags]
|
||||
[default_tag]
|
||||
name = "new tag"
|
||||
mwfact = 0.5
|
||||
nmaster = 1
|
||||
layout = "tile_right"
|
||||
resizehint = false
|
||||
infobar_position = "top"
|
||||
[/default_tag]
|
||||
|
||||
# whether client_next on the last tag will send you on the first
|
||||
# and client_prev on the first tag will send you on the last one
|
||||
tag_round = false
|
||||
|
||||
# Going twice on the same tag will bring you back on the previous one
|
||||
tag_auto_prev = true
|
||||
|
||||
occupied_bg = "#003366"
|
||||
occupied_fg = "#D4D4D4"
|
||||
sel_fg = "#191919"
|
||||
sel_bg = "#7E89A2"
|
||||
urgent_bg = "#DD1111"
|
||||
urgent_fg = "#000000"
|
||||
|
||||
# If true, number of the tag will be used for name
|
||||
name_count = false
|
||||
#default_name = "new tag" # deprecated, use [default_tag] instead
|
||||
#default_layout = "tile_right" # deprecated, use [default_tag] instead
|
||||
|
||||
expose_name = "EXPOSE"
|
||||
expose_layout = "tile_left"
|
||||
|
||||
# Border around the tag buttons.
|
||||
border = true
|
||||
|
||||
# Hide empty tags in tag list
|
||||
autohide = true
|
||||
|
||||
# Mouse buttons action on tag.
|
||||
mouse_button_tag_sel = "1"
|
||||
mouse_button_tag_transfert = "2"
|
||||
mouse_button_tag_add = "3"
|
||||
mouse_button_tag_next = "4"
|
||||
mouse_button_tag_prev = "5"
|
||||
|
||||
[tag]
|
||||
name = "one"
|
||||
screen = 0
|
||||
mwfact = 0.65
|
||||
nmaster = 1
|
||||
layout = "tile_right"
|
||||
resizehint = false
|
||||
infobar_position = "top"
|
||||
above_fc = false
|
||||
#[mouse] [/mouse] Possible multi mouse section
|
||||
[/tag]
|
||||
|
||||
# clients option is *DEPRECATED* but works, see [rules] section
|
||||
[tag] name = "two" clients = {"Browser"} [/tag]
|
||||
[tag] name = "three" [/tag]
|
||||
[tag] name = "four" [/tag]
|
||||
[tag] name = "five" [/tag]
|
||||
[tag] name = "six" [/tag]
|
||||
[tag] name = "seven" [/tag]
|
||||
[tag] name = "eight" [/tag]
|
||||
[tag] name = "nine" [/tag]
|
||||
[/tags]
|
||||
|
||||
[root]
|
||||
# Command you can execute to set the background.
|
||||
background_command = "xsetroot -solid black"
|
||||
|
||||
[mouse] button = "4" func = "tag_next" [/mouse]
|
||||
[mouse] button = "5" func = "tag_prev" [/mouse]
|
||||
[mouse] button = "3" func = "menu" cmd = "rootmenu" [/mouse]
|
||||
[/root]
|
||||
|
||||
[client]
|
||||
client_round = true
|
||||
client_auto_center = false
|
||||
border_height = 3
|
||||
border_shadow = true
|
||||
border_normal = "#191919"
|
||||
border_focus = "#003366"
|
||||
place_at_mouse = false
|
||||
resize_corner_normal = "#191919"
|
||||
resize_corner_focus = "#003366"
|
||||
set_new_win_master = true
|
||||
client_tile_raise = false
|
||||
new_client_get_mouse = false
|
||||
|
||||
# send all client that have no tag rule in this default tag
|
||||
#default_open_tag = 4
|
||||
# same as above but for the screen
|
||||
#default_open_screen = 1
|
||||
|
||||
# Space between tiled clients
|
||||
padding = 0
|
||||
|
||||
# Modifier for mouse use
|
||||
modifier = "Alt"
|
||||
|
||||
light_shade = 0.10
|
||||
dark_shade = -0.10
|
||||
|
||||
# *DEPRECATED* but works, see [rules] section
|
||||
# Set automatic free or max client
|
||||
# autofree = "xterm|MPlayer"
|
||||
# automax = "Navigator"
|
||||
|
||||
[mouse] button = "1" func = "client_raise" [/mouse]
|
||||
[mouse] button = "1" func = "mouse_move" [/mouse]
|
||||
[mouse] button = "3" func = "client_raise" [/mouse]
|
||||
[mouse] button = "3" func = "mouse_resize" [/mouse]
|
||||
|
||||
# Remove this section to delete the titlebar.
|
||||
[titlebar]
|
||||
stipple = false
|
||||
height = 12
|
||||
fg_normal = "#7E89A2"
|
||||
fg_focus = "#9F9AB3"
|
||||
|
||||
[mouse] button = "1" func = "client_raise" [/mouse]
|
||||
[mouse] button = "1" func = "mouse_move" [/mouse]
|
||||
[mouse] button = "3" func = "client_raise" [/mouse]
|
||||
[mouse] button = "3" func = "mouse_resize" [/mouse]
|
||||
|
||||
[button]
|
||||
# Available "free", "max", "tile" flags or button.
|
||||
flags = "free,max,tile"
|
||||
[mouse] button = "1" func = "client_kill" [/mouse]
|
||||
[mouse] button = "3" func = "menu" cmd = "clientmenu" [/mouse]
|
||||
|
||||
[line] coord = {1, 1, 4, 1} [/line]
|
||||
[line] coord = {1, 1, 1, 4} [/line]
|
||||
[line] coord = {1, 4, 4, 4} [/line]
|
||||
[/button]
|
||||
[/titlebar]
|
||||
[/client]
|
||||
|
||||
[rules]
|
||||
# Example of rule for MPlayer
|
||||
[rule]
|
||||
instance = "xv" # First part of WM_CLASS
|
||||
class = "MPlayer" # Seconf part of WM_CLASS, not needed if first part is correct
|
||||
# role = "" # WM_WINDOW_ROLE
|
||||
screen = 0 # Screen to use
|
||||
tag = 2 # Tag number of apps
|
||||
free = true # Set automatic free client
|
||||
max = false # Set automatic maximized client
|
||||
follow_client = false # follow the client
|
||||
ignore_tags = false # ignore tag (free mode)
|
||||
[/rule]
|
||||
[/rules]
|
||||
|
||||
[menu]
|
||||
# Default menu, binded on the root window, button 3.
|
||||
[set_menu]
|
||||
name = "rootmenu"
|
||||
|
||||
# place_at_mouse = false
|
||||
# x = 40 y = 50
|
||||
|
||||
# Available "center", "left", "right" menu align. Default: "center".
|
||||
align = "left"
|
||||
|
||||
fg_focus = "#191919" bg_focus = "#7E89A2"
|
||||
fg_normal = "#9F9AB3" bg_normal = "#191919"
|
||||
|
||||
[item] name = "Terminal" func = "spawn" cmd = "urxvt || xterm || gnome-terminal" [/item]
|
||||
[item] name = "Applications" submenu = "appmenu" [/item]
|
||||
[item] name = "Next tag" func = "tag_next" [/item]
|
||||
[item] name = "Previous tag" func = "tag_prev" [/item]
|
||||
[item] name = "Next layout" func = "layout_next" [/item]
|
||||
[item] name = "Previous layout" func = "layout_prev" [/item]
|
||||
[item] name = "Toggle infobar" func = "toggle_infobar_position" [/item]
|
||||
[item] name = "Quit WMFS" func = "quit" [/item]
|
||||
[/set_menu]
|
||||
|
||||
[set_menu]
|
||||
name = "appmenu"
|
||||
align = "left"
|
||||
|
||||
fg_focus = "#191919" bg_focus = "#7E89A2"
|
||||
fg_normal = "#9F9AB3" bg_normal = "#191919"
|
||||
|
||||
[item] name = "Browser" func = "spawn" cmd = "firefox" [/item]
|
||||
[item] name = "Calculator" func = "spawn" cmd = "xcalc" [/item]
|
||||
[/set_menu]
|
||||
|
||||
[set_menu]
|
||||
name = "clientmenu"
|
||||
|
||||
fg_focus = "#D4D4D4" bg_focus = "#003366"
|
||||
fg_normal = "#D4D4D4" bg_normal = "#191919"
|
||||
|
||||
# Check items: possible 'check_max' or 'check_free'.
|
||||
[item] name = "Close" func = "client_kill" [/item]
|
||||
[item] name = "Maximize" func = "toggle_max" check = "check_max" [/item]
|
||||
[item] name = "Free" func = "toggle_free" check = "check_free" [/item]
|
||||
[/set_menu]
|
||||
[/menu]
|
||||
|
||||
[launcher]
|
||||
[set_launcher]
|
||||
# Limit size of the launcher window (px)
|
||||
width_limit = 300
|
||||
|
||||
name = "launcher_exec"
|
||||
prompt = "Exec: "
|
||||
command = "exec"
|
||||
[/set_launcher]
|
||||
|
||||
#ViWMFS : manage wmfs with vi-based command.
|
||||
[set_launcher]
|
||||
name = "viwmfs"
|
||||
prompt = "> "
|
||||
command = "wmfs -V"
|
||||
[/set_launcher]
|
||||
[/launcher]
|
||||
|
||||
[keys]
|
||||
# Reload the configuration of wmfs.
|
||||
[key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key]
|
||||
|
||||
# Open a terminal.
|
||||
[key] mod = {"Control"} key = "Return" func = "spawn" cmd = "xterm" [/key]
|
||||
|
||||
# Kill the selected client.
|
||||
[key] mod = {"Alt"} key = "q" func = "client_kill" [/key]
|
||||
|
||||
# Quit wmfs.
|
||||
[key] mod = {"Control", "Alt", "Shift"} key = "q" func = "quit" [/key]
|
||||
|
||||
# Swap current client with the next.
|
||||
[key] mod = {"Alt"} key = "t" func = "client_swap_next" [/key]
|
||||
|
||||
# Swap current client with the previous.
|
||||
[key] mod = {"Alt", "Shift"} key = "t" func = "client_swap_prev" [/key]
|
||||
|
||||
# Set the selected client as Master
|
||||
[key] mod = {"Control"} key = "m" func = "client_set_master" [/key]
|
||||
|
||||
# Toggle maximum the selected client
|
||||
[key] mod = {"Alt"} key = "m" func = "toggle_max" [/key]
|
||||
|
||||
# Toggle free the selected client.
|
||||
[key] mod = {"Alt"} key = "f" func = "toggle_free" [/key]
|
||||
|
||||
# Toggle the position of the infobar.
|
||||
[key] mod = {"Alt"} key = "b" func = "toggle_infobar_position" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "b" func = "toggle_infobar_display" [/key]
|
||||
|
||||
# Toggle the resizehint of the current tag/screen
|
||||
[key] mod = {"Shift", "Control"} key = "r" func = "toggle_resizehint" [/key]
|
||||
|
||||
# Toggle the tag_autohide mode
|
||||
[key] mod = {"Shift", "Control"} key = "t" func = "toggle_tagautohide" [/key]
|
||||
|
||||
# Select the next client.
|
||||
[key] mod = {"Alt"} key = "Tab" func = "client_next" [/key]
|
||||
|
||||
# Select the previous client.
|
||||
[key] mod = {"Alt","Shift"} key = "Tab" func = "client_prev" [/key]
|
||||
|
||||
# Select the next tag.
|
||||
[key] mod = {"Control"} key = "Right" func = "tag_next" [/key]
|
||||
|
||||
# Select the previous tag.
|
||||
[key] mod = {"Control"} key = "Left" func = "tag_prev" [/key]
|
||||
|
||||
# Select the next visible tag.
|
||||
[key] mod = {"Control","Alt"} key = "Right" func = "tag_next_visible" [/key]
|
||||
|
||||
# Select the previous visible tag.
|
||||
[key] mod = {"Control","Alt"} key = "Left" func = "tag_prev_visible" [/key]
|
||||
|
||||
# Set the next layout.
|
||||
[key] mod = {"Alt"} key = "space" func = "layout_next" [/key]
|
||||
|
||||
# Set the previous layout.
|
||||
[key] mod = {"Alt", "Shift"} key = "space" func = "layout_prev" [/key]
|
||||
|
||||
# Increase mwfact.
|
||||
[key] mod = {"Alt"} key = "l" func = "set_mwfact" cmd = "+0.025" [/key]
|
||||
|
||||
# Decrease mwfact.
|
||||
[key] mod = {"Alt"} key = "h" func = "set_mwfact" cmd = "-0.025" [/key]
|
||||
|
||||
# Increase nmaster.
|
||||
[key] mod = {"Alt"} key = "d" func = "set_nmaster" cmd = "+1" [/key]
|
||||
|
||||
# Decease nmaster.
|
||||
[key] mod = {"Alt", "Shift"} key = "d" func = "set_nmaster" cmd = "-1" [/key]
|
||||
|
||||
#Launcher.
|
||||
[key] mod = {"Alt"} key = "p" func = "launcher" cmd = "launcher_exec" [/key]
|
||||
|
||||
#ViWMFS
|
||||
[key] mod = {"Alt"} key = "Escape" func = "launcher" cmd = "viwmfs" [/key]
|
||||
|
||||
# Set the tag x.
|
||||
[key] mod = {"Alt"} key = "F1" func = "tag" cmd = "1" [/key]
|
||||
[key] mod = {"Alt"} key = "F2" func = "tag" cmd = "2" [/key]
|
||||
[key] mod = {"Alt"} key = "F3" func = "tag" cmd = "3" [/key]
|
||||
[key] mod = {"Alt"} key = "F4" func = "tag" cmd = "4" [/key]
|
||||
[key] mod = {"Alt"} key = "F5" func = "tag" cmd = "5" [/key]
|
||||
[key] mod = {"Alt"} key = "F6" func = "tag" cmd = "6" [/key]
|
||||
[key] mod = {"Alt"} key = "F7" func = "tag" cmd = "7" [/key]
|
||||
[key] mod = {"Alt"} key = "F8" func = "tag" cmd = "8" [/key]
|
||||
[key] mod = {"Alt"} key = "F9" func = "tag" cmd = "9" [/key]
|
||||
|
||||
# Transfert selected client to x.
|
||||
[key] mod = {"Alt", "Shift"} key = "F1" func = "tag_transfert" cmd ="1" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F2" func = "tag_transfert" cmd ="2" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F3" func = "tag_transfert" cmd ="3" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F4" func = "tag_transfert" cmd ="4" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F5" func = "tag_transfert" cmd ="5" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F6" func = "tag_transfert" cmd ="6" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F7" func = "tag_transfert" cmd ="7" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F8" func = "tag_transfert" cmd ="8" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F9" func = "tag_transfert" cmd ="9" [/key]
|
||||
|
||||
# Toggle additional tags (x) on the current tag
|
||||
[key] mod = {"Alt", "Super"} key = "F1" func = "tag_toggle_additional" cmd ="1" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F2" func = "tag_toggle_additional" cmd ="2" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F3" func = "tag_toggle_additional" cmd ="3" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F4" func = "tag_toggle_additional" cmd ="4" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F5" func = "tag_toggle_additional" cmd ="5" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F6" func = "tag_toggle_additional" cmd ="6" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F7" func = "tag_toggle_additional" cmd ="7" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F8" func = "tag_toggle_additional" cmd ="8" [/key]
|
||||
[key] mod = {"Alt", "Super"} key = "F9" func = "tag_toggle_additional" cmd ="9" [/key]
|
||||
|
||||
# change screen
|
||||
[key] mod = {"Super"} key = "Tab" func = "screen_next" [/key]
|
||||
[key] mod = {"Super", "Shift"} key = "Tab" func = "screen_prev" [/key]
|
||||
|
||||
# swap client in the next/prev screen
|
||||
[key] mod = {"Super", "Shift"} key = "a" func = "client_screen_next" [/key]
|
||||
[key] mod = {"Super", "Shift"} key = "z" func = "client_screen_prev" [/key]
|
||||
|
||||
[key] mod = {"Alt"} key = "e" func = "toggle_tag_expose" [/key]
|
||||
|
||||
# unlisted fonctions that can be used in [key] func = ""
|
||||
# client_focus_{right, left, top, bottom}
|
||||
# client_ignore_tag # Toggle the client in ignore_tag (display the client on all tags)
|
||||
# tag_prev_sel # go back to the previous selected tag
|
||||
# tag_transfert_{next, prev}
|
||||
# tag_urgent # go to the urgent tag
|
||||
# tag_swap_{next, prev} # swap tag with the previous/next one
|
||||
# tag_last # go to the last tag
|
||||
# tag_stay_last # toggle the current tag as the last one
|
||||
# toggle_abovefc
|
||||
# screen_prev_sel # go to the previous screen selected
|
||||
# set_layout # set layout. need to be called with cmd = "<layout_name>"
|
||||
# ignore_next_client_rules # ignore the rule the next time a rule is called
|
||||
[/keys]
|
||||
256
wmfsrc.in
256
wmfsrc.in
@@ -1,256 +0,0 @@
|
||||
#
|
||||
# This is the default wmfs config file, copy it to
|
||||
# ~/.config/wmfs/wmfsrc and edit it.
|
||||
#
|
||||
|
||||
[misc]
|
||||
font = "dejavu-10"
|
||||
raisefocus = false
|
||||
focus_follow_mouse = true
|
||||
[/misc]
|
||||
|
||||
[bar]
|
||||
bg = "#191919"
|
||||
fg = "#D4D4D4"
|
||||
border = true
|
||||
[/bar]
|
||||
|
||||
[layouts]
|
||||
fg = "#191919"
|
||||
bg = "#7E89A2"
|
||||
|
||||
# Border around the layout button.
|
||||
border = true
|
||||
|
||||
# Value menu or switch.
|
||||
system = "menu"
|
||||
|
||||
# Tiling layouts.
|
||||
[layout] type = "tile_right" symbol = "RIGHT" [/layout]
|
||||
[layout] type = "tile_left" symbol = "LEFT" [/layout]
|
||||
[layout] type = "tile_top" symbol = "TOP" [/layout]
|
||||
[layout] type = "tile_bottom" symbol = "BOTTOM" [/layout]
|
||||
[layout] type = "tile_grid" symbol = "GRID" [/layout]
|
||||
[layout] type = "mirror_vertical" symbol = "MIRROR_V" [/layout]
|
||||
[layout] type = "mirror_horizontal" symbol = "MIRROR_H" [/layout]
|
||||
|
||||
# Other layouts.
|
||||
[layout] type = "max" symbol = "MAX" [/layout]
|
||||
[layout] type = "free" symbol = "FREE" [/layout]
|
||||
|
||||
[/layouts]
|
||||
|
||||
[tags]
|
||||
tag_round = false
|
||||
occupied_bg = "#003366"
|
||||
sel_fg = "#191919"
|
||||
sel_bg = "#7E89A2"
|
||||
|
||||
# Border around the tag buttons.
|
||||
border = true
|
||||
|
||||
[tag]
|
||||
name = "one"
|
||||
screen = 0
|
||||
mwfact = 0.65
|
||||
nmaster = 1
|
||||
layout = "tile_right"
|
||||
resizehint = false
|
||||
infobar_position = "top"
|
||||
[/tag]
|
||||
|
||||
[tag] name = "two" clients = {"Browser"} [/tag]
|
||||
[tag] name = "three" [/tag]
|
||||
[tag] name = "four" [/tag]
|
||||
[tag] name = "five" [/tag]
|
||||
[tag] name = "six" [/tag]
|
||||
[tag] name = "seven" [/tag]
|
||||
[tag] name = "eight" [/tag]
|
||||
[tag] name = "nine" [/tag]
|
||||
[/tags]
|
||||
|
||||
[root]
|
||||
# Command you can execute to set the background.
|
||||
background_command = "xsetroot -solid black"
|
||||
|
||||
[mouse] button = "4" func = "tag_next" [/mouse]
|
||||
[mouse] button = "5" func = "tag_prev" [/mouse]
|
||||
[mouse] button = "3" func = "menu" cmd = "rootmenu" [/mouse]
|
||||
[/root]
|
||||
|
||||
[client]
|
||||
border_height = 3
|
||||
border_shadow = true
|
||||
border_normal = "#191919"
|
||||
border_focus = "#003366"
|
||||
resize_corner_normal = "#191919"
|
||||
resize_corner_focus = "#003366"
|
||||
|
||||
modifier = "Alt"
|
||||
|
||||
[mouse] button = "1" func = "client_raise" [/mouse]
|
||||
[mouse] button = "1" func = "mouse_move" [/mouse]
|
||||
[mouse] button = "3" func = "client_raise" [/mouse]
|
||||
[mouse] button = "3" func = "mouse_resize" [/mouse]
|
||||
|
||||
# Remove this section to delete the titlebar.
|
||||
[titlebar]
|
||||
stipple = false
|
||||
height = 12
|
||||
fg_normal = "#7E89A2"
|
||||
fg_focus = "#9F9AB3"
|
||||
|
||||
[mouse] button = "1" func = "client_raise" [/mouse]
|
||||
[mouse] button = "1" func = "mouse_move" [/mouse]
|
||||
[mouse] button = "3" func = "client_raise" [/mouse]
|
||||
[mouse] button = "3" func = "mouse_resize" [/mouse]
|
||||
|
||||
[button]
|
||||
[mouse] button = "1" func = "client_kill" [/mouse]
|
||||
[mouse] button = "3" func = "menu" cmd = "clientmenu" [/mouse]
|
||||
|
||||
[line] coord = {1, 1, 4, 1} [/line]
|
||||
[line] coord = {1, 1, 1, 4} [/line]
|
||||
[line] coord = {1, 4, 4, 4} [/line]
|
||||
[/button]
|
||||
[/titlebar]
|
||||
[/client]
|
||||
|
||||
[menu]
|
||||
# Default menu, binded on the root window, button 3.
|
||||
[set_menu]
|
||||
name = "rootmenu"
|
||||
|
||||
# place_at_mouse = false
|
||||
# x = 40 y = 50
|
||||
|
||||
fg_focus = "#191919" bg_focus = "#7E89A2"
|
||||
fg_normal = "#9F9AB3" bg_normal = "#191919"
|
||||
|
||||
[item] name = "Terminal" func = "spawn" cmd = "@WMFS_TERM@" [/item]
|
||||
[item] name = "Next tag" func = "tag_next" [/item]
|
||||
[item] name = "Previous tag" func = "tag_prev" [/item]
|
||||
[item] name = "Next layout" func = "layout_next" [/item]
|
||||
[item] name = "Previous layout" func = "layout_prev" [/item]
|
||||
[item] name = "Toggle infobar" func = "toggle_infobar_position" [/item]
|
||||
[item] name = "Quit WMFS" func = "quit" [/item]
|
||||
[/set_menu]
|
||||
|
||||
[set_menu]
|
||||
name = "clientmenu"
|
||||
|
||||
fg_focus = "#D4D4D4" bg_focus = "#003366"
|
||||
fg_normal = "#D4D4D4" bg_normal = "#191919"
|
||||
|
||||
[item] name = "Close" func = "client_kill" [/item]
|
||||
[item] name = "Maximize" func = "toggle_max" [/item]
|
||||
[item] name = "Free" func = "toggle_free" [/item]
|
||||
[/set_menu]
|
||||
[/menu]
|
||||
|
||||
[launcher]
|
||||
[set_launcher]
|
||||
name = "launcher_exec"
|
||||
prompt = "Exec: "
|
||||
command = "exec"
|
||||
[/set_launcher]
|
||||
|
||||
#ViWMFS : manage wmfs with vi-based command.
|
||||
[set_launcher]
|
||||
name = "viwmfs"
|
||||
prompt = "> "
|
||||
command = "wmfs -V"
|
||||
[/set_launcher]
|
||||
[/launcher]
|
||||
|
||||
[keys]
|
||||
# Reload the configuration of wmfs.
|
||||
[key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key]
|
||||
|
||||
# Open a terminal.
|
||||
[key] mod = {"Control"} key = "Return" func = "spawn" cmd = "@WMFS_TERM@" [/key]
|
||||
|
||||
# Kill the selected client.
|
||||
[key] mod = {"Alt"} key = "q" func = "client_kill" [/key]
|
||||
|
||||
# Quit wmfs.
|
||||
[key] mod = {"Control", "Alt", "Shift"} key = "q" func = "quit" [/key]
|
||||
|
||||
# Swap current client with the next.
|
||||
[key] mod = {"Alt"} key = "t" func = "client_swap_next" [/key]
|
||||
|
||||
# Swap current client with the previous.
|
||||
[key] mod = {"Alt", "Shift"} key = "t" func = "client_swap_prev" [/key]
|
||||
|
||||
# Toggle maximum the selected client
|
||||
[key] mod = {"Alt"} key = "m" func = "toggle_max" [/key]
|
||||
|
||||
# Toggle free the selected client.
|
||||
[key] mod = {"Alt"} key = "f" func = "toggle_free" [/key]
|
||||
|
||||
# Toggle the position of the infobar.
|
||||
[key] mod = {"Alt"} key = "b" func = "toggle_infobar_position" [/key]
|
||||
|
||||
# Toggle the resizehint of the current tag/screen
|
||||
[key] mod = {"Shift", "Control"} key = "r" func = "toggle_resizehint" [/key]
|
||||
|
||||
# Select the next client.
|
||||
[key] mod = {"Alt"} key = "Tab" func = "client_next" [/key]
|
||||
|
||||
# Select the previous client.
|
||||
[key] mod = {"Alt","Shift"} key = "Tab" func = "client_prev" [/key]
|
||||
|
||||
# Select the next tag.
|
||||
[key] mod = {"Control"} key = "Right" func = "tag_next" [/key]
|
||||
|
||||
# Select the previous tag.
|
||||
[key] mod = {"Control"} key = "Left" func = "tag_prev" [/key]
|
||||
|
||||
# Set the next layout.
|
||||
[key] mod = {"Alt"} key = "space" func = "layout_next" [/key]
|
||||
|
||||
# Set the previous layout.
|
||||
[key] mod = {"Alt", "Shift"} key = "space" func = "layout_prev" [/key]
|
||||
|
||||
# Increase mwfact.
|
||||
[key] mod = {"Alt"} key = "l" func = "set_mwfact" cmd = "+0.025" [/key]
|
||||
|
||||
# Decrease mwfact.
|
||||
[key] mod = {"Alt"} key = "h" func = "set_mwfact" cmd = "-0.025" [/key]
|
||||
|
||||
# Increase nmaster.
|
||||
[key] mod = {"Alt"} key = "d" func = "set_nmaster" cmd = "+1" [/key]
|
||||
|
||||
# Decease nmaster.
|
||||
[key] mod = {"Alt", "Shift"} key = "d" func = "set_nmaster" cmd = "-1" [/key]
|
||||
|
||||
#Launcher.
|
||||
[key] mod = {"Alt"} key = "p" func = "launcher" cmd = "launcher_exec" [/key]
|
||||
|
||||
#ViWMFS
|
||||
[key] mod = {"Alt"} key = "Escape" func = "launcher" cmd = "viwmfs" [/key]
|
||||
|
||||
# Set the tag x.
|
||||
[key] mod = {"Alt"} key = "F1" func = "tag" cmd = "1" [/key]
|
||||
[key] mod = {"Alt"} key = "F2" func = "tag" cmd = "2" [/key]
|
||||
[key] mod = {"Alt"} key = "F3" func = "tag" cmd = "3" [/key]
|
||||
[key] mod = {"Alt"} key = "F4" func = "tag" cmd = "4" [/key]
|
||||
[key] mod = {"Alt"} key = "F5" func = "tag" cmd = "5" [/key]
|
||||
[key] mod = {"Alt"} key = "F6" func = "tag" cmd = "6" [/key]
|
||||
[key] mod = {"Alt"} key = "F7" func = "tag" cmd = "7" [/key]
|
||||
[key] mod = {"Alt"} key = "F8" func = "tag" cmd = "8" [/key]
|
||||
[key] mod = {"Alt"} key = "F9" func = "tag" cmd = "9" [/key]
|
||||
|
||||
# Transfert selected client to x.
|
||||
[key] mod = {"Alt", "Shift"} key = "F1" func = "tag_transfert" cmd ="1" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F2" func = "tag_transfert" cmd ="2" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F3" func = "tag_transfert" cmd ="3" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F4" func = "tag_transfert" cmd ="4" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F5" func = "tag_transfert" cmd ="5" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F6" func = "tag_transfert" cmd ="6" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F7" func = "tag_transfert" cmd ="7" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F8" func = "tag_transfert" cmd ="8" [/key]
|
||||
[key] mod = {"Alt", "Shift"} key = "F9" func = "tag_transfert" cmd ="9" [/key]
|
||||
[/keys]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user