150 Commits

Author SHA1 Message Date
Philippe Pepiot
b9e67982f8 Fix possible leak in parse.c. Fixes #149
If stat() fail and open() worked, file wasn't closed

Reported-by: mlq <mlq@pwmt.org>
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-11-01 14:02:53 +01:00
Philippe Pepiot
0400fb5454 Wait childs in main loop, fixes #142 Signed-off-by: Philippe Pepiot <phil@philpep.org> 2011-11-01 14:02:46 +01:00
Martin Duquesnoy
a7371e9445 Client/Event: Fix focus issue & client manual moving to next screen segfault 2011-10-27 19:06:54 +02:00
Martin Duquesnoy
a3a2f33ddf Event: Use MAX_EV instead of dynamic handle_event size: fix multi-head possible segfault 2011-09-01 17:43:58 +02:00
Martin Duquesnoy
13d8a0acc8 Infobar: Add Infobar element: see elements_order in [bar] 2011-08-04 18:43:51 +02:00
Martin Duquesnoy
02cd7d91e9 Event: Simplify layout switch 2011-08-04 10:36:42 +02:00
Martin Duquesnoy
71f4b9df89 Event: Replace ugly consecutive if by do_mousebind function 2011-08-04 10:25:59 +02:00
Martin Duquesnoy
8f040ed7a4 Wmfs: Add INAREA macro to replace ugly ifs 2011-08-04 09:53:58 +02:00
Martin Duquesnoy
e5a804cee8 Selbar: Dynamic selbar position is back 2011-08-04 09:18:32 +02:00
Martin Duquesnoy
48bdc94538 Infobar: Improve selbar render: draw it on infobar barwin directly 2011-08-04 09:00:24 +02:00
Martin Duquesnoy
a501bd1127 Merge branch 'master' of git.wmfs.info:wmfs 2011-08-03 20:17:22 +02:00
Philippe Pepiot
ec5b71b371 Build System: Freetype only when use Xft
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-08-03 20:15:13 +02:00
Joris van Zwieten
5e2bcf03d6 Fix segfault on selbar de-allocation. fixes #138 2011-08-03 20:04:16 +02:00
Martin Duquesnoy
fb04cef137 Infobar: Use pointer in infobar_init 2011-08-03 06:44:58 +02:00
Martin Duquesnoy
acffbdc188 Infobar: fix selbar (above statustext) 2011-08-03 06:26:47 +02:00
Martin Duquesnoy
b42c42245a Wmfs: Fix warnings 2011-08-03 06:17:07 +02:00
Martin Duquesnoy
570a3f0e64 Draw: Add bool arg to parse_image_block to don't save mouse bind at textw call 2011-08-01 23:38:03 +02:00
Martin Duquesnoy
39080f9952 Status: Use InfoBar* instead of win in StatusMouse struct 2011-08-01 23:26:51 +02:00
Philippe Pepiot
8958dbfe70 BuildSystem: Add xft support for old build system fixes #139 2011-08-01 13:52:40 +02:00
Martin Duquesnoy
84d30e25e2 Status: securize if in statustext_mouse 2011-07-31 19:03:23 +02:00
Martin Duquesnoy
31d875c438 Status: Allow void command argument in mouse action sequence 2011-07-31 18:57:20 +02:00
Martin Duquesnoy
c1fcd0dac7 Status: Multi (;;) dynamic mouse section possible 2011-07-31 16:06:39 +02:00
Martin Duquesnoy
8344b1cc82 Status: Dynamic mouse action: new format \b[x;y;w;h;col;(1;spawn;xterm)]\ (last arg of sequences b,s and i 2011-07-31 14:43:09 +02:00
Martin Duquesnoy
92831181e7 Status: Dynamic mouse bind with text sequence: (button;func;cmd)\s[1;10;#ffffff;clickable text]\ 2011-07-30 17:53:09 +02:00
Martin Duquesnoy
1934aa713d Status: Add dynamic mouse bind: (1;spawn;xterm)\b[;;;;]\ = clickable rectangle 2011-07-30 17:40:39 +02:00
Martin Duquesnoy
bbf11ac274 Wmfs: Fix help line 2011-07-29 17:51:39 +02:00
Martin Duquesnoy
2ec2bf4760 Barwin: Replace simple functions by macros 2011-07-29 17:48:06 +02:00
Martin Duquesnoy
08d55605da Code: cosmetic + warning fix 2011-07-29 17:19:09 +02:00
Martin Duquesnoy
69ec9d7db0 Apply pierreN patch: _NET_WM_NAME attribute in rules 2011-07-29 17:17:21 +02:00
Martin Duquesnoy
9c3130a17c BarWindow/Event: Make barwindows linked to improve render with expose event 2011-07-29 11:53:22 +02:00
Martin Duquesnoy
4e2459318c Init: init trayicons head 2011-07-29 10:55:05 +02:00
Martin Duquesnoy
58f6f674ca WMFS: Use SLIST from sys/queue.h instead homemade linked list 2011-07-29 10:54:08 +02:00
Martin Duquesnoy
5d80ec8538 Barwin: Remove useless check and fix wmfsrc 2011-07-28 09:54:23 +02:00
Martin Duquesnoy
7e33c322ff Wmfs: Remove unused var 2011-07-28 09:35:17 +02:00
Martin Duquesnoy
d1f5acf938 Util: Remove unused function 2011-07-28 09:34:16 +02:00
Martin Duquesnoy
6ed013fc7c Wmfs: Remove update_status and option 2011-07-28 00:10:36 +02:00
Martin Duquesnoy
4e33bc9bf7 Status: Remove status management (status_path, status_timing, threading), use loop in status script now (see scripts/status.sh) 2011-07-28 00:08:43 +02:00
Martin Duquesnoy
7bfba91a92 Update README 2011-07-27 14:20:26 +02:00
Philippe Pepiot
54687912c5 Old build system can still be used 2011-07-27 14:15:40 +02:00
Martin Duquesnoy
5d83a4a664 Merge master in dev branch 2011-07-21 22:14:57 +02:00
Philippe Pepiot
bfb8658bba Infobar: segfault when client->title is NULL, fixes #132
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-07-06 13:32:33 +02:00
Martin Duquesnoy
b47c4457f2 ViWMFS(rip)/Conf: Remove viWMFS, add cfactor_enable_split option and code cosmetic 2011-06-26 16:36:36 +02:00
Martin Duquesnoy
83c491527d Draw: Fix image shift with systray width 2011-06-17 16:21:03 +02:00
Martin Duquesnoy
c1d83e8c8b Client: Code cosmetic 2011-06-14 22:30:41 +02:00
Martin Duquesnoy
b6f728f1cc Client: Fix warning 2011-06-14 22:08:01 +02:00
Martin Duquesnoy
586620e1b1 Draw: Simplify draw_rectangle/graph 2011-06-14 19:27:49 +02:00
Martin Duquesnoy
52020cb22d Draw: Simplify draw_text & textw 2011-06-14 19:21:48 +02:00
Martin Duquesnoy
fbcd31253b Draw: Clean draw_text and textw 2011-06-14 19:12:44 +02:00
Martin Duquesnoy
ff0d345b11 Status: Use InfoBar pointer instead of global var + screen id 2011-06-14 18:12:32 +02:00
Martin Duquesnoy
134bb3add4 Status/Draw: Draw rec/img/str/graph block in status function, remove ofset draw functions 2011-06-14 17:51:01 +02:00
Martin Duquesnoy
74281424da README/Cmake: Add compiler options and update README 2011-06-14 15:56:17 +02:00
Martin Duquesnoy
b117a49b5a Split: Fix arrange closed loops 2011-06-14 14:35:03 +02:00
Martin Duquesnoy
43f44ae9fd Init: Add setlocale for x font 2011-06-13 20:51:31 +02:00
Martin Duquesnoy
2aa654709e Build system #2 2011-06-13 14:34:36 +02:00
David Demelier
9a8fdd37c6 Build system: CMake is back, managing xft optional. 2011-06-13 14:32:39 +02:00
Martin Duquesnoy
5d208730cd Wmfs: Make Xft font optional #1 2011-06-12 17:10:10 +02:00
Martin Duquesnoy
9bda577718 Event: Code cosmetic 2011-06-12 14:26:44 +02:00
Martin Duquesnoy
58f1c25eaf Infobar: Use InfoBar pointer instead of screen id as arg of infobar functions 2011-06-12 12:45:17 +02:00
Martin Duquesnoy
c0610091d6 Infobar/Tag: Fix occupied flag with multi head 2011-06-12 12:11:43 +02:00
Martin Duquesnoy
5491037f54 Client/Event: Fix random raise with multiscreen & max client and use local display in event.c 2011-06-12 01:34:02 +02:00
Martin Duquesnoy
e885449144 Cfactor/Split/Tag: Use macro instead of function for test functions and use bitfield instead of bool array in tag functions 2011-06-10 19:25:18 +02:00
Martin Duquesnoy
be2c983004 Wmfs: Use stdbool.h for bool type 2011-06-10 18:51:05 +02:00
Martin Duquesnoy
56ae367eee Layout: Fix arrange 2011-06-10 00:01:19 +02:00
Martin Duquesnoy
be5de68e93 Infobar: Use bitfield instead Bool array to check occupied tag 2011-06-09 23:54:50 +02:00
Martin Duquesnoy
5176103605 Infobar: Code cosmetic 2011-06-09 23:15:23 +02:00
Martin Duquesnoy
ef5c824a59 Infobar: Improve selbar render 2011-06-09 21:50:33 +02:00
Martin Duquesnoy
4a61cb8b18 Barwin: Typo 2011-06-09 21:32:51 +02:00
Martin Duquesnoy
87f926253f Client: Check if previous focus client was max to raise next 2011-06-09 19:42:40 +02:00
Martin Duquesnoy
96b1c0dff2 BarWindow: Use bitfield instead of Bool 2011-06-09 19:04:48 +02:00
Martin Duquesnoy
bccd36d522 Ewmh: Fix net_wm_name 2011-06-09 18:27:08 +02:00
Martin Duquesnoy
4e978c1824 Struct: Rename IgnoreNextExpose 2011-06-09 18:22:17 +02:00
Martin Duquesnoy
2a30083520 Client/Event: Fix raise with max flag and use flag IgnoreNextExose instead XQueryPointer for raise in client_focus 2011-06-09 18:13:05 +02:00
Martin Duquesnoy
13ac8cfa82 Launcher/menu: Fix possible segfault 2011-06-07 17:08:33 +02:00
Martin Duquesnoy
e4dbca928d Wmfs: Replace XRectangle by Geo (using int instead short) 2011-06-06 17:37:31 +02:00
Martin Duquesnoy
eeedd9e4be Cfactor/Mouse: Code cosmetic 2011-06-06 13:18:51 +02:00
Martin Duquesnoy
a06e0daa5a Event: Handle xrandr with event_handle 2011-06-05 16:37:00 +02:00
Martin Duquesnoy
860a1a2c11 Event: Handle xrandr correctly 2011-06-05 16:19:47 +02:00
Martin Duquesnoy
ff888494f2 Getinfo: Remove getinfo 2011-06-05 14:16:43 +02:00
Martin Duquesnoy
0774936a6f Split: Illustrate split_move func 2011-06-05 14:09:29 +02:00
Martin Duquesnoy
58b6d9bccb Cfactor: Add SplitFlag test in cfactor_clean() 2011-06-05 13:18:56 +02:00
Martin Duquesnoy
73a0d7ed01 Event: Replace event big switch by array of function pointer to handle events 2011-06-05 12:22:18 +02:00
Martin Duquesnoy
ecda7adcf7 Infobar/Split: Add split mode indicator (rectangle at bottom-right of layout button) 2011-06-04 21:30:58 +02:00
Martin Duquesnoy
9e78421e2e Wmfs: Optimization & cosmetic #2 2011-06-04 20:57:42 +02:00
Martin Duquesnoy
87b558b4b9 Wmfs: Optimization & cosmetic 2011-06-04 20:27:27 +02:00
Martin Duquesnoy
82bea4cee8 Client: Fix flag storage in _WMFS_FLAGS prop 2011-06-04 15:56:44 +02:00
Martin Duquesnoy
d9cc60a205 Wmfs: Replace _WMFS_ISFREE by _WMFS_FLAGS for clients win prop 2011-06-04 12:51:58 +02:00
Martin Duquesnoy
e2d775ff83 Conf: Change client_resize_dir keybind 2011-06-04 11:56:11 +02:00
Martin Duquesnoy
af0ddeda3f Split/Conf: Add split_move_direction function 2011-06-04 11:34:58 +02:00
Martin Duquesnoy
7d754f71d4 Split: Add test of sc & tile flag at integration 2011-06-03 18:10:25 +02:00
Martin Duquesnoy
517f6dc700 Split: Simplify set_current & integrate 2011-06-03 18:08:02 +02:00
Martin Duquesnoy
d229efe44b Split: Fix search for next splitted client 2011-06-03 18:02:51 +02:00
Martin Duquesnoy
0445bb05da Conf: Add "split" bool option in [tag] section 2011-06-03 17:47:41 +02:00
Martin Duquesnoy
7b47fd041a Struct/Conf: Remove useless var, add split toggle keybind (Alt-s) 2011-06-03 16:31:34 +02:00
Martin Duquesnoy
9636f9188d Tag/Split: Disable split mode with tag additional 2011-06-03 16:03:24 +02:00
Martin Duquesnoy
b36af57fb0 Split: Begin to set split mode 2011-06-02 23:54:03 +02:00
Martin Duquesnoy
a0e4a1657d Conf: Add default keybind for focus/swap/resize with direction and HJKL keys 2011-06-02 18:03:31 +02:00
Martin Duquesnoy
c054e529a3 Cfactor/Client: Use macro to generate redundant uicb functions #2 2011-06-02 17:48:53 +02:00
Martin Duquesnoy
9e932ec98a Revert "Cfactor/Client: Use macro to generate redundant uicb functions"
This reverts commit 83d56269f0.
2011-06-02 17:43:20 +02:00
Martin Duquesnoy
83d56269f0 Cfactor/Client: Use macro to generate redundant uicb functions 2011-06-02 17:41:53 +02:00
Martin Duquesnoy
0b94f5496e Client: Fix flag set and manage 2011-06-02 14:38:10 +02:00
Martin Duquesnoy
34d94335f2 Layout/Tag: Fix some screen/tag in tags[][] 2011-06-01 23:14:56 +02:00
Martin Duquesnoy
57ab723f5d All: Remove split layout (will make a split mode instead) and replace all tag struct bool by flags 2011-06-01 23:10:14 +02:00
Martin Duquesnoy
99018268ef Split/Tag: Adjust tag additional with split layout 2011-05-25 22:13:04 +02:00
Martin Duquesnoy
c556b45a8d Split/Client: Fix integration with 1 client & transfert on another screen 2011-05-24 23:14:29 +02:00
Martin Duquesnoy
f75c75645d Layout/Client: Fix arrange with split & transfert 2011-05-23 12:19:16 +02:00
Martin Duquesnoy
6a93c6fa35 Split/Layout: Improve split layout integration in tag behavior 2011-05-22 23:42:25 +02:00
Martin Duquesnoy
24de771713 Layout: Use grid layout for split if first arrange is needed with many client 2011-05-21 17:33:31 +02:00
Martin Duquesnoy
a44505c1a9 Split: Improve arrange_closed with _split_check_row 2011-05-21 17:14:52 +02:00
Martin Duquesnoy
468ecfdcb8 Cfactor: Improve cfactor_check_geo by checking all row parents client 2011-05-19 20:42:25 +02:00
Martin Duquesnoy
534eae3ae3 Conf: Clean wmfsrc 2011-05-18 12:23:11 +02:00
Martin Duquesnoy
d2f3377f97 Config/Client: Remove deprecated code, fix bug with nclients 2011-05-18 12:20:01 +02:00
Martin Duquesnoy
7839889071 Split/Layout: Manage splitted client in different case 2011-05-18 11:48:23 +02:00
Philippe Pepiot
664e4effdb Client: Fill new client with 0. fixes #116
Submitted-by: e-t172 <e-t172 _at_ akegroup.org>
Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-05-17 20:38:18 +02:00
Martin Duquesnoy
ff923542ba Client: Add cleanfact set removed by error in unmanage 2011-05-16 23:52:36 +02:00
Martin Duquesnoy
c5e96961cb Typo split 2011-05-16 23:37:44 +02:00
Martin Duquesnoy
1ba4a0ad46 Client: Improve client_manage with split 2011-05-16 23:16:53 +02:00
Martin Duquesnoy
825620b25c Split: Add split.c 2011-05-16 22:19:40 +02:00
Martin Duquesnoy
911ac2f74a Layout Split: Add split layout. 2011-05-16 20:38:54 +02:00
Martin Duquesnoy
7eb15d595f Layout/Client: Fix max layout (#92) 2011-05-14 17:30:02 +02:00
Martin Duquesnoy
dc836ccb86 Client/Layout/Tag: Balance position of window in frame with resizehint, refresh only client size at resizehint toggle and fix layout with tag additional 2011-05-14 15:19:02 +02:00
Martin Duquesnoy
f606b5ba88 Cfactor: Fix cfactor clean in case of split 2011-05-14 12:54:26 +02:00
Martin Duquesnoy
391aae2dea Client/Layout: Add without-resizehint geo in client struct for split resize use, improve split size of clients. 2011-05-13 23:54:11 +02:00
Martin Duquesnoy
f147bbbaf0 Client/Cfactor: Fix cfactor resizing in case of padding + 2 client resized and improve resizhint behaviour 2011-05-13 23:10:00 +02:00
Martin Duquesnoy
1b02cfed3e Layout: Add layout_split_client functio with 2 uicb; split_client_{vertical/horizontal} 2011-05-11 21:43:14 +02:00
Martin Duquesnoy
81e74e4bb6 Cfactor: Comment code 2011-05-10 22:19:50 +02:00
Martin Duquesnoy
4cda38ce26 Cfactor: Add exception for parent client and same size 2011-05-10 22:06:00 +02:00
Martin Duquesnoy
c8b9b41a3e Mouse: Add drag border for cfactor resizing 2011-05-09 22:15:14 +02:00
Martin Duquesnoy
9d44177f20 Mouse/Cfactor: Improve cfactor resize with mouse, resize different part according with the area 2011-05-08 16:09:00 +02:00
Martin Duquesnoy
06fb9553fc Client: Check if client is tiled for position research 2011-05-04 20:03:15 +02:00
Martin Duquesnoy
1061b79c5a Cfactor/Mouse: Replace mwfact resizing by cfactor resizing with mouse 2011-05-04 19:06:31 +02:00
Martin Duquesnoy
50dcf7c8c2 CFactor: Improve main function 2011-05-04 18:02:20 +02:00
Martin Duquesnoy
a7162d803d Cfactor: Add cfactor_scan_row to arrange row parents of factorized client 2011-05-04 16:15:49 +02:00
Martin Duquesnoy
4a804a740b Cfactor: Add cfactor.c and move all client_factor function of client.c 2011-05-01 15:48:12 +02:00
David Demelier
813d88ff7a Client: Clean factor if there is TileFlag in client_unmanage 2011-05-01 14:01:21 +02:00
David Demelier
3f9c8a0030 Buildsystem: Add mk/ 2011-05-01 13:06:15 +02:00
David Demelier
c628970c60 Buildsystem: Switching home-made configure to BSDBuild 2011-05-01 13:03:29 +02:00
Martin Duquesnoy
3e3b18e6a3 Layout/Client: Fix factor cleaning when new client appears in another tag 2011-04-29 17:49:38 +02:00
Martin Duquesnoy
89ff1ffcc5 Client: Travel client list to get by position 2011-04-29 17:43:02 +02:00
Martin Duquesnoy
dbaa966eb9 Client: Fix multi screen with client_gb_pos() 2011-04-29 14:45:57 +02:00
Martin Duquesnoy
cb8e9889c8 Layout: Fix nmaster cleanfact use 2011-04-29 14:25:39 +02:00
Martin Duquesnoy
11edb78e84 Client/Layout: Improve client tile factor 2011-04-29 14:03:42 +02:00
Martin Duquesnoy
82eb33df85 Client/Layout: Add manual resize for tiled client with client_resize_{direction} uicb function. 2011-04-28 04:34:29 +02:00
Philippe Pepiot
12aa86e914 build system: add a target dist to makefile
Generate a tarbal for wmfs with make dist
Version set to date +%Y%m in setlocalversion

Move .PHONY BEFORE phony targets

Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-04-16 21:36:27 +02:00
Philippe Pepiot
e57a6c5e62 build system: add setlocalversion
Version is built from git commit id, for example wmfs-ga33ec04-dirty
-> 'g', this is a git repo
-> a33ec04 is the beginning of the commit id (sha1)
-> dirty mean that there is uncommitted changes

wmfs users gives their 'wmfs -v' and developers can easily identify wmfs
version.

Move status.sh to scripts/ with setlocalversion

Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-04-16 20:52:28 +02:00
Philippe Pepiot
a33ec045ab Parser: fix leak in include() 2011-04-14 12:14:26 +02:00
Philippe Pepiot
05bedec5c6 Config: Don't allocate child [rule] section if no [rules] 2011-04-14 12:13:51 +02:00
Martin Duquesnoy
88d92149dd Wmfsrc: Fix default value for autohide 2011-04-07 18:05:50 +02:00
Martin Duquesnoy
e28c6a3d64 Merge branch 'bacardi55' of github.com:xorg62/wmfs
Conflicts:
	src/event.c
2011-04-07 18:02:27 +02:00
Philippe Pepiot
3f21c79f08 Prevent segfault in uicb_checklayout() closes #105 2011-03-24 14:31:54 +01:00
Martin Duquesnoy
ae47ab6f71 Event: Apply pl's patch (bug #97) 2011-03-12 23:09:42 +01:00
37 changed files with 3021 additions and 2355 deletions

4
.gitignore vendored
View File

@@ -3,7 +3,9 @@
wmfs
#*
\#*
Makefile
wmfs.1.gz
tags
*.patch
*.diff
Makefile
build/

134
CMakeLists.txt Normal file
View File

@@ -0,0 +1,134 @@
#
# CMake for wmfs David Demelier <markand@malikania.fr>
#
# General settings
cmake_minimum_required(VERSION 2.8)
project(wmfs)
set(CMAKE_C_FLAGS_RELEASE "-Wall")
set(CMAKE_C_FLAGS_DEBUG "-Wall -g -ansi -pendantic -O3 -funroll-loops")
# General option
option(WITH_XINERAMA "Build with X.Org xinerama support" ON)
option(WITH_XRANDR "Build with X.Org xrandr support" ON)
option(WITH_XFT "Build with X.Org xft support" ON)
option(WITH_IMLIB2 "Build with imlib2 graphic library" ON)
# WMFS Version and XDG directory
set(WMFS_VERSION "201106")
if (NOT XDG_CONFIG_DIR)
set(XDG_CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/etc/wmfs")
endif ()
# Man prefix
if (NOT MANPREFIX)
set(MANPREFIX "${CMAKE_INSTALL_PREFIX}/share")
endif ()
# Libraries are optional
find_package(X11)
if (NOT X11_FOUND)
message(FATAL_ERROR "You need x11 libraries to build wmfs")
else ()
list(APPEND INCLUDES ${X11_INCLUDE_DIR})
list(APPEND LIBRARIES ${X11_LIBRARIES})
endif ()
# pthread is needed
set(CMAKE_THREAD_PREFER_PTHREAD)
find_package(Threads)
if (NOT CMAKE_USE_PTHREADS_INIT)
message(FATAL_ERROR "You need pthread libraries to build wmfs")
else ()
list(APPEND LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif ()
# The following are optional X11 libraries
if (X11_Xinerama_FOUND AND WITH_XINERAMA)
list(APPEND INCLUDES ${X11_Xinerama_INCLUDE_PATH})
list(APPEND LIBRARIES ${X11_Xinerama_LIB})
list(APPEND DEFINES "HAVE_XINERAMA")
else ()
list(APPEND DISABLED "HAVE_XINERAMA")
endif ()
if (X11_Xrandr_FOUND AND WITH_XRANDR)
list(APPEND INCLUDES ${X11_Xrandr_INCLUDE_PATH})
list(APPEND LIBRARIES ${X11_Xrandr_LIB})
list(APPEND DEFINES "HAVE_XRANDR")
else ()
list(APPEND DISABLED "HAVE_XRANDR")
endif ()
if (X11_Xft_FOUND AND WITH_XFT)
find_package(Freetype)
if (FREETYPE_FOUND)
list(APPEND INCLUDES ${FREETYPE_INCLUDE_DIRS}
${X11_Xft_INCLUDE_PATH})
list(APPEND LIBRARIES ${FREETYPE_LIBRARIES}
${X11_Xft_LIB})
list(APPEND DEFINES "HAVE_XFT")
else ()
list(APPEND DISABLED "HAVE_XFT")
endif ()
endif ()
if (WITH_IMLIB2)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(IMLIB2 imlib2)
if (IMLIB2_FOUND)
list(APPEND INCLUDES ${IMLIB2_INCLUDE_DIRS})
list(APPEND LIBRARIES ${IMLIB2_LIBRARIES})
list(APPEND DEFINES "HAVE_IMLIB")
link_directories(${IMLIB2_LIBRARY_DIRS})
else ()
list(APPEND DISABLED "HAVE_IMLIB")
endif ()
else ()
list(APPEND DISABLED "HAVE_IMLIB")
endif ()
endif ()
# Enable the optional module to compilation
foreach (modname ${DEFINES})
add_definitions(-D${modname})
# Set a variable to print all enabled modules.
# Remove the HAVE_ from module names
string(SUBSTRING ${modname} 5 -1 upcase)
string(TOLOWER ${upcase} module)
message("INFO: ${module} enabled")
endforeach ()
# Show modules disabled
foreach (modname ${DISABLED})
string(SUBSTRING ${modname} 5 -1 upcase)
string(TOLOWER ${upcase} module)
message("INFO: ${module} disabled")
endforeach ()
file(
GLOB
SOURCES
src/*.c
src/*.h
)
# Add definitions for the version and XDG
add_definitions(-DWMFS_VERSION=\"${WMFS_VERSION}\")
add_definitions(-DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\")
include_directories(${INCLUDES})
add_executable(wmfs ${SOURCES})
target_link_libraries(wmfs ${LIBRARIES})
# Install targets
install(TARGETS wmfs DESTINATION bin/)
install(FILES wmfsrc DESTINATION ${XDG_CONFIG_DIR}/)
install(FILES wmfs.1 DESTINATION ${MANPREFIX}/man1/)

View File

@@ -2,7 +2,7 @@ PROG=wmfs
MAN=wmfs.1
# wmfs version
VERSION= 201011
VERSION=$(shell scripts/setlocalversion)
SRCS= \
src/barwin.c \
@@ -12,7 +12,6 @@ src/draw.c \
src/event.c \
src/ewmh.c \
src/frame.c \
src/getinfo.c \
src/infobar.c \
src/init.c \
src/launcher.c \
@@ -26,8 +25,9 @@ src/status.c \
src/systray.c \
src/tag.c \
src/util.c \
src/viwmfs.c \
src/color.c \
src/split.c \
src/cfactor.c \
src/wmfs.c
# flags
@@ -48,13 +48,14 @@ ${MAN}.gz: ${MAN}
.c.o:
${CC} -c ${CFLAGS} $< -o $@
.PHONY: all clean distclean install uninstall dist
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
@@ -80,7 +81,7 @@ uninstall:
rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc
rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
.PHONY: all clean distclean install uninstall
dist:
@echo "Generate wmfs-`date +%Y%m`.tar.gz"
git archive --format=tar --prefix=wmfs-`date +%Y%m`/ master | gzip -c > wmfs-`date +%Y%m`.tar.gz

21
README
View File

@@ -4,34 +4,39 @@ WMFS Window Manager.
A highly configurable and manageable tiling Window Manager created from scratch
AUTHORS : (in order of commits and > 5 commits)
AUTHOR :
- Martin Duquesnoy <xorg62@gmail.com>
CONTRIBUTORS :
- 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>
- David Demelier <markand@malikania.fr>
LICENSE : BSD
LICENSE : BSD, see COPYING.
REQUIREMENT :
- freetype2
- libxft
- libx11
- libxft (optional)
- freetype
- libxinerama (optional)
- libxrandr (optional)
- imlib2 (optional)
- cmake>=2.8 (build system, optional)
OS :
- GNU/Linux : Supported.
- FreeBSD/OpenBSD/NetBSD : Supported.
INSTALL :
./configure [--without-imlib2|--without-xrandr|--without-xinerama] (./configure -h)
make
sudo make install
mkdir build/ && cd build/
cmake ..
You can also use old build system if you don't want^Whave cmake
./configure && make
DISTROS :
- wmfs port for FreeBSD at x11-wm/wmfs

29
TODO
View File

@@ -1,5 +1,24 @@
· Add Doxygen comment <-> OK
· Mouse bindings in the config file
· Can change client position in the tile grid
· Fix all the bug \o/
· XCB ?
,
dM
MMr
4MMML .
MMMMM. xf
. "M6MMM .MM-
Mh.. +MM5MMM .MMMM
.MMM. .MMMMML. MMMMMh
)MMMh. MM5MMM MMMMMMM
3MMMMx. 'MMM3MMf xnMMMMMM"
'*MMMMM MMMMMM. nMMMMMMP"
*MMMMMx "MMM5M\ .MMMMMMM=
*MMMMMh "MMMMM" JMMMMMMP
MMMMMM GMMMM. dMMMMMM .
MMMMMM "MMMM .MMMMM( .nnMP"
.. *MMMMx MMM" dMMMM" .nnMMMMM*
"MMn... 'MMMMr 'MM MMM" .nMMMMMMM*"
"4MMMMnn.. *MMM MM MMP" .dMMMMMMM""
^MMMMMMMMx. *ML "M .M* .MMMMMM**"
*PMMMMMMhn. *x > M .MMMM**""
""**MMMMhx/.h/ .=*"
.3P"%....
nP" "*MMnx

12
configure vendored
View File

@@ -1,9 +1,10 @@
#!/bin/sh
LIBS="x11 xft freetype2"
LIBS="x11"
USE_XINERAMA="xinerama"
USE_XRANDR="xrandr"
USE_IMLIB2="imlib2"
USE_XFT="xft freetype2"
OS=`uname -s`
PREFIX=/usr/local
MANPREFIX="$PREFIX/man"
@@ -17,6 +18,8 @@ while true; do
USE_XRANDR=""; shift;;
--without-imlib2)
USE_IMLIB2=""; shift;;
--without-xft)
USE_XFT=""; shift;;
--prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
PREFIX=$2; shift 2;;
@@ -31,6 +34,7 @@ while true; do
--without-imlib2 : compile without imlib2 support
--without-xrandr : compile without xrandr support
--without-xinerama : compile without xinerama support
--without-xft : compile without xft 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)"
@@ -39,7 +43,7 @@ while true; do
esac
done
LIBS="$LIBS $USE_XINERAMA $USE_XRANDR $USE_IMLIB2"
LIBS="$LIBS $USE_XINERAMA $USE_XRANDR $USE_IMLIB2 $USE_XFT"
which pkg-config >/dev/null 2>&1
@@ -68,16 +72,18 @@ else
exit 1;;
esac
LDFLAGS="$LDFLAGS -lX11 -lXft -lfreetype"
LDFLAGS="$LDFLAGS -lX11"
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
[ -n "$USE_XRANDR" ] && LDFLAGS="$LDFLAGS -lXrandr"
[ -n "$USE_IMLIB2" ] && LDFLAGS="$LDFLAGS -lImlib2"
[ -n "$USE_XFT" ] && LDFLAGS="$LDFLAGS -lXft -lfreetype"
fi
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
[ -n "$USE_XRANDR" ] && CFLAGS="$CFLAGS -DHAVE_XRANDR"
[ -n "$USE_IMLIB2" ] && CFLAGS="$CFLAGS -DHAVE_IMLIB"
[ -n "$USE_XFT" ] && CFLAGS="$CFLAGS -DHAVE_XFT"
LDFLAGS="$LDFLAGS -lpthread"

75
scripts/setlocalversion Executable file
View File

@@ -0,0 +1,75 @@
#!/bin/sh
# Print additional version information for non-release trees.
usage() {
echo "Usage: $0 [srctree]" >&2
exit 1
}
cd "${1:-.}" || usage
# Check for git and a git repo.
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
# Do we have an untagged version?
if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
if tag=`git describe 2>/dev/null`; then
echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
else
printf '%s%s' -g $head
fi
fi
# Is this git on svn?
if git config --get svn-remote.svn.url >/dev/null; then
printf -- '-svn%s' "`git svn find-rev $head`"
fi
# Are there uncommitted changes?
git update-index --refresh --unmerged > /dev/null
if git diff-index --name-only HEAD | grep -v "^scripts/package" \
| read dummy; then
printf '%s' -dirty
fi
# All done with git
exit
fi
# Check for mercurial and a mercurial repo.
if hgid=`hg id 2>/dev/null`; then
tag=`printf '%s' "$hgid" | cut -d' ' -f2`
# Do we have an untagged version?
if [ -z "$tag" -o "$tag" = tip ]; then
id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
printf '%s%s' -hg "$id"
fi
# Are there uncommitted changes?
# These are represented by + after the changeset id.
case "$hgid" in
*+|*+\ *) printf '%s' -dirty ;;
esac
# All done with mercurial
exit
fi
# Check for svn and a svn repo.
if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
rev=`echo $rev | awk '{print $NF}'`
changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
# Are there uncommitted changes?
if [ $changes != 0 ]; then
printf -- '-svn%s%s' "$rev" -dirty
else
printf -- '-svn%s' "$rev"
fi
# All done with svn
exit
fi
# default version
printf -- '-%s' "`date +%Y%m`"

View File

@@ -8,4 +8,4 @@ statustext()
wmfs -s "`date`"
}
statustext
while true; do statustext; sleep 10; done

View File

@@ -39,20 +39,20 @@
* \param w BarWindow Width
* \param h BarWindow Height
* \param color BarWindow color
* \param entermask Bool for know if the EnterMask mask is needed
* \param entermask bool for know if the EnterMask mask is needed
* \return The BarWindow pointer
*/
BarWindow*
barwin_create(Window parent,
int x,
int y,
uint w,
uint h,
int w,
int h,
uint bg,
char *fg,
Bool entermask,
Bool stipple,
Bool border)
bool entermask,
bool stipple,
bool border)
{
XSetWindowAttributes at;
BarWindow *bw;
@@ -80,7 +80,7 @@ barwin_create(Window parent,
/* His border */
if(border)
{
bw->bord = True;
bw->flags |= BordFlag;
bw->border.light = color_shade(bg, conf.colors.bar_light_shade);
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
@@ -97,8 +97,11 @@ barwin_create(Window parent,
bw->geo.height = h;
bw->bg = bg;
bw->fg = fg;
bw->stipple = stipple;
bw->stipple_color = -1;
FLAGAPPLY(bw->flags, stipple, StippleFlag);
bw->stipple_color = 0xffffffff;
/* Attach */
SLIST_INSERT_HEAD(&bwhead, bw, next);
return bw;
}
@@ -108,11 +111,8 @@ 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)
if(bw->flags & StippleFlag)
draw_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg);
/* Draw text */
@@ -123,40 +123,21 @@ barwin_draw_text(BarWindow *bw, int x, int y, char *text)
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)
if(bw->flags & BordFlag)
{
bw->border.light = color_shade(bg, conf.colors.bar_light_shade);
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
}
if(bw->flags & StippleFlag && bw->stipple_color == 0xffffffff)
bw->stipple_color = getcolor(fg);
return;
}
@@ -166,8 +147,7 @@ barwin_color_set(BarWindow *bw, uint bg, char *fg)
void
barwin_delete(BarWindow *bw)
{
CHECK(bw);
SLIST_REMOVE(&bwhead, bw, BarWindow, next);
XSelectInput(dpy, bw->win, NoEventMask);
XDestroyWindow(dpy, bw->win);
XFreePixmap(dpy, bw->dr);
@@ -176,77 +156,6 @@ barwin_delete(BarWindow *bw)
return;
}
/** Delete the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_delete_subwin(BarWindow *bw)
{
CHECK(bw);
XDestroySubwindows(dpy, bw->win);
return;
}
/** Map a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_map(BarWindow *bw)
{
CHECK(!bw->mapped);
XMapWindow(dpy, bw->win);
bw->mapped = True;
return;
}
/** Map the subwindows of a BarWindow
* Use for the BarWindow special border...
* \param bw BarWindow pointer
*/
void
barwin_map_subwin(BarWindow *bw)
{
CHECK(bw);
XMapSubwindows(dpy, bw->win);
return;
}
/** Unmap a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_unmap(BarWindow *bw)
{
CHECK(bw->mapped);
XUnmapWindow(dpy, bw->win);
bw->mapped = False;
return;
}
/** Unmap the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_unmap_subwin(BarWindow *bw)
{
CHECK(bw);
XUnmapSubwindows(dpy, bw->win);
return;
}
/** Move a BarWindow
* \param bw BarWindow pointer
* \param x X position
@@ -255,7 +164,7 @@ barwin_unmap_subwin(BarWindow *bw)
void
barwin_move(BarWindow *bw, int x, int y)
{
if(!bw || (bw->geo.x == x && bw->geo.y == y))
if(bw->geo.x == x && bw->geo.y == y)
return;
XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y));
@@ -269,25 +178,26 @@ barwin_move(BarWindow *bw, int x, int y)
* \param h Height
*/
void
barwin_resize(BarWindow *bw, uint w, uint h)
barwin_resize(BarWindow *bw, int w, int h)
{
if(!bw || (bw->geo.width == w && bw->geo.height == h))
if(bw->geo.width == w && bw->geo.height == h)
return;
/* Frame */
XFreePixmap(dpy, bw->dr);
bw->dr = XCreatePixmap(dpy, ROOT,
w - ((bw->flags & BordFlag) ? SHADH : 0),
h - ((bw->flags & BordFlag) ? SHADH : 0),
DefaultDepth(dpy, SCREEN));
bw->geo.width = w;
bw->geo.height = h;
XFreePixmap(dpy, bw->dr);
/* Frame */
bw->dr = XCreatePixmap(dpy, ROOT,
w - ((bw->bord) ? SHADH : 0),
h - ((bw->bord) ? SHADH : 0),
DefaultDepth(dpy, SCREEN));
XResizeWindow(dpy, bw->win, w, h);
/* Border */
if(bw->bord)
if(bw->flags & BordFlag)
{
XResizeWindow(dpy, bw->border.left, SHADH, h);
XResizeWindow(dpy, bw->border.top, w, SHADH);
@@ -304,22 +214,21 @@ barwin_resize(BarWindow *bw, uint w, uint h)
void
barwin_refresh_color(BarWindow *bw)
{
CHECK(bw);
XSetForeground(dpy, gc, bw->bg);
XFillRectangle(dpy, bw->dr, gc, 0, 0, bw->geo.width, bw->geo.height);
draw_rectangle(bw->dr, 0, 0, bw->geo.width, bw->geo.height, bw->bg);
if(bw->stipple)
if(bw->flags & StippleFlag)
{
XSetForeground(dpy, gc_stipple, ((bw->stipple_color != (uint)-1) ? (long)bw->stipple_color : getcolor(bw->fg)));
XSetForeground(dpy, gc_stipple, bw->stipple_color);
XFillRectangle(dpy, bw->dr, gc_stipple, 3, 2, bw->geo.width - 6, bw->geo.height - 4);
}
if(bw->bord)
if(bw->flags & BordFlag)
{
XSetWindowBackground(dpy, bw->border.left, bw->border.light);
XSetWindowBackground(dpy, bw->border.top, bw->border.light);
XSetWindowBackground(dpy, bw->border.left, bw->border.light);
XSetWindowBackground(dpy, bw->border.top, bw->border.light);
XSetWindowBackground(dpy, bw->border.bottom, bw->border.dark);
XSetWindowBackground(dpy, bw->border.right, bw->border.dark);
XSetWindowBackground(dpy, bw->border.right, bw->border.dark);
XClearWindow(dpy, bw->border.left);
XClearWindow(dpy, bw->border.top);
@@ -330,16 +239,3 @@ barwin_refresh_color(BarWindow *bw)
return;
}
/** Refresh the BarWindow
* \param bw BarWindow pointer
*/
void
barwin_refresh(BarWindow *bw)
{
if(!bw || !bw->dr || !bw->win)
return;
XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0);
return;
}

279
src/cfactor.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* cfactor.c
* Copyright © 2011 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 CLIENT_RESIZE_DIR(d) \
void \
uicb_client_resize_##d(uicb_t cmd) \
{ \
CHECK(sel); \
cfactor_set(sel, d, atoi(cmd)); \
}
/* uicb_client_resize_dir() */
CLIENT_RESIZE_DIR(Right);
CLIENT_RESIZE_DIR(Left);
CLIENT_RESIZE_DIR(Top);
CLIENT_RESIZE_DIR(Bottom);
/** Clean client tile factors
*\param c Client pointer
*/
void
cfactor_clean(Client *c)
{
CHECK(c);
if(!(tags[c->screen][c->tag].flags & (SplitFlag | CleanFactFlag)))
return;
c->tilefact[Right] = c->tilefact[Left] = 0;
c->tilefact[Top] = c->tilefact[Bottom] = 0;
return;
}
/** Return new geo of client with factors applied
*\param c Client pointer
*\return geo
*/
Geo
cfactor_geo(Geo geo, int fact[4], int *err)
{
Geo cgeo = geo;
*err = 0;
/* Right factor */
cgeo.width += fact[Right];
/* Left factor */
cgeo.x -= fact[Left];
cgeo.width += fact[Left];
/* Top factor */
cgeo.y -= fact[Top];
cgeo.height += fact[Top];
/* Bottom factor */
cgeo.height += fact[Bottom];
/* Too big/small */
if(cgeo.width > sgeo[selscreen].width || cgeo.height > sgeo[selscreen].height
|| cgeo.width < (BORDH << 1) || cgeo.height < (BORDH + TBARH))
{
*err = 1;
return geo;
}
return cgeo;
}
/** Get c parents of row and resize
*\param c Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static void
_cfactor_arrange_row(Client *c, Position p, int fac)
{
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
/* Travel clients to search parents of row and apply fact */
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{
cc->tilefact[p] += fac;
client_moveresize(cc, cc->geo, (tags[cc->screen][cc->tag].flags & ResizeHintFlag));
}
return;
}
/** Get c parents of row and check geo with futur resize factor
*\param c Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*\return False in case of error
*/
static bool
_cfactor_check_geo_row(Client *c, Position p, int fac)
{
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
int e, f[4] = { 0 };
f[p] += fac;
/* Travel clients to search parents of row and check geos */
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{
(Geo)cfactor_geo(cc->wrgeo, f, &e);
if(e)
return False;
}
return True;
}
/* Resize only 2 client with applied factor
*\param c1 Client pointer
*\param c2 Client pointer
*\param p Direction of resizing
*\param fac Facotr
*/
static void
cfactor_arrange_two(Client *c1, Client *c2, Position p, int fac)
{
c1->tilefact[p] += fac;
c2->tilefact[RPOS(p)] -= fac;
/* Needed in case of padding */
if(conf.client.padding)
{
c1->flags |= FLayFlag;
c2->flags |= FLayFlag;
}
client_moveresize(c1, c1->geo, (tags[c1->screen][c1->tag].flags & ResizeHintFlag));
client_moveresize(c2, c2->geo, (tags[c2->screen][c2->tag].flags & ResizeHintFlag));
return;
}
/** Get c parents of row and resize, exception checking same size before arranging row
*\param c Client pointer
*\param gc Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static void
cfactor_arrange_row(Client *c, Client *gc, Position p, int fac)
{
if(CFACTOR_CHECK2(c->frame_geo, gc->frame_geo, p))
cfactor_arrange_two(c, gc, p, fac);
else
{
_cfactor_arrange_row(c, p, fac);
_cfactor_arrange_row(gc, RPOS(p), -fac);
}
return;
}
/** Check future geometry of factorized client
*\param c Client pointer
*\param g Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static bool
cfactor_check_geo(Client *c, Client *g, Position p, int fac)
{
int e, ee;
int cf[4] = { 0 }, gf[4] = { 0 };
/* Check c & g first */
cf[p] += fac;
gf[RPOS(p)] -= fac;
(Geo)cfactor_geo(c->geo, cf, &e);
(Geo)cfactor_geo(g->geo, gf, &ee);
/* Size failure */
if(e || ee || !_cfactor_check_geo_row(c, p, fac)
|| !_cfactor_check_geo_row(g, RPOS(p), -fac))
return False;
return True;
}
/** Manual resizing of tiled clients
* \param c Client pointer
* \param p Direction of resizing
* \param fac Factor of resizing
*/
void
cfactor_set(Client *c, Position p, int fac)
{
Client *gc = NULL;
if(!c || !(c->flags & TileFlag) || p > Bottom)
return;
/* Get next client with direction of resize */
gc = client_get_next_with_direction(c, p);
if(!gc || c->screen != gc->screen)
return;
/* Check size */
if(!cfactor_check_geo(c, gc, p, fac))
return;
/* Arrange client and row parents */
cfactor_arrange_row(c, gc, p, fac);
/* Enable split with cfactor_enable_split option */
if(conf.cfactor_enable_split
&& !(tags[c->screen][c->tag].flags & SplitFlag))
{
tags[c->screen][c->tag].flags |= SplitFlag;
infobar_draw_layout(&infobar[c->screen]);
}
return;
}
/** Apply a complete factor array to a client
* \param c Client pointer
* \param fac factor array
*/
void
cfactor_multi_set(Client *c, int fac[4])
{
if(!c)
return;
cfactor_set(c, Right, fac[Right]);
cfactor_set(c, Left, fac[Left]);
cfactor_set(c, Top, fac[Top]);
cfactor_set(c, Bottom, fac[Bottom]);
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -36,21 +36,29 @@ const func_name_list_t func_list[] =
{
{"spawn", uicb_spawn },
{"client_kill", uicb_client_kill },
{"client_prev", uicb_client_prev },
{"client_next", uicb_client_next },
{"client_swap_next", uicb_client_swap_next },
{"client_swap_prev", uicb_client_swap_prev },
{"client_prev", uicb_client_focus_prev },
{"client_next", uicb_client_focus_next },
{"client_swap_next", uicb_client_swapsel_next },
{"client_swap_prev", uicb_client_swapsel_prev },
{"client_swap_right", uicb_client_swapsel_Right },
{"client_swap_left", uicb_client_swapsel_Left },
{"client_swap_top", uicb_client_swapsel_Top },
{"client_swap_bottom", uicb_client_swapsel_Bottom },
{"client_screen_next", uicb_client_screen_next },
{"client_screen_prev", uicb_client_screen_prev },
{"client_screen_set", uicb_client_screen_set },
{"client_focus_right", uicb_client_focus_right },
{"client_focus_left" , uicb_client_focus_left },
{"client_focus_top", uicb_client_focus_top },
{"client_focus_bottom", uicb_client_focus_bottom },
{"client_focus_right", uicb_client_focus_Right },
{"client_focus_left" , uicb_client_focus_Left },
{"client_focus_top", uicb_client_focus_Top },
{"client_focus_bottom", uicb_client_focus_Bottom },
{"client_move", uicb_client_move },
{"client_resize", uicb_client_resize },
{"client_ignore_tag", uicb_client_ignore_tag },
{"client_set_master", uicb_client_set_master },
{"client_resize_right", uicb_client_resize_Right },
{"client_resize_left", uicb_client_resize_Left },
{"client_resize_top", uicb_client_resize_Top },
{"client_resize_bottom", uicb_client_resize_Bottom },
{"toggle_max", uicb_togglemax },
{"layout_next", uicb_layout_next },
{"layout_prev", uicb_layout_prev },
@@ -100,6 +108,13 @@ const func_name_list_t func_list[] =
{"check_clist", uicb_checkclist },
{"toggle_tagautohide", uicb_toggle_tagautohide },
{"toggle_tag_expose", uicb_tag_toggle_expose},
{"split_toggle", uicb_split_toggle },
{"split_move_right", uicb_split_move_Right },
{"split_move_left", uicb_split_move_Left },
{"split_move_top", uicb_split_move_Top },
{"split_move_bottom", uicb_split_move_Bottom },
/*{"split_client_vertical" uicb_split_client_vertical },
{"split_client_horizontal", uicb_split_client_horizontal }, */
{NULL, NULL}
};
@@ -151,19 +166,23 @@ mouse_section(MouseBinding mb[], struct conf_sec **sec)
static void
conf_misc_section(void)
{
bool xft = False;
int pad = 12;
uint opacity = 255;
struct conf_sec *sec;
sec = fetch_section_first(NULL, "misc");
#ifdef HAVE_XFT
xft = True;
#endif /* HAVE_XFT */
conf.font = fetch_opt_first(sec, "sans-9", "font").str;
conf.raisefocus = fetch_opt_first(sec, "false", "raisefocus").bool;
conf.focus_fmouse = fetch_opt_first(sec, "true", "focus_follow_mouse").bool;
conf.focus_fmov = fetch_opt_first(sec, "false", "focus_follow_movement").bool;
conf.focus_pclick = fetch_opt_first(sec, "true", "focus_pointer_click").bool;
conf.status_timing = fetch_opt_first(sec, "1", "status_timing").num;
conf.status_path = fetch_opt_first(sec, "", "status_path").str;
conf.use_xft = fetch_opt_first(sec, (xft ? "true" : "false"), "use_xft").boolean;
conf.raisefocus = fetch_opt_first(sec, "false", "raisefocus").boolean;
conf.focus_fmouse = fetch_opt_first(sec, "true", "focus_follow_mouse").boolean;
conf.focus_fmov = fetch_opt_first(sec, "false", "focus_follow_movement").boolean;
conf.focus_pclick = fetch_opt_first(sec, "true", "focus_pointer_click").boolean;
conf.autostart_path = fetch_opt_first(sec, "", "autostart_path").str;
conf.autostart_command = fetch_opt_first(sec, "", "autostart_command").str;
pad = fetch_opt_first(sec, "12", "pad").num;
@@ -177,18 +196,11 @@ conf_misc_section(void)
if(pad > 24 || pad < 1)
{
warnx("configuration : pad value (%d) incorrect.", pad);
pad = 12;
}
conf.pad = pad;
if(conf.status_timing < 0)
{
warnx("configuration : status_timing value (%d) incorrect.", conf.status_timing);
conf.status_timing = 1;
}
return;
}
@@ -201,14 +213,15 @@ conf_bar_section(void)
bar = fetch_section_first(NULL, "bar");
conf.border.bar = fetch_opt_first(bar, "false", "border").bool;
conf.border.bar = fetch_opt_first(bar, "false", "border").boolean;
conf.bars.height = fetch_opt_first(bar, "-1", "height").num;
conf.colors.bar = getcolor((barbg = fetch_opt_first(bar, "#000000", "bg").str));
conf.colors.text = fetch_opt_first(bar, "#ffffff", "fg").str;
conf.colors.bar_light_shade = fetch_opt_first(bar, "0.25", "light_shade").fnum;
conf.colors.bar_dark_shade = fetch_opt_first(bar, "-0.25", "dark_shade").fnum;
conf.bars.element_order = fetch_opt_first(bar, "tls", "elements_order").str;
mouse = fetch_section(bar, "mouse");
if ((conf.bars.nmouse = fetch_section_count(mouse)) > 0)
@@ -221,7 +234,7 @@ conf_bar_section(void)
if((systray = fetch_section_first(bar, "systray")))
{
conf.systray.active = fetch_opt_first(systray, "true", "active").bool;
conf.systray.active = fetch_opt_first(systray, "true", "active").boolean;
if((conf.systray.screen = fetch_opt_first(systray, "0", "screen").num) < 0
|| conf.systray.screen >= sc)
@@ -285,27 +298,27 @@ conf_client_section(void)
sec = fetch_section_first(NULL, "client");
conf.client_round = fetch_opt_first(sec, "true", "client_round").bool;
conf.client_auto_center = fetch_opt_first(sec, "false", "client_auto_center").bool;
conf.client_tile_raise = fetch_opt_first(sec, "false", "client_tile_raise").bool;
conf.client_round = fetch_opt_first(sec, "true", "client_round").boolean;
conf.client_auto_center = fetch_opt_first(sec, "false", "client_auto_center").boolean;
conf.client_tile_raise = fetch_opt_first(sec, "false", "client_tile_raise").boolean;
if ((conf.client.borderheight = fetch_opt_first(sec, "1", "border_height").num) < 1)
conf.client.borderheight = 1;
conf.client.border_shadow = fetch_opt_first(sec, "false", "border_shadow").bool;
conf.client.place_at_mouse = fetch_opt_first(sec, "false", "place_at_mouse").bool;
conf.client.border_shadow = fetch_opt_first(sec, "false", "border_shadow").boolean;
conf.client.place_at_mouse = fetch_opt_first(sec, "false", "place_at_mouse").boolean;
conf.client.bordernormal = getcolor(fetch_opt_first(sec, "#000000", "border_normal").str);
conf.client.borderfocus = getcolor(fetch_opt_first(sec, "#ffffff", "border_focus").str);
conf.client.resizecorner_normal = getcolor(fetch_opt_first(sec, "#222222", "resize_corner_normal").str);
conf.client.resizecorner_focus = getcolor(fetch_opt_first(sec, "#DDDDDD", "resize_corner_focus").str);
conf.client.mod |= char_to_modkey(fetch_opt_first(sec, "Alt", "modifier").str, key_list);
conf.client.set_new_win_master = fetch_opt_first(sec, "true", "set_new_win_master").bool;
conf.client.set_new_win_master = fetch_opt_first(sec, "true", "set_new_win_master").boolean;
conf.client.padding = fetch_opt_first(sec, "0", "padding").num;
conf.client.autofree = fetch_opt_first(sec, "", "autofree").str;
conf.client.automax = fetch_opt_first(sec, "", "automax").str;
conf.client.default_open_tag = fetch_opt_first(sec, "0", "default_open_tag").num;
conf.client.default_open_screen = fetch_opt_first(sec, "-1", "default_open_screen").num;
conf.client.new_client_get_mouse = fetch_opt_first(sec, "false", "new_client_get_mouse").bool;
conf.client.new_client_get_mouse = fetch_opt_first(sec, "false", "new_client_get_mouse").boolean;
conf.colors.client_light_shade = fetch_opt_first(sec, "0.25", "light_shade").fnum;
conf.colors.client_dark_shade = fetch_opt_first(sec, "-0.25", "dark_shade").fnum;
@@ -326,7 +339,7 @@ conf_client_section(void)
conf.titlebar.fg_normal = fetch_opt_first(titlebar, "#ffffff", "fg_normal").str;
conf.titlebar.fg_focus = fetch_opt_first(titlebar, "#000000", "fg_focus").str;
conf.titlebar.stipple.active = fetch_opt_first(titlebar, "false", "stipple").bool;
conf.titlebar.stipple.active = fetch_opt_first(titlebar, "false", "stipple").boolean;
if(!strcmp((p = fetch_opt_first(titlebar, "-1", "stipple_normal").str), "-1"))
conf.titlebar.stipple.colors.normal = getcolor(conf.titlebar.fg_normal);
@@ -420,18 +433,16 @@ conf_layout_section(void)
layouts = fetch_section_first(NULL, "layouts");
conf.layout_button_width = fetch_opt_first(layouts, "O", "layout_button_width").num;
conf.border.layout = fetch_opt_first(layouts, "false", "border").bool;
conf.border.layout = fetch_opt_first(layouts, "false", "border").boolean;
conf.colors.layout_fg = fetch_opt_first(layouts, "#ffffff", "fg").str;
conf.colors.layout_bg = getcolor((fetch_opt_first(layouts, "#000000", "bg").str));
conf.keep_layout_geo = fetch_opt_first(layouts, "false", "keep_layout_geo").bool;
conf.keep_layout_geo = fetch_opt_first(layouts, "false", "keep_layout_geo").boolean;
conf.selected_layout_symbol = fetch_opt_first(layouts, "*", "selected_layout_symbol").str;
conf.cfactor_enable_split = fetch_opt_first(layouts, "false", "cfactor_enable_split").boolean;
if((tmp = fetch_opt_first(layouts, "menu", "system").str) && !strcmp(tmp, "menu"))
conf.layout_system = True;
if((tmp = fetch_opt_first(layouts, "right", "placement").str) && !strcmp(tmp, "left"))
conf.layout_placement = True;
layout = fetch_section(layouts, "layout");
conf.nlayout = fetch_section_count(layout);
@@ -484,25 +495,24 @@ conf_layout_section(void)
static void
conf_tag_section(void)
{
int i, j, k, l = 0, m, n, sc, count, bar_pos;
int i, j, k, l = 0, n, sc, bar_pos;
char *tmp;
char *position;
struct conf_sec *sec, *def_tag, **tag, **mouse;
struct opt_type *opt;
sec = fetch_section_first(NULL, "tags");
conf.tag_round = fetch_opt_first(sec, "false", "tag_round").bool;
conf.tag_auto_prev = fetch_opt_first(sec, "true", "tag_auto_prev").bool;
conf.tag_round = fetch_opt_first(sec, "false", "tag_round").boolean;
conf.tag_auto_prev = fetch_opt_first(sec, "true", "tag_auto_prev").boolean;
conf.colors.tagselfg = fetch_opt_first(sec, "#ffffff", "sel_fg").str;
conf.colors.tagselbg = getcolor(fetch_opt_first(sec, "#000000", "sel_bg").str);
conf.colors.tagurfg = fetch_opt_first(sec, "#000000", "urgent_fg").str;
conf.colors.tagurbg = getcolor(fetch_opt_first(sec, "#DD1111", "urgent_bg").str);
conf.colors.tag_occupied_bg = getcolor(fetch_opt_first(sec, "#222222", "occupied_bg").str);
conf.colors.tag_occupied_fg = fetch_opt_first(sec, conf.colors.text, "occupied_fg").str;
conf.border.tag = fetch_opt_first(sec, "false", "border").bool;
conf.tagautohide = fetch_opt_first(sec, "false", "autohide").bool;
conf.tagnamecount = fetch_opt_first(sec, "false", "name_count").bool;
conf.border.tag = fetch_opt_first(sec, "false", "border").boolean;
conf.tagautohide = fetch_opt_first(sec, "false", "autohide").boolean;
conf.tagnamecount = fetch_opt_first(sec, "false", "name_count").boolean;
conf.tag_expose_name = fetch_opt_first(sec, "EXPOSE", "expose_name").str;
conf.expose_layout = fetch_opt_first(sec, "tile_grid_vertical", "expose_layout").str;
@@ -522,13 +532,29 @@ conf_tag_section(void)
/* If there is no tag in the conf or more than
* MAXTAG (36) print an error and create only one.
*/
Tag default_tag = { fetch_opt_first(def_tag, "new tag", "name").str, NULL, 0, 1,
fetch_opt_first(def_tag, "0.6", "mwfact").fnum,
fetch_opt_first(def_tag, "1", "nmaster").num,
False, fetch_opt_first(def_tag, "False", "resizehint").bool,
False, False, bar_pos, bar_pos,
layout_name_to_struct(conf.layout, fetch_opt_first(def_tag, "title_right", "layout").str, conf.nlayout, layout_list),
0, NULL, 0, False };
Tag default_tag =
{
fetch_opt_first(def_tag, "new tag", "name").str,
NULL,
1,
fetch_opt_first(def_tag, "0.6", "mwfact").fnum,
fetch_opt_first(def_tag, "1", "nmaster").num,
0,
bar_pos,
bar_pos,
layout_name_to_struct(conf.layout, fetch_opt_first(def_tag, "tile", "layout").str, conf.nlayout, layout_list),
0,
NULL,
0
};
FLAGAPPLY(default_tag.flags,
fetch_opt_first(def_tag, "false", "resizehint").boolean,
ResizeHintFlag);
FLAGAPPLY(default_tag.flags,
fetch_opt_first(def_tag, "false", "split").boolean,
(SplitFlag | FirstArrangeFlag));
conf.default_tag = default_tag;
@@ -577,9 +603,17 @@ conf_tag_section(void)
tags[k][conf.ntag[k]].name = fetch_opt_first(tag[i], fetch_opt_first(def_tag, "", "name").str, "name").str;
tags[k][conf.ntag[k]].mwfact = fetch_opt_first(tag[i], fetch_opt_first(def_tag, "0.65", "mwfact").str, "mwfact").fnum;
tags[k][conf.ntag[k]].nmaster = fetch_opt_first(tag[i], fetch_opt_first(def_tag, "1", "nmaster").str, "nmaster").num;
tags[k][conf.ntag[k]].resizehint = fetch_opt_first(tag[i], fetch_opt_first(def_tag, "false", "resizehint").str, "resizehint").bool;
tags[k][conf.ntag[k]].abovefc = fetch_opt_first(tag[i], "false", "abovefc").bool;
tags[k][conf.ntag[k]].layers = 1;
FLAGAPPLY(tags[k][conf.ntag[k]].flags,
fetch_opt_first(tag[i], fetch_opt_first(def_tag, "false", "resizehint").str, "resizehint").boolean,
ResizeHintFlag);
FLAGAPPLY(tags[k][conf.ntag[k]].flags,
fetch_opt_first(tag[i], "false", "abovefc").boolean,
AboveFCFlag);
FLAGAPPLY(tags[k][conf.ntag[k]].flags,
fetch_opt_first(tag[i], "false", "split").boolean,
(SplitFlag | FirstArrangeFlag));
tmp = fetch_opt_first(tag[i], fetch_opt_first(def_tag, "top", "infobar_position").str, "infobar_position").str;
@@ -591,22 +625,9 @@ conf_tag_section(void)
tags[k][conf.ntag[k]].barpos = IB_Top;
tags[k][conf.ntag[k]].layout = layout_name_to_struct(conf.layout,
fetch_opt_first(tag[i], fetch_opt_first(def_tag, "title_right", "layout").str, "layout").str,
conf.nlayout,
layout_list);
/* Clients list */
opt = fetch_opt(tag[i], "", "clients");
if ((count = fetch_opt_count(opt)))
{
tags[k][conf.ntag[k]].nclients = count;
tags[k][conf.ntag[k]].clients = xcalloc(count, sizeof(char *));
for(m = 0; m < count; ++m)
tags[k][conf.ntag[k]].clients[m] = opt[m].str;
}
free(opt);
fetch_opt_first(tag[i], fetch_opt_first(def_tag, "tile", "layout").str, "layout").str,
conf.nlayout,
layout_list);
/* Multi mouse sections */
mouse = fetch_section(tag[i], "mouse");
@@ -641,7 +662,8 @@ conf_rule_section(void)
int i;
struct conf_sec *rules, **rule;
rules = fetch_section_first(NULL, "rules");
if ((rules = fetch_section_first(NULL, "rules")) == NULL)
return;
rule = fetch_section(rules, "rule");
@@ -654,12 +676,13 @@ conf_rule_section(void)
conf.rule[i].class = fetch_opt_first(rule[i], "", "class").str;
conf.rule[i].instance = fetch_opt_first(rule[i], "", "instance").str;
conf.rule[i].role = fetch_opt_first(rule[i], "", "role").str;
conf.rule[i].name = fetch_opt_first(rule[i], "", "name").str;
conf.rule[i].screen = fetch_opt_first(rule[i], "-1", "screen").num;
conf.rule[i].tag = fetch_opt_first(rule[i], "-1", "tag").num;
conf.rule[i].free = fetch_opt_first(rule[i], "false", "free").bool;
conf.rule[i].max = fetch_opt_first(rule[i], "false", "max").bool;
conf.rule[i].ignoretags = fetch_opt_first(rule[i], "false", "ignoretags").bool;
conf.rule[i].follow_client = fetch_opt_first(rule[i], "false", "follow_client").bool;
conf.rule[i].free = fetch_opt_first(rule[i], "false", "free").boolean;
conf.rule[i].max = fetch_opt_first(rule[i], "false", "max").boolean;
conf.rule[i].ignoretags = fetch_opt_first(rule[i], "false", "ignoretags").boolean;
conf.rule[i].follow_client = fetch_opt_first(rule[i], "false", "follow_client").boolean;
}
free(rule);
@@ -687,7 +710,7 @@ conf_menu_section(void)
conf.menu[i].name = fetch_opt_first(set_menu[i], "menu_wname", "name").str;
if(!(conf.menu[i].place_at_mouse = fetch_opt_first(set_menu[i], "true", "place_at_mouse").bool))
if(!(conf.menu[i].place_at_mouse = fetch_opt_first(set_menu[i], "true", "place_at_mouse").boolean))
{
conf.menu[i].x = fetch_opt_first(set_menu[i], "0", "x").num;
conf.menu[i].y = fetch_opt_first(set_menu[i], "0", "y").num;

View File

@@ -33,20 +33,22 @@
#include "wmfs.h"
#ifdef HAVE_IMLIB
static int sw = 0;
/** 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)
static void
draw_image(Drawable dr, int x, int y, int w, int h, char *name)
{
Imlib_Image image;
if(!name)
if(!dr)
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)));
@@ -62,23 +64,67 @@ static void draw_image(Drawable dr, int x, int y, int w, int h, char *name)
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);
imlib_free_image();
return;
}
/** Check images blocks in str and return properties
* --> \i[x;y;w;h;name]\
*\param im ImageAttr pointer, image properties
*\param str String
*\param m Check dynamic mouse
*\return n Lenght of i
*/
static void
parse_image_block(Drawable dr, char *str, bool m)
{
ImageAttr im;
Geo area;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k = 0, n;
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^];]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, &as)) == 6
|| (n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^;];%512[^]]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, mouse, &as)) == 7)
&& as == '\\')
{
draw_image(dr, im.x - sw, im.y, im.w, im.h, im.name);
/* Etablish clickable area on image (on infobar wins only (status mouse bind) */
if(n == 7 && m)
{
area.x = im.x - sw;
area.y = im.y;
area.width = im.w;
area.height = im.h;
/* Associate drawable with window; travel infobars */
for(; k < screen_count(); ++k)
if(infobar[k].bar->dr == dr)
{
statustext_mouse(mouse, area, &infobar[k]);
break;
}
}
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i)
str[j] = str[i];
for(sw = 0, k = j; k < i; str[k++] = 0);
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
@@ -88,60 +134,61 @@ draw_text(Drawable d, int x, int y, char* fg, char *str)
* \param str String that will be draw
*/
void
draw_image_ofset_text(Drawable d, int x, int y, char* fg, char *str, int x_image_ofset, int y_image_ofset)
draw_text(Drawable d, int x, int y, char* fg, char *str)
{
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;
CHECK(str);
/* To draw image everywhere we can draw text */
#ifdef HAVE_IMLIB
ostr = xstrdup(str);
textlen = strlen(ostr);
char *ostr;
size_t textlen = 0;
if(strstr(str, "i["))
{
ni = parse_image_block(im, str);
if(infobar[conf.systray.screen].bar && d == infobar[conf.systray.screen].bar->dr)
if(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);
ostr = xstrdup(str);
textlen = strlen(ostr);
parse_image_block(d, str, True);
}
#endif /* HAVE_IMLIB */
/* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
#ifdef HAVE_XFT
if(conf.use_xft)
{
XftColor xftcolor;
XftDraw *xftd;
/* Alloc text color */
XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, SCREEN), fg, &xftcolor);
/* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
XftDrawStringUtf8(xftd, &xftcolor, font, x, y, (FcChar8 *)str, strlen(str));
/* Alloc text color */
XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, SCREEN), fg, &xftcolor);
/* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
XftDrawStringUtf8(xftd, &xftcolor, font.font, x, y, (FcChar8 *)str, strlen(str));
/* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
XftDrawDestroy(xftd);
}
else
#endif /* HAVE_XFT */
{
/* Use font set */
XSetForeground(dpy, gc, getcolor(fg));
XmbDrawString(dpy, d, font.fontset, gc, x, y, str, strlen(str));
}
XftDrawDestroy(xftd);
#ifdef HAVE_IMLIB
if(strstr(ostr, "i["))
if(textlen)
{
strncpy(str, ostr, textlen);
free(ostr);
free(ostr);
}
#endif /* HAVE_IMLIB */
return;
@@ -156,12 +203,10 @@ draw_image_ofset_text(Drawable d, int x, int y, char* fg, char *str, int x_image
* \param color Color of the rectangle
*/
void
draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color)
draw_rectangle(Drawable dr, int x, int y, int w, int h, uint color)
{
XRectangle r = { x, y, w, h };
XSetForeground(dpy, gc, color);
XFillRectangles(dpy, dr, gc, &r, 1);
XFillRectangle(dpy, dr, gc, x, y, (uint)w, (uint)h);
return;
}
@@ -176,18 +221,12 @@ draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color)
* \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)
draw_graph(Drawable dr, int x, int y, int w, int h, uint color, char *data)
{
uint i;
XSetForeground(dpy, gc, color);
int i;
for(i = 0; i < w; ++i)
{
XRectangle r = { (x + i), (y + h - data[i]), 1, data[i] };
XFillRectangles(dpy, dr, gc, &r, 1);
}
draw_rectangle(dr, x + i, y + h - data[i], 1, data[i], color);
return;
}
@@ -199,34 +238,48 @@ draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data)
ushort
textw(char *text)
{
XGlyphInfo gl;
#ifdef HAVE_IMLIB
char *ostr = NULL;
ImageAttr im[128];
size_t textlen;
#endif /* HAVE_IMLIB */
Drawable d = 0;
ushort ret = 0;
if(!text)
return 0;
#ifdef HAVE_IMLIB
ostr = xstrdup(text);
textlen = strlen(ostr);
char *ostr;
size_t textlen = 0;
if(strstr(text, "i["))
parse_image_block(im, text);
{
ostr = xstrdup(text);
textlen = strlen(ostr);
parse_image_block(d, text, False);
}
#endif /* HAVE_IMLIB */
XftTextExtentsUtf8(dpy, font, (FcChar8 *)text, strlen(text), &gl);
#ifdef HAVE_XFT
if(conf.use_xft)
{
XGlyphInfo gl;
XftTextExtentsUtf8(dpy, font.font, (FcChar8 *)text, strlen(text), &gl);
ret = gl.width + font.de;
}
else
#endif /* HAVE_XFT */
{
XRectangle r;
XmbTextExtents(font.fontset, text, strlen(text), NULL, &r);
ret = r.width;
}
#ifdef HAVE_IMLIB
if(strstr(ostr, "i["))
if(textlen)
{
strncpy(text, ostr, textlen);
free(ostr);
free(ostr);
}
#endif /* HAVE_IMLIB */
return gl.width + font->descent;
return ret;
}

