518 Commits

Author SHA1 Message Date
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
Raphael Khaiat
0e8634fbe4 Fix bug #104 found by pistache 2011-03-24 13:34:47 +01:00
Raphael Khaiat
df4e32f4f9 Fix feature expose when there is no client on the screen.
Bug found by pistache
2011-03-24 13:05:37 +01:00
Viet Nguyen Quoc
6372f3974c Fix "flick" when new client is not in current tag 2011-03-23 14:15:19 +01:00
Raphael Khaiat
703974cb00 Add the keybind client_set_master in the default wmfsrc 2011-03-23 13:55:54 +01:00
Viet Nguyen Quoc
4064cbdfd9 Add client_set_master command
The function swaps selected client with the first one (master).
2011-03-23 13:49:23 +01:00
Raphael Khaiat
a7f9bf65ff Fix "expose" feature by adding "request_update" to all tags of the
screen
2011-03-23 13:42:53 +01:00
Raphael Khaiat
79928efd35 Delete useless function 2011-03-22 14:08:59 +01:00
Raphael Khaiat
b1a52a3a6b Fix "expose feature" 2011-03-22 14:07:53 +01:00
Raphael Khaiat
41c4570dcf Add "expose" feature ala mac OS X to display all client of a screen
Feature #100 requested by shibo
2011-03-21 13:28:15 +01:00
Martin Duquesnoy
ae47ab6f71 Event: Apply pl's patch (bug #97) 2011-03-12 23:09:42 +01:00
Paride Legovini
5ece3a6e55 focus_follow_movement caused flickering, fixed.
When using focus_follow_movement, client_focus() should be called only
if the target client is unfocused. Calling client_focus() on every motion
event causes an ugly flickering of the window.

Signed-off-by: Raphael Khaiat <raphael@khaiat.org>
2011-03-11 17:18:00 +01:00
Raphael Khaiat
4d39413f56 Merge branch 'master' into bacardi55 2011-03-11 17:17:19 +01:00
Martin Duquesnoy
8bc30628c3 Client: Fix client closing from additional tag 2011-03-06 02:20:49 +01:00
Martin Duquesnoy
041e9ec20d Event/conf: Add focus_follow_movement [misc] option requested by pl_ 2011-02-25 19:22:29 +01:00
Martin Duquesnoy
1e35777c18 Client: Add client_screen_set uicb function requested by 0x1 2011-02-25 11:11:33 +01:00
Raphael Khaiat
3ca201c42a Delete deprecated option raiseswitch 2011-02-23 23:22:11 +01:00
Raphael Khaiat
34f2cb5b03 Merge branch 'master' of github.com:xorg62/wmfs into bacardi55 2011-02-23 23:19:40 +01:00
Raphael Khaiat
946e4c1606 Remove double follow_client entry in the rule section of the wmfsrc 2011-02-23 23:19:06 +01:00
Clément Bœsch
6291639b24 Remove a lot of static declarations
A lot of functions are also moved in the process.
2011-02-23 22:37:42 +01:00
Clément Bœsch
6a0eedb63c Make a bunch of stuff static 2011-02-23 22:37:13 +01:00
Clément Bœsch
22c9eee9af Remove unused functions 2011-02-23 22:37:13 +01:00
Clément Bœsch
7d66c50676 Cosmetic 2011-02-23 22:37:13 +01:00
Clément Bœsch
9766392332 Avoid overflow on ret 2011-02-23 21:53:40 +01:00
Clément Bœsch
d79404f5ee Avoid last ret char not being zero after strncpy 2011-02-23 21:53:40 +01:00
Clément Bœsch
f5134bd6b3 Option -W is deprecated; -Wextra is its replacement 2011-02-23 21:53:40 +01:00
Martin Duquesnoy
d213d13784 Barwin/Frame: Optimization of saikobee feature 2011-02-23 15:15:31 +01:00
Martin Duquesnoy
57019236aa Merge https://github.com/saikobee/wmfs 2011-02-23 14:15:56 +01:00
Brian Mock
ac00fefaa9 Fixed tag bar border drawing 2011-02-23 00:51:50 -08:00
Brian Mock
ddcdf6ce83 Tag background wasn't shaded properly 2011-02-22 23:25:39 -08:00
Brian Mock
9235775dd2 Final touches, including wmfsrc default options 2011-02-22 19:37:06 -08:00
Brian Mock
971fb3240a Should work... but no compile 2011-02-22 15:37:50 -08:00
Brian Mock
bd1575e1b2 Fixed some bad whitespace in config.c 2011-02-22 14:05:46 -08:00
Brian Mock
83d2da9da6 Added comments to all my color.c functions 2011-02-22 13:02:40 -08:00
Brian Mock
3be59059f4 Shading seems to work, still need to add config 2011-02-22 12:35:42 -08:00
Raphael Khaiat
891ba6d866 Fix client_tile_raise feature 2011-02-22 14:47:32 +01:00
Brian Mock
5729fe95fb Fixed style on "if" 2011-02-21 16:30:23 -08:00
Brian Mock
43686dc82c Fixed licensing info to use my name 2011-02-21 16:28:38 -08:00
Brian Mock
d1f400e940 Forgot license info 2011-02-21 16:23:56 -08:00
Brian Mock
16120744a8 Added color functions 2011-02-21 16:20:02 -08:00
Martin Duquesnoy
e2942ec597 Client: Fix raise of client when maximize 2011-02-21 12:54:42 +01:00
Martin Duquesnoy
bf26e8c22e Client: Add new_client_get_mouse feature requested by thechitowncubs 2011-02-21 03:20:58 +01:00
Raphael Khaiat
4898e07e5e Fix typo in wmfsrc about the status_path 2011-02-19 02:13:11 +01:00
Raphael Khaiat
ff7853738f Merge branch 'master' into bacardi55 2011-02-19 02:09:58 +01:00
Raphael Khaiat
7180d733bd Correct previous feature for raising tiled client 2011-02-16 19:20:58 +01:00
Raphael Khaiat
325f115c09 Add feature for raising tile client over free client when selected.
Feature requested by bacardi55 :)
2011-02-15 19:10:10 +01:00
Martin Duquesnoy
f48b9651c9 Fix mod of configure 2011-02-15 18:12:22 +01:00
Martin Duquesnoy
dcf3979c00 Add removed things from bacadi55 commits 2011-02-15 17:59:25 +01:00
Martin Duquesnoy
db98e3978b Client: Swap tag in client_swap if c1->tag != c2->tag 2011-02-15 17:57:24 +01:00
Raphael Khaiat
3cc68b6872 Delete unused param 2011-02-14 18:42:23 +01:00
Raphael Khaiat
45e796406b Add unused function and comments in the wmfsrc 2011-02-14 18:39:50 +01:00
Raphael Khaiat
f91699d6bc Add function about changing screen in the default wmfsrc 2011-02-02 18:43:04 +01:00
Raphael Khaiat
7d391f47f5 Merge branch 'master' into bacardi55 2011-02-01 20:54:56 +01:00
David Delassus
aa3f2b7fd0 Fix _WMFS_FONT, bug #83
Signed-off-by: Raphael Khaiat <raphael@khaiat.org>
2011-01-31 13:58:34 +01:00
Raphael Khaiat
2e4c8bd202 Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-26 13:37:21 +01:00
Raphael Khaiat
741002b724 remove bug if there is only one screen and screen_next is called
(used to unselect all client of the screen)
2011-01-26 13:35:54 +01:00
Raphael Khaiat
c8e5ac4619 Feature #79 : add a keybind to toggle the display of the infobar.
Feature requested by litemotiv
2011-01-24 23:50:52 +01:00
Raphael Khaiat
07ad0c6263 Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-24 08:51:46 +01:00
Raphael Khaiat
41cc6944ae Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-23 23:59:30 +01:00
Raphael Khaiat
48e226f5ae Merge branch 'master' into bacardi55 2011-01-23 23:58:39 +01:00
Raphael Khaiat
3652a4060c Add feature for following a client that is open in a different tag.
Feature requested by anonymous_user on the wmfs thread in the
archlinux.org forum
2011-01-23 23:56:21 +01:00
Raphael Khaiat
b4e33395b3 Merge branch 'master' into bacardi55 2011-01-21 16:10:28 +01:00
Philippe Pepiot
d0bb69150a Clean thread/spawn/signal usage in wmfs
- Don't create 2 thread
- Don't create status thread when conf.status_timing == 0
- Don't launch status script if still running
- Remove double fork() hack in spawn()
- Wait childs properly
- mutex on conf.status_pid and sig_chld variable, thread-safe and
  signal-safe
- Set exiting variable volatile, signal-safe
- Use sigaction instead of signal

TODO: set mutex for exiting variable because this is not thread-safe
2011-01-20 11:32:29 +01:00
Martin Duquesnoy
7e0436ffdc Systray: Replace zcalloc with xcalloc (potential bug) 2011-01-17 20:19:25 +01:00
Martin Duquesnoy
c8c210bcac Wmfs: Fix typo 2011-01-15 20:59:19 +01:00
Martin Duquesnoy
993b408262 Apply Almito's patchs for xcompmgr opacity support (#70), skype focus bug (#66) and fix for #68 & #69 2011-01-15 20:55:13 +01:00
Raphael Khaiat
f51d943bd9 Merge branch 'master' into bacardi55 2011-01-14 13:35:11 +01:00
Clément Bœsch
56b6b467ee Avoid fd leak in parse_keywords. 2011-01-12 20:17:57 +01:00
Clément Bœsch
7ac4bf32c2 One memset instead of two.
This also fix the strange sizeof.
2011-01-12 20:17:57 +01:00
Clément Bœsch
b5f24e042f Remove a few check before calling free in parser. 2011-01-12 20:17:57 +01:00
Clément Bœsch
a5432919ca Remove pointless if before calling free.
The free() function frees the memory space pointed to by ptr, which must
have been returned by a previous call to malloc(), calloc() or
realloc().  Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs.  If ptr is NULL, no operation is performed.
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

                                          -- man malloc(3)
2011-01-12 20:17:57 +01:00
Clément Bœsch
c174e69b64 Fix potential crash when using mouse_button_list. 2011-01-12 20:17:56 +01:00
Clément Bœsch
209f9a09a4 Make a bunch of functions static. 2011-01-12 20:17:56 +01:00
Raphael Khaiat
c5dfeb9878 Merge branch 'master' into bacardi55 2011-01-12 15:45:37 +01:00
Raphael Khaiat
3abfe9d7bb Report the correction of the reload event that had been made for the
uicb_reload function
2011-01-12 15:43:01 +01:00
Martin Duquesnoy
27c4c260c6 Client: Revert libvte patch by roidelapluie 2011-01-12 11:26:41 +01:00
Raphael Khaiat
8ea76e1167 Fix reload function (problem due to a bad merge), thanks to Erus 2011-01-10 21:45:11 +01:00
Raphael Khaiat
6ec79f626e Merge branch 'master' into bacardi55 2011-01-10 20:42:15 +01:00
Raphael Khaiat
2320e8586c Implement fixture #63 : auto center option for free client 2011-01-10 20:40:55 +01:00
Raphael Khaiat
c317afc79d Re-arrange code for fix #67 (avoid code duplication) 2011-01-10 20:39:14 +01:00
Martin Duquesnoy
056cb5daf6 Util: Fix spawn 2011-01-10 19:31:42 +01:00
Raphael Khaiat
7bb0fdcbad Fix bug #67 2011-01-08 18:23:11 +01:00
Raphael Khaiat
2273ccc5d5 Let wmfs reload now with the same argument that it was launched with 2011-01-08 18:20:27 +01:00
Martin Duquesnoy
18e97d3e1e Wmfs: Use pthread instead of setitimer 2011-01-08 15:47:19 +01:00
Martin Duquesnoy
9de133dac7 Merge branch 'master' of git.wmfs.info:wmfs 2011-01-08 15:21:59 +01:00
Raphael Khaiat
b1d4e2a403 Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-05 19:57:22 +01:00
Raphael Khaiat
8e6cea6d05 Makes code pretyer :) 2011-01-05 19:55:16 +01:00
bacardi55@gmail.com
03c41f9b3b Add option (tag_auto_prev) in wmfsrc to disable the auto tag prev
when going twice on the same tag.
2011-01-05 19:51:48 +01:00
Raphael Khaiat
42a0612664 Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-05 01:28:50 +01:00
Raphael Khaiat
fb1627e8cc Fix Feature #22 : set a default tag and/or screen where to send client
that have no tag/screen specific rule. Feature requested by philpep
2011-01-05 01:25:12 +01:00
bacardi55@gmail.com
c8eb002768 Fix tag_prev_sel 2011-01-04 22:53:24 +01:00
bacardi55@gmail.com
0d0c3af47b Merge branch 'master' of github.com:xorg62/wmfs into bacardi55 2011-01-04 22:51:42 +01:00
bacardi55@gmail.com
5b5dd104d9 Merge branch 'bacardi55' of github.com:xorg62/wmfs into bacardi55 2011-01-04 21:13:14 +01:00
Philippe Pepiot
0a2c1f9d13 Use sigaction instead of signal.
SIGCHLD and SIGALRM are now exclusives (one mask other)
2011-01-04 03:02:29 +01:00
Philippe Pepiot
c817b7277b Disable status script timer on reload (instead of ignoring signal) 2011-01-04 01:24:51 +01:00
Philippe Pepiot
99e85cbfc2 Use setitimer instead of alarm 2011-01-04 01:10:27 +01:00
Julien Pivotto
a1ad5685f9 Fix libvte bug when resizing them
Signed-off-by: Raphael Khaiat <raphael@khaiat.org>
2011-01-03 22:27:41 +01:00
Julien Pivotto
abf71d99b9 [PATCH] Add a ignoretags rule 2011-01-03 21:49:25 +01:00
Raphael Khaiat
1460229397 Merge branch 'master' into bacardi55 2011-01-03 21:40:27 +01:00
Martin Duquesnoy
47a68568fe Tag: Fix last feature with tag_round 2011-01-03 21:33:43 +01:00
Martin Duquesnoy
a0fd6a77cc Layout: Fix nmaster ksh bug with tile_right/left 2011-01-03 20:01:04 +01:00
bacardi55@gmail.com
ef6b057234 Merge branch 'master' into bacardi55 2011-01-03 19:42:54 +01:00
Martin Duquesnoy
e32726f008 Tag: Fix infobar position when tag switch with last feature 2011-01-03 19:40:42 +01:00
bacardi55@gmail.com
74bbf0bd04 Merge remote branch 'github/master' into bacardi55 2011-01-02 19:51:36 +01:00
Martin Duquesnoy
b85b6bd687 Tag: Add toggle to prev selected tag if tag is selected two times (requested by addikt1ve) 2011-01-02 19:36:33 +01:00
Julien Pivotto
bf16b4a2e7 Add a 'ignoretags' rule
Signed-off-by: bacardi55@gmail.com <bacardi55@daimadoshi.bacardi55.org>
2010-12-31 15:12:53 +01:00
Philippe Pepiot
f2bd808b86 Fix segfault in parser if options == PARSE_MAX_LIST-1
Reported by Armael
Increase PARSE_MAX_LIST from 10 to 32
2010-12-25 16:25:42 +01:00
bacardi55@gmail.com
f2734a5f2b Correct typo thanks to ubitux 2010-12-19 13:42:39 +01:00
bacardi55@gmail.com
b4fb75806a Merge branch 'master' into bacardi55 2010-12-19 13:14:30 +01:00
Philippe Pepiot
dbe7588c0a Ignore SIGALRM before restart
If new wmfs process receive SIGALRM before set the handler, wmfs quits
Bug found by Erus
2010-12-18 14:58:29 +01:00
Engil Hramn
dae3019185 Fix some error in the manpage and in the information printed by the binary 2010-12-09 17:09:47 +01:00
Raphael Khaiat
3f461810d2 Add engil's patch 2010-12-09 16:01:19 +01:00
Raphael Khaiat
0a708c8dda Merge branch 'master' into bacardi55
Conflicts:
	src/config.c
2010-12-07 19:16:32 +01:00
Philippe Pepiot
6072c2d811 Set default tag params. (patch by bacardi55) fixes #51 2010-12-07 01:38:21 +01:00
Philippe Pepiot
ce3813608c Status script not spawned if still running 2010-12-07 01:34:22 +01:00
Philippe Pepiot
6c332c9ea5 Oops. Fix signal not handled at all 2010-12-07 01:19:28 +01:00
Philippe Pepiot
d606f999f9 Add distclean target (clean && remove Makefile) 2010-12-07 00:30:36 +01:00
Philippe Pepiot
87575a019d Use SIGALRM instead of pthread for status script 2010-12-07 00:28:12 +01:00
Philippe Pepiot
6882cfb986 Only one handler for signals 2010-12-07 00:12:54 +01:00
Philippe Pepiot
9e457b3832 Remove glibc stuffs, wmfs is not ansi C that's a fact 2010-12-06 23:49:42 +01:00
Philippe Pepiot
c8a74878a1 Remove double fork for spawn and kill status with SIGTERM 2010-12-03 16:59:07 +01:00
Philippe Pepiot
d0058146dd Remove non used function get_mouse_pos 2010-12-03 12:36:51 +01:00
Philippe Pepiot
77e458048d Fix tag_new() tag name
possible overflow + random memory access
2010-12-03 11:06:33 +01:00
Raphael Khaiat
f6206d65b1 Merge branch 'master' into bacardi55
Conflicts:
	src/wmfs.c
2010-11-30 00:38:27 +01:00
Philippe Pepiot
c90a5743b3 Parser: Use read() instead of mmap() 2010-11-29 22:08:01 +01:00
Philippe Pepiot
3459ed0b20 Define optarg and optind (was breaking compilation on NetBSD) 2010-11-29 21:17:04 +01:00
Martin Duquesnoy
3cf93a0961 Launcher: Add width_limit option in multi set_launcher section to limit size of launcher window (Requested by s__C) 2010-11-28 13:06:24 +01:00
Martin Duquesnoy
719654fcbc Ewmh: Add _WMFS_FONT property for external information about font 2010-11-26 21:32:28 +01:00
Raphael Khaiat
e053d41a3d Change the default name at empty as it should be 2010-11-21 22:06:55 +01:00
Raphael Khaiat
1170a6afbc Put back the good default value, thanks xorg62 2010-11-21 22:01:43 +01:00
Raphael Khaiat
a42237aab7 Correction of the #51 bug for default_tag value in tag defined in the
wmfsrc without all options.
2010-11-21 21:55:57 +01:00
Raphael Khaiat
f5f2d8c7de Correction for the new function stay_last_tag 2010-11-21 19:58:01 +01:00
Raphael Khaiat
bc31510d64 Merge branch master in bacardi55 2010-11-19 23:41:56 +01:00
Raphael Khaiat
f928497e70 Add "stay_last_tag" fonction/keybind 2010-11-19 20:17:17 +01:00
Philippe Pepiot
daeffb324e Fix possibles segfaults, dead assignment and other division by zero.
Thanks to clang build report
2010-11-19 19:55:57 +01:00
Philippe Pepiot
d75746bcf4 s/strcpy/strncpy and fix somes unused variables 2010-11-19 17:36:37 +01:00
Philippe Pepiot
82b17ea02f Improve allocating system and integrate parser
emalloc remplaced with xcalloc/xmalloc/xrealloc
and easy wrappers for strings zmalloc/zcalloc/zrealloc
 - exit on fail
 - prevent size_t overflow

Integrate parser in src/
2010-11-19 16:42:14 +01:00
Philippe Pepiot
19ecd89d89 End func_list[] with { NULL, NULL } 2010-11-19 14:44:34 +01:00
Philippe Pepiot
c7b2d98303 BuildSystem: fix XDG_CONFIG_DIR issue 2010-11-19 14:35:35 +01:00
Raphael Khaiat
546366b282 Merge master in bacardi55 branch 2010-11-18 19:48:18 +01:00
Raphael Khaiat
20c99826ce Merge branch 'master' into bacardi55
Conflicts:
	src/wmfs.c
2010-11-18 19:47:36 +01:00
Martin Duquesnoy
eda1bfdfec Merge branch 'master' of git.wmfs.info:wmfs 2010-11-18 19:12:35 +01:00
Martin Duquesnoy
22295948ec Ewmh: Remove _NET_WORKAREA support, Fix bug #58 signaled by Kernald. 2010-11-18 19:12:10 +01:00
Philippe Pepiot
c2664e8e85 wmfs compile with -W -Wall -Wextra (TODO: fix types !!) 2010-11-17 02:27:15 +01:00
Raphael Khaiat
e5b2a9e058 Add a uicb function to go to the last tag directly (will probably be
used only by myself ^^)
2010-11-17 01:52:24 +01:00
Philippe Pepiot
b6c557a8ee Declare _POSIX_SOURCE for glib to define kill() 2010-11-17 01:30:35 +01:00
Philippe Pepiot
14f12edf25 Remove non ansi comments 2010-11-17 01:30:12 +01:00
Philippe Pepiot
3d6f8da805 Declare func_list const 2010-11-17 01:24:57 +01:00
Philippe Pepiot
40b4662ff8 Merge branch 'bacardi55' 2010-11-17 00:53:56 +01:00
Raphael Khaiat
8d71b8c2a8 Reload wmfs with exact same argument as it has been launched instead of
just reloading the good wmfsrc (idea from ksh.)
2010-11-16 23:18:18 +01:00
Raphael Khaiat
31899139e4 Revert "Reload wmfs with exact same argument as it has been launched instead of"
This reverts commit 61a1e18a59.
2010-11-16 23:13:47 +01:00
Raphael Khaiat
61a1e18a59 Reload wmfs with exact same argument as it has been launched instead of
just reloading the good wmfsrc (idea from ksh.)
2010-11-16 23:01:18 +01:00
Philippe Pepiot
3d3dbf589f BuildSystem: s/IMLIB2/IMLIB :> (thx to Erus) 2010-11-16 21:28:51 +01:00
Philippe Pepiot
6912599c72 BuildSystem: fix configure erase {C|LD}FLAGS 2010-11-16 19:15:39 +01:00
Philippe Pepiot
1294d7e35c BuildSystem: remove Makefile 2010-11-16 13:15:06 +01:00
Philippe Pepiot
6bd0175db0 BuildSystem: complete rewrite
Should compile properly on Linux, FreeBSD, OpenBSD and NetBSD
2010-11-16 13:09:40 +01:00
Raphael Khaiat
2d9baf78c5 Starting wmfs with an alternate wmfs was possible with wmfs -C
otherWmfsrc but only $HOME/.config/wmfsrc was read when reloading wmfs.
Now, if you start wmfs with -C and a different file, this file will be
reloaded.
2010-11-16 01:09:35 +01:00
Raphael Khaiat
b7ded56ef9 Merge branch 'master' into bacardi55 2010-11-15 20:54:17 +01:00
Raphael Khaiat
7f96a338c6 Merge branch 'master' of git://github.com/xorg62/wmfs 2010-11-15 20:53:59 +01:00
Philippe Pepiot
bfc56f8c37 BuildSystem: default {C|LD}FLAGS for OpenBSD 2010-11-14 19:32:12 +01:00
Philippe Pepiot
d8e2d54d8e BuildSystem: fix install target on OpenBSD 2010-11-14 19:23:41 +01:00
Philippe Pepiot
7096101651 Update README 2010-11-14 15:29:08 +01:00
Philippe Pepiot
103c86db03 BuildSystem: small stuffs
move VERSION to common.mk
Remove obscure {C|LD}_FLAGS
OPTIONS with optional libs and LIBS = ${REQUIRED} ${OPTIONS}
2010-11-14 15:19:36 +01:00
Philippe Pepiot
01bd4cc265 BuildSystem: set HAVE_IMLIB instead of HAVE_IMLIB 2010-11-12 18:14:31 +01:00
Philippe Pepiot
f6ad74273c BuildSystem: fix empty LD_FLAGS cause empty real arg 2010-11-11 22:36:42 +01:00
Philippe Pepiot
c3cf9d64b3 BuildSystem: CFLAGS and LDFLAGS can be customised through command line 2010-11-11 19:27:09 +01:00
Philippe Pepiot
26dde34d5c BuildSystem: create xsession directory 2010-11-11 18:51:25 +01:00
Philippe Pepiot
9ff9c81441 BuildSystem: change default MANPREFIX 2010-11-11 18:42:32 +01:00
Philippe Pepiot
66d1b9b2fb BuildSystem: install wmfsrc in XDG_CONFIG_DIR 2010-11-11 17:19:28 +01:00
Philippe Pepiot
6ac65840c0 BuildSystem: pkg-config optional 2010-11-11 17:13:34 +01:00
Philippe Pepiot
7c9e560236 BuildSystem: Improve detection of optionals libs 2010-11-11 16:33:24 +01:00
Philippe Pepiot
5a05594092 BuildSystem: add BSDMakefile 2010-11-11 16:14:26 +01:00
Philippe Pepiot
eb567d9936 BuildSystem: fix stuff on install 2010-11-09 20:07:29 +01:00
David Delassus
b055908080 Add out-of-tree building (make O=/path -C /path/to/wmfs) 2010-11-09 20:04:19 +01:00
Philippe Pepiot
2614c61657 build: all .o and wmfs depend on config.mk 2010-11-09 19:24:22 +01:00
Philippe Pepiot
52e53c7415 Remove another CMakelist.txt 2010-11-09 18:28:39 +01:00
Philippe Pepiot
e01bb5c3b0 Re use doxygen file (in fact still used /o\) 2010-11-09 18:22:02 +01:00
Philippe Pepiot
a1de32cac7 wmfsrc: Made change announced in f3c0f5492a 2010-11-09 12:36:13 +01:00
Philippe Pepiot
57f8768228 Merge branch 'master' of git.philpep.org:wmfs into nocmake 2010-11-09 12:33:45 +01:00
Philippe Pepiot
f3c0f5492a Parser: fix unused variable 2010-11-09 12:32:48 +01:00
Philippe Pepiot
7db51713e5 Build System: remove cmake
Cmake is bloat and wmfs doesn't need a complex build system
So now wmfs compile with a Makefile using gmake and pkg-config
compilation options can be customised through confix.mk (dwm like)

Remove doxygen config files (wmfs code doesn't use it, and nobody use
doxygen with wmfs)
Replace wmfsrc.in by wmfsrc (change @WMFS_TERM@ and use shell choice
urxvt || xterm || ...)
Remove generation of Changelog file (we can git log > Changelog before
creating a dist package)
Remove README from install process (this file don't need to be included in dist
package)

What's next before merging into master ?
- provide a BSD Makefile
- discuss if we use or not pkg-config (we can document common places
  to include directory and libs in config.mk)
- compile out of tree
2010-11-09 12:15:11 +01:00
Raphael Khaiat
20756b30cd Merge remote branch 'origin/master' into bacardi55 2010-11-01 18:43:10 +01:00
Raphael Khaiat
d242ab880a Merge branch 'bacardi55' 2010-11-01 18:42:40 +01:00
Philippe Pepiot
658e26bd49 parse: detect empty file + fix memleak 2010-10-30 23:16:44 +02:00
Philippe Pepiot
464f06c5c1 parse: typo 2010-10-30 23:11:10 +02:00
Martin Duquesnoy
a0e5ddc45a Ewmh: Apply lukasg's patch for fullscreen flag (Bug #48 fixed, thanks to lukasg) 2010-10-25 13:06:48 +02:00
Martin Duquesnoy
2a9d024784 Config/Infobar: Add occupied_fg option (Requested by s__C) 2010-10-23 16:36:07 +02:00
Martin Duquesnoy
6b788edc38 Tag: Disable prevseltag saving when switching tag to the current tag (bug #57 by Erus) 2010-10-11 20:56:42 +02:00
Raphael Khaiat
8f8d47dc23 Merge branches 'master' and 'bacardi55' into bacardi55 2010-09-19 12:29:03 +02:00
Philippe Pepiot
3a021bf026 Parse: fix segfault 2010-09-05 22:08:38 +02:00
Raphael Khaiat
1ec6d90c1e Merge branch 'master' into bacardi55 2010-09-05 15:13:49 +02:00
Philippe Pepiot
b91db6b431 Parser: free keywords list and free files 2010-08-31 01:55:42 +02:00
Philippe Pepiot
c6469260de Cmake: put default config in XDGCONFDIR 2010-08-31 00:59:35 +02:00
Philippe Pepiot
5aeeae4198 Parse: when syntax error, fallback to default config, fixes #45 2010-08-31 00:55:51 +02:00
Philippe Pepiot
3841e55f82 Parser: Use defined Bool or create one 2010-08-30 19:50:38 +02:00
Philippe Pepiot
4a3952f54f Parser: errors on calloc fail or buffer overflow 2010-08-30 19:37:04 +02:00
Philippe Pepiot
8816bd6753 Spawn: check write() 2010-08-28 23:47:47 +02:00
Philippe Pepiot
3366ec835f Parser and launcher: check asprintf return 2010-08-28 23:44:49 +02:00
Radek Tříška
839ebeaf2b Launcher: autocompletion alphabetical sort from PeVe 2010-08-28 23:26:35 +02:00
Philippe Pepiot
36aa4ce43a Parser: when @include path can be prefixed by "~" or be relative to
parent file directory. refs #21
2010-08-28 21:26:42 +02:00
Philippe Pepiot
4f1742eef9 Parser: recode / independant from wmfs code / @include works, closes #21 2010-08-28 20:40:54 +02:00
Philippe Pepiot
fd9cedd695 Parser: simplification, don't abuse of macros (work in progress) 2010-08-27 03:06:30 +02:00
Tomáš Chvátal
3644bc736b Fix typo in wmfsrc pathspec. 2010-08-23 07:04:51 +02:00
Tomáš Chvátal
1eeb5e167e Fixup one more source/binary dir missmatch 2010-08-23 07:04:46 +02:00
Tomáš Chvátal
a1d134a1b7 Drop duped file. 2010-08-21 20:40:42 +02:00
Tomáš Chvátal
52bfa713df Fix username settings in conf.h 2010-08-21 20:40:23 +02:00
Martin Duquesnoy
3b60e23f9f Remove warning 2010-08-21 20:30:03 +02:00
Tomáš Chvátal
59d9dcdc93 Fixup xinerama define. 2010-08-21 20:29:37 +02:00
Tomáš Chvátal
9055a55d58 Use cmake properly, basically complete cmake build system rewrite.
Signed-off-by: Tomáš Chvátal <scarabeus@gentoo.org>
2010-08-21 15:32:26 +02:00
Martin Duquesnoy
e254f76211 Revert "CMake: Add scarabeus patch (rewrite of CMakeLists.h), fix warning"
This reverts commit e6db51d8fd.
2010-08-21 13:42:30 +02:00
Martin Duquesnoy
e6db51d8fd CMake: Add scarabeus patch (rewrite of CMakeLists.h), fix warning 2010-08-21 13:38:25 +02:00
Martin Duquesnoy
ce4575ee04 Event: Focus client before click on titlebar buttons 2010-08-20 06:19:19 +02:00
Martin Duquesnoy
e9b409b564 Config: Put example in default conf 2010-08-18 23:45:12 +02:00
Martin Duquesnoy
578b62ec09 Update version 2010-08-18 23:43:20 +02:00
Martin Duquesnoy
4f42436098 Config: Apply second patch of mseed/PeVe about conf split: Can comment @include line in conf. 2010-08-18 23:42:31 +02:00
Martin Duquesnoy
dce3b8eb3c Client: Fix screen setting in client_set_attributes 2010-08-18 21:32:39 +02:00
Martin Duquesnoy
ce8238fb20 Client: Fix mistake in function name 2010-08-18 21:29:48 +02:00
Martin Duquesnoy
e9ffab7d62 Client: Fix client_get_prev/next not working when screen switching with mouse 2010-08-18 19:41:47 +02:00
Martin Duquesnoy
cf565c9b57 Config: Apply mseed/PeVe great patch: Add conf split with @include "file". Thanks to Czech WMFS dev team :) 2010-08-18 13:36:55 +02:00
Martin Duquesnoy
179c94f26f Menu: Apply PeVe/mseed path: Menu optimisation/improvment and some fixation 2010-08-13 03:11:44 +02:00
Martin Duquesnoy
5017c4ced5 Config: Apply PeVe/mseed patch: layout_button_width option in [layouts] section. Thanks to them. 2010-08-12 21:58:28 +02:00
Martin Duquesnoy
7b0113ab6e Config: Fix mistaken option 2010-08-12 20:23:09 +02:00
Martin Duquesnoy
dc2e571e5e Config: Fix UGLY mistake (lenght -> length, thanks chacha) 2010-08-12 19:57:00 +02:00
Martin Duquesnoy
5d9ad3e1db Client: Fix mistake 2010-08-10 14:22:03 +02:00
Martin Duquesnoy
695cf69790 Client: Fixed wm_window_role condition in rules function 2010-08-10 14:21:17 +02:00
Martin Duquesnoy
86b20ba799 Client: Fix role usage in rule section 2010-08-10 10:45:01 +02:00
Martin Duquesnoy
ec2c2f6337 Client: Fixes details in client_set_rule 2010-08-10 03:38:53 +02:00
Martin Duquesnoy
5d7f4a2382 Config: Add WM_WINDOW_ROLE match in rule section 2010-08-10 03:22:22 +02:00
Martin Duquesnoy
d8d09f9e1a Struct: Fix mistake in Alias struct 2010-08-10 02:47:14 +02:00
Martin Duquesnoy
a496d77f9e Conf: Add [rules] section. (Feature #34 requested by markand CHACHA) clients option, autofree and automax option are DEPRECATED but works for some revision. 2010-08-10 02:40:06 +02:00
Martin Duquesnoy
7a1bfb48f5 Menu: Set clientlist menu alignement to left for better visibility 2010-08-10 01:37:37 +02:00
Martin Duquesnoy
3e71c420d6 Client: Add "all" cmd option to clientlist uicb function to display all client in menu instead only in current tag 2010-08-10 01:31:23 +02:00
Raphael Khaiat
0eab6d1a92 Merge branch 'master' into bacardi55 2010-08-07 14:44:44 +02:00
Martin Duquesnoy
c63a9af492 Layout: Remove layer layout (was for testing) 2010-08-05 16:06:39 +02:00
Martin Duquesnoy
0c38afdb35 Frame: Fix buttons flags with max and layout max 2010-08-05 14:45:21 +02:00
Martin Duquesnoy
19f9a35685 Menu: Improve submenu behaviour (Thanks to peve and mseed) 2010-08-03 20:33:40 +02:00
Raphael Khaiat
ed390279f5 Merge branch 'master' into bacardi55 2010-08-03 08:20:13 +02:00
Martin Duquesnoy
6d99de883c Layout: Fix toggle maximization in free layout 2010-08-03 02:03:01 +02:00
Raphael Khaiat
7abc282d21 Merge branch 'master' into bacardi55 2010-08-03 00:08:52 +02:00
Martin Duquesnoy
ed254ea417 Event: Fix configure event in tiling mode. 2010-08-02 22:10:02 +02:00
Martin Duquesnoy
f2e9c1fd02 Util: Remove debug printf 2010-08-02 19:20:53 +02:00
Martin Duquesnoy
36ca03f8f3 Util: Add patht function to transform path: '~/' is now allowed 2010-08-02 19:20:06 +02:00
Martin Duquesnoy
00638264d3 Frame: Fix buttons flags with free and layout free 2010-08-02 18:56:49 +02:00
Martin Duquesnoy
6a420e2934 Systray: Reparent systray window to infobar 2010-08-02 17:32:16 +02:00
Martin Duquesnoy
132f7d1da4 Client: Add focusontag option in Client structure to save focused client on every tag 2010-08-02 17:26:43 +02:00
Martin Duquesnoy
4a1ab8ef79 Client/Tag: Fix focus problems with tag_transfert 2010-08-02 16:27:30 +02:00
Martin Duquesnoy
61015e2567 Client: Fix possible flash-fullscreen problem 2010-08-02 16:12:33 +02:00
Martin Duquesnoy
5742ed4fca Client: Fix client swapping with additional tag 2010-08-02 15:45:31 +02:00
Martin Duquesnoy
872d9cb348 Event: Remove test in propertynotify handle 2010-07-31 14:30:45 +02:00
Martin Duquesnoy
2292ab97d1 Systray: Fix systray at reloading or for manage already running tray icon 2010-07-31 14:28:04 +02:00
Martin Duquesnoy
3b81cacaac Client: Fix arranging bug when closing client in additional tag condition 2010-07-26 19:38:23 +02:00
Martin Duquesnoy
0270a28181 Ewmh: Improve ewmh_send_message 2010-07-26 11:38:25 +02:00
Martin Duquesnoy
e6fc0a4976 Event: Remove send_client_message function 2010-07-26 11:32:26 +02:00
Martin Duquesnoy
374abb0e26 Update improvement 2010-07-26 11:20:20 +02:00
Martin Duquesnoy
1d5792b278 Conf: Move [systray] section in [bar] section 2010-07-23 14:49:57 +02:00
Martin Duquesnoy
461b45545a Conf/Systray: add [systray] section 2010-07-23 14:36:05 +02:00
Martin Duquesnoy
4cf2b8bf8f Status: Fix text drawing with systray shift 2010-07-23 12:31:08 +02:00
Martin Duquesnoy
cc10d56359 Systray/status: Adapt statuspos (with image/rectangle) with systray width 2010-07-23 04:15:33 +02:00
Martin Duquesnoy
1094861b49 Ewmh: Fix panels crash and type_dock management 2010-07-22 23:57:31 +02:00
Martin Duquesnoy
fdb1d2c748 Systray: Fix BadWindow (because of unmap event) and segfault at pressing button 2010-07-22 22:07:26 +02:00
Martin Duquesnoy
908978cca1 !! Implementation of System tray !! 2010-07-22 20:12:27 +02:00
Raphael Khaiat
b3325867ed Merge remote branch 'origin/master' into bacardi55 2010-07-21 23:04:49 +02:00
Martin Duquesnoy
d32ee3295e Systray: Prepare file 2010-07-21 22:52:18 +02:00
Martin Duquesnoy
910421c41c Layout: Fix screen test in arrange (reported by mseed) 2010-07-21 13:20:09 +02:00
Martin Duquesnoy
46d212297a Ewmh: Add _NET_WM_STATE_STICKY management 2010-07-17 03:32:47 +02:00
Martin Duquesnoy
bf9e9ca578 Improve _NET_WM_STATE part in ewmh_manage_window_type 2010-07-17 03:21:08 +02:00
Martin Duquesnoy
ce652d29e4 Fix _NET_WM_STATE_FULLSCREEN for flash apps or stuff like this 2010-07-17 03:09:55 +02:00
Raphael Khaiat
00e4e9975e Fix a bug that printed the tag previous count instead of the new one when using the tag_add with the name_count = true 2010-07-06 23:03:40 +02:00
Raphael Khaiat
aa04eab011 Delete struct default_tag by using tag structure for default_layout feature 2010-07-05 00:43:33 +02:00
Raphael Khaiat
afdda3b95a Add an option (selected_layout_symbol) in the wmfsrc -> [layouts] to change the star (*) that is used as default symbol for the selected symbol in the layout list in the infobar 2010-07-04 19:42:05 +02:00
Raphael Khaiat
2522b21ab3 Add default_tag section in the tags section of the wmfsrc. It allows
user to set all options of a new tag when they will use add a tag
dynamically. Feature #73 requested by bacardi55
2010-07-04 17:46:01 +02:00
Martin Duquesnoy
8aeded6cd6 Fix mistake in ewmh manage window type function 2010-06-30 13:23:20 +02:00
Raphael Khaiat
9a3b06c645 Wmfs coding norms :) 2010-06-30 13:13:08 +02:00
Raphael Khaiat
89b115e850 Fix bug #54 reported by bacardi55 2010-06-30 00:57:55 +02:00
Raphael Khaiat
e71f85ff26 Fix segfault when using client_ignore_tag. bug #72 reported by myself 2010-06-27 00:47:36 +02:00
Raphael Khaiat
253d50762b Add an option to choose the default layout that will be used when adding
a new tag dynamically. Feature #71 requested by myself ^^
2010-06-26 00:26:16 +02:00
Raphael Khaiat
e17f36f24f Change declaration place for uniformity 2010-06-25 14:02:14 +02:00
Raphael Khaiat
6d720d9848 Remove useless lines, thanks to xorg62 :-) 2010-06-25 13:55:08 +02:00
Raphael Khaiat
414273fff9 Prevent user the resize client while using tile_grid vertically or
horizontally.
2010-06-25 13:52:04 +02:00
Raphael Khaiat
cee16d6f7f Add a tile_grid_vertical layout that split vertically unlike the tile_grid
layout that split horizontally. Add tile_grid_horizontal too that is the
same as tile_grid. You should use the tile_grid_horizontal, tile_grid is
kept for backward compatibility
2010-06-25 01:40:53 +02:00
Raphael Khaiat
fb0ddc6b73 When name_count is true, put the count in the tag name
after using wmfs -c tag_new
2010-06-22 01:11:11 +02:00
Raphael Khaiat
8062f4a42a Correcting bug reported by xorg62 while using the command line
wmfs -c tag_new
2010-06-22 00:59:06 +02:00
Raphael Khaiat
c6f0204901 Add a default name option (default_name) to change "new tag" when you
add a tag by a keybind.
Add an option (name_count) to put the number of the tag as a
default name.
2010-06-21 23:58:08 +02:00
Martin Duquesnoy
a90f4ee7ce Client: Fix bug #70 (reported by bacardi55) 2010-06-21 16:06:14 +02:00
Martin Duquesnoy
fb97d95787 Event: Improve grabkeys() 2010-06-10 16:39:48 +02:00
Martin Duquesnoy
6e05fd498d Conf/Layout/Client: Add option keep_layout_geo (requested by Armael) 2010-06-10 15:41:53 +02:00
Martin Duquesnoy
f683022678 Client: Code typo.. 2010-06-09 19:26:19 +02:00
Martin Duquesnoy
32b3120fbd Client/conf: Add automax option (same that autofree but for maximization) (Feature #62 requested by bacardi55) 2010-06-09 19:24:48 +02:00
Martin Duquesnoy
470606af1b Client: Fix possible segfault when there is no autofree option (shame on me :o) 2010-06-06 23:40:55 +02:00
Martin Duquesnoy
12fc01b824 Client: add autofree option in client section (Feature #9 requested by lidstah (and tamtam)) See default wmfsrc 2010-06-06 23:34:11 +02:00
Martin Duquesnoy
9067f3cb66 Client: Add focus traveling with uicb function: client_focus_{right, left, top, bottom} (Feature #45 requested by biiter) [NEED TEST] 2010-06-06 22:48:25 +02:00
Martin Duquesnoy
2040385af6 Tag: Add tag_rename uicb function (Feature #55 requested by bacardi55) 2010-06-05 23:36:49 +02:00
Martin Duquesnoy
510cb29e9f Launcher: Fix launchers position when layout placement is left (Bug #53 signaled by Armael) 2010-06-05 23:26:33 +02:00
Martin Duquesnoy
32686569c4 Merge version (201005 will never exist, mouahahahaha!!) 2010-06-05 23:01:29 +02:00
Martin Duquesnoy
faab6d946e Client: Remove urgent when unmanaging a client without focus it 2010-06-05 22:59:43 +02:00
Martin Duquesnoy
d49ebaa57e Ewmh: Fix closing of splash windows (Bug #60 signaled by nythain) 2010-06-05 22:39:39 +02:00
Philippe Pepiot
5d1aaa1363 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-05-09 03:03:51 +02:00
Philippe Pepiot
5dd811b91e Parse: fix possible segfaults. Add syntax() for syntax errors 2010-05-09 03:03:03 +02:00
Martin Duquesnoy
a0a53f3af2 Infobar: Improve selbar check if there is no sel (in current screen) 2010-05-08 21:41:53 +02:00
Martin Duquesnoy
6ecc58bdb1 Client: Remove free in client_get_name 2010-05-08 19:26:55 +02:00
Martin Duquesnoy
c524326714 Client: Remove comment lines in client_moveresize 2010-05-07 18:54:48 +02:00
Martin Duquesnoy
c886edb19d Client: Map client after almost all in client_manage 2010-05-07 18:53:43 +02:00
Martin Duquesnoy
995c4e94e7 Client: Add padding option in client to set space between tiled client (Feature #52 requested by Armael) 2010-04-25 17:20:24 +02:00
Martin Duquesnoy
d3207be191 Finally fix wmfs.desktop 2010-04-24 14:06:34 +02:00
Martin Duquesnoy
1cc8506610 wmfs.desktop: Remove TryExec line 2010-04-24 13:54:44 +02:00
Martin Duquesnoy
4b692b7a0f wmfs.desktop: Fix bug with Gdm? (Bug #48 signaled by add1ktive, fixed by arpinux) 2010-04-24 13:49:59 +02:00
OldMan
6d1bd844f7 Tag: add uicb functions: tag_next_visible & tag_prev_visible. 2010-04-23 16:36:11 +06:00
OldMan
1d9bb77d83 Tag: When adding a new tag, it is selected. Otherwise, if autohide is enabled, the new tag is not visible. 2010-04-23 13:36:34 +06:00
OldMan
d24e5e911f Tag: Fix: if delete last tag, then none tag selected. 2010-04-23 12:56:02 +06:00
Martin Duquesnoy
07db3fafbd Menu: Fix item height 2010-04-22 17:56:35 +02:00
Martin Duquesnoy
d38e7598a4 Client: uicb_client_select warp pointer on the client to avoid Bug #51 signaled by bacardi55 2010-04-22 17:40:55 +02:00
Martin Duquesnoy
add85a7509 Infobar: Fix toggle_autohide with whole infobar replacement 2010-04-20 18:27:49 +02:00
Martin Duquesnoy
f9157a4dda Merge branch 'oldman' of github.com:xorg62/wmfs 2010-04-20 18:11:09 +02:00
Martin Duquesnoy
f8115d686d Tag/Clients: Add client_ignore tag option (~Feature #6 requested by Elpinoutoufou) 2010-04-20 18:10:42 +02:00
OldMan
236b86ff0a Infobar: Add toggle_tagautohide uicb function. 2010-04-20 20:11:59 +06:00
Philippe Pepiot
46608a14be Fix possible use of unitialized variables 2010-04-20 14:25:57 +02:00
Philippe Pepiot
0e8ffff152 Kill status script in quit() 2010-04-20 03:43:28 +02:00
Philippe Pepiot
52dba6418e fix posible issue with statusbar when reloading wmfs
spawn() now return the child pid
2010-04-20 03:32:22 +02:00
Philippe Pepiot
e6b26eafc2 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-20 00:37:47 +02:00
Philippe Pepiot
a635e7c2d6 Parse: fix possible issue in fetch_section_first() 2010-04-20 00:13:39 +02:00
Philippe Pepiot
5271222e38 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-19 23:06:18 +02:00
Martin Duquesnoy
7119d3cc25 Tag: Improve and fix some bugs in tag_delete 2010-04-19 22:32:41 +02:00
Philippe Pepiot
c81312feff Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-19 18:24:25 +02:00
Martin Duquesnoy
fe22703fea Merge branch 'oldman' of github.com:xorg62/wmfs 2010-04-19 16:16:55 +02:00
Philippe Pepiot
2da44ff4d8 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-19 13:59:23 +02:00
Martin Duquesnoy
892b705f95 Tag: Fix 2nd segfault -> tag_new 2010-04-19 01:34:23 +02:00
Martin Duquesnoy
feadae05c8 Tag: Fix segfault in tag_del (Bug #50 signaled by addikt1ve) 2010-04-19 01:29:09 +02:00
Philippe Pepiot
ba841c74b3 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-18 23:38:08 +02:00
Martin Duquesnoy
129a21bada Tag: add tag_new and tag_del function *Dynamic taggin* 2010-04-18 22:25:26 +02:00
Philippe Pepiot
dd3d490c39 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-18 20:24:49 +02:00
Martin Duquesnoy
f8a3cc0e0e Merge branch 'philpep' of git.wmfs.info:wmfs 2010-04-18 19:44:41 +02:00
Martin Duquesnoy
de672fc7ad Tag: Fix tag swapping when there clients in both 2010-04-18 19:20:09 +02:00
Philippe Pepiot
06d014722f Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-18 19:12:27 +02:00
Martin Duquesnoy
5ccc31f7ec Tag: Fix tag_swap() with clients 2010-04-18 19:02:13 +02:00
Philippe Pepiot
37d6d105d8 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-18 19:00:23 +02:00
Martin Duquesnoy
3e2d4a6a01 Tag: Fix test in tag_swap() 2010-04-18 18:58:57 +02:00
Philippe Pepiot
eb16ebfb7f Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-18 18:53:19 +02:00
Philippe Pepiot
d0d62c798b Build System: permit user to change CFLAGS 2010-04-18 18:51:54 +02:00
Martin Duquesnoy
0f25f75f0d Tag: Add tag_swap and uicb function: tag_swap with cmd = <tag>, tag_swap_next & tag_swap_prev 2010-04-18 18:50:08 +02:00
Martin Duquesnoy
8c0e37cb38 Infobar: Add autohide option in [tags]: Hide empty tags in tag list (Feature #24 requested by Erus) 2010-04-18 17:38:12 +02:00
Martin Duquesnoy
3811d61858 Parser: Fix fetch_section_first when the section doesn't exist 2010-04-17 14:24:08 +02:00
OldMan
84f6aa31d0 Add bar future to draw graph with 'wmfs -s \g[x;y;w;h;#color;data]\' 2010-04-17 15:31:04 +06:00
Martin Duquesnoy
5875af2949 Selbar: Put ... only when sel->title lenght > max_lenght 2010-04-16 19:41:02 +02:00
Martin Duquesnoy
49b9a08fab Selbar/Conf: Add max_lenght option to cut title lenght (requested by Erus) 2010-04-16 19:31:33 +02:00
Philippe Pepiot
c7824780fa Fix wait for sleep() when exit 2010-04-15 20:37:34 +02:00
Philippe Pepiot
b472a08490 If conf.status_timing is 0 launch one time 2010-04-15 19:31:04 +02:00
Martin Duquesnoy
55e74cd849 Selbar: Unmap selbar if there is no selected client 2010-04-15 17:59:32 +02:00
Martin Duquesnoy
8e3e10f041 Client: Improve clientlist 2010-04-15 13:49:31 +02:00
Martin Duquesnoy
d5e1f1da78 Conf: Set bar color as default selbar color 2010-04-15 13:19:41 +02:00
Philippe Pepiot
aca9e78491 Parse: better converting function in string_to_opt 2010-04-15 02:22:44 +02:00
Philippe Pepiot
18b702c112 Parse: return sections in real order 2010-04-15 01:57:35 +02:00
Philippe Pepiot
7f7bbd1f09 Parse: add comment and make some code cosmetics 2010-04-15 01:30:23 +02:00
Philippe Pepiot
d6c2902d77 config.c: mouse section size is useless here 2010-04-15 01:13:40 +02:00
Philippe Pepiot
c8bb465bb0 Fix possible segfault when no [selbar] in config 2010-04-15 01:09:22 +02:00
Philippe Pepiot
891760bfac Missing param when merging 2010-04-14 21:17:54 +02:00
Philippe Pepiot
657dc33d63 Merge branch 'oldman' of git://github.com/xorg62/wmfs
Conflicts:
	src/config.c
2010-04-14 21:15:56 +02:00
OldMan
5363a7a8a9 Menu as Clientlist 2010-04-14 19:59:53 +06:00
Philippe Pepiot
3274e3f4ad config: fix wrong keybind order 2010-04-14 14:42:18 +02:00
Martin Duquesnoy
fb905b55c5 Tag: Fix tag_transfert bug if tag > conf.ntag[screen] 2010-04-14 01:45:33 +02:00
Philippe Pepiot
41bf8e2052 [parse] add free_conf() 2010-04-14 01:18:45 +02:00
Philippe Pepiot
5c5e137fdd [parse] print warning when option is unused 2010-04-14 00:49:09 +02:00
Philippe Pepiot
9f7f4c40e4 Fix segfault when fetch_opt on a NULL section 2010-04-13 22:48:50 +02:00
Philippe Pepiot
8975e04777 Fix layout menu in reverse order 2010-04-13 22:39:21 +02:00
Philippe Pepiot
d37dc481a1 New fonctions in parser
fetch_(opt|section)_first -> return the first (section|opt) found
fetch_(opt|section)_count -> return the size of (section|opt)
2010-04-13 22:05:01 +02:00
Philippe Pepiot
77d95275f0 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-13 21:03:06 +02:00
Martin Duquesnoy
81e6a63c1f Conf: Fix multi mouse section of multi button section 2010-04-13 21:01:25 +02:00
Philippe Pepiot
0d9f8d887d Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-13 20:51:01 +02:00
Martin Duquesnoy
9a38a64ced Conf: Fix multi mouse section of titlebar 2010-04-13 20:49:42 +02:00
Martin Duquesnoy
b4705bbaa7 Conf: Fix button section bug 2010-04-13 20:41:41 +02:00
Martin Duquesnoy
005f06c15e Merge branch 'philpep' of git.wmfs.info:wmfs 2010-04-13 20:08:25 +02:00
Philippe Pepiot
761afe51a0 Merge branch 'master' of git.philpep.org:wmfs into philpep 2010-04-13 19:58:58 +02:00
Philippe Pepiot
9b33623d33 New parser in use.
Warning : be prudent :)
2010-04-13 19:57:02 +02:00
OldMan
6f2d6385ac Merge branch 'oldman' into sb-sec 2010-04-13 18:31:21 +06:00
OldMan
a713e34b87 Merge branch 'master' into sb-sec 2010-04-13 18:31:14 +06:00
OldMan
db90cf65c9 Merge branch 'sb-sec' into oldman 2010-04-13 10:21:24 +06:00
OldMan
1ddc714196 Conf: section 'selbar' in section 'bar' 2010-04-13 10:15:40 +06:00
Philippe Pepiot
611a5fc38d New parser (not yet in use) 2010-04-13 01:43:12 +02:00
Martin Duquesnoy
b0b74b46eb Code cosmetic.. 2010-04-12 18:33:32 +02:00
Philippe Pepiot
b31d54b7e6 Abusive use of _strdup in confparse/util.c
String was also strdup into erase_(delim|sec)_content
2010-04-11 23:37:17 +02:00
Martin Duquesnoy
7908d3075c Merge branch 'philpep' of git.wmfs.info:wmfs 2010-04-11 20:19:00 +02:00
Philippe Pepiot
cf652aab50 Fix memleak in confparse.c 2010-04-11 17:54:33 +02:00
Philippe Pepiot
914b9f11c9 Fix abusive use of _strdup() in get_nsec 2010-04-11 17:36:45 +02:00
OldMan
dcb48cc2c5 Merge branch 'misc' into oldman 2010-04-11 16:59:00 +06:00
OldMan
9c693212bb Misc: client_round option 2010-04-11 16:57:07 +06:00
OldMan
d525e3ace1 Misc: focus_pointer_click option 2010-04-11 16:15:29 +06:00
OldMan
0bed70e52c InfoBar: taglist optimization 2010-04-11 12:47:58 +06:00
Martin Duquesnoy
61858bbe64 Config: Fix possible segfault with layout system switch 2010-04-10 23:41:27 +02:00
Philippe Pepiot
f6486d803c Fix possible segfault when parsing options 2010-04-10 18:38:21 +02:00
OldMan
8b16176edc Menu.submenu: fix segfault bug (thanks Martin for debug). 2010-04-10 19:54:03 +06:00
OldMan
4138894db1 Menuitem option 'submenu'. Draw bullet '>' on the right. 2010-04-10 18:53:30 +06:00
Martin Duquesnoy
8a45d219bd Update README 2010-04-10 13:55:26 +02:00
Martin Duquesnoy
b4c326ebaf Menu: Fix screen limits (bug with multi-head) 2010-04-10 13:48:12 +02:00
OldMan
c5c307deea Menuitem option 'check'. Draw bullet '*' on the left (ugly, but simple). 2010-04-10 17:16:24 +06:00
OldMan
590acffb62 Bugfix: Menu get out of the screen view area. Feature: New menu option 'align'. 2010-04-10 16:46:32 +06:00
OldMan
a0258c13d0 Menu: Little optimization 2010-04-10 11:33:21 +06:00
Martin Duquesnoy
466ebca9ea EWMH: Fix focus on _NET_WM_STATE_FULLSCREEN (Bug #42 signaled by tamtam) 2010-04-08 13:20:51 +02:00
Martin Duquesnoy
fbb36877dc EWMH: Improve _NET_WM_STATE_FULLSCREEN management 2010-04-08 12:33:52 +02:00
Martin Duquesnoy
ffaa243644 Conf: Improve default wmfsrc and set new version 2010-04-07 01:34:03 +02:00
Martin Duquesnoy
87a41561e7 Tag: Fix layout update in case of additional tag in tag_set 2010-04-07 00:57:39 +02:00
Martin Duquesnoy
5c439c245c Tag: Add multitag support (Feature #38 requested by Chacha^Wmarkand): button 3 click on tag to add it. (tagtransfert is now button 2 by default) 2010-04-07 00:33:00 +02:00
Martin Duquesnoy
e920b99951 Launcher: Add Control-p/n to manage historic (vim-like) requested by Bram 2010-04-06 21:15:56 +02:00
Martin Duquesnoy
22b405cba8 Launcher: Add historic for launcher (Feature #8 requested by bacardi55) 2010-04-06 21:06:21 +02:00
Martin Duquesnoy
6f82c73409 Tag: Add uicb_tag_urgent to go to urgent tag (Feature #37 request bien Erus) 2010-04-06 01:33:18 +02:00
Martin Duquesnoy
b38db34de5 Client: Fix possible bug in removing focus when client wanted tag is set 2010-04-05 16:41:28 +02:00
Martin Duquesnoy
8c24370a9f Conf: Reverse allowing border height of client to 0 2010-04-05 15:10:08 +02:00
Martin Duquesnoy
fb8daed2b5 Layout: Fix free geometry of client 2010-04-04 20:04:54 +02:00
Martin Duquesnoy
ee13255297 Client/Event/Tag: Fix XUrgencyHint support 2010-04-04 15:42:51 +02:00
Martin Duquesnoy
9c154fd0f3 Client/Event/Tag: Add XUrgencyHint support (colorize tag where there is an urgent client) 2010-04-04 15:13:02 +02:00
Martin Duquesnoy
b5dd942fd1 Conf: Allow border height of client to 0 (Feature #34 requested by addikt1ve) 2010-04-03 23:10:25 +02:00
45 changed files with 7114 additions and 3733 deletions

16
.gitignore vendored
View File

@@ -1,17 +1,11 @@
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
cmake_uninstall.cmake
Makefile
*.o *.o
.*.sw? .*.sw?
wmfs wmfs
src/config.h
changelog
config.h
#* #*
\#* \#*
wmfs.1.gz
tags
*.patch
*.diff
Makefile
build/ build/
doc/
wmfs.doxygen
wmfsrc

View File

@@ -1,274 +1,134 @@
# -*- mode: cmake -*- #
#Cmakelists.txt # CMake for wmfs David Demelier <markand@malikania.fr>
# Minimum version of CMake #
cmake_minimum_required(VERSION 2.6)
if(COMMAND cmake_policy)
cmake_policy(VERSION 2.6)
endif()
CONFIGURE_FILE( # General settings
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" cmake_minimum_required(VERSION 2.8)
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" project(wmfs)
IMMEDIATE @ONLY)
ADD_CUSTOM_TARGET(uninstall set(CMAKE_C_FLAGS_RELEASE "-Wall")
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") set(CMAKE_C_FLAGS_DEBUG "-Wall -g -ansi -pendantic -O3 -funroll-loops")
# Source and build dirs # General option
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) option(WITH_XINERAMA "Build with X.Org xinerama support" ON)
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) 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)
# Project name - wmfs # WMFS Version and XDG directory
set(PROJECT_NAME wmfs) set(WMFS_VERSION "201106")
project(${PROJECT_NAME} C) if (NOT XDG_CONFIG_DIR)
set(XDG_CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/etc/wmfs")
endif ()
# Definition of the wmfs source # Man prefix
set(wmfs_src if (NOT MANPREFIX)
src/confparse/util.c set(MANPREFIX "${CMAKE_INSTALL_PREFIX}/share")
src/confparse/confparse.c endif ()
src/barwin.c
src/client.c
src/config.c
src/
src/draw.c
src/event.c
src/ewmh.c
src/frame.c
src/getinfo.c
src/infobar.c
src/init.c
src/launcher.c
src/layout.c
src/menu.c
src/mouse.c
src/screen.c
src/status.c
src/tag.c
src/util.c
src/viwmfs.c
src/wmfs.c)
# Set the executable from the wmfs_src
add_executable(wmfs ${wmfs_src})
# Set the version
set(VERSION "WMFS-201003")
# FLAGS
set(CFLAGS "-Wall -ansi")
set(CMAKE_C_FLAGS ${CFLAGS})
# Linker FLAGS
set(DEFAULT_LDFLAGS "-L /usr/local/lib -lpthread")
if(CMAKE_SYSTEM_NAME MATCHES NetBSD)
message("-- NetBSD system found - Using /usr/pkg/lib for linker")
set(LDFLAGS "${DEFAULT_LDFLAGS} -L /usr/pkg/lib")
else(CMAKE_SYSTEM_NAME MATCHES NetBSD)
set(LDFLAGS ${DEFAULT_LDFLAGS})
endif(CMAKE_SYSTEM_NAME MATCHES NetBSD)
set_target_properties(wmfs PROPERTIES LINK_FLAGS ${LDFLAGS})
# Includes dir for libs in build_dir
include_directories(
${BUILD_DIR}/src
)
# Package find
find_package(Freetype)
if(FREETYPE_FOUND)
include_directories(${FREETYPE_INCLUDE_DIRS})
else (FREETYPE_FOUND)
message(FATAL_ERROR "Could not find Freetype")
endif (FREETYPE_FOUND)
# Libraries are optional
find_package(X11) find_package(X11)
if(X11_FOUND) if (NOT X11_FOUND)
include_directories(${X11_INCLUDE_DIR}) message(FATAL_ERROR "You need x11 libraries to build wmfs")
else (X11_FOUND) else ()
message(FATAL_ERROR "Could not find X11") list(APPEND INCLUDES ${X11_INCLUDE_DIR})
endif (X11_FOUND) list(APPEND LIBRARIES ${X11_LIBRARIES})
endif ()
# Link Libraries # pthread is needed
set(LIBRARIES_TO_LINK set(CMAKE_THREAD_PREFER_PTHREAD)
${FREETYPE_LIBRARIES} find_package(Threads)
${X11_LIBRARIES}
Xft)
# Includes if (NOT CMAKE_USE_PTHREADS_INIT)
include(FindDoxygen) message(FATAL_ERROR "You need pthread libraries to build wmfs")
include(FindPkgConfig) else ()
list(APPEND LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif ()
# Use pkgconfig to get required libraries # The following are optional X11 libraries
pkg_check_modules(WMFS_REQUIRED REQUIRED if (X11_Xinerama_FOUND AND WITH_XINERAMA)
x11 list(APPEND INCLUDES ${X11_Xinerama_INCLUDE_PATH})
freetype2 list(APPEND LIBRARIES ${X11_Xinerama_LIB})
xft) list(APPEND DEFINES "HAVE_XINERAMA")
else ()
list(APPEND DISABLED "HAVE_XINERAMA")
endif ()
# Optional dependencies check 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 ()
# Check for xinerama if (X11_Xft_FOUND AND WITH_XFT)
pkg_check_modules(HAVE_XINERAMA xinerama) find_package(Freetype)
if(HAVE_XINERAMA_FOUND) if (FREETYPE_FOUND)
set(WMFS_HAVE_XINERAMA "#define HAVE_XINERAMA") list(APPEND INCLUDES ${FREETYPE_INCLUDE_DIRS}
set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xinerama) ${X11_Xft_INCLUDE_PATH})
else() list(APPEND LIBRARIES ${FREETYPE_LIBRARIES}
set(WMFS_HAVE_XINERAMA "") ${X11_Xft_LIB})
endif() list(APPEND DEFINES "HAVE_XFT")
else ()
list(APPEND DISABLED "HAVE_XFT")
endif ()
endif ()
# Check for xrandr if (WITH_IMLIB2)
pkg_check_modules(HAVE_XRANDR xrandr) find_package(PkgConfig)
if(HAVE_XRANDR_FOUND) if (PKG_CONFIG_FOUND)
set(WMFS_HAVE_XRANDR "#define HAVE_XRANDR") pkg_check_modules(IMLIB2 imlib2)
set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Xrandr) if (IMLIB2_FOUND)
else() list(APPEND INCLUDES ${IMLIB2_INCLUDE_DIRS})
set(WMFS_HAVE_XRANDR "") list(APPEND LIBRARIES ${IMLIB2_LIBRARIES})
endif() list(APPEND DEFINES "HAVE_IMLIB")
# Check for Imlib link_directories(${IMLIB2_LIBRARY_DIRS})
pkg_check_modules(HAVE_IMLIB imlib2) else ()
if(HAVE_IMLIB_FOUND) list(APPEND DISABLED "HAVE_IMLIB")
set(WMFS_HAVE_IMLIB "#define HAVE_IMLIB") endif ()
set(LIBRARIES_TO_LINK ${LIBRARIES_TO_LINK} Imlib2) else ()
else() list(APPEND DISABLED "HAVE_IMLIB")
set(WMFS_HAVE_IMLIB "") endif ()
endif() endif ()
target_link_libraries(wmfs ${LIBRARIES_TO_LINK}) # Enable the optional module to compilation
foreach (modname ${DEFINES})
add_definitions(-D${modname})
# Messages # Set a variable to print all enabled modules.
message("Project version: ${VERSION}") # Remove the HAVE_ from module names
message("Using these CFLAGS: ${CFLAGS}") string(SUBSTRING ${modname} 5 -1 upcase)
message("Using these LDFLAGS: ${LDFLAGS}") string(TOLOWER ${upcase} module)
message("Linking with theses libraries : ${LIBRARIES_TO_LINK}")
# Generating man page message("INFO: ${module} enabled")
find_program(GZIP_EXECUTABLE gzip) endforeach ()
if(NOT GZIP_EXECUTABLE)
message(STATUS "Looking for gzip -- not found")
message(STATUS "Could not generating man page")
else()
message(STATUS "Looking for gzip -- ${GZIP_EXECUTABLE}")
message(STATUS "Generating man page")
set(WMFS_MAN1_FILES ${BUILD_DIR}/wmfs.1.gz)
execute_process(
COMMAND ${GZIP_EXECUTABLE} -c wmfs.1
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_FILE ${WMFS_MAN1_FILES})
endif()
# Generating CHANGELOG # Show modules disabled
find_program(GIT_EXECUTABLE git) foreach (modname ${DISABLED})
if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE) string(SUBSTRING ${modname} 5 -1 upcase)
message(STATUS "Looking for git -- ${GIT_EXECUTABLE}") string(TOLOWER ${upcase} module)
message(STATUS "Git dir -- Generating changelog...")
set(PROJECT_CHANGELOG ${SOURCE_DIR}/changelog)
execute_process(
COMMAND ${GIT_EXECUTABLE} log
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_FILE ${PROJECT_CHANGELOG})
else()
message(STATUS "Looking for git -- not found")
message(STATUS "Could not generating changelog")
endif()
# sets message("INFO: ${module} disabled")
# {{{ Install path and configuration variables endforeach ()
if(DEFINED PREFIX)
set(PREFIX ${PREFIX} CACHE PATH "install prefix")
set(CMAKE_INSTALL_PREFIX ${PREFIX})
else()
set(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "install prefix")
endif()
#If a sysconfdir is specified, use it instead file(
#of the default configuration dir. GLOB
if(DEFINED SYSCONFDIR) SOURCES
set(SYSCONFDIR ${SYSCONFDIR} CACHE PATH "config directory") src/*.c
else() src/*.h
set(SYSCONFDIR /etc CACHE PATH "config directory") )
endif()
#If an XDG Config Dir is specificed, use it instead # Add definitions for the version and XDG
#of the default XDG configuration dir. add_definitions(-DWMFS_VERSION=\"${WMFS_VERSION}\")
if(DEFINED XDG_CONFIG_DIR) add_definitions(-DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\")
set(XDG_CONFIG_DIR ${XDG_CONFIG_SYS} CACHE PATH "xdg config directory")
else()
set(XDG_CONFIG_DIR ${SYSCONFDIR}/xdg CACHE PATH "xdg config directory")
endif()
# setting WMFS_XSESSION_PATH include_directories(${INCLUDES})
if(DEFINED WMFS_XSESSION_PATH) add_executable(wmfs ${SOURCES})
set(WMFS_XSESSION_PATH ${WMFS_XSESSION_PATH} CACHE PATH "wmfs xsessions directory") target_link_libraries(wmfs ${LIBRARIES})
else()
set(WMFS_XSESSION_PATH ${PREFIX}/share/xsessions CACHE PATH "wmfs xsessions directory")
endif()
if(DEFINED WMFS_MAN_PATH) # Install targets
set(WMFS_MAN_PATH ${WMFS_MAN_PATH} CACHE PATH "wmfs manpage directory") install(TARGETS wmfs DESTINATION bin/)
else() install(FILES wmfsrc DESTINATION ${XDG_CONFIG_DIR}/)
set(WMFS_MAN_PATH ${PREFIX}/share/man CACHE PATH "wmfs manpage directory") install(FILES wmfs.1 DESTINATION ${MANPREFIX}/man1/)
endif()
if(DOXYGEN_EXECUTABLE)
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} ${SOURCE_DIR}/wmfs.doxygen
WORKING_DIRECTORY ${BUILD_DIR})
endif()
find_program(URXVT_EXECUTABLE urxvt)
if(URXVT_EXECUTABLE)
set(WMFS_TERM urxvt)
else()
set(WMFS_TERM xterm)
endif()
# Remplace strings in configs
set(WMFS_VERSION ${VERSION})
set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR})
set(WMFS_COMPILE_BY $ENV{USER})
set(WMFS_COMPILE_FLAGS ${CFLAGS})
set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK})
set(WMFS_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_NAME})
set(WMFS_SOURCE_DIR ${SOURCE_DIR})
# Configure files
set(wmfs_configure_files
src/config.h.in
wmfs.doxygen.in
wmfsrc.in)
macro(a_configure_file file)
string(REGEX REPLACE ".in\$" "" outfile ${file})
message(STATUS "Configuring ${outfile}")
configure_file(${SOURCE_DIR}/${file}
${SOURCE_DIR}/${outfile}
ESCAPE_QUOTE
@ONLY)
endmacro()
foreach(file ${wmfs_configure_files})
a_configure_file(${file})
endforeach()
set(PROJECT_DATA_PATH share/${PROJECT_NAME})
set(PROJECT_TODO ${SOURCE_DIR}/TODO)
set(PROJECT_README ${SOURCE_DIR}/README)
set(PROJECT_DEFAULT_CONF ${SOURCE_DIR}/wmfsrc)
# installs
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
if(WMFS_MAN1_FILES)
install(FILES ${WMFS_MAN1_FILES} DESTINATION ${WMFS_MAN_PATH}/man1)
endif()
if(PROJECT_CHANGELOG)
install(FILES ${PROJECT_CHANGELOG} DESTINATION ${PROJECT_DATA_PATH})
endif()
install(FILES ${PROJECT_TODO} ${PROJECT_README}
${PROJECT_DEFAULT_CONF} DESTINATION ${PROJECT_DATA_PATH})
install(FILES ${PROJECT_DEFAULT_CONF} DESTINATION ${WMFS_SYSCONFDIR})
install(FILES "wmfs.desktop" DESTINATION ${WMFS_XSESSION_PATH})

38
README
View File

@@ -4,33 +4,37 @@ WMFS Window Manager.
A highly configurable and manageable tiling Window Manager created from scratch A highly configurable and manageable tiling Window Manager created from scratch
AUTHORS : AUTHOR :
Martin Duquesnoy <xorg62@gmail.com> - Martin Duquesnoy <xorg62@gmail.com>
LICENSE : BSD 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, see COPYING.
REQUIREMENT : REQUIREMENT :
- freetype2 - libx11
- libxft (optional)
\- freetype
- libxinerama (optional) - libxinerama (optional)
- libxrandr (optional) - libxrandr (optional)
- libxft - imlib2 (optional)
- libx11 - cmake>=2.8 (build system)
- CMake >= 2.6
OS : OS :
- GNU/Linux : Supported. - GNU/Linux : Supported.
- FreeBSD : Supported. - FreeBSD/OpenBSD/NetBSD : Supported.
INSTALL : INSTALL :
- mkdir build mkdir build/ && cd build/
- cd build cmake ..
- cmake ..
- make
- sudo make install
- sudo make uninstall # if you would to remove it.
If you have doxygen installed you can generate doxygen documentation via custom target 'make doc' in the build dir.
DISTROS : DISTROS :
- wmfs port for FreeBSD at x11-wm/wmfs - wmfs port for FreeBSD at x11-wm/wmfs
- wmfs is available with AUR in ArchLinux - wmfs is available with AUR in ArchLinux (wmfs or wmfs-git)

29
TODO
View File

@@ -1,5 +1,24 @@
· Add Doxygen comment <-> OK ,
· Mouse bindings in the config file dM
· Can change client position in the tile grid MMr
· Fix all the bug \o/ 4MMML .
· XCB ? 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

View File

@@ -1,21 +0,0 @@
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

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

@@ -39,26 +39,26 @@
* \param w BarWindow Width * \param w BarWindow Width
* \param h BarWindow Height * \param h BarWindow Height
* \param color BarWindow color * \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 * \return The BarWindow pointer
*/ */
BarWindow* BarWindow*
barwin_create(Window parent, barwin_create(Window parent,
int x, int x,
int y, int y,
uint w, int w,
uint h, int h,
uint bg, uint bg,
char *fg, char *fg,
Bool entermask, bool entermask,
Bool stipple, bool stipple,
Bool border) bool border)
{ {
XSetWindowAttributes at; XSetWindowAttributes at;
BarWindow *bw; BarWindow *bw;
/* Allocate memory */ /* Allocate memory */
bw = emalloc(1, sizeof(BarWindow)); bw = zcalloc(sizeof(*bw));
/* Barwin attributes */ /* Barwin attributes */
at.override_redirect = True; at.override_redirect = True;
@@ -67,6 +67,7 @@ barwin_create(Window parent,
|ButtonMask|MouseMask |ButtonMask|MouseMask
|ExposureMask|VisibilityChangeMask |ExposureMask|VisibilityChangeMask
|StructureNotifyMask|SubstructureRedirectMask; |StructureNotifyMask|SubstructureRedirectMask;
if(entermask) if(entermask)
at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask; at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask;
@@ -79,12 +80,14 @@ barwin_create(Window parent,
/* His border */ /* His border */
if(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);
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(bg), &at); CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, bg, &at);
CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, color_enlight(bg), &at); CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, bg, &at);
CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, SHADC, &at); CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, bg, &at);
CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, SHADC, &at); CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, bg, &at);
} }
/* Property */ /* Property */
@@ -94,9 +97,7 @@ barwin_create(Window parent,
bw->geo.height = h; bw->geo.height = h;
bw->bg = bg; bw->bg = bg;
bw->fg = fg; bw->fg = fg;
bw->border.light = color_enlight(bg); FLAGAPPLY(bw->flags, stipple, StippleFlag);
bw->border.dark = SHADC;
bw->stipple = stipple;
bw->stipple_color = -1; bw->stipple_color = -1;
return bw; return bw;
@@ -107,21 +108,38 @@ barwin_create(Window parent,
void void
barwin_draw_text(BarWindow *bw, int x, int y, char *text) barwin_draw_text(BarWindow *bw, int x, int y, char *text)
{ {
if(!text)
return;
/* Background color of the text if there is stipple */ /* 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_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg);
/* Draw text */ /* Draw text */
draw_text(bw->dr, x, y, bw->fg, 0, text); draw_text(bw->dr, x, y, bw->fg, text);
barwin_refresh(bw); barwin_refresh(bw);
return; return;
} }
void
barwin_color_set(BarWindow *bw, uint bg, char *fg)
{
CHECK(bw);
bw->bg = bg;
bw->fg = fg;
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 == -1)
bw->stipple_color = getcolor(fg);
return;
}
/** Delete a BarWindow /** Delete a BarWindow
* \param bw BarWindow pointer * \param bw BarWindow pointer
*/ */
@@ -157,11 +175,11 @@ barwin_delete_subwin(BarWindow *bw)
void void
barwin_map(BarWindow *bw) barwin_map(BarWindow *bw)
{ {
CHECK(!bw->mapped); CHECK(!(bw->flags & MappedFlag));
XMapWindow(dpy, bw->win); XMapWindow(dpy, bw->win);
bw->mapped = True; bw->flags |= MappedFlag;
return; return;
} }
@@ -187,11 +205,11 @@ barwin_map_subwin(BarWindow *bw)
void void
barwin_unmap(BarWindow *bw) barwin_unmap(BarWindow *bw)
{ {
CHECK(bw->mapped); CHECK(bw->flags & MappedFlag);
XUnmapWindow(dpy, bw->win); XUnmapWindow(dpy, bw->win);
bw->mapped = False; bw->flags &= ~MappedFlag;
return; return;
} }
@@ -217,12 +235,10 @@ barwin_unmap_subwin(BarWindow *bw)
void void
barwin_move(BarWindow *bw, int x, int y) barwin_move(BarWindow *bw, int x, int y)
{ {
CHECK(bw); if(!bw || (bw->geo.x == x && bw->geo.y == y))
return;
bw->geo.x = x; XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y));
bw->geo.y = y;
XMoveWindow(dpy, bw->win, x, y);
return; return;
} }
@@ -233,24 +249,26 @@ barwin_move(BarWindow *bw, int x, int y)
* \param h Height * \param h Height
*/ */
void void
barwin_resize(BarWindow *bw, uint w, uint h) barwin_resize(BarWindow *bw, int w, int h)
{ {
CHECK(bw); if(!bw || (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.width = w;
bw->geo.height = h; 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); XResizeWindow(dpy, bw->win, w, h);
/* Border */ /* Border */
if(bw->bord) if(bw->flags & BordFlag)
{ {
XResizeWindow(dpy, bw->border.left, SHADH, h); XResizeWindow(dpy, bw->border.left, SHADH, h);
XResizeWindow(dpy, bw->border.top, w, SHADH); XResizeWindow(dpy, bw->border.top, w, SHADH);
@@ -269,15 +287,16 @@ barwin_refresh_color(BarWindow *bw)
{ {
CHECK(bw); CHECK(bw);
draw_rectangle(bw->dr, 0, 0, bw->geo.width, bw->geo.height, bw->bg); XSetForeground(dpy, gc, bw->bg);
XFillRectangle(dpy, bw->dr, gc, 0, 0, bw->geo.width, bw->geo.height);
if(bw->stipple) if(bw->flags & StippleFlag)
{ {
XSetForeground(dpy, gc_stipple, ((bw->stipple_color != -1) ? 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); 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.left, bw->border.light);
XSetWindowBackground(dpy, bw->border.top, bw->border.light); XSetWindowBackground(dpy, bw->border.top, bw->border.light);
@@ -299,8 +318,7 @@ barwin_refresh_color(BarWindow *bw)
void void
barwin_refresh(BarWindow *bw) barwin_refresh(BarWindow *bw)
{ {
if(!bw || !bw->dr || !bw->win) CHECK(bw);
return;
XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0); XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0);

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;
/* Travel clients to search parents of row and apply fact */
for(cc = tiled_client(c->screen, clients); cc; cc = tiled_client(c->screen, 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;
int e, f[4] = { 0 };
f[p] += fac;
/* Travel clients to search parents of row and check geos */
for(cc = tiled_client(c->screen, clients); cc; cc = tiled_client(c->screen, 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

223
src/color.c Normal file
View File

@@ -0,0 +1,223 @@
/*
* color.c
* Copyright © 2011 Brian Mock <mock.brian@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
/** Clamp a number x within the range [a, b].
* \param x the number which to clamp
* \param a the lowest possible value
* \param b the highest possible value
* \return the clamped number
*/
static double
color_clamp(double x, double a, double b)
{
if(x < a)
return a;
else if(x > b)
return b;
else
return x;
}
/** Pack a triplet of RGB values into a single uint
* \param r the red value
* \param g the green value
* \param b the blue value
* \return the packed RGB value
*/
static uint
color_pack_rgb(uint r, uint g, uint b)
{
return (r << 16) | (g << 8) | b;
}
/** Unpack an RGB uint into three separate values
* \param rgb the packed color
* \param r a pointer to a uint where the red value will be stored
* \param g a pointer to a uint where the green value will be stored
* \param b a pointer to a uint where the blue value will be stored
*/
static void
color_unpack_rgb(uint rgb, uint *r, uint *g, uint *b)
{
*r = (rgb >> 16) & 0xFF;
*g = (rgb >> 8) & 0xFF;
*b = rgb & 0xFF;
}
/** Convert unpacked RGB values into HSL, storing in the doubles referenced
* by the pointers h, s, l
*/
static void
color_rgb_to_hsl(uint xr, uint xg, uint xb, double *h, double *s, double *l)
{
double r = xr/255.0;
double g = xg/255.0;
double b = xb/255.0;
double v;
double m;
double vm;
double r2, g2, b2;
*h = 0;
*s = 0;
*l = 0;
/* v is max(r, g, b)
* m is min(r, g, b)
*/
v = r > g ? r : g;
v = v > b ? v : b;
m = r < g ? r : g;
m = m < b ? m : b;
*l = (m + v)/2.0;
if(*l <= 0.0)
return;
vm = v - m;
*s = vm;
if(*s > 0.0)
*s /= (*l <= 0.5) ? (v + m) : (2.0 - v - m);
else
return;
r2 = (v - r)/vm;
g2 = (v - g)/vm;
b2 = (v - b)/vm;
if(r == v)
*h = (g == m ? 5.0 + b2 : 1.0 - g2);
else if(g == v)
*h = (b == m ? 1.0 + r2 : 3.0 - b2);
else
*h = (r == m ? 3.0 + g2 : 5.0 - r2);
*h /= 6.0;
}
/** Convert h, s, l values to RGB and store them in the three uint
* referenced by the last three parameters.
*/
static void
color_hsl_to_rgb(double h, double sl, double l, uint *rx, uint *gx, uint *bx)
{
double v;
double r,g,b;
r = l;
g = l;
b = l;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if(v > 0)
{
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m ) / v;
h *= 6.0;
sextant = (int) h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch(sextant)
{
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
*rx = r * 255.0;
*gx = g * 255.0;
*bx = b * 255.0;
}
/** Shades a color by the amount. This works by converting a packed RGB
* color to HSL, adding the amount to the lightness,
* and then converting back to RGB. 1.0 is max lightness, 0.0 is min lightness.
* \param shadeVal the amount to shade the lightness by.
* \return the shaded color
*/
uint
color_shade(uint rgb, double shadeVal)
{
uint r, g, b;
double h, s, l;
color_unpack_rgb(rgb, &r, &g, &b);
color_rgb_to_hsl(r, g, b, &h, &s, &l);
l += shadeVal;
l = color_clamp(l, 0, 1);
color_hsl_to_rgb(h, s, l, &r, &g, &b);
rgb = color_pack_rgb(r, g, b);
return rgb;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +0,0 @@
/*
* config.h
* Copyright © 2008 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include "wmfs.h"
#define WMFS_VERSION "@WMFS_VERSION@"
#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@"
#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@"
#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@"
#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@"
#define XDG_CONFIG_DIR "@XDG_CONFIG_DIR@"
/* Optional dependencies */
@WMFS_HAVE_XINERAMA@
@WMFS_HAVE_XRANDR@
@WMFS_HAVE_IMLIB@
#endif /* CONFIG_H */

View File

@@ -1,289 +0,0 @@
/*
* confparse.c
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "confparse.h"
char*
file_to_str(char *path)
{
char *buf, *ret, *p, *c;
int fd, i;
struct stat st;
Bool is_char = False;
if (!path)
return NULL;
if (!(fd = open(path, O_RDONLY)))
{
warn("%s", path);
return NULL;
}
/* Get the file size */
stat(path, &st);
/* Bufferize file */
if((buf = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, SEEK_SET)) == (char*) MAP_FAILED)
return NULL;
/* Copy buffer without comments in return value */
ret = emalloc(strlen(buf) + 1, sizeof(char));
for(p = buf, i = 0; *p != '\0'; p++)
{
if(!is_char && (c = strchr("\"'", *p)))
is_char = !is_char;
else if (is_char && *p == *c)
is_char = !is_char;
if(*p == COMMENT_CHAR && !is_char)
{
if(!(p = strchr(p, '\n')))
break;
ret[i++] = '\n';
}
else
ret[i++] = *p;
}
ret[i++] = '\0';
/* Unmap buffer, thanks linkdd. */
munmap(buf, st.st_size);
close(fd);
warnx("%s read.", path);
return ret;
}
char*
get_sec(char *src, char *name)
{
char *ret = NULL, *start, *end, *p;
char **sec;
size_t len;
if(!src)
return NULL;
if(!name)
return src;
sec = secname(name);
len = strlen(sec[SecStart]);
/* Find start section pointer */
for(start = src; *start != '\0'; start++)
{
if( (p = strchr("\"'", *start)) )
while (*(++start) && *start != *p);
if(!strncmp(start, sec[SecStart], len))
break;
}
if(*start != '\0')
{
/* Here is_char == False */
start += len;
/* Find end section pointer */
for(end = start; *end != '\0'; end++)
{
if( (p = strchr("\"'", *start)) )
while (*(++start) && *start != *p);
if(!strncmp(end, sec[SecEnd], len+1))
break;
}
/* Allocate and set ret */
if(end != '\0')
{
len = end - start;
ret = emalloc(len + 1, sizeof(char));
memcpy(ret, start, len);
ret[len] = '\0';
}
}
free_secname(sec);
return ret;
}
char*
get_nsec(char *src, char *name, int n)
{
int i;
char *ret, *buf, **sec;
if(!src || !strlen(src))
return NULL;
if(!name)
return src;
if(!n)
return get_sec(src, name);
sec = secname(name);
buf = _strdup(sauv_delimc);
for(i = 0; i < n && (buf = strstr(buf, sec[SecStart])); ++i, buf += strlen(sec[SecStart]));
ret = get_sec(src + strlen(src) - strlen(buf), name);
free_secname(sec);
return ret;
}
int
get_size_sec(char *src, char *name)
{
int ret;
char **sec, *buf;
if(!src || !name)
return 0;
sec = secname(name);
buf = _strdup(sauv_secc);
for(ret = 0; (buf = strstr(buf, sec[SecStart])); ++ret, buf += strlen(sec[SecStart]));
free_secname(sec);
return ret;
}
opt_type
get_opt(char *src, char *def, char *name)
{
int i;
char *p = NULL, *p2 = NULL;
opt_type ret = null_opt_type;
if(!src || !name)
return (def) ? str_to_opt(def) : ret;
if((p = opt_srch(sauv_secc, name)))
{
for(i = 0; p[i] && p[i] != '\n'; ++i);
p[i] = '\0';
p2 = _strdup(p + strlen(name));
if((p = strchr(p, '=')) && !is_in_delimiter(p, 0))
{
for(i = 0; p2[i] && p2[i] != '='; ++i);
p2[i] = '\0';
/* Check if there is anything else that spaces
* between option name and '=' */
for(i = 0; i < strlen(p2); ++i)
if(p2[i] != ' ')
{
warnx("Configuration warning: Missing '=' after option: '%s'"
" and before expression: '%s'\n", name, p2);
return str_to_opt(def);
}
ret = str_to_opt(clean_value(++p));
}
}
if(!ret.str)
ret = str_to_opt(def);
return ret;
}
/* option = {val1, val2, val3} */
opt_type*
get_list_opt(char *src, char *def, char *name, int *n)
{
int i, j;
char *p, *p2;
opt_type *ret;
if(!src || !name)
return NULL;
*n = 0;
if(!(p = get_opt(src, def, name).str))
return NULL;
for(i = 0; p[i] && (p[i] != LIST_DEL_E || is_in_delimiter(p, i)); ++i);
p[i + 1] = '\0';
/* Syntax of list {val1, val2, ..., valx} */
if(*p != LIST_DEL_S || *(p + strlen(p) - 1) != LIST_DEL_E)
return NULL;
/* Erase ( ) */
++p;
*(p + strlen(p) - 1) = '\0';
/* > 1 value in list */
if(strchr(p, ','))
{
/* Count ',' */
for(i = 0, *n = 1; i < strlen(p); ++i)
if(p[i] == ',' && !is_in_delimiter(p, i))
++(*n);
ret = emalloc(*n, sizeof(opt_type));
p2 = _strdup(p);
/* Set all value in return array */
for(i = j = 0; i < *n; ++i, p2 += ++j)
{
for(j = 0; j < strlen(p2) && (p2[j] != ',' || is_in_delimiter(p2, j)); ++j);
p2[j] = '\0';
ret[i] = str_to_opt(clean_value(p2));
}
}
else
{
ret = emalloc((*n = 1), sizeof(opt_type));
*ret = str_to_opt(clean_value(p));
}
return ret;
}

View File

@@ -1,87 +0,0 @@
/*
* confparse.h
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONFPARSE_H
#define CONFPARSE_H
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "../wmfs.h"
/* Section delimiter */
#define SEC_DEL_S '['
#define SEC_DEL_E ']'
/* List delimiter */
#define LIST_DEL_S '{'
#define LIST_DEL_E '}'
/* Comment character */
#define COMMENT_CHAR '#'
enum { SecStart, SecEnd, SecLast };
typedef struct
{
long int num;
float fnum;
Bool bool;
char *str;
} opt_type;
/* util.c */
char *erase_delim_content(char *buf);
Bool is_in_delimiter(char *buf, int p);
char *erase_sec_content(char *buf);
char *opt_srch(char *buf, char *opt);
opt_type str_to_opt(char *str);
char *clean_value(char *str);
void cfg_set_sauv(char *str);
char **secname(char *name);
void free_secname(char **secname);
/* confparse.c */
char *file_to_str(char *path);
char *get_sec(char *src, char *name);
char *get_nsec(char *src, char *name, int n);
int get_size_sec(char *src, char *name);
opt_type get_opt(char *src, char *def, char *name);
opt_type *get_list_opt(char *src, char *def, char *name, int *n);
static const opt_type null_opt_type = {0, 0, 0, NULL};
char *sauv_delimc;
char *sauv_secc;
#endif /* CONFPARSE_H */

View File

@@ -1,220 +0,0 @@
/*
* confparse/util.c
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "confparse.h"
char*
erase_delim_content(char *buf)
{
int i, j;
char *str, c;
if(!buf || !(str = _strdup(buf)))
return NULL;
for(i = 0; i < strlen(str); ++i)
if(strchr("\"'", (c = str[i])))
{
for(*(str + (j = i)) = ' '; str[j] && str[j] != c; str[j++] = ' ');
str[j] = ' ';
}
return str;
}
/* Erase all content of all delimiters, put it
* int str, and check if buf[p] is in an delimiter. */
Bool
is_in_delimiter(char *buf, int p)
{
if(*(erase_delim_content(buf) + p) != buf[p])
return True;
return False;
}
char*
erase_sec_content(char *buf)
{
int i, j;
char *p, *str, *name, *ret;
char **sec;
if(!buf || !(str = _strdup(sauv_delimc)))
return NULL;
ret = _strdup(buf);
for(i = 1, name = _strdup(str + i); strchr(str + i, SEC_DEL_S); ++i, name = _strdup(str + i))
{
for(; str[i] && str[i] != SEC_DEL_S; ++i);
for(j = 0; str[i] && str[i] != SEC_DEL_E; name[j++] = str[i++]);
++name;
name[j - 1] = '\0';
if(*name == '/')
continue;
sec = secname(name);
if((p = strstr(str + i, sec[SecEnd])))
for(++i; i < strlen(ret) - strlen(p); ret[i++] = ' ');
else
break;
}
free_secname(sec);
return ret;
}
/* To get the RIGHT name of an option; if option needed is
* pwet and there is tagadapwettagada in the configuration,
* with strstr(), the name will matchs */
char*
opt_srch(char *buf, char *opt)
{
char *p;
if(!buf || !opt)
return NULL;
if((p = strstr(sauv_delimc /*erase_delim_content(buf)*/, opt)))
if((*(p + strlen(opt)) == ' ' || *(p + strlen(opt)) == '=')
&& (*(p - 1) == ' ' || *(p - 1) == '\n' || *(p - 1) == '\t' || !(*(p - 1))))
return _strdup(buf + (strlen(buf) - strlen(p)));
return NULL;
}
opt_type
str_to_opt(char *str)
{
opt_type ret = null_opt_type;
if(!strlen(str))
return ret;
/* Integer */
ret.num = atoi(str);
/* Float */
sscanf(str, "%f", &ret.fnum);
/* Boolean */
if(strstr(str, "true") || strstr(str, "True")
|| strstr(str, "TRUE") || strstr(str, "1"))
ret.bool = True;
/* String */
ret.str = _strdup(str);
return ret;
}
char*
clean_value(char *str)
{
int i;
char c, *p;
if(!str || !(p = _strdup(str)))
return NULL;
/* Remove useless spaces */
for(; *p == ' '; ++p);
for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0');
/* For string delimiter (" or ') */
if(((c = *p) == '"' || (c = *p) == '\'') && strchr(p + 1, c))
{
for(++p, i = 0; p[i] && p[i] != c; ++i);
p[i] = '\0';
}
return p;
}
void
cfg_set_sauv(char *str)
{
if(!str)
{
sauv_delimc = NULL;
sauv_secc = NULL;
return;
}
sauv_delimc = erase_delim_content(_strdup(str));
sauv_secc = erase_sec_content(_strdup(str));
return;
}
char**
secname(char *name)
{
char **ret = NULL;
if(!name)
return NULL;
ret = emalloc(SecLast, sizeof(char*));
/* Len of name + '[' + ']' + '\0' */
ret[SecStart] = emalloc(strlen(name) + 3, sizeof(char));
/* Len of name + '[' + '/' + ']' + '\0' */
ret[SecEnd] = emalloc(strlen(name) + 4, sizeof(char));
sprintf(ret[SecStart], "%c%s%c", SEC_DEL_S, name, SEC_DEL_E);
sprintf(ret[SecEnd], "%c/%s%c", SEC_DEL_S, name, SEC_DEL_E);
return ret;
}
void
free_secname(char **secname)
{
if(!secname || LEN(secname) != SecLast)
return;
if(secname[SecStart])
free(secname[SecStart]);
if(secname[SecEnd])
free(secname[SecEnd]);
free(secname);
return;
}

View File

@@ -32,6 +32,77 @@
#include "wmfs.h" #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)
{
Imlib_Image image;
if(!dr)
return;
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, DefaultScreen(dpy)));
imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy)));
imlib_context_set_drawable(dr);
image = imlib_load_image(patht(name));
imlib_context_set_image(image);
if(w <= 0)
w = imlib_image_get_width();
if(h <= 0)
h = imlib_image_get_height();
if(image)
imlib_render_image_on_drawable_at_size(x, y, w, h);
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
*\return n Lenght of i
*/
static int
parse_image_block(Drawable dr, char *str)
{
ImageAttr im;
char as;
int i, j, k;
for(i = j = 0; i < (int)strlen(str); ++i, ++j)
if(sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^]]]%c", &im.x, &im.y, &im.w, &im.h, im.name, &as) == 6
&& as == '\\')
{
draw_image(dr, im.x - sw, im.y, im.w, im.h, im.name);
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 */
/** Draw a string in a Drawable /** Draw a string in a Drawable
* \param d Drawable * \param d Drawable
* \param x X position * \param x X position
@@ -41,31 +112,32 @@
* \param str String that will be draw * \param str String that will be draw
*/ */
void void
draw_text(Drawable d, int x, int y, char* fg, int pad, char *str) draw_text(Drawable d, int x, int y, char* fg, char *str)
{ {
XftColor xftcolor; CHECK(str);
XftDraw *xftd;
if(!str)
return;
/* To draw image everywhere we can draw text */ /* To draw image everywhere we can draw text */
#ifdef HAVE_IMLIB #ifdef HAVE_IMLIB
char *ostr = NULL; char *ostr;
int i, ni; size_t textlen = 0;
ImageAttr im[128];
ostr = _strdup(str);
if(strstr(str, "i[")) if(strstr(str, "i["))
{ {
ni = parse_image_block(im, str); if(d == infobar[conf.systray.screen].bar->dr)
sw = systray_get_width();
for(i = 0; i < ni; ++i) ostr = xstrdup(str);
draw_image(d, im[i].x, im[i].y, im[i].w, im[i].h, im[i].name); textlen = strlen(ostr);
parse_image_block(d, str);
} }
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */
#ifdef HAVE_XFT
if(conf.use_xft)
{
XftColor xftcolor;
XftDraw *xftd;
/* Transform X Drawable -> Xft Drawable */ /* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN)); xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
@@ -73,18 +145,28 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN), XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, SCREEN), fg, &xftcolor); DefaultColormap(dpy, SCREEN), fg, &xftcolor);
XftDrawStringUtf8(xftd, &xftcolor, font, x, y, (FcChar8 *)str, strlen(str)); XftDrawStringUtf8(xftd, &xftcolor, font.font, x, y, (FcChar8 *)str, strlen(str));
/* Free the text color and XftDraw */ /* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor); XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
XftDrawDestroy(xftd); 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));
}
#ifdef HAVE_IMLIB #ifdef HAVE_IMLIB
if(strstr(ostr, "i[")) if(textlen)
strcpy(str, ostr); {
strncpy(str, ostr, textlen);
IFREE(ostr); free(ostr);
}
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */
return; return;
@@ -99,57 +181,33 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
* \param color Color of the rectangle * \param color Color of the rectangle
*/ */
void 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); XSetForeground(dpy, gc, color);
XFillRectangles(dpy, dr, gc, &r, 1); XFillRectangle(dpy, dr, gc, x, y, (uint)w, (uint)h);
return; return;
} }
#ifdef HAVE_IMLIB /** Draw a Graph in a drawable
/** Draw an image in a drawable
* \param dr Drawable * \param dr Drawable
* \param x X position * \param x X position
* \param y Y position * \param y Y position
* \param name Path of the image * \param w Width
* \param h Height
* \param color Color of the graph
* \param data Array of bytes that will be draw
*/ */
void void
draw_image(Drawable dr, int x, int y, int w, int h, char *name) draw_graph(Drawable dr, int x, int y, int w, int h, uint color, char *data)
{ {
Imlib_Image image; int i;
if(!name) for(i = 0; i < w; ++i)
return; draw_rectangle(dr, x + i, y + h - data[i], 1, data[i], color);
imlib_set_cache_size(2048 * 1024);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, DefaultScreen(dpy)));
imlib_context_set_colormap(DefaultColormap(dpy, DefaultScreen(dpy)));
imlib_context_set_drawable(dr);
image = imlib_load_image(name);
imlib_context_set_image(image);
if(w <= 0)
w = imlib_image_get_width();
if(h <= 0)
h = imlib_image_get_height();
if(image)
{
imlib_render_image_on_drawable_at_size(x, y, w, h);
imlib_free_image();
}
else
warnx("Can't draw image: '%s'", name);
return; return;
} }
#endif /* HAVE_IMLIB */
/** Calculates the text's size relatively to the font /** Calculates the text's size relatively to the font
* \param text Text string * \param text Text string
@@ -158,32 +216,48 @@ draw_image(Drawable dr, int x, int y, int w, int h, char *name)
ushort ushort
textw(char *text) textw(char *text)
{ {
XGlyphInfo gl; Drawable d = 0;
ushort ret = 0;
if(!text) if(!text)
return 0; return 0;
#ifdef HAVE_IMLIB #ifdef HAVE_IMLIB
char *ostr = NULL; char *ostr;
size_t textlen = 0;
ImageAttr im[128];
ostr = _strdup(text);
if(strstr(text, "i[")) if(strstr(text, "i["))
parse_image_block(im, text); {
ostr = xstrdup(text);
textlen = strlen(ostr);
parse_image_block(d, text);
}
#endif /* HAVE_IMLIB */ #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 #ifdef HAVE_IMLIB
if(strstr(ostr, "i[")) if(textlen)
strcpy(text, ostr); {
strncpy(text, ostr, textlen);
IFREE(ostr); free(ostr);
}
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */
return gl.width + font->descent; return ret;
} }

View File

@@ -32,12 +32,14 @@
#include "wmfs.h" #include "wmfs.h"
#define EVDPY (e->xany.display)
/** ButtonPress handle event /** ButtonPress handle event
* \param ev XButtonEvent pointer
*/ */
void static void
buttonpress(XButtonEvent *ev) buttonpress(XEvent *e)
{ {
XButtonEvent *ev = &e->xbutton;
Client *c; Client *c;
int i, j, n; int i, j, n;
@@ -49,6 +51,8 @@ buttonpress(XButtonEvent *ev)
{ {
client_focus(c); client_focus(c);
client_raise(c); client_raise(c);
return;
} }
/* Titlebar */ /* Titlebar */
@@ -63,7 +67,10 @@ buttonpress(XButtonEvent *ev)
for(i = 0; i < conf.titlebar.button[n].nmouse; ++i) for(i = 0; i < conf.titlebar.button[n].nmouse; ++i)
if(ev->button == conf.titlebar.button[n].mouse[i].button) if(ev->button == conf.titlebar.button[n].mouse[i].button)
if(conf.titlebar.button[n].mouse[i].func) if(conf.titlebar.button[n].mouse[i].func)
{
client_focus(c);
conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd); conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd);
}
/* Frame Resize Area */ /* Frame Resize Area */
if((c = client_gb_resize(ev->window))) if((c = client_gb_resize(ev->window)))
@@ -75,6 +82,7 @@ buttonpress(XButtonEvent *ev)
if(ev->button == conf.client.mouse[i].button) if(ev->button == conf.client.mouse[i].button)
if(conf.client.mouse[i].func) if(conf.client.mouse[i].func)
conf.client.mouse[i].func(conf.client.mouse[i].cmd); conf.client.mouse[i].func(conf.client.mouse[i].cmd);
/* Root */ /* Root */
if(ev->window == ROOT) if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i) for(i = 0; i < conf.root.nmouse; ++i)
@@ -96,15 +104,35 @@ buttonpress(XButtonEvent *ev)
if(conf.bars.mouse[j].func) if(conf.bars.mouse[j].func)
conf.bars.mouse[j].func(conf.bars.mouse[j].cmd); conf.bars.mouse[j].func(conf.bars.mouse[j].cmd);
/* Selbar */
if(conf.bars.selbar && ev->window == infobar[selscreen].selbar->win)
for(i = 0; i < conf.selbar.nmouse; ++i)
if(conf.selbar.mouse[i].tag == seltag[conf.selbar.mouse[i].screen]
|| conf.selbar.mouse[i].tag < 0)
if(ev->button == conf.selbar.mouse[i].button)
if(conf.selbar.mouse[i].func)
conf.selbar.mouse[i].func(conf.selbar.mouse[i].cmd);
/* Tags */ /* Tags */
for(i = 1; i < conf.ntag[selscreen] + 1; ++i) for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(ev->window == infobar[selscreen].tags[i]->win) if(ev->window == infobar[selscreen].tags[i]->win)
switch(ev->button)
{ {
case Button1: tag_set(i); break; for(j = 0; j < tags[selscreen][i].nmouse; ++j)
case Button3: tag_transfert(sel, i); break; if(ev->button == tags[selscreen][i].mouse[j].button)
case Button4: tag_set(seltag[selscreen] + 1); break; if(tags[selscreen][i].mouse[j].func)
case Button5: tag_set(seltag[selscreen] - 1); break; tags[selscreen][i].mouse[j].func(tags[selscreen][i].mouse[j].cmd);
/* Mouse button action on tag */
if(ev->button == conf.mouse_tag_action[TagSel])
tag_set(i);
else if(ev->button == conf.mouse_tag_action[TagTransfert])
tag_transfert(sel, i);
else if(ev->button == conf.mouse_tag_action[TagAdd])
tag_additional(selscreen, seltag[selscreen], i);
else if(ev->button == conf.mouse_tag_action[TagNext])
tag_set(seltag[selscreen] + 1);
else if(ev->button == conf.mouse_tag_action[TagPrev])
tag_set(seltag[selscreen] - 1);
} }
/* Layout button */ /* Layout button */
@@ -134,13 +162,14 @@ buttonpress(XButtonEvent *ev)
} }
/* ClientMessage handle event /* ClientMessage handle event
*\param ev XClientMessageEvent pointer
*/ */
void static void
clientmessageevent(XClientMessageEvent *ev) clientmessageevent(XEvent *e)
{ {
XClientMessageEvent *ev = &e->xclient;
Client *c; Client *c;
int s, i, mess_t = 0; Systray *sy;
int s, mess_t = 0;
Atom rt; Atom rt;
int rf; int rf;
ulong ir, il; ulong ir, il;
@@ -153,9 +182,8 @@ clientmessageevent(XClientMessageEvent *ev)
s = screen_count(); s = screen_count();
for(i = 0; i < net_last + s; ++i) while(mess_t < net_last + s && net_atom[mess_t] != ev->message_type)
if(net_atom[i] == ev->message_type) ++mess_t;
mess_t = i;
if(ev->window == ROOT) if(ev->window == ROOT)
{ {
@@ -173,8 +201,28 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _NET_ACTIVE_WINDOW */ /* Manage _NET_ACTIVE_WINDOW */
else if(mess_t == net_active_window) else if(mess_t == net_active_window)
{
if((c = client_gb_win(ev->window))) if((c = client_gb_win(ev->window)))
client_focus(c); client_focus(c);
else if((sy = systray_find(ev->data.l[0])))
XSetInputFocus(EVDPY, sy->win, RevertToNone, CurrentTime);
}
}
else if(ev->window == traywin)
{
/* Manage _NET_WM_SYSTEM_TRAY_OPCODE */
if(mess_t == net_wm_system_tray_opcode)
{
if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
{
systray_add(ev->data.l[2]);
systray_update();
}
else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
if((sy = systray_find(ev->data.l[2])))
ewmh_send_message(sy->win, sy->win, "_XEMBED",
XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0);
}
} }
/* Manage _NET_WM_STATE */ /* Manage _NET_WM_STATE */
@@ -189,13 +237,15 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _NET_WM_DESKTOP */ /* Manage _NET_WM_DESKTOP */
if(mess_t == net_wm_desktop) if(mess_t == net_wm_desktop)
if((c = client_gb_win(ev->window))) if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF)
tag_transfert(c, ev->data.l[0]); tag_transfert(c, ev->data.l[0]);
/* Manage _WMFS_STATUSTEXT_x */ if(ev->data.l[4])
if(mess_t >= wmfs_statustext && ev->data.l[4] == True)
{ {
if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096, /* Manage _WMFS_STATUSTEXT_x */
if(mess_t >= wmfs_statustext)
{
if(XGetWindowProperty(EVDPY, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success) False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
{ {
statustext_handle(mess_t - wmfs_statustext, (char*)ret); statustext_handle(mess_t - wmfs_statustext, (char*)ret);
@@ -204,13 +254,11 @@ clientmessageevent(XClientMessageEvent *ev)
} }
/* Manage _WMFS_FUNCTION && _WMFS_CMD */ /* Manage _WMFS_FUNCTION && _WMFS_CMD */
if((mess_t == wmfs_function && ev->data.l[4] == True) if(mess_t == wmfs_function || mess_t == wmfs_cmd)
|| (mess_t == wmfs_cmd && ev->data.l[4] == True))
{ {
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_function], 0, 4096, XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_function], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret); False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret);
XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_cmd], 0, 4096,
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_cmd], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd); False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd);
if((func = name_to_func((char*)ret, func_list))) if((func = name_to_func((char*)ret, func_list)))
@@ -219,6 +267,7 @@ clientmessageevent(XClientMessageEvent *ev)
XFree(ret_cmd); XFree(ret_cmd);
XFree(ret); XFree(ret);
} }
}
/* Manage _WMFS_UPDATE_HINTS */ /* Manage _WMFS_UPDATE_HINTS */
if(mess_t == wmfs_update_hints) if(mess_t == wmfs_update_hints)
@@ -228,36 +277,30 @@ clientmessageevent(XClientMessageEvent *ev)
ewmh_get_client_list(); ewmh_get_client_list();
ewmh_get_desktop_names(); ewmh_get_desktop_names();
ewmh_set_desktop_geometry(); ewmh_set_desktop_geometry();
ewmh_set_workarea();
screen_count(); screen_count();
screen_get_sel(); screen_get_sel();
} }
if(mess_t == wmfs_update_status /* Manage _WMFS_UPDATE_STATUS */
&& estatus) if(mess_t == wmfs_update_status && estatus)
spawn(conf.status_path); spawn(conf.status_path);
return; return;
} }
/** ConfigureRequest & ConfigureNotify handle events /** ConfigureRequesthandle events
* \param ev XEvent pointer
*/ */
void static void
configureevent(XConfigureRequestEvent *ev) configureevent(XEvent *e)
{ {
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc; XWindowChanges wc;
Client *c; Client *c;
/* Check part */ /* Check part */
if((c = client_gb_win(ev->window)) if(((c = client_gb_win(ev->window)) || (c = client_gb_win(ev->window)))
|| (c = client_gb_win(ev->window))) && (c->flags & (LMaxFlag | MaxFlag | FSSFlag)))
{ return;
CHECK(!(c->flags & TileFlag));
CHECK(!(c->flags & LMaxFlag));
CHECK(!(c->flags & MaxFlag));
CHECK(!(c->flags & FSSFlag));
}
if((c = client_gb_win(ev->window))) if((c = client_gb_win(ev->window)))
{ {
@@ -270,8 +313,13 @@ configureevent(XConfigureRequestEvent *ev)
if(ev->value_mask & CWHeight) if(ev->value_mask & CWHeight)
c->geo.height = ev->height; c->geo.height = ev->height;
if(c->flags & FreeFlag) if(c->flags & FreeFlag || !(c->flags & TileFlag))
client_moveresize(c, c->geo, False); client_moveresize(c, c->geo, False);
else
{
client_configure(c);
arrange(c->screen, True);
}
} }
else else
{ {
@@ -283,43 +331,59 @@ configureevent(XConfigureRequestEvent *ev)
wc.sibling = ev->above; wc.sibling = ev->above;
wc.stack_mode = ev->detail; wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); XConfigureWindow(EVDPY, ev->window, ev->value_mask, &wc);
} }
return; return;
} }
/** DestroyNotify handle event /** DestroyNotify handle event
* \param ev XDestroyWindowEvent pointer
*/ */
void static void
destroynotify(XDestroyWindowEvent *ev) destroynotify(XEvent *e)
{ {
XDestroyWindowEvent *ev = &e->xdestroywindow;
Client *c; Client *c;
Systray *s;
if((c = client_gb_win(ev->window))) if((c = client_gb_win(ev->window)))
{ {
client_unmanage(c); client_unmanage(c);
XSetErrorHandler(errorhandler); XSetErrorHandler(errorhandler);
} }
else if((s = systray_find(ev->window)))
{
setwinstate(s->win, WithdrawnState);
systray_del(s);
systray_update();
}
return; return;
} }
/** EnterNotify handle event /** EnterNotify handle event
* \param ev XCrossingEvent pointer
*/ */
void static void
enternotify(XCrossingEvent *ev) enternotify(XEvent *e)
{ {
XCrossingEvent *ev = &e->xcrossing;
Client *c; Client *c;
int n; int n;
if((ev->mode != NotifyNormal if((ev->mode != NotifyNormal || ev->detail == NotifyInferior)
|| ev->detail == NotifyInferior)
&& ev->window != ROOT) && ev->window != ROOT)
return; 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;
if(conf.focus_fmouse) if(conf.focus_fmouse)
{ {
if((c = client_gb_win(ev->window)) if((c = client_gb_win(ev->window))
@@ -336,11 +400,11 @@ enternotify(XCrossingEvent *ev)
} }
/** ExposeEvent handle event /** ExposeEvent handle event
* \param ev XExposeEvent pointer
*/ */
void static void
expose(XExposeEvent *ev) expose(XEvent *e)
{ {
XExposeEvent *ev = &e->xexpose;
Client *c; Client *c;
int i, sc; int i, sc;
@@ -366,49 +430,26 @@ expose(XExposeEvent *ev)
} }
/** FocusChange handle event /** FocusChange handle event
* \param ev XFocusChangeEvent pointer
* \return
*/ */
void static void
focusin(XFocusChangeEvent *ev) focusin(XEvent *e)
{ {
if(sel && ev->window != sel->win) if(sel && e->xfocus.window != sel->win)
client_focus(sel); client_focus(sel);
return; return;
} }
/** Key grabbing function
*/
void
grabkeys(void)
{
uint i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
for(i = 0; i < conf.nkeybind; ++i)
{
code = XKeysymToKeycode(dpy, keys[i].keysym);
XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
}
return;
}
/** KeyPress handle event /** KeyPress handle event
* \param ev XKeyPressedEvent pointer
*/ */
void static void
keypress(XKeyPressedEvent *ev) keypress(XEvent *e)
{ {
uint i; XKeyPressedEvent *ev = &e->xkey;
KeySym keysym; 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) for(i = 0; i < conf.nkeybind; ++i)
if(keysym == keys[i].keysym if(keysym == keys[i].keysym
&& (keys[i].mod & ~(numlockmask | LockMask)) && (keys[i].mod & ~(numlockmask | LockMask))
@@ -419,81 +460,150 @@ keypress(XKeyPressedEvent *ev)
return; return;
} }
/** MapNotify handle event /** MappingNotify handle event
* \param ev XMappingEvent pointer
*/ */
void static void
mappingnotify(XMappingEvent *ev) mappingnotify(XEvent *e)
{ {
XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard) if(ev->request == MappingKeyboard)
grabkeys(); grabkeys();
return; return;
} }
/** MapRequest handle event /** MapNotify handle event
* \param ev XMapRequestEvent pointer */
*/ static void
void mapnotify(XEvent *e)
maprequest(XMapRequestEvent *ev)
{ {
XWindowAttributes at; XMapEvent *ev = &e->xmap;
Client *c; Client *c;
Systray *s;
CHECK(XGetWindowAttributes(dpy, ev->window, &at)); if(ev->window != ev->event && !ev->send_event)
return;
if((c = client_gb_win(ev->window)))
setwinstate(c->win, NormalState);
else if((s = systray_find(ev->window)))
{
setwinstate(s->win, NormalState);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
}
return;
}
/** MapRequest handle event
*/
static void
maprequest(XEvent *e)
{
XMapRequestEvent *ev = &e->xmaprequest;
XWindowAttributes at;
Systray *s;
CHECK(XGetWindowAttributes(EVDPY, ev->window, &at));
CHECK(!at.override_redirect); CHECK(!at.override_redirect);
if(!(c = client_gb_win(ev->window))) if((s = systray_find(ev->window)))
{
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
systray_update();
}
else if(!client_gb_win(ev->window))
client_manage(ev->window, &at, True); client_manage(ev->window, &at, True);
return; return;
} }
/** PropertyNotify handle event /** PropertyNotify handle event
* \param ev XPropertyEvent pointer
*/ */
void static void
propertynotify(XPropertyEvent *ev) propertynotify(XEvent *e)
{ {
XPropertyEvent *ev = &e->xproperty;
Client *c; Client *c;
Systray *s;
Window trans; Window trans;
XWMHints *h;
if(ev->state == PropertyDelete) if(ev->state == PropertyDelete)
return; return;
if((s = systray_find(ev->window)))
{
systray_state(s);
systray_update();
}
if((c = client_gb_win(ev->window))) if((c = client_gb_win(ev->window)))
{ {
switch(ev->atom) switch(ev->atom)
{ {
default: break;
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(EVDPY, c->win, &trans);
if((c->flags & TileFlag || c->flags & MaxFlag)) if((c->flags & (TileFlag | MaxFlag)) && client_gb_win(trans))
if(((c->flags & HintFlag && (client_gb_win(trans) != NULL)))
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
arrange(c->screen, True); arrange(c->screen, True);
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:
client_size_hints(c); client_size_hints(c);
break; break;
case XA_WM_HINTS:
if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
{
client_urgent(c, True);
XFree(h);
}
break;
case XA_WM_NAME: case XA_WM_NAME:
client_get_name(c); client_get_name(c);
break; break;
} default:
if(ev->atom == net_atom[net_wm_name]) if(ev->atom == net_atom[net_wm_name])
client_get_name(c); client_get_name(c);
break;
}
} }
return; return;
} }
/** UnmapNotify handle event /** XReparentEvent handle event
* \param ev XUnmapEvent pointer
*/ */
void static void
unmapnotify(XUnmapEvent *ev) reparentnotify(XEvent *ev)
{ {
(void)ev;
return;
}
/** SelectionClearEvent handle event
*/
static void
selectionclearevent(XEvent *ev)
{
/* Getting selection if lost it */
if(ev->xselectionclear.window == traywin)
systray_acquire();
systray_update();
return;
}
/** UnmapNotify handle event
*/
static void
unmapnotify(XEvent *e)
{
XUnmapEvent *ev = &e->xunmap;
Client *c; Client *c;
Systray *s;
if((c = client_gb_win(ev->window)) if((c = client_gb_win(ev->window))
&& ev->send_event && ev->send_event
@@ -503,76 +613,111 @@ unmapnotify(XUnmapEvent *ev)
XSetErrorHandler(errorhandler); XSetErrorHandler(errorhandler);
} }
return; if((s = systray_find(ev->window)))
}
/** Send a client event
*\param data Event data
*\param atom_name Event atom name
*/
void
send_client_event(long data[5], char *atom_name)
{
XEvent ev;
int i;
ev.xclient.type = ClientMessage;
ev.xclient.serial = 0;
ev.xclient.send_event = True;
ev.xclient.message_type = ATOM(atom_name);
ev.xclient.window = ROOT;
ev.xclient.format = 32;
for(i = 0; i < 5; ++i, ev.xclient.data.l[i] = data[i]);
XSendEvent(dpy, ROOT, False, SubstructureRedirectMask | SubstructureNotifyMask, &ev);
XSync(dpy, False);
return;
}
/** Event handle function: execute every function
* handle by event
* \param ev Event
*/
void
getevent(XEvent ev)
{
switch(ev.type)
{ {
case ButtonPress: buttonpress(&ev.xbutton); break; systray_del(s);
case ClientMessage: clientmessageevent(&ev.xclient); break; systray_update();
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break; }
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
case EnterNotify: enternotify(&ev.xcrossing); break;
case Expose: expose(&ev.xexpose); break;
case FocusIn: focusin(&ev.xfocus); break;
case KeyPress: keypress(&ev.xkey); break;
case MapRequest: maprequest(&ev.xmaprequest); break;
case MappingNotify: mappingnotify(&ev.xmapping); break;
case PropertyNotify: propertynotify(&ev.xproperty); break;
case UnmapNotify: unmapnotify(&ev.xunmap); break;
default:
return;
}
/** XMotionNotify handle event
*/
static void
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)
client_focus(c);
return;
}
/** XRandr handle event
*/
#ifdef HAVE_XRANDR #ifdef HAVE_XRANDR
/* Check Xrandr event */ void
if(ev.type == xrandr_event) xrandrevent(XEvent *e)
{ {
/* Update xrandr configuration */ /* Update xrandr configuration */
XRRUpdateConfiguration(&ev); if(!XRRUpdateConfiguration(e))
return;
/* Reload WMFS to update the screen(s) geometry changement */ /* Reload WMFS to update the screen(s) geometry changement */
quit(); quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global); for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execlp(argv_global, argv_global, NULL); execvp(argv_global, all_argv);
}
#endif /* HAVE_XRANDR */
break;
}
wait((int[]){0}); }
#endif /* HAVE_XRANDR */
/** Key grabbing function
*/
void
grabkeys(void)
{
int i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
for(i = 0; i < conf.nkeybind; ++i)
if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
{
XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
}
return; return;
} }
/** Make event handle function pointer array
*/
void
event_make_array(void)
{
int i = LASTEvent;
#ifdef HAVE_XRANDR
i = xrandr_event + RRScreenChangeNotify;
#endif /* HAVE_XRANDR */
event_handle = xcalloc((nevent = i + 1), 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
event_handle[xrandr_event + RRScreenChangeNotify] = xrandrevent;
#endif /* HAVE_XRANDR */
return;
}

View File

@@ -43,12 +43,14 @@ void
ewmh_init_hints(void) ewmh_init_hints(void)
{ {
int i = 1, s, j, showing_desk = 0; int i = 1, s, j, showing_desk = 0;
char root_name[] = WMFS_VERSION; char rootn[] = "wmfs-"WMFS_VERSION;
char class[] = "wmfs", st[64]; char class[] = "wmfs", st[64];
long pid = (long)getpid(); long pid = (long)getpid();
char systray_atom[48];
s = screen_count(); s = screen_count();
net_atom = emalloc(net_last + s, sizeof(Atom)); net_atom = xcalloc(net_last + s, sizeof(Atom));
/* EWMH hints */ /* EWMH hints */
net_atom[net_supported] = ATOM("_NET_SUPPORTED"); net_atom[net_supported] = ATOM("_NET_SUPPORTED");
@@ -58,7 +60,6 @@ ewmh_init_hints(void)
net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP"); net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES"); net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY"); net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY");
net_atom[net_workarea] = ATOM("_NET_WORKAREA");
net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW"); net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW"); net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
net_atom[net_wm_name] = ATOM("_NET_WM_NAME"); net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
@@ -68,6 +69,7 @@ ewmh_init_hints(void)
net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME"); net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE"); net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK"); net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL"); net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK"); net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH"); net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
@@ -75,7 +77,19 @@ ewmh_init_hints(void)
net_atom[net_wm_icon] = ATOM("_NET_WM_ICON"); net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
net_atom[net_wm_state] = ATOM("_NET_WM_STATE"); net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN"); net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION"); net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
snprintf(systray_atom, sizeof(systray_atom), "_NET_SYSTEM_TRAY_S%d", 0/*SCREEN*/);
net_atom[net_system_tray_s] = ATOM(systray_atom);
net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
net_atom[xembed] = ATOM("_XEMBED");
net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
net_atom[manager] = ATOM("MANAGER");
net_atom[utf8_string] = ATOM("UTF8_STRING"); net_atom[utf8_string] = ATOM("UTF8_STRING");
/* WMFS hints */ /* WMFS hints */
@@ -92,6 +106,7 @@ ewmh_init_hints(void)
net_atom[wmfs_nmaster] = ATOM("_WMFS_NMASTER"); net_atom[wmfs_nmaster] = ATOM("_WMFS_NMASTER");
net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION"); net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
net_atom[wmfs_cmd] = ATOM("_WMFS_CMD"); net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
net_atom[wmfs_font] = ATOM("_WMFS_FONT");
/* Multi atom _WMFS_STATUSTEXT_<screennum> */ /* Multi atom _WMFS_STATUSTEXT_<screennum> */
for(j = 0; j < s; ++j) for(j = 0; j < s; ++j)
@@ -111,7 +126,7 @@ ewmh_init_hints(void)
PropModeReplace, (uchar*)&ROOT, 1); PropModeReplace, (uchar*)&ROOT, 1);
XChangeProperty(dpy, ROOT, net_atom[net_wm_name], net_atom[utf8_string], 8, 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, XChangeProperty(dpy, ROOT, ATOM("WM_CLASS"), XA_STRING, 8,
PropModeReplace, (uchar*)&class, strlen(class)); PropModeReplace, (uchar*)&class, strlen(class));
@@ -127,6 +142,54 @@ ewmh_init_hints(void)
return; return;
} }
/** Send ewmh message
*/
void
ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4)
{
XClientMessageEvent e;
e.type = ClientMessage;
e.message_type = ATOM(atom);
e.window = w;
e.format = 32;
e.data.l[0] = d0;
e.data.l[1] = d1;
e.data.l[2] = d2;
e.data.l[3] = d3;
e.data.l[4] = d4;
XSendEvent(dpy, d, False, StructureNotifyMask, (XEvent*)&e);
XSync(dpy, False);
return;
}
/** Get xembed state
*/
long
ewmh_get_xembed_state(Window win)
{
Atom rf;
int f;
ulong n, il;
long ret = 0;
uchar *data = NULL;
if(XGetWindowProperty(dpy, win, net_atom[xembedinfo], 0L, 2, False,
net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
return 0;
if(rf == net_atom[xembedinfo] && n == 2)
ret = (long)data[1];
if(n && data)
XFree(data);
return ret;
}
/** Get the number of desktop (tag) /** Get the number of desktop (tag)
*/ */
void void
@@ -149,13 +212,11 @@ void
ewmh_update_current_tag_prop(void) ewmh_update_current_tag_prop(void)
{ {
int t; int t;
char *s = NULL; char s[8] = { 0 };
screen_get_sel(); screen_get_sel();
t = seltag[selscreen] - 1; t = seltag[selscreen] - 1;
s = emalloc(8, sizeof(char));
/* Get current desktop (tag) */ /* Get current desktop (tag) */
XChangeProperty(dpy, ROOT, net_atom[net_current_desktop], XA_CARDINAL, 32, XChangeProperty(dpy, ROOT, net_atom[net_current_desktop], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&t, 1); PropModeReplace, (uchar*)&t, 1);
@@ -180,8 +241,6 @@ ewmh_update_current_tag_prop(void)
PropModeReplace, (uchar*)tags[selscreen][seltag[selscreen]].layout.symbol, PropModeReplace, (uchar*)tags[selscreen][seltag[selscreen]].layout.symbol,
strlen(tags[selscreen][seltag[selscreen]].layout.symbol)); strlen(tags[selscreen][seltag[selscreen]].layout.symbol));
free(s);
return; return;
} }
@@ -195,7 +254,7 @@ ewmh_get_client_list(void)
int win_n; int win_n;
for(win_n = 0, c = clients; c; c = c->next, ++win_n); for(win_n = 0, c = clients; c; c = c->next, ++win_n);
list = emalloc(win_n, sizeof(Window)); list = xcalloc(win_n, sizeof(Window));
for(win_n = 0, c = clients; c; c = c->next, ++win_n) for(win_n = 0, c = clients; c; c = c->next, ++win_n)
list[win_n] = c->win; list[win_n] = c->win;
@@ -203,7 +262,7 @@ ewmh_get_client_list(void)
XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32, XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32,
PropModeReplace, (uchar *)list, win_n); PropModeReplace, (uchar *)list, win_n);
free(list); XFree(list);
return; return;
} }
@@ -214,7 +273,7 @@ void
ewmh_get_desktop_names(void) ewmh_get_desktop_names(void)
{ {
char *str = NULL; char *str = NULL;
int S, s, i, len = 0, pos = 0; int S, s, i = 0, len = 0, pos = 0;
S = screen_count(); S = screen_count();
@@ -222,7 +281,7 @@ ewmh_get_desktop_names(void)
for(i = 1; i < conf.ntag[s] + 1; ++i) for(i = 1; i < conf.ntag[s] + 1; ++i)
len += strlen(tags[s][i].name); len += strlen(tags[s][i].name);
str = emalloc(len + i + 1, sizeof(char*)); str = xcalloc(len + i + 1, sizeof(char*));
for(s = 0; s < S; ++s) for(s = 0; s < S; ++s)
for(i = 1; i < conf.ntag[s] + 1; ++i, ++pos) for(i = 1; i < conf.ntag[s] + 1; ++i, ++pos)
@@ -261,56 +320,25 @@ ewmh_set_desktop_geometry(void)
return; return;
} }
/** Manage _NET_WORKAREA
*/
void
ewmh_set_workarea(void)
{
long *data;
int i, s, j, tag_c = 0, pos = 0;
s = screen_count();
for(i = 0; i < s; ++i)
tag_c += conf.ntag[i];
data = emalloc(tag_c * 4, sizeof(long));
for(i = 0; i < s; ++i)
for(j = 0; j < conf.ntag[i]; ++j)
{
data[pos++] = spgeo[i].x;
data[pos++] = spgeo[i].y;
data[pos++] = spgeo[i].width;
data[pos++] = spgeo[i].height;
}
XChangeProperty(dpy, ROOT, net_atom[net_workarea], XA_CARDINAL, 32,
PropModeReplace, (uchar*)data, 4 * tag_c);
free(data);
return;
}
/** Manage _NET_WM_STATE_* ewmh /** Manage _NET_WM_STATE_* ewmh
*/ */
void void
ewmh_manage_net_wm_state(long data_l[], Client *c) ewmh_manage_net_wm_state(long data_l[], Client *c)
{ {
/* Manage _NET_WM_STATE_FULLSCREEN */ /* Manage _NET_WM_STATE_FULLSCREEN */
if(data_l[1] == net_atom[net_wm_state_fullscreen]) if(data_l[1] == (long)net_atom[net_wm_state_fullscreen])
{ {
if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag)) if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag))
{ {
c->screen = screen_get_with_geo(c->geo.x, c->geo.y); c->screen = screen_get_with_geo(c->geo.x, c->geo.y);
client_unmap(c);
c->flags &= ~UnmapFlag; c->flags &= ~UnmapFlag;
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y); XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y);
XResizeWindow(dpy, c->win, XResizeWindow(dpy, c->win,
spgeo[c->screen].width, spgeo[c->screen].width,
spgeo[c->screen].height); spgeo[c->screen].height);
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32,
PropModeReplace, (uchar *)&net_atom[net_wm_state_fullscreen], 1);
c->tmp_geo = c->geo; c->tmp_geo = c->geo;
@@ -321,20 +349,29 @@ ewmh_manage_net_wm_state(long data_l[], Client *c)
client_raise(c); client_raise(c);
client_focus(c); client_focus(c);
XUnmapWindow(dpy, c->frame);
} }
else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag)) else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag))
{ {
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)0, 0);
c->flags &= ~(FSSFlag | MaxFlag); c->flags &= ~(FSSFlag | MaxFlag);
client_map(c); client_map(c);
XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH); XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH);
client_moveresize(c, c->tmp_geo, False); client_moveresize(c, c->tmp_geo, False);
} }
} }
/* Manage _NET_WM_STATE_STICKY */
else if(data_l[1] == (long)net_atom[net_wm_state_sticky])
{
/* == client_ignore_tag */
c->tag = MAXTAG + 1;
arrange(c->screen, True);
}
/* Manage _NET_WM_STATE_DEMANDS_ATTENTION */ /* Manage _NET_WM_STATE_DEMANDS_ATTENTION */
else if(data_l[1] == net_atom[net_wm_state_demands_attention]) else if(data_l[1] == (long)net_atom[net_wm_state_demands_attention])
{ {
if(data_l[0] == _NET_WM_STATE_ADD) if(data_l[0] == _NET_WM_STATE_ADD)
client_focus(c); client_urgent(c, True);
if(data_l[0] == _NET_WM_STATE_REMOVE) if(data_l[0] == _NET_WM_STATE_REMOVE)
if(c == sel) if(c == sel)
client_focus(NULL); client_focus(NULL);
@@ -351,9 +388,10 @@ void
ewmh_manage_window_type(Client *c) ewmh_manage_window_type(Client *c)
{ {
Atom *atom, rf; Atom *atom, rf;
int i, f; int f;
ulong n, il; ulong n, il, i;
uchar *data = NULL; uchar *data = NULL;
long ldata[5] = { 0 };
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL, if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n) False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
@@ -376,23 +414,36 @@ ewmh_manage_window_type(Client *c)
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y); XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
XRaiseWindow(dpy, c->win); XRaiseWindow(dpy, c->win);
/* This window will not be managed anymore, c->flags |= DockFlag;
* so let's detach it. */
client_detach(c);
} }
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */ /* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
else if(atom[i] == net_atom[net_wm_window_type_dialog]) else if(atom[i] == net_atom[net_wm_window_type_dialog])
{ {
c->flags |= FreeFlag; c->flags |= FreeFlag;
c->flags &= ~(TileFlag | MaxFlag | LMaxFlag); c->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(sel, sel->ogeo, True); client_moveresize(c, c->ogeo, True);
client_focus(c); client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen); layout_func(selscreen, seltag[selscreen]);
} }
} }
XFree(data); XFree(data);
} }
/* Get NET_WM_STATE set without sending client message event */
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_state], 0L, 0x7FFFFFFFL,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
{
atom = (Atom*)data;
for(i = 0; i < n; ++i)
{
ldata[0] = _NET_WM_STATE_ADD;
ldata[1] = atom[i];
ewmh_manage_net_wm_state(ldata, c);
}
XFree(data);
}
return; return;
} }

View File

@@ -83,12 +83,12 @@ frame_create(Client *c)
/* Buttons */ /* Buttons */
if(BUTTONWH >= 1) if(BUTTONWH >= 1)
{ {
c->button = emalloc(conf.titlebar.nbutton, sizeof(Window)); c->button = xcalloc(conf.titlebar.nbutton, sizeof(Window));
for(i = 0; i < conf.titlebar.nbutton; ++i) for(i = 0; i < conf.titlebar.nbutton; ++i)
{ {
CWIN(c->button[i], c->titlebar->win, CWIN(c->button[i], c->titlebar->win,
(c->button_last_x = (BORDH + (BUTTONWH * i) + (4 * i))), (c->button_last_x = (BORDH + (BUTTONWH * i) + (i << 2))),
((BUTTONWH - 1) / 2), BUTTONWH, BUTTONWH, ((BUTTONWH - 1) >> 1), BUTTONWH, BUTTONWH,
1, CWEventMask|CWOverrideRedirect|CWBackPixmap, 1, CWEventMask|CWOverrideRedirect|CWBackPixmap,
c->colors.frame, &at); c->colors.frame, &at);
@@ -118,10 +118,13 @@ frame_create(Client *c)
/* Border (for shadow) */ /* Border (for shadow) */
if(conf.client.border_shadow) if(conf.client.border_shadow)
{ {
CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, color_enlight(c->colors.frame), &at); c->colors.borddark = color_shade(c->colors.frame, conf.colors.client_dark_shade);
CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, color_enlight(c->colors.frame), &at); c->colors.bordlight = color_shade(c->colors.frame, conf.colors.client_light_shade);
CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, SHADC, &at);
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, SHADC, &at); CWIN(c->left, c->frame, 0, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, c->colors.bordlight, &at);
CWIN(c->top, c->frame, 0, 0, c->frame_geo.width, SHADH, 0, CWBackPixel, c->colors.bordlight, &at);
CWIN(c->bottom, c->frame, 0, c->frame_geo.height - SHADH, c->frame_geo.width, SHADH, 0, CWBackPixel, c->colors.borddark, &at);
CWIN(c->right, c->frame, c->frame_geo.width - SHADH, 0, SHADH, c->frame_geo.height, 0, CWBackPixel, c->colors.borddark, &at);
} }
/* Reparent window with the frame */ /* Reparent window with the frame */
@@ -155,7 +158,7 @@ frame_delete(Client *c)
* \param geo Coordinate info for move the frame * \param geo Coordinate info for move the frame
*/ */
void void
frame_moveresize(Client *c, XRectangle geo) frame_moveresize(Client *c, Geo geo)
{ {
CHECK(c); CHECK(c);
@@ -191,6 +194,44 @@ frame_moveresize(Client *c, XRectangle geo)
return; return;
} }
/** Update frame colors for focus event
*\param c Client pointer
*/
void
frame_update_color(Client *c, bool focused)
{
CHECK(c);
/* Not focused client */
if(focused)
{
c->colors.frame = conf.client.bordernormal;
c->colors.fg = conf.titlebar.fg_normal;
c->colors.resizecorner = conf.client.resizecorner_normal;
if(TBARH - BORDH)
c->titlebar->stipple_color = conf.titlebar.stipple.colors.normal;
}
/* Focused */
else
{
c->colors.frame = conf.client.borderfocus;
c->colors.fg = conf.titlebar.fg_focus;
c->colors.resizecorner = conf.client.resizecorner_focus;
if(TBARH - BORDH)
c->titlebar->stipple_color = conf.titlebar.stipple.colors.focus;
}
if(conf.client.border_shadow)
{
c->colors.borddark = color_shade(c->colors.frame, conf.colors.client_dark_shade);
c->colors.bordlight = color_shade(c->colors.frame, conf.colors.client_light_shade);
}
return;
}
/** Update the client frame; Set the new color /** Update the client frame; Set the new color
* and the title --> refresh * and the title --> refresh
* \param c Client pointer * \param c Client pointer
@@ -213,8 +254,8 @@ frame_update(Client *c)
if(conf.titlebar.nbutton && BUTTONWH >= 1) if(conf.titlebar.nbutton && BUTTONWH >= 1)
{ {
if(conf.titlebar.stipple.active) if(conf.titlebar.stipple.active)
draw_rectangle(c->titlebar->dr, 0, 0, c->button_last_x + TBARH - (TBARH / 4), draw_rectangle(c->titlebar->dr, 0, 0, c->button_last_x + TBARH - (TBARH >> 2),
TBARH + BORDH * 2, c->colors.frame); TBARH + (BORDH << 2), c->colors.frame);
for(i = 0; i < conf.titlebar.nbutton; ++i) for(i = 0; i < conf.titlebar.nbutton; ++i)
{ {
@@ -222,8 +263,10 @@ frame_update(Client *c)
XClearWindow(dpy, c->button[i]); XClearWindow(dpy, c->button[i]);
if((!conf.titlebar.button[i].flags) if((!conf.titlebar.button[i].flags)
|| ((conf.titlebar.button[i].flags & FreeFlag) && (c->flags & FreeFlag)) || ((conf.titlebar.button[i].flags & FreeFlag)
|| ((conf.titlebar.button[i].flags & MaxFlag) && (c->flags & MaxFlag)) && ((c->flags & FreeFlag) || !(c->flags & (TileFlag | LMaxFlag))))
|| ((conf.titlebar.button[i].flags & MaxFlag)
&& ((c->flags & MaxFlag) || (c->flags & LMaxFlag)))
|| ((conf.titlebar.button[i].flags & TileFlag) && (c->flags & TileFlag))) || ((conf.titlebar.button[i].flags & TileFlag) && (c->flags & TileFlag)))
{ {
@@ -242,8 +285,6 @@ frame_update(Client *c)
XSetWindowBorder(dpy, c->button[i], c->colors.frame); XSetWindowBorder(dpy, c->button[i], c->colors.frame);
} }
} }
barwin_refresh(c->titlebar);
} }
XSetWindowBackground(dpy, c->frame, c->colors.frame); XSetWindowBackground(dpy, c->frame, c->colors.frame);
@@ -256,10 +297,10 @@ frame_update(Client *c)
if(conf.client.border_shadow) if(conf.client.border_shadow)
{ {
XSetWindowBackground(dpy, c->left, color_enlight(c->colors.frame)); XSetWindowBackground(dpy, c->left, c->colors.bordlight);
XSetWindowBackground(dpy, c->top, color_enlight(c->colors.frame)); XSetWindowBackground(dpy, c->top, c->colors.bordlight);
XSetWindowBackground(dpy, c->right, SHADC); XSetWindowBackground(dpy, c->right, c->colors.borddark);
XSetWindowBackground(dpy, c->bottom, SHADC); XSetWindowBackground(dpy, c->bottom, c->colors.borddark);
XClearWindow(dpy, c->left); XClearWindow(dpy, c->left);
XClearWindow(dpy, c->top); XClearWindow(dpy, c->top);
@@ -269,8 +310,8 @@ frame_update(Client *c)
if(TBARH - BORDH) if(TBARH - BORDH)
barwin_draw_text(c->titlebar, barwin_draw_text(c->titlebar,
(c->frame_geo.width / 2) - (textw(c->title) / 2), (c->frame_geo.width >> 1) - (textw(c->title) >> 1),
((font->height - font->descent) + (TBARH - font->height) / 2), ((font.height - font.de) + ((TBARH - font.height) >> 1)),
c->title); c->title);
return; return;

View File

@@ -1,207 +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)
*/
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 = _strdup((char*)ret);
XFree(ret);
}
if(XGetWindowProperty(dpy, ROOT, ATOM("_WMFS_TAG_LIST"), 0L, 4096,
False, ATOM("UTF8_STRING"), &rt, &rf, &ir, &il, &ret) == Success && ret)
{
tag_list = _strdup((char*)ret);
XFree(ret);
}
printf("Current tag: %d - %s\n", tag, tag_name);
printf("Tag list: %s\n", tag_list);
IFREE(tag_name);
IFREE(tag_list);
return;
}
/** Get information about screens
*/
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
*/
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 = _strdup((char*)ret);
XFree(ret);
}
printf("Current layout: %s\n", layout);
IFREE(layout);
return;
}
/** Get information about current mwfact
*/
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 = _strdup((char*)ret);
XFree(ret);
}
printf("Current mwfact: %s\n", mwfact);
IFREE(mwfact);
return;
}
/** Get information about current nmaster
*/
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)
{
long data[5];
if(!check_wmfs_running())
return;
data[4] = True;
send_client_event(data, "_WMFS_UPDATE_HINTS");
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,7 +32,9 @@
#include "wmfs.h" #include "wmfs.h"
/** Init the Infobar #define SPLIT_IND_S (3 + conf.border.layout)
/** Init the InfoBar
*/ */
void void
infobar_init(void) infobar_init(void)
@@ -42,19 +44,20 @@ infobar_init(void)
s = screen_count(); s = screen_count();
if(!infobar) if(!infobar)
infobar = emalloc(s, sizeof(InfoBar)); infobar = xcalloc(s, sizeof(InfoBar));
for(sc = 0; sc < s; ++sc) for(sc = 0; sc < s; ++sc)
{ {
j = 0; j = 0;
infobar[sc].geo.height = INFOBARH; infobar[sc].geo.height = INFOBARH;
infobar[sc].screen = sc;
switch(tags[sc][seltag[sc]].barpos) switch(tags[sc][seltag[sc]].barpos)
{ {
case IB_Hide: case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH; sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH; sgeo[sc].height += INFOBARH;
infobar[sc].geo.y = -(infobar[sc].geo.height) * 2; infobar[sc].geo.y = (-(infobar[sc].geo.height) << 2);
break; break;
case IB_Bottom: case IB_Bottom:
sgeo[sc].y = TBARH; sgeo[sc].y = TBARH;
@@ -94,8 +97,8 @@ infobar_init(void)
/* Create layout switch barwindow */ /* Create layout switch barwindow */
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, infobar[sc].layout_button = barwin_create(infobar[sc].bar->win,
((conf.layout_placement) ? 0 : (j + PAD / 2)), 0, ((conf.layout_placement) ? 0 : (j + (PAD >> 1))), 0,
textw(tags[sc][seltag[sc]].layout.symbol) + PAD, ((conf.layout_button_width > 0) ? (uint)conf.layout_button_width : (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)),
infobar[sc].geo.height, infobar[sc].geo.height,
conf.colors.layout_bg, conf.colors.layout_fg, conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout); False, False, conf.border.layout);
@@ -104,11 +107,11 @@ infobar_init(void)
if(conf.bars.selbar) if(conf.bars.selbar)
infobar[sc].selbar = barwin_create(infobar[sc].bar->win, infobar[sc].selbar = barwin_create(infobar[sc].bar->win,
((conf.layout_placement) ((conf.layout_placement)
? (j + PAD / 2) ? (j + (PAD >> 1))
: infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + PAD / 2), 1, : infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + (PAD >> 1)), 1,
(sel) ? textw(sel->title) + PAD : 1, (sel) ? textw(sel->title) + PAD : 1,
infobar[sc].geo.height - 2, infobar[sc].geo.height - 2,
conf.colors.bar, conf.colors.text, False, False, False); conf.selbar.bg, conf.selbar.fg, False, False, False);
/* Map/Refresh all */ /* Map/Refresh all */
barwin_map(infobar[sc].bar); barwin_map(infobar[sc].bar);
@@ -127,41 +130,57 @@ infobar_init(void)
barwin_refresh(infobar[sc].bar); barwin_refresh(infobar[sc].bar);
/* Default statustext is set here */ /* Default statustext is set here */
for(i = 0; i < s; ++i) infobar[sc].statustext = xstrdup("wmfs"WMFS_VERSION);
infobar[i].statustext = _strdup(WMFS_VERSION);
infobar_draw(sc); infobar_draw(&infobar[sc]);
} }
return; return;
} }
/** Draw the Infobar /** Draw the layout button in the InfoBar
*\param sc Screen number *\param i InfoBar pointer
*/ */
void void
infobar_draw(int sc) infobar_draw_layout(InfoBar *i)
{ {
infobar_draw_taglist(sc); int w, sc = i->screen;
infobar_draw_layout(sc);
infobar_draw_selbar(sc); if(!conf.layout_placement)
barwin_refresh_color(infobar[sc].bar); barwin_move(i->layout_button, i->tags_board->geo.width + (PAD >> 1), 0);
statustext_handle(sc, infobar[sc].statustext);
w = (conf.layout_button_width > 0)
? conf.layout_button_width
: textw(tags[sc][seltag[sc]].layout.symbol) + PAD;
barwin_resize(i->layout_button, w, i->geo.height);
barwin_refresh_color(i->layout_button);
/* Split mode indicator; little rectangle at bottom-right */
if(tags[sc][seltag[sc]].flags & SplitFlag)
draw_rectangle(i->layout_button->dr,
w - SPLIT_IND_S,
i->geo.height - SPLIT_IND_S,
SPLIT_IND_S, SPLIT_IND_S,
getcolor(i->layout_button->fg));
if(tags[sc][seltag[sc]].layout.symbol)
barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
return; return;
} }
/** Draw the layout button in the InfoBar /** Draw the InfoBar
*\param sc Screen number *\param i InfoBar pointer
*/ */
void void
infobar_draw_layout(int sc) infobar_draw(InfoBar *i)
{ {
barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height); infobar_draw_taglist(i);
barwin_refresh_color(infobar[sc].layout_button); infobar_draw_layout(i);
infobar_draw_selbar(i);
if(tags[sc][seltag[sc]].layout.symbol) barwin_refresh_color(i->bar);
barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol); statustext_handle(i->screen, i->statustext);
return; return;
} }
@@ -170,55 +189,143 @@ infobar_draw_layout(int sc)
*\param sc Screen Number *\param sc Screen Number
*/ */
void void
infobar_draw_selbar(int sc) infobar_draw_selbar(InfoBar *i)
{ {
char *str = NULL;
int s, sc = i->screen;
if(!conf.bars.selbar) if(!conf.bars.selbar)
return; return;
barwin_move(infobar[sc].selbar, if(!sel || (sel && sel->screen != sc))
{
barwin_unmap(i->selbar);
return;
}
else if(sel)
barwin_map(i->selbar);
/* Truncate string if too long */
if(conf.selbar.maxlength >= 0 && sel && sel->title)
{
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, "...");
}
if((s = (textw(str ? str : sel->title) + PAD)) > i->selbar->geo.width)
barwin_resize(i->selbar, s, i->geo.height - 2);
barwin_move(i->selbar,
((conf.layout_placement) ((conf.layout_placement)
? (infobar[sc].tags_board->geo.x + infobar[sc].tags_board->geo.width + PAD / 2) ? (i->tags_board->geo.x + i->tags_board->geo.width + (PAD >> 1))
: (infobar[sc].layout_button->geo.x + infobar[sc].layout_button->geo.width + PAD / 2)), 1); : (i->layout_button->geo.x + i->layout_button->geo.width + (PAD >> 1))), 1);
barwin_resize(infobar[sc].selbar, textw(sel ? sel->title : NULL) + PAD, infobar[sc].geo.height - 2); barwin_refresh_color(i->selbar);
barwin_refresh_color(infobar[sc].selbar); barwin_draw_text(i->selbar, (PAD >> 1), FHINFOBAR - 1, ((str) ? str : sel->title));
barwin_draw_text(infobar[sc].selbar, PAD / 2, FHINFOBAR - 1, (sel) ? sel->title : NULL);
barwin_refresh(infobar[sc].selbar); barwin_refresh(i->selbar);
free(str);
return; return;
} }
/** Draw the taglist in the InfoBar /** Draw the taglist in the InfoBar
*\param sc Screen number *\param i InfoBar pointer
*/ */
void void
infobar_draw_taglist(int sc) infobar_draw_taglist(InfoBar *i)
{ {
int i; int j, x, sc = i->screen;
Client *c; Client *c = NULL;
uint occupied = 0;
if(conf.layout_placement) if(conf.layout_placement)
barwin_move(infobar[sc].tags_board, textw(tags[sc][seltag[sc]].layout.symbol) + PAD * 1.5, 0); barwin_move(i->tags_board,
((conf.layout_button_width > 0)
? (uint)conf.layout_button_width
: (textw(tags[sc][seltag[sc]].layout.symbol) + PAD)) + (PAD >> 1), 0);
for(i = 1; i < conf.ntag[sc] + 1; ++i)
{
infobar[sc].tags[i]->bg = ((i == seltag[sc]) ? conf.colors.tagselbg : conf.colors.bar);
infobar[sc].tags[i]->fg = ((i == seltag[sc]) ? conf.colors.tagselfg : conf.colors.text);
barwin_refresh_color(infobar[sc].tags[i]);
/* Colorize a tag if there are clients in this */
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
{
if(c->screen == sc) if(c->screen == sc)
occupied |= TagFlag(c->tag);
for(j = 1, x = 0; j < conf.ntag[sc] + 1; ++j)
{ {
infobar[sc].tags[c->tag]->bg = ((c->tag == seltag[sc]) ? conf.colors.tagselbg : conf.colors.tag_occupied_bg); /* Autohide tag feature */
barwin_refresh_color(infobar[sc].tags[i]); if(conf.tagautohide)
{
if(!(occupied & TagFlag(j)) && j != seltag[sc])
{
barwin_unmap(i->tags[j]);
continue;
} }
barwin_map(i->tags[j]);
barwin_move(i->tags[j], x, 0);
barwin_resize(i->tags_board, (x += i->tags[j]->geo.width), i->geo.height);
} }
if(tags[sc][i].name)
barwin_draw_text(infobar[sc].tags[i], PAD / 2, FHINFOBAR, tags[sc][i].name); 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);
}
barwin_color_set(i->tags[j], i->tags[j]->bg, i->tags[j]->fg);
barwin_refresh_color(i->tags[j]);
if(tags[sc][j].name)
barwin_draw_text(i->tags[j], (PAD >> 1), FHINFOBAR, tags[sc][j].name);
}
return;
}
/** Update taglist geo
*\param i InfoBar pointer
*/
void
infobar_update_taglist(InfoBar *i)
{
int t, j, sc = i->screen;
for(t = 1, j = 0; t < conf.ntag[sc] + 1; ++t)
{
/* If the tag t does not exist yet (graphically) or need full update */
if(!i->tags[t] || i->need_update)
{
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(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(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);
}
i->need_update = False;
return; return;
} }
@@ -243,6 +350,7 @@ infobar_destroy(void)
barwin_delete_subwin(infobar[sc].tags_board); barwin_delete_subwin(infobar[sc].tags_board);
barwin_delete(infobar[sc].tags_board); barwin_delete(infobar[sc].tags_board);
barwin_delete(infobar[sc].selbar);
barwin_delete_subwin(infobar[sc].bar); barwin_delete_subwin(infobar[sc].bar);
barwin_delete(infobar[sc].bar); barwin_delete(infobar[sc].bar);
} }
@@ -263,7 +371,7 @@ infobar_set_position(int pos)
case IB_Hide: case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH; sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH; sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = -(infobar[selscreen].geo.height) * 2; infobar[selscreen].geo.y = (-(infobar[selscreen].geo.height) << 1);
break; break;
case IB_Bottom: case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH; sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
@@ -281,8 +389,7 @@ infobar_set_position(int pos)
tags[selscreen][seltag[selscreen]].barpos = pos; tags[selscreen][seltag[selscreen]].barpos = pos;
barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y); barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
infobar_draw(selscreen); infobar_draw(&infobar[selscreen]);
ewmh_set_workarea();
arrange(selscreen, True); arrange(selscreen, True);
return; return;
@@ -294,6 +401,7 @@ infobar_set_position(int pos)
void void
uicb_infobar_togglepos(uicb_t cmd) uicb_infobar_togglepos(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
infobar_set_position((tags[selscreen][seltag[selscreen]].barpos infobar_set_position((tags[selscreen][seltag[selscreen]].barpos
@@ -303,3 +411,54 @@ uicb_infobar_togglepos(uicb_t cmd)
return; return;
} }
/** Toggle hide/display infobar
* \param cmd uicb_t type unused
*/
void
uicb_infobar_toggledisplay(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
int new_pos;
new_pos = (tags[selscreen][seltag[selscreen]].barpos
? 0 : (tags[selscreen][seltag[selscreen]].prev_barpos
? tags[selscreen][seltag[selscreen]].prev_barpos : 2));
tags[selscreen][seltag[selscreen]].prev_barpos = tags[selscreen][seltag[selscreen]].barpos;
tags[selscreen][seltag[selscreen]].barpos = new_pos;
infobar_set_position(new_pos);
return;
}
/** Toggle the tag_autohide mode
* \param cmd uicb_t type unused
*/
void
uicb_toggle_tagautohide(uicb_t cmd)
{
int i, x;
(void)cmd;
screen_get_sel();
conf.tagautohide = !conf.tagautohide;
if(!conf.tagautohide)
{
for(i = 1, x = 0; i < conf.ntag[selscreen] + 1; ++i)
{
barwin_map(infobar[selscreen].tags[i]);
barwin_move(infobar[selscreen].tags[i], x, 0);
x += infobar[selscreen].tags[i]->geo.width;
}
barwin_resize(infobar[selscreen].tags_board, x, infobar[selscreen].geo.height);
}
infobar_draw(&infobar[selscreen]);
return;
}

View File

@@ -40,13 +40,14 @@ const func_name_list_t layout_list[] =
{"tile_left", tile_left }, {"tile_left", tile_left },
{"tile_top", tile_top }, {"tile_top", tile_top },
{"tile_bottom", tile_bottom }, {"tile_bottom", tile_bottom },
{"tile_grid", grid }, {"tile_grid", grid_horizontal },
{"grid", grid }, {"tile_grid_horizontal", grid_horizontal },
{"tile_grid_vertical", grid_vertical },
{"grid", grid_horizontal },
{"mirror_vertical", mirror_vertical }, {"mirror_vertical", mirror_vertical },
{"tile_mirror_vertical", mirror_vertical }, {"tile_mirror_vertical", mirror_vertical },
{"mirror_horizontal", mirror_horizontal }, {"mirror_horizontal", mirror_horizontal },
{"tile_mirror_horizontal", mirror_horizontal }, {"tile_mirror_horizontal", mirror_horizontal },
{"layer", layer },
{"max", maxlayout }, {"max", maxlayout },
{"maxlayout", maxlayout }, {"maxlayout", maxlayout },
{"freelayout", freelayout }, {"freelayout", freelayout },
@@ -54,47 +55,67 @@ const func_name_list_t layout_list[] =
{ NULL, NULL } { NULL, NULL }
}; };
/** Init WMFS
*/
void
init(void)
{
/* First init */
ewmh_init_hints();
init_conf();
init_gc();
init_font();
init_cursor();
init_key();
init_root();
screen_init_geo();
infobar_init();
init_status();
ewmh_update_current_tag_prop();
grabkeys();
return;
}
/** Init the font /** Init the font
*/ */
void static void
init_font(void) init_font(void)
{ {
font = XftFontOpenName(dpy, SCREEN, conf.font); #ifdef HAVE_XFT
if(conf.use_xft)
if(!font)
{ {
warnx("WMFS Error: Cannot initialize font"); if(!(font.font = XftFontOpenName(dpy, SCREEN, conf.font)))
font = XftFontOpenName(dpy, SCREEN, "sans-10"); {
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 */
XChangeProperty(dpy, ROOT, net_atom[wmfs_font], net_atom[utf8_string], 8,
PropModeReplace, (uchar*)conf.font, strlen(conf.font));
return; return;
} }
/** Init the graphic context /** Init the graphic context
*/ */
void static void
init_gc(void) init_gc(void)
{ {
XGCValues gcv; XGCValues gcv;
@@ -121,7 +142,7 @@ init_gc(void)
/** Init WMFS cursor /** Init WMFS cursor
*/ */
void static void
init_cursor(void) init_cursor(void)
{ {
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
@@ -135,7 +156,7 @@ init_cursor(void)
/** Init key modifier /** Init key modifier
*/ */
void static void
init_key(void) init_key(void)
{ {
int i, j; int i, j;
@@ -154,7 +175,7 @@ init_key(void)
/** Init root Window /** Init root Window
*/ */
void static void
init_root(void) init_root(void)
{ {
XSetWindowAttributes at; XSetWindowAttributes at;
@@ -177,47 +198,61 @@ init_root(void)
/** Init statustext shell script /** Init statustext shell script
*/ */
void static void
init_status(void) init_status(void)
{ {
int fd;
struct stat st; struct stat st;
char *home; char *home;
conf.status_pid = -1;
estatus = False;
if(!conf.status_path) if(!conf.status_path)
{ {
if(!(home = getenv("HOME"))) if(!(home = getenv("HOME")))
{ {
warnx("HOME not set, can't launch status.sh"); warnx("HOME not set, can't launch status.sh");
estatus = False;
return; return;
} }
conf.status_path = emalloc(strlen(home) + strlen(DEF_STATUS) + 2, sizeof(char)); conf.status_path = zmalloc(strlen(home) + strlen(DEF_STATUS) + 2);
sprintf(conf.status_path, "%s/"DEF_STATUS, home); sprintf(conf.status_path, "%s/"DEF_STATUS, home);
} }
if(!(fd = open(conf.status_path, O_RDONLY)) if (stat(patht(conf.status_path), &st) == -1)
|| !fopen(conf.status_path, "r"))
{ {
free(conf.status_path); warn("%s", patht(conf.status_path));
estatus = False;
return; return;
} }
stat(conf.status_path, &st);
if(st.st_size && st.st_mode & S_IXUSR) if(st.st_size && st.st_mode & S_IXUSR)
{
estatus = True; estatus = True;
spawn(conf.status_path);
}
else else
warnx("status file specified in configuratin (status_path) or present in wmfs directory can't be executed, try 'chmod +x %s'.", conf.status_path); 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));
close(fd); return;
}
/** Init WMFS
*/
void
init(void)
{
/* First init */
ewmh_init_hints();
init_conf();
init_gc();
init_font();
init_cursor();
init_key();
init_root();
screen_init_geo();
event_make_array();
infobar_init();
systray_acquire();
init_status();
ewmh_update_current_tag_prop();
grabkeys();
return; return;
} }

View File

@@ -30,178 +30,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* conforming to glib use _GNU_SOURCE for asprintf declaration */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "wmfs.h" #include "wmfs.h"
static char *complete_on_command(char*, size_t);
static char *complete_on_files(char*, size_t);
void
launcher_execute(Launcher launcher)
{
BarWindow *bw;
Bool found;
Bool lastwastab = False;
Bool my_guitar_gently_wheeps = True;
char tmp[32] = { 0 };
char buf[512] = { 0 };
char tmpbuf[512] = { 0 };
char *complete;
int pos = 0, x;
int tabhits = 0;
KeySym ks;
XEvent ev;
screen_get_sel();
x = (infobar[selscreen].layout_button->geo.x
+ textw(tags[selscreen][seltag[selscreen]].layout.symbol) + PAD);
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
bw = barwin_create(infobar[selscreen].bar->win, x, 1,
infobar[selscreen].bar->geo.width - x - 1,
infobar[selscreen].bar->geo.height - 2,
infobar[selscreen].bar->bg,
infobar[selscreen].bar->fg,
False, False, conf.border.bar);
barwin_map(bw);
barwin_refresh_color(bw);
/* First draw of the cursor */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc, textw(launcher.prompt) + textw(" "),
2, textw(launcher.prompt) + textw(" "), INFOBARH - 4);
barwin_refresh(bw);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
while(my_guitar_gently_wheeps)
{
if(ev.type == KeyPress)
{
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
/* Check Ctrl-c / Ctrl-d */
if(ev.xkey.state & ControlMask)
if(ks == XK_c || ks == XK_d)
ks = XK_Escape;
/* Check if there is a keypad */
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
ks = XK_Return;
switch(ks)
{
case XK_Return:
spawn("%s %s", launcher.command, buf);
my_guitar_gently_wheeps = 0;
break;
case XK_Escape:
my_guitar_gently_wheeps = 0;
break;
case XK_Tab:
/*
* completion
* if there is not space in buffer we
* complete the command using complete_on_command.
* Else we try to complete on filename using
* complete_on_files.
*/
buf[pos] = '\0';
if (lastwastab)
tabhits++;
else
{
tabhits = 1;
strcpy(tmpbuf, buf);
}
if (pos)
{
if (strchr(tmpbuf, ' '))
complete = complete_on_files(tmpbuf, tabhits);
else
complete = complete_on_command(tmpbuf, tabhits);
if (complete)
{
strcpy(buf, tmpbuf);
strncat(buf, complete, sizeof(buf));
found = True;
free(complete);
}
}
lastwastab = True;
/* start a new round of tabbing */
if (!found)
tabhits = 0;
pos = strlen(buf);
break;
case XK_BackSpace:
lastwastab = False;
if(pos)
buf[--pos] = 0;
break;
default:
lastwastab = False;
strncat(buf, tmp, sizeof(buf));
++pos;
break;
}
barwin_refresh_color(bw);
/* Update cursor position */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc,
1 + textw(launcher.prompt) + textw(" ") + textw(buf), 2,
1 + textw(launcher.prompt) + textw(" ") + textw(buf), INFOBARH - 4);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
barwin_draw_text(bw, 1 + textw(launcher.prompt) + textw(" "), FHINFOBAR - 1, buf);
barwin_refresh(bw);
}
else
getevent(ev);
XNextEvent(dpy, &ev);
}
barwin_unmap(bw);
barwin_delete(bw);
infobar_draw(selscreen);
XUngrabKeyboard(dpy, CurrentTime);
return;
}
void
uicb_launcher(uicb_t cmd)
{
int i;
for(i = 0; i < conf.nlauncher; ++i)
if(!strcmp(cmd, conf.launcher[i].name))
launcher_execute(conf.launcher[i]);
return;
}
/* /*
* Just search command in PATH. * Just search command in PATH.
* Return the characters to complete the command. * Return the characters to complete the command.
@@ -214,36 +44,50 @@ complete_on_command(char *start, size_t hits)
char *ret = NULL; char *ret = NULL;
DIR *dir; DIR *dir;
struct dirent *content; struct dirent *content;
size_t count = 0;
char **namelist = NULL;
int n = 0, i;
if (!getenv("PATH") || !start || hits <= 0) if (!getenv("PATH") || !start || hits <= 0)
return NULL; return NULL;
path = _strdup(getenv("PATH")); path = xstrdup(getenv("PATH"));
dirname = strtok(path, ":"); dirname = strtok(path, ":");
/* recursively open PATH */ /* recursively open PATH */
while (dirname) while (dirname != NULL)
{ {
if ((dir = opendir(dirname))) if ((dir = opendir(dirname)))
{ {
while ((content = readdir(dir))) while ((content = readdir(dir)))
if (!strncmp(content->d_name, start, strlen(start)) && ++count == hits)
{ {
ret = _strdup(content->d_name + strlen(start)); if(strncmp(content->d_name, ".", 1))
break; {
if (!strncmp(content->d_name, start, strlen(start)))
{
namelist = xrealloc(namelist, ++n, sizeof(*namelist));
namelist[n-1] = xstrdup(content->d_name);
}
}
} }
closedir(dir); closedir(dir);
} }
if (ret)
break;
dirname = strtok(NULL, ":"); dirname = strtok(NULL, ":");
} }
free(path); free(path);
if(n > 0)
{
qsort(namelist, n, sizeof(char *), qsort_string_compare);
ret = xstrdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start));
for(i = 0; i < n; i++)
free(namelist[i]);
free(namelist);
}
return ret; return ret;
} }
@@ -272,14 +116,14 @@ complete_on_files(char *start, size_t hits)
* the beginning of file to complete on pointer 'p'. * the beginning of file to complete on pointer 'p'.
*/ */
if (*(++p) == '\0' || !strrchr(p, '/')) if (*(++p) == '\0' || !strrchr(p, '/'))
path = _strdup("."); path = xstrdup(".");
else else
{ {
/* remplace ~ by $HOME in dirname */ /* remplace ~ by $HOME in dirname */
if (!strncmp(p, "~/", 2) && getenv("HOME")) if (!strncmp(p, "~/", 2) && getenv("HOME"))
asprintf(&dirname, "%s%s", getenv("HOME"), p+1); xasprintf(&dirname, "%s%s", getenv("HOME"), p+1);
else else
dirname = _strdup(p); dirname = xstrdup(p);
/* Set p to filename to be complete /* Set p to filename to be complete
* and path the directory containing the file * and path the directory containing the file
@@ -290,11 +134,11 @@ complete_on_files(char *start, size_t hits)
if (p != dirname) if (p != dirname)
{ {
*(p++) = '\0'; *(p++) = '\0';
path = _strdup(dirname); path = xstrdup(dirname);
} }
else else
{ {
path = _strdup("/"); path = xstrdup("/");
p++; p++;
} }
} }
@@ -308,19 +152,19 @@ complete_on_files(char *start, size_t hits)
if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits) if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits)
{ {
/* If it's a directory append '/' to the completion */ /* If it's a directory append '/' to the completion */
asprintf(&filepath, "%s/%s", path, content->d_name); xasprintf(&filepath, "%s/%s", path, content->d_name);
if (filepath && stat(filepath, &st) != -1) if (filepath && stat(filepath, &st) != -1)
{ {
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
asprintf(&ret, "%s/", content->d_name + strlen(p)); xasprintf(&ret, "%s/", content->d_name + strlen(p));
else else
ret = _strdup(content->d_name + strlen(p)); ret = xstrdup(content->d_name + strlen(p));
} }
else else
warn("%s", filepath); warn("%s", filepath);
IFREE(filepath); free(filepath);
break; break;
} }
@@ -328,8 +172,212 @@ complete_on_files(char *start, size_t hits)
closedir(dir); closedir(dir);
} }
IFREE(dirname); free(dirname);
IFREE(path); free(path);
return ret; return ret;
} }
static void
launcher_execute(Launcher *launcher)
{
BarWindow *bw;
bool found;
bool lastwastab = False;
bool my_guitar_gently_wheeps = True;
char tmp[32] = { 0 };
char buf[512] = { 0 };
char tmpbuf[512] = { 0 };
char *complete;
int i, pos = 0, histpos = 0, x, w;
int tabhits = 0;
KeySym ks;
XEvent ev;
screen_get_sel();
x = (conf.layout_placement)
? (infobar[selscreen].tags_board->geo.x + infobar[selscreen].tags_board->geo.width)
: (infobar[selscreen].layout_button->geo.x + infobar[selscreen].layout_button->geo.width);
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
w = (launcher->width ? launcher->width : infobar[selscreen].bar->geo.width - x - 1);
bw = barwin_create(infobar[selscreen].bar->win, x, 1, w,
/* infobar[selscreen].bar->geo.width - x - 1, */
infobar[selscreen].bar->geo.height - 2,
infobar[selscreen].bar->bg,
infobar[selscreen].bar->fg,
False, False, conf.border.bar);
barwin_map(bw);
barwin_refresh_color(bw);
/* First draw of the cursor */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc,
1 + textw(launcher->prompt) + textw(" ") + textw(buf), 2,
1 + textw(launcher->prompt) + textw(" ") + textw(buf), INFOBARH - 4);
barwin_refresh(bw);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher->prompt);
while(my_guitar_gently_wheeps)
{
if(ev.type == KeyPress)
{
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
/* Check Ctrl-c / Ctrl-d */
if(ev.xkey.state & ControlMask)
{
if(ks == XK_c || ks == XK_d)
ks = XK_Escape;
else if(ks == XK_p)
ks = XK_Up;
else if(ks == XK_n)
ks = XK_Down;
}
/* Check if there is a keypad */
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
ks = XK_Return;
switch(ks)
{
case XK_Up:
if(launcher->nhisto)
{
if(histpos >= (int)launcher->nhisto)
histpos = 0;
strncpy(buf, launcher->histo[launcher->nhisto - ++histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Down:
if(launcher->nhisto && histpos > 0 && histpos < (int)launcher->nhisto)
{
strncpy(buf, launcher->histo[launcher->nhisto - --histpos], sizeof(buf));
pos = strlen(buf);
}
break;
case XK_Return:
spawn("%s %s", launcher->command, buf);
/* Histo */
if(launcher->nhisto + 1 > HISTOLEN)
{
for(i = launcher->nhisto - 1; i > 1; --i)
strncpy(launcher->histo[i], launcher->histo[i - 1], sizeof(launcher->histo[i]));
launcher->nhisto = 0;
}
/* Store in histo array */
strncpy(launcher->histo[launcher->nhisto++], buf, sizeof(buf));
my_guitar_gently_wheeps = 0;
break;
case XK_Escape:
my_guitar_gently_wheeps = 0;
break;
case XK_Tab:
/*
* completion
* if there is not space in buffer we
* complete the command using complete_on_command.
* Else we try to complete on filename using
* complete_on_files.
*/
buf[pos] = '\0';
if (lastwastab)
tabhits++;
else
{
tabhits = 1;
strncpy(tmpbuf, buf, sizeof(tmpbuf));
}
if (pos)
{
if (strchr(tmpbuf, ' '))
complete = complete_on_files(tmpbuf, tabhits);
else
complete = complete_on_command(tmpbuf, tabhits);
if (complete)
{
strncpy(buf, tmpbuf, sizeof(buf));
strncat(buf, complete, sizeof(buf));
found = True;
free(complete);
}
}
lastwastab = True;
/* start a new round of tabbing */
if (found == False)
tabhits = 0;
pos = strlen(buf);
break;
case XK_BackSpace:
lastwastab = False;
if(pos)
buf[--pos] = 0;
break;
default:
lastwastab = False;
strncat(buf, tmp, sizeof(tmp));
++pos;
break;
}
barwin_refresh_color(bw);
/* Update cursor position */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc,
1 + textw(launcher->prompt) + textw(" ") + textw(buf), 2,
1 + textw(launcher->prompt) + textw(" ") + textw(buf), INFOBARH - 4);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher->prompt);
barwin_draw_text(bw, 1 + textw(launcher->prompt) + textw(" "), FHINFOBAR - 1, buf);
barwin_refresh(bw);
}
else if(ev.type < nevent && ev.type > 0)
HANDLE_EVENT(&ev);
XNextEvent(dpy, &ev);
}
barwin_unmap(bw);
barwin_delete(bw);
infobar_draw(&infobar[selscreen]);
XUngrabKeyboard(dpy, CurrentTime);
return;
}
void
uicb_launcher(uicb_t cmd)
{
int i;
for(i = 0; i < conf.nlauncher; ++i)
if(!strcmp(cmd, conf.launcher[i].name))
launcher_execute(&conf.launcher[i]);
return;
}

View File

@@ -35,11 +35,11 @@
/** Arrange All /** Arrange All
*/ */
void void
arrange(int screen, Bool update_layout) arrange(int screen, bool update_layout)
{ {
Client *c; Client *c;
if(screen < 0 || screen > screen_count()) if(screen < 0 || screen > screen_count() - 1)
screen = screen_get_sel(); screen = screen_get_sel();
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
@@ -51,10 +51,30 @@ arrange(int screen, Bool update_layout)
client_hide(c); client_hide(c);
} }
if(tags[screen][seltag[screen]].layout.func)
{
if(update_layout) 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; return;
} }
@@ -65,10 +85,11 @@ void
freelayout(int screen) freelayout(int screen)
{ {
Client *c; Client *c;
(void)screen;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
if(!ishide(c, selscreen) if(!ishide(c, selscreen)
&& c->screen == screen_get_sel() && c->screen == screen
&& !(c->flags & MaxFlag)) && !(c->flags & MaxFlag))
{ {
client_moveresize(c, c->free_geo, True); client_moveresize(c, c->free_geo, True);
@@ -81,10 +102,10 @@ freelayout(int screen)
} }
/** Layout switching function /** Layout switching function
* \param b Bool True : next False : previous * \param b bool True : next False : previous
*/ */
void void
layoutswitch(Bool b) layoutswitch(bool b)
{ {
int i; int i;
Client *c; Client *c;
@@ -92,7 +113,7 @@ layoutswitch(Bool b)
screen_get_sel(); screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layout.func == freelayout) if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
for(c = clients; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = c->next) for(c = clients; c && (c->tag != (uint)seltag[selscreen] && c->screen != selscreen); c = c->next)
{ {
c->ogeo = c->geo; c->ogeo = c->geo;
c->free_geo = c->geo; c->free_geo = c->geo;
@@ -112,8 +133,10 @@ layoutswitch(Bool b)
} }
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
tags[selscreen][seltag[selscreen]].layout.func(selscreen); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
infobar_draw(selscreen); tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
layout_func(selscreen, seltag[selscreen]);
infobar_draw_layout(&infobar[selscreen]);
return; return;
} }
@@ -124,6 +147,7 @@ layoutswitch(Bool b)
void void
uicb_layout_next(uicb_t cmd) uicb_layout_next(uicb_t cmd)
{ {
(void)cmd;
layoutswitch(True); layoutswitch(True);
return; return;
@@ -135,11 +159,30 @@ uicb_layout_next(uicb_t cmd)
void void
uicb_layout_prev(uicb_t cmd) uicb_layout_prev(uicb_t cmd)
{ {
(void)cmd;
layoutswitch(False); layoutswitch(False);
return; return;
} }
/** Sort all the client that can be
* tiled
* \param c Client pointer
* \return a client pointer
*/
Client*
tiled_client(int screen, Client *c)
{
for(;c && (c->flags & (MaxFlag | FreeFlag | FSSFlag | AboveFlag)
|| c->screen != screen
|| ishide(c, screen)); c = c->next);
if(c)
c->flags |= FLayFlag;
return c;
}
/** Max layout function /** Max layout function
*/ */
void void
@@ -160,24 +203,6 @@ maxlayout(int screen)
return; return;
} }
/** Sort all the client that can be
* tiled
* \param c Client pointer
* \return a client pointer
*/
Client*
tiled_client(int screen, Client *c)
{
for(;c && ((c->flags & MaxFlag)
|| (c->flags & FreeFlag)
|| (c->flags & FSSFlag)
|| (c->flags & AboveFlag)
|| c->screen != screen
|| ishide(c, screen)); c = c->next);
return c;
}
/** Set the mwfact /** Set the mwfact
* \param cmd Mwfact (string) * \param cmd Mwfact (string)
*/ */
@@ -195,7 +220,7 @@ uicb_set_mwfact(uicb_t cmd)
return; return;
tags[selscreen][seltag[selscreen]].mwfact += c; tags[selscreen][seltag[selscreen]].mwfact += c;
tags[selscreen][seltag[selscreen]].layout.func(selscreen); layout_func(selscreen, seltag[selscreen]);
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
@@ -220,64 +245,28 @@ uicb_set_nmaster(uicb_t cmd)
return; return;
tags[selscreen][seltag[selscreen]].nmaster += n; 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(); ewmh_update_current_tag_prop();
return; return;
} }
void
uicb_set_client_layer(uicb_t cmd)
{
int n = atoi(cmd);
screen_get_sel();
CHECK(sel);
if(sel->layer + n < 1
|| sel->layer + n > tags[selscreen][seltag[selscreen]].layers)
return;
sel->layer += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;
}
void
uicb_set_layer(uicb_t cmd)
{
int n = atoi(cmd);
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layers + n < 1)
return;
tags[selscreen][seltag[selscreen]].layers += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;
}
/** Grid layout function /** Grid layout function
*/ */
void static void
grid(int screen) grid(int screen, bool horizontal)
{ {
Client *c; Client *c;
XRectangle sg = sgeo[screen]; Geo sg = sgeo[screen];
XRectangle cgeo = {sg.x, sg.y, 0, 0}; Geo cgeo = {sg.x, sg.y, 0, 0};
unsigned int i, n, cols, rows, cpcols = 0; unsigned int i, n, temp, cols, rows, cpcols = 0;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(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) if(rows * rows >= n)
break; break;
@@ -285,13 +274,23 @@ grid(int screen)
? rows - 1 ? rows - 1
: rows; : rows;
if(!horizontal)
{
temp = cols;
cols = rows;
rows = temp;
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i) for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
{ {
/* Set client property */ /* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag; c->flags |= TileFlag;
++cpcols; ++cpcols;
cgeo.width = (sg.width / cols) - (BORDH * 2);
cfactor_clean(c);
cgeo.width = (sg.width / cols) - (BORDH << 1);
cgeo.height = (sg.height / rows) - BORDH; cgeo.height = (sg.height / rows) - BORDH;
/* Last row's and last client remainder */ /* Last row's and last client remainder */
@@ -300,22 +299,23 @@ grid(int screen)
/* Last column's client remainder */ /* Last column's client remainder */
if(i >= rows * (cols - 1)) 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 */ /* 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 */ /* 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) if(cpcols + 1 > rows)
{ {
cpcols = 0; 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; cgeo.y = sg.y;
} }
} }
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
return; return;
@@ -324,17 +324,17 @@ grid(int screen)
/** Multi tile function /** Multi tile function
* \param type Postion type { Top, Bottom, Left, Right } * \param type Postion type { Top, Bottom, Left, Right }
*/ */
void static void
multi_tile(int screen, Position type) multi_tile(int screen, Position type)
{ {
Client *c; Client *c;
XRectangle sg = sgeo[screen]; Geo sg = sgeo[screen];
XRectangle mastergeo = {sg.x, sg.y, 0, 0}; Geo mastergeo = {sg.x, sg.y, 0, 0};
XRectangle cgeo = {sg.x, sg.y, 0, 0}; Geo cgeo = {sg.x, sg.y, 0, 0};
uint i, n, tilesize, mwfact, nmaster = tags[screen][seltag[screen]].nmaster; uint i, n, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n); for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n); CHECK((tags[screen][seltag[screen]].nclients = n));
/* FIX NMASTER */ /* FIX NMASTER */
nmaster = (n < nmaster) ? n : nmaster; nmaster = (n < nmaster) ? n : nmaster;
@@ -345,28 +345,27 @@ multi_tile(int screen, Position type)
: tags[screen][seltag[screen]].mwfact * sg.width; : tags[screen][seltag[screen]].mwfact * sg.width;
/* MASTER SIZE */ /* MASTER SIZE */
if(type == Top || type == Bottom) if(LDIR(type))
{ {
if(type == Top) if(type == Left)
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH; mastergeo.x = (n <= nmaster) ? (uint)sg.x : (sg.x + sg.width) - mwfact - (BORDH << 1);
mastergeo.width = (sg.width / nmaster) - (BORDH * 4); mastergeo.width = (n <= nmaster) ? (uint)(sg.width - (BORDH << 1)) : mwfact;
mastergeo.height = (n <= nmaster) ? sg.height - BORDH : mwfact; mastergeo.height = (sg.height / nmaster) - BORDH;
} }
else else
{ {
if(type == Left) if(type == Top)
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2); mastergeo.y = (n <= nmaster) ? (uint)sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (n <= nmaster) ? sg.width - (BORDH * 2) : mwfact; mastergeo.width = (sg.width / nmaster) - (BORDH << 2);
mastergeo.height = (sg.height / nmaster) - BORDH; mastergeo.height = (n <= nmaster) ? (uint)(sg.height - BORDH) : mwfact;
} }
/* TILED SIZE */ /* TILED SIZE */
if(n > nmaster) if(n > nmaster)
{ {
if(type == Top || type == Bottom) if(LDIR(type))
tilesize = sg.width / (n - nmaster) - (BORDH * 4); tilesize = sg.height / (n - nmaster) - ((BORDH << 1) + TBARH);
else else
tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH); tilesize = sg.width / (n - nmaster) - (BORDH << 2);
} }
@@ -376,19 +375,21 @@ multi_tile(int screen, Position type)
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag; c->flags |= TileFlag;
cfactor_clean(c);
/* MASTER */ /* MASTER */
if(i < nmaster) if(i < nmaster)
{ {
cgeo.width = mastergeo.width; cgeo.width = mastergeo.width;
cgeo.height = mastergeo.height; cgeo.height = mastergeo.height;
if(type == Top || type == Bottom) if(LDIR(type))
cgeo.y = mastergeo.y;
else
{ {
cgeo.x = mastergeo.x; cgeo.x = mastergeo.x;
cgeo.height -= (TBARH + BORDH); cgeo.height -= (TBARH + BORDH);
} }
else
cgeo.y = mastergeo.y;
} }
/* TILED */ /* TILED */
@@ -409,42 +410,43 @@ multi_tile(int screen, Position type)
break; break;
default: default:
case Right: case Right:
cgeo.x += mastergeo.width + (BORDH * 2); cgeo.x += mastergeo.width + (BORDH << 1);
cgeo.y = sg.y; cgeo.y = sg.y;
break; break;
} }
} }
if(type == Top || type == Bottom) if(LDIR(type))
{ {
cgeo.width = tilesize; cgeo.width = sg.width - mastergeo.width - (BORDH << 2);
cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2); cgeo.height = tilesize;
} }
else else
{ {
cgeo.width = sg.width - mastergeo.width - (BORDH * 4); cgeo.width = tilesize;
cgeo.height = tilesize; cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH << 1);
} }
} }
/* REMAINDER */ /* 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) if(LDIR(type))
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
else
cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH; cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH;
else
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH << 1)));
} }
/* Magic instant */ /* 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 */ /* Set the position of the next client */
if(type == Top || type == Bottom) if(LDIR(type))
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2); cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
else 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(); ewmh_update_current_tag_prop();
return; return;
@@ -454,27 +456,29 @@ multi_tile(int screen, Position type)
* \param screen Screen to execute this function * \param screen Screen to execute this function
* \param horizont To specify the mirror mode (vertical/horizontal) * \param horizont To specify the mirror mode (vertical/horizontal)
*/ */
void static void
mirror(int screen, Bool horizontal) mirror(int screen, bool horizontal)
{ {
Client *c; Client *c;
XRectangle sg = sgeo[screen]; Geo sg = sgeo[screen];
XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height}; Geo mastergeo = {sg.x, sg.y, sg.width, sg.height};
XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height}; Geo cgeo = {sg.x, sg.y , sg.width, sg.height};
XRectangle nextg[2] = { {0} }; Geo nextg[2];
uint i, n, tilesize, mwfact; uint i, n, tilesize = 0, mwfact;
uint nmaster = tags[screen][seltag[screen]].nmaster; uint nmaster = tags[screen][seltag[screen]].nmaster;
int pa, imp; 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); for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n); CHECK((tags[screen][seltag[screen]].nclients = n));
/* Fix nmaster */ /* Fix nmaster */
nmaster = (n < nmaster) ? n : nmaster; nmaster = (n < nmaster) ? n : nmaster;
imp = ((n - (nmaster - 1)) / 2); imp = ((n - (nmaster - 1)) >> 1);
pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1); pa = ((n - (nmaster - 1)) >> 1) - (((n - (nmaster - 1)) & 1) ? 0 : 1);
/* Set mwfact */ /* Set mwfact */
if(tags[screen][seltag[screen]].mwfact < 0.55) if(tags[screen][seltag[screen]].mwfact < 0.55)
@@ -485,26 +489,26 @@ mirror(int screen, Bool horizontal)
/* Master size */ /* Master size */
if(horizontal) if(horizontal)
{ {
mastergeo.width = (sg.width / nmaster) - (BORDH * 2); mastergeo.width = (sg.width / nmaster) - (BORDH << 1);
mastergeo.height -= BORDH; mastergeo.height -= BORDH;
} }
else else
{ {
mastergeo.width -= BORDH * 2; mastergeo.width -= (BORDH << 1);
mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2)); mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH << 1));
} }
if(n == nmaster + 1) if(n == nmaster + 1)
{ {
if(horizontal) if(horizontal)
{ {
mastergeo.height = mwfact - ((BORDH * 2) + TBARH); mastergeo.height = mwfact - ((BORDH << 1) + TBARH);
tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH); tilesize = (sg.height - mastergeo.height) - ((BORDH << 1) + TBARH);
} }
else else
{ {
mastergeo.width = mwfact - (BORDH * 3); mastergeo.width = mwfact - (BORDH * 3);
tilesize = (sg.width - mastergeo.width) - (BORDH * 4); tilesize = (sg.width - mastergeo.width) - (BORDH << 2);
} }
} }
if(n > nmaster + 1) if(n > nmaster + 1)
@@ -512,13 +516,13 @@ mirror(int screen, Bool horizontal)
if(horizontal) if(horizontal)
{ {
mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH; mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH;
mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2)); mastergeo.height = ((mwfact << 1) - sg.height) - ((BORDH * 3) + (TBARH << 1));
tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2)); tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH << 1));
} }
else else
{ {
mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH; 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); tilesize = (mwfact - mastergeo.width) - (BORDH * 5);
} }
} }
@@ -529,6 +533,8 @@ mirror(int screen, Bool horizontal)
c->flags &= ~(MaxFlag | LMaxFlag); c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag; c->flags |= TileFlag;
cfactor_clean(c);
if(i < nmaster) if(i < nmaster)
{ {
cgeo = mastergeo; cgeo = mastergeo;
@@ -537,7 +543,7 @@ mirror(int screen, Bool horizontal)
if(i + 1 == nmaster) if(i + 1 == nmaster)
{ {
if(horizontal) if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
} }
@@ -549,19 +555,19 @@ mirror(int screen, Bool horizontal)
else else
cgeo.width = tilesize; cgeo.width = tilesize;
if((i + nmaster) % 2) if((i + nmaster) & 1)
{ {
isp = 1; isp = 1;
if(horizontal) if(horizontal)
{ {
cgeo.y = sg.y; cgeo.y = sg.y;
cgeo.width = (sg.width / pa) - (BORDH * 2); cgeo.width = (sg.width / pa) - (BORDH << 1);
} }
else else
{ {
cgeo.x = sg.x; cgeo.x = sg.x;
cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2)); cgeo.height = (sg.height / pa) - (TBARH + (BORDH << 1));
} }
} }
else else
@@ -571,12 +577,12 @@ mirror(int screen, Bool horizontal)
if(horizontal) if(horizontal)
{ {
cgeo.y = (sg.y + mwfact) - BORDH; cgeo.y = (sg.y + mwfact) - BORDH;
cgeo.width = (sg.width / imp) - (BORDH * 2); cgeo.width = (sg.width / imp) - (BORDH << 1);
} }
else else
{ {
cgeo.x = (sg.x + mwfact) - BORDH; cgeo.x = (sg.x + mwfact) - BORDH;
cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2)); cgeo.height = (sg.height / imp) - (TBARH + (BORDH << 1));
} }
} }
@@ -584,16 +590,16 @@ mirror(int screen, Bool horizontal)
if(i + 1 == n || i + 1 == n - 1) if(i + 1 == n || i + 1 == n - 1)
{ {
if(horizontal) if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2)); cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH); 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) if(i >= nmaster)
nextg[!isp] = c->geo; nextg[!isp] = c->pgeo;
/* Next y/x position */ /* Next y/x position */
if(i >= nmaster - 1) if(i >= nmaster - 1)
@@ -603,7 +609,7 @@ mirror(int screen, Bool horizontal)
if(i == nmaster || i == nmaster - 1) if(i == nmaster || i == nmaster - 1)
cgeo.x = sg.x; cgeo.x = sg.x;
else else
cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2; cgeo.x = nextg[isp].x + nextg[isp].width + (BORDH << 1);
} }
else else
{ {
@@ -616,79 +622,14 @@ mirror(int screen, Bool horizontal)
else if (i <= nmaster - 1) else if (i <= nmaster - 1)
{ {
if(horizontal) if(horizontal)
mastergeo.x = c->geo.x + c->geo.width + BORDH * 2; mastergeo.x = cgeo.x + cgeo.width + (BORDH << 1);
else else
mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH; mastergeo.y = cgeo.y + cgeo.height + BORDH + TBARH;
} }
} }
ewmh_update_current_tag_prop(); tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
return;
}
/** Layer layout function
*/
void
layer(int screen)
{
Client *c;
XRectangle geo = { 0 };
XRectangle sg = sgeo[screen];
int n, i, l = tags[screen][seltag[screen]].layers;
int *x = NULL;
int *nl = NULL;
int *ncl = NULL;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
x = emalloc(l + 1, sizeof(int));
nl = emalloc(l + 1, sizeof(int));
ncl = emalloc(l + 1, sizeof(int));
for(i = 0; i < l + 1; ++i)
{
x[i] = sg.x;
nl[i] = 0;
ncl[i] = 0;
}
for(c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next))
{
for(; c->layer > l; --(c->layer));
++nl[c->layer];
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
++ncl[c->layer];
geo.x = x[c->layer];
geo.height = (sg.height / l) - (BORDH + TBARH);
geo.width = (sg.width / ((nl[c->layer]) ? nl[c->layer] : 1)) - BORDH * 2;
geo.y = sg.y + ((geo.height + TBARH + BORDH) * c->layer) - (geo.height + TBARH + BORDH);
if(c->layer == l)
geo.height = (sg.y + sg.height) - geo.y - BORDH;
if(ncl[c->layer] == nl[c->layer])
geo.width = sg.width - (geo.x - (sg.x - (BORDH * 2)));
client_moveresize(c, geo, False);
x[c->layer] = geo.x + geo.width + BORDH * 2;
}
free(x);
free(nl);
free(ncl);
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
return; return;
@@ -754,13 +695,23 @@ mirror_horizontal(int screen)
return; return;
} }
/** Put the selected client to the master postion /** Horizontal grid function
* \param cmd uicb_t type unused */
*/
void void
uicb_tile_switch(uicb_t cmd) grid_horizontal(int screen)
{ {
layout_set_client_master (sel); grid(screen, True);
return;
}
/** Vertical grid function
*/
void
grid_vertical(int screen)
{
grid(screen, False);
return; return;
} }
@@ -770,13 +721,16 @@ uicb_tile_switch(uicb_t cmd)
void void
uicb_togglefree(uicb_t cmd) uicb_togglefree(uicb_t cmd)
{ {
(void)cmd;
if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag)) if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag))
return; return;
sel->flags ^= FreeFlag; sel->flags ^= FreeFlag;
if((sel->flags & FreeFlag)) if(sel->flags & FreeFlag)
{ {
split_set_current(NULL, sel);
sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag); sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(sel, sel->free_geo, True); client_moveresize(sel, sel->free_geo, True);
client_raise(sel); client_raise(sel);
@@ -785,41 +739,50 @@ uicb_togglefree(uicb_t cmd)
{ {
sel->free_geo = sel->geo; sel->free_geo = sel->geo;
sel->ogeo = sel->geo; sel->ogeo = sel->geo;
split_set_current(sel, NULL);
} }
client_update_attributes(sel); client_update_attributes(sel);
tags[selscreen][seltag[selscreen]].layout.func(selscreen); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return; return;
} }
/** Toggle the selected client to max /** Toggle the selected client to max
* \param cmd uicb_t type unused * \param cmd uicb_t type unused
*/ */
void void
uicb_togglemax(uicb_t cmd) uicb_togglemax(uicb_t cmd)
{ {
if(!sel || ishide(sel, selscreen) (void)cmd;
|| (sel->flags & HintFlag)|| (sel->flags & FSSFlag))
if(!sel || ishide(sel, selscreen) || (sel->flags & (HintFlag | FSSFlag)))
return; return;
if(!(sel->flags & MaxFlag)) sel->flags ^= MaxFlag;
if(sel->flags & MaxFlag)
{ {
sel->ogeo = sel->geo; sel->ogeo = sel->geo;
sel->free_geo = sel->geo; sel->free_geo = sel->geo;
sel->flags &= ~(TileFlag | FreeFlag); sel->flags &= ~(TileFlag | FreeFlag);
split_set_current(NULL, sel);
client_maximize(sel); client_maximize(sel);
client_raise(sel); XRaiseWindow(dpy, sel->frame);
sel->flags |= MaxFlag;
} }
else else
{ {
sel->geo = sel->free_geo; sel->geo = sel->ogeo;
client_moveresize(sel, sel->geo, True); 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; return;
@@ -831,11 +794,15 @@ uicb_togglemax(uicb_t cmd)
void void
uicb_toggle_resizehint(uicb_t cmd) uicb_toggle_resizehint(uicb_t cmd)
{ {
Client *c;
screen_get_sel(); 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 = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next))
client_moveresize(c, c->geo, (tags[selscreen][seltag[selscreen]].flags & ResizeHintFlag));
return; return;
} }
@@ -847,21 +814,25 @@ void
uicb_toggle_abovefc(uicb_t cmd) uicb_toggle_abovefc(uicb_t cmd)
{ {
Client *c; Client *c;
(void)cmd;
screen_get_sel(); 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) for(c = clients; c; c = c->next)
if(c->flags & AboveFlag if(c->flags & AboveFlag
&& c->screen == selscreen && c->screen == selscreen
&& c->tag == seltag[selscreen]) && c->tag == (uint)seltag[selscreen])
{ {
c->flags &= ~AboveFlag; c->flags &= ~AboveFlag;
break; break;
} }
tags[selscreen][seltag[selscreen]].layout.func(selscreen); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
} }
client_focus(sel); client_focus(sel);
@@ -875,7 +846,7 @@ uicb_toggle_abovefc(uicb_t cmd)
void void
uicb_set_layout(uicb_t cmd) uicb_set_layout(uicb_t cmd)
{ {
int i, j, n; size_t i, j, n;
screen_get_sel(); screen_get_sel();
@@ -883,11 +854,13 @@ uicb_set_layout(uicb_t cmd)
for(n = 0; layout_list[n].name != NULL && layout_list[n].func != NULL; ++n); for(n = 0; layout_list[n].name != NULL && layout_list[n].func != NULL; ++n);
for(i = 0; i < n; ++i) for(i = 0; i < n; ++i)
if(!strcmp(cmd, _strdup(layout_list[i].name))) if(!strcmp(cmd, xstrdup(layout_list[i].name)))
for(j = 0; j < LEN(conf.layout); ++j) for(j = 0; j < LEN(conf.layout); ++j)
if(layout_list[i].func == conf.layout[j].func) if(layout_list[i].func == conf.layout[j].func)
tags[selscreen][seltag[selscreen]].layout = conf.layout[j]; tags[selscreen][seltag[selscreen]].layout = conf.layout[j];
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
arrange(selscreen, True); arrange(selscreen, True);
return; return;
@@ -901,8 +874,7 @@ layout_set_client_master(Client *c)
{ {
screen_get_sel(); screen_get_sel();
if(!c || (c->flags & HintFlag) || !(c->flags & TileFlag) if(!c || (c->flags & (HintFlag | FSSFlag)) || !(c->flags & TileFlag))
|| (c->flags & FSSFlag))
return; return;
if(c == tiled_client(selscreen, clients)) if(c == tiled_client(selscreen, clients))
@@ -910,9 +882,59 @@ layout_set_client_master(Client *c)
client_detach(c); client_detach(c);
client_attach(c); client_attach(c);
client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen); tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return; return;
} }
/** Check the selected client is max
* \param cmd uicb_t type unused
*/
bool
uicb_checkmax(uicb_t cmd)
{
(void)cmd;
if(!sel)
return False;
if(sel->flags & MaxFlag)
return True;
return False;
}
/** Check the selected client is free
* \param cmd uicb_t type unused
*/
bool
uicb_checkfree(uicb_t cmd)
{
(void)cmd;
if(!sel)
return False;
if(sel->flags & FreeFlag)
return True;
return False;
}
/** Check layout type
* \param cmd uicb_t type layout type
*/
bool
uicb_checklayout(uicb_t cmd)
{
screen_get_sel();
char *type = tags[selscreen][seltag[selscreen]].layout.type;
if(type && !strcmp(cmd, type))
return True;
return False;
}

View File

@@ -32,91 +32,124 @@
#include "wmfs.h" #include "wmfs.h"
void static int
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n) menu_get_longer_string(MenuItem *mi, int nitem)
{ {
int i, w, l = 0;
/* Item */ for(i = 0; i < nitem; ++i)
menu->nitem = nitem; if((w = textw(mi[i].name)) > l)
menu->item = emalloc(sizeof(MenuItem), nitem); l = w;
menu->name = name;
/* Colors */ return l;
menu->colors.focus.bg = bg_f;
menu->colors.focus.fg = fg_f;
menu->colors.normal.bg = bg_n;
menu->colors.normal.fg = fg_n;
return;
} }
void static bool
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd) menu_get_checkstring_needed(MenuItem *mi, int nitem)
{ {
mi->name = name; (void)mi;
mi->func = func; (void)nitem;
mi->cmd = cmd; return True;
return;
} }
void static void
menu_draw(Menu menu, int x, int y) menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen)
{ {
int i, width; int x;
XEvent ev; int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3;
BarWindow *item[menu.nitem];
BarWindow *frame;
width = menu_get_longer_string(menu.item, menu.nitem); switch(menu->align)
/* Frame barwin */
frame = barwin_create(ROOT, x, y, width + SHADH, menu.nitem * (INFOBARH - SHADH) + SHADH * 2,
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
barwin_map(frame);
barwin_map_subwin(frame);
barwin_refresh_color(frame);
for(i = 0; i < menu.nitem; ++i)
{ {
item[i] = barwin_create(frame->win, case MA_Left:
SHADH, x = chcklen + PAD / 2;
(i * (INFOBARH - SHADH) + SHADH), break;
width - SHADH, case MA_Right:
INFOBARH, x = width - textw(menu->item[item].name) + PAD * 3 / 2;
menu.colors.normal.bg, break;
menu.colors.normal.fg, default:
True, False, False); case MA_Center:
x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3;
break;
}
barwin_draw_text(winitem[item], x, FHINFOBAR, menu->item[item].name);
barwin_map(item[i]); if(menu->item[item].check)
barwin_refresh_color(item[i]); if(menu->item[item].check(menu->item[item].cmd))
menu_draw_item_name(&menu, i, item); barwin_draw_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol);
barwin_refresh(item[i]);
if(menu->item[item].submenu)
barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">");
return;
}
static bool
menu_activate_item(Menu *menu, int i)
{
int j, x, y;
int chcklen = 0;
if(menu_get_checkstring_needed(menu->item, menu->nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
if(menu->item[i].submenu)
{
for(j = 0; j < conf.nmenu; ++j)
if(!strcmp(menu->item[i].submenu, conf.menu[j].name))
{
y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2;
x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3;
menu_draw(conf.menu[j], x, y);
return True;
}
}
else if(menu->item[i].func)
{
menu->item[i].func(menu->item[i].cmd);
return True;
} }
/* Select the first item */ return False;
menu_focus_item(&menu, 0, item); }
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime); static void
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
{
int i;
while(!menu_manage_event(&ev, &menu, item)); int chcklen = 0;
if(menu_get_checkstring_needed(menu->item, menu->nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
XUngrabKeyboard(dpy, CurrentTime); menu->focus_item = item;
for(i = 0; i < menu.nitem; ++i) if(menu->focus_item > menu->nitem - 1)
barwin_delete(item[i]); menu->focus_item = 0;
barwin_delete(frame); else if(menu->focus_item < 0)
menu->focus_item = menu->nitem - 1;
for(i = 0; i < menu->nitem; ++i)
{
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
barwin_refresh_color(winitem[i]);
menu_draw_item_name(menu, i, winitem, chcklen);
barwin_refresh(winitem[i]);
}
return; return;
} }
Bool static bool
menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]) menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
{ {
int i, c = 0; int i, c = 0;
KeySym ks; KeySym ks = 0;
Bool quit = False; bool quit = False;
char acc = 0;
switch(ev->type) switch(ev->type)
{ {
@@ -127,12 +160,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
{ {
if(ev->xbutton.window == winitem[i]->win if(ev->xbutton.window == winitem[i]->win
&& (ev->xbutton.button == Button1 || ev->xbutton.button == Button2)) && (ev->xbutton.button == Button1 || ev->xbutton.button == Button2))
{ quit = menu_activate_item(menu, i);
if(menu->item[i].func)
menu->item[i].func(menu->item[i].cmd);
quit = True;
}
else if(ev->xbutton.window != winitem[i]->win) else if(ev->xbutton.window != winitem[i]->win)
++c; ++c;
else if(ev->xbutton.button == Button4) else if(ev->xbutton.button == Button4)
@@ -161,9 +189,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
break; break;
case XK_Return: case XK_Return:
if(menu->item[menu->focus_item].func) quit = menu_activate_item(menu, menu->focus_item);
menu->item[menu->focus_item].func(menu->item[menu->focus_item].cmd);
quit = True;
break; break;
case XK_Escape: case XK_Escape:
@@ -178,69 +204,33 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
/* For focus an item with the mouse */ /* For focus an item with the mouse */
for(i = 0; i < menu->nitem; ++i) for(i = 0; i < menu->nitem; ++i)
if(ev->xcrossing.window == winitem[i]->win) if(ev->xcrossing.window == winitem[i]->win)
{
acc = 1;
menu_focus_item(menu, i, winitem); menu_focus_item(menu, i, winitem);
if(menu->item[i].submenu)
menu_activate_item(menu, menu->focus_item);
}
if(!acc)
{
if(ev->xcrossing.window)
XSendEvent(dpy, ev->xcrossing.window, False, StructureNotifyMask, ev);
return True;
}
break; break;
default: default:
getevent(*ev); if(ev->type < nevent && ev->type > 0)
HANDLE_EVENT(ev);
break; break;
} }
XNextEvent(dpy, ev); XNextEvent(dpy, ev);
return quit; return quit;
} }
void
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
{
int i;
menu->focus_item = item;
if(menu->focus_item > menu->nitem - 1)
menu->focus_item = 0;
else if(menu->focus_item < 0)
menu->focus_item = menu->nitem - 1;
for(i = 0; i < menu->nitem; ++i)
{
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
barwin_refresh_color(winitem[i]);
menu_draw_item_name(menu, i, winitem);
barwin_refresh(winitem[i]);
}
return;
}
void
menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[])
{
int width = menu_get_longer_string(menu->item, menu->nitem);
barwin_draw_text(winitem[item],
((width / 2) - (textw(menu->item[item].name) / 2)),
FHINFOBAR,
menu->item[item].name);
return;
}
int
menu_get_longer_string(MenuItem *mt, int nitem)
{
int i, l = 0;
for(i = 0; i < nitem; ++i)
if(textw(mt[i].name) > l)
l = textw(mt[i].name);
return l + PAD;
}
void void
uicb_menu(uicb_t cmd) uicb_menu(uicb_t cmd)
{ {
@@ -254,7 +244,11 @@ uicb_menu(uicb_t cmd)
if(!strcmp(cmd, conf.menu[i].name)) if(!strcmp(cmd, conf.menu[i].name))
{ {
if(conf.menu[i].place_at_mouse) if(conf.menu[i].place_at_mouse)
{
XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&u); XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&u);
conf.menu[i].x = x;
conf.menu[i].y = y;
}
else else
{ {
screen_get_sel(); screen_get_sel();
@@ -266,3 +260,104 @@ uicb_menu(uicb_t cmd)
return; return;
} }
void
menu_clear(Menu *menu)
{
free(menu->item);
menu->nitem = 0;
return;
}
void
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n)
{
/* Item */
menu->nitem = nitem;
menu->item = xcalloc(nitem, sizeof(*menu->item));
menu->name = name;
/* Colors */
menu->colors.focus.bg = bg_f;
menu->colors.focus.fg = fg_f;
menu->colors.normal.bg = bg_n;
menu->colors.normal.fg = fg_n;
return;
}
void
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd)
{
mi->name = name;
mi->func = func;
mi->cmd = cmd;
return;
}
void
menu_draw(Menu menu, int x, int y)
{
int i, width, height, out;
XEvent ev;
BarWindow *item[menu.nitem];
BarWindow *frame;
int chcklen = 0;
if(menu_get_checkstring_needed(menu.item, menu.nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3;
height = menu.nitem * (INFOBARH - SHADH);
/* Frame barwin */
screen_get_sel();
if((out = x + width - MAXW) > 0)
x -= out;
if((out = y + height - MAXH) > 0)
y -= out;
frame = barwin_create(ROOT, x, y, width + SHADH, height + SHADH * 3,
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
barwin_map(frame);
barwin_map_subwin(frame);
barwin_refresh_color(frame);
for(i = 0; i < menu.nitem; ++i)
{
item[i] = barwin_create(frame->win,
SHADH,
(i * (INFOBARH - SHADH) + SHADH),
width - SHADH,
INFOBARH,
menu.colors.normal.bg,
menu.colors.normal.fg,
True, False, False);
barwin_map(item[i]);
barwin_refresh_color(item[i]);
menu_draw_item_name(&menu, i, item, chcklen);
barwin_refresh(item[i]);
}
/* Select the first item */
menu_focus_item(&menu, 0, item);
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XNextEvent(dpy, &ev);
while(!menu_manage_event(&ev, &menu, item));
XUngrabKeyboard(dpy, CurrentTime);
for(i = 0; i < menu.nitem; ++i)
barwin_delete(item[i]);
barwin_delete(frame);
return;
}

View File

@@ -32,37 +32,50 @@
#include "wmfs.h" #include "wmfs.h"
Window prevwin;
/** Draw the border when a client in dragging/resizing with mouse /** Draw the border when a client in dragging/resizing with mouse
*/ */
void static void
mouse_dragborder(XRectangle geo, GC g) mouse_dragborder(Geo geo, GC g)
{ {
XDrawRectangle(dpy, ROOT, g, XDrawRectangle(dpy, ROOT, g,
geo.x - BORDH / 2, geo.x - (BORDH >> 1),
geo.y - (TBARH - (BORDH / 2)), geo.y - (TBARH - (BORDH >> 1)),
geo.width + BORDH, geo.width + BORDH,
geo.height + TBARH); geo.height + TBARH);
return; 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 /** Move a client in tile grid with the mouse
*\param c Client double pointer *\param c Client double pointer
*/ */
void static void
mouse_move_tile_client(Client **c) mouse_move_tile_client(Client **c)
{ {
Client *sc; Client *sc;
Window w; Window w;
int d; int d;
if(!((*c)->flags & TileFlag) && !((*c)->flags & LMaxFlag)) if(!((*c)->flags & (TileFlag | LMaxFlag)))
return; return;
XQueryPointer(dpy, ROOT, &w, &w, &d, &d, &d, &d, (uint*)&d); 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))) 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_swap(sc, *c);
client_focus(sc); client_focus(sc);
@@ -76,27 +89,29 @@ mouse_move_tile_client(Client **c)
/** Move a client from one tag to another with dah mouse /** Move a client from one tag to another with dah mouse
*\param c client pointer *\param c client pointer
*/ */
void static void
mouse_move_tag_client(Client *c) mouse_move_tag_client(Client *c)
{ {
Window w; Window w;
int i, d, s; int i, d, s;
if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag)) if(!(c->flags & (TileFlag | LMaxFlag)))
return; return;
s = c->screen; s = c->screen;
XQueryPointer(dpy, infobar[selscreen].tags_board->win, &w, &w, &d, &d, &d, &d, (uint*)&d); 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) for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(infobar[selscreen].tags[i]->win == w if(infobar[selscreen].tags[i]->win == w
&& tags[selscreen][i].layout.func != freelayout) && tags[selscreen][i].layout.func != freelayout)
{ {
c->screen = selscreen; tag_transfert(c, i);
c->tag = i;
tags[c->screen][c->tag].request_update = True;
arrange(s, True);
if(s != c->screen) if(s != c->screen)
arrange(c->screen, True); arrange(c->screen, True);
@@ -108,19 +123,19 @@ mouse_move_tag_client(Client *c)
/** Move the client with the mouse /** Move the client with the mouse
* \param c Client pointer * \param c Client pointer
*/ */
void static void
mouse_move(Client *c) mouse_move(Client *c)
{ {
int ocx, ocy, mx, my; int ocx, ocy, mx, my;
int dint; int dint;
uint duint; uint duint;
Window dw; Window dw;
XRectangle geo = c->geo; Geo geo = c->geo;
XGCValues xgc; XGCValues xgc;
GC gci; GC gci;
XEvent ev; XEvent ev;
if((c->flags & MaxFlag) || (c->flags & FSSFlag)) if(c->flags & (MaxFlag | FSSFlag))
return; return;
ocx = c->geo.x; ocx = c->geo.x;
@@ -169,14 +184,13 @@ mouse_move(Client *c)
mouse_dragborder(geo, gci); mouse_dragborder(geo, gci);
} }
} }
else if(ev.type == MapRequest else if((ev.type == MapRequest || ev.type == ConfigureRequest))
|| ev.type == ConfigureRequest) HANDLE_EVENT(&ev);
getevent(ev);
} }
while(ev.type != ButtonRelease); while(ev.type != ButtonRelease);
/* One time again to delete all the trace on the window */ /* 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); mouse_dragborder(geo, gci);
client_moveresize(c, geo, False); client_moveresize(c, geo, False);
@@ -197,23 +211,21 @@ mouse_move(Client *c)
void void
mouse_resize(Client *c) mouse_resize(Client *c)
{ {
XRectangle geo = c->geo, ogeo = c->geo; Geo geo = c->geo, ogeo = c->geo;
Position pos = Right; Position pos = Right;
XEvent ev; XEvent ev;
Window w; Window w;
int d, u, omx, omy; int d, u, omx, omy;
XGCValues xgc; XGCValues xgc;
GC gci; GC gci;
float mwf = tags[selscreen][seltag[selscreen]].mwfact; int f[4] = { 0 };
if((c->flags & MaxFlag) if(c->flags & (MaxFlag | LMaxFlag | FSSFlag))
|| (c->flags & LMaxFlag)
|| (c->flags & FSSFlag))
return; return;
XQueryPointer(dpy, ROOT, &w, &w, &omx, &omy, &d, &d, (uint *)&u); 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; pos = Left;
if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None, if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None,
@@ -238,6 +250,8 @@ mouse_resize(Client *c)
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, c->geo.height); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, c->geo.height);
mouse_dragborder(c->geo, gci); mouse_dragborder(c->geo, gci);
} }
else
mouse_cfactor_border(c, f, gci);
do do
{ {
@@ -245,23 +259,22 @@ mouse_resize(Client *c)
if(ev.type == MotionNotify) if(ev.type == MotionNotify)
{ {
/* To resize MWFACT in tile mode */ /* To resize client in tile mode with cfactor */
if((c->flags & TileFlag) if(c->flags & TileFlag)
&& tags[selscreen][seltag[selscreen]].layout.func != grid)
{ {
if(tags[selscreen][seltag[selscreen]].layout.func == tile) mouse_cfactor_border(c, f, gci);
mwf += (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left) if(omx >= c->frame_geo.x + (c->frame_geo.width >> 1))
mwf -= (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width); f[Right] = ev.xmotion.x_root - omx;
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top)
mwf -= (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height);
else 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); if(omy >= c->frame_geo.y + (c->frame_geo.height >> 1))
omy = ROUND(ev.xmotion.y_root); 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 */ /* Free mode */
else if(!(c->flags & TileFlag)) else if(!(c->flags & TileFlag))
@@ -300,7 +313,10 @@ mouse_resize(Client *c)
XUngrabServer(dpy); XUngrabServer(dpy);
} }
else else
tags[selscreen][seltag[selscreen]].layout.func(c->screen); {
mouse_cfactor_border(c, f, gci);
cfactor_multi_set(c, f);
}
client_update_attributes(c); client_update_attributes(c);
XUngrabPointer(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime);
@@ -314,9 +330,9 @@ mouse_resize(Client *c)
* \param focused For know if c is or not focused * \param focused For know if c is or not focused
*/ */
void void
mouse_grabbuttons(Client *c, Bool focused) mouse_grabbuttons(Client *c, bool focused)
{ {
int i; size_t i;
uint but[] = {Button1, Button2, Button3, Button4, Button5}; uint but[] = {Button1, Button2, Button3, Button4, Button5};
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
@@ -345,6 +361,7 @@ mouse_grabbuttons(Client *c, Bool focused)
void void
uicb_mouse_move(uicb_t cmd) uicb_mouse_move(uicb_t cmd)
{ {
(void)cmd;
CHECK(sel); CHECK(sel);
mouse_move(sel); mouse_move(sel);
@@ -358,6 +375,7 @@ uicb_mouse_move(uicb_t cmd)
void void
uicb_mouse_resize(uicb_t cmd) uicb_mouse_resize(uicb_t cmd)
{ {
(void)cmd;
CHECK(sel); CHECK(sel);
mouse_resize(sel); mouse_resize(sel);

626
src/parse.c Normal file
View File

@@ -0,0 +1,626 @@
/*
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <err.h>
#include "parse.h"
extern char *__progname;
enum keyword_t { SEC_START, SEC_END, INCLUDE, WORD, EQUAL, LIST_START, LIST_END, NONE };
#ifdef DEBUG
static struct {
const char *name;
enum keyword_t type;
} kw_t_name[] = {
{"SEC_START", SEC_START},
{"SEC_END", SEC_END},
{"INCLUDE", INCLUDE},
{"WORD", WORD},
{"EQUAL", EQUAL},
{"LIST_START", LIST_START},
{"LIST_END", LIST_END},
{"NONE", NONE},
};
#endif
struct files {
char *name;
struct files *parent;
};
struct keyword {
enum keyword_t type;
/* if WORD */
int line;
struct files *file;
char *name;
struct keyword *next;
};
struct state {
bool quote;
bool comment;
char quote_char;
};
/* TO REMOVE (use a identifier for config and fallback XDG in api functions) */
TAILQ_HEAD(, conf_sec) config;
static struct keyword *keywords = NULL;
static struct keyword *
push_keyword(struct keyword *tail, enum keyword_t type, char *buf, size_t *offset, struct files *file, int line)
{
struct keyword *kw;
#ifdef DEBUG
int i = 0;
#endif
if (type == WORD && *offset == 0)
return tail;
kw = zcalloc(sizeof(*kw));
kw->type = type;
kw->line = line;
kw->file = file;
kw->next = NULL;
if (*offset != 0) {
buf[*offset] = '\0';
if (!strcmp(buf, INCLUDE_CMD))
kw->type = INCLUDE;
else
kw->name = strdup(buf);
*offset = 0;
}
else
kw->name = NULL;
if (tail)
tail->next = kw;
#ifdef DEBUG
for (i = 0; kw_t_name[i].type != NONE; i++) {
if (kw_t_name[i].type == kw->type) {
warnx("%s %s %s:%d\n", kw_t_name[i].name,
(kw->name) ? kw->name : "",
kw->file->name, kw->line);
}
}
#endif
return kw;
}
static void
syntax(struct keyword *kw, const char *fmt, ...)
{
va_list args;
fprintf(stderr, "%s:", __progname);
if (kw && kw->file && kw->file->name)
fprintf(stderr, "%s:%d", kw->file->name, kw->line);
if (kw && kw->name)
fprintf(stderr, ", near '%s'", kw->name);
fprintf(stderr, ": ");
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
}
#define PUSH_KEYWORD(type) tail = push_keyword(tail, type, bufname, &j, file, line)
static struct keyword *
parse_keywords(const char *filename)
{
int fd;
struct stat st;
char *buf;
struct keyword *head = NULL;
struct keyword *tail = NULL;
struct files *file;
enum keyword_t type; /* keyword type to push */
struct state s = { False, False, '\0'};
char *bufname;
char path[PATH_MAX];
size_t i, j;
int line;
bool error = False;
if ((fd = open(filename, O_RDONLY)) == -1 || stat(filename, &st) == -1) {
warn("%s", filename);
return NULL;
}
if (st.st_size == 0) {
warnx("%s: empty file", filename);
close(fd);
return NULL;
}
if (!realpath(filename, path)) {
warn("%s", filename);
close(fd);
return NULL;
}
buf = zmalloc(st.st_size+1);
if (read(fd, buf, st.st_size) == -1) {
warn("%s", filename);
free(buf);
close(fd);
return NULL;
}
buf[st.st_size] = '\0';
file = zcalloc(sizeof(*file));
bufname = zcalloc(sizeof(*bufname) * BUFSIZ);
file->name = strdup(path);
file->parent = NULL;
for(i = 0, j = 0, line = 1; i < (size_t)st.st_size; i++) {
if (!head && tail)
head = tail;
if (buf[i] == '\n' && s.comment == True) {
line++;
s.comment = False;
continue;
}
if (buf[i] == '#' && s.quote == False) {
s.comment = True;
continue;
}
if (s.comment == True)
continue;
if (s.quote == True && buf[i] == s.quote_char) {
/* end of quotted string */
PUSH_KEYWORD(WORD);
s.quote = False;
continue;
}
if (s.quote == False) {
if ((buf[i] == '"' || buf[i] == '\'')) {
PUSH_KEYWORD(WORD);
/* begin quotted string */
s.quote_char = buf[i];
s.quote = True;
continue;
}
if (buf[i] == '[') {
PUSH_KEYWORD(WORD);
if (buf[i+1] == '/') {
i +=2;
type = SEC_END;
}
else {
i++;
type = SEC_START;
}
/* get section name */
while (buf[i] != ']') {
if (i >= ((size_t)st.st_size-1) || j >= (BUFSIZ-1)) {
bufname[j] = '\0';
syntax(NULL, "word too long in %s:%d near '%s'",
file->name, line, bufname);
error = True;
break;
}
bufname[j++] = buf[i++];
}
PUSH_KEYWORD(type);
continue;
}
if (buf[i] == '{') {
PUSH_KEYWORD(WORD);
PUSH_KEYWORD(LIST_START);
continue;
}
if (buf[i] == '}') {
PUSH_KEYWORD(WORD);
PUSH_KEYWORD(LIST_END);
continue;
}
if (buf[i] == ',') {
PUSH_KEYWORD(WORD);
continue;
}
if (buf[i] == '=') {
PUSH_KEYWORD(WORD);
PUSH_KEYWORD(EQUAL);
continue;
}
if (strchr("\t\n ", buf[i])) {
PUSH_KEYWORD(WORD);
if (buf[i] == '\n')
line++;
continue;
}
} /* s.quote == False */
if (j >= (BUFSIZ - 1)) {
bufname[j] = '\0';
syntax(NULL, "word too long in %s:%d near '%s'",
file->name, line, bufname);
error = True;
break;
}
bufname[j++] = buf[i];
}
free(buf);
free(bufname);
close(fd);
warnx("%s read", file->name);
return (error ? NULL: head);
}
/*
* return NULL on failure and head->next if
* no config found (of file doesn't exist)
* NOTE to devs: head->name is the file to include
*/
static struct keyword *
include(struct keyword *head)
{
struct keyword *kw;
struct keyword *tail;
struct files *file;
struct passwd *user;
char *filename = NULL;
char *base = NULL;
head = head->next;
if (!head || head->type != WORD) {
syntax(head, "missing filename to include");
return NULL;
}
/* replace ~ by user directory */
if (head->name && head->name[0] == '~') {
if ( (user = getpwuid(getuid())) && user->pw_dir)
xasprintf(&filename, "%s%s", user->pw_dir, head->name+1);
else if (getenv("HOME"))
xasprintf(&filename, "%s%s", getenv("HOME"), head->name+1);
else /* to warning ? */
filename = head->name;
}
/* relative path from parent file */
else if (head->name && head->name[0] != '/') {
base = strdup(head->file->name);
xasprintf(&filename, "%s/%s", dirname(base), head->name);
free(base);
}
else
filename = head->name;
if (!(kw = parse_keywords(filename))) {
warnx("no config found in include file %s", head->name);
if (filename != head->name)
free(filename);
return NULL;
}
kw->file->parent = head->file;
/* detect circular include */
for (file = kw->file->parent; file != NULL; file = file->parent) {
if (!strcmp(file->name, kw->file->name)) {
syntax(kw, "circular include of %s", kw->file->name);
if (filename != head->name)
free(filename);
return NULL;
}
}
if (filename != head->name)
free(filename);
head = head->next;
if (kw) {
for (tail = kw; tail->next; tail = tail->next);
tail->next = head;
}
return kw;
}
static void *
free_opt(struct conf_opt *o)
{
free(o);
return NULL;
}
static struct conf_opt *
get_option(struct keyword **head)
{
struct conf_opt *o;
size_t j = 0;
struct keyword *kw = *head;
o = zcalloc(sizeof(*o));
o->name = kw->name;
o->used = False;
o->line = kw->line;
o->filename = kw->file->name;
kw = kw->next;
if (kw->type != EQUAL) {
syntax(kw, "missing '=' here");
return free_opt(o);
}
kw = kw->next;
if (!kw) {
syntax(kw, "missing value");
return free_opt(o);
}
switch (kw->type) {
case INCLUDE:
if (!(kw = include(kw)))
return free_opt(o);
break;
case WORD:
o->val[0] = kw->name;
o->val[1] = NULL;
kw = kw->next;
break;
case LIST_START:
kw = kw->next;
while (kw && kw->type != LIST_END) {
switch (kw->type) {
case WORD:
if (j >= (PARSE_MAX_LIST - 1)) {
syntax(kw, "too much values in list");
return free_opt(o);
}
o->val[j++] = kw->name;
kw = kw->next;
break;
case INCLUDE:
if (!(kw = include(kw)))
return free_opt(o);
break;
default:
syntax(kw, "declaration into a list");
return free_opt(o);
break;
}
}
if (!kw) {
syntax(kw, "list unclosed");
return free_opt(o);
}
kw = kw->next;
break;
default:
syntax(kw, "missing value");
return free_opt(o);
break;
}
*head = kw;
return o;
}
static void *
free_sec(struct conf_sec *sec)
{
struct conf_opt *o;
struct conf_sec *s;
if (sec) {
while (!SLIST_EMPTY(&sec->optlist)) {
o = SLIST_FIRST(&sec->optlist);
SLIST_REMOVE_HEAD(&sec->optlist, entry);
free_opt(o);
}
while (!TAILQ_EMPTY(&sec->sub)) {
s = TAILQ_FIRST(&sec->sub);
TAILQ_REMOVE(&sec->sub, s, entry);
free_sec(s);
}
free(sec);
}
return NULL;
}
static struct conf_sec *
get_section(struct keyword **head)
{
struct conf_sec *s;
struct conf_opt *o;
struct conf_sec *sub;
struct keyword *kw = *head;
s = zcalloc(sizeof(*s));
s->name = kw->name;
TAILQ_INIT(&s->sub);
SLIST_INIT(&s->optlist);
kw = kw->next;
while (kw && kw->type != SEC_END) {
switch (kw->type) {
case INCLUDE:
if (!(kw = include(kw)))
return free_sec(s);
break;
case SEC_START:
if (!(sub = get_section(&kw)))
return free_sec(s);
TAILQ_INSERT_TAIL(&s->sub, sub, entry);
s->nsub++;
break;
case WORD:
if (!(o = get_option(&kw)))
return free_sec(s);
SLIST_INSERT_HEAD(&s->optlist, o, entry);
s->nopt++;
break;
default:
syntax(kw, "syntax error");
return free_sec(s);
break;
}
}
if (!kw || strcmp(kw->name, s->name)) {
syntax(kw, "missing end section %s", s->name);
return free_sec(s);
}
kw = kw->next;
*head = kw;
return s;
}
int
free_conf(void)
{
struct conf_sec *s;
struct keyword *kw, *nkw;
struct files **f = NULL;
int i, nf = 0;
while (!TAILQ_EMPTY(&config)) {
s = TAILQ_FIRST(&config);
TAILQ_REMOVE(&config, s, entry);
free_sec(s);
}
kw = keywords;
while (kw) {
nkw = kw->next;
free(kw->name);
for (i = 0; i < nf; i++) {
if (f[i] == kw->file) {
if (!(f = realloc(f, sizeof(*f) * (++i))))
err(EXIT_FAILURE, "realloc");
f[i-1] = kw->file;
}
}
kw = nkw;
}
if (nf > 0) {
for (i = 0; i < nf; i++) {
free(f[i]->name);
free(f[i]);
}
free(f);
}
return -1;
}
int
get_conf(const char *filename)
{
struct conf_sec *s;
struct keyword *head, *kw;
kw = head = parse_keywords(filename);
if (!head)
return -1; /* TODO ERREUR */
keywords = head;
TAILQ_INIT(&config);
while (kw) {
switch (kw->type) {
case INCLUDE:
if (!(kw = include(kw)))
return free_conf();
break;
case SEC_START:
if (!(s = get_section(&kw)))
return free_conf();
TAILQ_INSERT_TAIL(&config, s, entry);
break;
default:
syntax(kw, "out of any section");
return free_conf();
break;
}
}
return 0;
}

115
src/parse.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef PARSE_H
#define PARSE_H
#include "wmfs.h"
#include <sys/queue.h>
#define INCLUDE_CMD "@include"
#define PARSE_MAX_LIST 32
struct conf_opt {
char *name;
char *val[PARSE_MAX_LIST];
size_t nval;
bool used;
int line;
char *filename;
SLIST_ENTRY(conf_opt) entry;
};
struct conf_sec {
char *name;
SLIST_HEAD(, conf_opt) optlist;
TAILQ_HEAD(, conf_sec) sub;
size_t nopt;
size_t nsub;
TAILQ_ENTRY(conf_sec) entry;
};
struct opt_type {
long int num;
float fnum;
bool boolean;
char *str;
};
/*
* Create config from file
* return -1 on failure
*/
int get_conf(const char *);
/*
* Print unused option name from section s (and subsections).
* If s == NULL print unused option name for all config struct.
*/
void print_unused(struct conf_sec *s);
/*
* Free the config struct.
* WARNING: This make all string
* returned by fetch_(opt|section)(_first) unusable.
*/
int free_conf(void);
/*
* Get all subsection matching the given name on the given
* section.
* If section == NULL, return subsections from root section.
* Return a NULL terminated array.
* Subsections are returned in order as they are in config file
* WARNING : This MUST be free() after use.
*/
struct conf_sec **fetch_section(struct conf_sec *, char *);
/*
* Get first subsection matching the given name
* on the given section. (first found on the file)
*/
struct conf_sec *fetch_section_first(struct conf_sec *, char *);
/*
* Count member of a conf_sec **
*/
size_t fetch_section_count(struct conf_sec **);
/*
* Return all options matching the given name on the given subsection.
* If none match or section == NULL return opt_type build with the
* given default param.
* WARNING: This MUST be free() after use.
* WARNING: The string member is directly taken from the config struct.
* WARNING: Returned in reverse order as they are in config file.
* (I think the last option MUST overwrite all others)
*/
struct opt_type fetch_opt_first(struct conf_sec *, char *, char *);
/*
* Get first (last in config file) option matching the given name
* on the given section.
* WARNING: The string member is directly taken from the config struct.
*/
struct opt_type *fetch_opt(struct conf_sec *, char *, char *);
/*
* Count member of a opt_type *
*/
size_t fetch_opt_count(struct opt_type *);
#endif /* PARSE_H */

197
src/parse_api.c Normal file
View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2010 Philippe Pepiot <phil@philpep.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include "parse.h"
extern TAILQ_HEAD(, conf_sec) config;
static const struct opt_type opt_type_null = { 0, 0, False, NULL };
static struct opt_type
string_to_opt(char *s)
{
struct opt_type ret = opt_type_null;
if (!s || !strlen(s))
return ret;
ret.num = strtol(s, (char**)NULL, 10);
ret.fnum = strtod(s, NULL);
if (!strcmp(s, "true") || !strcmp(s, "True") ||
!strcmp(s, "TRUE") || !strcmp(s, "1"))
ret.boolean = True;
else
ret.boolean = False;
ret.str = s;
return ret;
}
void
print_unused(struct conf_sec *sec)
{
struct conf_sec *s;
struct conf_opt *o;
if (!sec)
{
TAILQ_FOREACH(s, &config, entry)
print_unused(s);
return;
}
SLIST_FOREACH(o, &sec->optlist, entry)
if (o->used == False)
warnx("%s:%d, unused param %s",
o->filename, o->line, o->name);
TAILQ_FOREACH(s, &sec->sub, entry)
if (!TAILQ_EMPTY(&s->sub))
print_unused(s);
}
struct conf_sec **
fetch_section(struct conf_sec *s, char *name)
{
struct conf_sec **ret;
struct conf_sec *sec;
size_t i = 0;
if (!name)
return NULL;
if (!s) {
ret = xcalloc(2, sizeof(struct conf_sec *));
TAILQ_FOREACH(sec, &config, entry)
if (!strcmp(sec->name, name)) {
ret[0] = sec;
ret[1] = NULL;
break;
}
}
else {
ret = xcalloc(s->nsub+1, sizeof(struct conf_sec *));
TAILQ_FOREACH(sec, &s->sub, entry) {
if (!strcmp(sec->name, name) && i < s->nsub)
ret[i++] = sec;
}
ret[i] = NULL;
}
return ret;
}
struct conf_sec *
fetch_section_first(struct conf_sec *s, char *name)
{
struct conf_sec *sec, *ret = NULL;
if (!name)
return NULL;
if (!s)
{
TAILQ_FOREACH(sec, &config, entry)
if(sec->name && !strcmp(sec->name, name)) {
ret = sec;
break;
}
}
else
{
TAILQ_FOREACH(sec, &s->sub, entry)
if (sec->name && !strcmp(sec->name, name)) {
ret = sec;
break;
}
}
return ret;
}
size_t
fetch_section_count(struct conf_sec **s)
{
size_t ret;
for (ret = 0; s[ret]; ret++);
return ret;
}
struct opt_type *
fetch_opt(struct conf_sec *s, char *dfl, char *name)
{
struct conf_opt *o;
struct opt_type *ret;
size_t i = 0;
if (!name)
return NULL;
ret = xcalloc(10, sizeof(struct opt_type));
if (s) {
SLIST_FOREACH(o, &s->optlist, entry)
if (!strcmp(o->name, name)) {
while (o->val[i]) {
o->used = True;
ret[i] = string_to_opt(o->val[i]);
i++;
}
ret[i] = opt_type_null;
return ret;
}
}
ret[0] = string_to_opt(dfl);
ret[1] = opt_type_null;
return ret;
}
struct opt_type
fetch_opt_first(struct conf_sec *s, char *dfl, char *name)
{
struct conf_opt *o;
if (!name)
return opt_type_null;
else if (s)
SLIST_FOREACH(o, &s->optlist, entry)
if (!strcmp(o->name, name)) {
o->used = True;
return string_to_opt(o->val[0]);
}
return string_to_opt(dfl);
}
size_t
fetch_opt_count(struct opt_type *o)
{
size_t ret;
for(ret = 0; o[ret].str; ret++);
return ret;
}

View File

@@ -57,13 +57,13 @@ screen_count(void)
/** Get screen geometry by number /** Get screen geometry by number
*\param s Screen number *\param s Screen number
*\return XRectangle struct *\return Geo struct
*/ */
XRectangle Geo
screen_get_geo(int s) screen_get_geo(int s)
{ {
int barpos = tags[selscreen][seltag[selscreen]].barpos; int barpos = tags[selscreen][seltag[selscreen]].barpos;
XRectangle geo; Geo geo;
geo.x = BORDH; geo.x = BORDH;
if(barpos == IB_Hide || barpos == IB_Bottom) if(barpos == IB_Hide || barpos == IB_Bottom)
@@ -91,6 +91,8 @@ screen_get_geo(int s)
XFree(xsi); XFree(xsi);
} }
#else
(void)s;
#endif /* HAVE_XINERAMA */ #endif /* HAVE_XINERAMA */
return geo; return geo;
@@ -104,14 +106,14 @@ screen_get_geo(int s)
int int
screen_get_with_geo(int x, int y) screen_get_with_geo(int x, int y)
{ {
int i, r = 0; int i;
for(i = 0; i < screen_count(); ++i) for(i = 0; i < screen_count(); ++i)
if((x >= spgeo[i].x && x < spgeo[i].x + spgeo[i].width) if((x >= spgeo[i].x && x < spgeo[i].x + spgeo[i].width)
&& y >= spgeo[i].y && y < spgeo[i].y + spgeo[i].height) && y >= spgeo[i].y && y < spgeo[i].y + spgeo[i].height)
r = i; return i;
return r; return 0;
} }
/** Set the selected screen /** Set the selected screen
@@ -123,12 +125,13 @@ screen_set_sel(int screen)
if(screen < 0 || screen > screen_count() - 1) if(screen < 0 || screen > screen_count() - 1)
screen = 0; screen = 0;
if(selscreen != screen)
prevselscreen = selscreen; prevselscreen = selscreen;
client_focus(NULL); client_focus(NULL);
XWarpPointer(dpy, None, ROOT, 0, 0, 0, 0, XWarpPointer(dpy, None, ROOT, 0, 0, 0, 0,
sgeo[screen].x + sgeo[screen].width / 2, sgeo[screen].x + (sgeo[screen].width >> 1),
sgeo[screen].y + sgeo[screen].height / 2); sgeo[screen].y + (sgeo[screen].height >> 1));
selscreen = screen; selscreen = screen;
@@ -162,7 +165,7 @@ screen_get_sel(void)
XChangeProperty(dpy, ROOT, net_atom[wmfs_current_screen], XA_CARDINAL, 32, XChangeProperty(dpy, ROOT, net_atom[wmfs_current_screen], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&selscreen, 1); PropModeReplace, (uchar*)&selscreen, 1);
if(os != selscreen) if(os != selscreen && os != prevselscreen)
prevselscreen = os; prevselscreen = os;
return selscreen; return selscreen;
@@ -176,8 +179,8 @@ screen_init_geo(void)
int i; int i;
int s = screen_count(); int s = screen_count();
sgeo = emalloc(s, sizeof(XRectangle)); sgeo = xcalloc(s, sizeof(Geo));
spgeo = emalloc(s, sizeof(XRectangle)); spgeo = xcalloc(s, sizeof(Geo));
for(i = 0; i < s; ++i) for(i = 0; i < s; ++i)
sgeo[i] = screen_get_geo(i); sgeo[i] = screen_get_geo(i);
@@ -214,7 +217,6 @@ screen_init_geo(void)
#endif /* HAVE_XRANDR */ #endif /* HAVE_XRANDR */
ewmh_set_desktop_geometry(); ewmh_set_desktop_geometry();
ewmh_set_workarea();
return; return;
} }
@@ -236,11 +238,15 @@ uicb_screen_select(uicb_t cmd)
void void
uicb_screen_next(uicb_t cmd) uicb_screen_next(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
if(screen_count() > 1)
{
selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1; selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1;
screen_set_sel(selscreen); screen_set_sel(selscreen);
}
return; return;
} }
@@ -251,6 +257,7 @@ uicb_screen_next(uicb_t cmd)
void void
uicb_screen_prev(uicb_t cmd) uicb_screen_prev(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
selscreen = (selscreen - 1 < 0) ? screen_count() - 1 : selscreen - 1; selscreen = (selscreen - 1 < 0) ? screen_count() - 1 : selscreen - 1;
@@ -266,6 +273,7 @@ uicb_screen_prev(uicb_t cmd)
void void
uicb_screen_prev_sel(uicb_t cmd) uicb_screen_prev_sel(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
screen_set_sel(prevselscreen); screen_set_sel(prevselscreen);

373
src/split.c Normal file
View File

@@ -0,0 +1,373 @@
/*
* 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) \
{ \
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, cs;
Geo cgeo;
Client *cc;
cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width);
for(s = 0, cgeo = c->frame_geo, cc = tiled_client(c->screen, clients);
cc; cc = tiled_client(c->screen, 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, clients);
cc; cc = tiled_client(c->screen, 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 */
for(b = False, sc = clients; sc; sc = sc->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,94 +32,129 @@
#include "wmfs.h" #include "wmfs.h"
/** Check rectangles blocks in str and return properties /* Systray width */
static int sw = 0;
/** Check rectangles blocks in str and draw it
* --> \b[x;y;width;height;#color]\ * --> \b[x;y;width;height;#color]\
*\param r StatusRec pointer, rectangles properties *\param ib Infobar pointer
*\param str String *\param str String
*\return n Length of r
*/ */
int static void
statustext_rectangle(StatusRec *r, char *str) statustext_rectangle(InfoBar *ib, char *str)
{ {
StatusRec r;
char as; char as;
int n, i, j, k; int i, j, k;
for(i = j = n = 0; i < strlen(str); ++i, ++j) for(i = j = 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 if(sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c", &r.x, &r.y, &r.w, &r.h, &r.color, &as) == 6
&& as == '\\') && as == '\\')
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i); {
draw_rectangle(ib->bar->dr, r.x - sw, r.y, r.w, r.h, r.color);
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i) else if(j != i)
str[j] = str[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 /** Check graphs blocks in str and draw it
* --> \g[x;y;width;height;#color;data]\
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_graph(InfoBar *ib, char *str)
{
StatusGraph g;
char as, c, *p;
int i, j, k, m, w;
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 == '\\')
{
/* 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');
return;
}
/** Check text blocks in str and draw it
* --> \s[x;y;#color;text]\ * --> \s[x;y;#color;text]\
*\param s StatusText pointer, text properties *\param ib Infobar pointer
*\param str String *\param str String
*\return n Length of s
*/ */
int static void
statustext_text(StatusText *s, char *str) statustext_text(InfoBar *ib, char *str)
{ {
StatusText s;
char as; char as;
int n, i, j, k; int i, j, k;
for(i = j = n = 0; i < strlen(str); ++i, ++j) for(i = j = 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 if(sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^]]]%c", &s.x, &s.y, s.color, s.text, &as) == 5
&& as == '\\') && as == '\\')
for(++n, ++i, --j; str[i] != as || str[i - 1] != ']'; ++i); {
draw_text(ib->bar->dr, s.x - sw, s.y, s.color, s.text);
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i) else if(j != i)
str[j] = str[i]; str[j] = str[i];
for(k = j; k < i; str[k++] = 0); for(k = j; k < i; str[k++] = '\0');
return n; 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
statustext_image(ImageAttr *im, char *str)
{
char as;
int n, i, j, k;
for(i = j = n = 0; i < 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 */
/** Draw normal text and colored normal text /** Draw normal text and colored normal text
* --> \#color\ text in color * --> \#color\ text in color
*\param sc Screen *\param sc Screen id
*\param ib Infobar pointer
*\param str String *\param str String
*/ */
void static void
statustext_normal(int sc, char *str) statustext_normal(int sc, InfoBar *ib, char *str)
{ {
char strwc[MAXSTATUS] = { 0 }; char strwc[MAXSTATUS] = { 0 };
char buf[MAXSTATUS] = { 0 }; char buf[MAXSTATUS] = { 0 };
char col[8] = { 0 }; char col[8] = { 0 };
int n, i, j, k; int n, i, j, k, tw;
for(i = j = n = 0; i < strlen(str); ++i, ++j) for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\') if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{ {
++n; ++n;
@@ -130,29 +165,29 @@ statustext_normal(int sc, char *str)
strwc[j] = str[i]; strwc[j] = str[i];
/* Draw normal text without any blocks */ /* Draw normal text without any blocks */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(strwc), draw_text(ib->bar->dr, (sgeo[sc].width - SHADH) - (textw(strwc) + sw), FHINFOBAR, ib->bar->fg, strwc);
FHINFOBAR, infobar[sc].bar->fg, 0, strwc);
if(n) if(n)
{ {
strcpy(buf, strwc); strncpy(buf, strwc, sizeof(buf));
for(i = k = 0; i < strlen(str); ++i, ++k) for(i = k = 0; i < (int)strlen(str); ++i, ++k)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\') if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{ {
tw = textw(&buf[k]);
/* Store current color in col[] */ /* Store current color in col[] */
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]); for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
/* Draw a rectangle with the bar color to draw the text properly */ /* 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]), draw_rectangle(ib->bar->dr, (sgeo[sc].width - SHADH) - (tw + sw),
0, INFOBARH - (sgeo[sc].width - SHADH) - textw(&buf[k]), 0, INFOBARH - (sgeo[sc].width - SHADH) - tw,
INFOBARH, conf.colors.bar); INFOBARH, conf.colors.bar);
/* Draw text with its color */ /* Draw text with its color */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(&buf[k]), draw_text(ib->bar->dr, (sgeo[sc].width - SHADH) - (tw + sw), FHINFOBAR, col, &buf[k]);
FHINFOBAR, col, 0, &buf[k]);
strcpy(buf, strwc); strncpy(buf, strwc, sizeof(buf));
++i; ++i;
} }
} }
@@ -161,45 +196,40 @@ statustext_normal(int sc, char *str)
} }
/** Handle statustext and draw all things in infobar of specified screen /** Handle statustext and draw all things in infobar of specified screen
*\param sc Screen number *\param sc Screen id
*\param str String *\param str String
*/ */
void void
statustext_handle(int sc, char *str) statustext_handle(int sc, char *str)
{ {
InfoBar *ib = &infobar[sc];
char *lastst; char *lastst;
int i, nr, ns, len; int i;
StatusRec r[128];
StatusText s[128];
/* If the str == the current statustext, return (not needed) */ /* If the str == the current statustext, return (not needed) */
if(!str) if(!str)
return; return;
barwin_refresh_color(infobar[sc].bar); if(sc == conf.systray.screen)
sw = systray_get_width();
barwin_refresh_color(ib->bar);
/* save last status text address (for free at the end) */ /* save last status text address (for free at the end) */
lastst = infobar[sc].statustext; lastst = ib->statustext;
infobar[sc].statustext = _strdup(str); ib->statustext = xstrdup(str);
len = ((strlen(str) > MAXSTATUS) ? MAXSTATUS : strlen(str));
/* Store rectangles, located text & images properties. */ /* Store rectangles, located text & images properties. */
nr = statustext_rectangle(r, str); statustext_rectangle(ib, str);
ns = statustext_text(s, str); statustext_graph(ib, str);
statustext_text(ib, str);
/* Draw normal text (and possibly colored with \#color\ blocks) */ /* Draw normal text (and possibly colored with \#color\ blocks) */
statustext_normal(sc, str); statustext_normal(sc, ib, str);
/* Draw rectangles with stored properties. */ sw = 0;
for(i = 0; i < nr; ++i) barwin_refresh(ib->bar);
draw_rectangle(infobar[sc].bar->dr, r[i].x, r[i].y, r[i].w, r[i].h, r[i].color);
/* Draw located text with stored properties. */
for(i = 0; i < ns; ++i)
draw_text(infobar[sc].bar->dr, s[i].x, s[i].y, s[i].color, 0, s[i].text);
barwin_refresh(infobar[sc].bar);
free(lastst); free(lastst);

View File

@@ -37,18 +37,44 @@
#define NBUTTON 8 #define NBUTTON 8
#define MAXTAG 36 #define MAXTAG 36
#define NUM_OF_LAYOUT 10 #define NUM_OF_LAYOUT 11
#define HISTOLEN 128
/* Clients flags definition */ /* Clients flags definition */
#define FreeFlag (1 << 1) #define FreeFlag 0x01
#define MaxFlag (1 << 2) #define MaxFlag 0x02
#define TileFlag (1 << 3) #define TileFlag 0x04
#define HideFlag (1 << 4) #define HideFlag 0x08
#define LMaxFlag (1 << 5) #define LMaxFlag 0x10
#define UnmapFlag (1 << 6) #define UnmapFlag 0x20
#define HintFlag (1 << 7) #define HintFlag 0x40
#define FSSFlag (1 << 8) #define FSSFlag 0x80
#define AboveFlag (1 << 9) #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 */ /* XEMBED messages */
#define XEMBED_MAPPED (1 << 0) #define XEMBED_MAPPED (1 << 0)
@@ -81,12 +107,15 @@ typedef unsigned char uchar;
/* Enum */ /* Enum */
enum { CurNormal, CurResize, CurRightResize, CurLeftResize, CurMove, CurLast }; enum { CurNormal, CurResize, CurRightResize, CurLeftResize, CurMove, CurLast };
enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast };
/* Menu align */
enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 };
/* Infobar position */ /* Infobar position */
enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 }; 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;
/* Ewmh hints list */ /* Ewmh hints list */
enum enum
@@ -99,7 +128,6 @@ enum
net_current_desktop, net_current_desktop,
net_desktop_names, net_desktop_names,
net_desktop_geometry, net_desktop_geometry,
net_workarea,
net_active_window, net_active_window,
net_close_window, net_close_window,
net_wm_icon_name, net_wm_icon_name,
@@ -107,6 +135,7 @@ enum
net_wm_pid, net_wm_pid,
net_showing_desktop, net_showing_desktop,
net_supporting_wm_check, net_supporting_wm_check,
net_wm_window_opacity,
net_wm_window_type_normal, net_wm_window_type_normal,
net_wm_window_type_dock, net_wm_window_type_dock,
net_wm_window_type_splash, net_wm_window_type_splash,
@@ -115,7 +144,16 @@ enum
net_wm_icon, net_wm_icon,
net_wm_state, net_wm_state,
net_wm_state_fullscreen, net_wm_state_fullscreen,
net_wm_state_sticky,
net_wm_state_demands_attention, net_wm_state_demands_attention,
net_wm_system_tray_opcode,
net_system_tray_message_data,
net_system_tray_s,
net_system_tray_visual,
net_system_tray_orientation,
xembed,
xembedinfo,
manager,
utf8_string, utf8_string,
/* WMFS HINTS */ /* WMFS HINTS */
wmfs_running, wmfs_running,
@@ -131,10 +169,18 @@ enum
wmfs_screen_count, wmfs_screen_count,
wmfs_function, wmfs_function,
wmfs_cmd, wmfs_cmd,
wmfs_font,
wmfs_statustext, wmfs_statustext,
net_last net_last
}; };
/* Geometry structure */
typedef struct
{
int x, y;
int width, height;
} Geo;
/* /*
* BarWindow Structure * BarWindow Structure
* (titlebar, infobar..) * (titlebar, infobar..)
@@ -154,8 +200,8 @@ typedef struct
uint bg; uint bg;
char *fg; char *fg;
uint stipple_color; uint stipple_color;
XRectangle geo; Geo geo;
Bool mapped, stipple, bord; uint flags;
} BarWindow; } BarWindow;
/* Client Structure. */ /* Client Structure. */
@@ -166,18 +212,17 @@ struct Client
char *title; char *title;
/* Tag num */ /* Tag num */
uint tag; uint tag;
int focusontag;
/* Screen */ /* Screen */
int screen; int screen;
/* Layer */
int layer;
/* Window attribute */ /* Window attribute */
XRectangle geo; Geo geo, pgeo; /* Window geo, tiling pure geo */
XRectangle tmp_geo; Geo tmp_geo, wrgeo; /* Temporary geo, without resizehint geo */
XRectangle frame_geo; Geo frame_geo; /* Frame geo */
/* Old window attribute */ Geo ogeo; /* Old window attribute */
XRectangle ogeo; Geo split_geo, free_geo; /* Split & Free window attribute */
/* Free window attribute */ /* Tile size factors */
XRectangle free_geo; int tilefact[4];
/* For resizehint usage */ /* For resizehint usage */
int basew, baseh, incw, inch; int basew, baseh, incw, inch;
int maxw, maxh, minw, minh; int maxw, maxh, minw, minh;
@@ -196,6 +241,7 @@ struct Client
uint frame; uint frame;
char *fg; char *fg;
uint resizecorner; uint resizecorner;
uint bordlight, borddark;
} colors; } colors;
/* Client Information by flags */ /* Client Information by flags */
uint flags; uint flags;
@@ -229,32 +275,47 @@ typedef struct
BarWindow *bar, *selbar; BarWindow *bar, *selbar;
BarWindow *layout_button; BarWindow *layout_button;
BarWindow *tags_board, *tags[MAXTAG]; BarWindow *tags_board, *tags[MAXTAG];
XRectangle geo; Geo geo;
int position; int screen, position;
char *statustext; char *statustext;
bool need_update;
} InfoBar; } InfoBar;
/* Layout Structure */ /* Layout Structure */
typedef struct typedef struct
{ {
uint flags; /* Flags */
Client *nc; /* New client needing integration */
Client ghost; /* Ghost client to arrange hole in split */
char *symbol; char *symbol;
char *type;
void (*func)(int screen); void (*func)(int screen);
} Layout; } Layout;
/* Systray Structure */
typedef struct Systray Systray;
struct Systray
{
Window win;
Geo geo;
Systray *next, *prev;
};
/* Tag Structure */ /* Tag Structure */
typedef struct typedef struct
{ {
char *name; char *name;
char **clients; char **clients;
int nclients; int nclients;
int layers;
float mwfact; float mwfact;
int nmaster; int nmaster;
Bool resizehint; uint flags;
Bool request_update;
Bool abovefc;
int barpos; int barpos;
int prev_barpos;
Layout layout; Layout layout;
uint tagad;
MouseBinding *mouse;
int nmouse;
} Tag; } Tag;
/* Menu Item Struct */ /* Menu Item Struct */
@@ -263,6 +324,8 @@ typedef struct
char *name; char *name;
void (*func)(uicb_t); void (*func)(uicb_t);
uicb_t cmd; uicb_t cmd;
bool (*check)(uicb_t);
char *submenu;
} MenuItem; } MenuItem;
/* Menu Struct */ /* Menu Struct */
@@ -274,7 +337,8 @@ typedef struct
*/ */
char *name; char *name;
/* Placement */ /* Placement */
Bool place_at_mouse; bool place_at_mouse;
int align;
int x, y; int x, y;
/* Color */ /* Color */
struct struct
@@ -294,6 +358,9 @@ typedef struct
char *name; char *name;
char *prompt; char *prompt;
char *command; char *command;
char histo[HISTOLEN][512];
uint nhisto;
int width;
} Launcher; } Launcher;
/* Button struct */ /* Button struct */
@@ -313,6 +380,20 @@ typedef struct
char *content; char *content;
} Alias; } Alias;
/* Rule struct */
typedef struct
{
char *class;
char *instance;
char *role;
int screen;
int tag;
bool free;
bool max;
bool ignoretags;
bool follow_client;
} Rule;
/* Configuration structure */ /* Configuration structure */
typedef struct typedef struct
{ {
@@ -321,13 +402,22 @@ typedef struct
/* Misc option */ /* Misc option */
char *font; char *font;
Bool raisefocus; bool use_xft;
Bool raiseswitch; uint opacity;
Bool focus_fmouse; bool raisefocus;
Bool ignore_next_client_rules; bool focus_fmouse;
bool focus_fmov;
bool focus_pclick;
bool ignore_next_client_rules;
bool tagautohide;
bool tagnamecount;
Tag default_tag;
uint pad; uint pad;
int status_timing; int status_timing;
char *status_path; char *status_path;
pid_t status_pid;
char *autostart_path;
char *autostart_command;
struct struct
{ {
/* /*
@@ -337,20 +427,35 @@ typedef struct
uint bar; uint bar;
char *text; char *text;
char *tagselfg; char *tagselfg;
char *tagurfg;
uint tagurbg;
uint tagselbg; uint tagselbg;
uint tag_occupied_bg; uint tag_occupied_bg;
char *tag_occupied_fg;
uint tagbord; uint tagbord;
char *layout_fg; char *layout_fg;
uint layout_bg; uint layout_bg;
float client_light_shade;
float client_dark_shade;
float bar_light_shade;
float bar_dark_shade;
} colors; } colors;
struct struct
{ {
int height; int height;
MouseBinding *mouse; MouseBinding *mouse;
int nmouse; int nmouse;
Bool selbar; bool selbar;
} bars; } bars;
struct struct
{
char *fg;
uint bg;
int maxlength;
MouseBinding *mouse;
int nmouse;
} selbar;
struct
{ {
char *background_command; char *background_command;
MouseBinding *mouse; MouseBinding *mouse;
@@ -358,17 +463,22 @@ typedef struct
} root; } root;
struct struct
{ {
Bool set_new_win_master; bool set_new_win_master;
Bool place_at_mouse; bool place_at_mouse;
Bool border_shadow; bool border_shadow;
bool new_client_get_mouse;
int borderheight; int borderheight;
char *autofree, *automax;
uint bordernormal; uint bordernormal;
uint borderfocus; uint borderfocus;
uint resizecorner_normal; uint resizecorner_normal;
uint resizecorner_focus; uint resizecorner_focus;
uint mod; uint mod;
uint padding;
MouseBinding *mouse; MouseBinding *mouse;
int nmouse; int nmouse;
uint default_open_tag;
int default_open_screen;
} client; } client;
struct struct
{ {
@@ -377,7 +487,7 @@ typedef struct
char *fg_focus; char *fg_focus;
struct struct
{ {
Bool active; bool active;
struct { uint normal, focus; } colors; struct { uint normal, focus; } colors;
} stipple; } stipple;
MouseBinding *mouse; MouseBinding *mouse;
@@ -387,41 +497,77 @@ typedef struct
} titlebar; } titlebar;
struct struct
{ {
Bool bar; bool bar;
Bool tag; bool tag;
Bool layout; bool layout;
} border; } border;
struct
{
bool active;
int screen;
int spacing;
} systray;
Alias alias[256]; Alias alias[256];
uint mouse_tag_action[TagActionLast];
int layout_button_width;
Layout layout[NUM_OF_LAYOUT]; Layout layout[NUM_OF_LAYOUT];
Menu *menu; Menu *menu;
Launcher *launcher; Launcher *launcher;
Rule *rule;
int *ntag; int *ntag;
Bool tag_round; bool tag_round;
Bool layout_system; /* Switch: False, Menu: True. */ bool tag_auto_prev;
Bool layout_placement; /* Right (normal): False, Left: True. */ 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 cfactor_enable_split;
char *tag_expose_name;
char *expose_layout;
char *selected_layout_symbol;
/* Number of... */ /* Number of... */
int nkeybind; int nkeybind;
int nlayout; int nlayout;
int nmenu; int nmenu;
int nlauncher; int nlauncher;
int nrule;
} Conf; } Conf;
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
{
int x, y, w, h;
uint color; uint color;
} StatusRec; } StatusRec;
typedef struct typedef struct
{ {
uint x, y; int x, y, w, h;
uint color;
char data[512];
} StatusGraph;
typedef struct
{
int x, y;
char color[8]; char color[8];
char text[512]; char text[512];
} StatusText; } StatusText;
typedef struct typedef struct
{ {
uint x, y, w, h; int x, y, w, h;
char name[512]; char name[512];
} ImageAttr; } ImageAttr;
@@ -450,4 +596,10 @@ typedef struct
char *uicb; char *uicb;
} vicmd_to_uicb; } vicmd_to_uicb;
typedef struct
{
int version;
int flags;
} xembed_info;
#endif /* STRUCTS_H */ #endif /* STRUCTS_H */

234
src/systray.c Normal file
View File

@@ -0,0 +1,234 @@
/*
* systray.c
* Copyright © 2008, 2009, 2010 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
#define TRAY_DWIDTH (infobar[conf.systray.screen].bar->geo.height + conf.systray.spacing)
bool
systray_acquire(void)
{
XSetWindowAttributes wattr;
if(!conf.systray.active || traywin)
return False;
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != None)
{
warnx("Can't initialize system tray: owned by another process");
return False;
}
/* Init traywin window */
wattr.event_mask = ButtonPressMask | ExposureMask;
wattr.override_redirect = True;
wattr.background_pixmap = ParentRelative;
wattr.background_pixel = conf.colors.bar;
traywin = XCreateSimpleWindow(dpy, infobar[conf.systray.screen].bar->win, -1, -1, 1, 1, 0, 0, conf.colors.bar);
XChangeWindowAttributes(dpy, traywin, CWEventMask | CWOverrideRedirect | CWBackPixel, &wattr);
XSelectInput(dpy, traywin, KeyPressMask | ButtonPressMask);
XMapRaised(dpy, traywin);
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], traywin, CurrentTime);
if(XGetSelectionOwner(dpy, net_atom[net_system_tray_s]) != traywin)
{
systray_freeicons();
warnx("System tray: can't get systray manager");
return False;
}
ewmh_send_message(ROOT, ROOT, "MANAGER", CurrentTime, net_atom[net_system_tray_s], traywin, 0, 0);
XSync(dpy, False);
return True;
}
void
systray_add(Window win)
{
Systray *s;
if(!conf.systray.active)
return;
s = xcalloc(1, sizeof(Systray));
s->win = win;
s->geo.height = infobar[conf.systray.screen].bar->geo.height;
s->geo.width = TRAY_DWIDTH;
setwinstate(s->win, WithdrawnState);
XSelectInput(dpy, s->win, StructureNotifyMask | PropertyChangeMask| EnterWindowMask | FocusChangeMask);
XReparentWindow(dpy, s->win, traywin, 0, 0);
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0, traywin, 0);
/* Attach */
if(trayicons)
trayicons->prev = s;
s->next = trayicons;
trayicons = s;
return;
}
void
systray_del(Systray *s)
{
Systray **ss;
if(!conf.systray.active)
return;
for(ss = &trayicons; *ss && *ss != s; ss = &(*ss)->next);
*ss = s->next;
free(s);
return;
}
void
systray_state(Systray *s)
{
long flags;
int code = 0;
if(!(flags = ewmh_get_xembed_state(s->win)) || !conf.systray.active)
return;
if(flags & XEMBED_MAPPED)
{
code = XEMBED_WINDOW_ACTIVATE;
XMapRaised(dpy, s->win);
setwinstate(s->win, NormalState);
}
else
{
code = XEMBED_WINDOW_DEACTIVATE;
XUnmapWindow(dpy, s->win);
setwinstate(s->win, WithdrawnState);
}
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, code, 0, 0, 0);
return;
}
void
systray_freeicons(void)
{
Systray *i;
if(!conf.systray.active)
return;
for(i = trayicons; i; i = i->next)
{
XUnmapWindow(dpy, i->win);
XReparentWindow(dpy, i->win, ROOT, 0, 0);
free(i);
}
XSetSelectionOwner(dpy, net_atom[net_system_tray_s], None, CurrentTime);
XDestroyWindow(dpy, traywin);
XSync(dpy, 0);
return;
}
Systray*
systray_find(Window win)
{
Systray *i;
if(!conf.systray.active)
return NULL;
for(i = trayicons; i; i = i->next)
if(i->win == win)
return i;
return NULL;
}
int
systray_get_width(void)
{
int w = 0;
Systray *i;
if(!conf.systray.active)
return 0;
for(i = trayicons; i; i = i->next)
w += i->geo.width + conf.systray.spacing + 1;
return w;
}
void
systray_update(void)
{
Systray *i;
int x = 1;
if(!conf.systray.active)
return;
if(!trayicons)
{
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
return;
}
for(i = trayicons; i; i = i->next)
{
XMapWindow(dpy, i->win);
XMoveResizeWindow(dpy, i->win, (i->geo.x = x), 0, i->geo.width, i->geo.height);
x += i->geo.width + conf.systray.spacing;
}
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - x,
0, x, infobar[conf.systray.screen].bar->geo.height);
return;
}

588
src/tag.c
View File

@@ -39,10 +39,20 @@ void
tag_set(int tag) tag_set(int tag)
{ {
Client *c; Client *c;
bool al = False;
int i;
if(tag < 0 || tag > MAXTAG)
return;
screen_get_sel(); screen_get_sel();
if(seltag[selscreen] != tag)
prevseltag[selscreen] = seltag[selscreen]; prevseltag[selscreen] = seltag[selscreen];
else if(tag == seltag[selscreen] && tag != prevseltag[selscreen] && conf.tag_auto_prev)
tag = seltag[selscreen] = prevseltag[selscreen];
else
seltag[selscreen] = tag;
if(conf.tag_round) if(conf.tag_round)
{ {
@@ -55,8 +65,7 @@ tag_set(int tag)
} }
else else
{ {
if(!tag || tag == seltag[selscreen] if(!tag || tag > conf.ntag[selscreen])
|| tag > conf.ntag[selscreen])
return; return;
seltag[selscreen] = tag; seltag[selscreen] = tag;
@@ -65,20 +74,51 @@ tag_set(int tag)
ewmh_update_current_tag_prop(); ewmh_update_current_tag_prop();
/* Arrange infobar position */ /* Arrange infobar position */
if(tags[selscreen][prevseltag[selscreen]].barpos != tags[selscreen][seltag[selscreen]].barpos) if(tags[selscreen][prevseltag[selscreen]].barpos != tags[selscreen][seltag[selscreen]].barpos
|| prevseltag[selscreen] == seltag[selscreen])
infobar_set_position(tags[selscreen][seltag[selscreen]].barpos); infobar_set_position(tags[selscreen][seltag[selscreen]].barpos);
arrange(selscreen, False); /* Check if a layout update is needed with additional tags */
if(tags[selscreen][seltag[selscreen]].tagad)
if(tags[selscreen][tag].request_update) al = True;
else if(tags[selscreen][seltag[selscreen]].flags & RequestUpdateFlag)
{ {
tags[selscreen][seltag[selscreen]].layout.func(selscreen); al = True;
tags[selscreen][tag].request_update = False; tags[selscreen][seltag[selscreen]].flags &= ~RequestUpdateFlag;
} }
/* To focus the first client in the new tag */ for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(tags[selscreen][i].tagad & TagFlag(seltag[selscreen]))
{
al = True;
break;
}
/* Check for ignore_tag clients */
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
if(c->tag == seltag[selscreen] && c->screen == selscreen) if(c->tag == MAXTAG + 1 && c->screen == selscreen)
{
al = True;
break;
}
arrange(selscreen, al);
if(tags[selscreen][tag].flags & RequestUpdateFlag)
{
layout_func(selscreen, tag);
tags[selscreen][tag].flags &= ~RequestUpdateFlag;
}
/* To focus selected client of the via focusontag option */
for(c = clients; c; c = c->next)
if(c->focusontag == tag && c->screen == selscreen)
break;
/* No focusontag option found on any client, try to find the first of the tag */
if(!c)
for(c = clients; c; c = c->next)
if(c->tag == (uint)seltag[selscreen] && c->screen == selscreen)
break; break;
client_focus((c) ? c : NULL); client_focus((c) ? c : NULL);
@@ -93,24 +133,43 @@ tag_set(int tag)
void void
tag_transfert(Client *c, int tag) tag_transfert(Client *c, int tag)
{ {
screen_get_sel(); int s;
CHECK(c); CHECK(c);
if(!tag) screen_get_sel();
if(tag <= 0)
tag = 1; tag = 1;
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->tag = tag;
c->screen = selscreen; c->screen = selscreen;
if(s != c->screen)
arrange(s, True);
arrange(c->screen, True); arrange(c->screen, True);
if(c == sel && c->tag != tag) client_focus_next(c);
client_focus(NULL);
client_update_attributes(c); client_update_attributes(c);
tags[c->screen][tag].request_update = True; tags[c->screen][tag].flags |= RequestUpdateFlag;
return; return;
} }
@@ -137,6 +196,7 @@ uicb_tag(uicb_t cmd)
void void
uicb_tag_next(uicb_t cmd) uicb_tag_next(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
tag_set(seltag[selscreen] + 1); tag_set(seltag[selscreen] + 1);
@@ -150,6 +210,7 @@ uicb_tag_next(uicb_t cmd)
void void
uicb_tag_prev(uicb_t cmd) uicb_tag_prev(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
tag_set(seltag[selscreen] - 1); tag_set(seltag[selscreen] - 1);
@@ -157,6 +218,184 @@ uicb_tag_prev(uicb_t cmd)
return; return;
} }
/** Set the next visible tag
* \param cmd uicb_t type unused
*/
void
uicb_tag_next_visible(uicb_t cmd)
{
int tag;
Client *c;
uint occupied = 0;
(void)cmd;
screen_get_sel();
if(!conf.tagautohide)
{
tag_set(seltag[selscreen] + 1);
return;
}
for(c = clients; c; c = c->next)
if(c->screen == selscreen)
occupied |= TagFlag(c->tag);
for(tag = seltag[selscreen] + 1; tag < conf.ntag[selscreen] + 1; ++tag)
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
}
if(conf.tag_round)
for(tag = 0; tag < seltag[selscreen]; ++tag)
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
}
return;
}
/** Set the prev visible tag
* \param cmd uicb_t type unused
*/
void
uicb_tag_prev_visible(uicb_t cmd)
{
int tag;
Client *c;
uint occupied = 0;
(void)cmd;
screen_get_sel();
if(!conf.tagautohide)
{
tag_set(seltag[selscreen] - 1);
return;
}
for(c = clients; c; c = c->next)
if(c->screen == selscreen)
occupied |= TagFlag(c->tag);
for(tag = seltag[selscreen] - 1; tag >= 0; --tag)
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
}
if(conf.tag_round)
for(tag = conf.ntag[selscreen]; tag > seltag[selscreen]; --tag)
if(occupied & TagFlag(tag))
{
tag_set(tag);
return;
}
return;
}
/** Go to the last tag
*\param cmd uicb_t type unused
*/
void
uicb_tag_last(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
tag_set(conf.ntag[selscreen]);
return;
}
/**
*\param selscreen int
*/
static void
remove_old_last_tag(int selscreen)
{
int i;
for(i = 0; i <= conf.ntag[selscreen]; i++)
{
if(tags[selscreen][i].flags & StayLastFlag)
{
tags[selscreen][i].flags &= ~StayLastFlag;
break;
}
}
return;
}
/** Swap 2 tags
*\param s Screen
*\param t1 Tag 1
*\param t2 Tag 2
*/
static void
tag_swap(int s, int t1, int t2)
{
Client *c;
Tag t;
if(t1 == 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)
{
if(c->screen == s && c->tag == (uint)t1)
c->tag = t2;
else if(c->screen == s && c->tag == (uint)t2)
c->tag = t1;
}
infobar_update_taglist(&infobar[s]);
tag_set(t2);
return;
}
/** Keep that tag the last one
*\param cmd uicb_t type unused
*/
void
uicb_tag_stay_last(uicb_t cmd)
{
int i;
(void)cmd;
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].flags & StayLastFlag)
tags[selscreen][seltag[selscreen]].flags &= ~StayLastFlag;
else
{
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]].flags |= StayLastFlag;
arrange(selscreen, True);
}
return;
}
/** Transfert the selected client to /** Transfert the selected client to
* the wanted tag * the wanted tag
* \param cmd Wanted tag, uicb_t type * \param cmd Wanted tag, uicb_t type
@@ -177,6 +416,7 @@ uicb_tagtransfert(uicb_t cmd)
void void
uicb_tag_prev_sel(uicb_t cmd) uicb_tag_prev_sel(uicb_t cmd)
{ {
(void)cmd;
screen_get_sel(); screen_get_sel();
tag_set(prevseltag[selscreen]); tag_set(prevseltag[selscreen]);
@@ -192,6 +432,7 @@ uicb_tagtransfert_next(uicb_t cmd)
{ {
CHECK(sel); CHECK(sel);
int tag = seltag[selscreen] + 1; int tag = seltag[selscreen] + 1;
(void)cmd;
if(tag > conf.ntag[selscreen]) if(tag > conf.ntag[selscreen])
{ {
@@ -212,6 +453,7 @@ uicb_tagtransfert_prev(uicb_t cmd)
{ {
CHECK(sel); CHECK(sel);
int tag = seltag[selscreen] - 1; int tag = seltag[selscreen] - 1;
(void)cmd;
if(tag <= 0) if(tag <= 0)
{ {
@@ -223,3 +465,317 @@ uicb_tagtransfert_prev(uicb_t cmd)
return; return;
} }
/** Go to the current urgent tag
*\param cmd uicb_t type unused
*/
void
uicb_tag_urgent(uicb_t cmd)
{
Client *c;
(void)cmd;
/* Check if there is a urgent client */
for(c = clients; c; c = c->next)
if(c->flags & UrgentFlag)
{
screen_set_sel(c->screen);
tag_set(c->tag);
client_focus(c);
break;
}
return;
}
/** Add an additional tag to the current tag
*\param sc Screen
*\param tag Tag where apply additional tag
*\param adtag Additional tag to apply in tag
*/
void
tag_additional(int sc, int tag, int adtag)
{
if(tag < 0 || (tag | adtag) > conf.ntag[sc] + 1
|| adtag < 1 || adtag == seltag[sc])
return;
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;
}
/** Add an additional tag to the current tag
*\param cmd uicb_t
*/
void
uicb_tag_toggle_additional(uicb_t cmd)
{
screen_get_sel();
tag_additional(selscreen, seltag[selscreen], atoi(cmd));
return;
}
/** Swap current tag with a specified tag
*\param cmd uicb_t type
*/
void
uicb_tag_swap(uicb_t cmd)
{
screen_get_sel();
tag_swap(selscreen, seltag[selscreen], atoi(cmd));
return;
}
/** Swap current tag with next tag
*\param cmd uicb_t type
*/
void
uicb_tag_swap_next(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
/* Check if the next one does have the stay_last bool */
if(!(tags[selscreen][conf.ntag[selscreen]].flags & StayLastFlag))
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] + 1);
else
warnx("The next tag is set to always stay the last one");
return;
}
/** Swap current tag with previous tag
*\param cmd uicb_t type
*/
void
uicb_tag_swap_previous(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
tag_swap(selscreen, seltag[selscreen], seltag[selscreen] - 1);
return;
}
/** Adding a tag
*\param s Screen number
*\param name New tag name
*/
static void
tag_new(int s, char *name)
{
char * displayedName;
int goToTag;
if(conf.ntag[s] + 1 > MAXTAG)
{
warnx("Too many tag: Can't create new tag");
return;
}
++conf.ntag[s];
/* TODO: memleak here */
if(!name || strlen(name) == 0)
{
if(conf.tagnamecount)
{
/* displayedName = zmalloc(2); */
xasprintf(&displayedName, "[%d]", conf.ntag[s]);
}
else
displayedName = conf.default_tag.name;
}
else
displayedName = xstrdup(name);
Tag t = { displayedName, NULL, 0,
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].flags & StayLastFlag)
{
tag_swap(s, conf.ntag[s], conf.ntag[s] - 1);
goToTag = conf.ntag[s] - 1;
}
else
goToTag = conf.ntag[s];
infobar_update_taglist(&infobar[s]);
infobar_draw(&infobar[s]);
tag_set(goToTag);
return;
}
/** Adding a tag
*\param cmd uicb_t type
*/
void
uicb_tag_new(uicb_t cmd)
{
screen_get_sel();
tag_new(selscreen, (char*)cmd);
return;
}
/** Delete a tag
*\param s Screen number
*\param tag Tag number
*/
static void
tag_delete(int s, int tag)
{
Tag t;
Client *c;
size_t i;
memset(&t, 0, sizeof(t));
if(tag < 0 || tag > conf.ntag[s] || conf.ntag[s] == 1)
return;
for(c = clients; c; c = c->next)
if(c->screen == s && c->tag == (uint)tag)
{
warnx("Client(s) present in this tag, can't delete it");
return;
}
--conf.ntag[s];
tags[s][tag] = t;
infobar[s].tags[tag] = NULL;
for(i = tag; i < (size_t)conf.ntag[s] + 1; ++i)
{
/* Set clients tag because of shift */
for(c = clients; c; c = c->next)
if(c->screen == s && c->tag == i + 1)
c->tag = i;
/* shift */
tags[s][i] = tags[s][i + 1];
}
infobar[s].need_update = True;
infobar_update_taglist(&infobar[s]);
infobar_draw(&infobar[s]);
if(tag == seltag[s])
tag_set(tag <= conf.ntag[s] ? tag : conf.ntag[s]);
return;
}
/** Delete a tag
*\param cmd uicb_t type
*/
void
uicb_tag_del(uicb_t cmd)
{
int n;
screen_get_sel();
if(cmd == NULL || !(n = atoi(cmd)))
n = seltag[selscreen];
tag_delete(selscreen, n);
return;
}
/** Rename the selected tag
*\param cmd uicb_t type
*/
void
uicb_tag_rename(uicb_t cmd)
{
screen_get_sel();
char *str;
size_t len;
if(!cmd || !strlen(cmd))
return;
str = tags[selscreen][seltag[selscreen]].name;
len = strlen(str);
/* TODO: if strlen(cmd) > len, the tag name
* will be truncated...
* We can't do a realloc because if the pointer change
* free() on paser will segfault.on free_conf()...
*/
strncpy(str, cmd, len);
infobar_update_taglist(&infobar[selscreen]);
infobar_draw(&infobar[selscreen]);
return;
}
void
uicb_tag_toggle_expose(uicb_t cmd)
{
(void)cmd;
int i, j;
screen_get_sel();
for(i = 1; i <= conf.ntag[selscreen]; i++)
{
if(strcmp(tags[selscreen][i].name, conf.tag_expose_name) == 0)
{
if(clients && sel->tag)
tag_set(sel->tag);
tag_delete(selscreen, i);
for(j = 0; j < conf.ntag[selscreen]; j++)
tags[selscreen][j].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];
for(i = 1; i < conf.ntag[selscreen]; ++i)
tags[selscreen][conf.ntag[selscreen]].tagad ^= TagFlag(i);
tags[selscreen][conf.ntag[selscreen]].flags |= RequestUpdateFlag;
arrange(selscreen, True);
return;
}

View File

@@ -30,24 +30,103 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include "wmfs.h" #include "wmfs.h"
/** Calloc with an error message if there is a probleme /** malloc with error support and size_t overflow protection
* \param element Element * \param nmemb number of objects
* \param size Size * \param size size of single object
* \return void pointer * \return non null void pointer
*/ */
void* void *
emalloc(uint element, uint size) xmalloc(size_t nmemb, size_t size)
{ {
void *ret = calloc(element, size); void *ret;
if(!ret) if (SIZE_MAX / nmemb < size)
warn("calloc()"); err(EXIT_FAILURE, "xmalloc(%zu, %zu), "
"size_t overflow detected", nmemb, size);
if ((ret = malloc(nmemb * size)) == NULL)
err(EXIT_FAILURE, "malloc(%zu)", nmemb * size);
return ret; return ret;
} }
/** calloc with error support
* \param nmemb Number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xcalloc(size_t nmemb, size_t size)
{
void *ret;
if ((ret = calloc(nmemb, size)) == NULL)
err(EXIT_FAILURE, "calloc(%zu * %zu)", nmemb, size);
return ret;
}
/** realloc with error support and size_t overflow check
* \param ptr old pointer
* \param nmemb number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xrealloc(void *ptr, size_t nmemb, size_t size)
{
void *ret;
if (SIZE_MAX / nmemb < size)
err(EXIT_FAILURE, "xrealloc(%p, %zu, %zu), "
"size_t overflow detected", ptr, nmemb, size);
if ((ret = realloc(ptr, nmemb * size)) == NULL)
err(EXIT_FAILURE, "realloc(%p, %zu)", ptr, nmemb * size);
return ret;
}
/** strdup with error support
* \param str char pointer
* \retun non null void pointer
*/
char *
xstrdup(const char *str)
{
char *ret;
if (str == NULL || (ret = strdup(str)) == NULL)
err(EXIT_FAILURE, "strdup(%s)", str);
return ret;
}
/** asprintf wrapper
* \param strp target string
* \param fmt format
* \return non zero integer
*/
int
xasprintf(char **strp, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
ret = vasprintf(strp, fmt, args);
va_end(args);
if (ret == -1)
err(EXIT_FAILURE, "asprintf(%s)", fmt);
return ret;
}
/** Get a color with a string /** Get a color with a string
* \param color Color string * \param color Color string
* \return Color pixel * \return Color pixel
@@ -63,21 +142,6 @@ getcolor(char *color)
return xcolor.pixel; return xcolor.pixel;
} }
/** Enlight an hexadecimal color
* \param col Color
* \return The clarified color
*/
ulong
color_enlight(ulong col)
{
if((col + 0x330000) < 0xffffff
&& (col + 0x003300) < 0xffffff
&& (col + 0x000033) < 0xffffff)
return col + 0x333333;
else
return col;
}
/** Set the window WM State /** Set the window WM State
* \param win Window target * \param win Window target
* \param state WM State * \param state WM State
@@ -93,20 +157,6 @@ setwinstate(Window win, long state)
return; return;
} }
/** My strdup. the strdup of string.h isn't ansi compatible..
* Thanks linkdd.
* \param str char pointer
*/
char*
_strdup(const char *str)
{
char *ret = emalloc(strlen(str) + 1, sizeof(char));
strcpy(ret, str);
return ret;
}
/* The following function are for configuration /* The following function are for configuration
usage. {{{ usage. {{{
*/ */
@@ -116,7 +166,7 @@ name_to_func(char *name, const func_name_list_t *l)
int i; int i;
if(name) if(name)
for(i = 0; l[i].name ; ++i) for(i = 0; l[i].name; ++i)
if(!strcmp(name, l[i].name)) if(!strcmp(name, l[i].name))
return l[i].func; return l[i].func;
@@ -160,84 +210,47 @@ layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t lli
return lt[0]; return lt[0];
} }
char*
alias_to_str(char *conf_choice)
{
int i;
char *tmpchar = NULL;
if(!conf_choice)
return 0;
if(conf.alias)
for(i = 0; conf.alias[i].name; i++)
if(!strcmp(conf_choice, conf.alias[i].name))
tmpchar = conf.alias[i].content;
if(tmpchar)
return _strdup(tmpchar);
else
return _strdup(conf_choice);
return NULL;
}
/* }}} */ /* }}} */
/** Get the mouse pointer position.
*/
XRectangle
get_mouse_pos(void)
{
Window dum;
int d, u;
XRectangle ret;
XQueryPointer(dpy, ROOT, &dum, &dum, (int*)&ret.x, (int*)&ret.y, &d, &d, (uint *)&u);
return ret;
}
/** Execute a sh command /** Execute a sh command
* \param cmd Command * \param cmd Command
* \return child pid
*/ */
void pid_t
spawn(const char *format, ...) spawn(const char *format, ...)
{ {
char *sh = NULL; char *sh = NULL;
char cmd[512]; char cmd[512];
va_list ap; va_list ap;
pid_t pid;
if(strlen(format) > 511) size_t len;
{
warnx("spawn(): Error, command too long.");
return;
}
va_start(ap, format); va_start(ap, format);
vsprintf(cmd, format, ap); len = vsnprintf(cmd, sizeof(cmd), format, ap);
va_end(ap); va_end(ap);
if(!strlen(cmd)) if (len >= sizeof(cmd))
return; {
warnx("command too long (> 512 bytes)");
return -1;
}
if(!(sh = getenv("SHELL"))) if(!(sh = getenv("SHELL")))
sh = "/bin/sh"; sh = "/bin/sh";
if(fork() == 0) if((pid = fork()) == 0)
{
if(fork() == 0)
{ {
if(dpy) if(dpy)
close(ConnectionNumber(dpy)); close(ConnectionNumber(dpy));
setsid(); setsid();
execl(sh, sh, "-c", cmd, (char*)NULL); if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
exit(EXIT_SUCCESS); warn("execl(sh -c %s)", cmd);
} exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
} }
else if (pid == -1)
warn("fork");
return; return pid;
} }
/** Swap two pointer. /** Swap two pointer.
@@ -262,31 +275,53 @@ void
uicb_spawn(uicb_t cmd) uicb_spawn(uicb_t cmd)
{ {
spawn("%s", cmd); spawn("%s", cmd);
return;
} }
#ifdef HAVE_IMLIB char*
/** Check images blocks in str and return properties clean_value(char *str)
* --> \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 i;
int n, i, j, k; char c, *p;
for(i = j = n = 0; i < strlen(str); ++i, ++j) if(!str || !(p = xstrdup(str)))
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 return NULL;
&& 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); /* Remove useless spaces */
for(; *p == ' '; ++p);
for(; *(p + strlen(p) - 1) == ' '; *(p + strlen(p) - 1) = '\0');
return n; /* For string delimiter (" or ') */
if(((c = *p) == '"' || (c = *p) == '\'') && strchr(p + 1, c))
{
for(++p, i = 0; p[i] && p[i] != c; ++i);
p[i] = '\0';
}
return p;
}
/* To use ~/ shortcut.. */
char*
patht(char *path)
{
static char ret[512];
if(!path)
return NULL;
strncpy(ret, path, sizeof(ret));
ret[sizeof(ret) - 1] = 0;
if(strstr(path, "~/"))
snprintf(ret, sizeof(ret), "%s/%s", getenv("HOME"), path + 2);
return ret;
}
int
qsort_string_compare (const void * a, const void * b)
{
return (strcmp(*(char **)a, *(char **)b));
} }
#endif /* HAVE_IMLIB */

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"
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"},
};
void
viwmfs_help(void)
{
int 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)
{
int i;
char *cmd, str[256] = { 0 };
Bool e;
if(!argc)
return;
if(argc > 3)
{
for(i = 2; i < argc; ++i)
{
strcat(str, argv[i]);
if(*(str + strlen(str) - 1) != ':')
strcat(str, " ");
}
}
else
strcpy(str, argv[2]);
if(!strcmp(str, "help"))
{
viwmfs_help();
return;
}
if(*str == ':')
{
for(i = 0; i < strlen(str); str[i] = str[i + 1], ++i);
cmd = _strdup(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,11 +32,13 @@
#include "wmfs.h" #include "wmfs.h"
static volatile bool exiting = False, sig_chld = False;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
int int
errorhandler(Display *d, XErrorEvent *event) errorhandler(Display *d, XErrorEvent *event)
{ {
char mess[256]; char mess[256];
Client *c;
/* Check if there is another WM running */ /* Check if there is another WM running */
if(BadAccess == event->error_code if(BadAccess == event->error_code
@@ -48,7 +50,7 @@ errorhandler(Display *d, XErrorEvent *event)
* 42 = X_SetInputFocus * 42 = X_SetInputFocus
* 28 = X_GrabButton * 28 = X_GrabButton
*/ */
if((c = client_gb_win(event->resourceid))) if(client_gb_win(event->resourceid))
if(event->error_code == BadWindow if(event->error_code == BadWindow
|| event->request_code == 42 || event->request_code == 42
|| event->request_code == 28) || event->request_code == 28)
@@ -68,6 +70,8 @@ errorhandler(Display *d, XErrorEvent *event)
int int
errorhandlerdummy(Display *d, XErrorEvent *event) errorhandlerdummy(Display *d, XErrorEvent *event)
{ {
(void)d;
(void)event;
return 0; return 0;
} }
@@ -77,7 +81,7 @@ void
quit(void) quit(void)
{ {
Client *c; Client *c;
int i; size_t i, len;
/* Set the silent error handler */ /* Set the silent error handler */
XSetErrorHandler(errorhandlerdummy); XSetErrorHandler(errorhandlerdummy);
@@ -89,104 +93,131 @@ quit(void)
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y); XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
} }
IFREE(tags); free(tags);
IFREE(seltag); free(seltag);
systray_freeicons();
#ifdef HAVE_XFT
if(conf.use_xft)
XftFontClose(dpy, font.font);
else
#endif /* HAVE_XFT */
XFreeFontSet(dpy, font.fontset);
XftFontClose(dpy, font);
for(i = 0; i < CurLast; ++i) for(i = 0; i < CurLast; ++i)
XFreeCursor(dpy, cursor[i]); XFreeCursor(dpy, cursor[i]);
XFreeGC(dpy, gc_stipple); XFreeGC(dpy, gc_stipple);
infobar_destroy(); infobar_destroy();
IFREE(sgeo); free(sgeo);
IFREE(spgeo); free(spgeo);
IFREE(infobar); free(infobar);
IFREE(keys); free(keys);
IFREE(func_list); free(net_atom);
IFREE(net_atom);
/* Clean conf alloced thing */ /* Clean conf alloced thing */
IFREE(menulayout.item); free(menulayout.item);
if(conf.menu) if(conf.menu)
{ {
for(i = 0; i < LEN(conf.menu); ++i) len = LEN(conf.menu);
IFREE(conf.menu[i].item); for(i = 0; i < len; ++i)
IFREE(conf.menu); free(conf.menu[i].item);
free(conf.menu);
} }
IFREE(conf.launcher); free(conf.launcher);
IFREE(conf.ntag); free(conf.rule);
IFREE(conf.titlebar.mouse);
for(i = 0; i < conf.titlebar.nbutton; ++i)
{
IFREE(conf.titlebar.button[i].mouse);
IFREE(conf.titlebar.button[i].linecoord);
}
IFREE(conf.bars.mouse); free(conf.bars.mouse);
IFREE(conf.titlebar.button); free(conf.selbar.mouse);
IFREE(conf.client.mouse); free(conf.titlebar.button);
IFREE(conf.root.mouse); free(conf.client.mouse);
free(conf.root.mouse);
free_conf();
XSync(dpy, False); XSync(dpy, False);
XCloseDisplay(dpy); XCloseDisplay(dpy);
free(event_handle);
/* kill status script */
if (conf.status_pid != (pid_t)-1)
kill(conf.status_pid, SIGTERM);
return; return;
} }
void * static void
thread_process(void *arg) wait_childs_and_status(void)
{ {
XEvent ev; int pid;
/* X event loop */ pthread_mutex_lock(&mtx);
if(!(int*)arg) if (sig_chld) {
{ while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
while(!exiting && !XNextEvent(dpy, &ev)) if (pid == conf.status_pid)
getevent(ev); conf.status_pid = -1;
sig_chld = False;
pthread_exit(0);
} }
pthread_mutex_unlock(&mtx);
}
/* Status checking loop with timing */ static void *
else thread_status(void *arg)
{ {
while(!exiting) (void)arg;
{ int left = conf.status_timing;
spawn(conf.status_path);
sleep(conf.status_timing);
}
pthread_exit(0); 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. /** WMFS main loop.
*/ */
void static void
mainloop(void) mainloop(void)
{ {
XEvent ev; XEvent ev;
pthread_t evloop, evstatus; pthread_t th_status;
void *ret;
if(!estatus) if(estatus && !conf.status_timing)
while(!exiting && !XNextEvent(dpy, &ev)) conf.status_pid = spawn(conf.status_path);
getevent(ev); else if(estatus && pthread_create(&th_status, NULL, thread_status, NULL) != 0)
else
{ {
pthread_create(&evloop, NULL, thread_process, "1"); warnx("pthread_create");
pthread_create(&evstatus, NULL, thread_process, NULL); estatus = False;
(void)pthread_join(evloop, &ret);
(void)pthread_join(evstatus, &ret);
} }
while(!exiting && !XNextEvent(dpy, &ev))
{
HANDLE_EVENT(&ev);
wait_childs_and_status();
}
if(estatus)
pthread_join(th_status, NULL);
return; return;
} }
/** Set the exiting variable to True /** Set the exiting variable to True
* for stop the main loop * for stop the main loop
* \param cmd unused uicb_t * \param cmd unused uicb_t
@@ -194,6 +225,7 @@ mainloop(void)
void void
uicb_quit(uicb_t cmd) uicb_quit(uicb_t cmd)
{ {
(void)cmd;
exiting = True; exiting = True;
return; return;
@@ -202,14 +234,14 @@ uicb_quit(uicb_t cmd)
/** Scan if there are windows on X /** Scan if there are windows on X
* for manage it * for manage it
*/ */
void static void
scan(void) scan(void)
{ {
uint i, n; uint n;
XWindowAttributes wa; XWindowAttributes wa;
Window usl, usl2, *w = NULL; Window usl, usl2, *w = NULL;
Atom rt; Atom rt;
int s, rf, tag = -1, screen = -1, free = -1; int s, rf, tag = -1, screen = -1, flags = -1, i;
ulong ir, il; ulong ir, il;
uchar *ret; uchar *ret;
Client *c; Client *c;
@@ -218,9 +250,10 @@ scan(void)
if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n)) if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n))
for(i = n - 1; i != -1; --i) for(i = n - 1; i != -1; --i)
if(XGetWindowAttributes(dpy, w[i], &wa) {
&& !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl)) XGetWindowAttributes(dpy, w[i], &wa);
&& wa.map_state == IsViewable)
if(!wa.override_redirect && wa.map_state == IsViewable)
{ {
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32, if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret) False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
@@ -236,31 +269,32 @@ scan(void)
XFree(ret); 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) False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{ {
free = *ret; flags = *ret;
XFree(ret); XFree(ret);
} }
c = client_manage(w[i], &wa, False); c = client_manage(w[i], &wa, False);
if(tag != -1) if(tag != -1 && tag != MAXTAG + 1)
c->tag = tag; c->tag = tag;
if(screen != -1 && screen <= s - 1) if(screen != -1 && screen <= s - 1)
c->screen = screen; c->screen = screen;
if(free != -1) if(flags != -1)
c->flags |= (free) ? FreeFlag : 0; c->flags = flags;
client_update_attributes(c); client_update_attributes(c);
} }
}
/* Set update layout request */ /* Set update layout request */
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
{ {
if(c->tag > conf.ntag[c->screen]) if(c->tag > (uint)conf.ntag[c->screen])
c->tag = conf.ntag[c->screen]; 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) for(i = 0; i < s; ++i)
@@ -277,11 +311,13 @@ scan(void)
void void
uicb_reload(uicb_t cmd) uicb_reload(uicb_t cmd)
{ {
(void)cmd;
quit(); quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global); for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execlp(argv_global, argv_global, NULL); /* add -C to always load the same config file */
execvp(argv_global, all_argv);
return; return;
} }
@@ -290,7 +326,7 @@ uicb_reload(uicb_t cmd)
execute when wmfs will be already running). execute when wmfs will be already running).
\return False if wmfs is not running \return False if wmfs is not running
*/ */
Bool bool
check_wmfs_running(void) check_wmfs_running(void)
{ {
Atom rt; Atom rt;
@@ -323,15 +359,11 @@ check_wmfs_running(void)
void void
exec_uicb_function(char *func, char *cmd) exec_uicb_function(char *func, char *cmd)
{ {
long data[5];
/* Check if wmfs is running (this function is executed when wmfs /* Check if wmfs is running (this function is executed when wmfs
is already running normally...) */ is already running normally...) */
if(!check_wmfs_running()) if(!check_wmfs_running())
return; return;
data[4] = True;
XChangeProperty(dpy, ROOT, ATOM("_WMFS_FUNCTION"), ATOM("UTF8_STRING"), XChangeProperty(dpy, ROOT, ATOM("_WMFS_FUNCTION"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)func, strlen(func)); 8, PropModeReplace, (uchar*)func, strlen(func));
@@ -341,7 +373,7 @@ exec_uicb_function(char *func, char *cmd)
XChangeProperty(dpy, ROOT, ATOM("_WMFS_CMD"), ATOM("UTF8_STRING"), XChangeProperty(dpy, ROOT, ATOM("_WMFS_CMD"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)cmd, strlen(cmd)); 8, PropModeReplace, (uchar*)cmd, strlen(cmd));
send_client_event(data, "_WMFS_FUNCTION"); ewmh_send_message(ROOT, ROOT, "_WMFS_FUNCTION", 0, 0, 0, 0, True);
return; return;
} }
@@ -349,15 +381,12 @@ exec_uicb_function(char *func, char *cmd)
/** Set statustext /** Set statustext
*\param str Statustext string *\param str Statustext string
*/ */
void static void
set_statustext(int s, char *str) set_statustext(int s, char *str)
{ {
int i; int i;
long data[5];
char atom_name[64]; char atom_name[64];
data[4] = True;
if(!str) if(!str)
return; return;
@@ -370,7 +399,7 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"), XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str)); 8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name); ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
} }
} }
else else
@@ -380,7 +409,7 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"), XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str)); 8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name); ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
} }
return; return;
@@ -388,29 +417,32 @@ set_statustext(int s, char *str)
/** Update status script by ewmh hint /** Update status script by ewmh hint
*/ */
void static void
update_status(void) update_status(void)
{ {
long data[5];
if(!check_wmfs_running()) if(!check_wmfs_running())
return; return;
data[4] = True; ewmh_send_message(ROOT, ROOT, "_WMFS_UPDATE_STATUS", 0, 0, 0, 0, True);
send_client_event(data, "_WMFS_UPDATE_STATUS");
return; return;
} }
/** Signal handle function /** Signal handle function
*/ */
void static void
signal_handle(int sig) signal_handle(int sig)
{ {
switch (sig)
{
case SIGQUIT:
case SIGTERM:
exiting = True; exiting = True;
quit(); break;
exit(EXIT_SUCCESS); case SIGCHLD:
sig_chld = True;
break;
}
return; return;
} }
@@ -424,12 +456,16 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int i; int i;
char *ol = "csgVS"; char *ol = "csS";
extern char *optarg;
extern int optind;
struct sigaction sa;
argv_global = _strdup(argv[0]); argv_global = xstrdup(argv[0]);
all_argv = argv;
sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME")); sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME"));
while((i = getopt(argc, argv, "hviSc:s:g:C:V:")) != -1) while((i = getopt(argc, argv, "hviSc:s:C:")) != -1)
{ {
/* For options who need WMFS running */ /* For options who need WMFS running */
@@ -443,9 +479,7 @@ main(int argc, char **argv)
printf("usage: %s [-ihvS] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>] [-V <viwmfs cmd]\n" printf("usage: %s [-ihvS] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>] [-V <viwmfs cmd]\n"
" -C <file> Load a configuration file\n" " -C <file> Load a configuration file\n"
" -c <uicb_function> <cmd> Execute an uicb function to control WMFS\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" " -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" " -S Update status script\n"
" -h Show this page\n" " -h Show this page\n"
" -i Show informations\n" " -i Show informations\n"
@@ -459,11 +493,7 @@ main(int argc, char **argv)
break; break;
case 'v': case 'v':
printf("WMFS version : "WMFS_VERSION"\n" printf("wmfs"WMFS_VERSION"\n");
" Compilation settings :\n"
" - Flags : "WMFS_COMPILE_FLAGS"\n"
" - Linked Libs : "WMFS_LINKED_LIBS"\n"
" - On "WMFS_COMPILE_MACHINE" by "WMFS_COMPILE_BY".\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
@@ -474,11 +504,11 @@ main(int argc, char **argv)
break; break;
case 'C': case 'C':
strcpy(conf.confpath, optarg); strncpy(conf.confpath, optarg, sizeof(conf.confpath));
break; break;
case 'c': case 'c':
exec_uicb_function(argv[2], ((argv[3]) ? argv[3] : NULL)); exec_uicb_function(optarg, argv[optind]);
XCloseDisplay(dpy); XCloseDisplay(dpy);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
@@ -491,17 +521,6 @@ main(int argc, char **argv)
XCloseDisplay(dpy); XCloseDisplay(dpy);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'g':
getinfo(optarg);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'V':
viwmfs(argc, argv);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
} }
} }
@@ -510,8 +529,12 @@ main(int argc, char **argv)
errx(EXIT_FAILURE, "cannot open X server."); errx(EXIT_FAILURE, "cannot open X server.");
/* Set signal handler */ /* Set signal handler */
(void)signal(SIGTERM, &signal_handle); memset(&sa, 0, sizeof(sa));
(void)signal(SIGINT, &signal_handle); sa.sa_handler = signal_handle;
sigemptyset(&sa.sa_mask);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
/* Check if an other WM is already running; set the error handler */ /* Check if an other WM is already running; set the error handler */
XSetErrorHandler(errorhandler); XSetErrorHandler(errorhandler);

View File

@@ -1,3 +1,4 @@
/* /*
* wmfs.h * wmfs.h
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com> * Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
@@ -38,28 +39,32 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <time.h> #include <time.h>
#include <getopt.h> #include <getopt.h>
#include <dirent.h> #include <dirent.h>
#include <err.h> #include <err.h>
#include <pthread.h> #include <pthread.h>
#include <locale.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/cursorfont.h> #include <X11/cursorfont.h>
#include <X11/Xft/Xft.h>
/* Local headers */
#include "confparse/confparse.h"
#include "config.h"
#include "structs.h"
/* Optional dependencies */ /* Optional dependencies */
#ifdef HAVE_XFT
#include <X11/Xft/Xft.h>
#endif /* HAVE_XFT */
#ifdef HAVE_XINERAMA #ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif /* HAVE_XINERAMA */ #endif /* HAVE_XINERAMA */
@@ -72,6 +77,10 @@
#include <Imlib2.h> #include <Imlib2.h>
#endif /* HAVE_IMLIB */ #endif /* HAVE_IMLIB */
/* Local headers */
#include "parse.h"
#include "structs.h"
/* MACRO */ /* MACRO */
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask) #define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
#define MouseMask (ButtonMask | PointerMotionMask) #define MouseMask (ButtonMask | PointerMotionMask)
@@ -80,43 +89,54 @@
#define ROOT RootWindow(dpy, SCREEN) #define ROOT RootWindow(dpy, SCREEN)
#define MAXH DisplayHeight(dpy, DefaultScreen(dpy)) #define MAXH DisplayHeight(dpy, DefaultScreen(dpy))
#define MAXW DisplayWidth(dpy, DefaultScreen(dpy)) #define MAXW DisplayWidth(dpy, DefaultScreen(dpy))
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font->height * 1.5)) #define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font.height * 1.5))
#define FHINFOBAR ((font->height - font->descent) + (INFOBARH - font->height) / 2) #define FHINFOBAR ((font.height - font.de) + (((int)INFOBARH - font.height) >> 1))
#define SHADH (1) #define SHADH (1)
#define SHADC (0x000000) /* 'Cause i don't know how darken a color yet */
#define BORDH conf.client.borderheight #define BORDH conf.client.borderheight
#define TBARH ((conf.titlebar.height < BORDH) ? BORDH : conf.titlebar.height) #define TBARH ((conf.titlebar.height < BORDH) ? BORDH : conf.titlebar.height)
#define RESHW (6 * BORDH) #define RESHW (6 * (BORDH))
#define BUTTONWH (TBARH / 2) #define BUTTONWH (TBARH >> 1)
#define DEF_CONF ".config/wmfs/wmfsrc" #define DEF_CONF ".config/wmfs/wmfsrc"
#define DEF_STATUS ".config/wmfs/status.sh" #define DEF_STATUS ".config/wmfs/status.sh"
#define PAD conf.pad #define PAD conf.pad
#define MAXSTATUS 4096 #define MAXSTATUS (4096)
#define CWIN(win, parent, x, y, w, h, b, mask, col, at) \ #define CWIN(win, parent, x, y, w, h, b, mask, col, at) \
do { \ do { \
win = XCreateWindow(dpy, (parent), (x), (y), (w), (h), (b), CopyFromParent, \ win = XCreateWindow(dpy, (parent), (x), (y), (w), (h), (b), CopyFromParent, \
InputOutput, CopyFromParent, (mask), (at)); \ InputOutput, CopyFromParent, (mask), (at)); \
XSetWindowBackground(dpy, win, (col)); \ XSetWindowBackground(dpy, win, (col)); \
} while (/* CONSTCOND */ 0) } while(/* CONSTCOND */ 0)
#define HANDLE_EVENT(e) event_handle[(e)->type](e);
#define ATOM(a) XInternAtom(dpy, (a), False) #define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + BORDH * 2) #define FRAMEW(w) ((w) + (BORDH << 1))
#define FRAMEH(h) ((h) + (BORDH + TBARH)) #define FRAMEH(h) ((h) + (BORDH + TBARH))
#define ROUND(x) (float)((x > 0) ? x + (float)0.5 : x - (float)0.5) #define ROUND(x) (float)((x > 0) ? x + (float)0.5 : x - (float)0.5)
#define CHECK(x) if(!(x)) return #define CHECK(x) if(!(x)) return
#define IFREE(x) if(x) free(x)
#define LEN(x) (sizeof(x) / sizeof((x)[0])) #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)))
/* 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.c */ /* barwin.c */
BarWindow *barwin_create(Window parent, BarWindow *barwin_create(Window parent,
int x, int y, int x, int y,
uint w, uint h, int w, int h,
uint bg, char*fg, uint bg, char*fg,
Bool entermask, bool entermask,
Bool stipple, bool stipple,
Bool border); bool border);
void barwin_draw_text(BarWindow *bw, int x, int y, char *text); void barwin_draw_text(BarWindow *bw, int x, int y, char *text);
void barwin_color_set(BarWindow *bw, uint bg, char *fg);
void barwin_delete(BarWindow *bw); void barwin_delete(BarWindow *bw);
void barwin_delete_subwin(BarWindow *bw); void barwin_delete_subwin(BarWindow *bw);
void barwin_map(BarWindow *bw); void barwin_map(BarWindow *bw);
@@ -124,159 +144,177 @@ void barwin_map_subwin(BarWindow *bw);
void barwin_unmap(BarWindow *bw); void barwin_unmap(BarWindow *bw);
void barwin_unmap_subwin(BarWindow *bw); void barwin_unmap_subwin(BarWindow *bw);
void barwin_move(BarWindow *bw, int x, int y); 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_color(BarWindow *bw);
void barwin_refresh(BarWindow *bw); void barwin_refresh(BarWindow *bw);
/* draw.c */ /* draw.c */
void draw_text(Drawable d, int x, int y, char* fg, int pad, char *str); void draw_text(Drawable d, int x, int y, char* fg, char *str);
void draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color); 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);
#ifdef HAVE_IMLIB
void draw_image(Drawable dr, int x, int y, int w, int h, char *name);
#endif /* HAVE_IMLIB */
ushort textw(char *text); ushort textw(char *text);
/* infobar.c */ /* infobar.c */
void infobar_init(void); void infobar_init(void);
void infobar_draw(int sc); void infobar_draw_layout(InfoBar *i);
void infobar_draw_layout(int sc); void infobar_draw(InfoBar *i);
void infobar_draw_selbar(int sc); void infobar_draw_selbar(InfoBar *i);
void infobar_draw_taglist(int sc); void infobar_draw_taglist(InfoBar *i);
void infobar_update_taglist(InfoBar *i);
void infobar_destroy(void); void infobar_destroy(void);
void infobar_set_position(int pos); void infobar_set_position(int pos);
void uicb_infobar_togglepos(uicb_t); 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 */ /* client.c */
void client_attach(Client *c); void client_attach(Client *c);
void client_configure(Client *c); void client_configure(Client *c);
void client_detach(Client *c); void client_detach(Client *c);
void client_above(Client *c);
void client_focus(Client *c); void client_focus(Client *c);
Client* client_get_next(void); Client *client_get_next(void);
Client* client_get_prev(void); Client *client_get_prev(void);
/* client_gb_*() {{{ */ /* client_gb_*() {{{ */
Client* client_gb_win(Window w); Client* client_gb_win(Window w);
Client* client_gb_frame(Window w); Client* client_gb_frame(Window w);
Client* client_gb_titlebar(Window w); Client* client_gb_titlebar(Window w);
Client* client_gb_resize(Window w); Client* client_gb_resize(Window w);
Client* client_gb_button(Window w, int *n); 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_get_name(Client *c);
void client_hide(Client *c); void client_hide(Client *c);
void client_kill(Client *c); void client_kill(Client *c);
Bool ishide(Client *c, int screen); bool ishide(Client *c, int screen);
void client_map(Client *c); void client_map(Client *c);
Client* client_manage(Window w, XWindowAttributes *wa, Bool ar); Client* client_manage(Window w, XWindowAttributes *wa, bool ar);
void client_geo_hints(XRectangle *geo, Client *c); void client_geo_hints(Geo *geo, Client *c);
void client_moveresize(Client *c, XRectangle geo, Bool r); void client_moveresize(Client *c, Geo geo, bool r);
void client_maximize(Client *c); void client_maximize(Client *c);
void client_size_hints(Client *c); void client_size_hints(Client *c);
void client_swap(Client *c1, Client *c2); void client_swap(Client *c1, Client *c2);
void client_raise(Client *c); void client_raise(Client *c);
void client_unhide(Client *c); void client_unhide(Client *c);
void client_focus_next(Client *c);
void client_unmanage(Client *c); void client_unmanage(Client *c);
void client_unmap(Client *c); void client_unmap(Client *c);
void client_set_wanted_tag(Client *c);
void client_update_attributes(Client *c); void client_update_attributes(Client *c);
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_raise(uicb_t);
void uicb_client_next(uicb_t); /* Generated with macro {{{ */
void uicb_client_prev(uicb_t); void uicb_client_focus_next(uicb_t);
void uicb_client_swap_next(uicb_t); void uicb_client_focus_prev(uicb_t);
void uicb_client_swap_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_kill(uicb_t);
void uicb_client_screen_next(uicb_t); void uicb_client_screen_next(uicb_t);
void uicb_client_screen_prev(uicb_t); void uicb_client_screen_prev(uicb_t);
void uicb_client_screen_set(uicb_t);
void uicb_client_move(uicb_t cmd); void uicb_client_move(uicb_t cmd);
void uicb_client_resize(uicb_t cmd); void uicb_client_resize(uicb_t cmd);
void uicb_ignore_next_client_rules(uicb_t cmd); void uicb_ignore_next_client_rules(uicb_t cmd);
void uicb_clientlist(uicb_t cmd);
bool uicb_checkclist(uicb_t);
void uicb_client_ignore_tag(uicb_t);
void uicb_client_set_master(uicb_t);
/* ewmh.c */ /* ewmh.c */
void ewmh_init_hints(void); void ewmh_init_hints(void);
void ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4);
long ewmh_get_xembed_state(Window win);
void ewmh_get_number_of_desktop(void); void ewmh_get_number_of_desktop(void);
void ewmh_update_current_tag_prop(void); void ewmh_update_current_tag_prop(void);
void ewmh_get_client_list(void); void ewmh_get_client_list(void);
void ewmh_get_desktop_names(void); void ewmh_get_desktop_names(void);
void ewmh_set_desktop_geometry(void); void ewmh_set_desktop_geometry(void);
void ewmh_set_workarea(void);
void ewmh_manage_net_wm_state(long data_l[], Client *c); void ewmh_manage_net_wm_state(long data_l[], Client *c);
void ewmh_manage_window_type(Client *c); void ewmh_manage_window_type(Client *c);
/* frame.c */ /* frame.c */
void frame_create(Client *c); void frame_create(Client *c);
void frame_delete(Client *c); void frame_delete(Client *c);
void frame_moveresize(Client *c, XRectangle geo); void frame_moveresize(Client *c, Geo geo);
void frame_update_color(Client *c, bool focused);
void frame_update(Client *c); void frame_update(Client *c);
/* config.c */ /* config.c */
void init_conf(void); void init_conf(void);
/* color.c */
uint color_shade(uint, double);
/* event.c */ /* event.c */
void buttonpress(XButtonEvent *ev);
void configureevent(XConfigureRequestEvent *ev);
void clientmessageevent(XClientMessageEvent *ev);
void destroynotify(XDestroyWindowEvent *ev);
void enternotify(XCrossingEvent *ev);
void expose(XExposeEvent *ev);
void focusin(XFocusChangeEvent *ev);
void grabkeys(void); void grabkeys(void);
void keypress(XKeyPressedEvent *ev); void event_make_array(void);
void mappingnotify(XMappingEvent *ev);
void maprequest(XMapRequestEvent *ev); #ifdef HAVE_XRANDR
void propertynotify(XPropertyEvent *ev); void xrandrevent(XEvent *e);
void unmapnotify(XUnmapEvent *ev); #endif /* HAVE_XRANDR */
void send_client_event(long data[5], char *atom_name);
void getevent(XEvent ev);
/* menu.c */ /* menu.c */
void menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n); void menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n);
void menu_new_item(MenuItem *mi, char *name, void *func, char *cmd); void menu_new_item(MenuItem *mi, char *name, void *func, char *cmd);
void menu_draw(Menu menu, int x, int y); void menu_draw(Menu menu, int x, int y);
Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]);
void menu_focus_item(Menu *menu, int item, BarWindow *winitem[]);
void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[]);
int menu_get_longer_string(MenuItem *mt, int nitem);
void uicb_menu(uicb_t cmd); void uicb_menu(uicb_t cmd);
void menu_clear(Menu *menu);
/* launcher.c */ /* launcher.c */
void launcher_execute(Launcher launcher);
void uicb_launcher(uicb_t); void uicb_launcher(uicb_t);
/* mouse.c */ /* mouse.c */
void mouse_dragborder(XRectangle geo, GC g);
void mouse_move_tile_client(Client **c);
void mouse_move_tag_client(Client *c);
void mouse_move(Client *c);
void mouse_resize(Client *c); void mouse_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_move(uicb_t);
void uicb_mouse_resize(uicb_t); void uicb_mouse_resize(uicb_t);
/* util.c */ /* util.c */
ulong color_enlight(ulong col); void *xmalloc(size_t, size_t);
void *emalloc(uint element, uint size); void *xcalloc(size_t, size_t);
void *xrealloc(void *, size_t, size_t);
/* simples wrappers for allocating only one object */
#define zmalloc(size) xmalloc(1, (size))
#define zcalloc(size) xcalloc(1, (size))
#define zrealloc(ptr, size) xrealloc((ptr), 1, (size))
char *xstrdup(const char *);
int xasprintf(char **, const char *, ...);
long getcolor(char *color); long getcolor(char *color);
void setwinstate(Window win, long state); void setwinstate(Window win, long state);
char* _strdup(char const *str);
/* Conf usage {{{ */ /* Conf usage {{{ */
void* name_to_func(char *name, const func_name_list_t *l); void* name_to_func(char *name, const func_name_list_t *l);
ulong char_to_modkey(char *name, key_name_list_t key_l[]); ulong char_to_modkey(char *name, key_name_list_t key_l[]);
uint char_to_button(char *name, name_to_uint_t blist[]); uint char_to_button(char *name, name_to_uint_t blist[]);
Layout layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[]); Layout layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[]);
char* alias_to_str(char *conf_choice);
/* }}} */ /* }}} */
XRectangle get_mouse_pos(void);
char *char_to_str(const char c); char *char_to_str(const char c);
void spawn(const char *str, ...); pid_t spawn(const char *str, ...);
void swap_ptr(void **x, void **y); void swap_ptr(void **x, void **y);
void uicb_spawn(uicb_t); void uicb_spawn(uicb_t);
char *clean_value(char *str);
#ifdef HAVE_IMLIB char* patht(char *path);
int parse_image_block(ImageAttr *im, char *str); int qsort_string_compare (const void * a, const void * b);
#endif /* HAVE_IMLIB */
/* tag.c */ /* tag.c */
void tag_set(int tag); void tag_set(int tag);
@@ -284,14 +322,28 @@ void tag_transfert(Client *c, int tag);
void uicb_tag(uicb_t); void uicb_tag(uicb_t);
void uicb_tag_next(uicb_t); void uicb_tag_next(uicb_t);
void uicb_tag_prev(uicb_t); void uicb_tag_prev(uicb_t);
void uicb_tag_next_visible(uicb_t);
void uicb_tag_prev_visible(uicb_t);
void uicb_tagtransfert(uicb_t); void uicb_tagtransfert(uicb_t);
void uicb_tag_prev_sel(uicb_t); void uicb_tag_prev_sel(uicb_t);
void uicb_tagtransfert_next(uicb_t); void uicb_tagtransfert_next(uicb_t);
void uicb_tagtransfert_prev(uicb_t); void uicb_tagtransfert_prev(uicb_t);
void uicb_tag_urgent(uicb_t cmd);
void tag_additional(int sc, int tag, int adtag);
void uicb_tag_toggle_additional(uicb_t);
void uicb_tag_swap(uicb_t);
void uicb_tag_swap_next(uicb_t);
void uicb_tag_swap_previous(uicb_t);
void uicb_tag_new(uicb_t);
void uicb_tag_del(uicb_t);
void uicb_tag_rename(uicb_t cmd);
void uicb_tag_last(uicb_t cmd);
void uicb_tag_stay_last(uicb_t cmd);
void uicb_tag_toggle_expose(uicb_t cmd);
/* screen.c */ /* screen.c */
int screen_count(void); 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_with_geo(int x, int y);
int screen_get_sel(void); int screen_get_sel(void);
void screen_set_sel(int screen); void screen_set_sel(int screen);
@@ -302,26 +354,34 @@ void uicb_screen_prev(uicb_t);
void uicb_screen_prev_sel(uicb_t); void uicb_screen_prev_sel(uicb_t);
/* status.c */ /* status.c */
int statustext_rectangle(StatusRec *r, char *str);
int statustext_text(StatusText *s, char *str);
void statustext_normal(int sc, char *str);
void statustext_handle(int sc, char *str); void statustext_handle(int sc, char *str);
/* systray.c */
bool systray_acquire(void);
void systray_add(Window win);
void systray_del(Systray *s);
void systray_state(Systray *s);
void systray_freeicons(void);
Systray* systray_find(Window win);
int systray_get_width(void);
void systray_update(void);
/* layout.c */ /* layout.c */
void arrange(int screen, Bool update_layout); void arrange(int screen, bool update_layout);
void freelayout(int screen); void layout_func(int screen, int tag);
void layoutswitch(Bool b);
void maxlayout(int screen);
Client *tiled_client(int screen, Client *c); Client *tiled_client(int screen, Client *c);
void freelayout(int screen);
void layoutswitch(bool b);
void maxlayout(int screen);
/* tile {{{ */ /* tile {{{ */
void grid(int screen);
void tile(int screen); void tile(int screen);
void tile_left(int screen); void tile_left(int screen);
void tile_top(int screen); void tile_top(int screen);
void tile_bottom(int screen); void tile_bottom(int screen);
void mirror_vertical(int screen); void mirror_vertical(int screen);
void mirror_horizontal(int screen); void mirror_horizontal(int screen);
void layer(int screen); void grid_vertical(int screen);
void grid_horizontal(int screen);
/* }}} */ /* }}} */
void uicb_togglemax(uicb_t); void uicb_togglemax(uicb_t);
void uicb_togglefree(uicb_t); void uicb_togglefree(uicb_t);
@@ -332,42 +392,43 @@ void uicb_set_nmaster(uicb_t);
void uicb_set_layout(uicb_t); void uicb_set_layout(uicb_t);
void uicb_toggle_resizehint(uicb_t); void uicb_toggle_resizehint(uicb_t);
void uicb_toggle_abovefc(uicb_t cmd); void uicb_toggle_abovefc(uicb_t cmd);
void uicb_set_layer(uicb_t cmd);
void uicb_set_client_layer(uicb_t cmd);
void layout_set_client_master(Client *c); void layout_set_client_master(Client *c);
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 */ /* init.c */
void init(void); void init(void);
void init_root(void);
void init_font(void);
void init_gc(void);
void init_cursor(void);
void init_key(void);
void init_geometry(void);
void init_status(void);
/* getinfo.c */ /* split.c */
void getinfo_tag(void); void split_store_geo(int screen, int tag);
void getinfo_screen(void); void split_set_current(Client *nc, Client *ghost);
void getinfo_layout(void); void split_apply_current(int screen, int tag);
void getinfo_mwfact(void); void split_arrange_closed(Client *ghost);
void getinfo_nmaster(void); Geo split_client(Client *c, bool p);
void getinfo(char *info); void split_client_fill(Client *c, Geo geo);
void split_client_integrate(Client *c, Client *sc, int screen, int tag);
/* viwmfs.c */ void split_move_dir(Client *c, Position p);
void viwmfs(int argc, char **argv); 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 */ /* wmfs.c */
int errorhandler(Display *d, XErrorEvent *event); int errorhandler(Display *d, XErrorEvent *event);
int errorhandlerdummy(Display *d, XErrorEvent *event); int errorhandlerdummy(Display *d, XErrorEvent *event);
void quit(void); void quit(void);
void *thread_process(void *arg); void *thread_process(void *arg);
void mainloop(void); bool check_wmfs_running(void);
void scan(void);
Bool check_wmfs_running(void);
void exec_uicb_function(char *func, char *cmd); void exec_uicb_function(char *func, char *cmd);
void set_statustext(int s, char *str);
void update_status(void);
void handle_signal(int signum); void handle_signal(int signum);
void uicb_quit(uicb_t); void uicb_quit(uicb_t);
void uicb_reload(uicb_t); void uicb_reload(uicb_t);
@@ -381,19 +442,21 @@ int selscreen;
int prevselscreen; int prevselscreen;
Conf conf; Conf conf;
Key *keys; Key *keys;
Bool exiting, estatus; bool estatus;
XRectangle *sgeo; Geo *sgeo;
XRectangle *spgeo; Geo *spgeo;
Cursor cursor[CurLast]; Cursor cursor[CurLast];
char *argv_global; char *argv_global;
char **all_argv;
int xrandr_event; int xrandr_event;
uint timing; uint timing;
/* Fonts */ /* Fonts */
XftFont *font; FontStruct font;
/* Atoms list */ /* Atoms list */
Atom *net_atom; Atom *net_atom;
Atom trayatom;
/* InfoBar/Tags */ /* InfoBar/Tags */
InfoBar *infobar; InfoBar *infobar;
@@ -402,14 +465,26 @@ int *seltag;
int *prevseltag; int *prevseltag;
Menu menulayout; Menu menulayout;
/* ClientList */
Menu clientlist;
struct clndx {
char key[4];
Client *client;
} clist_index[MAXCLIST];
/* Important Client */ /* Important Client */
Client *clients; Client *clients;
Client *sel; Client *sel;
/* Other */ /* Other */
func_name_list_t *func_list; int nevent;
void (**event_handle)(XEvent*);
extern const func_name_list_t func_list[];
extern const func_name_list_t layout_list[]; extern const func_name_list_t layout_list[];
uint numlockmask; uint numlockmask;
Systray *trayicons;
Window traywin;
int tray_width;
#endif /* WMFS_H */ #endif /* WMFS_H */

8
wmfs.1
View File

@@ -62,7 +62,7 @@ Print help information, then exit\&.
.PP .PP
\fB\-i\fR \fB\-i\fR
.RS 4 .RS 4
Print WMFS informations Print WMFS information
.RE .RE
.SH "DEFAULT KEY BINDINGS" .SH "DEFAULT KEY BINDINGS"
.PP .PP
@@ -143,7 +143,7 @@ Increase the nmaster (+1)\fR
.PP .PP
\fBAlt\-Shift + d\fR \fBAlt\-Shift + d\fR
.RS 4 .RS 4
Decrease the nmaster (-1)\fR Decrease the nmaster (\-1)\fR
.RE .RE
.PP .PP
\fBAlt + t\fR \fBAlt + t\fR
@@ -163,7 +163,7 @@ Make a launcher in the infobar to run an unix command\fR
.PP .PP
\fBAlt + Escape\fR \fBAlt + Escape\fR
.RS 4 .RS 4
Set WMFS in ViWMFS mode. (see wmfs -V)\fR Set WMFS in ViWMFS mode. (see wmfs \-V)\fR
.RE .RE
.PP .PP
\fBAlt\-Shift + p\fR \fBAlt\-Shift + p\fR
@@ -193,7 +193,7 @@ Martin Duquesnoy <\fIxorg62@gmail\&.com\fR\&[1]>\&.
Main site: \fIhttp://wmfs\&.info\fR Bug tracker: \fIhttp://bugs\&.wmfs\&.info\fR Main site: \fIhttp://wmfs\&.info\fR Bug tracker: \fIhttp://bugs\&.wmfs\&.info\fR
.sp .sp
.SH "COPYING" .SH "COPYING"
WMFS is under the BSD license\&. See COPYING for more informations\&. WMFS is under the BSD license\&. See COPYING for more information\&.
.sp .sp
.SH "NOTES" .SH "NOTES"
.IP " 1." 4 .IP " 1." 4

View File

@@ -1,6 +1,5 @@
[Desktop Entry] [Desktop Entry]
Encoding=UTF-8 Encoding=UTF-8
Name=wmfs Name=wmfs
Comment=Window manager from scratch Comment=Window Manager From Scratch
TryExec=wmfs Exec=ck-launch-session wmfs
Exec=wmfs

View File

@@ -73,7 +73,7 @@ WARN_LOGFILE =
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# configuration options related to the input files # configuration options related to the input files
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
INPUT = @SOURCE_DIR@/src INPUT = src
INPUT_ENCODING = UTF-8 INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \ FILE_PATTERNS = *.c \
*.h \ *.h \

472
wmfsrc Normal file
View File

@@ -0,0 +1,472 @@
#
# This is the default wmfs config file, copy it to
# ~/.config/wmfs/wmfsrc and edit it.
#
# Include file to split configuration
# @include "~/.config/wmfs/menu-wmfsrc"
[misc]
use_xft = true
font = "dejavu-10"
raisefocus = true
focus_follow_mouse = true
focus_follow_movement = false
opacity = 255
# focus_pointer_click: click on unfocused client area:
# true -- default, set focus
# false -- click go to client; including dockapps
focus_pointer_click = true
status_timing = 1 #seconds
# status_path = "~/.config/wmfs/status.sh"
[/misc]
[bar]
bg = "#191919"
fg = "#D4D4D4"
border = true
#height = "-1"
light_shade = 0.10
dark_shade = -0.10
[systray]
# Enable/disable systray
active = true
# Screen of systray
screen = 0
# Spacing between tray icons
spacing = 3
[/systray]
# Remove this section to disable the selbar.
[selbar]
bg = "#191919"
fg = "#D4D4ff"
# Cut title length
# max_length = 25
[mouse] button = "3" func = "clientlist" [/mouse]
[mouse] button = "4" func = "client_next" [/mouse]
[mouse] button = "5" func = "client_prev" [/mouse]
[/selbar]
[/bar]
[layouts]
fg = "#191919"
bg = "#7E89A2"
# Border around the layout button.
border = true
# Value menu or switch.
system = "menu"
# Value left or right.
placement = "right"
# Keep layout geo for free layout
keep_layout_geo = false
# Enable split mode with client_resize_<direction>
cfactor_enable_split = true
# Symbol displayed for the selected layout in the list
selected_layout_symbol = "*"
# Width of layout button
# layout_button_width = x
# Tiling layouts.
[layout] type = "tile_right" symbol = "RIGHT" [/layout]
[layout] type = "tile_left" symbol = "LEFT" [/layout]
[layout] type = "tile_top" symbol = "TOP" [/layout]
[layout] type = "tile_bottom" symbol = "BOTTOM" [/layout]
[layout] type = "tile_grid" symbol = "GRID_H" [/layout]
[layout] type = "tile_grid_vertical" symbol = "GRID_V" [/layout]
[layout] type = "mirror_vertical" symbol = "MIRROR_V" [/layout]
[layout] type = "mirror_horizontal" symbol = "MIRROR_H" [/layout]
# Other layouts.
[layout] type = "max" symbol = "MAX" [/layout]
[layout] type = "free" symbol = "FREE" [/layout]
[/layouts]
[tags]
[default_tag]
name = "new tag"
mwfact = 0.5
nmaster = 1
layout = "tile"
resizehint = false
infobar_position = "top"
split = false
[/default_tag]
# whether client_next on the last tag will send you on the first
# and client_prev on the first tag will send you on the last one
tag_round = false
# Going twice on the same tag will bring you back on the previous one
tag_auto_prev = true
occupied_bg = "#003366"
occupied_fg = "#D4D4D4"
sel_fg = "#191919"
sel_bg = "#7E89A2"
urgent_bg = "#DD1111"
urgent_fg = "#000000"
# If true, number of the tag will be used for name
name_count = false
#default_name = "new tag" # deprecated, use [default_tag] instead
#default_layout = "tile_right" # deprecated, use [default_tag] instead
expose_name = "EXPOSE"
expose_layout = "tile_left"
# Border around the tag buttons.
border = true
# Hide empty tags in tag list
autohide = false
# Mouse buttons action on tag.
mouse_button_tag_sel = "1"
mouse_button_tag_transfert = "2"
mouse_button_tag_add = "3"
mouse_button_tag_next = "4"
mouse_button_tag_prev = "5"
[tag]
name = "one"
screen = 0
mwfact = 0.65
nmaster = 1
layout = "tile_right"
resizehint = false
infobar_position = "top"
above_fc = false
split = false
#[mouse] [/mouse] Possible multi mouse section
[/tag]
[tag] name = "two" [/tag]
[tag] name = "three" [/tag]
[tag] name = "four" [/tag]
[tag] name = "five" [/tag]
[tag] name = "six" [/tag]
[tag] name = "seven" [/tag]
[tag] name = "eight" [/tag]
[tag] name = "nine" [/tag]
[/tags]
[root]
# Command you can execute to set the background.
background_command = "xsetroot -solid black"
[mouse] button = "4" func = "tag_next" [/mouse]
[mouse] button = "5" func = "tag_prev" [/mouse]
[mouse] button = "3" func = "menu" cmd = "rootmenu" [/mouse]
[/root]
[client]
client_round = true
client_auto_center = false
border_height = 3
border_shadow = true
border_normal = "#191919"
border_focus = "#003366"
place_at_mouse = false
resize_corner_normal = "#191919"
resize_corner_focus = "#003366"
set_new_win_master = true
client_tile_raise = false
new_client_get_mouse = false
# send all client that have no tag rule in this default tag
#default_open_tag = 4
# same as above but for the screen
#default_open_screen = 1
# Space between tiled clients (px)
padding = 0
# Modifier for mouse use
modifier = "Alt"
light_shade = 0.10
dark_shade = -0.10
# *DEPRECATED* but works, see [rules] section
# Set automatic free or max client
# autofree = "xterm|MPlayer"
# automax = "Navigator"
[mouse] button = "1" func = "client_raise" [/mouse]
[mouse] button = "1" func = "mouse_move" [/mouse]
[mouse] button = "3" func = "client_raise" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
# Remove this section to delete the titlebar.
[titlebar]
stipple = false
height = 12
fg_normal = "#7E89A2"
fg_focus = "#9F9AB3"
[mouse] button = "1" func = "client_raise" [/mouse]
[mouse] button = "1" func = "mouse_move" [/mouse]
[mouse] button = "3" func = "client_raise" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
[button]
# Available "free", "max", "tile" flags or button.
flags = "free,max,tile"
[mouse] button = "1" func = "client_kill" [/mouse]
[mouse] button = "3" func = "menu" cmd = "clientmenu" [/mouse]
[line] coord = {1, 1, 4, 1} [/line]
[line] coord = {1, 1, 1, 4} [/line]
[line] coord = {1, 4, 4, 4} [/line]
[/button]
[/titlebar]
[/client]
[rules]
# Example of rule for MPlayer
[rule]
instance = "xv" # First part of WM_CLASS
class = "MPlayer" # Seconf part of WM_CLASS, not needed if first part is correct
# role = "" # WM_WINDOW_ROLE
screen = 0 # Screen to use
tag = 2 # Tag number of apps
free = true # Set automatic free client
max = false # Set automatic maximized client
follow_client = false # follow the client
ignore_tags = false # ignore tag (free mode)
[/rule]
[/rules]
[menu]
# Default menu, binded on the root window, button 3.
[set_menu]
name = "rootmenu"
# place_at_mouse = false
# x = 40 y = 50
# Available "center", "left", "right" menu align. Default: "center".
align = "left"
fg_focus = "#191919" bg_focus = "#7E89A2"
fg_normal = "#9F9AB3" bg_normal = "#191919"
[item] name = "Terminal" func = "spawn" cmd = "urxvt || xterm || gnome-terminal" [/item]
[item] name = "Applications" submenu = "appmenu" [/item]
[item] name = "Next tag" func = "tag_next" [/item]
[item] name = "Previous tag" func = "tag_prev" [/item]
[item] name = "Next layout" func = "layout_next" [/item]
[item] name = "Previous layout" func = "layout_prev" [/item]
[item] name = "Toggle infobar" func = "toggle_infobar_position" [/item]
[item] name = "Quit WMFS" func = "quit" [/item]
[/set_menu]
[set_menu]
name = "appmenu"
align = "left"
fg_focus = "#191919" bg_focus = "#7E89A2"
fg_normal = "#9F9AB3" bg_normal = "#191919"
[item] name = "Browser" func = "spawn" cmd = "firefox" [/item]
[item] name = "Calculator" func = "spawn" cmd = "xcalc" [/item]
[/set_menu]
[set_menu]
name = "clientmenu"
fg_focus = "#D4D4D4" bg_focus = "#003366"
fg_normal = "#D4D4D4" bg_normal = "#191919"
# Check items: possible 'check_max' or 'check_free'.
[item] name = "Close" func = "client_kill" [/item]
[item] name = "Maximize" func = "toggle_max" check = "check_max" [/item]
[item] name = "Free" func = "toggle_free" check = "check_free" [/item]
[/set_menu]
[/menu]
[launcher]
[set_launcher]
# Limit size of the launcher window (px)
width_limit = 300
name = "launcher_exec"
prompt = "Exec: "
command = "exec"
[/set_launcher]
[keys]
# Reload the configuration of wmfs.
[key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key]
# Open a terminal.
[key] mod = {"Control"} key = "Return" func = "spawn" cmd = "xterm" [/key]
# Kill the selected client.
[key] mod = {"Alt"} key = "q" func = "client_kill" [/key]
# Quit wmfs.
[key] mod = {"Control", "Alt", "Shift"} key = "q" func = "quit" [/key]
# Swap current client with the next.
[key] mod = {"Alt"} key = "t" func = "client_swap_next" [/key]
# Swap current client with the previous.
[key] mod = {"Alt", "Shift"} key = "t" func = "client_swap_prev" [/key]
# Set the selected client as Master
[key] mod = {"Control"} key = "m" func = "client_set_master" [/key]
# Toggle maximum the selected client
[key] mod = {"Alt"} key = "m" func = "toggle_max" [/key]
# Toggle free the selected client.
[key] mod = {"Alt"} key = "f" func = "toggle_free" [/key]
# Toggle the position of the infobar.
[key] mod = {"Alt"} key = "b" func = "toggle_infobar_position" [/key]
[key] mod = {"Alt", "Shift"} key = "b" func = "toggle_infobar_display" [/key]
# Toggle the resizehint of the current tag/screen
[key] mod = {"Shift", "Control"} key = "r" func = "toggle_resizehint" [/key]
# Toggle the tag_autohide mode
[key] mod = {"Shift", "Control"} key = "t" func = "toggle_tagautohide" [/key]
# Select the next client.
[key] mod = {"Alt"} key = "Tab" func = "client_next" [/key]
# Select the previous client.
[key] mod = {"Alt","Shift"} key = "Tab" func = "client_prev" [/key]
# Select the next tag.
[key] mod = {"Control"} key = "Right" func = "tag_next" [/key]
# Select the previous tag.
[key] mod = {"Control"} key = "Left" func = "tag_prev" [/key]
# Select the next visible tag.
[key] mod = {"Control","Alt"} key = "Right" func = "tag_next_visible" [/key]
# Select the previous visible tag.
[key] mod = {"Control","Alt"} key = "Left" func = "tag_prev_visible" [/key]
# Set the next layout.
[key] mod = {"Alt"} key = "space" func = "layout_next" [/key]
# Set the previous layout.
[key] mod = {"Alt", "Shift"} key = "space" func = "layout_prev" [/key]
# Increase nmaster.
[key] mod = {"Alt"} key = "d" func = "set_nmaster" cmd = "+1" [/key]
# Decease nmaster.
[key] mod = {"Alt", "Shift"} key = "d" func = "set_nmaster" cmd = "-1" [/key]
#Launcher.
[key] mod = {"Alt"} key = "p" func = "launcher" cmd = "launcher_exec" [/key]
# Set the tag x.
[key] mod = {"Alt"} key = "F1" func = "tag" cmd = "1" [/key]
[key] mod = {"Alt"} key = "F2" func = "tag" cmd = "2" [/key]
[key] mod = {"Alt"} key = "F3" func = "tag" cmd = "3" [/key]
[key] mod = {"Alt"} key = "F4" func = "tag" cmd = "4" [/key]
[key] mod = {"Alt"} key = "F5" func = "tag" cmd = "5" [/key]
[key] mod = {"Alt"} key = "F6" func = "tag" cmd = "6" [/key]
[key] mod = {"Alt"} key = "F7" func = "tag" cmd = "7" [/key]
[key] mod = {"Alt"} key = "F8" func = "tag" cmd = "8" [/key]
[key] mod = {"Alt"} key = "F9" func = "tag" cmd = "9" [/key]
# Transfert selected client to x.
[key] mod = {"Alt", "Shift"} key = "F1" func = "tag_transfert" cmd ="1" [/key]
[key] mod = {"Alt", "Shift"} key = "F2" func = "tag_transfert" cmd ="2" [/key]
[key] mod = {"Alt", "Shift"} key = "F3" func = "tag_transfert" cmd ="3" [/key]
[key] mod = {"Alt", "Shift"} key = "F4" func = "tag_transfert" cmd ="4" [/key]
[key] mod = {"Alt", "Shift"} key = "F5" func = "tag_transfert" cmd ="5" [/key]
[key] mod = {"Alt", "Shift"} key = "F6" func = "tag_transfert" cmd ="6" [/key]
[key] mod = {"Alt", "Shift"} key = "F7" func = "tag_transfert" cmd ="7" [/key]
[key] mod = {"Alt", "Shift"} key = "F8" func = "tag_transfert" cmd ="8" [/key]
[key] mod = {"Alt", "Shift"} key = "F9" func = "tag_transfert" cmd ="9" [/key]
# Toggle additional tags (x) on the current tag
[key] mod = {"Alt", "Super"} key = "F1" func = "tag_toggle_additional" cmd ="1" [/key]
[key] mod = {"Alt", "Super"} key = "F2" func = "tag_toggle_additional" cmd ="2" [/key]
[key] mod = {"Alt", "Super"} key = "F3" func = "tag_toggle_additional" cmd ="3" [/key]
[key] mod = {"Alt", "Super"} key = "F4" func = "tag_toggle_additional" cmd ="4" [/key]
[key] mod = {"Alt", "Super"} key = "F5" func = "tag_toggle_additional" cmd ="5" [/key]
[key] mod = {"Alt", "Super"} key = "F6" func = "tag_toggle_additional" cmd ="6" [/key]
[key] mod = {"Alt", "Super"} key = "F7" func = "tag_toggle_additional" cmd ="7" [/key]
[key] mod = {"Alt", "Super"} key = "F8" func = "tag_toggle_additional" cmd ="8" [/key]
[key] mod = {"Alt", "Super"} key = "F9" func = "tag_toggle_additional" cmd ="9" [/key]
# change screen
[key] mod = {"Super"} key = "Tab" func = "screen_next" [/key]
[key] mod = {"Super", "Shift"} key = "Tab" func = "screen_prev" [/key]
# swap client in the next/prev screen
[key] mod = {"Super", "Shift"} key = "a" func = "client_screen_next" [/key]
[key] mod = {"Super", "Shift"} key = "z" func = "client_screen_prev" [/key]
# 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_ignore_tag # Toggle the client in ignore_tag (display the client on all tags)
# tag_prev_sel # go back to the previous selected tag
# tag_transfert_{next, prev}
# tag_urgent # go to the urgent tag
# tag_swap_{next, prev} # swap tag with the previous/next one
# tag_last # go to the last tag
# tag_stay_last # toggle the current tag as the last one
# toggle_abovefc
# screen_prev_sel # go to the previous screen selected
# set_layout # set layout. need to be called with cmd = "<layout_name>"
# ignore_next_client_rules # ignore the rule the next time a rule is called
[/keys]

263
wmfsrc.in
View File

@@ -1,263 +0,0 @@
#
# This is the default wmfs config file, copy it to
# ~/.config/wmfs/wmfsrc and edit it.
#
[misc]
font = "dejavu-10"
raisefocus = false
focus_follow_mouse = true
status_timing = 1 #seconds
[/misc]
[bar]
bg = "#191919"
fg = "#D4D4D4"
border = true
selbar = false
[/bar]
[layouts]
fg = "#191919"
bg = "#7E89A2"
# Border around the layout button.
border = true
# Value menu or switch.
system = "menu"
# Value left or right.
placement = "right"
# Tiling layouts.
[layout] type = "tile_right" symbol = "RIGHT" [/layout]
[layout] type = "tile_left" symbol = "LEFT" [/layout]
[layout] type = "tile_top" symbol = "TOP" [/layout]
[layout] type = "tile_bottom" symbol = "BOTTOM" [/layout]
[layout] type = "tile_grid" symbol = "GRID" [/layout]
[layout] type = "mirror_vertical" symbol = "MIRROR_V" [/layout]
[layout] type = "mirror_horizontal" symbol = "MIRROR_H" [/layout]
# Other layouts.
[layout] type = "max" symbol = "MAX" [/layout]
[layout] type = "free" symbol = "FREE" [/layout]
[/layouts]
[tags]
tag_round = false
occupied_bg = "#003366"
sel_fg = "#191919"
sel_bg = "#7E89A2"
# Border around the tag buttons.
border = true
[tag]
name = "one"
screen = 0
mwfact = 0.65
nmaster = 1
layout = "tile_right"
resizehint = false
infobar_position = "top"
[/tag]
[tag] name = "two" clients = {"Browser"} [/tag]
[tag] name = "three" [/tag]
[tag] name = "four" [/tag]
[tag] name = "five" [/tag]
[tag] name = "six" [/tag]
[tag] name = "seven" [/tag]
[tag] name = "eight" [/tag]
[tag] name = "nine" [/tag]
[/tags]
[root]
# Command you can execute to set the background.
background_command = "xsetroot -solid black"
[mouse] button = "4" func = "tag_next" [/mouse]
[mouse] button = "5" func = "tag_prev" [/mouse]
[mouse] button = "3" func = "menu" cmd = "rootmenu" [/mouse]
[/root]
[client]
border_height = 3
border_shadow = true
border_normal = "#191919"
border_focus = "#003366"
resize_corner_normal = "#191919"
resize_corner_focus = "#003366"
modifier = "Alt"
[mouse] button = "1" func = "client_raise" [/mouse]
[mouse] button = "1" func = "mouse_move" [/mouse]
[mouse] button = "3" func = "client_raise" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
# Remove this section to delete the titlebar.
[titlebar]
stipple = false
height = 12
fg_normal = "#7E89A2"
fg_focus = "#9F9AB3"
[mouse] button = "1" func = "client_raise" [/mouse]
[mouse] button = "1" func = "mouse_move" [/mouse]
[mouse] button = "3" func = "client_raise" [/mouse]
[mouse] button = "3" func = "mouse_resize" [/mouse]
[button]
# Available "free", "max", "tile" flags of button.
flags = "free,max,tile"
[mouse] button = "1" func = "client_kill" [/mouse]
[mouse] button = "3" func = "menu" cmd = "clientmenu" [/mouse]
[line] coord = {1, 1, 4, 1} [/line]
[line] coord = {1, 1, 1, 4} [/line]
[line] coord = {1, 4, 4, 4} [/line]
[/button]
[/titlebar]
[/client]
[menu]
# Default menu, binded on the root window, button 3.
[set_menu]
name = "rootmenu"
# place_at_mouse = false
# x = 40 y = 50
fg_focus = "#191919" bg_focus = "#7E89A2"
fg_normal = "#9F9AB3" bg_normal = "#191919"
[item] name = "Terminal" func = "spawn" cmd = "@WMFS_TERM@" [/item]
[item] name = "Next tag" func = "tag_next" [/item]
[item] name = "Previous tag" func = "tag_prev" [/item]
[item] name = "Next layout" func = "layout_next" [/item]
[item] name = "Previous layout" func = "layout_prev" [/item]
[item] name = "Toggle infobar" func = "toggle_infobar_position" [/item]
[item] name = "Quit WMFS" func = "quit" [/item]
[/set_menu]
[set_menu]
name = "clientmenu"
fg_focus = "#D4D4D4" bg_focus = "#003366"
fg_normal = "#D4D4D4" bg_normal = "#191919"
[item] name = "Close" func = "client_kill" [/item]
[item] name = "Maximize" func = "toggle_max" [/item]
[item] name = "Free" func = "toggle_free" [/item]
[/set_menu]
[/menu]
[launcher]
[set_launcher]
name = "launcher_exec"
prompt = "Exec: "
command = "exec"
[/set_launcher]
#ViWMFS : manage wmfs with vi-based command.
[set_launcher]
name = "viwmfs"
prompt = "> "
command = "wmfs -V"
[/set_launcher]
[/launcher]
[keys]
# Reload the configuration of wmfs.
[key] mod = {"Alt", "Control"} key = "r" func = "reload" [/key]
# Open a terminal.
[key] mod = {"Control"} key = "Return" func = "spawn" cmd = "@WMFS_TERM@" [/key]
# Kill the selected client.
[key] mod = {"Alt"} key = "q" func = "client_kill" [/key]
# Quit wmfs.
[key] mod = {"Control", "Alt", "Shift"} key = "q" func = "quit" [/key]
# Swap current client with the next.
[key] mod = {"Alt"} key = "t" func = "client_swap_next" [/key]
# Swap current client with the previous.
[key] mod = {"Alt", "Shift"} key = "t" func = "client_swap_prev" [/key]
# Toggle maximum the selected client
[key] mod = {"Alt"} key = "m" func = "toggle_max" [/key]
# Toggle free the selected client.
[key] mod = {"Alt"} key = "f" func = "toggle_free" [/key]
# Toggle the position of the infobar.
[key] mod = {"Alt"} key = "b" func = "toggle_infobar_position" [/key]
# Toggle the resizehint of the current tag/screen
[key] mod = {"Shift", "Control"} key = "r" func = "toggle_resizehint" [/key]
# Select the next client.
[key] mod = {"Alt"} key = "Tab" func = "client_next" [/key]
# Select the previous client.
[key] mod = {"Alt","Shift"} key = "Tab" func = "client_prev" [/key]
# Select the next tag.
[key] mod = {"Control"} key = "Right" func = "tag_next" [/key]
# Select the previous tag.
[key] mod = {"Control"} key = "Left" func = "tag_prev" [/key]
# Set the next layout.
[key] mod = {"Alt"} key = "space" func = "layout_next" [/key]
# Set the previous layout.
[key] mod = {"Alt", "Shift"} key = "space" func = "layout_prev" [/key]
# Increase mwfact.
[key] mod = {"Alt"} key = "l" func = "set_mwfact" cmd = "+0.025" [/key]
# Decrease mwfact.
[key] mod = {"Alt"} key = "h" func = "set_mwfact" cmd = "-0.025" [/key]
# Increase nmaster.
[key] mod = {"Alt"} key = "d" func = "set_nmaster" cmd = "+1" [/key]
# Decease nmaster.
[key] mod = {"Alt", "Shift"} key = "d" func = "set_nmaster" cmd = "-1" [/key]
#Launcher.
[key] mod = {"Alt"} key = "p" func = "launcher" cmd = "launcher_exec" [/key]
#ViWMFS
[key] mod = {"Alt"} key = "Escape" func = "launcher" cmd = "viwmfs" [/key]
# Set the tag x.
[key] mod = {"Alt"} key = "F1" func = "tag" cmd = "1" [/key]
[key] mod = {"Alt"} key = "F2" func = "tag" cmd = "2" [/key]
[key] mod = {"Alt"} key = "F3" func = "tag" cmd = "3" [/key]
[key] mod = {"Alt"} key = "F4" func = "tag" cmd = "4" [/key]
[key] mod = {"Alt"} key = "F5" func = "tag" cmd = "5" [/key]
[key] mod = {"Alt"} key = "F6" func = "tag" cmd = "6" [/key]
[key] mod = {"Alt"} key = "F7" func = "tag" cmd = "7" [/key]
[key] mod = {"Alt"} key = "F8" func = "tag" cmd = "8" [/key]
[key] mod = {"Alt"} key = "F9" func = "tag" cmd = "9" [/key]
# Transfert selected client to x.
[key] mod = {"Alt", "Shift"} key = "F1" func = "tag_transfert" cmd ="1" [/key]
[key] mod = {"Alt", "Shift"} key = "F2" func = "tag_transfert" cmd ="2" [/key]
[key] mod = {"Alt", "Shift"} key = "F3" func = "tag_transfert" cmd ="3" [/key]
[key] mod = {"Alt", "Shift"} key = "F4" func = "tag_transfert" cmd ="4" [/key]
[key] mod = {"Alt", "Shift"} key = "F5" func = "tag_transfert" cmd ="5" [/key]
[key] mod = {"Alt", "Shift"} key = "F6" func = "tag_transfert" cmd ="6" [/key]
[key] mod = {"Alt", "Shift"} key = "F7" func = "tag_transfert" cmd ="7" [/key]
[key] mod = {"Alt", "Shift"} key = "F8" func = "tag_transfert" cmd ="8" [/key]
[key] mod = {"Alt", "Shift"} key = "F9" func = "tag_transfert" cmd ="9" [/key]
[/keys]