View File

@@ -32,20 +32,46 @@
#include "wmfs.h"
#define EVDPY (e->xany.display)
#define MAX_EV 256
/** Check mouse bind condition and execute associated function
*/
static void
do_mousebind(int screen, uint button, int n, MouseBinding m[])
{
int i = 0;
for(; i < n; ++i)
{
if(m[i].screen == screen || m[i].screen < 0) /* Screen */
if(m[i].tag == seltag[i] || m[i].tag < 0) /* Tag */
if(m[i].button == button) /* Button */
if(m[i].func) /* Function */
m[i].func(m[i].cmd);
}
return;
}
/** ButtonPress handle event
* \param ev XButtonEvent pointer
*/
static void
buttonpress(XButtonEvent *ev)
buttonpress(XEvent *e)
{
XButtonEvent *ev = &e->xbutton;
StatusMouse *sm;
InfoBar *ib;
Client *c;
int i, j, n;
int i, n;
screen_get_sel();
ib = &infobar[selscreen];
/* If the mouse is on a not selected client and you click on it. */
if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window))) && c != sel
&& (ev->button == Button1 || ev->button == Button2 || ev->button == Button3))
if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window)))
&& c != sel && ev->button >= Button1 && ev->button <= Button3)
{
client_focus(c);
client_raise(c);
@@ -55,10 +81,7 @@ buttonpress(XButtonEvent *ev)
/* Titlebar */
if((c = client_gb_titlebar(ev->window)) && c == sel)
for(i = 0; i < conf.titlebar.nmouse; ++i)
if(ev->button == conf.titlebar.mouse[i].button)
if(conf.titlebar.mouse[i].func)
conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.titlebar.nmouse, conf.titlebar.mouse);
/* Titlebar buttons */
if((c = client_gb_button(ev->window, &n)))
@@ -76,98 +99,81 @@ buttonpress(XButtonEvent *ev)
/* Client */
if((c = client_gb_win(ev->window)) && c == sel)
for(i = 0; i < conf.client.nmouse; ++i)
if(ev->button == conf.client.mouse[i].button)
if(conf.client.mouse[i].func)
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.client.nmouse, conf.client.mouse);
/* Root */
if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i)
if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen]
|| conf.root.mouse[i].tag < 0)
if(ev->button == conf.root.mouse[i].button)
if(conf.root.mouse[i].func)
conf.root.mouse[i].func(conf.root.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.root.nmouse, conf.root.mouse);
/* Infobars */
for(i = 0; i < screen_count(); ++i)
if(ev->window == infobar[i].bar->win)
for(j = 0; j < conf.bars.nmouse; ++j)
if(conf.bars.mouse[j].screen == i
|| conf.bars.mouse[j].screen < 0)
if(conf.bars.mouse[j].tag == seltag[i]
|| conf.bars.mouse[j].tag < 0)
if(ev->button == conf.bars.mouse[j].button)
if(conf.bars.mouse[j].func)
conf.bars.mouse[j].func(conf.bars.mouse[j].cmd);
do_mousebind(i, ev->button, conf.bars.nmouse, conf.bars.mouse);
/* 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);
if(conf.bars.selbar && ev->window == ib->bar->win)
if(INAREA(ev->x, ev->y, ib->selbar_geo))
do_mousebind(selscreen, ev->button, conf.selbar.nmouse, conf.selbar.mouse);
/* Tags */
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(ev->window == infobar[selscreen].tags[i]->win)
{
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);
if(ib->tags_board)
{
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(ib->tags[i] && ev->window == ib->tags[i]->win)
{
do_mousebind(selscreen, ev->button, tags[selscreen][i].nmouse, tags[selscreen][i].mouse);
/* 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);
}
/* 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)
if(ib->layout_button && ev->window == ib->layout_button->win && conf.nlayout > 1)
{
if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */
{
menulayout.y = spgeo[selscreen].y + infobar[selscreen].layout_button->geo.y + INFOBARH;
menulayout.x = infobar[selscreen].layout_button->geo.x + (sgeo[selscreen].x - BORDH);
menulayout.y = spgeo[selscreen].y + ib->layout_button->geo.y + INFOBARH;
menulayout.x = ib->layout_button->geo.x + (sgeo[selscreen].x - BORDH);
if(infobar[selscreen].geo.y != spgeo[selscreen].y)
menulayout.y = infobar[selscreen].geo.y - (INFOBARH * menulayout.nitem) - SHADH;
if(ib->geo.y != spgeo[selscreen].y)
menulayout.y = ib->geo.y - (INFOBARH * menulayout.nitem) - SHADH;
uicb_menu("menulayout");
}
else
{
switch(ev->button)
{
case Button1: case Button4: layoutswitch(True); break;
case Button3: case Button5: layoutswitch(False); break;
}
}
layoutswitch(ev->button == Button1 || ev->button == Button4);
}
/* Status mouse bindings */
SLIST_FOREACH(sm, &smhead, next)
if(sm->infobar->bar->win == ev->window && ev->button == sm->button)
if(INAREA(ev->x, ev->y, sm->area))
if(sm->func)
sm->func(sm->cmd);
return;
}
/* ClientMessage handle event
*\param ev XClientMessageEvent pointer
*/
static void
clientmessageevent(XClientMessageEvent *ev)
clientmessageevent(XEvent *e)
{
XClientMessageEvent *ev = &e->xclient;
Client *c;
InfoBar *ib;
Systray *sy;
int s, i, mess_t = 0;
int s, mess_t = 0;
Atom rt;
int rf;
ulong ir, il;
@@ -180,9 +186,8 @@ clientmessageevent(XClientMessageEvent *ev)
s = screen_count();
for(i = 0; i < net_last + s; ++i)
if(net_atom[i] == ev->message_type)
mess_t = i;
while(mess_t < net_last + s && net_atom[mess_t] != ev->message_type)
++mess_t;
if(ev->window == ROOT)
{
@@ -204,7 +209,7 @@ clientmessageevent(XClientMessageEvent *ev)
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);
XSetInputFocus(EVDPY, sy->win, RevertToNone, CurrentTime);
}
}
else if(ev->window == traywin)
@@ -239,34 +244,38 @@ clientmessageevent(XClientMessageEvent *ev)
if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF)
tag_transfert(c, ev->data.l[0]);
/* Manage _WMFS_STATUSTEXT_x */
if(mess_t >= wmfs_statustext && ev->data.l[4] == True)
if(ev->data.l[4])
{
if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
/* Manage _WMFS_STATUSTEXT_x */
if(mess_t >= wmfs_statustext)
{
statustext_handle(mess_t - wmfs_statustext, (char*)ret);
if(XGetWindowProperty(EVDPY, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
{
ib = &infobar[mess_t - wmfs_statustext];
free(ib->statustext);
ib->statustext = xstrdup((char*)ret);
_infobar_draw(ib);
XFree(ret);
}
}
/* Manage _WMFS_FUNCTION && _WMFS_CMD */
if(mess_t == wmfs_function || mess_t == wmfs_cmd)
{
XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_function], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret);
XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_cmd], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd);
if((func = name_to_func((char*)ret, func_list)))
func((uicb_t)ret_cmd);
XFree(ret_cmd);
XFree(ret);
}
}
/* Manage _WMFS_FUNCTION && _WMFS_CMD */
if((mess_t == wmfs_function && ev->data.l[4] == True)
|| (mess_t == wmfs_cmd && ev->data.l[4] == True))
{
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_function], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret);
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_cmd], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd);
if((func = name_to_func((char*)ret, func_list)))
func((uicb_t)ret_cmd);
XFree(ret_cmd);
XFree(ret);
}
/* Manage _WMFS_UPDATE_HINTS */
if(mess_t == wmfs_update_hints)
{
@@ -279,30 +288,22 @@ clientmessageevent(XClientMessageEvent *ev)
screen_get_sel();
}
if(mess_t == wmfs_update_status
&& estatus)
spawn(conf.status_path);
return;
}
/** ConfigureRequesthandle events
* \param ev XConfigureRequestEvent pointer
*/
static void
configureevent(XConfigureRequestEvent *ev)
configureevent(XEvent *e)
{
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc;
Client *c;
/* Check part */
if((c = client_gb_win(ev->window))
|| (c = client_gb_win(ev->window)))
{
CHECK(!(c->flags & LMaxFlag));
CHECK(!(c->flags & MaxFlag));
CHECK(!(c->flags & FSSFlag));
}
if(((c = client_gb_win(ev->window)) || (c = client_gb_win(ev->window)))
&& (c->flags & (LMaxFlag | MaxFlag | FSSFlag)))
return;
if((c = client_gb_win(ev->window)))
{
@@ -315,7 +316,7 @@ configureevent(XConfigureRequestEvent *ev)
if(ev->value_mask & CWHeight)
c->geo.height = ev->height;
if(c->flags & FreeFlag || !(c->flags & (TileFlag | LMaxFlag)))
if(c->flags & FreeFlag || !(c->flags & TileFlag))
client_moveresize(c, c->geo, False);
else
{
@@ -333,18 +334,18 @@ configureevent(XConfigureRequestEvent *ev)
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XConfigureWindow(EVDPY, ev->window, ev->value_mask, &wc);
}
return;
}
/** DestroyNotify handle event
* \param ev XDestroyWindowEvent pointer
*/
static void
destroynotify(XDestroyWindowEvent *ev)
destroynotify(XEvent *e)
{
XDestroyWindowEvent *ev = &e->xdestroywindow;
Client *c;
Systray *s;
@@ -364,19 +365,24 @@ destroynotify(XDestroyWindowEvent *ev)
}
/** EnterNotify handle event
* \param ev XCrossingEvent pointer
*/
static void
enternotify(XCrossingEvent *ev)
enternotify(XEvent *e)
{
XCrossingEvent *ev = &e->xcrossing;
Client *c;
int n;
if((ev->mode != NotifyNormal
|| ev->detail == NotifyInferior)
&& ev->window != ROOT)
if((ev->mode != NotifyNormal || ev->detail == NotifyInferior)
&& ev->window != ROOT)
return;
if(tags[selscreen][seltag[selscreen]].flags & IgnoreEnterFlag)
{
tags[selscreen][seltag[selscreen]].flags &= ~IgnoreEnterFlag;
return;
}
/* Don't handle EnterNotify event if it's about systray */
if(systray_find(ev->window) || ev->window == traywin)
return;
@@ -397,27 +403,21 @@ enternotify(XCrossingEvent *ev)
}
/** ExposeEvent handle event
* \param ev XExposeEvent pointer
*/
static void
expose(XExposeEvent *ev)
expose(XEvent *e)
{
XExposeEvent *ev = &e->xexpose;
Client *c;
int i, sc;
BarWindow *bw;
/* InfoBar member */
for(sc = 0; sc < screen_count(); ++sc)
{
if(ev->window == infobar[sc].bar->win)
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]);
}
/* BarWindows */
SLIST_FOREACH(bw, &bwhead, next)
if(ev->window == bw->win)
{
barwin_refresh(bw);
break;
}
/* Client frame */
if((c = client_gb_titlebar(ev->window)))
@@ -427,28 +427,26 @@ expose(XExposeEvent *ev)
}
/** FocusChange handle event
* \param ev XFocusChangeEvent pointer
* \return
*/
static void
focusin(XFocusChangeEvent *ev)
focusin(XEvent *e)
{
if(sel && ev->window != sel->win)
if(sel && e->xfocus.window != sel->win)
client_focus(sel);
return;
}
/** KeyPress handle event
* \param ev XKeyPressedEvent pointer
*/
static void
keypress(XKeyPressedEvent *ev)
keypress(XEvent *e)
{
int i;
XKeyPressedEvent *ev = &e->xkey;
KeySym keysym;
int i;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
keysym = XKeycodeToKeysym(EVDPY, (KeyCode)ev->keycode, 0);
for(i = 0; i < conf.nkeybind; ++i)
if(keysym == keys[i].keysym
&& (keys[i].mod & ~(numlockmask | LockMask))
@@ -460,11 +458,11 @@ keypress(XKeyPressedEvent *ev)
}
/** MappingNotify handle event
* \param ev XMappingEvent pointer
*/
static void
mappingnotify(XMappingEvent *ev)
mappingnotify(XEvent *e)
{
XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
@@ -474,11 +472,11 @@ mappingnotify(XMappingEvent *ev)
}
/** MapNotify handle event
* \param ev XMapEvent pointer
*/
static void
mapnotify(XMapEvent *ev)
mapnotify(XEvent *e)
{
XMapEvent *ev = &e->xmap;
Client *c;
Systray *s;
@@ -497,15 +495,15 @@ mapnotify(XMapEvent *ev)
}
/** MapRequest handle event
* \param ev XMapRequestEvent pointer
*/
static void
maprequest(XMapRequestEvent *ev)
maprequest(XEvent *e)
{
XMapRequestEvent *ev = &e->xmaprequest;
XWindowAttributes at;
Systray *s;
CHECK(XGetWindowAttributes(dpy, ev->window, &at));
CHECK(XGetWindowAttributes(EVDPY, ev->window, &at));
CHECK(!at.override_redirect);
if((s = systray_find(ev->window)))
@@ -520,11 +518,11 @@ maprequest(XMapRequestEvent *ev)
}
/** PropertyNotify handle event
* \param ev XPropertyEvent pointer
*/
static void
propertynotify(XPropertyEvent *ev)
propertynotify(XEvent *e)
{
XPropertyEvent *ev = &e->xproperty;
Client *c;
Systray *s;
Window trans;
@@ -544,17 +542,15 @@ propertynotify(XPropertyEvent *ev)
switch(ev->atom)
{
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))))
arrange(c->screen, True);
XGetTransientForHint(EVDPY, c->win, &trans);
if((c->flags & (TileFlag | MaxFlag)) && client_gb_win(trans))
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)
if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
{
client_urgent(c, True);
XFree(h);
@@ -574,10 +570,9 @@ propertynotify(XPropertyEvent *ev)
}
/** XReparentEvent handle event
* \param ev XReparentEvent pointer
*/
static void
reparentnotify(XReparentEvent *ev)
reparentnotify(XEvent *ev)
{
(void)ev;
@@ -585,13 +580,12 @@ reparentnotify(XReparentEvent *ev)
}
/** SelectionClearEvent handle event
* \param ev XSelectionClearEvent pointer
*/
static void
selectionclearevent(XSelectionClearEvent *ev)
selectionclearevent(XEvent *ev)
{
/* Getting selection if lost it */
if(ev->window == traywin)
if(ev->xselectionclear.window == traywin)
systray_acquire();
systray_update();
@@ -600,11 +594,11 @@ selectionclearevent(XSelectionClearEvent *ev)
}
/** UnmapNotify handle event
* \param ev XUnmapEvent pointer
*/
static void
unmapnotify(XUnmapEvent *ev)
unmapnotify(XEvent *e)
{
XUnmapEvent *ev = &e->xunmap;
Client *c;
Systray *s;
@@ -626,23 +620,41 @@ unmapnotify(XUnmapEvent *ev)
}
/** XMotionNotify handle event
* \param ev XMotionEvent pointer
*/
static void
motionnotify(XMotionEvent *ev)
motionnotify(XEvent *e)
{
XMotionEvent *ev = &e->xmotion;
Client *c;
if(!conf.focus_fmouse || !conf.focus_fmov)
return;
if((c = client_gb_win(ev->subwindow)))
if (c != sel)
if(c != sel)
client_focus(c);
return;
}
/** XRandr handle event
*/
#ifdef HAVE_XRANDR
void
xrandrevent(XEvent *e)
{
/* Update xrandr configuration */
if(!XRRUpdateConfiguration(e))
return;
/* Reload WMFS to update the screen(s) geometry changement */
quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execvp(argv_global, all_argv);
}
#endif /* HAVE_XRANDR */
/** Key grabbing function
*/
void
@@ -664,49 +676,41 @@ grabkeys(void)
return;
}
/** Event handle function: execute every function
* handle by event
* \param ev Event
*/
/** Make event handle function pointer array
*/
void
getevent(XEvent ev)
event_make_array(void)
{
int i = MAX_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 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:
event_handle = xcalloc(MAX_EV, sizeof(event_handle));
/* Fill array with non-used function (do nothing) */
while(i--)
event_handle[i] = reparentnotify;
event_handle[ButtonPress] = buttonpress;
event_handle[ClientMessage] = clientmessageevent;
event_handle[ConfigureRequest] = configureevent;
event_handle[DestroyNotify] = destroynotify;
event_handle[EnterNotify] = enternotify;
event_handle[Expose] = expose;
event_handle[FocusIn] = focusin;
event_handle[KeyPress] = keypress;
event_handle[MapNotify] = mapnotify;
event_handle[MapRequest] = maprequest;
event_handle[MappingNotify] = mappingnotify;
event_handle[MotionNotify] = motionnotify;
event_handle[PropertyNotify] = propertynotify;
event_handle[ReparentNotify] = reparentnotify;
event_handle[SelectionClear] = selectionclearevent;
event_handle[UnmapNotify] = unmapnotify;
#ifdef HAVE_XRANDR
/* Check Xrandr event */
if(ev.type == xrandr_event)
{
/* Update xrandr configuration */
XRRUpdateConfiguration(&ev);
/* Reload WMFS to update the screen(s) geometry changement */
quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execvp(argv_global, all_argv);
}
event_handle[xrandr_event + RRScreenChangeNotify] = xrandrevent;
#endif /* HAVE_XRANDR */
break;
}
return;
}

View File

@@ -43,7 +43,7 @@ void
ewmh_init_hints(void)
{
int i = 1, s, j, showing_desk = 0;
char root_name[] = WMFS_VERSION;
char rootn[] = "wmfs-"WMFS_VERSION;
char class[] = "wmfs", st[64];
long pid = (long)getpid();
char systray_atom[48];
@@ -95,7 +95,6 @@ ewmh_init_hints(void)
/* WMFS hints */
net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
net_atom[wmfs_update_status] = ATOM("_WMFS_UPDATE_STATUS");
net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
@@ -126,7 +125,7 @@ ewmh_init_hints(void)
PropModeReplace, (uchar*)&ROOT, 1);
XChangeProperty(dpy, ROOT, net_atom[net_wm_name], net_atom[utf8_string], 8,
PropModeReplace, (uchar*)&root_name, strlen(root_name));
PropModeReplace, (uchar*)&rootn, strlen(rootn));
XChangeProperty(dpy, ROOT, ATOM("WM_CLASS"), XA_STRING, 8,
PropModeReplace, (uchar*)&class, strlen(class));
@@ -251,13 +250,16 @@ ewmh_get_client_list(void)
{
Window *list;
Client *c;
int win_n;
int win_n = 0;
SLIST_FOREACH(c, &clients, next)
++win_n;
for(win_n = 0, c = clients; c; c = c->next, ++win_n);
list = xcalloc(win_n, sizeof(Window));
for(win_n = 0, c = clients; c; c = c->next, ++win_n)
list[win_n] = c->win;
win_n = 0;
SLIST_FOREACH(c, &clients, next)
list[win_n++] = c->win;
XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32,
PropModeReplace, (uchar *)list, win_n);
@@ -423,7 +425,7 @@ ewmh_manage_window_type(Client *c)
c->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(c, c->ogeo, True);
client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
layout_func(selscreen, seltag[selscreen]);
}
}
XFree(data);

View File

@@ -87,8 +87,8 @@ frame_create(Client *c)
for(i = 0; i < conf.titlebar.nbutton; ++i)
{
CWIN(c->button[i], c->titlebar->win,
(c->button_last_x = (BORDH + (BUTTONWH * i) + (4 * i))),
((BUTTONWH - 1) / 2), BUTTONWH, BUTTONWH,
(c->button_last_x = (BORDH + (BUTTONWH * i) + (i << 2))),
((BUTTONWH - 1) >> 1), BUTTONWH, BUTTONWH,
1, CWEventMask|CWOverrideRedirect|CWBackPixmap,
c->colors.frame, &at);
@@ -158,7 +158,7 @@ frame_delete(Client *c)
* \param geo Coordinate info for move the frame
*/
void
frame_moveresize(Client *c, XRectangle geo)
frame_moveresize(Client *c, Geo geo)
{
CHECK(c);
@@ -198,7 +198,7 @@ frame_moveresize(Client *c, XRectangle geo)
*\param c Client pointer
*/
void
frame_update_color(Client *c, Bool focused)
frame_update_color(Client *c, bool focused)
{
CHECK(c);
@@ -209,7 +209,7 @@ frame_update_color(Client *c, Bool focused)
c->colors.fg = conf.titlebar.fg_normal;
c->colors.resizecorner = conf.client.resizecorner_normal;
if(TBARH - BORDH && c->titlebar->stipple)
if(TBARH - BORDH)
c->titlebar->stipple_color = conf.titlebar.stipple.colors.normal;
}
/* Focused */
@@ -219,7 +219,7 @@ frame_update_color(Client *c, Bool focused)
c->colors.fg = conf.titlebar.fg_focus;
c->colors.resizecorner = conf.client.resizecorner_focus;
if(TBARH - BORDH && c->titlebar->stipple)
if(TBARH - BORDH)
c->titlebar->stipple_color = conf.titlebar.stipple.colors.focus;
}
@@ -254,8 +254,8 @@ frame_update(Client *c)
if(conf.titlebar.nbutton && BUTTONWH >= 1)
{
if(conf.titlebar.stipple.active)
draw_rectangle(c->titlebar->dr, 0, 0, c->button_last_x + TBARH - (TBARH / 4),
TBARH + BORDH * 2, c->colors.frame);
draw_rectangle(c->titlebar->dr, 0, 0, c->button_last_x + TBARH - (TBARH >> 2),
TBARH + (BORDH << 2), c->colors.frame);
for(i = 0; i < conf.titlebar.nbutton; ++i)
{
@@ -265,8 +265,8 @@ frame_update(Client *c)
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 & MaxFlag)
&& ((c->flags & MaxFlag) || (c->flags & LMaxFlag)))
|| ((conf.titlebar.button[i].flags & TileFlag) && (c->flags & TileFlag)))
{
@@ -285,8 +285,6 @@ frame_update(Client *c)
XSetWindowBorder(dpy, c->button[i], c->colors.frame);
}
}
barwin_refresh(c->titlebar);
}
XSetWindowBackground(dpy, c->frame, c->colors.frame);
@@ -312,9 +310,9 @@ frame_update(Client *c)
if(TBARH - BORDH)
barwin_draw_text(c->titlebar,
(c->frame_geo.width / 2) - (textw(c->title) / 2),
((font->height - font->descent) + (TBARH - font->height) / 2),
c->title);
(c->frame_geo.width >> 1) - (textw(c->title) >> 1),
((font.height - font.de) + ((TBARH - font.height) >> 1)),
c->title);
return;
}

View File

@@ -1,203 +0,0 @@
/*
* getinfo.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"
/* Global variables for each XGetWindowProperty
* of each getinfo functions.
*/
Atom rt;
int rf;
ulong ir, il;
uchar *ret;
/** Get information about tag (current, list, names)
*/
static void
getinfo_tag(void)
{
int tag = 0;
char *tag_name = NULL;
char *tag_list = NULL;
if(XGetWindowProperty(dpy, ROOT, ATOM("_NET_CURRENT_DESKTOP"), 0L, 4096,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
tag = (int)*ret + 1;
XFree(ret);
}
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_CURRENT_TAG"), 0L, 4096,
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && 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 = xstrdup((char*)ret);
XFree(ret);
}
printf("Current tag: %d - %s\n", tag, tag_name);
printf("Tag list: %s\n", tag_list);
free(tag_name);
free(tag_list);
return;
}
/** Get information about screens
*/
static void
getinfo_screen(void)
{
int screen = 1;
int screen_num = 1;
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_CURRENT_SCREEN"), 0L, 4096,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
screen = (int)*ret + 1;
XFree(ret);
}
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_SCREEN_COUNT"), 0L, 4096,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
screen_num = (int)*ret;
XFree(ret);
}
printf("Current screen: %d\nScreen number: %d\n", screen, screen_num);
return;
}
/** Get current layout name
*/
static void
getinfo_layout(void)
{
char *layout = NULL;
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_CURRENT_LAYOUT"), 0L, 4096,
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && ret)
{
layout = xstrdup((char*)ret);
XFree(ret);
}
printf("Current layout: %s\n", layout);
free(layout);
return;
}
/** Get information about current mwfact
*/
static void
getinfo_mwfact(void)
{
char *mwfact = NULL;
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_MWFACT"), 0L, 4096,
False, XA_STRING, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
mwfact = xstrdup((char*)ret);
XFree(ret);
}
printf("Current mwfact: %s\n", mwfact);
free(mwfact);
return;
}
/** Get information about current nmaster
*/
static void
getinfo_nmaster(void)
{
int nmaster = 1;
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_NMASTER"), 0L, 4096,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
nmaster = (int)*ret;
XFree(ret);
}
printf("Current nmaster: %d\n", nmaster);
return;
}
/** Get information about wmfs
*\param info Type of information in a string
*/
void
getinfo(char *info)
{
if(!check_wmfs_running())
return;
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_HINTS", 0, 0, 0, 0, True);
if(!strcmp(info, "tag"))
getinfo_tag();
else if(!strcmp(info, "screen"))
getinfo_screen();
else if(!strcmp(info, "layout"))
getinfo_layout();
else if(!strcmp(info, "mwfact"))
getinfo_mwfact();
else if(!strcmp(info, "nmaster"))
getinfo_nmaster();
else if(!strcmp(info, "help"))
printf("Argument list for wmfs -g options:\n"
" tag Show current tag number and name, and tag list.\n"
" screen Show current screen and screens number.\n"
" layout Show current layout name.\n"
" mwfact Show mwfact of current tag.\n"
" nmaster Show nmaster of current tag.\n");
else
warnx("Unknow info argument '%s'\nTry 'wmfs -g help'", info);
return;
}

View File

@@ -32,138 +32,257 @@
#include "wmfs.h"
/** Init the Infobar
#define SPLIT_IND_S (3 + conf.border.layout)
/** Init InfoBar elements
*/
static void
infobar_init_element(InfoBar *i)
{
int j = 0, k, n = 0;
InfobarElem *e, *prev = NULL;
Geo pg = { -PAD, 0, 0, 0 };
STAILQ_INIT(&i->elemhead);
for(; n < (int)strlen(i->elemorder); ++n)
{
e = zcalloc(sizeof(InfobarElem));
/* Previous element geo */
if(prev)
pg = prev->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
e->geo.height = i->geo.height;
switch(i->elemorder[n])
{
/* Tags element */
case 't':
e->type = ElemTag;
e->geo.width = PAD; /* Will change */
if(!i->tags_board)
{
i->tags_board = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.bar, conf.colors.text,
False, False, False);
/* Create tags window */
for(k = 1; k < conf.ntag[i->screen] + 1; ++k)
{
i->tags[k] = barwin_create(i->tags_board->win,
j, 0,
textw(tags[i->screen][k].name) + PAD,
i->geo.height,
conf.colors.bar, conf.colors.text,
False, False, conf.border.tag);
j += textw(tags[i->screen][k].name) + PAD;
barwin_map_subwin(i->tags[k]);
}
}
barwin_resize(i->tags_board, (e->geo.width = j), i->geo.height);
barwin_map(i->tags_board);
barwin_map_subwin(i->tags_board);
break;
/* Layout button element */
case 'l':
e->type = ElemLayout;
e->geo.width = (conf.layout_button_width > 0
? (uint)conf.layout_button_width
: textw(tags[i->screen][seltag[i->screen]].layout.symbol) + PAD);
if(!i->layout_button)
i->layout_button = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout);
barwin_map(i->layout_button);
if(conf.border.layout)
barwin_map_subwin(i->layout_button);
break;
/* Selbar element */
case 's':
e->type = ElemSelbar;
i->selbar_geo = e->geo;
break;
}
STAILQ_INSERT_TAIL(&i->elemhead, e, next);
prev = e;
e = NULL;
}
return;
}
/** Init the InfoBar
*/
void
infobar_init(void)
{
int s, sc, i, j = 0;
s = screen_count();
InfoBar *i;
int s = screen_count(), sc = 0;
if(!infobar)
infobar = xcalloc(s, sizeof(InfoBar));
for(sc = 0; sc < s; ++sc)
for(; sc < s; ++sc)
{
j = 0;
infobar[sc].geo.height = INFOBARH;
i = &infobar[sc];
i->geo.height = INFOBARH;
i->screen = sc;
i->elemorder = conf.bars.element_order;
switch(tags[sc][seltag[sc]].barpos)
{
case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH;
infobar[sc].geo.y = -(infobar[sc].geo.height) * 2;
break;
case IB_Bottom:
sgeo[sc].y = TBARH;
infobar[sc].geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
break;
default:
case IB_Top:
sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
infobar[sc].geo.y = spgeo[sc].y;
break;
case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH;
i->geo.y = (-(i->geo.height) << 2);
break;
case IB_Bottom:
sgeo[sc].y = TBARH;
i->geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
break;
default:
case IB_Top:
sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
i->geo.y = spgeo[sc].y;
break;
}
/* Create infobar barwindow */
infobar[sc].bar = barwin_create(ROOT, sgeo[sc].x - BORDH, infobar[sc].geo.y,
sgeo[sc].width, infobar[sc].geo.height,
conf.colors.bar, conf.colors.text, False, False, conf.border.bar);
i->bar = barwin_create(ROOT,
sgeo[sc].x - BORDH,
i->geo.y,
sgeo[sc].width,
i->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);
barwin_map(i->bar);
barwin_map_subwin(i->bar);
barwin_refresh_color(i->bar);
barwin_refresh(i->bar);
/* Create tags window */
for(i = 1; i < conf.ntag[sc] + 1; ++i)
{
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,
((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);
/* Init elements */
infobar_init_element(i);
/* Default statustext is set here */
infobar[sc].statustext = xstrdup(WMFS_VERSION);
i->statustext = xstrdup("wmfs"WMFS_VERSION);
infobar_draw(sc);
infobar_draw(i);
}
return;
}
static void
infobar_arrange_element(InfoBar *i)
{
Geo pg = { -PAD, 0, 0, 0 };
InfobarElem *e, *pe = NULL;
STAILQ_FOREACH(e, &i->elemhead, next)
{
if(pe)
pg = pe->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
if(e->type != ElemSelbar)
barwin_move((e->type == ElemTag ? i->tags_board : i->layout_button), e->geo.x, e->geo.y);
pe = e;
}
return;
}
/** Draw the layout button in the InfoBar
*\param sc Screen number
*\param i InfoBar pointer
*/
static void
infobar_draw_layout(int sc)
void
infobar_draw_layout(InfoBar *i)
{
if(!conf.layout_placement)
barwin_move(infobar[sc].layout_button, infobar[sc].tags_board->geo.width + PAD / 2, 0);
InfobarElem *e;
int s = i->screen;
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);
/* Check if there is element in string element list */
if(!strchr(i->elemorder, 'l'))
return;
if(tags[sc][seltag[sc]].layout.symbol)
barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemLayout)
break;
e->geo.width = (conf.layout_button_width >= 1)
? conf.layout_button_width
: (int)(textw(tags[s][seltag[s]].layout.symbol) + PAD);
barwin_resize(i->layout_button, e->geo.width, e->geo.height);
barwin_refresh_color(i->layout_button);
/* Split mode indicator; little rectangle at bottom-right */
if(tags[s][seltag[s]].flags & SplitFlag)
draw_rectangle(i->layout_button->dr,
e->geo.width - SPLIT_IND_S,
e->geo.height - SPLIT_IND_S,
SPLIT_IND_S, SPLIT_IND_S,
getcolor(i->layout_button->fg));
if(tags[s][seltag[s]].layout.symbol)
barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[s][seltag[s]].layout.symbol);
return;
}
/** Draw the Infobar
*\param sc Screen number
/** Draw Infobar barwin (selbar / statustext)
*\param i Infobar pointer
*/
void
_infobar_draw(InfoBar *i)
{
barwin_refresh_color(i->bar);
infobar_draw_selbar(i);
statustext_handle(i);
barwin_refresh(i->bar);
infobar_arrange_element(i);
return;
}
/** Draw the InfoBar
*\param i InfoBar pointer
*/
void
infobar_draw(int sc)
infobar_draw(InfoBar *i)
{
infobar_draw_taglist(sc);
infobar_draw_layout(sc);
infobar_draw_selbar(sc);
barwin_refresh_color(infobar[sc].bar);
statustext_handle(sc, infobar[sc].statustext);
infobar_draw_taglist(i);
infobar_draw_layout(i);
_infobar_draw(i);
return;
}
@@ -172,151 +291,152 @@ infobar_draw(int sc)
*\param sc Screen Number
*/
void
infobar_draw_selbar(int sc)
infobar_draw_selbar(InfoBar *i)
{
InfobarElem *e;
char *str = NULL;
int sc = i->screen;
bool f = False;
if(!conf.bars.selbar)
return;
if(!sel || (sel && sel->screen != sc))
{
barwin_unmap(infobar[sc].selbar);
if(!strchr(i->elemorder, 's'))
return;
}
else if(sel && !infobar[sc].selbar->mapped)
barwin_map(infobar[sc].selbar);
if(conf.selbar.maxlength >= 0 && sel)
if(!sel || (sel && sel->screen != sc))
return;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemSelbar)
break;
str = sel->title;
/* Truncate string if too long */
if(conf.selbar.maxlength >= 0 && sel && sel->title)
{
str = NULL;
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, "...");
f = True;
}
barwin_resize(infobar[sc].selbar, textw(str ? str : sel->title) + PAD, infobar[sc].geo.height - 2);
XSetForeground(dpy, gc, conf.selbar.bg);
XFillRectangle(dpy, i->bar->dr, gc,
e->geo.x,
e->geo.y,
(e->geo.width = textw(str) + PAD),
e->geo.height);
draw_text(i->bar->dr, e->geo.x, FHINFOBAR, conf.selbar.fg, str);
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);
if(f)
free(str);
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);
i->selbar_geo = e->geo;
return;
}
/** Draw the taglist in the InfoBar
*\param sc Screen number
*\param i InfoBar pointer
*/
void
infobar_draw_taglist(int sc)
infobar_draw_taglist(InfoBar *i)
{
int i, x;
Client *c = NULL;
Bool is_occupied[MAXTAG + 1];
InfobarElem *e;
Client *c;
int j = 1, x = 0, sc = i->screen;
uint occupied = 0;
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);
if(!strchr(i->elemorder, 't'))
return;
for(i = 0; i < MAXTAG; i++)
is_occupied[i] = False;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemTag)
break;
for(c = clients; c; c = c->next)
if(c->screen == sc && c->tag != MAXTAG + 1)
is_occupied[c->tag] = True;
SLIST_FOREACH(c, &clients, next)
if(c->screen == sc)
occupied |= TagFlag(c->tag);
for(i = 1, x = 0; i < conf.ntag[sc] + 1; ++i)
for(; j < conf.ntag[sc] + 1; ++j)
{
/* Autohide tag feature */
if(conf.tagautohide)
{
if(!is_occupied[i] && i != seltag[sc])
if(!(occupied & TagFlag(j)) && j != seltag[sc])
{
barwin_unmap(infobar[sc].tags[i]);
barwin_unmap(i->tags[j]);
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);
barwin_map(i->tags[j]);
barwin_move(i->tags[j], x, 0);
barwin_resize(i->tags_board, (e->geo.width = (x += i->tags[j]->geo.width)), e->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));
if(tags[sc][j].flags & TagUrgentFlag)
{
i->tags[j]->bg = conf.colors.tagurbg;
i->tags[j]->fg = conf.colors.tagurfg;
}
else if(j == seltag[sc] || tags[sc][seltag[sc]].tagad & TagFlag(j))
{
i->tags[j]->bg = conf.colors.tagselbg;
i->tags[j]->fg = conf.colors.tagselfg;
}
else
{
i->tags[j]->bg = ((occupied & TagFlag(j)) ? conf.colors.tag_occupied_bg : conf.colors.bar);
i->tags[j]->fg = ((occupied & TagFlag(j)) ? conf.colors.tag_occupied_fg : conf.colors.text);
}
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(i->tags[j], i->tags[j]->bg, i->tags[j]->fg);
barwin_refresh_color(i->tags[j]);
barwin_color_set(infobar[sc].tags[i], infobar[sc].tags[i]->bg, infobar[sc].tags[i]->fg);
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);
if(tags[sc][j].name)
barwin_draw_text(i->tags[j], (PAD >> 1), FHINFOBAR, tags[sc][j].name);
}
return;
}
/** Update taglist geo
*\param sc Screen number
*\param i InfoBar pointer
*/
void
infobar_update_taglist(int sc)
infobar_update_taglist(InfoBar *i)
{
int i, j;
int t, j, sc = i->screen;
for(i = 1, j = 0; i < conf.ntag[sc] + 1; ++i)
for(t = 1, j = 0; t < conf.ntag[sc] + 1; ++t)
{
/* If the tag i does not exist yet (graphically) or need full update */
if(!infobar[sc].tags[i] || infobar[sc].need_update)
/* If the tag t does not exist yet (graphically) or need full update */
if(!i->tags[t] || i->need_update)
{
infobar[sc].tags[i] = barwin_create(infobar[sc].tags_board->win, j, 0,
textw(tags[sc][i].name) + PAD,
infobar[sc].geo.height,
i->tags[t] = barwin_create(i->tags_board->win, j, 0,
textw(tags[sc][t].name) + PAD,
i->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);
barwin_map(i->tags[t]);
barwin_map_subwin(i->tags[t]);
barwin_resize(i->tags_board, (j += textw(tags[sc][t].name) + PAD), i->geo.height);
continue;
}
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);
barwin_move(i->tags[t], j, 0);
barwin_resize(i->tags[t], textw(tags[sc][t].name) + PAD, i->geo.height);
barwin_resize(i->tags_board, (j += textw(tags[sc][t].name) + PAD), i->geo.height);
}
infobar[sc].need_update = False;
i->need_update = False;
return;
}
@@ -326,6 +446,7 @@ infobar_update_taglist(int sc)
void
infobar_destroy(void)
{
InfobarElem *e;
int sc, i;
for(sc = 0; sc < screen_count(); ++sc)
@@ -341,9 +462,17 @@ infobar_destroy(void)
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);
/* Free elements */
while(!STAILQ_EMPTY(&infobar[sc].elemhead))
{
e = STAILQ_FIRST(&infobar[sc].elemhead);
STAILQ_REMOVE_HEAD(&infobar[sc].elemhead, next);
free(e);
}
}
return;
@@ -359,28 +488,27 @@ infobar_set_position(int pos)
switch(pos)
{
case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = -(infobar[selscreen].geo.height) * 2;
break;
case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
break;
default:
case IB_Top:
sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y;
break;
case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = (-(infobar[selscreen].geo.height) << 1);
break;
case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
break;
default:
case IB_Top:
sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y;
break;
}
tags[selscreen][seltag[selscreen]].barpos = pos;
barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
infobar_draw(selscreen);
arrange(selscreen, True);
return;
@@ -415,8 +543,7 @@ uicb_infobar_toggledisplay(uicb_t cmd)
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 : 2));
tags[selscreen][seltag[selscreen]].prev_barpos = tags[selscreen][seltag[selscreen]].barpos;
tags[selscreen][seltag[selscreen]].barpos = new_pos;
@@ -442,9 +569,7 @@ uicb_toggle_tagautohide(uicb_t cmd)
{
for(i = 1, x = 0; i < conf.ntag[selscreen] + 1; ++i)
{
if(!infobar[selscreen].tags[i]->mapped)
barwin_map(infobar[selscreen].tags[i]);
barwin_map(infobar[selscreen].tags[i]);
barwin_move(infobar[selscreen].tags[i], x, 0);
x += infobar[selscreen].tags[i]->geo.width;
}
@@ -452,7 +577,7 @@ uicb_toggle_tagautohide(uicb_t cmd)
barwin_resize(infobar[selscreen].tags_board, x, infobar[selscreen].geo.height);
}
infobar_draw(selscreen);
infobar_draw(&infobar[selscreen]);
return;
}

View File

@@ -60,12 +60,50 @@ const func_name_list_t layout_list[] =
static void
init_font(void)
{
font = XftFontOpenName(dpy, SCREEN, conf.font);
if(!font)
#ifdef HAVE_XFT
if(conf.use_xft)
{
warnx("WMFS Error: Cannot initialize font");
font = XftFontOpenName(dpy, SCREEN, "sans-10");
if(!(font.font = XftFontOpenName(dpy, SCREEN, conf.font)))
{
warnx("WMFS Error: Cannot initialize Xft font");
font.font = XftFontOpenName(dpy, SCREEN, "sans-10");
}
font.de = font.font->descent;
font.as = font.font->ascent;
font.height = font.font->height;
}
else
#endif /* HAVE_XFT */
{
char **misschar, **names, *defstring;
int d;
XFontStruct **xfs = NULL;
/* locale support */
setlocale(LC_CTYPE, "");
if(!conf.font)
conf.font = xstrdup("fixed");
/* Using Font Set */
if(!(font.fontset = XCreateFontSet(dpy, conf.font, &misschar, &d, &defstring)))
{
warnx("Can't load font '%s'", conf.font);
font.fontset = XCreateFontSet(dpy, "fixed", &misschar, &d, &defstring);
}
XExtentsOfFontSet(font.fontset);
XFontsOfFontSet(font.fontset, &xfs, &names);
font.as = xfs[0]->max_bounds.ascent;
font.de = xfs[0]->max_bounds.descent;
font.width = xfs[0]->max_bounds.width;
font.height = font.as + font.de;
if(misschar)
XFreeStringList(misschar);
}
/* Set font in _WMFS_FONT for eventual status tools */
@@ -158,48 +196,17 @@ init_root(void)
return;
}
/** Init statustext shell script
*/
static void
init_status(void)
{
struct stat st;
char *home;
conf.status_pid = -1;
estatus = False;
if(!conf.status_path)
{
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;
}
if(st.st_size && st.st_mode & S_IXUSR)
estatus = True;
else
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)
{
/* Init lists heads */
SLIST_INIT(&bwhead);
SLIST_INIT(&smhead);
SLIST_INIT(&clients);
SLIST_INIT(&trayicons);
/* First init */
ewmh_init_hints();
init_conf();
@@ -209,9 +216,9 @@ init(void)
init_key();
init_root();
screen_init_geo();
event_make_array();
infobar_init();
systray_acquire();
init_status();
ewmh_update_current_tag_prop();
grabkeys();

View File

@@ -182,23 +182,24 @@ static void
launcher_execute(Launcher *launcher)
{
BarWindow *bw;
Bool found;
Bool lastwastab = False;
Bool my_guitar_gently_wheeps = True;
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 i, pos = 0, histpos = 0, w, x = 0;
int tabhits = 0;
KeySym ks;
XEvent ev;
InfobarElem *e;
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);
STAILQ_FOREACH(e, &infobar[selscreen].elemhead, next)
if(x < (e->geo.x + e->geo.width))
x = e->geo.x + e->geo.width + PAD;
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
@@ -354,14 +355,15 @@ launcher_execute(Launcher *launcher)
barwin_draw_text(bw, 1 + textw(launcher->prompt) + textw(" "), FHINFOBAR - 1, buf);
barwin_refresh(bw);
}
else
getevent(ev);
else if(ev.type < nevent && ev.type > 0)
HANDLE_EVENT(&ev);
XNextEvent(dpy, &ev);
}
barwin_unmap(bw);
barwin_delete(bw);
infobar_draw(selscreen);
infobar_draw(&infobar[selscreen]);
XUngrabKeyboard(dpy, CurrentTime);

View File

@@ -35,14 +35,14 @@
/** Arrange All
*/
void
arrange(int screen, Bool update_layout)
arrange(int screen, bool update_layout)
{
Client *c;
if(screen < 0 || screen > screen_count() - 1)
screen = screen_get_sel();
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->screen == screen)
{
if(!ishide(c, screen))
@@ -54,9 +54,26 @@ arrange(int screen, Bool update_layout)
if(tags[screen][seltag[screen]].layout.func)
{
if(update_layout)
tags[screen][seltag[screen]].layout.func(screen);
layout_func(screen, seltag[screen]);
infobar_draw(screen);
infobar_draw(&infobar[screen]);
}
return;
}
/** Apply layout function
*/
void
layout_func(int screen, int tag)
{
if((tags[screen][tag].flags & SplitFlag)
&& !(tags[screen][tag].flags & FirstArrangeFlag))
split_apply_current(screen, tag);
else
{
tags[screen][tag].layout.func(screen);
tags[screen][tag].flags &= ~FirstArrangeFlag;
}
return;
@@ -70,10 +87,10 @@ freelayout(int screen)
Client *c;
(void)screen;
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(!ishide(c, selscreen)
&& c->screen == screen_get_sel()
&& !(c->flags & MaxFlag))
&& c->screen == screen
&& !(c->flags & MaxFlag))
{
client_moveresize(c, c->free_geo, True);
c->flags &= ~(TileFlag | LMaxFlag);
@@ -85,18 +102,18 @@ freelayout(int screen)
}
/** Layout switching function
* \param b Bool True : next False : previous
* \param b bool True : next False : previous
*/
void
layoutswitch(Bool b)
layoutswitch(bool b)
{
int i;
Client *c;
Client *c = SLIST_FIRST(&clients);
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
for(c = clients; c && (c->tag != (uint)seltag[selscreen] && c->screen != selscreen); c = c->next)
for(; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = SLIST_NEXT(c, next))
{
c->ogeo = c->geo;
c->free_geo = c->geo;
@@ -116,8 +133,12 @@ layoutswitch(Bool b)
}
ewmh_update_current_tag_prop();
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
infobar_draw(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
layout_func(selscreen, seltag[selscreen]);
infobar_draw(&infobar[selscreen]);
return;
}
@@ -151,15 +172,12 @@ uicb_layout_prev(uicb_t cmd)
* \param c Client pointer
* \return a client pointer
*/
static Client*
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);
for(; c && (c->flags & (MaxFlag | FreeFlag | FSSFlag | AboveFlag)
|| c->screen != screen
|| ishide(c, screen)); c = SLIST_NEXT(c, next));
if(c)
c->flags |= FLayFlag;
@@ -172,10 +190,10 @@ tiled_client(int screen, Client *c)
void
maxlayout(int screen)
{
Client *c;
int i;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
int i = 0;
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
c->flags &= ~TileFlag;
c->flags |= LMaxFlag;
@@ -204,7 +222,7 @@ uicb_set_mwfact(uicb_t cmd)
return;
tags[selscreen][seltag[selscreen]].mwfact += c;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
layout_func(selscreen, seltag[selscreen]);
ewmh_update_current_tag_prop();
@@ -217,19 +235,20 @@ uicb_set_mwfact(uicb_t cmd)
void
uicb_set_nmaster(uicb_t cmd)
{
int nc, n = atoi(cmd);
Client *c;
int nc = 0, n = atoi(cmd);
Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel();
for(nc = 0, c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next), ++nc);
for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)), ++nc);
if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0
|| tags[selscreen][seltag[selscreen]].nmaster + n > nc)
return;
tags[selscreen][seltag[selscreen]].nmaster += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
ewmh_update_current_tag_prop();
@@ -239,17 +258,17 @@ uicb_set_nmaster(uicb_t cmd)
/** Grid layout function
*/
static void
grid(int screen, Bool horizontal)
grid(int screen, bool horizontal)
{
Client *c;
XRectangle sg = sgeo[screen];
XRectangle cgeo = {sg.x, sg.y, 0, 0};
unsigned int i, n, temp, cols, rows, cpcols = 0;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo cgeo = {sg.x, sg.y, 0, 0};
unsigned int i = 0, n = 0, temp, cols, rows, cpcols = 0;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
for(rows = 0; rows <= n / 2; ++rows)
for(rows = 0; rows <= (n >> 1); ++rows)
if(rows * rows >= n)
break;
@@ -264,13 +283,16 @@ grid(int screen, Bool horizontal)
rows = temp;
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
++cpcols;
cgeo.width = (sg.width / cols) - (BORDH * 2);
cfactor_clean(c);
cgeo.width = (sg.width / cols) - (BORDH << 1);
cgeo.height = (sg.height / rows) - BORDH;
/* Last row's and last client remainder */
@@ -279,22 +301,23 @@ grid(int screen, Bool horizontal)
/* Last column's client remainder */
if(i >= rows * (cols - 1))
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH << 1)));
/* Resize */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
/* Set all the other size with current client info */
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
if(cpcols + 1 > rows)
{
cpcols = 0;
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH << 1);
cgeo.y = sg.y;
}
}
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -306,14 +329,14 @@ grid(int screen, Bool horizontal)
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 = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, 0, 0};
Geo cgeo = {sg.x, sg.y, 0, 0};
int i = 0, n = 0, 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);
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
/* FIX NMASTER */
nmaster = (n < nmaster) ? n : nmaster;
@@ -324,50 +347,51 @@ multi_tile(int screen, Position type)
: tags[screen][seltag[screen]].mwfact * sg.width;
/* MASTER SIZE */
if(type == Top || type == Bottom)
if(LDIR(type))
{
if(type == Top)
mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (sg.width / nmaster) - (BORDH * 4);
mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact;
if(type == Left)
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH << 1);
mastergeo.width = (n <= nmaster) ? (sg.width - (BORDH << 1)) : mwfact;
mastergeo.height = (sg.height / nmaster) - BORDH;
}
else
{
if(type == Left)
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;
if(type == Top)
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (sg.width / nmaster) - (BORDH << 2);
mastergeo.height = (n <= nmaster) ? (sg.height - BORDH) : mwfact;
}
/* TILED SIZE */
if(n > nmaster)
{
if(type == Top || type == Bottom)
tilesize = sg.width / (n - nmaster) - (BORDH * 4);
if(LDIR(type))
tilesize = sg.height / (n - nmaster) - ((BORDH << 1) + TBARH);
else
tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH);
tilesize = sg.width / (n - nmaster) - (BORDH << 2);
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
/* MASTER */
if(i < nmaster)
{
cgeo.width = mastergeo.width;
cgeo.height = mastergeo.height;
if(type == Top || type == Bottom)
cgeo.y = mastergeo.y;
else
if(LDIR(type))
{
cgeo.x = mastergeo.x;
cgeo.height -= (TBARH + BORDH);
}
else
cgeo.y = mastergeo.y;
}
/* TILED */
@@ -388,42 +412,43 @@ multi_tile(int screen, Position type)
break;
default:
case Right:
cgeo.x += mastergeo.width + (BORDH * 2);
cgeo.x += mastergeo.width + (BORDH << 1);
cgeo.y = sg.y;
break;
}
}
if(type == Top || type == Bottom)
if(LDIR(type))
{
cgeo.width = tilesize;
cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2);
cgeo.width = sg.width - mastergeo.width - (BORDH << 2);
cgeo.height = tilesize;
}
else
{
cgeo.width = sg.width - mastergeo.width - (BORDH * 4);
cgeo.height = tilesize;
cgeo.width = tilesize;
cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH << 1);
}
}
/* REMAINDER */
if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
{
if(type == Top || type == Bottom)
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
else
if(LDIR(type))
cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH;
else
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH << 1)));
}
/* Magic instant */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
/* Set the position of the next client */
if(type == Top || type == Bottom)
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
if(LDIR(type))
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
else
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH << 1);
}
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -434,28 +459,28 @@ multi_tile(int screen, Position type)
* \param horizont To specify the mirror mode (vertical/horizontal)
*/
static void
mirror(int screen, Bool horizontal)
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];
uint i, n, tilesize = 0, mwfact;
uint nmaster = tags[screen][seltag[screen]].nmaster;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, sg.width, sg.height};
Geo cgeo = {sg.x, sg.y , sg.width, sg.height};
Geo nextg[2];
int i = 0, n = 0, tilesize = 0, mwfact;
int nmaster = tags[screen][seltag[screen]].nmaster;
int pa, imp;
Bool isp = 0;
bool isp = False;
memset(nextg, 0, sizeof(nextg));
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
/* Fix nmaster */
nmaster = (n < nmaster) ? n : nmaster;
imp = ((n - (nmaster - 1)) / 2);
pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1);
imp = ((n - (nmaster - 1)) >> 1);
pa = ((n - (nmaster - 1)) >> 1) - (((n - (nmaster - 1)) & 1) ? 0 : 1);
/* Set mwfact */
if(tags[screen][seltag[screen]].mwfact < 0.55)
@@ -466,26 +491,26 @@ mirror(int screen, Bool horizontal)
/* Master size */
if(horizontal)
{
mastergeo.width = (sg.width / nmaster) - (BORDH * 2);
mastergeo.width = (sg.width / nmaster) - (BORDH << 1);
mastergeo.height -= BORDH;
}
else
{
mastergeo.width -= BORDH * 2;
mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2));
mastergeo.width -= (BORDH << 1);
mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH << 1));
}
if(n == nmaster + 1)
{
if(horizontal)
{
mastergeo.height = mwfact - ((BORDH * 2) + TBARH);
tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH);
mastergeo.height = mwfact - ((BORDH << 1) + TBARH);
tilesize = (sg.height - mastergeo.height) - ((BORDH << 1) + TBARH);
}
else
{
mastergeo.width = mwfact - (BORDH * 3);
tilesize = (sg.width - mastergeo.width) - (BORDH * 4);
tilesize = (sg.width - mastergeo.width) - (BORDH << 2);
}
}
if(n > nmaster + 1)
@@ -493,23 +518,25 @@ mirror(int screen, Bool horizontal)
if(horizontal)
{
mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH;
mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2));
tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2));
mastergeo.height = ((mwfact << 1) - sg.height) - ((BORDH * 3) + (TBARH << 1));
tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH << 1));
}
else
{
mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH;
mastergeo.width = ((2 * mwfact - sg.width) - (BORDH * 4));
mastergeo.width = ((mwfact << 1) - sg.width) - (BORDH << 2);
tilesize = (mwfact - mastergeo.width) - (BORDH * 5);
}
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
if(i < nmaster)
{
cgeo = mastergeo;
@@ -518,7 +545,7 @@ mirror(int screen, Bool horizontal)
if(i + 1 == nmaster)
{
if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
}
@@ -530,19 +557,19 @@ mirror(int screen, Bool horizontal)
else
cgeo.width = tilesize;
if((i + nmaster) % 2)
if((i + nmaster) & 1)
{
isp = 1;
if(horizontal)
{
cgeo.y = sg.y;
cgeo.width = (sg.width / pa) - (BORDH * 2);
cgeo.width = (sg.width / pa) - (BORDH << 1);
}
else
{
cgeo.x = sg.x;
cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2));
cgeo.height = (sg.height / pa) - (TBARH + (BORDH << 1));
}
}
else
@@ -552,12 +579,12 @@ mirror(int screen, Bool horizontal)
if(horizontal)
{
cgeo.y = (sg.y + mwfact) - BORDH;
cgeo.width = (sg.width / imp) - (BORDH * 2);
cgeo.width = (sg.width / imp) - (BORDH << 1);
}
else
{
cgeo.x = (sg.x + mwfact) - BORDH;
cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2));
cgeo.height = (sg.height / imp) - (TBARH + (BORDH << 1));
}
}
@@ -565,16 +592,16 @@ mirror(int screen, Bool horizontal)
if(i + 1 == n || i + 1 == n - 1)
{
if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
}
}
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
if(i >= nmaster)
nextg[!isp] = c->geo;
nextg[!isp] = c->pgeo;
/* Next y/x position */
if(i >= nmaster - 1)
@@ -584,7 +611,7 @@ mirror(int screen, Bool horizontal)
if(i == nmaster || i == nmaster - 1)
cgeo.x = sg.x;
else
cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2;
cgeo.x = nextg[isp].x + nextg[isp].width + (BORDH << 1);
}
else
{
@@ -597,13 +624,14 @@ mirror(int screen, Bool horizontal)
else if (i <= nmaster - 1)
{
if(horizontal)
mastergeo.x = c->geo.x + c->geo.width + BORDH * 2;
mastergeo.x = cgeo.x + cgeo.width + (BORDH << 1);
else
mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
mastergeo.y = cgeo.y + cgeo.height + BORDH + TBARH;
}
}
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -689,10 +717,6 @@ grid_vertical(int screen)
return;
}
/** Put the selected client to the master postion
* \param cmd uicb_t type unused
*/
/** Toggle the selected client to free
* \param cmd uicb_t type unused
*/
@@ -706,8 +730,9 @@ uicb_togglefree(uicb_t cmd)
sel->flags ^= FreeFlag;
if((sel->flags & FreeFlag))
if(sel->flags & FreeFlag)
{
split_set_current(NULL, sel);
sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(sel, sel->free_geo, True);
client_raise(sel);
@@ -716,11 +741,13 @@ uicb_togglefree(uicb_t cmd)
{
sel->free_geo = sel->geo;
sel->ogeo = sel->geo;
split_set_current(sel, NULL);
}
client_update_attributes(sel);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return;
}
@@ -733,26 +760,31 @@ uicb_togglemax(uicb_t cmd)
{
(void)cmd;
if(!sel || ishide(sel, selscreen)
|| (sel->flags & HintFlag)|| (sel->flags & FSSFlag))
if(!sel || ishide(sel, selscreen) || (sel->flags & (HintFlag | FSSFlag)))
return;
if(!(sel->flags & MaxFlag))
sel->flags ^= MaxFlag;
if(sel->flags & MaxFlag)
{
sel->ogeo = sel->geo;
sel->free_geo = sel->geo;
sel->flags &= ~(TileFlag | FreeFlag);
split_set_current(NULL, sel);
client_maximize(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);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
split_set_current(sel, NULL);
layout_func(selscreen, seltag[selscreen]);
}
return;
@@ -764,12 +796,15 @@ uicb_togglemax(uicb_t cmd)
void
uicb_toggle_resizehint(uicb_t cmd)
{
Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel();
(void)cmd;
tags[selscreen][seltag[selscreen]].resizehint = !tags[selscreen][seltag[selscreen]].resizehint;
tags[selscreen][seltag[selscreen]].flags ^= ResizeHintFlag;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)))
client_moveresize(c, c->geo, (tags[selscreen][seltag[selscreen]].flags & ResizeHintFlag));
return;
}
@@ -785,18 +820,21 @@ uicb_toggle_abovefc(uicb_t cmd)
screen_get_sel();
if(!(tags[selscreen][seltag[selscreen]].abovefc = !tags[selscreen][seltag[selscreen]].abovefc))
tags[selscreen][seltag[selscreen]].flags ^= AboveFCFlag;
if(!(tags[selscreen][seltag[selscreen]].flags & AboveFCFlag))
{
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->flags & AboveFlag
&& c->screen == selscreen
&& c->tag == (uint)seltag[selscreen])
&& c->tag == seltag[selscreen])
{
c->flags &= ~AboveFlag;
break;
}
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
}
client_focus(sel);
@@ -823,6 +861,8 @@ uicb_set_layout(uicb_t cmd)
if(layout_list[i].func == conf.layout[j].func)
tags[selscreen][seltag[selscreen]].layout = conf.layout[j];
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
arrange(selscreen, True);
return;
@@ -836,17 +876,17 @@ layout_set_client_master(Client *c)
{
screen_get_sel();
if(!c || (c->flags & HintFlag) || !(c->flags & TileFlag)
|| (c->flags & FSSFlag))
if(!c || (c->flags & (HintFlag | FSSFlag)) || !(c->flags & TileFlag))
return;
if(c == tiled_client(selscreen, clients))
CHECK((c = tiled_client(selscreen, c->next)));
if(c == tiled_client(selscreen, SLIST_FIRST(&clients)))
CHECK((c = tiled_client(selscreen, SLIST_NEXT(c, next))));
client_detach(c);
client_attach(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return;
}
@@ -854,7 +894,7 @@ layout_set_client_master(Client *c)
/** Check the selected client is max
* \param cmd uicb_t type unused
*/
Bool
bool
uicb_checkmax(uicb_t cmd)
{
(void)cmd;
@@ -871,7 +911,7 @@ uicb_checkmax(uicb_t cmd)
/** Check the selected client is free
* \param cmd uicb_t type unused
*/
Bool
bool
uicb_checkfree(uicb_t cmd)
{
(void)cmd;
@@ -888,12 +928,13 @@ uicb_checkfree(uicb_t cmd)
/** Check layout type
* \param cmd uicb_t type layout type
*/
Bool
bool
uicb_checklayout(uicb_t cmd)
{
screen_get_sel();
char *type = tags[selscreen][seltag[selscreen]].layout.type;
if(!strcmp(cmd, tags[selscreen][seltag[selscreen]].layout.type))
if(type && !strcmp(cmd, type))
return True;
return False;

View File

@@ -44,7 +44,7 @@ menu_get_longer_string(MenuItem *mi, int nitem)
return l;
}
static Bool
static bool
menu_get_checkstring_needed(MenuItem *mi, int nitem)
{
(void)mi;
@@ -71,11 +71,11 @@ menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen)
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_draw_text(winitem[item], x, FHINFOBAR, menu->item[item].name);
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);
barwin_draw_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol);
if(menu->item[item].submenu)
barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">");
@@ -83,7 +83,7 @@ menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen)
return;
}
static Bool
static bool
menu_activate_item(Menu *menu, int i)
{
int j, x, y;
@@ -143,12 +143,12 @@ menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
return;
}
static Bool
static bool
menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
{
int i, c = 0;
KeySym ks;
Bool quit = False;
KeySym ks = 0;
bool quit = False;
char acc = 0;
switch(ev->type)
@@ -221,9 +221,11 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
break;
default:
getevent(*ev);
if(ev->type < nevent && ev->type > 0)
HANDLE_EVENT(ev);
break;
}
XNextEvent(dpy, ev);
return quit;
@@ -347,6 +349,8 @@ menu_draw(Menu menu, int x, int y)
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XNextEvent(dpy, &ev);
while(!menu_manage_event(&ev, &menu, item));
XUngrabKeyboard(dpy, CurrentTime);

View File

@@ -32,20 +32,33 @@
#include "wmfs.h"
Window prevwin;
/** Draw the border when a client in dragging/resizing with mouse
*/
static void
mouse_dragborder(XRectangle geo, GC g)
mouse_dragborder(Geo geo, GC g)
{
XDrawRectangle(dpy, ROOT, g,
geo.x - BORDH / 2,
geo.y - (TBARH - (BORDH / 2)),
geo.x - (BORDH >> 1),
geo.y - (TBARH - (BORDH >> 1)),
geo.width + BORDH,
geo.height + TBARH);
return;
}
static void
mouse_cfactor_border(Client *c, int f[4], GC g)
{
int e;
mouse_dragborder(cfactor_geo(c->wrgeo, f, &e), g);
return;
}
/** Move a client in tile grid with the mouse
*\param c Client double pointer
*/
@@ -56,13 +69,13 @@ mouse_move_tile_client(Client **c)
Window w;
int d;
if(!((*c)->flags & TileFlag) && !((*c)->flags & LMaxFlag))
if(!((*c)->flags & (TileFlag | LMaxFlag)))
return;
XQueryPointer(dpy, ROOT, &w, &w, &d, &d, &d, &d, (uint*)&d);
if(((sc = client_gb_win(w)) || (sc = client_gb_frame(w)) || (sc = client_gb_titlebar(w)))
&& (*c)->win != sc->win && !((*c)->flags & HideFlag) && !(sc->flags & HideFlag))
&& (*c)->win != sc->win && !((*c)->flags & HideFlag) && !(sc->flags & HideFlag) && (sc->flags & TileFlag))
{
client_swap(sc, *c);
client_focus(sc);
@@ -82,28 +95,28 @@ mouse_move_tag_client(Client *c)
Window w;
int i, d, s;
if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag))
if(!(c->flags & (TileFlag | LMaxFlag)))
return;
s = c->screen;
XQueryPointer(dpy, infobar[selscreen].tags_board->win, &w, &w, &d, &d, &d, &d, (uint*)&d);
if(w == prevwin)
return;
prevwin = w;
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(infobar[selscreen].tags[i]->win == w
&& tags[selscreen][i].layout.func != freelayout)
{
c->screen = selscreen;
c->tag = i;
tags[c->screen][c->tag].request_update = True;
arrange(s, True);
tag_transfert(c, i);
if(s != c->screen)
arrange(c->screen, True);
}
client_focus_next(c);
return;
}
@@ -117,12 +130,12 @@ mouse_move(Client *c)
int dint;
uint duint;
Window dw;
XRectangle geo = c->geo;
Geo geo = c->geo;
XGCValues xgc;
GC gci;
XEvent ev;
if((c->flags & MaxFlag) || (c->flags & FSSFlag))
if(c->flags & (MaxFlag | FSSFlag))
return;
ocx = c->geo.x;
@@ -171,14 +184,13 @@ mouse_move(Client *c)
mouse_dragborder(geo, gci);
}
}
else if(ev.type == MapRequest
|| ev.type == ConfigureRequest)
getevent(ev);
else if((ev.type == MapRequest || ev.type == ConfigureRequest))
HANDLE_EVENT(&ev);
}
while(ev.type != ButtonRelease);
/* One time again to delete all the trace on the window */
if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag))
if(!(c->flags & (TileFlag | LMaxFlag)))
{
mouse_dragborder(geo, gci);
client_moveresize(c, geo, False);
@@ -199,23 +211,21 @@ mouse_move(Client *c)
void
mouse_resize(Client *c)
{
XRectangle geo = c->geo, ogeo = c->geo;
Geo geo = c->geo, ogeo = c->geo;
Position pos = Right;
XEvent ev;
Window w;
int d, u, omx, omy;
XGCValues xgc;
GC gci;
float mwf = tags[selscreen][seltag[selscreen]].mwfact;
int f[4] = { 0 };
if((c->flags & MaxFlag)
|| (c->flags & LMaxFlag)
|| (c->flags & FSSFlag))
if(c->flags & (MaxFlag | LMaxFlag | FSSFlag))
return;
XQueryPointer(dpy, ROOT, &w, &w, &omx, &omy, &d, &d, (uint *)&u);
if((omx - c->geo.x) < (c->geo.width / 2))
if((omx - c->geo.x) < (c->geo.width >> 1))
pos = Left;
if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None,
@@ -240,6 +250,8 @@ mouse_resize(Client *c)
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, c->geo.height);
mouse_dragborder(c->geo, gci);
}
else
mouse_cfactor_border(c, f, gci);
do
{
@@ -247,24 +259,22 @@ mouse_resize(Client *c)
if(ev.type == MotionNotify)
{
/* To resize MWFACT in tile mode */
if((c->flags & TileFlag)
&& tags[selscreen][seltag[selscreen]].layout.func != grid_vertical
&& tags[selscreen][seltag[selscreen]].layout.func != grid_horizontal)
/* To resize client in tile mode with cfactor */
if(c->flags & TileFlag)
{
if(tags[selscreen][seltag[selscreen]].layout.func == tile)
mwf += (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left)
mwf -= (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top)
mwf -= (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height);
mouse_cfactor_border(c, f, gci);
if(omx >= c->frame_geo.x + (c->frame_geo.width >> 1))
f[Right] = ev.xmotion.x_root - omx;
else
mwf += (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height);
f[Left] = omx - ev.xmotion.x_root;
omx = ROUND(ev.xmotion.x_root);
omy = ROUND(ev.xmotion.y_root);
if(omy >= c->frame_geo.y + (c->frame_geo.height >> 1))
f[Bottom] = ev.xmotion.y_root - omy;
else
f[Top] = omy - ev.xmotion.y_root;
tags[selscreen][seltag[selscreen]].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf);
mouse_cfactor_border(c, f, gci);
}
/* Free mode */
else if(!(c->flags & TileFlag))
@@ -303,7 +313,10 @@ mouse_resize(Client *c)
XUngrabServer(dpy);
}
else
tags[selscreen][seltag[selscreen]].layout.func(c->screen);
{
mouse_cfactor_border(c, f, gci);
cfactor_multi_set(c, f);
}
client_update_attributes(c);
XUngrabPointer(dpy, CurrentTime);
@@ -317,23 +330,23 @@ mouse_resize(Client *c)
* \param focused For know if c is or not focused
*/
void
mouse_grabbuttons(Client *c, Bool focused)
mouse_grabbuttons(Client *c, bool focused)
{
size_t i;
size_t i = 0;
uint but[] = {Button1, Button2, Button3, Button4, Button5};
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused)
for(i = 0; i < LEN(but); ++i)
for(; i < LEN(but); ++i)
{
XGrabButton(dpy, but[i], conf.client.mod, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | LockMask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | LockMask | numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
}
else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,

View File

@@ -70,8 +70,8 @@ struct keyword {
};
struct state {
bool_t quote;
bool_t comment;
bool quote;
bool comment;
char quote_char;
};
@@ -162,10 +162,10 @@ parse_keywords(const char *filename)
char path[PATH_MAX];
size_t i, j;
int line;
bool_t error = False;
bool error = False;
if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) {
if (stat(filename, &st) == -1 || (fd = open(filename, O_RDONLY)) == -1) {
warn("%s", filename);
return NULL;
}
@@ -376,6 +376,9 @@ include(struct keyword *head)
}
}
if (filename != head->name)
free(filename);
head = head->next;
if (kw) {

View File

@@ -18,22 +18,15 @@
#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;
bool used;
int line;
char *filename;
SLIST_ENTRY(conf_opt) entry;
@@ -51,7 +44,7 @@ struct conf_sec {
struct opt_type {
long int num;
float fnum;
bool_t bool;
bool boolean;
char *str;
};

View File

@@ -40,9 +40,9 @@ string_to_opt(char *s)
if (!strcmp(s, "true") || !strcmp(s, "True") ||
!strcmp(s, "TRUE") || !strcmp(s, "1"))
ret.bool = True;
ret.boolean = True;
else
ret.bool = False;
ret.boolean = False;
ret.str = s;

View File

@@ -38,9 +38,7 @@
int
screen_count(void)
{
int n = 0;
n = ScreenCount(dpy);
int n = ScreenCount(dpy);
#ifdef HAVE_XINERAMA
if(XineramaIsActive(dpy))
@@ -57,13 +55,13 @@ screen_count(void)
/** Get screen geometry by number
*\param s Screen number
*\return XRectangle struct
*\return Geo struct
*/
XRectangle
Geo
screen_get_geo(int s)
{
int barpos = tags[selscreen][seltag[selscreen]].barpos;
XRectangle geo;
Geo geo;
geo.x = BORDH;
if(barpos == IB_Hide || barpos == IB_Bottom)
@@ -106,14 +104,13 @@ screen_get_geo(int s)
int
screen_get_with_geo(int x, int y)
{
int i, r = 0;
int i = 0;
for(i = 0; i < screen_count(); ++i)
if((x >= spgeo[i].x && x < spgeo[i].x + spgeo[i].width)
&& y >= spgeo[i].y && y < spgeo[i].y + spgeo[i].height)
r = i;
for(; i < screen_count(); ++i)
if(INAREA(x, y, spgeo[i]))
return i;
return r;
return 0;
}
/** Set the selected screen
@@ -130,8 +127,8 @@ screen_set_sel(int screen)
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);
sgeo[screen].x + (sgeo[screen].width >> 1),
sgeo[screen].y + (sgeo[screen].height >> 1));
selscreen = screen;
@@ -179,8 +176,8 @@ screen_init_geo(void)
int i;
int s = screen_count();
sgeo = xcalloc(s, sizeof(XRectangle));
spgeo = xcalloc(s, sizeof(XRectangle));
sgeo = xcalloc(s, sizeof(Geo));
spgeo = xcalloc(s, sizeof(Geo));
for(i = 0; i < s; ++i)
sgeo[i] = screen_get_geo(i);

374
src/split.c Normal file
View File

@@ -0,0 +1,374 @@
/*
* split.c
* Copyright © 2011 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 SPLIT_CHECK_ROW(g1, g2, p) \
(LDIR(p) \
? (g1.y >= g2.y && (g1.y + g1.height) <= (g2.y + g2.height)) \
: (g1.x >= g2.x && (g1.x + g1.width) <= (g2.x + g2.width))) \
#define SPLIT_MOVE_DIR(d) \
void \
uicb_split_move_##d(uicb_t cmd) \
{ \
(void)cmd; \
CHECK(sel); \
split_move_dir(sel, d); \
}
/* uicb_split_move_dir() */
SPLIT_MOVE_DIR(Right);
SPLIT_MOVE_DIR(Left);
SPLIT_MOVE_DIR(Top);
SPLIT_MOVE_DIR(Bottom);
/** Arrange size of parent client of last closed client
*/
static void
_split_arrange_size(Geo g, Geo *cg, Position p)
{
if(LDIR(p))
cg->width += FRAMEW(g.width);
else
cg->height += FRAMEH(g.height);
if(p == Right)
cg->x -= FRAMEW(g.width);
if(p == Bottom)
cg->y -= FRAMEH(g.height);
return;
}
/** Set layout current clients to split/unsplit
*/
void
split_set_current(Client *nc, Client *ghost)
{
if(nc && (tags[nc->screen][nc->tag].flags & SplitFlag))
{
tags[nc->screen][nc->tag].layout.nc = nc;
tags[nc->screen][nc->tag].layout.flags |= IntegrationFlag;
}
if(ghost && (tags[ghost->screen][ghost->tag].flags & SplitFlag))
{
tags[ghost->screen][ghost->tag].layout.ghost = *ghost;
tags[ghost->screen][ghost->tag].layout.flags |= ArrangeFlag;
}
return;
}
/** Apply current operation about split
*/
void
split_apply_current(int screen, int tag)
{
/* Integrate in split mode */
if(tags[screen][tag].layout.flags & IntegrationFlag)
{
split_client_integrate(tags[screen][tag].layout.nc, sel, screen, tag);
tags[screen][tag].layout.flags &= ~IntegrationFlag;
}
/* Remove from split mode */
if(tags[screen][tag].layout.flags & ArrangeFlag)
{
split_arrange_closed(&tags[screen][tag].layout.ghost);
tags[screen][tag].layout.flags &= ~ArrangeFlag;
}
return;
}
/** Check if row direction is available to resize from it
*\param c Client pointer
*\param g Client pointer
*\param p Position
*\return True if available
*/
static bool
_split_check_row_dir(Client *c, Client *g, Position p)
{
int s = 0, cs;
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width);
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, g->frame_geo, p))
{
s += (LDIR(p) ? cc->frame_geo.height : cc->frame_geo.width);
if(s == cs)
return True;
if(s > cs)
return False;
}
return False;
}
/** Arrange clients after a client close
*\param ghost Ghost client
*/
void
split_arrange_closed(Client *ghost)
{
Position p;
bool b = False;
Geo cgeo;
Client *c, *cc;
int screen = ghost->screen;
int tag = (ghost->tag ? ghost->tag : seltag[screen]);
/* Use ghost client properties to fix holes in tile
* .--. ~ ~
* /xx \ ~ ~
* ~~\O _ (____ ~
* __.| .--'-==~ ~
* '---\ '. ~ , ~
* '. '-.___.-'/ ~
* '-.__ _.' ~
* ````` ~
*/
/* Search for single parent for easy resize
* Example case:
* ___________ ___________
* | | B | -> -> | | |
* | A |_____| -> Close -> | A | B |
* | | C | -> C -> | |v v v|
* |_____|_____| -> -> |_____|_____|
*/
for(p = Right; p < Center; ++p)
if((c = client_get_next_with_direction(ghost, p)))
if(CFACTOR_CHECK2(ghost->frame_geo, c->frame_geo, p))
{
_split_arrange_size(ghost->wrgeo, &c->wrgeo, p);
cfactor_clean(c);
client_moveresize(c, (c->pgeo = c->wrgeo), (tags[screen][tag].flags & ResizeHintFlag));
return;
}
/* Check row parents for full resize
* Example case:
* ___________ ___________
* | | B | -> -> | << B |
* | A |_____| -> Close -> |___________|
* | | C | -> A -> | << C |
* |_____|_____| -> -> |___________|
*/
for(p = Right; p < Center && !b; ++p)
if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p))
{
for(cgeo = c->frame_geo, cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p))
{
_split_arrange_size(ghost->wrgeo, &cc->wrgeo, p);
cfactor_clean(cc);
client_moveresize(cc, (cc->pgeo = cc->wrgeo), (tags[screen][tag].flags & ResizeHintFlag));
b = True;
}
}
return;
}
/** Split client hor or vert to insert another client in the new area
*\param c Client pointer
*\param p True = Vertical, False = Horizontal
*\return sgeo Geo of future integrated client
*/
Geo
split_client(Client *c, bool p)
{
Geo geo, sgeo;
if(!c || !(c->flags & TileFlag))
return c->wrgeo;
cfactor_clean(c);
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
/* Use geometry without resizehint applied on it */
geo = sgeo = c->wrgeo;
/* Vertical */
if(p)
{
geo.width >>= 1;
sgeo.x = FRAMEW(geo.x + geo.width);
sgeo.width = (sgeo.width >> 1) - (BORDH << 1);
/* Remainder */
sgeo.width += (c->wrgeo.x + c->wrgeo.width) - (sgeo.x + sgeo.width);
}
/* Horizontal */
else
{
geo.height = (geo.height >> 1) - TBARH;
sgeo.y = FRAMEH(geo.y + geo.height);
sgeo.height = (sgeo.height >> 1) - BORDH;
/* Remainder */
sgeo.height += (c->wrgeo.y + c->wrgeo.height) - (sgeo.y + sgeo.height);
}
client_moveresize(c, (c->pgeo = geo), (tags[c->screen][c->tag].flags & ResizeHintFlag));
return sgeo;
}
/** Apply new attributes to splitted client
*\param c Client pointer
*\param geo New geo
*/
void
split_client_fill(Client *c, Geo geo)
{
if(!c)
return;
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
client_moveresize(c, (c->pgeo = geo), (tags[c->screen][c->tag].flags & ResizeHintFlag));
return;
}
/** Integrate client in tag
*\param c Client pointer (integrate)
*\param sc Splitted client pointer
*/
void
split_client_integrate(Client *c, Client *sc, int screen, int tag)
{
bool b = True;
Geo g;
if(!c || c->flags & FreeFlag || !(tags[screen][tag].flags & SplitFlag))
return;
/* Can't integrate in sc */
if(!sc || sc == c || !(sc->flags & TileFlag)
|| sc->screen != screen || sc->tag != tag)
{
/* Looking for first client on wanted tag */
b = False;
SLIST_FOREACH(sc, &clients, next)
if(sc != c && sc->screen == screen && sc->tag == tag
&& (sc->flags & TileFlag))
{
b = True;
break;
}
/* No client on wanted tag to integrate */
if(!b)
{
/* client_maximize check position of client
* to maximize it; so in case of transfert one client
* on a tag from another screen, we need it.
*/
c->geo.x = sgeo[screen].x;
c->geo.y = sgeo[screen].y;
client_maximize(c);
c->flags |= TileFlag;
return;
}
}
g = split_client(sc, (sc->frame_geo.height < sc->frame_geo.width));
split_client_fill(c, g);
return;
}
/** Move splitted client by re-arranging it in next by direction client
* Integrate c in next client by direction
* Example case, direction = left:
* ___________ ___________
* | | B | -> | A | |
* | A |_____| -> |_____| B |
* | |< C | -> | C |v v v|
* |_____|_____| -> |_____|_____|
*/
void
split_move_dir(Client *c, Position p)
{
Client *sc;
if(!c || !(tags[c->screen][c->tag].flags & SplitFlag))
return;
if((sc = client_get_next_with_direction(c, p)))
{
split_arrange_closed(c);
split_client_integrate(c, sc, sc->screen, sc->tag);
}
return;
}
/** Toggle split mode
*/
void
uicb_split_toggle(uicb_t cmd)
{
(void)cmd;
tags[selscreen][seltag[selscreen]].flags ^= SplitFlag;
layout_func(selscreen, seltag[selscreen]);
infobar_draw_layout(&infobar[selscreen]);
return;
}

View File

@@ -32,119 +32,181 @@
#include "wmfs.h"
/** Check rectangles blocks in str and return properties
* --> \b[x;y;width;height;#color]\
*\param r StatusRec pointer, rectangles properties
/* Systray width */
static int sw = 0;
/** Parse dynamic mouse binds in str and insert it in linked list
* --> \<block>[;;;;(button;func;cmd)]\ add a mouse bind on the block object
*\param str String
*\return n Length of r
*/
static int
statustext_rectangle(StatusRec *r, char *str)
*\param area Area of clicking
*\param infobar Infobar pointer
*/
void
statustext_mouse(char *str, Geo area, InfoBar *infobar)
{
char as;
int n, i, j, k;
StatusMouse *sm = NULL;
int i = 0, button = 1, n;
char cmd[256] = { 0 };
char func[64] = { 0 };
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(; i < (int)strlen(str); ++i, sm = NULL)
if((n = sscanf(&str[i], "(%d;%64[^;];%256[^)])", &button, func, cmd) >= 2) && n < 4)
{
sm = zcalloc(sizeof(StatusMouse));
sm->button = button;
sm->func = name_to_func((char*)func, func_list);
sm->cmd = xstrdup(cmd);
sm->area = area;
sm->infobar = infobar;
for(k = j; k < i; str[k++] = 0);
SLIST_INSERT_HEAD(&smhead, sm, next);
return n;
/* Jump to the end of the sequence */
while(str[++i + 1] != ')');
}
return;
}
/** Check graphs blocks in str and return properties
* --> \g[x;y;width;height;#color;data]\
*\param g StatusGraph pointer, graphs properties
/** Check rectangles blocks in str and draw it
* --> \b[x;y;width;height;#color]\
*\param ib Infobar pointer
*\param str String
*\return n Length of g
*/
static int
statustext_graph(StatusGraph *g, char *str)
static void
statustext_rectangle(InfoBar *ib, char *str)
{
char as, c, *p;
int n, i, j, k, m, w;
StatusRec r;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k, n;
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
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, &as)) == 6
|| (n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x;%512[^]]]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, mouse, &as)) == 7)
&& as == '\\')
{
/* data is a list of numbers separated by ';' */
w = g[n].w;
p = strtok(g[n].data, ";");
m = 0;
draw_rectangle(ib->bar->dr, r.g.x - sw, r.g.y, r.g.width, r.g.height, r.color);
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;
}
if(n == 7)
statustext_mouse(mouse, r.g, ib);
/* 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);
for(++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);
for(k = j; k < i; str[k++] = '\0');
return n;
return;
}
/** Check text blocks in str and return properties
* --> \s[x;y;#color;text]\
*\param s StatusText pointer, text properties
/** Check graphs blocks in str and draw it
* --> \g[x;y;width;height;#color;data]\
*\param ib Infobar pointer
*\param str String
*\return n Length of s
*/
static int
statustext_text(StatusText *s, char *str)
static void
statustext_graph(InfoBar *ib, char *str)
{
char as;
int n, i, j, k;
StatusGraph g;
char as, c, *p;
int i, j, k, m, w;
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
for(i = j = 0; i < (int)strlen(str); ++i, ++j)
if(sscanf(&str[i], "\\g[%d;%d;%d;%d;#%x;%512[^]]]%c",
&g.x, &g.y, &g.w, &g.h, &g.color, g.data, &as) == 7
&& as == '\\')
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
{
/* data is a list of numbers separated by ';' */
w = g.w;
p = strtok(g.data, ";");
m = 0;
for(c = atoi(p); p && m < w; ++m)
{
/* height limits */
if(c < 0)
c = 0;
if(c > (char)g.h)
c = g.h;
g.data[m] = c;
p = strtok(NULL, ";");
}
/* width limits */
for(; m < w; g.data[m++] = 0);
/* data is a array[w] of bytes now */
draw_graph(ib->bar->dr, g.x - sw, g.y, g.w, g.h, g.color, g.data);
for(++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);
for(k = j; k < i; str[k++] = '\0');
return n;
return;
}
/** Check text blocks in str and draw it
* --> \s[x;y;#color;text]\
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_text(InfoBar *ib, char *str)
{
StatusText s;
Geo area;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k, n;
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^];]]%c",
&s.x, &s.y, s.color, s.text, &as)) == 5
|| (n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^;];%512[^]]]%c",
&s.x, &s.y, s.color, s.text, mouse, &as)) == 6)
&& as == '\\')
{
draw_text(ib->bar->dr, s.x - sw, s.y, s.color, s.text);
/* Etablish clickable area on text */
if(n == 6)
{
area.height = font.height;
area.width = textw(s.text);
area.x = s.x - sw;
area.y = s.y - area.height;
statustext_mouse(mouse, area, ib);
}
for(++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;
}
/** Draw normal text and colored normal text
* --> \#color\ text in color
*\param sc Screen
*\param sc Screen id
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_normal(int sc, char *str)
statustext_normal(InfoBar *ib, 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();
int n, i, j, k, tw;
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
@@ -157,8 +219,7 @@ statustext_normal(int sc, char *str)
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);
draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (textw(strwc) + sw), FHINFOBAR, ib->bar->fg, strwc);
if(n)
{
@@ -167,17 +228,18 @@ statustext_normal(int sc, char *str)
for(i = k = 0; i < (int)strlen(str); ++i, ++k)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{
tw = textw(&buf[k]);
/* 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_rectangle(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw),
0, INFOBARH - (sgeo[ib->screen].width - SHADH) - tw,
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]);
draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw), FHINFOBAR, col, &buf[k]);
strncpy(buf, strwc, sizeof(buf));
++i;
@@ -188,55 +250,41 @@ statustext_normal(int sc, char *str)
}
/** Handle statustext and draw all things in infobar of specified screen
*\param sc Screen number
*\param sc Screen id
*\param str String
*/
void
statustext_handle(int sc, char *str)
statustext_handle(InfoBar *ib)
{
char *lastst;
int i, nr, ng, ns, sw = 0;
StatusRec r[128];
StatusGraph g[128];
StatusText s[128];
char *str;
StatusMouse *sm;
/* If the str == the current statustext, return (not needed) */
if(!str)
return;
/* Free previous linked list of mouse bind */
if(!ib->screen)
while(!SLIST_EMPTY(&smhead))
{
sm = SLIST_FIRST(&smhead);
SLIST_REMOVE_HEAD(&smhead, next);
free((void*)sm->cmd);
free(sm);
}
if(sc == conf.systray.screen)
if(ib->screen == 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);
str = xstrdup(ib->statustext);
/* Store rectangles, located text & images properties. */
nr = statustext_rectangle(r, str);
ng = statustext_graph(g, str);
ns = statustext_text(s, str);
statustext_rectangle(ib, str);
statustext_graph(ib, str);
statustext_text(ib, str);
/* Draw normal text (and possibly colored with \#color\ blocks) */
statustext_normal(sc, str);
statustext_normal(ib, 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);
sw = 0;
/* 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);
free(str);
return;
}

View File

@@ -37,25 +37,45 @@
#define NBUTTON 8
#define MAXTAG 36
#define NUM_OF_LAYOUT 10
#define NUM_OF_LAYOUT 11
#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 UrgentFlag (1 << 10)
#define FLayFlag (1 << 11)
#define DockFlag (1 << 12)
#define FreeFlag 0x01
#define MaxFlag 0x02
#define TileFlag 0x04
#define HideFlag 0x08
#define LMaxFlag 0x10
#define UnmapFlag 0x20
#define HintFlag 0x40
#define FSSFlag 0x80
#define AboveFlag 0x100
#define UrgentFlag 0x200
#define FLayFlag 0x400
#define DockFlag 0x800
/* Layout flags definition */
#define IntegrationFlag 0x01
#define ArrangeFlag 0x02
/* Tag flags definition */
#define TagUrgentFlag 0x01
#define ResizeHintFlag 0x02
#define RequestUpdateFlag 0x04
#define AboveFCFlag 0x08
#define CleanFactFlag 0x10
#define StayLastFlag 0x20
#define SplitFlag 0x40
#define FirstArrangeFlag 0x80
#define IgnoreEnterFlag 0x100
#define TagFlag(t) (1 << (t))
/* BarWindow flags definition */
#define MappedFlag 0x01
#define StippleFlag 0x02
#define BordFlag 0x04
/* XEMBED messages */
#define XEMBED_MAPPED (1 << 0)
#define XEMBED_EMBEDDED_NOTIFY 0
@@ -92,10 +112,10 @@ enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast };
/* Menu align */
enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 };
/* Infobar position */
/* Infobar position / elements */
enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 };
typedef enum { Right, Left, Top, Bottom, Center, PositionLast } Position;
typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position;
typedef enum { ElemTag, ElemLayout, ElemSelbar } IbElemType;
/* Ewmh hints list */
enum
@@ -138,7 +158,6 @@ enum
/* WMFS HINTS */
wmfs_running,
wmfs_update_hints,
wmfs_update_status,
wmfs_current_tag,
wmfs_current_screen,
wmfs_current_layout,
@@ -154,11 +173,18 @@ enum
net_last
};
/* Geometry structure */
typedef struct
{
int x, y;
int width, height;
} Geo;
/*
* BarWindow Structure
* (titlebar, infobar..)
*/
typedef struct
typedef struct BarWindow
{
Window win;
Drawable dr;
@@ -173,31 +199,29 @@ typedef struct
uint bg;
char *fg;
uint stipple_color;
XRectangle geo;
Bool mapped, stipple, bord;
Geo geo;
uint flags;
SLIST_ENTRY(BarWindow) next;
} BarWindow;
/* Client Structure. */
typedef struct Client Client;
struct Client
typedef struct Client
{
/* Client title */
char *title;
/* Tag num */
uint tag;
int tag;
int focusontag;
/* Screen */
int screen;
/* Layer */
int layer;
/* Window attribute */
XRectangle geo;
XRectangle tmp_geo;
XRectangle frame_geo;
/* Old window attribute */
XRectangle ogeo;
/* Free window attribute */
XRectangle free_geo;
Geo geo, pgeo; /* Window geo, tiling pure geo */
Geo tmp_geo, wrgeo; /* Temporary geo, without resizehint geo */
Geo frame_geo; /* Frame geo */
Geo ogeo; /* Old window attribute */
Geo split_geo, free_geo; /* Split & Free window attribute */
/* Tile size factors */
int tilefact[4];
/* For resizehint usage */
int basew, baseh, incw, inch;
int maxw, maxh, minw, minh;
@@ -220,10 +244,9 @@ struct Client
} colors;
/* Client Information by flags */
uint flags;
/* Struct in chains */
Client *next;
Client *prev;
};
/* Simply-linked list */
SLIST_ENTRY(Client) next;
} Client;
/* Keybind Structure */
typedef struct
@@ -244,34 +267,46 @@ typedef struct
uicb_t cmd;
} MouseBinding;
/* InfoBar elements */
typedef struct InfobarElem
{
IbElemType type;
Geo geo;
STAILQ_ENTRY(InfobarElem) next;
} InfobarElem;
/* InfoBar Struct */
typedef struct
{
BarWindow *bar, *selbar;
BarWindow *layout_button;
BarWindow *tags_board, *tags[MAXTAG];
XRectangle geo;
int position;
BarWindow *layout_button;
BarWindow *bar;
STAILQ_HEAD(, InfobarElem) elemhead;
char *elemorder;
Geo geo, selbar_geo;
int screen, position;
char *statustext;
Bool need_update;
bool need_update;
} InfoBar;
/* Layout Structure */
typedef struct
{
uint flags; /* Flags */
Client *nc; /* New client needing integration */
Client ghost; /* Ghost client to arrange hole in split */
char *symbol;
char *type;
void (*func)(int screen);
} Layout;
/* Systray Structure */
typedef struct Systray Systray;
struct Systray
typedef struct Systray
{
Window win;
XRectangle geo;
Systray *next, *prev;
};
Geo geo;
SLIST_ENTRY(Systray) next;
} Systray;
/* Tag Structure */
typedef struct
@@ -279,20 +314,15 @@ typedef struct
char *name;
char **clients;
int nclients;
int layers;
float mwfact;
int nmaster;
Bool urgent;
Bool resizehint;
Bool request_update;
Bool abovefc;
uint flags;
int barpos;
int prev_barpos;
Layout layout;
uint tagad;
MouseBinding *mouse;
int nmouse;
Bool stay_last;
} Tag;
/* Menu Item Struct */
@@ -301,7 +331,7 @@ typedef struct
char *name;
void (*func)(uicb_t);
uicb_t cmd;
Bool (*check)(uicb_t);
bool (*check)(uicb_t);
char *submenu;
} MenuItem;
@@ -314,7 +344,7 @@ typedef struct
*/
char *name;
/* Placement */
Bool place_at_mouse;
bool place_at_mouse;
int align;
int x, y;
/* Color */
@@ -363,12 +393,13 @@ typedef struct
char *class;
char *instance;
char *role;
char *name;
int screen;
int tag;
Bool free;
Bool max;
Bool ignoretags;
Bool follow_client;
bool free;
bool max;
bool ignoretags;
bool follow_client;
} Rule;
/* Configuration structure */
@@ -379,19 +410,17 @@ typedef struct
/* Misc option */
char *font;
bool use_xft;
uint opacity;
Bool raisefocus;
Bool focus_fmouse;
Bool focus_fmov;
Bool focus_pclick;
Bool ignore_next_client_rules;
Bool tagautohide;
Bool tagnamecount;
bool raisefocus;
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
@@ -421,7 +450,8 @@ typedef struct
int height;
MouseBinding *mouse;
int nmouse;
Bool selbar;
bool selbar;
char *element_order;
} bars;
struct
{
@@ -439,10 +469,10 @@ typedef struct
} root;
struct
{
Bool set_new_win_master;
Bool place_at_mouse;
Bool border_shadow;
Bool new_client_get_mouse;
bool set_new_win_master;
bool place_at_mouse;
bool border_shadow;
bool new_client_get_mouse;
int borderheight;
char *autofree, *automax;
uint bordernormal;
@@ -463,7 +493,7 @@ typedef struct
char *fg_focus;
struct
{
Bool active;
bool active;
struct { uint normal, focus; } colors;
} stipple;
MouseBinding *mouse;
@@ -473,13 +503,13 @@ typedef struct
} titlebar;
struct
{
Bool bar;
Bool tag;
Bool layout;
bool bar;
bool tag;
bool layout;
} border;
struct
{
Bool active;
bool active;
int screen;
int spacing;
} systray;
@@ -491,14 +521,14 @@ typedef struct
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;
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 keep_layout_geo;
bool cfactor_enable_split;
char *tag_expose_name;
char *expose_layout;
char *selected_layout_symbol;
@@ -512,27 +542,47 @@ typedef struct
typedef struct
{
uint x, y, w, h;
int as, de, width, height;
#ifdef HAVE_XFT
XftFont *font;
#endif /* HAVE_XFT */
XFontSet fontset;
} FontStruct;
/* status.c util struct */
typedef struct
{
Geo g;
uint color;
} StatusRec;
typedef struct
{
uint x, y, w, h;
int x, y, w, h;
uint color;
char data[512];
} StatusGraph;
typedef struct
{
uint x, y;
int x, y;
char color[8];
char text[512];
} StatusText;
typedef struct StatusMouse
{
Geo area;
InfoBar *infobar;
uint button;
void (*func)(uicb_t);
uicb_t cmd;
SLIST_ENTRY(StatusMouse) next;
} StatusMouse;
typedef struct
{
uint x, y, w, h;
int x, y, w, h;
char name[512];
} ImageAttr;

View File

@@ -34,7 +34,7 @@
#define TRAY_DWIDTH (infobar[conf.systray.screen].bar->geo.height + conf.systray.spacing)
Bool
bool
systray_acquire(void)
{
XSetWindowAttributes wattr;
@@ -98,11 +98,7 @@ systray_add(Window win)
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;
SLIST_INSERT_HEAD(&trayicons, s, next);
return;
}
@@ -110,14 +106,10 @@ systray_add(Window win)
void
systray_del(Systray *s)
{
Systray **ss;
if(!conf.systray.active)
return;
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next);
*ss = s->next;
SLIST_REMOVE(&trayicons, s, Systray, next);
free(s);
return;
@@ -158,10 +150,13 @@ systray_freeicons(void)
if(!conf.systray.active)
return;
for(i = trayicons; i; i = i->next)
while(!SLIST_EMPTY(&trayicons))
{
i = SLIST_FIRST(&trayicons);
SLIST_REMOVE_HEAD(&trayicons, next);
XUnmapWindow(dpy, i->win);
XReparentWindow(dpy, i->win, ROOT, 0, 0);
XReparentWindow(dpy, i->win, ROOT, 0, 0);
free(i);
}
@@ -181,7 +176,7 @@ systray_find(Window win)
if(!conf.systray.active)
return NULL;
for(i = trayicons; i; i = i->next)
SLIST_FOREACH(i, &trayicons, next)
if(i->win == win)
return i;
@@ -197,7 +192,7 @@ systray_get_width(void)
if(!conf.systray.active)
return 0;
for(i = trayicons; i; i = i->next)
SLIST_FOREACH(i, &trayicons, next)
w += i->geo.width + conf.systray.spacing + 1;
return w;
@@ -212,13 +207,13 @@ systray_update(void)
if(!conf.systray.active)
return;
if(!trayicons)
if(!SLIST_FIRST(&trayicons))
{
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
return;
}
for(i = trayicons; i; i = i->next)
SLIST_FOREACH(i, &trayicons, next)
{
XMapWindow(dpy, i->win);

202
src/tag.c
View File

@@ -39,7 +39,7 @@ void
tag_set(int tag)
{
Client *c;
Bool al = False;
bool al = False;
int i;
if(tag < 0 || tag > MAXTAG)
@@ -81,10 +81,10 @@ tag_set(int tag)
/* 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)
else if(tags[selscreen][seltag[selscreen]].flags & RequestUpdateFlag)
{
al = True;
tags[selscreen][seltag[selscreen]].request_update = False;
tags[selscreen][seltag[selscreen]].flags &= ~RequestUpdateFlag;
}
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
@@ -95,30 +95,30 @@ tag_set(int tag)
}
/* Check for ignore_tag clients */
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->tag == MAXTAG + 1 && c->screen == selscreen)
{
al = True;
break;
}
arrange(selscreen, al);
if(tags[selscreen][tag].request_update)
{
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][tag].request_update = False;
}
/* To focus selected client of the via focusontag option */
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->focusontag == tag && c->screen == selscreen)
break;
arrange(selscreen, al);
if(tags[selscreen][tag].flags & RequestUpdateFlag)
{
layout_func(selscreen, tag);
tags[selscreen][tag].flags &= ~RequestUpdateFlag;
}
/* 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)
SLIST_FOREACH(c, &clients, next)
if(c->tag == seltag[selscreen] && c->screen == selscreen)
break;
client_focus((c) ? c : NULL);
@@ -133,26 +133,43 @@ tag_set(int tag)
void
tag_transfert(Client *c, int tag)
{
screen_get_sel();
int s;
CHECK(c);
screen_get_sel();
if(tag <= 0)
tag = 1;
if(tag > conf.ntag[selscreen])
if(tag > conf.ntag[selscreen]
|| (c->tag == tag && c->screen == selscreen))
return;
s = c->screen;
tags[c->screen][c->tag].flags |= CleanFactFlag;
cfactor_clean(c);
/* Case of tag in split mode */
if(tags[c->screen][c->tag].flags & SplitFlag)
split_arrange_closed(c);
if(tags[selscreen][tag].flags & SplitFlag)
split_client_integrate(c, NULL, selscreen, tag);
/* Set new location */
c->tag = tag;
c->screen = selscreen;
if(s != c->screen)
arrange(s, True);
arrange(c->screen, True);
client_focus_next(c);
client_update_attributes(c);
tags[c->screen][tag].request_update = True;
tags[c->screen][tag].flags |= RequestUpdateFlag;
return;
}
@@ -207,9 +224,9 @@ uicb_tag_prev(uicb_t cmd)
void
uicb_tag_next_visible(uicb_t cmd)
{
int i, tag;
int tag;
Client *c;
Bool is_occupied[MAXTAG];
uint occupied = 0;
(void)cmd;
screen_get_sel();
@@ -220,15 +237,12 @@ uicb_tag_next_visible(uicb_t cmd)
return;
}
for(i = 0; i < MAXTAG; i++)
is_occupied[i] = False;
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->screen == selscreen)
is_occupied[c->tag] = True;
occupied |= TagFlag(c->tag);
for(tag = seltag[selscreen] + 1; tag < conf.ntag[selscreen] + 1; ++tag)
if(is_occupied[tag])
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
@@ -236,7 +250,7 @@ uicb_tag_next_visible(uicb_t cmd)
if(conf.tag_round)
for(tag = 0; tag < seltag[selscreen]; ++tag)
if(is_occupied[tag])
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
@@ -251,9 +265,9 @@ uicb_tag_next_visible(uicb_t cmd)
void
uicb_tag_prev_visible(uicb_t cmd)
{
int i, tag;
int tag;
Client *c;
Bool is_occupied[MAXTAG];
uint occupied = 0;
(void)cmd;
screen_get_sel();
@@ -264,15 +278,12 @@ uicb_tag_prev_visible(uicb_t cmd)
return;
}
for(i = 0; i < MAXTAG; i++)
is_occupied[i] = False;
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->screen == selscreen)
is_occupied[c->tag] = True;
occupied |= TagFlag(c->tag);
for(tag = seltag[selscreen] - 1; tag >= 0; --tag)
if(is_occupied[tag])
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
@@ -280,7 +291,7 @@ uicb_tag_prev_visible(uicb_t cmd)
if(conf.tag_round)
for(tag = conf.ntag[selscreen]; tag > seltag[selscreen]; --tag)
if(is_occupied[tag])
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
@@ -312,9 +323,9 @@ remove_old_last_tag(int selscreen)
int i;
for(i = 0; i <= conf.ntag[selscreen]; i++)
{
if(tags[selscreen][i].stay_last)
if(tags[selscreen][i].flags & StayLastFlag)
{
tags[selscreen][i].stay_last = False;
tags[selscreen][i].flags &= ~StayLastFlag;
break;
}
}
@@ -333,23 +344,22 @@ 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)
if(t1 == t2 || (t1 & t2) < 1 || (t1 | t2) > conf.ntag[s])
return;
t = tags[s][t1];
tags[s][t1] = tags[s][t2];
tags[s][t2] = t;
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
{
if(c->screen == s && c->tag == (uint)t1)
if(c->screen == s && c->tag == t1)
c->tag = t2;
else if(c->screen == s && c->tag == (uint)t2)
else if(c->screen == s && c->tag == t2)
c->tag = t1;
}
infobar_update_taglist(s);
infobar_update_taglist(&infobar[s]);
tag_set(t2);
return;
@@ -361,25 +371,24 @@ tag_swap(int s, int t1, int t2)
void
uicb_tag_stay_last(uicb_t cmd)
{
int i;
(void)cmd;
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].stay_last)
tags[selscreen][seltag[selscreen]].stay_last = False;
if(tags[selscreen][seltag[selscreen]].flags & StayLastFlag)
tags[selscreen][seltag[selscreen]].flags &= ~StayLastFlag;
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;
tags[selscreen][seltag[selscreen]].flags |= StayLastFlag;
arrange(selscreen, True);
}
@@ -464,25 +473,20 @@ 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)
SLIST_FOREACH(c, &clients, next)
if(c->flags & UrgentFlag)
{
b = True;
screen_set_sel(c->screen);
tag_set(c->tag);
client_focus(c);
break;
}
if(!b)
return;
screen_set_sel(c->screen);
tag_set(c->tag);
client_focus(c);
return;
}
@@ -494,12 +498,17 @@ uicb_tag_urgent(uicb_t cmd)
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])
if(tag < 0 || (tag | adtag) > conf.ntag[sc] + 1
|| adtag < 1 || adtag == seltag[sc])
return;
tags[sc][tag].tagad ^= TagFlag(adtag);
tags[sc][adtag].request_update = True;
tags[sc][tag].flags &= ~SplitFlag;
tags[sc][tag].tagad ^= TagFlag(adtag);
tags[sc][adtag].flags |= RequestUpdateFlag;
tags[sc][tag].flags |= CleanFactFlag;
tags[sc][adtag].flags |= CleanFactFlag;
tags[sc][adtag].flags &= ~SplitFlag;
arrange(sc, True);
return;
@@ -541,14 +550,10 @@ uicb_tag_swap_next(uicb_t cmd)
screen_get_sel();
/* Check if the next one does have the stay_last bool */
if(!tags[selscreen][conf.ntag[selscreen]].stay_last)
{
if(!(tags[selscreen][conf.ntag[selscreen]].flags & StayLastFlag))
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] + 1);
}
else
{
warnx("The next tag is set to always stay the last one");
}
return;
}
@@ -601,25 +606,24 @@ tag_new(int s, char *name)
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 };
Tag t = { displayedName, NULL, 0,
conf.default_tag.mwfact, conf.default_tag.nmaster, conf.default_tag.flags,
conf.default_tag.barpos, conf.default_tag.barpos,
conf.default_tag.layout, 0, NULL, 0 };
tags[s][conf.ntag[s]] = t;
/* For stay_last_tag */
if(tags[s][conf.ntag[s]-1].stay_last)
if(tags[s][conf.ntag[s] - 1].flags & StayLastFlag)
{
tag_swap(s, conf.ntag[s], conf.ntag[s]-1);
goToTag = conf.ntag[s]-1;
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);
infobar_update_taglist(&infobar[s]);
infobar_draw(&infobar[s]);
tag_set(goToTag);
return;
@@ -647,15 +651,15 @@ tag_delete(int s, int tag)
{
Tag t;
Client *c;
size_t i;
int 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)
SLIST_FOREACH(c, &clients, next)
if(c->screen == s && c->tag ==tag)
{
warnx("Client(s) present in this tag, can't delete it");
@@ -667,10 +671,10 @@ tag_delete(int s, int tag)
tags[s][tag] = t;
infobar[s].tags[tag] = NULL;
for(i = tag; i < (size_t)conf.ntag[s] + 1; ++i)
for(i = tag; i < conf.ntag[s] + 1; ++i)
{
/* Set clients tag because of shift */
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->screen == s && c->tag == i + 1)
c->tag = i;
@@ -679,8 +683,8 @@ tag_delete(int s, int tag)
}
infobar[s].need_update = True;
infobar_update_taglist(s);
infobar_draw(s);
infobar_update_taglist(&infobar[s]);
infobar_draw(&infobar[s]);
if(tag == seltag[s])
tag_set(tag <= conf.ntag[s] ? tag : conf.ntag[s]);
@@ -729,8 +733,8 @@ uicb_tag_rename(uicb_t cmd)
*/
strncpy(str, cmd, len);
infobar_update_taglist(selscreen);
infobar_draw(selscreen);
infobar_update_taglist(&infobar[selscreen]);
infobar_draw(&infobar[selscreen]);
return;
}
@@ -747,36 +751,30 @@ uicb_tag_toggle_expose(uicb_t cmd)
{
if(strcmp(tags[selscreen][i].name, conf.tag_expose_name) == 0)
{
if(clients && sel->tag)
if(SLIST_FIRST(&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;
tags[selscreen][j].flags |= RequestUpdateFlag;
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];
}
}
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;
tags[selscreen][conf.ntag[selscreen]].flags |= RequestUpdateFlag;
arrange(selscreen, True);
return;

View File

@@ -166,7 +166,7 @@ name_to_func(char *name, const func_name_list_t *l)
int i;
if(name)
for(i = 0; l[i].name ; ++i)
for(i = 0; l[i].name; ++i)
if(!strcmp(name, l[i].name))
return l[i].func;
@@ -279,55 +279,6 @@ uicb_spawn(uicb_t 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)

View File

@@ -1,143 +0,0 @@
/*
* viwmfs.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"
static vicmd_to_uicb vicmd[] =
{
{"r", "reload"},
{"q", "quit"},
{"t", "tag"},
{"tn", "tag_next"},
{"tp", "tag_prev"},
{"l", "set_layout"},
{"layout", "set_layout"},
{"ln", "layout_next"},
{"lp", "layout_prev"},
{"s", "screen_select"},
{"screen", "screen_select"},
{"sn", "screen_next"},
{"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"},
{"csp", "client_swap_prev"},
{"mwf", "set_mwfact"},
{"mwfact", "set_mwfact"},
{"nmaster", "set_nmaster"},
{"tm", "toggle_max"},
{"tf", "toggle_free"},
};
static void
viwmfs_help(void)
{
size_t i;
char s[20];
printf("ViWMFS commands list:\n");
for(i = 0; i < LEN(vicmd); ++i)
{
memset(s, ' ', sizeof(s));
s[15 - strlen(vicmd[i].cmd)] = '\0';
printf(" :%s%s %s\n", vicmd[i].cmd, s, vicmd[i].uicb);
}
return;
}
void
viwmfs(int argc, char **argv)
{
size_t i;
char *cmd, str[256] = { 0 };
Bool e;
if(!argc)
return;
if(argc > 3)
{
for(i = 2; i < (size_t)argc; ++i)
{
strcat(str, argv[i]);
if(*(str + strlen(str) - 1) != ':')
strcat(str, " ");
}
}
else
strncpy(str, argv[2], sizeof(str));
if(!strcmp(str, "help"))
{
viwmfs_help();
return;
}
if(*str == ':')
{
for(i = 0; i < strlen(str); str[i] = str[i + 1], ++i);
cmd = xstrdup(str);
for(i = 0; cmd[i] && cmd[i] != ' '; ++i);
cmd[i] = '\0';
for(i = 0; i < LEN(vicmd); ++i)
if(!strncmp(cmd, vicmd[i].cmd, strlen(cmd)))
{
exec_uicb_function(vicmd[i].uicb, clean_value(str + strlen(cmd)));
e = True;
break;
}
/* For uicb function with normal name specified */
if(!e)
{
if(!strcmp(str, "h") || !strcmp(str, "help"))
viwmfs_help();
else
exec_uicb_function(cmd, str + strlen(cmd));
}
}
return;
}

View File

@@ -32,8 +32,7 @@
#include "wmfs.h"
static volatile Bool exiting = False, sig_chld = False;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static volatile bool exiting = False, sig_chld = False;
int
errorhandler(Display *d, XErrorEvent *event)
@@ -80,17 +79,19 @@ errorhandlerdummy(Display *d, XErrorEvent *event)
void
quit(void)
{
Client *c;
size_t i, len;
/* Set the silent error handler */
XSetErrorHandler(errorhandlerdummy);
/* Unmanage all clients */
for(c = clients; c; c = c->next)
while(!SLIST_EMPTY(&clients))
{
Client *c = SLIST_FIRST(&clients);
client_unhide(c);
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
free(c);
SLIST_REMOVE_HEAD(&clients, next);
}
free(tags);
@@ -98,12 +99,22 @@ quit(void)
systray_freeicons();
XftFontClose(dpy, font);
#ifdef HAVE_XFT
if(conf.use_xft)
XftFontClose(dpy, font.font);
else
#endif /* HAVE_XFT */
XFreeFontSet(dpy, font.fontset);
for(i = 0; i < CurLast; ++i)
XFreeCursor(dpy, cursor[i]);
XFreeGC(dpy, gc_stipple);
infobar_destroy();
/* BarWindows */
while(!SLIST_EMPTY(&bwhead))
SLIST_REMOVE_HEAD(&bwhead, next);
free(sgeo);
free(spgeo);
free(infobar);
@@ -135,80 +146,29 @@ quit(void)
XSync(dpy, False);
XCloseDisplay(dpy);
/* kill status script */
if (conf.status_pid != (pid_t)-1)
kill(conf.status_pid, SIGTERM);
free(event_handle);
return;
}
static void
wait_childs_and_status(void)
{
int pid;
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);
}
static void *
thread_status(void *arg)
{
(void)arg;
int left = conf.status_timing;
pthread_detach(pthread_self());
do
{
wait_childs_and_status();
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.
*/
static void
mainloop(void)
{
XEvent ev;
pthread_t th_status;
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)) {
if (sig_chld) {
while(waitpid(-1, NULL, WNOHANG) > 0);
sig_chld = False;
}
HANDLE_EVENT(&ev);
}
while (!exiting && !XNextEvent(dpy, &ev)) {
getevent(ev);
wait_childs_and_status();
}
if (estatus)
pthread_join(th_status, NULL);
return;
}
/** Set the exiting variable to True
* for stop the main loop
* \param cmd unused uicb_t
@@ -232,7 +192,7 @@ scan(void)
XWindowAttributes wa;
Window usl, usl2, *w = NULL;
Atom rt;
int s, rf, tag = -1, screen = -1, free = -1, i;
int s, rf, tag = -1, screen = -1, flags = -1, i;
ulong ir, il;
uchar *ret;
Client *c;
@@ -260,10 +220,10 @@ scan(void)
XFree(ret);
}
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_ISFREE"), 0, 32,
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_FLAGS"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
free = *ret;
flags = *ret;
XFree(ret);
}
@@ -273,19 +233,19 @@ scan(void)
c->tag = tag;
if(screen != -1 && screen <= s - 1)
c->screen = screen;
if(free != -1)
c->flags |= (free) ? FreeFlag : 0;
if(flags != -1)
c->flags = flags;
client_update_attributes(c);
}
}
/* Set update layout request */
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
{
if(c->tag > (uint)conf.ntag[c->screen])
if(c->tag > conf.ntag[c->screen])
c->tag = conf.ntag[c->screen];
tags[c->screen][c->tag].request_update = True;
tags[c->screen][c->tag].flags |= RequestUpdateFlag;
}
for(i = 0; i < s; ++i)
@@ -317,7 +277,7 @@ uicb_reload(uicb_t cmd)
execute when wmfs will be already running).
\return False if wmfs is not running
*/
Bool
bool
check_wmfs_running(void)
{
Atom rt;
@@ -406,19 +366,6 @@ set_statustext(int s, char *str)
return;
}
/** Update status script by ewmh hint
*/
static void
update_status(void)
{
if(!check_wmfs_running())
return;
ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_STATUS", 0, 0, 0, 0, True);
return;
}
/** Signal handle function
*/
static void
@@ -447,7 +394,7 @@ int
main(int argc, char **argv)
{
int i;
char *ol = "csgVS";
char *ol = "cs";
extern char *optarg;
extern int optind;
struct sigaction sa;
@@ -456,7 +403,7 @@ main(int argc, char **argv)
all_argv = argv;
sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME"));
while((i = getopt(argc, argv, "hviSc:s:g:C:V:")) != -1)
while((i = getopt(argc, argv, "hvic:s:C:")) != -1)
{
/* For options who need WMFS running */
@@ -467,13 +414,10 @@ main(int argc, char **argv)
{
case 'h':
default:
printf("usage: %s [-ihvS] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>] [-V <viwmfs cmd]\n"
printf("usage: %s [-ihv] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>]\n"
" -C <file> Load a configuration file\n"
" -c <uicb_function> <cmd> Execute an uicb function to control WMFS\n"
" -g <argument> Show information about wmfs status\n"
" -s <screen_num> <string> Set the bar(s) statustext\n"
" -V <viwmfs cmd> Manage WMFS with vi-like command\n"
" -S Update status script\n"
" -h Show this page\n"
" -i Show informations\n"
" -v Show WMFS version\n", argv[0]);
@@ -486,13 +430,7 @@ main(int argc, char **argv)
break;
case 'v':
printf("WMFS "WMFS_VERSION"\n");
exit(EXIT_SUCCESS);
break;
case 'S':
update_status();
XCloseDisplay(dpy);
printf("wmfs"WMFS_VERSION"\n");
exit(EXIT_SUCCESS);
break;
@@ -514,17 +452,6 @@ main(int argc, char **argv)
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'g':
getinfo(optarg);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'V':
viwmfs(argc, argv);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
}
}

View File

@@ -1,3 +1,4 @@
/*
* wmfs.h
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
@@ -39,6 +40,7 @@
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
@@ -48,6 +50,8 @@
#include <dirent.h>
#include <err.h>
#include <pthread.h>
#include <locale.h>
#include <sys/queue.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -55,14 +59,14 @@
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xft/Xft.h>
/* Local headers */
#include "parse.h"
#include "structs.h"
/* Optional dependencies */
#ifdef HAVE_XFT
#include <X11/Xft/Xft.h>
#endif /* HAVE_XFT */
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* HAVE_XINERAMA */
@@ -75,6 +79,10 @@
#include <Imlib2.h>
#endif /* HAVE_IMLIB */
/* Local headers */
#include "parse.h"
#include "structs.h"
/* MACRO */
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
#define MouseMask (ButtonMask | PointerMotionMask)
@@ -83,13 +91,13 @@
#define ROOT RootWindow(dpy, SCREEN)
#define MAXH DisplayHeight(dpy, DefaultScreen(dpy))
#define MAXW DisplayWidth(dpy, DefaultScreen(dpy))
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font->height * 1.5))
#define FHINFOBAR ((font->height - font->descent) + (INFOBARH - font->height) / 2)
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font.height * 1.5))
#define FHINFOBAR ((font.height - font.de) + (((int)INFOBARH - font.height) >> 1))
#define SHADH (1)
#define BORDH conf.client.borderheight
#define TBARH ((conf.titlebar.height < BORDH) ? BORDH : conf.titlebar.height)
#define RESHW (6 * (BORDH))
#define BUTTONWH (TBARH / 2)
#define BUTTONWH (TBARH >> 1)
#define DEF_CONF ".config/wmfs/wmfsrc"
#define DEF_STATUS ".config/wmfs/status.sh"
#define PAD conf.pad
@@ -100,78 +108,114 @@
win = XCreateWindow(dpy, (parent), (x), (y), (w), (h), (b), CopyFromParent, \
InputOutput, CopyFromParent, (mask), (at)); \
XSetWindowBackground(dpy, win, (col)); \
} while (/* CONSTCOND */ 0)
} while(/* CONSTCOND */ 0)
#define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + BORDH * 2)
#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 LEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAXCLIST (64)
#define HANDLE_EVENT(e) event_handle[(e)->type](e);
#define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + (BORDH << 1))
#define FRAMEH(h) ((h) + (BORDH + TBARH))
#define CHECK(x) if(!(x)) return
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAXCLIST (64)
#define RPOS(x) (x & 1 ? x - 1 : x + 1)
#define LDIR(x) (x < Top)
#define FLAGAPPLY(v, b, f) ((b) ? (v |= (f)) : (v &= ~(f)))
#define INAREA(i, j, a) ((i) >= (a).x && (i) <= (a).x + (a).width && (j) >= (a).y && (j) <= (a).y + (a).height)
/* Cfactor define */
#define CFACTOR_CHECK2(g1, g2, p) (LDIR(p) ? (g1.height == g2.height) : (g1.width == g2.width))
#define CFACTOR_PARENTROW(g1, g2, p) \
(LDIR(p) \
? (p == Left ? (g1.x == g2.x) : (g1.x + g1.width == g2.x + g2.width)) \
: (p == Top ? (g1.y == g2.y) : (g1.y + g1.height == g2.y + g2.height))) \
/* Barwin define, wrappers for simple function */
#define barwin_delete_subwin(bw) XDestroySubwindows(dpy, bw->win)
#define barwin_map_subwin(bw) XMapSubwindows(dpy, bw->win)
#define barwin_unmap_subwin(bw) XUnmapSubwindows(dpy, bw->win)
#define barwin_refresh(bw) XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0)
#define barwin_map(bw) \
do { \
XMapWindow(dpy, bw->win); \
bw->flags |= MappedFlag; \
} while(/* CONSTCOND */ 0)
#define barwin_unmap(bw) \
do { \
XUnmapWindow(dpy, bw->win); \
bw->flags &= ~MappedFlag; \
} while(/* CONSTCOND */ 0)
/* barwin.c */
BarWindow *barwin_create(Window parent,
int x, int y,
uint w, uint h,
int w, int h,
uint bg, char*fg,
Bool entermask,
Bool stipple,
Bool border);
bool entermask,
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);
void barwin_map_subwin(BarWindow *bw);
void barwin_unmap(BarWindow *bw);
void barwin_unmap_subwin(BarWindow *bw);
void barwin_move(BarWindow *bw, int x, int y);
void barwin_resize(BarWindow *bw, uint w, uint h);
void barwin_resize(BarWindow *bw, int w, int h);
void barwin_refresh_color(BarWindow *bw);
void barwin_refresh(BarWindow *bw);
/* draw.c */
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);
void draw_graph(Drawable dr, int x, int y, uint w, uint h, uint color, char *data);
void draw_rectangle(Drawable dr, int x, int y, int w, int h, uint color);
void draw_graph(Drawable dr, int x, int y, int w, int h, uint color, char *data);
ushort textw(char *text);
/* infobar.c */
void infobar_init(void);
void infobar_draw(int sc);
void infobar_draw_selbar(int sc);
void infobar_draw_taglist(int sc);
void infobar_update_taglist(int sc);
void infobar_draw_layout(InfoBar *i);
void _infobar_draw(InfoBar *i);
void infobar_draw(InfoBar *i);
void infobar_draw_selbar(InfoBar *i);
void infobar_draw_taglist(InfoBar *i);
void infobar_update_taglist(InfoBar *i);
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);
/* cfactor.c */
void cfactor_clean(Client *c);
Geo cfactor_geo(Geo geo, int fact[4], int *err);
void cfactor_set(Client *c, Position p, int fac);
void cfactor_multi_set(Client *c, int fac[4]);
/* Generated with macro {{{ */
void uicb_client_resize_Right(uicb_t cmd);
void uicb_client_resize_Left(uicb_t cmd);
void uicb_client_resize_Top(uicb_t cmd);
void uicb_client_resize_Bottom(uicb_t cmd);
/* }}} */
/* client.c */
void client_attach(Client *c);
void client_configure(Client *c);
void client_detach(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);
Client* client_gb_titlebar(Window w);
Client* client_gb_resize(Window w);
Client* client_gb_button(Window w, int *n);
Client* client_gb_pos(Client *c, int x, int y);
/* }}} */
void client_get_name(Client *c);
void client_hide(Client *c);
void client_kill(Client *c);
Bool ishide(Client *c, int screen);
bool ishide(Client *c, int screen);
void client_map(Client *c);
Client* client_manage(Window w, XWindowAttributes *wa, Bool ar);
void client_geo_hints(XRectangle *geo, Client *c);
void client_moveresize(Client *c, XRectangle geo, Bool r);
Client* client_manage(Window w, XWindowAttributes *wa, bool ar);
void client_geo_hints(Geo *geo, Client *c);
void client_moveresize(Client *c, Geo geo, bool r);
void client_maximize(Client *c);
void client_size_hints(Client *c);
void client_swap(Client *c1, Client *c2);
@@ -181,16 +225,23 @@ void client_focus_next(Client *c);
void client_unmanage(Client *c);
void client_unmap(Client *c);
void client_update_attributes(Client *c);
void client_urgent(Client *c, Bool u);
void client_urgent(Client *c, bool u);
Client* client_get_next_with_direction(Client *bc, Position pos);
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);
/* Generated with macro {{{ */
void uicb_client_focus_next(uicb_t);
void uicb_client_focus_prev(uicb_t);
void uicb_client_swapsel_next(uicb_t);
void uicb_client_swapsel_prev(uicb_t);
void uicb_client_swapsel_Right(uicb_t);
void uicb_client_swapsel_Left(uicb_t);
void uicb_client_swapsel_Top(uicb_t);
void uicb_client_swapsel_Bottom(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);
@@ -199,7 +250,7 @@ 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);
bool uicb_checkclist(uicb_t);
void uicb_client_ignore_tag(uicb_t);
void uicb_client_set_master(uicb_t);
@@ -218,8 +269,8 @@ void ewmh_manage_window_type(Client *c);
/* frame.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_moveresize(Client *c, Geo geo);
void frame_update_color(Client *c, bool focused);
void frame_update(Client *c);
/* config.c */
@@ -230,7 +281,11 @@ uint color_shade(uint, double);
/* event.c */
void grabkeys(void);
void getevent(XEvent ev);
void event_make_array(void);
#ifdef HAVE_XRANDR
void xrandrevent(XEvent *e);
#endif /* HAVE_XRANDR */
/* menu.c */
void menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n);
@@ -244,7 +299,7 @@ void uicb_launcher(uicb_t);
/* mouse.c */
void mouse_resize(Client *c);
void mouse_grabbuttons(Client *c, Bool focused);
void mouse_grabbuttons(Client *c, bool focused);
void uicb_mouse_move(uicb_t);
void uicb_mouse_resize(uicb_t);
@@ -270,14 +325,9 @@ char *char_to_str(const char c);
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);
void tag_transfert(Client *c, int tag);
@@ -305,7 +355,7 @@ void uicb_tag_toggle_expose(uicb_t cmd);
/* screen.c */
int screen_count(void);
XRectangle screen_get_geo(int s);
Geo screen_get_geo(int s);
int screen_get_with_geo(int x, int y);
int screen_get_sel(void);
void screen_set_sel(int screen);
@@ -316,10 +366,11 @@ void uicb_screen_prev(uicb_t);
void uicb_screen_prev_sel(uicb_t);
/* status.c */
void statustext_handle(int sc, char *str);
void statustext_mouse(char *str, Geo area, InfoBar *infobar);
void statustext_handle(InfoBar *ib);
/* systray.c */
Bool systray_acquire(void);
bool systray_acquire(void);
void systray_add(Window win);
void systray_del(Systray *s);
void systray_state(Systray *s);
@@ -329,9 +380,11 @@ int systray_get_width(void);
void systray_update(void);
/* layout.c */
void arrange(int screen, Bool update_layout);
void arrange(int screen, bool update_layout);
void layout_func(int screen, int tag);
Client *tiled_client(int screen, Client *c);
void freelayout(int screen);
void layoutswitch(Bool b);
void layoutswitch(bool b);
void maxlayout(int screen);
/* tile {{{ */
void tile(int screen);
@@ -353,25 +406,41 @@ void uicb_set_layout(uicb_t);
void uicb_toggle_resizehint(uicb_t);
void uicb_toggle_abovefc(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);
void layout_split_client(Client *c, bool p);
void layout_split_apply(Client *c);
void layout_split_arrange_closed(int screen);
void uicb_split_client_vertical(uicb_t);
void uicb_split_client_horizontal(uicb_t);
bool uicb_checkmax(uicb_t);
bool uicb_checkfree(uicb_t);
bool uicb_checklayout(uicb_t);
/* init.c */
void init(void);
/* getinfo.c */
void getinfo(char *info);
/* viwmfs.c */
void viwmfs(int argc, char **argv);
/* split.c */
void split_store_geo(int screen, int tag);
void split_set_current(Client *nc, Client *ghost);
void split_apply_current(int screen, int tag);
void split_arrange_closed(Client *ghost);
Geo split_client(Client *c, bool p);
void split_client_fill(Client *c, Geo geo);
void split_client_integrate(Client *c, Client *sc, int screen, int tag);
void split_move_dir(Client *c, Position p);
void uicb_split_toggle(uicb_t cmd);
/* Generated with macro {{{ */
void uicb_split_move_Right(uicb_t);
void uicb_split_move_Left(uicb_t);
void uicb_split_move_Top(uicb_t);
void uicb_split_move_Bottom(uicb_t);
/* }}} */
/* wmfs.c */
int errorhandler(Display *d, XErrorEvent *event);
int errorhandlerdummy(Display *d, XErrorEvent *event);
void quit(void);
void *thread_process(void *arg);
Bool check_wmfs_running(void);
bool check_wmfs_running(void);
void exec_uicb_function(char *func, char *cmd);
void handle_signal(int signum);
void uicb_quit(uicb_t);
@@ -379,16 +448,15 @@ void uicb_reload(uicb_t);
/* Variables */
/* Principal */
/* Main */
Display *dpy;
GC gc, gc_stipple;
int selscreen;
int prevselscreen;
Conf conf;
Key *keys;
Bool estatus;
XRectangle *sgeo;
XRectangle *spgeo;
Geo *sgeo;
Geo *spgeo;
Cursor cursor[CurLast];
char *argv_global;
char **all_argv;
@@ -396,7 +464,7 @@ int xrandr_event;
uint timing;
/* Fonts */
XftFont *font;
FontStruct font;
/* Atoms list */
Atom *net_atom;
@@ -416,18 +484,28 @@ struct clndx {
Client *client;
} clist_index[MAXCLIST];
/* Important Client */
Client *clients;
/* Client */
SLIST_HEAD(, Client) clients;
Client *sel;
/* Other */
/* Event */
int nevent;
void (**event_handle)(XEvent*);
extern const func_name_list_t func_list[];
extern const func_name_list_t layout_list[];
uint numlockmask;
Systray *trayicons;
/* Systray */
SLIST_HEAD(, Systray) trayicons;
Window traywin;
int tray_width;
/* BarWindow */
SLIST_HEAD(, BarWindow) bwhead;
/* Status */
SLIST_HEAD(, StatusMouse) smhead;
#endif /* WMFS_H */

88
wmfsrc
View File

@@ -7,19 +7,17 @@
# @include "~/.config/wmfs/menu-wmfsrc"
[misc]
use_xft = true
font = "dejavu-10"
raisefocus = true
raiseswitch = false
focus_follow_mouse = true
focus_follow_movement = false
focus_follow_movement = true
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]
@@ -31,6 +29,12 @@
light_shade = 0.10
dark_shade = -0.10
# Order of infobar elements:
# t = Tag list
# l = Layout button
# s = Selbar
elements_order = "tls"
[systray]
# Enable/disable systray
active = true
@@ -67,12 +71,12 @@
# Value menu or switch.
system = "menu"
# Value left or right.
placement = "right"
# Keep layout geo for free layout
keep_layout_geo = false
# Enable split mode with client_resize_<direction>
cfactor_enable_split = true
# Symbol displayed for the selected layout in the list
selected_layout_symbol = "*"
@@ -100,9 +104,10 @@
name = "new tag"
mwfact = 0.5
nmaster = 1
layout = "tile_right"
layout = "tile"
resizehint = false
infobar_position = "top"
split = false
[/default_tag]
# whether client_next on the last tag will send you on the first
@@ -124,14 +129,14 @@
#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"
expose_name = "EXPOSE"
expose_layout = "tile_left"
# Border around the tag buttons.
border = true
border = true
# Hide empty tags in tag list
autohide = true
autohide = false
# Mouse buttons action on tag.
mouse_button_tag_sel = "1"
@@ -149,11 +154,11 @@
resizehint = false
infobar_position = "top"
above_fc = false
split = 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 = "two" [/tag]
[tag] name = "three" [/tag]
[tag] name = "four" [/tag]
[tag] name = "five" [/tag]
@@ -191,7 +196,7 @@
# same as above but for the screen
#default_open_screen = 1
# Space between tiled clients
# Space between tiled clients (px)
padding = 0
# Modifier for mouse use
@@ -307,13 +312,6 @@
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]
@@ -334,7 +332,7 @@
# 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]
@@ -378,12 +376,6 @@
# 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]
@@ -393,9 +385,6 @@
#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]
@@ -437,10 +426,41 @@
[key] mod = {"Super", "Shift"} key = "a" func = "client_screen_next" [/key]
[key] mod = {"Super", "Shift"} key = "z" func = "client_screen_prev" [/key]
# Toggle tag explose
[key] mod = {"Alt"} key = "e" func = "toggle_tag_expose" [/key]
# Toggle split mode
[key] mod = {"Alt"} key = "s" func = "split_toggle" [/key]
# Focus next client with direction
[key] mod = {"Alt"} key = "h" func = "client_focus_left" [/key]
[key] mod = {"Alt"} key = "l" func = "client_focus_right" [/key]
[key] mod = {"Alt"} key = "k" func = "client_focus_top" [/key]
[key] mod = {"Alt"} key = "j" func = "client_focus_bottom" [/key]
# Swap next client with direction
[key] mod = {"Control"} key = "h" func = "client_swap_left" [/key]
[key] mod = {"Control"} key = "l" func = "client_swap_right" [/key]
[key] mod = {"Control"} key = "k" func = "client_swap_top" [/key]
[key] mod = {"Control"} key = "j" func = "client_swap_bottom" [/key]
# Move next splitted client with direction
[key] mod = {"Control", "Shift"} key = "h" func = "split_move_left" [/key]
[key] mod = {"Control", "Shift"} key = "l" func = "split_move_right" [/key]
[key] mod = {"Control", "Shift"} key = "k" func = "split_move_top" [/key]
[key] mod = {"Control", "Shift"} key = "j" func = "split_move_bottom" [/key]
# Resize selected tiled client with direction
[key] mod = {"Super"} key = "h" func = "client_resize_left" cmd = "20" [/key]
[key] mod = {"Super"} key = "l" func = "client_resize_right" cmd = "20" [/key]
[key] mod = {"Super"} key = "k" func = "client_resize_top" cmd = "20" [/key]
[key] mod = {"Super"} key = "j" func = "client_resize_bottom" cmd = "20" [/key]
[key] mod = { "Super", "Control"} key = "h" func = "client_resize_right" cmd = "-20" [/key]
[key] mod = { "Super", "Control"} key = "l" func = "client_resize_left" cmd = "-20" [/key]
[key] mod = { "Super", "Control"} key = "k" func = "client_resize_bottom" cmd = "-20" [/key]
[key] mod = { "Super", "Control"} key = "j" func = "client_resize_top" cmd = "-20" [/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}