596 Commits

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

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

Move .PHONY BEFORE phony targets

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

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

Move status.sh to scripts/ with setlocalversion

Signed-off-by: Philippe Pepiot <phil@philpep.org>
2011-04-16 20:52:28 +02:00
Philippe Pepiot
a33ec045ab Parser: fix leak in include() 2011-04-14 12:14:26 +02:00
Philippe Pepiot
05bedec5c6 Config: Don't allocate child [rule] section if no [rules] 2011-04-14 12:13:51 +02:00
Martin Duquesnoy
88d92149dd Wmfsrc: Fix default value for autohide 2011-04-07 18:05:50 +02:00
Martin Duquesnoy
e28c6a3d64 Merge branch 'bacardi55' of github.com:xorg62/wmfs
Conflicts:
	src/event.c
2011-04-07 18:02:27 +02:00
Philippe Pepiot
3f21c79f08 Prevent segfault in uicb_checklayout() closes #105 2011-03-24 14:31:54 +01:00
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
Martin Duquesnoy
321669eb3a Draw: Fix possible segfault in textw (securize strcpy) 2010-03-28 16:09:00 +02:00
Martin Duquesnoy
aa9609b5cf Draw: Replace statustext_image by parse_color_block, remove image stuff in status.c (draw_text image stuff is sufficient) and update version 2010-03-28 15:41:54 +02:00
Martin Duquesnoy
09418c6dd7 Draw: Can put image everywhere we can habitually put text with same sequences than in statustext: \i[x;y;w;h;/image/path.ext]\ (example: layout, tag: http://omploader.org/vM3lzNg) 2010-03-28 14:49:10 +02:00
Martin Duquesnoy
0ce0d1a352 Draw: Add Imlib2 support to draw image (optional feature, work only if have imlib2): statustext block to draw image: \i[x;y;width;height;imagepath.extension]\ 2010-03-28 03:36:56 +02:00
OldMan
c350bb45d0 Conf: Buttons as indicators of client mode (Feature #33) 2010-03-25 19:53:00 +01:00
Martin Duquesnoy
06a9c44792 Client: Add ignore_next_client_rules uicb function requested by Armael. 2010-03-25 19:40:21 +01:00
Martin Duquesnoy
c5da009b7a Conf: Add [misc] status_path option to choose status script path 2010-03-25 19:19:24 +01:00
Martin Duquesnoy
23b0539686 Client: Reverse client_configure last modif 2010-03-25 13:46:59 +01:00
Martin Duquesnoy
8a236cc7ac Client: Update selbar if selected client get a new title 2010-03-25 12:36:34 +01:00
Martin Duquesnoy
4199b7bb50 Event: manage expose event for selbar 2010-03-24 19:15:11 +01:00
Martin Duquesnoy
842bc7d3ce Infobar: Add selbar; title of selected client in infobar (Feature #31 requested by markand), conf: [bar] selbar = true/false 2010-03-24 18:03:17 +01:00
Martin Duquesnoy
fab6a9f584 Tag: Fix mad behavior when wanting to transfer a client on the its tag 2010-03-04 21:54:18 +01:00
Martin Duquesnoy
7a714c03a9 Screen: Add screen_prev_sel function to go to the last used screen. (Feature #30 requested by Erus) 2010-02-26 23:40:16 +01:00
Martin Duquesnoy
2e0b050be3 Update version 2010-02-26 21:07:57 +01:00
OldMan
ade723b6bc Tag: Add functions to transfert selected client to next/previous tag. 2010-02-25 20:56:49 +01:00
OldMan
2b7d1c115d Client: Keep free-size after toggle_{free, max}. 2010-02-25 20:48:24 +01:00
Martin Duquesnoy
7e44e4b314 Tag: Add tag_prev_sel function request by Erus (Feature #29) 2010-02-25 20:39:04 +01:00
Martin Duquesnoy
77cb589f03 Mouse: Fix move_tag_client. 2010-02-07 17:56:48 +01:00
Martin Duquesnoy
56079ebdfe Infobar: Add option to move layout button before of after tags list (Feature #20 requested by Erus.) 2010-02-07 17:27:42 +01:00
Martin Duquesnoy
881ac9f68f Status: Add status.c, clean statutext fonction and add located text stuff: \s[x;y;#color;text]\. 2010-02-04 02:58:28 +01:00
Martin Duquesnoy
55fa590785 Revert "Conf: Fix bug (last keybind)"
This reverts commit a164eb8f7c.
2010-02-03 16:09:12 +01:00
Martin Duquesnoy
a164eb8f7c Conf: Fix bug (last keybind) 2010-02-03 15:42:59 +01:00
Martin Duquesnoy
888b2a7467 Infobar: Set buffers size to MAXSS 2010-01-31 16:27:27 +01:00
Philippe Pepiot
6f1624f43b Init: Define layout_list statically 2010-01-24 19:41:24 +01:00
Philippe Pepiot
04bef9a4b8 rc/status.sh: be posix compliant 2010-01-24 16:44:26 +01:00
Philippe Pepiot
344d80206c init: fix possible segfault if HOME not set 2010-01-20 11:38:32 +01:00
Philippe Pepiot
c6b97b7892 init: end layout list with { NULL, NULL } 2010-01-20 11:29:59 +01:00
Martin Duquesnoy
6c0a0b62b6 Infobar: Remove debug stuff ... again... 2010-01-10 16:33:56 +01:00
Martin Duquesnoy
bc94d42372 Infobar: Remove useless strncpy. 2010-01-10 16:32:49 +01:00
Martin Duquesnoy
f4d683f17f Infobar: Remove debug stuff 2010-01-10 15:07:19 +01:00
Martin Duquesnoy
d8afcfa013 Infobar: Fix strncpy mistake. 2010-01-10 15:06:37 +01:00
Martin Duquesnoy
af0d459b4c Infobar: Improve and simplify infobar_draw_statustext. 2010-01-10 03:00:48 +01:00
Martin Duquesnoy
b766375db8 Infobar: Code cosmetic. 2010-01-07 18:33:16 +01:00
Martin Duquesnoy
26498dc07b Infobar: Add bar feature in infobar_draw_statustext to make rectangle with wmfs -s -> \b[xx;yy;width;height;#color]\ *TEST* 2010-01-07 18:27:34 +01:00
Martin Duquesnoy
000a1f4c3d Infobar: Add bar feature in infobar_draw_statustext to make rectangle with wmfs -s -> \b[xx;yy;width;height;#color]\ *TEST* 2010-01-03 23:02:25 +01:00
Martin Duquesnoy
f0daf5ba20 Init: Replace system by spawn at the first execution of status_path 2010-01-02 20:31:42 +01:00
Martin Duquesnoy
250518c2a4 Wmfsrc: Add status_timing in default conf 2010-01-02 18:31:19 +01:00
Martin Duquesnoy
7acf0139d4 Infobar/Wmfs: Fix infobar_draw_statustext, remove useless screen_count() 2010-01-02 17:38:13 +01:00
Martin Duquesnoy
e4bbe15fc4 Infobar: Fix memleak in infobar_draw_statustext by replacing pointer to array 2010-01-02 16:50:37 +01:00
47 changed files with 8082 additions and 3966 deletions

16
.gitignore vendored
View File

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

View File

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

87
Makefile.in Normal file
View File

@@ -0,0 +1,87 @@
PROG=wmfs
MAN=wmfs.1
# wmfs version
VERSION=$(shell scripts/setlocalversion)
SRCS= \
src/barwin.c \
src/client.c \
src/config.c \
src/draw.c \
src/event.c \
src/ewmh.c \
src/frame.c \
src/infobar.c \
src/init.c \
src/launcher.c \
src/layout.c \
src/menu.c \
src/mouse.c \
src/parse_api.c \
src/parse.c \
src/screen.c \
src/status.c \
src/systray.c \
src/tag.c \
src/util.c \
src/color.c \
src/split.c \
src/cfactor.c \
src/wmfs.c
# flags
CFLAGS+= -DXDG_CONFIG_DIR=\"${XDG_CONFIG_DIR}\"
CFLAGS+= -DWMFS_VERSION=\"${VERSION}\"
CFLAGS+= -Wall -Wextra
OBJS= ${SRCS:.c=.o}
all: ${PROG} ${MAN}.gz
${PROG}: ${OBJS} src/structs.h src/wmfs.h src/parse.h
${CC} -o $@ ${OBJS} ${LDFLAGS}
${MAN}.gz: ${MAN}
gzip -cn -9 ${MAN} > $@
.c.o:
${CC} -c ${CFLAGS} $< -o $@
.PHONY: all clean distclean install uninstall dist
clean:
rm -f ${OBJS} wmfs ${MAN}.gz
distclean: clean
rm -f Makefile
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
mkdir -p ${DESTDIR}${PREFIX}/bin
install ${PROG} ${DESTDIR}${PREFIX}/bin
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
mkdir -p ${DESTDIR}${MANPREFIX}/man1
install -m 644 ${MAN}.gz ${DESTDIR}${MANPREFIX}/man1/
@echo installing xsession file to ${DESTDIR}${PREFIX}/share/xsessions
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
install -m 644 wmfs.desktop ${DESTDIR}${PREFIX}/share/xsessions/
@echo installing default config file to ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
mkdir -p ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
install -m 444 wmfsrc ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
rm -f ${DESTDIR}${PREFIX}/bin/wmfs
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
rm -f ${DESTDIR}${MANPREFIX}/man1/wmfs.1.gz
@echo removing xsession file from ${DESTDIR}${PREFIX}/share/xsessions
rm -f ${DESTDIR}${PREFIX}/share/xsessions/wmfs.desktop
@echo removing config file from ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
rm -f ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/wmfsrc
rmdir ${DESTDIR}${XDG_CONFIG_DIR}/wmfs/
dist:
@echo "Generate wmfs-`date +%Y%m`.tar.gz"
git archive --format=tar --prefix=wmfs-`date +%Y%m`/ master | gzip -c > wmfs-`date +%Y%m`.tar.gz

39
README
View File

@@ -4,33 +4,40 @@ WMFS Window Manager.
A highly configurable and manageable tiling Window Manager created from scratch
AUTHORS :
Martin Duquesnoy <xorg62@gmail.com>
AUTHOR :
- 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 :
- freetype2
- libx11
- libxft (optional)
- freetype
- libxinerama (optional)
- libxrandr (optional)
- libxft
- libx11
- CMake >= 2.6
- imlib2 (optional)
- cmake>=2.8 (build system, optional)
OS :
- GNU/Linux : Supported.
- FreeBSD : Supported.
- FreeBSD/OpenBSD/NetBSD : Supported.
INSTALL :
- mkdir build
- cd build
- cmake ..
- make
- sudo make install
- sudo make uninstall # if you would to remove it.
mkdir build/ && cd build/
cmake ..
If you have doxygen installed you can generate doxygen documentation via custom target 'make doc' in the build dir.
You can also use old build system if you don't want^Whave cmake
./configure && make
DISTROS :
- wmfs port for FreeBSD at x11-wm/wmfs
- 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
· Can change client position in the tile grid
· Fix all the bug \o/
· XCB ?
,
dM
MMr
4MMML .
MMMMM. xf
. "M6MMM .MM-
Mh.. +MM5MMM .MMMM
.MMM. .MMMMML. MMMMMh
)MMMh. MM5MMM MMMMMMM
3MMMMx. 'MMM3MMf xnMMMMMM"
'*MMMMM MMMMMM. nMMMMMMP"
*MMMMMx "MMM5M\ .MMMMMMM=
*MMMMMh "MMMMM" JMMMMMMP
MMMMMM GMMMM. dMMMMMM .
MMMMMM "MMMM .MMMMM( .nnMP"
.. *MMMMx MMM" dMMMM" .nnMMMMM*
"MMn... 'MMMMr 'MM MMM" .nMMMMMMM*"
"4MMMMnn.. *MMM MM MMP" .dMMMMMMM""
^MMMMMMMMx. *ML "M .M* .MMMMMM**"
*PMMMMMMhn. *x > M .MMMM**""
""**MMMMhx/.h/ .=*"
.3P"%....
nP" "*MMnx

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)

111
configure vendored Executable file
View File

@@ -0,0 +1,111 @@
#!/bin/sh
LIBS="x11"
USE_XINERAMA="xinerama"
USE_XRANDR="xrandr"
USE_IMLIB2="imlib2"
USE_XFT="xft freetype2"
OS=`uname -s`
PREFIX=/usr/local
MANPREFIX="$PREFIX/man"
XDG_CONFIG_DIR="$PREFIX/etc/xdg"
while true; do
case "$1" in
--without-xinerama)
USE_XINERAMA=""; shift;;
--without-xrandr)
USE_XRANDR=""; shift;;
--without-imlib2)
USE_IMLIB2=""; shift;;
--without-xft)
USE_XFT=""; shift;;
--prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
PREFIX=$2; shift 2;;
--xdg-config-dir)
[ -z "$2" ] && echo "Missing argument" && exit 1
XDG_CONFIG_DIR=$2; shift 2;;
--man-prefix)
[ -z "$2" ] && echo "Missing argument" && exit 1
MANPREFIX=$2; shift 2;;
--help|-h)
echo "Usage: ./configure [options]
--without-imlib2 : compile without imlib2 support
--without-xrandr : compile without xrandr support
--without-xinerama : compile without xinerama support
--without-xft : compile without xft support
--prefix DIRECTORY : install binary with specified prefix (default $PREFIX)
--xdg-config-dir DIRECTORY : install configuration to specified directory (default $XDG_CONFIG_DIR)
--man-prefix DIRECTORY : install man page to specified prefix (default $MANPREFIX)"
exit 0;;
*) break;;
esac
done
LIBS="$LIBS $USE_XINERAMA $USE_XRANDR $USE_IMLIB2 $USE_XFT"
which pkg-config >/dev/null 2>&1
if [ $? -eq 0 ];
then
CFLAGS=`pkg-config --cflags-only-I $LIBS`
LDFLAGS=`pkg-config --libs $LIBS`
else
# Try to use some known paths
case $OS in
FreeBSD)
CFLAGS="-I/usr/local/include -I/usr/local/include/freetype2"
LDFLAGS="-L/usr/local/lib";;
OpenBSD)
CFLAGS="-I/usr/X11R6/include -I/usr/X11R6/include/freetype2 -I/usr/local/include"
LDFLAGS="-L/usr/X11R6/lib -L/usr/local/lib";;
NetBSD)
CFLAGS="-I/usr/X11R7/include -I/usr/X11R7/include/freetype2 -I/usr/local/include"
LDFLAGS="-L/usr/X11R7/lib -L/usr/local/lib";;
Linux)
CFLAGS="-I/usr/include/freetype2"
LDFLAGS=""
;;
*)
echo "No default CFLAGS and LDFLAGS found for your OS, feel free to contribute or install pkg-config :)"
exit 1;;
esac
LDFLAGS="$LDFLAGS -lX11"
[ -n "$USE_XINERAMA" ] && LDFLAGS="$LDFLAGS -lXinerama"
[ -n "$USE_XRANDR" ] && LDFLAGS="$LDFLAGS -lXrandr"
[ -n "$USE_IMLIB2" ] && LDFLAGS="$LDFLAGS -lImlib2"
[ -n "$USE_XFT" ] && LDFLAGS="$LDFLAGS -lXft -lfreetype"
fi
[ -n "$USE_XINERAMA" ] && CFLAGS="$CFLAGS -DHAVE_XINERAMA"
[ -n "$USE_XRANDR" ] && CFLAGS="$CFLAGS -DHAVE_XRANDR"
[ -n "$USE_IMLIB2" ] && CFLAGS="$CFLAGS -DHAVE_IMLIB"
[ -n "$USE_XFT" ] && CFLAGS="$CFLAGS -DHAVE_XFT"
LDFLAGS="$LDFLAGS -lpthread"
cat > Makefile << EOF
PREFIX=$PREFIX
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
MANPREFIX=$MANPREFIX
CFLAGS+=$CFLAGS
LDFLAGS+=$LDFLAGS
EOF
cat Makefile.in >> Makefile
echo "Compilation resume:
OS=$OS
CFLAGS=$CFLAGS
LDFLAGS=$LDFLAGS
PREFIX=$PREFIX
MANPREFIX=$MANPREFIX
XDG_CONFIG_DIR=$XDG_CONFIG_DIR
You can run 'make' now :-)
"

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

@@ -5,9 +5,7 @@
statustext()
{
local DATE=`date`
wmfs -s "$DATE"
wmfs -s "`date`"
}
statustext
while true; do statustext; sleep 10; done

View File

@@ -39,26 +39,26 @@
* \param w BarWindow Width
* \param h BarWindow Height
* \param color BarWindow color
* \param entermask Bool for know if the EnterMask mask is needed
* \param entermask bool for know if the EnterMask mask is needed
* \return The BarWindow pointer
*/
BarWindow*
barwin_create(Window parent,
int x,
int y,
uint w,
uint h,
int w,
int h,
uint bg,
char *fg,
Bool entermask,
Bool stipple,
Bool border)
bool entermask,
bool stipple,
bool border)
{
XSetWindowAttributes at;
BarWindow *bw;
/* Allocate memory */
bw = emalloc(1, sizeof(BarWindow));
bw = zcalloc(sizeof(*bw));
/* Barwin attributes */
at.override_redirect = True;
@@ -67,6 +67,7 @@ barwin_create(Window parent,
|ButtonMask|MouseMask
|ExposureMask|VisibilityChangeMask
|StructureNotifyMask|SubstructureRedirectMask;
if(entermask)
at.event_mask |= EnterWindowMask|LeaveWindowMask|FocusChangeMask;
@@ -79,12 +80,14 @@ barwin_create(Window parent,
/* His border */
if(border)
{
bw->bord = True;
bw->flags |= BordFlag;
bw->border.light = color_shade(bg, conf.colors.bar_light_shade);
bw->border.dark = color_shade(bg, conf.colors.bar_dark_shade);
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, color_enlight(bg), &at);
CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, color_enlight(bg), &at);
CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, SHADC, &at);
CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, SHADC, &at);
CWIN(bw->border.left, bw->win, 0, 0, SHADH, h, 0, CWBackPixel, bg, &at);
CWIN(bw->border.top, bw->win, 0, 0, w, SHADH, 0, CWBackPixel, bg, &at);
CWIN(bw->border.bottom, bw->win, 0, h - SHADH, w, SHADH, 0, CWBackPixel, bg, &at);
CWIN(bw->border.right, bw->win, w - SHADH, 0, SHADH, h, 0, CWBackPixel, bg, &at);
}
/* Property */
@@ -94,10 +97,11 @@ barwin_create(Window parent,
bw->geo.height = h;
bw->bg = bg;
bw->fg = fg;
bw->border.light = color_enlight(bg);
bw->border.dark = SHADC;
bw->stipple = stipple;
bw->stipple_color = -1;
FLAGAPPLY(bw->flags, stipple, StippleFlag);
bw->stipple_color = 0xffffffff;
/* Attach */
SLIST_INSERT_HEAD(&bwhead, bw, next);
return bw;
}
@@ -108,25 +112,42 @@ void
barwin_draw_text(BarWindow *bw, int x, int y, char *text)
{
/* Background color of the text if there is stipple */
if(bw->stipple)
if(bw->flags & StippleFlag)
draw_rectangle(bw->dr, x - 4, 0, textw(text) + 8, bw->geo.height, bw->bg);
/* Draw text */
draw_text(bw->dr, x, y, bw->fg, 0, text);
draw_text(bw->dr, x, y, bw->fg, text);
barwin_refresh(bw);
return;
}
void
barwin_color_set(BarWindow *bw, uint bg, char *fg)
{
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 == 0xffffffff)
bw->stipple_color = getcolor(fg);
return;
}
/** Delete a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_delete(BarWindow *bw)
{
CHECK(bw);
SLIST_REMOVE(&bwhead, bw, BarWindow, next);
XSelectInput(dpy, bw->win, NoEventMask);
XDestroyWindow(dpy, bw->win);
XFreePixmap(dpy, bw->dr);
@@ -135,77 +156,6 @@ barwin_delete(BarWindow *bw)
return;
}
/** Delete the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_delete_subwin(BarWindow *bw)
{
CHECK(bw);
XDestroySubwindows(dpy, bw->win);
return;
}
/** Map a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_map(BarWindow *bw)
{
CHECK(!bw->mapped);
XMapWindow(dpy, bw->win);
bw->mapped = True;
return;
}
/** Map the subwindows of a BarWindow
* Use for the BarWindow special border...
* \param bw BarWindow pointer
*/
void
barwin_map_subwin(BarWindow *bw)
{
CHECK(bw);
XMapSubwindows(dpy, bw->win);
return;
}
/** Unmap a BarWindow
* \param bw BarWindow pointer
*/
void
barwin_unmap(BarWindow *bw)
{
CHECK(bw->mapped);
XUnmapWindow(dpy, bw->win);
bw->mapped = False;
return;
}
/** Unmap the BarWindow sub windows
* \param bw BarWindow pointer
*/
void
barwin_unmap_subwin(BarWindow *bw)
{
CHECK(bw);
XUnmapSubwindows(dpy, bw->win);
return;
}
/** Move a BarWindow
* \param bw BarWindow pointer
* \param x X position
@@ -214,12 +164,10 @@ barwin_unmap_subwin(BarWindow *bw)
void
barwin_move(BarWindow *bw, int x, int y)
{
CHECK(bw);
if(bw->geo.x == x && bw->geo.y == y)
return;
bw->geo.x = x;
bw->geo.y = y;
XMoveWindow(dpy, bw->win, x, y);
XMoveWindow(dpy, bw->win, (bw->geo.x = x), (bw->geo.y = y));
return;
}
@@ -230,24 +178,26 @@ barwin_move(BarWindow *bw, int x, int y)
* \param h Height
*/
void
barwin_resize(BarWindow *bw, uint w, uint h)
barwin_resize(BarWindow *bw, int w, int h)
{
CHECK(bw);
if(bw->geo.width == w && bw->geo.height == h)
return;
/* Frame */
XFreePixmap(dpy, bw->dr);
bw->dr = XCreatePixmap(dpy, ROOT,
w - ((bw->flags & BordFlag) ? SHADH : 0),
h - ((bw->flags & BordFlag) ? SHADH : 0),
DefaultDepth(dpy, SCREEN));
bw->geo.width = w;
bw->geo.height = h;
XFreePixmap(dpy, bw->dr);
/* Frame */
bw->dr = XCreatePixmap(dpy, ROOT,
w - ((bw->bord) ? SHADH : 0),
h - ((bw->bord) ? SHADH : 0),
DefaultDepth(dpy, SCREEN));
XResizeWindow(dpy, bw->win, w, h);
/* Border */
if(bw->bord)
if(bw->flags & BordFlag)
{
XResizeWindow(dpy, bw->border.left, SHADH, h);
XResizeWindow(dpy, bw->border.top, w, SHADH);
@@ -264,22 +214,21 @@ barwin_resize(BarWindow *bw, uint w, uint h)
void
barwin_refresh_color(BarWindow *bw)
{
CHECK(bw);
XSetForeground(dpy, gc, bw->bg);
XFillRectangle(dpy, bw->dr, gc, 0, 0, bw->geo.width, bw->geo.height);
draw_rectangle(bw->dr, 0, 0, bw->geo.width, bw->geo.height, bw->bg);
if(bw->stipple)
if(bw->flags & StippleFlag)
{
XSetForeground(dpy, gc_stipple, ((bw->stipple_color != -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);
}
if(bw->bord)
if(bw->flags & BordFlag)
{
XSetWindowBackground(dpy, bw->border.left, bw->border.light);
XSetWindowBackground(dpy, bw->border.top, bw->border.light);
XSetWindowBackground(dpy, bw->border.left, bw->border.light);
XSetWindowBackground(dpy, bw->border.top, bw->border.light);
XSetWindowBackground(dpy, bw->border.bottom, bw->border.dark);
XSetWindowBackground(dpy, bw->border.right, bw->border.dark);
XSetWindowBackground(dpy, bw->border.right, bw->border.dark);
XClearWindow(dpy, bw->border.left);
XClearWindow(dpy, bw->border.top);
@@ -290,16 +239,3 @@ barwin_refresh_color(BarWindow *bw)
return;
}
/** Refresh the BarWindow
* \param bw BarWindow pointer
*/
void
barwin_refresh(BarWindow *bw)
{
if(!bw || !bw->dr || !bw->win)
return;
XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0);
return;
}

279
src/cfactor.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* cfactor.c
* Copyright © 2011 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
#define CLIENT_RESIZE_DIR(d) \
void \
uicb_client_resize_##d(uicb_t cmd) \
{ \
CHECK(sel); \
cfactor_set(sel, d, atoi(cmd)); \
}
/* uicb_client_resize_dir() */
CLIENT_RESIZE_DIR(Right);
CLIENT_RESIZE_DIR(Left);
CLIENT_RESIZE_DIR(Top);
CLIENT_RESIZE_DIR(Bottom);
/** Clean client tile factors
*\param c Client pointer
*/
void
cfactor_clean(Client *c)
{
CHECK(c);
if(!(tags[c->screen][c->tag].flags & (SplitFlag | CleanFactFlag)))
return;
c->tilefact[Right] = c->tilefact[Left] = 0;
c->tilefact[Top] = c->tilefact[Bottom] = 0;
return;
}
/** Return new geo of client with factors applied
*\param c Client pointer
*\return geo
*/
Geo
cfactor_geo(Geo geo, int fact[4], int *err)
{
Geo cgeo = geo;
*err = 0;
/* Right factor */
cgeo.width += fact[Right];
/* Left factor */
cgeo.x -= fact[Left];
cgeo.width += fact[Left];
/* Top factor */
cgeo.y -= fact[Top];
cgeo.height += fact[Top];
/* Bottom factor */
cgeo.height += fact[Bottom];
/* Too big/small */
if(cgeo.width > sgeo[selscreen].width || cgeo.height > sgeo[selscreen].height
|| cgeo.width < (BORDH << 1) || cgeo.height < (BORDH + TBARH))
{
*err = 1;
return geo;
}
return cgeo;
}
/** Get c parents of row and resize
*\param c Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static void
_cfactor_arrange_row(Client *c, Position p, int fac)
{
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
/* Travel clients to search parents of row and apply fact */
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{
cc->tilefact[p] += fac;
client_moveresize(cc, cc->geo, (tags[cc->screen][cc->tag].flags & ResizeHintFlag));
}
return;
}
/** Get c parents of row and check geo with futur resize factor
*\param c Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*\return False in case of error
*/
static bool
_cfactor_check_geo_row(Client *c, Position p, int fac)
{
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
int e, f[4] = { 0 };
f[p] += fac;
/* Travel clients to search parents of row and check geos */
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, p))
{
(Geo)cfactor_geo(cc->wrgeo, f, &e);
if(e)
return False;
}
return True;
}
/* Resize only 2 client with applied factor
*\param c1 Client pointer
*\param c2 Client pointer
*\param p Direction of resizing
*\param fac Facotr
*/
static void
cfactor_arrange_two(Client *c1, Client *c2, Position p, int fac)
{
c1->tilefact[p] += fac;
c2->tilefact[RPOS(p)] -= fac;
/* Needed in case of padding */
if(conf.client.padding)
{
c1->flags |= FLayFlag;
c2->flags |= FLayFlag;
}
client_moveresize(c1, c1->geo, (tags[c1->screen][c1->tag].flags & ResizeHintFlag));
client_moveresize(c2, c2->geo, (tags[c2->screen][c2->tag].flags & ResizeHintFlag));
return;
}
/** Get c parents of row and resize, exception checking same size before arranging row
*\param c Client pointer
*\param gc Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static void
cfactor_arrange_row(Client *c, Client *gc, Position p, int fac)
{
if(CFACTOR_CHECK2(c->frame_geo, gc->frame_geo, p))
cfactor_arrange_two(c, gc, p, fac);
else
{
_cfactor_arrange_row(c, p, fac);
_cfactor_arrange_row(gc, RPOS(p), -fac);
}
return;
}
/** Check future geometry of factorized client
*\param c Client pointer
*\param g Client pointer
*\param p Direction of resizing
*\param fac Factor of resizing
*/
static bool
cfactor_check_geo(Client *c, Client *g, Position p, int fac)
{
int e, ee;
int cf[4] = { 0 }, gf[4] = { 0 };
/* Check c & g first */
cf[p] += fac;
gf[RPOS(p)] -= fac;
(Geo)cfactor_geo(c->geo, cf, &e);
(Geo)cfactor_geo(g->geo, gf, &ee);
/* Size failure */
if(e || ee || !_cfactor_check_geo_row(c, p, fac)
|| !_cfactor_check_geo_row(g, RPOS(p), -fac))
return False;
return True;
}
/** Manual resizing of tiled clients
* \param c Client pointer
* \param p Direction of resizing
* \param fac Factor of resizing
*/
void
cfactor_set(Client *c, Position p, int fac)
{
Client *gc = NULL;
if(!c || !(c->flags & TileFlag) || p > Bottom)
return;
/* Get next client with direction of resize */
gc = client_get_next_with_direction(c, p);
if(!gc || c->screen != gc->screen)
return;
/* Check size */
if(!cfactor_check_geo(c, gc, p, fac))
return;
/* Arrange client and row parents */
cfactor_arrange_row(c, gc, p, fac);
/* Enable split with cfactor_enable_split option */
if(conf.cfactor_enable_split
&& !(tags[c->screen][c->tag].flags & SplitFlag))
{
tags[c->screen][c->tag].flags |= SplitFlag;
infobar_draw_layout(&infobar[c->screen]);
}
return;
}
/** Apply a complete factor array to a client
* \param c Client pointer
* \param fac factor array
*/
void
cfactor_multi_set(Client *c, int fac[4])
{
if(!c)
return;
cfactor_set(c, Right, fac[Right]);
cfactor_set(c, Left, fac[Left]);
cfactor_set(c, Top, fac[Top]);
cfactor_set(c, Bottom, fac[Bottom]);
return;
}

File diff suppressed because it is too large Load Diff

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

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,99 @@
#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
*\param m Check dynamic mouse
*\return n Lenght of i
*/
static void
parse_image_block(Drawable dr, char *str, bool m)
{
ImageAttr im;
Geo area;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k = 0, n;
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^];]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, &as)) == 6
|| (n = sscanf(&str[i], "\\i[%d;%d;%d;%d;%512[^;];%512[^]]]%c",
&im.x, &im.y, &im.w, &im.h, im.name, mouse, &as)) == 7)
&& as == '\\')
{
draw_image(dr, im.x - sw, im.y, im.w, im.h, im.name);
/* Etablish clickable area on image (on infobar wins only (status mouse bind) */
if(n == 7 && m)
{
area.x = im.x - sw;
area.y = im.y;
area.width = im.w;
area.height = im.h;
/* Associate drawable with window; travel infobars */
for(; k < screen_count(); ++k)
if(infobar[k].bar->dr == dr)
{
statustext_mouse(mouse, area, &infobar[k]);
break;
}
}
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i)
str[j] = str[i];
for(sw = 0, k = j; k < i; str[k++] = 0);
return;
}
#endif /* HAVE_IMLIB */
/** Draw a string in a Drawable
* \param d Drawable
* \param x X position
@@ -41,24 +134,62 @@
* \param str String that will be draw
*/
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;
XftDraw *xftd;
CHECK(str);
/* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
/* To draw image everywhere we can draw text */
#ifdef HAVE_IMLIB
char *ostr;
size_t textlen = 0;
/* Alloc text color */
XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, SCREEN), fg, &xftcolor);
if(strstr(str, "i["))
{
if(d == infobar[conf.systray.screen].bar->dr)
sw = systray_get_width();
XftDrawStringUtf8(xftd, &xftcolor, font, x, y, (FcChar8 *)str, strlen(str));
ostr = xstrdup(str);
textlen = strlen(ostr);
parse_image_block(d, str, True);
}
#endif /* HAVE_IMLIB */
/* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
#ifdef HAVE_XFT
if(conf.use_xft)
{
XftColor xftcolor;
XftDraw *xftd;
XftDrawDestroy(xftd);
/* Transform X Drawable -> Xft Drawable */
xftd = XftDrawCreate(dpy, d, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN));
/* Alloc text color */
XftColorAllocName(dpy, DefaultVisual(dpy, SCREEN),
DefaultColormap(dpy, SCREEN), fg, &xftcolor);
XftDrawStringUtf8(xftd, &xftcolor, font.font, x, y, (FcChar8 *)str, strlen(str));
/* Free the text color and XftDraw */
XftColorFree(dpy, DefaultVisual(dpy, SCREEN), DefaultColormap(dpy, SCREEN), &xftcolor);
XftDrawDestroy(xftd);
}
else
#endif /* HAVE_XFT */
{
/* Use font set */
XSetForeground(dpy, gc, getcolor(fg));
XmbDrawString(dpy, d, font.fontset, gc, x, y, str, strlen(str));
}
#ifdef HAVE_IMLIB
if(textlen)
{
strncpy(str, ostr, textlen);
free(ostr);
}
#endif /* HAVE_IMLIB */
return;
}
@@ -72,12 +203,30 @@ draw_text(Drawable d, int x, int y, char* fg, int pad, char *str)
* \param color Color of the rectangle
*/
void
draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color)
draw_rectangle(Drawable dr, int x, int y, int w, int h, uint color)
{
XRectangle r = { x, y, w, h };
XSetForeground(dpy, gc, color);
XFillRectangles(dpy, dr, gc, &r, 1);
XFillRectangle(dpy, dr, gc, x, y, (uint)w, (uint)h);
return;
}
/** Draw a Graph in a drawable
* \param dr Drawable
* \param x X position
* \param y Y position
* \param w Width
* \param h Height
* \param color Color of the graph
* \param data Array of bytes that will be draw
*/
void
draw_graph(Drawable dr, int x, int y, int w, int h, uint color, char *data)
{
int i;
for(i = 0; i < w; ++i)
draw_rectangle(dr, x + i, y + h - data[i], 1, data[i], color);
return;
}
@@ -87,16 +236,50 @@ draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color)
* \return final text width
*/
ushort
textw(const char *text)
textw(char *text)
{
XGlyphInfo gl;
Drawable d = 0;
ushort ret = 0;
if(!text)
return 0;
XftTextExtentsUtf8(dpy, font, (FcChar8 *)text, strlen(text), &gl);
#ifdef HAVE_IMLIB
char *ostr;
size_t textlen = 0;
return gl.width + font->descent;
if(strstr(text, "i["))
{
ostr = xstrdup(text);
textlen = strlen(ostr);
parse_image_block(d, text, False);
}
#endif /* HAVE_IMLIB */
#ifdef HAVE_XFT
if(conf.use_xft)
{
XGlyphInfo gl;
XftTextExtentsUtf8(dpy, font.font, (FcChar8 *)text, strlen(text), &gl);
ret = gl.width + font.de;
}
else
#endif /* HAVE_XFT */
{
XRectangle r;
XmbTextExtents(font.fontset, text, strlen(text), NULL, &r);
ret = r.width;
}
#ifdef HAVE_IMLIB
if(textlen)
{
strncpy(text, ostr, textlen);
free(ostr);
}
#endif /* HAVE_IMLIB */
return ret;
}

View File

@@ -32,38 +32,66 @@
#include "wmfs.h"
/** ButtonPress handle event
* \param ev XButtonEvent pointer
*/
void
buttonpress(XButtonEvent *ev)
#define EVDPY (e->xany.display)
#define MAX_EV 256
/** Check mouse bind condition and execute associated function
*/
static void
do_mousebind(int screen, uint button, int n, MouseBinding m[])
{
int i = 0;
for(; i < n; ++i)
{
if(m[i].screen == screen || m[i].screen < 0) /* Screen */
if(m[i].tag == seltag[i] || m[i].tag < 0) /* Tag */
if(m[i].button == button) /* Button */
if(m[i].func) /* Function */
m[i].func(m[i].cmd);
}
return;
}
/** ButtonPress handle event
*/
static void
buttonpress(XEvent *e)
{
XButtonEvent *ev = &e->xbutton;
StatusMouse *sm;
InfoBar *ib;
Client *c;
int i, j, n;
int i, n;
screen_get_sel();
ib = &infobar[selscreen];
/* If the mouse is on a not selected client and you click on it. */
if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window))) && c != sel
&& (ev->button == Button1 || ev->button == Button2 || ev->button == Button3))
if(((c = client_gb_win(ev->window)) || (c = client_gb_titlebar(ev->window)))
&& c != sel && ev->button >= Button1 && ev->button <= Button3)
{
client_focus(c);
client_raise(c);
return;
}
/* Titlebar */
if((c = client_gb_titlebar(ev->window)) && c == sel)
for(i = 0; i < conf.titlebar.nmouse; ++i)
if(ev->button == conf.titlebar.mouse[i].button)
if(conf.titlebar.mouse[i].func)
conf.titlebar.mouse[i].func(conf.titlebar.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.titlebar.nmouse, conf.titlebar.mouse);
/* Titlebar buttons */
if((c = client_gb_button(ev->window, &n)))
for(i = 0; i < conf.titlebar.button[n].nmouse; ++i)
if(ev->button == conf.titlebar.button[n].mouse[i].button)
if(conf.titlebar.button[n].mouse[i].func)
{
client_focus(c);
conf.titlebar.button[n].mouse[i].func(conf.titlebar.button[n].mouse[i].cmd);
}
/* Frame Resize Area */
if((c = client_gb_resize(ev->window)))
@@ -71,76 +99,81 @@ buttonpress(XButtonEvent *ev)
/* Client */
if((c = client_gb_win(ev->window)) && c == sel)
for(i = 0; i < conf.client.nmouse; ++i)
if(ev->button == conf.client.mouse[i].button)
if(conf.client.mouse[i].func)
conf.client.mouse[i].func(conf.client.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.client.nmouse, conf.client.mouse);
/* Root */
if(ev->window == ROOT)
for(i = 0; i < conf.root.nmouse; ++i)
if(conf.root.mouse[i].tag == seltag[conf.root.mouse[i].screen]
|| conf.root.mouse[i].tag < 0)
if(ev->button == conf.root.mouse[i].button)
if(conf.root.mouse[i].func)
conf.root.mouse[i].func(conf.root.mouse[i].cmd);
do_mousebind(selscreen, ev->button, conf.root.nmouse, conf.root.mouse);
/* Infobars */
for(i = 0; i < screen_count(); ++i)
if(ev->window == infobar[i].bar->win)
for(j = 0; j < conf.bars.nmouse; ++j)
if(conf.bars.mouse[j].screen == i
|| conf.bars.mouse[j].screen < 0)
if(conf.bars.mouse[j].tag == seltag[i]
|| conf.bars.mouse[j].tag < 0)
if(ev->button == conf.bars.mouse[j].button)
if(conf.bars.mouse[j].func)
conf.bars.mouse[j].func(conf.bars.mouse[j].cmd);
do_mousebind(i, ev->button, conf.bars.nmouse, conf.bars.mouse);
/* Selbar */
if(conf.bars.selbar && ev->window == ib->bar->win)
if(INAREA(ev->x, ev->y, ib->selbar_geo))
do_mousebind(selscreen, ev->button, conf.selbar.nmouse, conf.selbar.mouse);
/* Tags */
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(ev->window == infobar[selscreen].tags[i]->win)
switch(ev->button)
if(ib->tags_board)
{
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(ib->tags[i] && ev->window == ib->tags[i]->win)
{
case Button1: tag_set(i); break;
case Button3: tag_transfert(sel, i); break;
case Button4: tag_set(seltag[selscreen] + 1); break;
case Button5: tag_set(seltag[selscreen] - 1); break;
do_mousebind(selscreen, ev->button, tags[selscreen][i].nmouse, tags[selscreen][i].mouse);
/* Mouse button action on tag */
if(ev->button == conf.mouse_tag_action[TagSel])
tag_set(i);
else if(ev->button == conf.mouse_tag_action[TagTransfert])
tag_transfert(sel, i);
else if(ev->button == conf.mouse_tag_action[TagAdd])
tag_additional(selscreen, seltag[selscreen], i);
else if(ev->button == conf.mouse_tag_action[TagNext])
tag_set(seltag[selscreen] + 1);
else if(ev->button == conf.mouse_tag_action[TagPrev])
tag_set(seltag[selscreen] - 1);
}
}
/* Layout button */
if(ev->window == infobar[selscreen].layout_button->win && conf.nlayout > 1)
if(ib->layout_button && ev->window == ib->layout_button->win && conf.nlayout > 1)
{
if(conf.layout_system && (ev->button == Button1 || ev->button == Button3)) /* True -> menu */
{
menulayout.y = spgeo[selscreen].y + infobar[selscreen].layout_button->geo.y + INFOBARH;
menulayout.x = infobar[selscreen].layout_button->geo.x + (sgeo[selscreen].x - BORDH);
menulayout.y = spgeo[selscreen].y + ib->layout_button->geo.y + INFOBARH;
menulayout.x = ib->layout_button->geo.x + (sgeo[selscreen].x - BORDH);
if(infobar[selscreen].geo.y != spgeo[selscreen].y)
menulayout.y = infobar[selscreen].geo.y - (INFOBARH * menulayout.nitem) - SHADH;
if(ib->geo.y != spgeo[selscreen].y)
menulayout.y = ib->geo.y - (INFOBARH * menulayout.nitem) - SHADH;
uicb_menu("menulayout");
}
else
{
switch(ev->button)
{
case Button1: case Button4: layoutswitch(True); break;
case Button3: case Button5: layoutswitch(False); break;
}
}
layoutswitch(ev->button == Button1 || ev->button == Button4);
}
/* Status mouse bindings */
SLIST_FOREACH(sm, &smhead, next)
if(sm->infobar->bar->win == ev->window && ev->button == sm->button)
if(INAREA(ev->x, ev->y, sm->area))
if(sm->func)
sm->func(sm->cmd);
return;
}
/* ClientMessage handle event
*\param ev XClientMessageEvent pointer
*/
void
clientmessageevent(XClientMessageEvent *ev)
static void
clientmessageevent(XEvent *e)
{
XClientMessageEvent *ev = &e->xclient;
Client *c;
int i, mess_t = 0;
InfoBar *ib;
Systray *sy;
int s, mess_t = 0;
Atom rt;
int rf;
ulong ir, il;
@@ -151,9 +184,10 @@ clientmessageevent(XClientMessageEvent *ev)
if(ev->format != 32)
return;
for(i = 0; i < net_last + screen_count(); ++i)
if(net_atom[i] == ev->message_type)
mess_t = i;
s = screen_count();
while(mess_t < net_last + s && net_atom[mess_t] != ev->message_type)
++mess_t;
if(ev->window == ROOT)
{
@@ -166,13 +200,33 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _WMFS_SET_SCREEN */
if(mess_t == wmfs_set_screen
&& ev->data.l[0] >= 0
&& ev->data.l[0] <= screen_count())
&& ev->data.l[0] <= s)
screen_set_sel((int)(ev->data.l[0]));
/* Manage _NET_ACTIVE_WINDOW */
else if(mess_t == net_active_window)
{
if((c = client_gb_win(ev->window)))
client_focus(c);
else if((sy = systray_find(ev->data.l[0])))
XSetInputFocus(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 */
@@ -187,37 +241,41 @@ clientmessageevent(XClientMessageEvent *ev)
/* Manage _NET_WM_DESKTOP */
if(mess_t == net_wm_desktop)
if((c = client_gb_win(ev->window)))
if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF)
tag_transfert(c, ev->data.l[0]);
/* Manage _WMFS_STATUSTEXT_x */
if(mess_t >= wmfs_statustext && ev->data.l[4] == True)
if(ev->data.l[4])
{
if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
/* Manage _WMFS_STATUSTEXT_x */
if(mess_t >= wmfs_statustext)
{
infobar_draw_statustext(mess_t - wmfs_statustext, (char*)ret);
if(XGetWindowProperty(EVDPY, ROOT, net_atom[mess_t], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success)
{
ib = &infobar[mess_t - wmfs_statustext];
free(ib->statustext);
ib->statustext = xstrdup((char*)ret);
_infobar_draw(ib);
XFree(ret);
}
}
/* Manage _WMFS_FUNCTION && _WMFS_CMD */
if(mess_t == wmfs_function || mess_t == wmfs_cmd)
{
XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_function], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret);
XGetWindowProperty(EVDPY, ROOT, net_atom[wmfs_cmd], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd);
if((func = name_to_func((char*)ret, func_list)))
func((uicb_t)ret_cmd);
XFree(ret_cmd);
XFree(ret);
}
}
/* Manage _WMFS_FUNCTION && _WMFS_CMD */
if((mess_t == wmfs_function && ev->data.l[4] == True)
|| (mess_t == wmfs_cmd && ev->data.l[4] == True))
{
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_function], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret);
XGetWindowProperty(dpy, ROOT, net_atom[wmfs_cmd], 0, 4096,
False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd);
if((func = name_to_func((char*)ret, func_list)))
func((uicb_t)ret_cmd);
XFree(ret_cmd);
XFree(ret);
}
/* Manage _WMFS_UPDATE_HINTS */
if(mess_t == wmfs_update_hints)
{
@@ -226,36 +284,26 @@ clientmessageevent(XClientMessageEvent *ev)
ewmh_get_client_list();
ewmh_get_desktop_names();
ewmh_set_desktop_geometry();
ewmh_set_workarea();
screen_count();
screen_get_sel();
}
if(mess_t == wmfs_update_status
&& estatus)
spawn(status_path);
return;
}
/** ConfigureRequest & ConfigureNotify handle events
* \param ev XEvent pointer
/** ConfigureRequesthandle events
*/
void
configureevent(XConfigureRequestEvent *ev)
static void
configureevent(XEvent *e)
{
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc;
Client *c;
/* Check part */
if((c = client_gb_win(ev->window))
|| (c = client_gb_win(ev->window)))
{
CHECK(!(c->flags & TileFlag));
CHECK(!(c->flags & LMaxFlag));
CHECK(!(c->flags & MaxFlag));
CHECK(!(c->flags & FSSFlag));
}
if(((c = client_gb_win(ev->window)) || (c = client_gb_win(ev->window)))
&& (c->flags & (LMaxFlag | MaxFlag | FSSFlag)))
return;
if((c = client_gb_win(ev->window)))
{
@@ -268,8 +316,13 @@ configureevent(XConfigureRequestEvent *ev)
if(ev->value_mask & CWHeight)
c->geo.height = ev->height;
if(c->flags & FreeFlag)
if(c->flags & FreeFlag || !(c->flags & TileFlag))
client_moveresize(c, c->geo, False);
else
{
client_configure(c);
arrange(c->screen, True);
}
}
else
{
@@ -281,41 +334,57 @@ configureevent(XConfigureRequestEvent *ev)
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XConfigureWindow(EVDPY, ev->window, ev->value_mask, &wc);
}
return;
}
/** DestroyNotify handle event
* \param ev XDestroyWindowEvent pointer
*/
void
destroynotify(XDestroyWindowEvent *ev)
static void
destroynotify(XEvent *e)
{
XDestroyWindowEvent *ev = &e->xdestroywindow;
Client *c;
Systray *s;
if((c = client_gb_win(ev->window)))
{
client_unmanage(c);
XSetErrorHandler(errorhandler);
}
else if((s = systray_find(ev->window)))
{
setwinstate(s->win, WithdrawnState);
systray_del(s);
systray_update();
}
return;
}
/** EnterNotify handle event
* \param ev XCrossingEvent pointer
*/
void
enternotify(XCrossingEvent *ev)
static void
enternotify(XEvent *e)
{
XCrossingEvent *ev = &e->xcrossing;
Client *c;
int n;
if((ev->mode != NotifyNormal
|| ev->detail == NotifyInferior)
&& ev->window != ROOT)
if((ev->mode != NotifyNormal || ev->detail == NotifyInferior)
&& ev->window != ROOT)
return;
if(tags[selscreen][seltag[selscreen]].flags & IgnoreEnterFlag)
{
tags[selscreen][seltag[selscreen]].flags &= ~IgnoreEnterFlag;
return;
}
/* Don't handle EnterNotify event if it's about systray */
if(systray_find(ev->window) || ev->window == traywin)
return;
if(conf.focus_fmouse)
@@ -334,25 +403,21 @@ enternotify(XCrossingEvent *ev)
}
/** ExposeEvent handle event
* \param ev XExposeEvent pointer
*/
void
expose(XExposeEvent *ev)
static void
expose(XEvent *e)
{
XExposeEvent *ev = &e->xexpose;
Client *c;
int i, sc;
BarWindow *bw;
/* InfoBar member */
for(sc = 0; sc < screen_count(); ++sc)
{
if(ev->window == infobar[sc].bar->win)
barwin_refresh(infobar[sc].bar);
if(ev->window == infobar[sc].layout_button->win)
barwin_refresh(infobar[sc].layout_button);
for(i = 1; i < conf.ntag[sc] + 1; ++i)
if(ev->window == infobar[sc].tags[i]->win)
barwin_refresh(infobar[sc].tags[i]);
}
/* BarWindows */
SLIST_FOREACH(bw, &bwhead, next)
if(ev->window == bw->win)
{
barwin_refresh(bw);
break;
}
/* Client frame */
if((c = client_gb_titlebar(ev->window)))
@@ -362,49 +427,26 @@ expose(XExposeEvent *ev)
}
/** FocusChange handle event
* \param ev XFocusChangeEvent pointer
* \return
*/
void
focusin(XFocusChangeEvent *ev)
static void
focusin(XEvent *e)
{
if(sel && ev->window != sel->win)
if(sel && e->xfocus.window != sel->win)
client_focus(sel);
return;
}
/** Key grabbing function
*/
void
grabkeys(void)
{
uint i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, ROOT);
for(i = 0; i < conf.nkeybind; ++i)
{
code = XKeysymToKeycode(dpy, keys[i].keysym);
XGrabKey(dpy, code, keys[i].mod, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, keys[i].mod | LockMask | numlockmask, ROOT, True, GrabModeAsync, GrabModeAsync);
}
return;
}
/** KeyPress handle event
* \param ev XKeyPressedEvent pointer
*/
void
keypress(XKeyPressedEvent *ev)
static void
keypress(XEvent *e)
{
uint i;
XKeyPressedEvent *ev = &e->xkey;
KeySym keysym;
int i;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
keysym = XKeycodeToKeysym(EVDPY, (KeyCode)ev->keycode, 0);
for(i = 0; i < conf.nkeybind; ++i)
if(keysym == keys[i].keysym
&& (keys[i].mod & ~(numlockmask | LockMask))
@@ -415,81 +457,150 @@ keypress(XKeyPressedEvent *ev)
return;
}
/** MapNotify handle event
* \param ev XMappingEvent pointer
/** MappingNotify handle event
*/
void
mappingnotify(XMappingEvent *ev)
static void
mappingnotify(XEvent *e)
{
XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
grabkeys();
return;
}
/** MapRequest handle event
* \param ev XMapRequestEvent pointer
*/
void
maprequest(XMapRequestEvent *ev)
/** MapNotify handle event
*/
static void
mapnotify(XEvent *e)
{
XWindowAttributes at;
XMapEvent *ev = &e->xmap;
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);
if(!(c = client_gb_win(ev->window)))
if((s = systray_find(ev->window)))
{
ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
systray_update();
}
else if(!client_gb_win(ev->window))
client_manage(ev->window, &at, True);
return;
}
/** PropertyNotify handle event
* \param ev XPropertyEvent pointer
*/
void
propertynotify(XPropertyEvent *ev)
static void
propertynotify(XEvent *e)
{
XPropertyEvent *ev = &e->xproperty;
Client *c;
Systray *s;
Window trans;
XWMHints *h;
if(ev->state == PropertyDelete)
return;
if((s = systray_find(ev->window)))
{
systray_state(s);
systray_update();
}
if((c = client_gb_win(ev->window)))
{
switch(ev->atom)
{
default: break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans);
if((c->flags & TileFlag || c->flags & MaxFlag))
if(((c->flags & HintFlag && (client_gb_win(trans) != NULL)))
|| (!(c->flags & HintFlag && (client_gb_win(trans) != NULL))))
arrange(c->screen, True);
XGetTransientForHint(EVDPY, c->win, &trans);
if((c->flags & (TileFlag | MaxFlag)) && client_gb_win(trans))
arrange(c->screen, True);
break;
case XA_WM_NORMAL_HINTS:
client_size_hints(c);
break;
case XA_WM_HINTS:
if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
{
client_urgent(c, True);
XFree(h);
}
break;
case XA_WM_NAME:
client_get_name(c);
break;
default:
if(ev->atom == net_atom[net_wm_name])
client_get_name(c);
break;
}
if(ev->atom == net_atom[net_wm_name])
client_get_name(c);
}
return;
}
/** UnmapNotify handle event
* \param ev XUnmapEvent pointer
/** XReparentEvent handle event
*/
void
unmapnotify(XUnmapEvent *ev)
static void
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;
Systray *s;
if((c = client_gb_win(ev->window))
&& ev->send_event
@@ -499,76 +610,107 @@ unmapnotify(XUnmapEvent *ev)
XSetErrorHandler(errorhandler);
}
return;
}
/** 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)
if((s = systray_find(ev->window)))
{
case ButtonPress: buttonpress(&ev.xbutton); break;
case ClientMessage: clientmessageevent(&ev.xclient); break;
case ConfigureRequest: configureevent(&ev.xconfigurerequest); break;
case DestroyNotify: destroynotify(&ev.xdestroywindow); break;
case EnterNotify: enternotify(&ev.xcrossing); break;
case Expose: expose(&ev.xexpose); break;
case FocusIn: focusin(&ev.xfocus); break;
case KeyPress: keypress(&ev.xkey); break;
case MapRequest: maprequest(&ev.xmaprequest); break;
case MappingNotify: mappingnotify(&ev.xmapping); break;
case PropertyNotify: propertynotify(&ev.xproperty); break;
case UnmapNotify: unmapnotify(&ev.xunmap); break;
default:
#ifdef HAVE_XRANDR
/* Check Xrandr event */
if(ev.type == xrandr_event)
{
/* Update xrandr configuration */
XRRUpdateConfiguration(&ev);
/* Reload WMFS to update the screen(s) geometry changement */
quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execlp(argv_global, argv_global, NULL);
}
#endif /* HAVE_XRANDR */
break;
systray_del(s);
systray_update();
}
wait((int[]){0});
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
void
xrandrevent(XEvent *e)
{
/* Update xrandr configuration */
if(!XRRUpdateConfiguration(e))
return;
/* Reload WMFS to update the screen(s) geometry changement */
quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execvp(argv_global, all_argv);
}
#endif /* HAVE_XRANDR */
/** Key grabbing function
*/
void
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;
}
/** Make event handle function pointer array
*/
void
event_make_array(void)
{
int i = MAX_EV;
event_handle = xcalloc(MAX_EV, sizeof(event_handle));
/* Fill array with non-used function (do nothing) */
while(i--)
event_handle[i] = reparentnotify;
event_handle[ButtonPress] = buttonpress;
event_handle[ClientMessage] = clientmessageevent;
event_handle[ConfigureRequest] = configureevent;
event_handle[DestroyNotify] = destroynotify;
event_handle[EnterNotify] = enternotify;
event_handle[Expose] = expose;
event_handle[FocusIn] = focusin;
event_handle[KeyPress] = keypress;
event_handle[MapNotify] = mapnotify;
event_handle[MapRequest] = maprequest;
event_handle[MappingNotify] = mappingnotify;
event_handle[MotionNotify] = motionnotify;
event_handle[PropertyNotify] = propertynotify;
event_handle[ReparentNotify] = reparentnotify;
event_handle[SelectionClear] = selectionclearevent;
event_handle[UnmapNotify] = unmapnotify;
#ifdef HAVE_XRANDR
event_handle[xrandr_event + RRScreenChangeNotify] = xrandrevent;
#endif /* HAVE_XRANDR */
return;
}

View File

@@ -42,12 +42,15 @@
void
ewmh_init_hints(void)
{
int i = 1, j, showing_desk = 0;
char root_name[] = WMFS_VERSION;
int i = 1, s, j, showing_desk = 0;
char rootn[] = "wmfs-"WMFS_VERSION;
char class[] = "wmfs", st[64];
long pid = (long)getpid();
char systray_atom[48];
net_atom = emalloc(net_last + screen_count(), sizeof(Atom));
s = screen_count();
net_atom = xcalloc(net_last + s, sizeof(Atom));
/* EWMH hints */
net_atom[net_supported] = ATOM("_NET_SUPPORTED");
@@ -57,7 +60,6 @@ ewmh_init_hints(void)
net_atom[net_current_desktop] = ATOM("_NET_CURRENT_DESKTOP");
net_atom[net_desktop_names] = ATOM("_NET_DESKTOP_NAMES");
net_atom[net_desktop_geometry] = ATOM("_NET_DESKTOP_GEOMETRY");
net_atom[net_workarea] = ATOM("_NET_WORKAREA");
net_atom[net_active_window] = ATOM("_NET_ACTIVE_WINDOW");
net_atom[net_close_window] = ATOM("_NET_CLOSE_WINDOW");
net_atom[net_wm_name] = ATOM("_NET_WM_NAME");
@@ -67,6 +69,7 @@ ewmh_init_hints(void)
net_atom[net_wm_icon_name] = ATOM("_NET_WM_ICON_NAME");
net_atom[net_wm_window_type] = ATOM("_NET_WM_WINDOW_TYPE");
net_atom[net_supporting_wm_check] = ATOM("_NET_SUPPORTING_WM_CHECK");
net_atom[net_wm_window_opacity] = ATOM("_NET_WM_WINDOW_OPACITY");
net_atom[net_wm_window_type_normal] = ATOM("_NET_WM_WINDOW_TYPE_NORMAL");
net_atom[net_wm_window_type_dock] = ATOM("_NET_WM_WINDOW_TYPE_DOCK");
net_atom[net_wm_window_type_splash] = ATOM("_NET_WM_WINDOW_TYPE_SPLASH");
@@ -74,13 +77,24 @@ ewmh_init_hints(void)
net_atom[net_wm_icon] = ATOM("_NET_WM_ICON");
net_atom[net_wm_state] = ATOM("_NET_WM_STATE");
net_atom[net_wm_state_fullscreen] = ATOM("_NET_WM_STATE_FULLSCREEN");
net_atom[net_wm_state_sticky] = ATOM("_NET_WM_STATE_STICKY");
net_atom[net_wm_state_demands_attention] = ATOM("_NET_WM_STATE_DEMANDS_ATTENTION");
net_atom[net_wm_system_tray_opcode] = ATOM("_NET_SYSTEM_TRAY_OPCODE");
net_atom[net_system_tray_message_data] = ATOM("_NET_SYSTEM_TRAY_MESSAGE_DATA");
net_atom[net_system_tray_visual] = ATOM("_NET_SYSTEM_TRAY_VISUAL");
snprintf(systray_atom, sizeof(systray_atom), "_NET_SYSTEM_TRAY_S%d", 0/*SCREEN*/);
net_atom[net_system_tray_s] = ATOM(systray_atom);
net_atom[net_system_tray_orientation] = ATOM("_NET_SYSTEM_TRAY_ORIENTATION");
net_atom[xembed] = ATOM("_XEMBED");
net_atom[xembedinfo] = ATOM("_XEMBED_INFO");
net_atom[manager] = ATOM("MANAGER");
net_atom[utf8_string] = ATOM("UTF8_STRING");
/* WMFS hints */
net_atom[wmfs_running] = ATOM("_WMFS_RUNNING");
net_atom[wmfs_update_hints] = ATOM("_WMFS_UPDATE_HINTS");
net_atom[wmfs_update_status] = ATOM("_WMFS_UPDATE_STATUS");
net_atom[wmfs_set_screen] = ATOM("_WMFS_SET_SCREEN");
net_atom[wmfs_screen_count] = ATOM("_WMFS_SCREEN_COUNT");
net_atom[wmfs_current_tag] = ATOM("_WMFS_CURRENT_TAG");
@@ -91,16 +105,17 @@ ewmh_init_hints(void)
net_atom[wmfs_nmaster] = ATOM("_WMFS_NMASTER");
net_atom[wmfs_function] = ATOM("_WMFS_FUNCTION");
net_atom[wmfs_cmd] = ATOM("_WMFS_CMD");
net_atom[wmfs_font] = ATOM("_WMFS_FONT");
/* Multi atom _WMFS_STATUSTEXT_<screennum> */
for(j = 0; j < screen_count(); ++j)
for(j = 0; j < s; ++j)
{
sprintf(st, "_WMFS_STATUSTEXT_%d", j);
net_atom[wmfs_statustext + j] = ATOM(st);
}
XChangeProperty(dpy, ROOT, net_atom[net_supported], XA_ATOM, 32,
PropModeReplace, (uchar*)net_atom, net_last + screen_count());
PropModeReplace, (uchar*)net_atom, net_last + s);
XChangeProperty(dpy, ROOT, net_atom[wmfs_running], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&i, 1);
@@ -110,7 +125,7 @@ ewmh_init_hints(void)
PropModeReplace, (uchar*)&ROOT, 1);
XChangeProperty(dpy, ROOT, net_atom[net_wm_name], net_atom[utf8_string], 8,
PropModeReplace, (uchar*)&root_name, strlen(root_name));
PropModeReplace, (uchar*)&rootn, strlen(rootn));
XChangeProperty(dpy, ROOT, ATOM("WM_CLASS"), XA_STRING, 8,
PropModeReplace, (uchar*)&class, strlen(class));
@@ -126,6 +141,54 @@ ewmh_init_hints(void)
return;
}
/** Send ewmh message
*/
void
ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4)
{
XClientMessageEvent e;
e.type = ClientMessage;
e.message_type = ATOM(atom);
e.window = w;
e.format = 32;
e.data.l[0] = d0;
e.data.l[1] = d1;
e.data.l[2] = d2;
e.data.l[3] = d3;
e.data.l[4] = d4;
XSendEvent(dpy, d, False, StructureNotifyMask, (XEvent*)&e);
XSync(dpy, False);
return;
}
/** Get xembed state
*/
long
ewmh_get_xembed_state(Window win)
{
Atom rf;
int f;
ulong n, il;
long ret = 0;
uchar *data = NULL;
if(XGetWindowProperty(dpy, win, net_atom[xembedinfo], 0L, 2, False,
net_atom[xembedinfo], &rf, &f, &n, &il, &data) != Success)
return 0;
if(rf == net_atom[xembedinfo] && n == 2)
ret = (long)data[1];
if(n && data)
XFree(data);
return ret;
}
/** Get the number of desktop (tag)
*/
void
@@ -148,13 +211,11 @@ void
ewmh_update_current_tag_prop(void)
{
int t;
char *s = NULL;
char s[8] = { 0 };
screen_get_sel();
t = seltag[selscreen] - 1;
s = emalloc(8, sizeof(char));
/* Get current desktop (tag) */
XChangeProperty(dpy, ROOT, net_atom[net_current_desktop], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&t, 1);
@@ -179,8 +240,6 @@ ewmh_update_current_tag_prop(void)
PropModeReplace, (uchar*)tags[selscreen][seltag[selscreen]].layout.symbol,
strlen(tags[selscreen][seltag[selscreen]].layout.symbol));
free(s);
return;
}
@@ -191,18 +250,21 @@ ewmh_get_client_list(void)
{
Window *list;
Client *c;
int win_n;
int win_n = 0;
for(win_n = 0, c = clients; c; c = c->next, ++win_n);
list = emalloc(win_n, sizeof(Window));
SLIST_FOREACH(c, &clients, next)
++win_n;
for(win_n = 0, c = clients; c; c = c->next, ++win_n)
list[win_n] = c->win;
list = xcalloc(win_n, sizeof(Window));
win_n = 0;
SLIST_FOREACH(c, &clients, next)
list[win_n++] = c->win;
XChangeProperty(dpy, ROOT, net_atom[net_client_list], XA_WINDOW, 32,
PropModeReplace, (uchar *)list, win_n);
free(list);
XFree(list);
return;
}
@@ -213,15 +275,17 @@ void
ewmh_get_desktop_names(void)
{
char *str = NULL;
int s, i, len = 0, pos = 0;
int S, s, i = 0, len = 0, pos = 0;
for(s = 0 ; s < screen_count(); ++s)
S = screen_count();
for(s = 0 ; s < S; ++s)
for(i = 1; i < conf.ntag[s] + 1; ++i)
len += strlen(tags[s][i].name);
str = emalloc(len + i + 1, sizeof(char*));
str = xcalloc(len + i + 1, sizeof(char*));
for(s = 0; s < screen_count(); ++s)
for(s = 0; s < S; ++s)
for(i = 1; i < conf.ntag[s] + 1; ++i, ++pos)
{
strncpy(str + pos, tags[s][i].name, strlen(tags[s][i].name));
@@ -258,54 +322,25 @@ ewmh_set_desktop_geometry(void)
return;
}
/** Manage _NET_WORKAREA
*/
void
ewmh_set_workarea(void)
{
long *data;
int i, j, tag_c = 0, pos = 0;
for(i = 0; i < screen_count(); ++i)
tag_c += conf.ntag[i];
data = emalloc(tag_c * 4, sizeof(long));
for(i = 0; i < screen_count(); ++i)
for(j = 0; j < conf.ntag[i]; ++j)
{
data[pos++] = spgeo[i].x;
data[pos++] = spgeo[i].y;
data[pos++] = spgeo[i].width;
data[pos++] = spgeo[i].height;
}
XChangeProperty(dpy, ROOT, net_atom[net_workarea], XA_CARDINAL, 32,
PropModeReplace, (uchar*)data, 4 * tag_c);
free(data);
return;
}
/** Manage _NET_WM_STATE_* ewmh
*/
void
ewmh_manage_net_wm_state(long data_l[], Client *c)
{
/* Manage _NET_WM_STATE_FULLSCREEN */
if(data_l[1] == net_atom[net_wm_state_fullscreen])
if(data_l[1] == (long)net_atom[net_wm_state_fullscreen])
{
if(data_l[0] == _NET_WM_STATE_ADD && !(c->flags & FSSFlag))
{
c->screen = screen_get_with_geo(c->geo.x, c->geo.y);
client_unmap(c);
c->flags &= ~UnmapFlag;
XMapWindow(dpy, c->win);
XReparentWindow(dpy, c->win, ROOT, spgeo[c->screen].x, spgeo[c->screen].y);
XResizeWindow(dpy, c->win,
spgeo[c->screen].width,
spgeo[c->screen].height);
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32,
PropModeReplace, (uchar *)&net_atom[net_wm_state_fullscreen], 1);
c->tmp_geo = c->geo;
@@ -316,20 +351,29 @@ ewmh_manage_net_wm_state(long data_l[], Client *c)
client_raise(c);
client_focus(c);
XUnmapWindow(dpy, c->frame);
}
else if(data_l[0] == _NET_WM_STATE_REMOVE && (c->flags & FSSFlag))
{
XChangeProperty(dpy, c->win, net_atom[net_wm_state], XA_ATOM, 32, PropModeReplace, (uchar *)0, 0);
c->flags &= ~(FSSFlag | MaxFlag);
client_map(c);
XReparentWindow(dpy, c->win, c->frame, BORDH, TBARH);
client_moveresize(c, c->tmp_geo, False);
}
}
/* Manage _NET_WM_STATE_STICKY */
else if(data_l[1] == (long)net_atom[net_wm_state_sticky])
{
/* == client_ignore_tag */
c->tag = MAXTAG + 1;
arrange(c->screen, True);
}
/* Manage _NET_WM_STATE_DEMANDS_ATTENTION */
else if(data_l[1] == net_atom[net_wm_state_demands_attention])
else if(data_l[1] == (long)net_atom[net_wm_state_demands_attention])
{
if(data_l[0] == _NET_WM_STATE_ADD)
client_focus(c);
client_urgent(c, True);
if(data_l[0] == _NET_WM_STATE_REMOVE)
if(c == sel)
client_focus(NULL);
@@ -346,9 +390,10 @@ void
ewmh_manage_window_type(Client *c)
{
Atom *atom, rf;
int i, f;
ulong n, il;
int f;
ulong n, il, i;
uchar *data = NULL;
long ldata[5] = { 0 };
if(XGetWindowProperty(dpy, c->win, net_atom[net_wm_window_type], 0L, 0x7FFFFFFFL,
False, XA_ATOM, &rf, &f, &n, &il, &data) == Success && n)
@@ -371,23 +416,36 @@ ewmh_manage_window_type(Client *c)
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
XRaiseWindow(dpy, c->win);
/* This window will not be managed anymore,
* so let's detach it. */
client_detach(c);
c->flags |= DockFlag;
}
/* MANAGE _NET_WM_WINDOW_TYPE_DIALOG */
else if(atom[i] == net_atom[net_wm_window_type_dialog])
{
c->flags |= FreeFlag;
c->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(sel, sel->ogeo, True);
client_moveresize(c, c->ogeo, True);
client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
layout_func(selscreen, seltag[selscreen]);
}
}
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;
}

View File

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

View File

@@ -1,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,214 +32,411 @@
#include "wmfs.h"
/** Init the Infobar
#define SPLIT_IND_S (3 + conf.border.layout)
/** Init InfoBar elements
*/
void
infobar_init(void)
static void
infobar_init_element(InfoBar *i)
{
int sc, i, j;
int j = 0, k, n = 0;
InfobarElem *e, *prev = NULL;
Geo pg = { -PAD, 0, 0, 0 };
if(!infobar)
infobar = emalloc(screen_count(), sizeof(InfoBar));
STAILQ_INIT(&i->elemhead);
for(sc = 0; sc < screen_count(); ++sc)
for(; n < (int)strlen(i->elemorder); ++n)
{
j = 0;
infobar[sc].geo.height = INFOBARH;
e = zcalloc(sizeof(InfobarElem));
switch(tags[sc][seltag[sc]].barpos)
/* Previous element geo */
if(prev)
pg = prev->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
e->geo.height = i->geo.height;
switch(i->elemorder[n])
{
case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH;
infobar[sc].geo.y = -(infobar[sc].geo.height) * 2;
break;
case IB_Bottom:
sgeo[sc].y = TBARH;
infobar[sc].geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
break;
default:
case IB_Top:
sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
infobar[sc].geo.y = spgeo[sc].y;
break;
/* Tags element */
case 't':
e->type = ElemTag;
e->geo.width = PAD; /* Will change */
if(!i->tags_board)
{
i->tags_board = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.bar, conf.colors.text,
False, False, False);
/* Create tags window */
for(k = 1; k < conf.ntag[i->screen] + 1; ++k)
{
i->tags[k] = barwin_create(i->tags_board->win,
j, 0,
textw(tags[i->screen][k].name) + PAD,
i->geo.height,
conf.colors.bar, conf.colors.text,
False, False, conf.border.tag);
j += textw(tags[i->screen][k].name) + PAD;
barwin_map_subwin(i->tags[k]);
}
}
barwin_resize(i->tags_board, (e->geo.width = j), i->geo.height);
barwin_map(i->tags_board);
barwin_map_subwin(i->tags_board);
break;
/* Layout button element */
case 'l':
e->type = ElemLayout;
e->geo.width = (conf.layout_button_width > 0
? (uint)conf.layout_button_width
: textw(tags[i->screen][seltag[i->screen]].layout.symbol) + PAD);
if(!i->layout_button)
i->layout_button = barwin_create(i->bar->win,
e->geo.x,
e->geo.y,
e->geo.width,
e->geo.height,
conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout);
barwin_map(i->layout_button);
if(conf.border.layout)
barwin_map_subwin(i->layout_button);
break;
/* Selbar element */
case 's':
e->type = ElemSelbar;
i->selbar_geo = e->geo;
break;
}
/* Create infobar barwindow */
infobar[sc].bar = barwin_create(ROOT, sgeo[sc].x - BORDH, infobar[sc].geo.y,
sgeo[sc].width, infobar[sc].geo.height,
conf.colors.bar, conf.colors.text, False, False, conf.border.bar);
STAILQ_INSERT_TAIL(&i->elemhead, e, next);
/* Create tags window */
for(i = 1; i < conf.ntag[sc] + 1; ++i)
{
infobar[sc].tags[i] = barwin_create(infobar[sc].bar->win, j, 0,
textw(tags[sc][i].name) + PAD,
infobar[sc].geo.height,
conf.colors.bar, conf.colors.text, False, False, conf.border.tag);
j += textw(tags[sc][i].name) + PAD;
barwin_map_subwin(infobar[sc].tags[i]);
}
/* Create layout switch barwindow */
infobar[sc].layout_button = barwin_create(infobar[sc].bar->win, j + PAD / 2, 0,
textw(tags[sc][seltag[sc]].layout.symbol) + PAD,
infobar[sc].geo.height,
conf.colors.layout_bg, conf.colors.layout_fg,
False, False, conf.border.layout);
/* Map/Refresh all */
barwin_map(infobar[sc].bar);
barwin_map_subwin(infobar[sc].bar);
if(conf.border.layout)
barwin_map_subwin(infobar[sc].layout_button);
barwin_refresh_color(infobar[sc].bar);
barwin_refresh(infobar[sc].bar);
/* Default statustext is set here */
for(i = 0; i < screen_count(); ++i)
infobar[i].statustext = _strdup(WMFS_VERSION);
infobar_draw(sc);
prev = e;
e = NULL;
}
return;
}
/** Draw the Infobar
*\param sc Screen number
/** Init the InfoBar
*/
void
infobar_draw(int sc)
infobar_init(void)
{
infobar_draw_taglist(sc);
infobar_draw_layout(sc);
barwin_refresh_color(infobar[sc].bar);
infobar_draw_statustext(sc, infobar[sc].statustext);
InfoBar *i;
int s = screen_count(), sc = 0;
if(!infobar)
infobar = xcalloc(s, sizeof(InfoBar));
for(; sc < s; ++sc)
{
i = &infobar[sc];
i->geo.height = INFOBARH;
i->screen = sc;
i->elemorder = conf.bars.element_order;
switch(tags[sc][seltag[sc]].barpos)
{
case IB_Hide:
sgeo[sc].y = spgeo[sc].y + TBARH;
sgeo[sc].height += INFOBARH;
i->geo.y = (-(i->geo.height) << 2);
break;
case IB_Bottom:
sgeo[sc].y = TBARH;
i->geo.y = spgeo[sc].y + sgeo[sc].height + TBARH;
break;
default:
case IB_Top:
sgeo[sc].y = spgeo[sc].y + INFOBARH + TBARH;
i->geo.y = spgeo[sc].y;
break;
}
/* Create infobar barwindow */
i->bar = barwin_create(ROOT,
sgeo[sc].x - BORDH,
i->geo.y,
sgeo[sc].width,
i->geo.height,
conf.colors.bar, conf.colors.text,
False, False, conf.border.bar);
barwin_map(i->bar);
barwin_map_subwin(i->bar);
barwin_refresh_color(i->bar);
barwin_refresh(i->bar);
/* Init elements */
infobar_init_element(i);
/* Default statustext is set here */
i->statustext = xstrdup("wmfs"WMFS_VERSION);
infobar_draw(i);
}
return;
}
static void
infobar_arrange_element(InfoBar *i)
{
Geo pg = { -PAD, 0, 0, 0 };
InfobarElem *e, *pe = NULL;
STAILQ_FOREACH(e, &i->elemhead, next)
{
if(pe)
pg = pe->geo;
e->geo.x = pg.x + pg.width + PAD;
e->geo.y = 0;
if(e->type != ElemSelbar)
barwin_move((e->type == ElemTag ? i->tags_board : i->layout_button), e->geo.x, e->geo.y);
pe = e;
}
return;
}
/** Draw the layout button in the InfoBar
*\param sc Screen number
*\param i InfoBar pointer
*/
void
infobar_draw_layout(int sc)
infobar_draw_layout(InfoBar *i)
{
barwin_resize(infobar[sc].layout_button, textw(tags[sc][seltag[sc]].layout.symbol) + PAD, infobar[sc].geo.height);
barwin_refresh_color(infobar[sc].layout_button);
if(tags[sc][seltag[sc]].layout.symbol)
barwin_draw_text(infobar[sc].layout_button, PAD / 2, FHINFOBAR, tags[sc][seltag[sc]].layout.symbol);
InfobarElem *e;
int s = i->screen;
/* Check if there is element in string element list */
if(!strchr(i->elemorder, 'l'))
return;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemLayout)
break;
e->geo.width = (conf.layout_button_width >= 1)
? conf.layout_button_width
: (int)(textw(tags[s][seltag[s]].layout.symbol) + PAD);
barwin_resize(i->layout_button, e->geo.width, e->geo.height);
barwin_refresh_color(i->layout_button);
/* Split mode indicator; little rectangle at bottom-right */
if(tags[s][seltag[s]].flags & SplitFlag)
draw_rectangle(i->layout_button->dr,
e->geo.width - SPLIT_IND_S,
e->geo.height - SPLIT_IND_S,
SPLIT_IND_S, SPLIT_IND_S,
getcolor(i->layout_button->fg));
if(tags[s][seltag[s]].layout.symbol)
barwin_draw_text(i->layout_button, (PAD >> 1), FHINFOBAR, tags[s][seltag[s]].layout.symbol);
return;
}
/** Draw Infobar barwin (selbar / statustext)
*\param i Infobar pointer
*/
void
_infobar_draw(InfoBar *i)
{
barwin_refresh_color(i->bar);
infobar_draw_selbar(i);
statustext_handle(i);
barwin_refresh(i->bar);
infobar_arrange_element(i);
return;
}
/** Draw the InfoBar
*\param i InfoBar pointer
*/
void
infobar_draw(InfoBar *i)
{
infobar_draw_taglist(i);
infobar_draw_layout(i);
_infobar_draw(i);
return;
}
/** Draw Selbar (selected client title bar in infobar
*\param sc Screen Number
*/
void
infobar_draw_selbar(InfoBar *i)
{
InfobarElem *e;
char *str = NULL;
int sc = i->screen;
bool f = False;
if(!conf.bars.selbar)
return;
if(!strchr(i->elemorder, 's'))
return;
if(!sel || (sel && sel->screen != sc))
return;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemSelbar)
break;
str = sel->title;
/* Truncate string if too long */
if(conf.selbar.maxlength >= 0 && sel && sel->title)
{
str = NULL;
str = xcalloc(conf.selbar.maxlength + 4, sizeof(char));
strncpy(str, sel->title, conf.selbar.maxlength);
if(strlen(sel->title) > (size_t)conf.selbar.maxlength)
strcat(str, "...");
f = True;
}
XSetForeground(dpy, gc, conf.selbar.bg);
XFillRectangle(dpy, i->bar->dr, gc,
e->geo.x,
e->geo.y,
(e->geo.width = textw(str) + PAD),
e->geo.height);
draw_text(i->bar->dr, e->geo.x, FHINFOBAR, conf.selbar.fg, str);
if(f)
free(str);
i->selbar_geo = e->geo;
return;
}
/** Draw the taglist in the InfoBar
*\param sc Screen number
*\param i InfoBar pointer
*/
void
infobar_draw_taglist(int sc)
infobar_draw_taglist(InfoBar *i)
{
int i;
InfobarElem *e;
Client *c;
int j = 1, x = 0, sc = i->screen;
uint occupied = 0;
for(i = 1; i < conf.ntag[sc] + 1; ++i)
if(!strchr(i->elemorder, 't'))
return;
STAILQ_FOREACH(e, &i->elemhead, next)
if(e->type == ElemTag)
break;
SLIST_FOREACH(c, &clients, next)
if(c->screen == sc)
occupied |= TagFlag(c->tag);
for(; j < conf.ntag[sc] + 1; ++j)
{
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)
/* Autohide tag feature */
if(conf.tagautohide)
{
if(c->screen == sc)
if(!(occupied & TagFlag(j)) && j != seltag[sc])
{
infobar[sc].tags[c->tag]->bg = ((c->tag == seltag[sc]) ? conf.colors.tagselbg : conf.colors.tag_occupied_bg);
barwin_refresh_color(infobar[sc].tags[i]);
barwin_unmap(i->tags[j]);
continue;
}
barwin_map(i->tags[j]);
barwin_move(i->tags[j], x, 0);
barwin_resize(i->tags_board, (e->geo.width = (x += i->tags[j]->geo.width)), e->geo.height);
}
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;
}
/** Draw text in the statustext and parse color format
*\param sc Screen
*\param str String
/** Update taglist geo
*\param i InfoBar pointer
*/
void
infobar_draw_statustext(int sc, char *str)
infobar_update_taglist(InfoBar *i)
{
char *buf = NULL;
char *strwc = NULL;
char col[8] = { 0 };
int i, j, c, k = 0;
char *lastst;
int t, j, sc = i->screen;
/* If the str == the current statustext, return (not needed) */
if(!str)
return;
barwin_refresh_color(infobar[sc].bar);
/* save last status text address (for free at the end) */
lastst = infobar[sc].statustext;
infobar[sc].statustext = _strdup(str);
strwc = _strdup(str);
/* Count how many color block there is and make a string without color block (\#....\)*/
for(i = j = c = 0; i < strlen(str); ++i, ++j)
for(t = 1, j = 0; t < conf.ntag[sc] + 1; ++t)
{
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
/* If the tag t does not exist yet (graphically) or need full update */
if(!i->tags[t] || i->need_update)
{
++c;
i += 8;
--j;
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;
}
else
strwc[j] = str[i];
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);
}
strwc[j] = '\0';
/* Draw a first time the statustext for non colorized text */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(strwc),
FHINFOBAR, infobar[sc].bar->fg, 0, strwc);
/* Draw text with its color */
if(c)
{
buf = _strdup(strwc);
for(i = k; i < strlen(str); ++i, ++k)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{
/* Store current color in col[] */
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
buf += k;
/* Draw a rectangle with the bar color to draw the text properly */
draw_rectangle(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
0, INFOBARH - (sgeo[sc].width - SHADH) - textw(buf),
INFOBARH, conf.colors.bar);
/* Draw text with its color */
draw_text(infobar[sc].bar->dr, (sgeo[sc].width - SHADH) - textw(buf),
FHINFOBAR, col, 0, buf);
buf = _strdup(strwc);
++i;
}
free(buf);
}
barwin_refresh(infobar[sc].bar);
free(lastst);
free(strwc);
i->need_update = False;
return;
}
@@ -249,19 +446,33 @@ infobar_draw_statustext(int sc, char *str)
void
infobar_destroy(void)
{
InfobarElem *e;
int sc, i;
for(sc = 0; sc < screen_count(); ++sc)
{
barwin_delete(infobar[sc].layout_button);
barwin_delete_subwin(infobar[sc].layout_button);
for(i = 1; i < conf.ntag[sc] + 1; ++i)
{
barwin_delete_subwin(infobar[sc].tags[i]);
barwin_delete(infobar[sc].tags[i]);
}
barwin_delete_subwin(infobar[sc].tags_board);
barwin_delete(infobar[sc].tags_board);
barwin_delete_subwin(infobar[sc].bar);
barwin_delete(infobar[sc].bar);
/* Free elements */
while(!STAILQ_EMPTY(&infobar[sc].elemhead))
{
e = STAILQ_FIRST(&infobar[sc].elemhead);
STAILQ_REMOVE_HEAD(&infobar[sc].elemhead, next);
free(e);
}
}
return;
@@ -277,29 +488,27 @@ infobar_set_position(int pos)
switch(pos)
{
case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = -(infobar[selscreen].geo.height) * 2;
break;
case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
break;
default:
case IB_Top:
sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y;
break;
case IB_Hide:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - TBARH;
infobar[selscreen].geo.y = (-(infobar[selscreen].geo.height) << 1);
break;
case IB_Bottom:
sgeo[selscreen].y = spgeo[selscreen].y + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y + sgeo[selscreen].height + TBARH;
break;
default:
case IB_Top:
sgeo[selscreen].y = spgeo[selscreen].y + INFOBARH + TBARH;
sgeo[selscreen].height = spgeo[selscreen].height - INFOBARH - TBARH;
infobar[selscreen].geo.y = spgeo[selscreen].y;
break;
}
tags[selscreen][seltag[selscreen]].barpos = pos;
barwin_move(infobar[selscreen].bar, sgeo[selscreen].x - BORDH, infobar[selscreen].geo.y);
infobar_draw(selscreen);
ewmh_set_workarea();
arrange(selscreen, True);
return;
@@ -311,6 +520,7 @@ infobar_set_position(int pos)
void
uicb_infobar_togglepos(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
infobar_set_position((tags[selscreen][seltag[selscreen]].barpos
@@ -320,3 +530,54 @@ uicb_infobar_togglepos(uicb_t cmd)
return;
}
/** Toggle hide/display infobar
* \param cmd uicb_t type unused
*/
void
uicb_infobar_toggledisplay(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
int new_pos;
new_pos = (tags[selscreen][seltag[selscreen]].barpos
? 0 : (tags[selscreen][seltag[selscreen]].prev_barpos
? tags[selscreen][seltag[selscreen]].prev_barpos : 2));
tags[selscreen][seltag[selscreen]].prev_barpos = tags[selscreen][seltag[selscreen]].barpos;
tags[selscreen][seltag[selscreen]].barpos = new_pos;
infobar_set_position(new_pos);
return;
}
/** Toggle the tag_autohide mode
* \param cmd uicb_t type unused
*/
void
uicb_toggle_tagautohide(uicb_t cmd)
{
int i, x;
(void)cmd;
screen_get_sel();
conf.tagautohide = !conf.tagautohide;
if(!conf.tagautohide)
{
for(i = 1, x = 0; i < conf.ntag[selscreen] + 1; ++i)
{
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

@@ -32,48 +32,90 @@
#include "wmfs.h"
/** Init WMFS
*/
void
init(void)
{
/* First init */
ewmh_init_hints();
init_layout();
init_conf();
init_gc();
init_font();
init_cursor();
init_key();
init_root();
screen_init_geo();
infobar_init();
init_status();
ewmh_update_current_tag_prop();
grabkeys();
return;
}
const func_name_list_t layout_list[] =
{
{"tile", tile },
{"tile_right", tile },
{"tile_left", tile_left },
{"tile_top", tile_top },
{"tile_bottom", tile_bottom },
{"tile_grid", grid_horizontal },
{"tile_grid_horizontal", grid_horizontal },
{"tile_grid_vertical", grid_vertical },
{"grid", grid_horizontal },
{"mirror_vertical", mirror_vertical },
{"tile_mirror_vertical", mirror_vertical },
{"mirror_horizontal", mirror_horizontal },
{"tile_mirror_horizontal", mirror_horizontal },
{"max", maxlayout },
{"maxlayout", maxlayout },
{"freelayout", freelayout },
{"free", freelayout },
{ NULL, NULL }
};
/** Init the font
*/
void
static void
init_font(void)
{
font = XftFontOpenName(dpy, SCREEN, conf.font);
if(!font)
#ifdef HAVE_XFT
if(conf.use_xft)
{
warnx("WMFS Error: Cannot initialize font");
font = XftFontOpenName(dpy, SCREEN, "sans-10");
if(!(font.font = XftFontOpenName(dpy, SCREEN, conf.font)))
{
warnx("WMFS Error: Cannot initialize Xft font");
font.font = XftFontOpenName(dpy, SCREEN, "sans-10");
}
font.de = font.font->descent;
font.as = font.font->ascent;
font.height = font.font->height;
}
else
#endif /* HAVE_XFT */
{
char **misschar, **names, *defstring;
int d;
XFontStruct **xfs = NULL;
/* locale support */
setlocale(LC_CTYPE, "");
if(!conf.font)
conf.font = xstrdup("fixed");
/* Using Font Set */
if(!(font.fontset = XCreateFontSet(dpy, conf.font, &misschar, &d, &defstring)))
{
warnx("Can't load font '%s'", conf.font);
font.fontset = XCreateFontSet(dpy, "fixed", &misschar, &d, &defstring);
}
XExtentsOfFontSet(font.fontset);
XFontsOfFontSet(font.fontset, &xfs, &names);
font.as = xfs[0]->max_bounds.ascent;
font.de = xfs[0]->max_bounds.descent;
font.width = xfs[0]->max_bounds.width;
font.height = font.as + font.de;
if(misschar)
XFreeStringList(misschar);
}
/* Set font in _WMFS_FONT for eventual status tools */
XChangeProperty(dpy, ROOT, net_atom[wmfs_font], net_atom[utf8_string], 8,
PropModeReplace, (uchar*)conf.font, strlen(conf.font));
return;
}
/** Init the graphic context
*/
void
static void
init_gc(void)
{
XGCValues gcv;
@@ -100,7 +142,7 @@ init_gc(void)
/** Init WMFS cursor
*/
void
static void
init_cursor(void)
{
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
@@ -114,7 +156,7 @@ init_cursor(void)
/** Init key modifier
*/
void
static void
init_key(void)
{
int i, j;
@@ -133,7 +175,7 @@ init_key(void)
/** Init root Window
*/
void
static void
init_root(void)
{
XSetWindowAttributes at;
@@ -154,75 +196,31 @@ init_root(void)
return;
}
/** Init layout
*/
/** Init WMFS
*/
void
init_layout(void)
init(void)
{
int i;
/* Init lists heads */
SLIST_INIT(&bwhead);
SLIST_INIT(&smhead);
SLIST_INIT(&clients);
SLIST_INIT(&trayicons);
const func_name_list_t layout_list_tmp[] =
{
{"tile", tile },
{"tile_right", tile },
{"tile_left", tile_left },
{"tile_top", tile_top },
{"tile_bottom", tile_bottom },
{"tile_grid", grid },
{"grid", grid },
{"mirror_vertical", mirror_vertical },
{"tile_mirror_vertical", mirror_vertical },
{"mirror_horizontal", mirror_horizontal },
{"tile_mirror_horizontal", mirror_horizontal },
{"layer", layer },
{"max", maxlayout },
{"maxlayout", maxlayout },
{"freelayout", freelayout },
{"free", freelayout }
};
layout_list = emalloc(LEN(layout_list_tmp), sizeof(func_name_list_t));
memset(layout_list, 0, LEN(layout_list_tmp));
for(i = 0; i < LEN(layout_list_tmp); ++i)
layout_list[i] = layout_list_tmp[i];
return;
}
/** Init statustext shell script
*/
void
init_status(void)
{
int fd;
struct stat st;
status_path = emalloc(strlen(getenv("HOME")) + strlen(DEF_STATUS) + 2, sizeof(char));
sprintf(status_path, "%s/"DEF_STATUS, getenv("HOME"));
if(!(fd = open(status_path, O_RDONLY))
|| !fopen(status_path, "r"))
{
free(status_path);
estatus = False;
return;
}
stat(status_path, &st);
if(st.st_size && st.st_mode & S_IXUSR)
{
estatus = True;
system(status_path);
}
else
warnx("status.sh file present in wmfs directory can't be executed, try 'chmod +x %s'.",
status_path);
close(fd);
/* 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();
ewmh_update_current_tag_prop();
grabkeys();
return;
}

View File

@@ -30,178 +30,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* conforming to glib use _GNU_SOURCE for asprintf declaration */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "wmfs.h"
static char *complete_on_command(char*, size_t);
static char *complete_on_files(char*, size_t);
void
launcher_execute(Launcher launcher)
{
BarWindow *bw;
Bool found;
Bool lastwastab = False;
Bool my_guitar_gently_wheeps = True;
char tmp[32] = { 0 };
char buf[512] = { 0 };
char tmpbuf[512] = { 0 };
char *complete;
int pos = 0, x;
int tabhits = 0;
KeySym ks;
XEvent ev;
screen_get_sel();
x = (infobar[selscreen].layout_button->geo.x
+ textw(tags[selscreen][seltag[selscreen]].layout.symbol) + PAD);
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
bw = barwin_create(infobar[selscreen].bar->win, x, 1,
infobar[selscreen].bar->geo.width - x - 1,
infobar[selscreen].bar->geo.height - 2,
infobar[selscreen].bar->bg,
infobar[selscreen].bar->fg,
False, False, conf.border.bar);
barwin_map(bw);
barwin_refresh_color(bw);
/* First draw of the cursor */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc, textw(launcher.prompt) + textw(" "),
2, textw(launcher.prompt) + textw(" "), INFOBARH - 4);
barwin_refresh(bw);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
while(my_guitar_gently_wheeps)
{
if(ev.type == KeyPress)
{
XLookupString(&ev.xkey, tmp, sizeof(tmp), &ks, 0);
/* Check Ctrl-c / Ctrl-d */
if(ev.xkey.state & ControlMask)
if(ks == XK_c || ks == XK_d)
ks = XK_Escape;
/* Check if there is a keypad */
if(IsKeypadKey(ks) && ks == XK_KP_Enter)
ks = XK_Return;
switch(ks)
{
case XK_Return:
spawn("%s %s", launcher.command, buf);
my_guitar_gently_wheeps = 0;
break;
case XK_Escape:
my_guitar_gently_wheeps = 0;
break;
case XK_Tab:
/*
* completion
* if there is not space in buffer we
* complete the command using complete_on_command.
* Else we try to complete on filename using
* complete_on_files.
*/
buf[pos] = '\0';
if (lastwastab)
tabhits++;
else
{
tabhits = 1;
strcpy(tmpbuf, buf);
}
if (pos)
{
if (strchr(tmpbuf, ' '))
complete = complete_on_files(tmpbuf, tabhits);
else
complete = complete_on_command(tmpbuf, tabhits);
if (complete)
{
strcpy(buf, tmpbuf);
strncat(buf, complete, sizeof(buf));
found = True;
free(complete);
}
}
lastwastab = True;
/* start a new round of tabbing */
if (!found)
tabhits = 0;
pos = strlen(buf);
break;
case XK_BackSpace:
lastwastab = False;
if(pos)
buf[--pos] = 0;
break;
default:
lastwastab = False;
strncat(buf, tmp, sizeof(buf));
++pos;
break;
}
barwin_refresh_color(bw);
/* Update cursor position */
XSetForeground(dpy, gc, getcolor(infobar[selscreen].bar->fg));
XDrawLine(dpy, bw->dr, gc,
1 + textw(launcher.prompt) + textw(" ") + textw(buf), 2,
1 + textw(launcher.prompt) + textw(" ") + textw(buf), INFOBARH - 4);
barwin_draw_text(bw, 1, FHINFOBAR - 1, launcher.prompt);
barwin_draw_text(bw, 1 + textw(launcher.prompt) + textw(" "), FHINFOBAR - 1, buf);
barwin_refresh(bw);
}
else
getevent(ev);
XNextEvent(dpy, &ev);
}
barwin_unmap(bw);
barwin_delete(bw);
infobar_draw(selscreen);
XUngrabKeyboard(dpy, CurrentTime);
return;
}
void
uicb_launcher(uicb_t cmd)
{
int i;
for(i = 0; i < conf.nlauncher; ++i)
if(!strcmp(cmd, conf.launcher[i].name))
launcher_execute(conf.launcher[i]);
return;
}
/*
* Just search command in PATH.
* Return the characters to complete the command.
@@ -214,36 +44,50 @@ complete_on_command(char *start, size_t hits)
char *ret = NULL;
DIR *dir;
struct dirent *content;
size_t count = 0;
char **namelist = NULL;
int n = 0, i;
if (!getenv("PATH") || !start || hits <= 0)
return NULL;
path = _strdup(getenv("PATH"));
path = xstrdup(getenv("PATH"));
dirname = strtok(path, ":");
/* recursively open PATH */
while (dirname)
while (dirname != NULL)
{
if ((dir = opendir(dirname)))
{
while ((content = readdir(dir)))
if (!strncmp(content->d_name, start, strlen(start)) && ++count == hits)
{
if(strncmp(content->d_name, ".", 1))
{
ret = _strdup(content->d_name + strlen(start));
break;
if (!strncmp(content->d_name, start, strlen(start)))
{
namelist = xrealloc(namelist, ++n, sizeof(*namelist));
namelist[n-1] = xstrdup(content->d_name);
}
}
}
closedir(dir);
}
if (ret)
break;
dirname = strtok(NULL, ":");
}
free(path);
if(n > 0)
{
qsort(namelist, n, sizeof(char *), qsort_string_compare);
ret = xstrdup(namelist[((hits > 0) ? hits - 1 : 0) % n] + strlen(start));
for(i = 0; i < n; i++)
free(namelist[i]);
free(namelist);
}
return ret;
}
@@ -272,14 +116,14 @@ complete_on_files(char *start, size_t hits)
* the beginning of file to complete on pointer 'p'.
*/
if (*(++p) == '\0' || !strrchr(p, '/'))
path = _strdup(".");
path = xstrdup(".");
else
{
/* remplace ~ by $HOME in dirname */
if (!strncmp(p, "~/", 2) && getenv("HOME"))
asprintf(&dirname, "%s%s", getenv("HOME"), p+1);
xasprintf(&dirname, "%s%s", getenv("HOME"), p+1);
else
dirname = _strdup(p);
dirname = xstrdup(p);
/* Set p to filename to be complete
* and path the directory containing the file
@@ -290,11 +134,11 @@ complete_on_files(char *start, size_t hits)
if (p != dirname)
{
*(p++) = '\0';
path = _strdup(dirname);
path = xstrdup(dirname);
}
else
{
path = _strdup("/");
path = xstrdup("/");
p++;
}
}
@@ -308,19 +152,19 @@ complete_on_files(char *start, size_t hits)
if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits)
{
/* If it's a directory append '/' to the completion */
asprintf(&filepath, "%s/%s", path, content->d_name);
xasprintf(&filepath, "%s/%s", path, content->d_name);
if (filepath && stat(filepath, &st) != -1)
{
if (S_ISDIR(st.st_mode))
asprintf(&ret, "%s/", content->d_name + strlen(p));
xasprintf(&ret, "%s/", content->d_name + strlen(p));
else
ret = _strdup(content->d_name + strlen(p));
ret = xstrdup(content->d_name + strlen(p));
}
else
warn("%s", filepath);
IFREE(filepath);
free(filepath);
break;
}
@@ -328,8 +172,213 @@ complete_on_files(char *start, size_t hits)
closedir(dir);
}
IFREE(dirname);
IFREE(path);
free(dirname);
free(path);
return ret;
}
static void
launcher_execute(Launcher *launcher)
{
BarWindow *bw;
bool found;
bool lastwastab = False;
bool my_guitar_gently_wheeps = True;
char tmp[32] = { 0 };
char buf[512] = { 0 };
char tmpbuf[512] = { 0 };
char *complete;
int i, pos = 0, histpos = 0, w, x = 0;
int tabhits = 0;
KeySym ks;
XEvent ev;
InfobarElem *e;
screen_get_sel();
STAILQ_FOREACH(e, &infobar[selscreen].elemhead, next)
if(x < (e->geo.x + e->geo.width))
x = e->geo.x + e->geo.width + PAD;
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
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,14 +35,14 @@
/** Arrange All
*/
void
arrange(int screen, Bool update_layout)
arrange(int screen, bool update_layout)
{
Client *c;
if(screen < 0 || screen > screen_count())
if(screen < 0 || screen > screen_count() - 1)
screen = screen_get_sel();
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->screen == screen)
{
if(!ishide(c, screen))
@@ -51,10 +51,30 @@ arrange(int screen, Bool update_layout)
client_hide(c);
}
if(update_layout)
tags[screen][seltag[screen]].layout.func(screen);
if(tags[screen][seltag[screen]].layout.func)
{
if(update_layout)
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;
}
@@ -65,13 +85,14 @@ void
freelayout(int screen)
{
Client *c;
(void)screen;
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(!ishide(c, selscreen)
&& c->screen == screen_get_sel()
&& !(c->flags & MaxFlag))
&& c->screen == screen
&& !(c->flags & MaxFlag))
{
client_moveresize(c, c->ogeo, True);
client_moveresize(c, c->free_geo, True);
c->flags &= ~(TileFlag | LMaxFlag);
}
@@ -81,19 +102,22 @@ freelayout(int screen)
}
/** Layout switching function
* \param b Bool True : next False : previous
* \param b bool True : next False : previous
*/
void
layoutswitch(Bool b)
layoutswitch(bool b)
{
int i;
Client *c;
Client *c = SLIST_FIRST(&clients);
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
for(c = clients; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = c->next)
for(; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = SLIST_NEXT(c, next))
{
c->ogeo = c->geo;
c->free_geo = c->geo;
}
for(i = 0; i < conf.nlayout; ++i)
{
@@ -109,8 +133,12 @@ layoutswitch(Bool b)
}
ewmh_update_current_tag_prop();
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
infobar_draw(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
layout_func(selscreen, seltag[selscreen]);
infobar_draw(&infobar[selscreen]);
return;
}
@@ -121,6 +149,7 @@ layoutswitch(Bool b)
void
uicb_layout_next(uicb_t cmd)
{
(void)cmd;
layoutswitch(True);
return;
@@ -132,31 +161,12 @@ uicb_layout_next(uicb_t cmd)
void
uicb_layout_prev(uicb_t cmd)
{
(void)cmd;
layoutswitch(False);
return;
}
/** Max layout function
*/
void
maxlayout(int screen)
{
Client *c;
int i;
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
{
c->flags &= ~TileFlag;
c->flags |= LMaxFlag;
client_maximize(c);
}
ewmh_update_current_tag_prop();
return;
}
/** Sort all the client that can be
* tiled
* \param c Client pointer
@@ -165,16 +175,36 @@ maxlayout(int screen)
Client*
tiled_client(int screen, Client *c)
{
for(;c && ((c->flags & MaxFlag)
|| (c->flags & FreeFlag)
|| (c->flags & FSSFlag)
|| (c->flags & AboveFlag)
|| c->screen != screen
|| ishide(c, screen)); c = c->next);
for(; c && (c->flags & (MaxFlag | FreeFlag | FSSFlag | AboveFlag)
|| c->screen != screen
|| ishide(c, screen)); c = SLIST_NEXT(c, next));
if(c)
c->flags |= FLayFlag;
return c;
}
/** Max layout function
*/
void
maxlayout(int screen)
{
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
int i = 0;
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
c->flags &= ~TileFlag;
c->flags |= LMaxFlag;
client_maximize(c);
}
ewmh_update_current_tag_prop();
return;
}
/** Set the mwfact
* \param cmd Mwfact (string)
*/
@@ -192,7 +222,7 @@ uicb_set_mwfact(uicb_t cmd)
return;
tags[selscreen][seltag[selscreen]].mwfact += c;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
layout_func(selscreen, seltag[selscreen]);
ewmh_update_current_tag_prop();
@@ -205,76 +235,40 @@ uicb_set_mwfact(uicb_t cmd)
void
uicb_set_nmaster(uicb_t cmd)
{
int nc, n = atoi(cmd);
Client *c;
int nc = 0, n = atoi(cmd);
Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel();
for(nc = 0, c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next), ++nc);
for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)), ++nc);
if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0
|| tags[selscreen][seltag[selscreen]].nmaster + n > nc)
return;
tags[selscreen][seltag[selscreen]].nmaster += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
ewmh_update_current_tag_prop();
return;
}
void
uicb_set_client_layer(uicb_t cmd)
{
int n = atoi(cmd);
screen_get_sel();
CHECK(sel);
if(sel->layer + n < 1
|| sel->layer + n > tags[selscreen][seltag[selscreen]].layers)
return;
sel->layer += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;
}
void
uicb_set_layer(uicb_t cmd)
{
int n = atoi(cmd);
screen_get_sel();
if(tags[selscreen][seltag[selscreen]].layers + n < 1)
return;
tags[selscreen][seltag[selscreen]].layers += n;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
return;
}
/** Grid layout function
*/
void
grid(int screen)
static void
grid(int screen, bool horizontal)
{
Client *c;
XRectangle sg = sgeo[screen];
XRectangle cgeo = {sg.x, sg.y, 0, 0};
unsigned int i, n, cols, rows, cpcols = 0;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo cgeo = {sg.x, sg.y, 0, 0};
unsigned int i = 0, n = 0, temp, cols, rows, cpcols = 0;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
for(rows = 0; rows <= n / 2; ++rows)
for(rows = 0; rows <= (n >> 1); ++rows)
if(rows * rows >= n)
break;
@@ -282,13 +276,23 @@ grid(int screen)
? rows - 1
: rows;
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
if(!horizontal)
{
temp = cols;
cols = rows;
rows = temp;
}
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
++cpcols;
cgeo.width = (sg.width / cols) - (BORDH * 2);
cfactor_clean(c);
cgeo.width = (sg.width / cols) - (BORDH << 1);
cgeo.height = (sg.height / rows) - BORDH;
/* Last row's and last client remainder */
@@ -297,22 +301,23 @@ grid(int screen)
/* Last column's client remainder */
if(i >= rows * (cols - 1))
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH << 1)));
/* Resize */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
/* Set all the other size with current client info */
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
if(cpcols + 1 > rows)
{
cpcols = 0;
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH << 1);
cgeo.y = sg.y;
}
}
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -321,17 +326,17 @@ grid(int screen)
/** Multi tile function
* \param type Postion type { Top, Bottom, Left, Right }
*/
void
static void
multi_tile(int screen, Position type)
{
Client *c;
XRectangle sg = sgeo[screen];
XRectangle mastergeo = {sg.x, sg.y, 0, 0};
XRectangle cgeo = {sg.x, sg.y, 0, 0};
uint i, n, tilesize, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, 0, 0};
Geo cgeo = {sg.x, sg.y, 0, 0};
int i = 0, n = 0, tilesize = 0, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
/* FIX NMASTER */
nmaster = (n < nmaster) ? n : nmaster;
@@ -342,50 +347,51 @@ multi_tile(int screen, Position type)
: tags[screen][seltag[screen]].mwfact * sg.width;
/* MASTER SIZE */
if(type == Top || type == Bottom)
if(LDIR(type))
{
if(type == Top)
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (sg.width / nmaster) - (BORDH * 4);
mastergeo.height = (n <= nmaster) ? sg.height - BORDH : mwfact;
if(type == Left)
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH << 1);
mastergeo.width = (n <= nmaster) ? (sg.width - (BORDH << 1)) : mwfact;
mastergeo.height = (sg.height / nmaster) - BORDH;
}
else
{
if(type == Left)
mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2);
mastergeo.width = (n <= nmaster) ? sg.width - (BORDH * 2) : mwfact;
mastergeo.height = (sg.height / nmaster) - BORDH;
if(type == Top)
mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
mastergeo.width = (sg.width / nmaster) - (BORDH << 2);
mastergeo.height = (n <= nmaster) ? (sg.height - BORDH) : mwfact;
}
/* TILED SIZE */
if(n > nmaster)
{
if(type == Top || type == Bottom)
tilesize = sg.width / (n - nmaster) - (BORDH * 4);
if(LDIR(type))
tilesize = sg.height / (n - nmaster) - ((BORDH << 1) + TBARH);
else
tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH);
tilesize = sg.width / (n - nmaster) - (BORDH << 2);
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
/* MASTER */
if(i < nmaster)
{
cgeo.width = mastergeo.width;
cgeo.height = mastergeo.height;
if(type == Top || type == Bottom)
cgeo.y = mastergeo.y;
else
if(LDIR(type))
{
cgeo.x = mastergeo.x;
cgeo.height -= (TBARH + BORDH);
}
else
cgeo.y = mastergeo.y;
}
/* TILED */
@@ -406,42 +412,43 @@ multi_tile(int screen, Position type)
break;
default:
case Right:
cgeo.x += mastergeo.width + (BORDH * 2);
cgeo.x += mastergeo.width + (BORDH << 1);
cgeo.y = sg.y;
break;
}
}
if(type == Top || type == Bottom)
if(LDIR(type))
{
cgeo.width = tilesize;
cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2);
cgeo.width = sg.width - mastergeo.width - (BORDH << 2);
cgeo.height = tilesize;
}
else
{
cgeo.width = sg.width - mastergeo.width - (BORDH * 4);
cgeo.height = tilesize;
cgeo.width = tilesize;
cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH << 1);
}
}
/* REMAINDER */
if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
{
if(type == Top || type == Bottom)
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
else
if(LDIR(type))
cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH;
else
cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH << 1)));
}
/* Magic instant */
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
/* Set the position of the next client */
if(type == Top || type == Bottom)
cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
if(LDIR(type))
cgeo.y = c->pgeo.y + c->pgeo.height + BORDH + TBARH;
else
cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
cgeo.x = c->pgeo.x + c->pgeo.width + (BORDH << 1);
}
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -451,27 +458,29 @@ multi_tile(int screen, Position type)
* \param screen Screen to execute this function
* \param horizont To specify the mirror mode (vertical/horizontal)
*/
void
mirror(int screen, Bool horizontal)
static void
mirror(int screen, bool horizontal)
{
Client *c;
XRectangle sg = sgeo[screen];
XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height};
XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height};
XRectangle nextg[2] = { {0} };
uint i, n, tilesize, mwfact;
uint nmaster = tags[screen][seltag[screen]].nmaster;
Client *c = tiled_client(screen, SLIST_FIRST(&clients));
Geo sg = sgeo[screen];
Geo mastergeo = {sg.x, sg.y, sg.width, sg.height};
Geo cgeo = {sg.x, sg.y , sg.width, sg.height};
Geo nextg[2];
int i = 0, n = 0, tilesize = 0, mwfact;
int nmaster = tags[screen][seltag[screen]].nmaster;
int pa, imp;
Bool isp = 0;
bool isp = False;
for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
CHECK(n);
memset(nextg, 0, sizeof(nextg));
for(; c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++n);
CHECK((tags[screen][seltag[screen]].nclients = n));
/* Fix nmaster */
nmaster = (n < nmaster) ? n : nmaster;
imp = ((n - (nmaster - 1)) / 2);
pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1);
imp = ((n - (nmaster - 1)) >> 1);
pa = ((n - (nmaster - 1)) >> 1) - (((n - (nmaster - 1)) & 1) ? 0 : 1);
/* Set mwfact */
if(tags[screen][seltag[screen]].mwfact < 0.55)
@@ -482,26 +491,26 @@ mirror(int screen, Bool horizontal)
/* Master size */
if(horizontal)
{
mastergeo.width = (sg.width / nmaster) - (BORDH * 2);
mastergeo.width = (sg.width / nmaster) - (BORDH << 1);
mastergeo.height -= BORDH;
}
else
{
mastergeo.width -= BORDH * 2;
mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2));
mastergeo.width -= (BORDH << 1);
mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH << 1));
}
if(n == nmaster + 1)
{
if(horizontal)
{
mastergeo.height = mwfact - ((BORDH * 2) + TBARH);
tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH);
mastergeo.height = mwfact - ((BORDH << 1) + TBARH);
tilesize = (sg.height - mastergeo.height) - ((BORDH << 1) + TBARH);
}
else
{
mastergeo.width = mwfact - (BORDH * 3);
tilesize = (sg.width - mastergeo.width) - (BORDH * 4);
tilesize = (sg.width - mastergeo.width) - (BORDH << 2);
}
}
if(n > nmaster + 1)
@@ -509,23 +518,25 @@ mirror(int screen, Bool horizontal)
if(horizontal)
{
mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH;
mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2));
tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2));
mastergeo.height = ((mwfact << 1) - sg.height) - ((BORDH * 3) + (TBARH << 1));
tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH << 1));
}
else
{
mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH;
mastergeo.width = ((2 * mwfact - sg.width) - (BORDH * 4));
mastergeo.width = ((mwfact << 1) - sg.width) - (BORDH << 2);
tilesize = (mwfact - mastergeo.width) - (BORDH * 5);
}
}
for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
for(c = tiled_client(screen, SLIST_FIRST(&clients)); c; c = tiled_client(screen, SLIST_NEXT(c, next)), ++i)
{
/* Set client property */
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
if(i < nmaster)
{
cgeo = mastergeo;
@@ -534,7 +545,7 @@ mirror(int screen, Bool horizontal)
if(i + 1 == nmaster)
{
if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
}
@@ -546,19 +557,19 @@ mirror(int screen, Bool horizontal)
else
cgeo.width = tilesize;
if((i + nmaster) % 2)
if((i + nmaster) & 1)
{
isp = 1;
if(horizontal)
{
cgeo.y = sg.y;
cgeo.width = (sg.width / pa) - (BORDH * 2);
cgeo.width = (sg.width / pa) - (BORDH << 1);
}
else
{
cgeo.x = sg.x;
cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2));
cgeo.height = (sg.height / pa) - (TBARH + (BORDH << 1));
}
}
else
@@ -568,12 +579,12 @@ mirror(int screen, Bool horizontal)
if(horizontal)
{
cgeo.y = (sg.y + mwfact) - BORDH;
cgeo.width = (sg.width / imp) - (BORDH * 2);
cgeo.width = (sg.width / imp) - (BORDH << 1);
}
else
{
cgeo.x = (sg.x + mwfact) - BORDH;
cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2));
cgeo.height = (sg.height / imp) - (TBARH + (BORDH << 1));
}
}
@@ -581,16 +592,16 @@ mirror(int screen, Bool horizontal)
if(i + 1 == n || i + 1 == n - 1)
{
if(horizontal)
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH << 1));
else
cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
}
}
client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
client_moveresize(c, (c->pgeo = cgeo), (tags[screen][seltag[screen]].flags & ResizeHintFlag));
if(i >= nmaster)
nextg[!isp] = c->geo;
nextg[!isp] = c->pgeo;
/* Next y/x position */
if(i >= nmaster - 1)
@@ -600,7 +611,7 @@ mirror(int screen, Bool horizontal)
if(i == nmaster || i == nmaster - 1)
cgeo.x = sg.x;
else
cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2;
cgeo.x = nextg[isp].x + nextg[isp].width + (BORDH << 1);
}
else
{
@@ -613,79 +624,14 @@ mirror(int screen, Bool horizontal)
else if (i <= nmaster - 1)
{
if(horizontal)
mastergeo.x = c->geo.x + c->geo.width + BORDH * 2;
mastergeo.x = cgeo.x + cgeo.width + (BORDH << 1);
else
mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
mastergeo.y = cgeo.y + cgeo.height + BORDH + TBARH;
}
}
ewmh_update_current_tag_prop();
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);
tags[screen][seltag[screen]].flags &= ~CleanFactFlag;
ewmh_update_current_tag_prop();
return;
@@ -751,14 +697,24 @@ mirror_horizontal(int screen)
return;
}
/** Put the selected client to the master postion
* \param cmd uicb_t type unused
*/
/** Horizontal grid function
*/
void
uicb_tile_switch(uicb_t cmd)
grid_horizontal(int screen)
{
layout_set_client_master (sel);
return;
grid(screen, True);
return;
}
/** Vertical grid function
*/
void
grid_vertical(int screen)
{
grid(screen, False);
return;
}
/** Toggle the selected client to free
@@ -767,50 +723,68 @@ uicb_tile_switch(uicb_t cmd)
void
uicb_togglefree(uicb_t cmd)
{
(void)cmd;
if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag))
return;
sel->flags ^= FreeFlag;
if((sel->flags & FreeFlag))
if(sel->flags & FreeFlag)
{
split_set_current(NULL, sel);
sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
client_moveresize(sel, sel->ogeo, True);
client_moveresize(sel, sel->free_geo, True);
client_raise(sel);
}
else
{
sel->free_geo = sel->geo;
sel->ogeo = sel->geo;
split_set_current(sel, NULL);
}
client_update_attributes(sel);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return;
}
/** Toggle the selected client to max
* \param cmd uicb_t type unused
*/
void
uicb_togglemax(uicb_t cmd)
{
if(!sel || ishide(sel, selscreen)
|| (sel->flags & HintFlag)|| (sel->flags & FSSFlag))
(void)cmd;
if(!sel || ishide(sel, selscreen) || (sel->flags & (HintFlag | FSSFlag)))
return;
if(!(sel->flags & MaxFlag))
sel->flags ^= MaxFlag;
if(sel->flags & MaxFlag)
{
sel->ogeo = sel->geo;
sel->free_geo = sel->geo;
sel->flags &= ~(TileFlag | FreeFlag);
split_set_current(NULL, sel);
client_maximize(sel);
client_raise(sel);
sel->flags |= MaxFlag;
XRaiseWindow(dpy, sel->frame);
}
else
{
sel->flags &= ~MaxFlag;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
sel->geo = sel->ogeo;
client_moveresize(sel, sel->geo, True);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
split_set_current(sel, NULL);
layout_func(selscreen, seltag[selscreen]);
}
return;
@@ -822,11 +796,15 @@ uicb_togglemax(uicb_t cmd)
void
uicb_toggle_resizehint(uicb_t cmd)
{
Client *c = tiled_client(selscreen, SLIST_FIRST(&clients));
screen_get_sel();
(void)cmd;
tags[selscreen][seltag[selscreen]].resizehint = !tags[selscreen][seltag[selscreen]].resizehint;
tags[selscreen][seltag[selscreen]].flags ^= ResizeHintFlag;
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
for(; c; c = tiled_client(selscreen, SLIST_NEXT(c, next)))
client_moveresize(c, c->geo, (tags[selscreen][seltag[selscreen]].flags & ResizeHintFlag));
return;
}
@@ -838,12 +816,15 @@ void
uicb_toggle_abovefc(uicb_t cmd)
{
Client *c;
(void)cmd;
screen_get_sel();
if(!(tags[selscreen][seltag[selscreen]].abovefc = !tags[selscreen][seltag[selscreen]].abovefc))
tags[selscreen][seltag[selscreen]].flags ^= AboveFCFlag;
if(!(tags[selscreen][seltag[selscreen]].flags & AboveFCFlag))
{
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
if(c->flags & AboveFlag
&& c->screen == selscreen
&& c->tag == seltag[selscreen])
@@ -852,7 +833,8 @@ uicb_toggle_abovefc(uicb_t cmd)
break;
}
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
}
client_focus(sel);
@@ -866,7 +848,7 @@ uicb_toggle_abovefc(uicb_t cmd)
void
uicb_set_layout(uicb_t cmd)
{
int i, j, n;
size_t i, j, n;
screen_get_sel();
@@ -874,11 +856,13 @@ uicb_set_layout(uicb_t cmd)
for(n = 0; layout_list[n].name != NULL && layout_list[n].func != NULL; ++n);
for(i = 0; i < n; ++i)
if(!strcmp(cmd, _strdup(layout_list[i].name)))
if(!strcmp(cmd, xstrdup(layout_list[i].name)))
for(j = 0; j < LEN(conf.layout); ++j)
if(layout_list[i].func == conf.layout[j].func)
tags[selscreen][seltag[selscreen]].layout = conf.layout[j];
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
tags[selscreen][seltag[selscreen]].flags &= ~SplitFlag;
arrange(selscreen, True);
return;
@@ -892,18 +876,67 @@ layout_set_client_master(Client *c)
{
screen_get_sel();
if(!c || (c->flags & HintFlag) || !(c->flags & TileFlag)
|| (c->flags & FSSFlag))
if(!c || (c->flags & (HintFlag | FSSFlag)) || !(c->flags & TileFlag))
return;
if(c == tiled_client(selscreen, clients))
CHECK((c = tiled_client(selscreen, c->next)));
if(c == tiled_client(selscreen, SLIST_FIRST(&clients)))
CHECK((c = tiled_client(selscreen, SLIST_NEXT(c, next))));
client_detach(c);
client_attach(c);
client_focus(c);
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][seltag[selscreen]].flags |= CleanFactFlag;
layout_func(selscreen, seltag[selscreen]);
return;
}
/** Check the selected client is max
* \param cmd uicb_t type unused
*/
bool
uicb_checkmax(uicb_t cmd)
{
(void)cmd;
if(!sel)
return False;
if(sel->flags & MaxFlag)
return True;
return False;
}
/** Check the selected client is free
* \param cmd uicb_t type unused
*/
bool
uicb_checkfree(uicb_t cmd)
{
(void)cmd;
if(!sel)
return False;
if(sel->flags & FreeFlag)
return True;
return False;
}
/** Check layout type
* \param cmd uicb_t type layout type
*/
bool
uicb_checklayout(uicb_t cmd)
{
screen_get_sel();
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"
void
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n)
static int
menu_get_longer_string(MenuItem *mi, int nitem)
{
int i, w, l = 0;
/* Item */
menu->nitem = nitem;
menu->item = emalloc(sizeof(MenuItem), nitem);
menu->name = name;
for(i = 0; i < nitem; ++i)
if((w = textw(mi[i].name)) > l)
l = w;
/* Colors */
menu->colors.focus.bg = bg_f;
menu->colors.focus.fg = fg_f;
menu->colors.normal.bg = bg_n;
menu->colors.normal.fg = fg_n;
return;
return l;
}
void
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd)
static bool
menu_get_checkstring_needed(MenuItem *mi, int nitem)
{
mi->name = name;
mi->func = func;
mi->cmd = cmd;
return;
(void)mi;
(void)nitem;
return True;
}
void
menu_draw(Menu menu, int x, int y)
static void
menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[], int chcklen)
{
int i, width;
XEvent ev;
BarWindow *item[menu.nitem];
BarWindow *frame;
int x;
int width = menu_get_longer_string(menu->item, menu->nitem) + chcklen + PAD / 3;
width = menu_get_longer_string(menu.item, menu.nitem);
/* Frame barwin */
frame = barwin_create(ROOT, x, y, width + SHADH, menu.nitem * (INFOBARH - SHADH) + SHADH * 2,
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
barwin_map(frame);
barwin_map_subwin(frame);
barwin_refresh_color(frame);
for(i = 0; i < menu.nitem; ++i)
switch(menu->align)
{
item[i] = barwin_create(frame->win,
SHADH,
(i * (INFOBARH - SHADH) + SHADH),
width - SHADH,
INFOBARH,
menu.colors.normal.bg,
menu.colors.normal.fg,
True, False, False);
case MA_Left:
x = chcklen + PAD / 2;
break;
case MA_Right:
x = width - textw(menu->item[item].name) + PAD * 3 / 2;
break;
default:
case MA_Center:
x = (width - (chcklen + PAD / 3)) / 2 - textw(menu->item[item].name) / 2 + chcklen + PAD / 3;
break;
}
barwin_draw_text(winitem[item], x, FHINFOBAR, menu->item[item].name);
barwin_map(item[i]);
barwin_refresh_color(item[i]);
menu_draw_item_name(&menu, i, item);
barwin_refresh(item[i]);
if(menu->item[item].check)
if(menu->item[item].check(menu->item[item].cmd))
barwin_draw_text(winitem[item], PAD / 3, FHINFOBAR, conf.selected_layout_symbol);
if(menu->item[item].submenu)
barwin_draw_text(winitem[item], width + PAD * 2, FHINFOBAR, ">");
return;
}
static bool
menu_activate_item(Menu *menu, int i)
{
int j, x, y;
int chcklen = 0;
if(menu_get_checkstring_needed(menu->item, menu->nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
if(menu->item[i].submenu)
{
for(j = 0; j < conf.nmenu; ++j)
if(!strcmp(menu->item[i].submenu, conf.menu[j].name))
{
y = menu->y + ((i - 1) * INFOBARH + PAD) - SHADH * 2;
x = menu->x + menu_get_longer_string(menu->item, menu->nitem) + chcklen + textw(">") + PAD * 3;
menu_draw(conf.menu[j], x, y);
return True;
}
}
else if(menu->item[i].func)
{
menu->item[i].func(menu->item[i].cmd);
return True;
}
/* Select the first item */
menu_focus_item(&menu, 0, item);
return False;
}
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
static void
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
{
int i;
while(!menu_manage_event(&ev, &menu, item));
int chcklen = 0;
if(menu_get_checkstring_needed(menu->item, menu->nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
XUngrabKeyboard(dpy, CurrentTime);
menu->focus_item = item;
for(i = 0; i < menu.nitem; ++i)
barwin_delete(item[i]);
barwin_delete(frame);
if(menu->focus_item > menu->nitem - 1)
menu->focus_item = 0;
else if(menu->focus_item < 0)
menu->focus_item = menu->nitem - 1;
for(i = 0; i < menu->nitem; ++i)
{
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
barwin_refresh_color(winitem[i]);
menu_draw_item_name(menu, i, winitem, chcklen);
barwin_refresh(winitem[i]);
}
return;
}
Bool
static bool
menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
{
int i, c = 0;
KeySym ks;
Bool quit = False;
KeySym ks = 0;
bool quit = False;
char acc = 0;
switch(ev->type)
{
@@ -127,12 +160,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
{
if(ev->xbutton.window == winitem[i]->win
&& (ev->xbutton.button == Button1 || ev->xbutton.button == Button2))
{
if(menu->item[i].func)
menu->item[i].func(menu->item[i].cmd);
quit = True;
}
quit = menu_activate_item(menu, i);
else if(ev->xbutton.window != winitem[i]->win)
++c;
else if(ev->xbutton.button == Button4)
@@ -161,9 +189,7 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
break;
case XK_Return:
if(menu->item[menu->focus_item].func)
menu->item[menu->focus_item].func(menu->item[menu->focus_item].cmd);
quit = True;
quit = menu_activate_item(menu, menu->focus_item);
break;
case XK_Escape:
@@ -178,69 +204,33 @@ menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[])
/* For focus an item with the mouse */
for(i = 0; i < menu->nitem; ++i)
if(ev->xcrossing.window == winitem[i]->win)
{
acc = 1;
menu_focus_item(menu, i, winitem);
if(menu->item[i].submenu)
menu_activate_item(menu, menu->focus_item);
}
if(!acc)
{
if(ev->xcrossing.window)
XSendEvent(dpy, ev->xcrossing.window, False, StructureNotifyMask, ev);
return True;
}
break;
default:
getevent(*ev);
if(ev->type < nevent && ev->type > 0)
HANDLE_EVENT(ev);
break;
}
XNextEvent(dpy, ev);
return quit;
}
void
menu_focus_item(Menu *menu, int item, BarWindow *winitem[])
{
int i;
menu->focus_item = item;
if(menu->focus_item > menu->nitem - 1)
menu->focus_item = 0;
else if(menu->focus_item < 0)
menu->focus_item = menu->nitem - 1;
for(i = 0; i < menu->nitem; ++i)
{
winitem[i]->fg = ((i == menu->focus_item) ? menu->colors.focus.fg : menu->colors.normal.fg);
winitem[i]->bg = ((i == menu->focus_item) ? menu->colors.focus.bg : menu->colors.normal.bg);
barwin_refresh_color(winitem[i]);
menu_draw_item_name(menu, i, winitem);
barwin_refresh(winitem[i]);
}
return;
}
void
menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[])
{
int width = menu_get_longer_string(menu->item, menu->nitem);
barwin_draw_text(winitem[item],
((width / 2) - (textw(menu->item[item].name) / 2)),
FHINFOBAR,
menu->item[item].name);
return;
}
int
menu_get_longer_string(MenuItem *mt, int nitem)
{
int i, l = 0;
for(i = 0; i < nitem; ++i)
if(textw(mt[i].name) > l)
l = textw(mt[i].name);
return l + PAD;
}
void
uicb_menu(uicb_t cmd)
{
@@ -254,7 +244,11 @@ uicb_menu(uicb_t cmd)
if(!strcmp(cmd, conf.menu[i].name))
{
if(conf.menu[i].place_at_mouse)
{
XQueryPointer(dpy, ROOT, &w, &w, &x, &y, &d, &d, (uint *)&u);
conf.menu[i].x = x;
conf.menu[i].y = y;
}
else
{
screen_get_sel();
@@ -266,3 +260,104 @@ uicb_menu(uicb_t cmd)
return;
}
void
menu_clear(Menu *menu)
{
free(menu->item);
menu->nitem = 0;
return;
}
void
menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n)
{
/* Item */
menu->nitem = nitem;
menu->item = xcalloc(nitem, sizeof(*menu->item));
menu->name = name;
/* Colors */
menu->colors.focus.bg = bg_f;
menu->colors.focus.fg = fg_f;
menu->colors.normal.bg = bg_n;
menu->colors.normal.fg = fg_n;
return;
}
void
menu_new_item(MenuItem *mi, char *name, void *func, char *cmd)
{
mi->name = name;
mi->func = func;
mi->cmd = cmd;
return;
}
void
menu_draw(Menu menu, int x, int y)
{
int i, width, height, out;
XEvent ev;
BarWindow *item[menu.nitem];
BarWindow *frame;
int chcklen = 0;
if(menu_get_checkstring_needed(menu.item, menu.nitem))
chcklen = textw(conf.selected_layout_symbol) + PAD / 3;
width = menu_get_longer_string(menu.item, menu.nitem) + chcklen + textw(">") + PAD * 3;
height = menu.nitem * (INFOBARH - SHADH);
/* Frame barwin */
screen_get_sel();
if((out = x + width - MAXW) > 0)
x -= out;
if((out = y + height - MAXH) > 0)
y -= out;
frame = barwin_create(ROOT, x, y, width + SHADH, height + SHADH * 3,
menu.colors.normal.bg, menu.colors.normal.fg, False, False, True);
barwin_map(frame);
barwin_map_subwin(frame);
barwin_refresh_color(frame);
for(i = 0; i < menu.nitem; ++i)
{
item[i] = barwin_create(frame->win,
SHADH,
(i * (INFOBARH - SHADH) + SHADH),
width - SHADH,
INFOBARH,
menu.colors.normal.bg,
menu.colors.normal.fg,
True, False, False);
barwin_map(item[i]);
barwin_refresh_color(item[i]);
menu_draw_item_name(&menu, i, item, chcklen);
barwin_refresh(item[i]);
}
/* Select the first item */
menu_focus_item(&menu, 0, item);
XGrabKeyboard(dpy, ROOT, True, GrabModeAsync, GrabModeAsync, CurrentTime);
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,38 +32,50 @@
#include "wmfs.h"
Window prevwin;
/** Draw the border when a client in dragging/resizing with mouse
*/
void
mouse_dragborder(XRectangle geo, GC g)
static void
mouse_dragborder(Geo geo, GC g)
{
XDrawRectangle(dpy, ROOT, g,
geo.x - BORDH / 2,
geo.y - (TBARH - (BORDH / 2)),
geo.x - (BORDH >> 1),
geo.y - (TBARH - (BORDH >> 1)),
geo.width + BORDH,
geo.height + TBARH);
return;
}
static void
mouse_cfactor_border(Client *c, int f[4], GC g)
{
int e;
mouse_dragborder(cfactor_geo(c->wrgeo, f, &e), g);
return;
}
/** Move a client in tile grid with the mouse
*\param c Client double pointer
*/
void
static void
mouse_move_tile_client(Client **c)
{
Client *sc;
Window w;
int d;
if(!((*c)->flags & TileFlag) && !((*c)->flags & LMaxFlag))
if(!((*c)->flags & (TileFlag | LMaxFlag)))
return;
XQueryPointer(dpy, ROOT, &w, &w, &d, &d, &d, &d, (uint*)&d);
if(((sc = client_gb_win(w)) || (sc = client_gb_frame(w)) || (sc = client_gb_titlebar(w)))
&& (*c)->win != sc->win && !((*c)->flags & HideFlag) && !(sc->flags & HideFlag))
&& (*c)->win != sc->win && !((*c)->flags & HideFlag) && !(sc->flags & HideFlag) && (sc->flags & TileFlag))
{
client_swap(sc, *c);
client_focus(sc);
@@ -77,27 +89,29 @@ mouse_move_tile_client(Client **c)
/** Move a client from one tag to another with dah mouse
*\param c client pointer
*/
void
static void
mouse_move_tag_client(Client *c)
{
Window w;
int i, d, s;
if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag))
if(!(c->flags & (TileFlag | LMaxFlag)))
return;
s = c->screen;
XQueryPointer(dpy, infobar[selscreen].bar->win, &w, &w, &d, &d, &d, &d, (uint*)&d);
XQueryPointer(dpy, infobar[selscreen].tags_board->win, &w, &w, &d, &d, &d, &d, (uint*)&d);
if(w == prevwin)
return;
prevwin = w;
for(i = 1; i < conf.ntag[selscreen] + 1; ++i)
if(infobar[selscreen].tags[i]->win == w
&& tags[selscreen][i].layout.func != freelayout)
{
c->screen = selscreen;
c->tag = i;
tags[c->screen][c->tag].request_update = True;
arrange(s, True);
tag_transfert(c, i);
if(s != c->screen)
arrange(c->screen, True);
@@ -109,19 +123,19 @@ mouse_move_tag_client(Client *c)
/** Move the client with the mouse
* \param c Client pointer
*/
void
static void
mouse_move(Client *c)
{
int ocx, ocy, mx, my;
int dint;
uint duint;
Window dw;
XRectangle geo = c->geo;
Geo geo = c->geo;
XGCValues xgc;
GC gci;
XEvent ev;
if((c->flags & MaxFlag) || (c->flags & FSSFlag))
if(c->flags & (MaxFlag | FSSFlag))
return;
ocx = c->geo.x;
@@ -170,14 +184,13 @@ mouse_move(Client *c)
mouse_dragborder(geo, gci);
}
}
else if(ev.type == MapRequest
|| ev.type == ConfigureRequest)
getevent(ev);
else if((ev.type == MapRequest || ev.type == ConfigureRequest))
HANDLE_EVENT(&ev);
}
while(ev.type != ButtonRelease);
/* One time again to delete all the trace on the window */
if(!(c->flags & TileFlag) && !(c->flags & LMaxFlag))
if(!(c->flags & (TileFlag | LMaxFlag)))
{
mouse_dragborder(geo, gci);
client_moveresize(c, geo, False);
@@ -198,23 +211,21 @@ mouse_move(Client *c)
void
mouse_resize(Client *c)
{
XRectangle geo = c->geo, ogeo = c->geo;
Geo geo = c->geo, ogeo = c->geo;
Position pos = Right;
XEvent ev;
Window w;
int d, u, omx, omy;
XGCValues xgc;
GC gci;
float mwf = tags[selscreen][seltag[selscreen]].mwfact;
int f[4] = { 0 };
if((c->flags & MaxFlag)
|| (c->flags & LMaxFlag)
|| (c->flags & FSSFlag))
if(c->flags & (MaxFlag | LMaxFlag | FSSFlag))
return;
XQueryPointer(dpy, ROOT, &w, &w, &omx, &omy, &d, &d, (uint *)&u);
if((omx - c->geo.x) < (c->geo.width / 2))
if((omx - c->geo.x) < (c->geo.width >> 1))
pos = Left;
if(XGrabPointer(dpy, ROOT, False, MouseMask, GrabModeAsync, GrabModeAsync, None,
@@ -239,6 +250,8 @@ mouse_resize(Client *c)
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, c->geo.height);
mouse_dragborder(c->geo, gci);
}
else
mouse_cfactor_border(c, f, gci);
do
{
@@ -246,23 +259,22 @@ mouse_resize(Client *c)
if(ev.type == MotionNotify)
{
/* To resize MWFACT in tile mode */
if((c->flags & TileFlag)
&& tags[selscreen][seltag[selscreen]].layout.func != grid)
/* To resize client in tile mode with cfactor */
if(c->flags & TileFlag)
{
if(tags[selscreen][seltag[selscreen]].layout.func == tile)
mwf += (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_left)
mwf -= (ROUND(ev.xmotion.x_root) - omx) / (sgeo[c->screen].width);
else if(tags[selscreen][seltag[selscreen]].layout.func == tile_top)
mwf -= (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height);
mouse_cfactor_border(c, f, gci);
if(omx >= c->frame_geo.x + (c->frame_geo.width >> 1))
f[Right] = ev.xmotion.x_root - omx;
else
mwf += (ROUND(ev.xmotion.y_root) - omy) / (sgeo[c->screen].height);
f[Left] = omx - ev.xmotion.x_root;
omx = ROUND(ev.xmotion.x_root);
omy = ROUND(ev.xmotion.y_root);
if(omy >= c->frame_geo.y + (c->frame_geo.height >> 1))
f[Bottom] = ev.xmotion.y_root - omy;
else
f[Top] = omy - ev.xmotion.y_root;
tags[selscreen][seltag[selscreen]].mwfact = (mwf < 0.05) ? 0.05 : ((mwf > 0.95) ? 0.95 : mwf);
mouse_cfactor_border(c, f, gci);
}
/* Free mode */
else if(!(c->flags & TileFlag))
@@ -301,7 +313,10 @@ mouse_resize(Client *c)
XUngrabServer(dpy);
}
else
tags[selscreen][seltag[selscreen]].layout.func(c->screen);
{
mouse_cfactor_border(c, f, gci);
cfactor_multi_set(c, f);
}
client_update_attributes(c);
XUngrabPointer(dpy, CurrentTime);
@@ -315,23 +330,23 @@ mouse_resize(Client *c)
* \param focused For know if c is or not focused
*/
void
mouse_grabbuttons(Client *c, Bool focused)
mouse_grabbuttons(Client *c, bool focused)
{
int i;
size_t i = 0;
uint but[] = {Button1, Button2, Button3, Button4, Button5};
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused)
for(i = 0; i < LEN(but); ++i)
for(; i < LEN(but); ++i)
{
XGrabButton(dpy, but[i], conf.client.mod, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod|LockMask|numlockmask, c->win, False,
ButtonMask, GrabModeAsync,GrabModeSync, None, None);
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | LockMask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, but[i], conf.client.mod | LockMask | numlockmask, c->win, False,
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
}
else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
@@ -346,6 +361,7 @@ mouse_grabbuttons(Client *c, Bool focused)
void
uicb_mouse_move(uicb_t cmd)
{
(void)cmd;
CHECK(sel);
mouse_move(sel);
@@ -359,6 +375,7 @@ uicb_mouse_move(uicb_t cmd)
void
uicb_mouse_resize(uicb_t cmd)
{
(void)cmd;
CHECK(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 (stat(filename, &st) == -1 || (fd = open(filename, O_RDONLY)) == -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;
}

114
src/parse.h Normal file
View File

@@ -0,0 +1,114 @@
/*
* 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"
#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

@@ -38,9 +38,7 @@
int
screen_count(void)
{
int n = 0;
n = ScreenCount(dpy);
int n = ScreenCount(dpy);
#ifdef HAVE_XINERAMA
if(XineramaIsActive(dpy))
@@ -57,13 +55,13 @@ screen_count(void)
/** Get screen geometry by number
*\param s Screen number
*\return XRectangle struct
*\return Geo struct
*/
XRectangle
Geo
screen_get_geo(int s)
{
int barpos = tags[selscreen][seltag[selscreen]].barpos;
XRectangle geo;
Geo geo;
geo.x = BORDH;
if(barpos == IB_Hide || barpos == IB_Bottom)
@@ -91,6 +89,8 @@ screen_get_geo(int s)
XFree(xsi);
}
#else
(void)s;
#endif /* HAVE_XINERAMA */
return geo;
@@ -104,14 +104,13 @@ screen_get_geo(int s)
int
screen_get_with_geo(int x, int y)
{
int i, r = 0;
int i = 0;
for(i = 0; i < screen_count(); ++i)
if((x >= spgeo[i].x && x < spgeo[i].x + spgeo[i].width)
&& y >= spgeo[i].y && y < spgeo[i].y + spgeo[i].height)
r = i;
for(; i < screen_count(); ++i)
if(INAREA(x, y, spgeo[i]))
return i;
return r;
return 0;
}
/** Set the selected screen
@@ -123,10 +122,14 @@ screen_set_sel(int screen)
if(screen < 0 || screen > screen_count() - 1)
screen = 0;
if(selscreen != screen)
prevselscreen = selscreen;
client_focus(NULL);
XWarpPointer(dpy, None, ROOT, 0, 0, 0, 0,
sgeo[screen].x + sgeo[screen].width / 2,
sgeo[screen].y + sgeo[screen].height / 2);
sgeo[screen].x + (sgeo[screen].width >> 1),
sgeo[screen].y + (sgeo[screen].height >> 1));
selscreen = screen;
return;
@@ -138,6 +141,8 @@ screen_set_sel(int screen)
int
screen_get_sel(void)
{
int os = selscreen;
selscreen = 0;
#ifdef HAVE_XINERAMA
@@ -157,6 +162,9 @@ screen_get_sel(void)
XChangeProperty(dpy, ROOT, net_atom[wmfs_current_screen], XA_CARDINAL, 32,
PropModeReplace, (uchar*)&selscreen, 1);
if(os != selscreen && os != prevselscreen)
prevselscreen = os;
return selscreen;
}
@@ -166,11 +174,12 @@ void
screen_init_geo(void)
{
int i;
int s = screen_count();
sgeo = emalloc(screen_count(), sizeof(XRectangle));
spgeo = emalloc(screen_count(), sizeof(XRectangle));
sgeo = xcalloc(s, sizeof(Geo));
spgeo = xcalloc(s, sizeof(Geo));
for(i = 0; i < screen_count(); ++i)
for(i = 0; i < s; ++i)
sgeo[i] = screen_get_geo(i);
spgeo[0].x = 0;
@@ -205,7 +214,6 @@ screen_init_geo(void)
#endif /* HAVE_XRANDR */
ewmh_set_desktop_geometry();
ewmh_set_workarea();
return;
}
@@ -227,11 +235,15 @@ uicb_screen_select(uicb_t cmd)
void
uicb_screen_next(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1;
if(screen_count() > 1)
{
selscreen = (selscreen + 1 > screen_count() - 1) ? 0 : selscreen + 1;
screen_set_sel(selscreen);
screen_set_sel(selscreen);
}
return;
}
@@ -242,6 +254,7 @@ uicb_screen_next(uicb_t cmd)
void
uicb_screen_prev(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
selscreen = (selscreen - 1 < 0) ? screen_count() - 1 : selscreen - 1;
@@ -250,3 +263,19 @@ uicb_screen_prev(uicb_t cmd)
return;
}
/** Uicb: screen prev sel
* \param cmd uicb_t type unused
*/
void
uicb_screen_prev_sel(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
screen_set_sel(prevselscreen);
return;
}

374
src/split.c Normal file
View File

@@ -0,0 +1,374 @@
/*
* split.c
* Copyright © 2011 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
#define SPLIT_CHECK_ROW(g1, g2, p) \
(LDIR(p) \
? (g1.y >= g2.y && (g1.y + g1.height) <= (g2.y + g2.height)) \
: (g1.x >= g2.x && (g1.x + g1.width) <= (g2.x + g2.width))) \
#define SPLIT_MOVE_DIR(d) \
void \
uicb_split_move_##d(uicb_t cmd) \
{ \
(void)cmd; \
CHECK(sel); \
split_move_dir(sel, d); \
}
/* uicb_split_move_dir() */
SPLIT_MOVE_DIR(Right);
SPLIT_MOVE_DIR(Left);
SPLIT_MOVE_DIR(Top);
SPLIT_MOVE_DIR(Bottom);
/** Arrange size of parent client of last closed client
*/
static void
_split_arrange_size(Geo g, Geo *cg, Position p)
{
if(LDIR(p))
cg->width += FRAMEW(g.width);
else
cg->height += FRAMEH(g.height);
if(p == Right)
cg->x -= FRAMEW(g.width);
if(p == Bottom)
cg->y -= FRAMEH(g.height);
return;
}
/** Set layout current clients to split/unsplit
*/
void
split_set_current(Client *nc, Client *ghost)
{
if(nc && (tags[nc->screen][nc->tag].flags & SplitFlag))
{
tags[nc->screen][nc->tag].layout.nc = nc;
tags[nc->screen][nc->tag].layout.flags |= IntegrationFlag;
}
if(ghost && (tags[ghost->screen][ghost->tag].flags & SplitFlag))
{
tags[ghost->screen][ghost->tag].layout.ghost = *ghost;
tags[ghost->screen][ghost->tag].layout.flags |= ArrangeFlag;
}
return;
}
/** Apply current operation about split
*/
void
split_apply_current(int screen, int tag)
{
/* Integrate in split mode */
if(tags[screen][tag].layout.flags & IntegrationFlag)
{
split_client_integrate(tags[screen][tag].layout.nc, sel, screen, tag);
tags[screen][tag].layout.flags &= ~IntegrationFlag;
}
/* Remove from split mode */
if(tags[screen][tag].layout.flags & ArrangeFlag)
{
split_arrange_closed(&tags[screen][tag].layout.ghost);
tags[screen][tag].layout.flags &= ~ArrangeFlag;
}
return;
}
/** Check if row direction is available to resize from it
*\param c Client pointer
*\param g Client pointer
*\param p Position
*\return True if available
*/
static bool
_split_check_row_dir(Client *c, Client *g, Position p)
{
int s = 0, cs;
Geo cgeo = c->frame_geo;
Client *cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cs = (LDIR(p) ? g->frame_geo.height : g->frame_geo.width);
for(; cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, g->frame_geo, p))
{
s += (LDIR(p) ? cc->frame_geo.height : cc->frame_geo.width);
if(s == cs)
return True;
if(s > cs)
return False;
}
return False;
}
/** Arrange clients after a client close
*\param ghost Ghost client
*/
void
split_arrange_closed(Client *ghost)
{
Position p;
bool b = False;
Geo cgeo;
Client *c, *cc;
int screen = ghost->screen;
int tag = (ghost->tag ? ghost->tag : seltag[screen]);
/* Use ghost client properties to fix holes in tile
* .--. ~ ~
* /xx \ ~ ~
* ~~\O _ (____ ~
* __.| .--'-==~ ~
* '---\ '. ~ , ~
* '. '-.___.-'/ ~
* '-.__ _.' ~
* ````` ~
*/
/* Search for single parent for easy resize
* Example case:
* ___________ ___________
* | | B | -> -> | | |
* | A |_____| -> Close -> | A | B |
* | | C | -> C -> | |v v v|
* |_____|_____| -> -> |_____|_____|
*/
for(p = Right; p < Center; ++p)
if((c = client_get_next_with_direction(ghost, p)))
if(CFACTOR_CHECK2(ghost->frame_geo, c->frame_geo, p))
{
_split_arrange_size(ghost->wrgeo, &c->wrgeo, p);
cfactor_clean(c);
client_moveresize(c, (c->pgeo = c->wrgeo), (tags[screen][tag].flags & ResizeHintFlag));
return;
}
/* Check row parents for full resize
* Example case:
* ___________ ___________
* | | B | -> -> | << B |
* | A |_____| -> Close -> |___________|
* | | C | -> A -> | << C |
* |_____|_____| -> -> |___________|
*/
for(p = Right; p < Center && !b; ++p)
if((c = client_get_next_with_direction(ghost, p)) && _split_check_row_dir(c, ghost, p))
{
for(cgeo = c->frame_geo, cc = tiled_client(c->screen, SLIST_FIRST(&clients));
cc; cc = tiled_client(c->screen, SLIST_NEXT(cc, next)))
if(CFACTOR_PARENTROW(cgeo, cc->frame_geo, RPOS(p))
&& SPLIT_CHECK_ROW(cc->frame_geo, ghost->frame_geo, p))
{
_split_arrange_size(ghost->wrgeo, &cc->wrgeo, p);
cfactor_clean(cc);
client_moveresize(cc, (cc->pgeo = cc->wrgeo), (tags[screen][tag].flags & ResizeHintFlag));
b = True;
}
}
return;
}
/** Split client hor or vert to insert another client in the new area
*\param c Client pointer
*\param p True = Vertical, False = Horizontal
*\return sgeo Geo of future integrated client
*/
Geo
split_client(Client *c, bool p)
{
Geo geo, sgeo;
if(!c || !(c->flags & TileFlag))
return c->wrgeo;
cfactor_clean(c);
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
/* Use geometry without resizehint applied on it */
geo = sgeo = c->wrgeo;
/* Vertical */
if(p)
{
geo.width >>= 1;
sgeo.x = FRAMEW(geo.x + geo.width);
sgeo.width = (sgeo.width >> 1) - (BORDH << 1);
/* Remainder */
sgeo.width += (c->wrgeo.x + c->wrgeo.width) - (sgeo.x + sgeo.width);
}
/* Horizontal */
else
{
geo.height = (geo.height >> 1) - TBARH;
sgeo.y = FRAMEH(geo.y + geo.height);
sgeo.height = (sgeo.height >> 1) - BORDH;
/* Remainder */
sgeo.height += (c->wrgeo.y + c->wrgeo.height) - (sgeo.y + sgeo.height);
}
client_moveresize(c, (c->pgeo = geo), (tags[c->screen][c->tag].flags & ResizeHintFlag));
return sgeo;
}
/** Apply new attributes to splitted client
*\param c Client pointer
*\param geo New geo
*/
void
split_client_fill(Client *c, Geo geo)
{
if(!c)
return;
c->flags &= ~(MaxFlag | LMaxFlag);
c->flags |= TileFlag;
cfactor_clean(c);
client_moveresize(c, (c->pgeo = geo), (tags[c->screen][c->tag].flags & ResizeHintFlag));
return;
}
/** Integrate client in tag
*\param c Client pointer (integrate)
*\param sc Splitted client pointer
*/
void
split_client_integrate(Client *c, Client *sc, int screen, int tag)
{
bool b = True;
Geo g;
if(!c || c->flags & FreeFlag || !(tags[screen][tag].flags & SplitFlag))
return;
/* Can't integrate in sc */
if(!sc || sc == c || !(sc->flags & TileFlag)
|| sc->screen != screen || sc->tag != tag)
{
/* Looking for first client on wanted tag */
b = False;
SLIST_FOREACH(sc, &clients, next)
if(sc != c && sc->screen == screen && sc->tag == tag
&& (sc->flags & TileFlag))
{
b = True;
break;
}
/* No client on wanted tag to integrate */
if(!b)
{
/* client_maximize check position of client
* to maximize it; so in case of transfert one client
* on a tag from another screen, we need it.
*/
c->geo.x = sgeo[screen].x;
c->geo.y = sgeo[screen].y;
client_maximize(c);
c->flags |= TileFlag;
return;
}
}
g = split_client(sc, (sc->frame_geo.height < sc->frame_geo.width));
split_client_fill(c, g);
return;
}
/** Move splitted client by re-arranging it in next by direction client
* Integrate c in next client by direction
* Example case, direction = left:
* ___________ ___________
* | | B | -> | A | |
* | A |_____| -> |_____| B |
* | |< C | -> | C |v v v|
* |_____|_____| -> |_____|_____|
*/
void
split_move_dir(Client *c, Position p)
{
Client *sc;
if(!c || !(tags[c->screen][c->tag].flags & SplitFlag))
return;
if((sc = client_get_next_with_direction(c, p)))
{
split_arrange_closed(c);
split_client_integrate(c, sc, sc->screen, sc->tag);
}
return;
}
/** Toggle split mode
*/
void
uicb_split_toggle(uicb_t cmd)
{
(void)cmd;
tags[selscreen][seltag[selscreen]].flags ^= SplitFlag;
layout_func(selscreen, seltag[selscreen]);
infobar_draw_layout(&infobar[selscreen]);
return;
}

290
src/status.c Normal file
View File

@@ -0,0 +1,290 @@
/*
* status.c
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
/* Systray width */
static int sw = 0;
/** Parse dynamic mouse binds in str and insert it in linked list
* --> \<block>[;;;;(button;func;cmd)]\ add a mouse bind on the block object
*\param str String
*\param area Area of clicking
*\param infobar Infobar pointer
*/
void
statustext_mouse(char *str, Geo area, InfoBar *infobar)
{
StatusMouse *sm = NULL;
int i = 0, button = 1, n;
char cmd[256] = { 0 };
char func[64] = { 0 };
for(; i < (int)strlen(str); ++i, sm = NULL)
if((n = sscanf(&str[i], "(%d;%64[^;];%256[^)])", &button, func, cmd) >= 2) && n < 4)
{
sm = zcalloc(sizeof(StatusMouse));
sm->button = button;
sm->func = name_to_func((char*)func, func_list);
sm->cmd = xstrdup(cmd);
sm->area = area;
sm->infobar = infobar;
SLIST_INSERT_HEAD(&smhead, sm, next);
/* Jump to the end of the sequence */
while(str[++i + 1] != ')');
}
return;
}
/** Check rectangles blocks in str and draw it
* --> \b[x;y;width;height;#color]\
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_rectangle(InfoBar *ib, char *str)
{
StatusRec r;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k, n;
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, &as)) == 6
|| (n = sscanf(&str[i], "\\b[%d;%d;%d;%d;#%x;%512[^]]]%c",
&r.g.x, &r.g.y, &r.g.width, &r.g.height, &r.color, mouse, &as)) == 7)
&& as == '\\')
{
draw_rectangle(ib->bar->dr, r.g.x - sw, r.g.y, r.g.width, r.g.height, r.color);
if(n == 7)
statustext_mouse(mouse, r.g, ib);
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i)
str[j] = str[i];
for(k = j; k < i; str[k++] = '\0');
return;
}
/** 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]\
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_text(InfoBar *ib, char *str)
{
StatusText s;
Geo area;
char as, mouse[512] = { 0 };
int i = 0, j = 0, k, n;
for(; i < (int)strlen(str); ++i, ++j)
if(((n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^];]]%c",
&s.x, &s.y, s.color, s.text, &as)) == 5
|| (n = sscanf(&str[i], "\\s[%d;%d;%7[^;];%512[^;];%512[^]]]%c",
&s.x, &s.y, s.color, s.text, mouse, &as)) == 6)
&& as == '\\')
{
draw_text(ib->bar->dr, s.x - sw, s.y, s.color, s.text);
/* Etablish clickable area on text */
if(n == 6)
{
area.height = font.height;
area.width = textw(s.text);
area.x = s.x - sw;
area.y = s.y - area.height;
statustext_mouse(mouse, area, ib);
}
for(++i, --j; str[i] != as || str[i - 1] != ']'; ++i);
}
else if(j != i)
str[j] = str[i];
for(k = j; k < i; str[k++] = '\0');
return;
}
/** Draw normal text and colored normal text
* --> \#color\ text in color
*\param sc Screen id
*\param ib Infobar pointer
*\param str String
*/
static void
statustext_normal(InfoBar *ib, char *str)
{
char strwc[MAXSTATUS] = { 0 };
char buf[MAXSTATUS] = { 0 };
char col[8] = { 0 };
int n, i, j, k, tw;
for(i = j = n = 0; i < (int)strlen(str); ++i, ++j)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{
++n;
i += 8;
--j;
}
else
strwc[j] = str[i];
/* Draw normal text without any blocks */
draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (textw(strwc) + sw), FHINFOBAR, ib->bar->fg, strwc);
if(n)
{
strncpy(buf, strwc, sizeof(buf));
for(i = k = 0; i < (int)strlen(str); ++i, ++k)
if(str[i] == '\\' && str[i + 1] == '#' && str[i + 8] == '\\')
{
tw = textw(&buf[k]);
/* Store current color in col[] */
for(j = 0, ++i; str[i] != '\\'; col[j++] = str[i++]);
/* Draw a rectangle with the bar color to draw the text properly */
draw_rectangle(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw),
0, INFOBARH - (sgeo[ib->screen].width - SHADH) - tw,
INFOBARH, conf.colors.bar);
/* Draw text with its color */
draw_text(ib->bar->dr, (sgeo[ib->screen].width - SHADH) - (tw + sw), FHINFOBAR, col, &buf[k]);
strncpy(buf, strwc, sizeof(buf));
++i;
}
}
return;
}
/** Handle statustext and draw all things in infobar of specified screen
*\param sc Screen id
*\param str String
*/
void
statustext_handle(InfoBar *ib)
{
char *str;
StatusMouse *sm;
/* Free previous linked list of mouse bind */
if(!ib->screen)
while(!SLIST_EMPTY(&smhead))
{
sm = SLIST_FIRST(&smhead);
SLIST_REMOVE_HEAD(&smhead, next);
free((void*)sm->cmd);
free(sm);
}
if(ib->screen == conf.systray.screen)
sw = systray_get_width();
str = xstrdup(ib->statustext);
/* Store rectangles, located text & images properties. */
statustext_rectangle(ib, str);
statustext_graph(ib, str);
statustext_text(ib, str);
/* Draw normal text (and possibly colored with \#color\ blocks) */
statustext_normal(ib, str);
sw = 0;
free(str);
return;
}

View File

@@ -37,18 +37,44 @@
#define NBUTTON 8
#define MAXTAG 36
#define NUM_OF_LAYOUT 10
#define NUM_OF_LAYOUT 11
#define HISTOLEN 128
/* Clients flags definition */
#define FreeFlag (1 << 1)
#define MaxFlag (1 << 2)
#define TileFlag (1 << 3)
#define HideFlag (1 << 4)
#define LMaxFlag (1 << 5)
#define UnmapFlag (1 << 6)
#define HintFlag (1 << 7)
#define FSSFlag (1 << 8)
#define AboveFlag (1 << 9)
#define FreeFlag 0x01
#define MaxFlag 0x02
#define TileFlag 0x04
#define HideFlag 0x08
#define LMaxFlag 0x10
#define UnmapFlag 0x20
#define HintFlag 0x40
#define FSSFlag 0x80
#define AboveFlag 0x100
#define UrgentFlag 0x200
#define FLayFlag 0x400
#define DockFlag 0x800
/* Layout flags definition */
#define IntegrationFlag 0x01
#define ArrangeFlag 0x02
/* Tag flags definition */
#define TagUrgentFlag 0x01
#define ResizeHintFlag 0x02
#define RequestUpdateFlag 0x04
#define AboveFCFlag 0x08
#define CleanFactFlag 0x10
#define StayLastFlag 0x20
#define SplitFlag 0x40
#define FirstArrangeFlag 0x80
#define IgnoreEnterFlag 0x100
#define TagFlag(t) (1 << (t))
/* BarWindow flags definition */
#define MappedFlag 0x01
#define StippleFlag 0x02
#define BordFlag 0x04
/* XEMBED messages */
#define XEMBED_MAPPED (1 << 0)
@@ -81,12 +107,15 @@ typedef unsigned char uchar;
/* Enum */
enum { CurNormal, CurResize, CurRightResize, CurLeftResize, CurMove, CurLast };
enum { TagSel, TagTransfert, TagAdd, TagNext, TagPrev, TagActionLast };
/* Infobar position */
/* Menu align */
enum { MA_Center = 0, MA_Left = 1, MA_Right = 2 };
/* Infobar position / elements */
enum { IB_Hide = 0, IB_Bottom = 1, IB_Top = 2 };
typedef enum { Right, Left, Top, Bottom, Center, PositionLast } Position;
typedef enum { Right = 0, Left, Top, Bottom, Center, PositionLast } Position;
typedef enum { ElemTag, ElemLayout, ElemSelbar } IbElemType;
/* Ewmh hints list */
enum
@@ -99,7 +128,6 @@ enum
net_current_desktop,
net_desktop_names,
net_desktop_geometry,
net_workarea,
net_active_window,
net_close_window,
net_wm_icon_name,
@@ -107,6 +135,7 @@ enum
net_wm_pid,
net_showing_desktop,
net_supporting_wm_check,
net_wm_window_opacity,
net_wm_window_type_normal,
net_wm_window_type_dock,
net_wm_window_type_splash,
@@ -115,12 +144,20 @@ enum
net_wm_icon,
net_wm_state,
net_wm_state_fullscreen,
net_wm_state_sticky,
net_wm_state_demands_attention,
net_wm_system_tray_opcode,
net_system_tray_message_data,
net_system_tray_s,
net_system_tray_visual,
net_system_tray_orientation,
xembed,
xembedinfo,
manager,
utf8_string,
/* WMFS HINTS */
wmfs_running,
wmfs_update_hints,
wmfs_update_status,
wmfs_current_tag,
wmfs_current_screen,
wmfs_current_layout,
@@ -131,15 +168,23 @@ enum
wmfs_screen_count,
wmfs_function,
wmfs_cmd,
wmfs_font,
wmfs_statustext,
net_last
};
/* Geometry structure */
typedef struct
{
int x, y;
int width, height;
} Geo;
/*
* BarWindow Structure
* (titlebar, infobar..)
*/
typedef struct
typedef struct BarWindow
{
Window win;
Drawable dr;
@@ -154,28 +199,29 @@ typedef struct
uint bg;
char *fg;
uint stipple_color;
XRectangle geo;
Bool mapped, stipple, bord;
Geo geo;
uint flags;
SLIST_ENTRY(BarWindow) next;
} BarWindow;
/* Client Structure. */
typedef struct Client Client;
struct Client
typedef struct Client
{
/* Client title */
char *title;
/* Tag num */
uint tag;
int tag;
int focusontag;
/* Screen */
int screen;
/* Layer */
int layer;
/* Window attribute */
XRectangle geo;
XRectangle tmp_geo;
XRectangle frame_geo;
/* Old window attribute */
XRectangle ogeo;
Geo geo, pgeo; /* Window geo, tiling pure geo */
Geo tmp_geo, wrgeo; /* Temporary geo, without resizehint geo */
Geo frame_geo; /* Frame geo */
Geo ogeo; /* Old window attribute */
Geo split_geo, free_geo; /* Split & Free window attribute */
/* Tile size factors */
int tilefact[4];
/* For resizehint usage */
int basew, baseh, incw, inch;
int maxw, maxh, minw, minh;
@@ -194,13 +240,13 @@ struct Client
uint frame;
char *fg;
uint resizecorner;
uint bordlight, borddark;
} colors;
/* Client Information by flags */
uint flags;
/* Struct in chains */
Client *next;
Client *prev;
};
/* Simply-linked list */
SLIST_ENTRY(Client) next;
} Client;
/* Keybind Structure */
typedef struct
@@ -221,38 +267,62 @@ typedef struct
uicb_t cmd;
} MouseBinding;
/* InfoBar elements */
typedef struct InfobarElem
{
IbElemType type;
Geo geo;
STAILQ_ENTRY(InfobarElem) next;
} InfobarElem;
/* InfoBar Struct */
typedef struct
{
BarWindow *bar;
BarWindow *tags_board, *tags[MAXTAG];
BarWindow *layout_button;
BarWindow *tags[MAXTAG];
XRectangle geo;
int position;
BarWindow *bar;
STAILQ_HEAD(, InfobarElem) elemhead;
char *elemorder;
Geo geo, selbar_geo;
int screen, position;
char *statustext;
bool need_update;
} InfoBar;
/* Layout Structure */
typedef struct
{
uint flags; /* Flags */
Client *nc; /* New client needing integration */
Client ghost; /* Ghost client to arrange hole in split */
char *symbol;
char *type;
void (*func)(int screen);
} Layout;
/* Systray Structure */
typedef struct Systray
{
Window win;
Geo geo;
SLIST_ENTRY(Systray) next;
} Systray;
/* Tag Structure */
typedef struct
{
char *name;
char **clients;
int nclients;
int layers;
float mwfact;
int nmaster;
Bool resizehint;
Bool request_update;
Bool abovefc;
uint flags;
int barpos;
int prev_barpos;
Layout layout;
uint tagad;
MouseBinding *mouse;
int nmouse;
} Tag;
/* Menu Item Struct */
@@ -261,6 +331,8 @@ typedef struct
char *name;
void (*func)(uicb_t);
uicb_t cmd;
bool (*check)(uicb_t);
char *submenu;
} MenuItem;
/* Menu Struct */
@@ -272,7 +344,8 @@ typedef struct
*/
char *name;
/* Placement */
Bool place_at_mouse;
bool place_at_mouse;
int align;
int x, y;
/* Color */
struct
@@ -292,6 +365,9 @@ typedef struct
char *name;
char *prompt;
char *command;
char histo[HISTOLEN][512];
uint nhisto;
int width;
} Launcher;
/* Button struct */
@@ -301,6 +377,7 @@ typedef struct
XSegment *linecoord;
int nlines;
int nmouse;
uint flags;
} Button;
/* Alias struct */
@@ -310,6 +387,21 @@ typedef struct
char *content;
} Alias;
/* Rule struct */
typedef struct
{
char *class;
char *instance;
char *role;
char *name;
int screen;
int tag;
bool free;
bool max;
bool ignoretags;
bool follow_client;
} Rule;
/* Configuration structure */
typedef struct
{
@@ -318,11 +410,19 @@ typedef struct
/* Misc option */
char *font;
Bool raisefocus;
Bool raiseswitch;
Bool focus_fmouse;
bool use_xft;
uint opacity;
bool raisefocus;
bool focus_fmouse;
bool focus_fmov;
bool focus_pclick;
bool ignore_next_client_rules;
bool tagautohide;
bool tagnamecount;
Tag default_tag;
uint pad;
int status_timing;
char *autostart_path;
char *autostart_command;
struct
{
/*
@@ -332,19 +432,36 @@ typedef struct
uint bar;
char *text;
char *tagselfg;
char *tagurfg;
uint tagurbg;
uint tagselbg;
uint tag_occupied_bg;
char *tag_occupied_fg;
uint tagbord;
char *layout_fg;
uint layout_bg;
float client_light_shade;
float client_dark_shade;
float bar_light_shade;
float bar_dark_shade;
} colors;
struct
{
int height;
MouseBinding *mouse;
int nmouse;
bool selbar;
char *element_order;
} bars;
struct
{
char *fg;
uint bg;
int maxlength;
MouseBinding *mouse;
int nmouse;
} selbar;
struct
{
char *background_command;
MouseBinding *mouse;
@@ -352,17 +469,22 @@ typedef struct
} root;
struct
{
Bool set_new_win_master;
Bool place_at_mouse;
Bool border_shadow;
bool set_new_win_master;
bool place_at_mouse;
bool border_shadow;
bool new_client_get_mouse;
int borderheight;
char *autofree, *automax;
uint bordernormal;
uint borderfocus;
uint resizecorner_normal;
uint resizecorner_focus;
uint mod;
uint padding;
MouseBinding *mouse;
int nmouse;
uint default_open_tag;
int default_open_screen;
} client;
struct
{
@@ -371,7 +493,7 @@ typedef struct
char *fg_focus;
struct
{
Bool active;
bool active;
struct { uint normal, focus; } colors;
} stipple;
MouseBinding *mouse;
@@ -381,24 +503,89 @@ typedef struct
} titlebar;
struct
{
Bool bar;
Bool tag;
Bool layout;
bool bar;
bool tag;
bool layout;
} border;
struct
{
bool active;
int screen;
int spacing;
} systray;
Alias alias[256];
uint mouse_tag_action[TagActionLast];
int layout_button_width;
Layout layout[NUM_OF_LAYOUT];
Menu *menu;
Launcher *launcher;
Rule *rule;
int *ntag;
Bool tag_round;
Bool layout_system; /* Switch: False, Menu: True. */
bool tag_round;
bool tag_auto_prev;
bool client_round;
bool client_auto_center;
bool client_tile_raise;
bool layout_system; /* Switch: False, Menu: True. */
bool keep_layout_geo;
bool cfactor_enable_split;
char *tag_expose_name;
char *expose_layout;
char *selected_layout_symbol;
/* Number of... */
int nkeybind;
int nlayout;
int nmenu;
int nlauncher;
int nrule;
} Conf;
typedef struct
{
int as, de, width, height;
#ifdef HAVE_XFT
XftFont *font;
#endif /* HAVE_XFT */
XFontSet fontset;
} FontStruct;
/* status.c util struct */
typedef struct
{
Geo g;
uint color;
} StatusRec;
typedef struct
{
int x, y, w, h;
uint color;
char data[512];
} StatusGraph;
typedef struct
{
int x, y;
char color[8];
char text[512];
} StatusText;
typedef struct StatusMouse
{
Geo area;
InfoBar *infobar;
uint button;
void (*func)(uicb_t);
uicb_t cmd;
SLIST_ENTRY(StatusMouse) next;
} StatusMouse;
typedef struct
{
int x, y, w, h;
char name[512];
} ImageAttr;
/* Config.c struct */
typedef struct
{
@@ -424,4 +611,10 @@ typedef struct
char *uicb;
} vicmd_to_uicb;
typedef struct
{
int version;
int flags;
} xembed_info;
#endif /* STRUCTS_H */

229
src/systray.c Normal file
View File

@@ -0,0 +1,229 @@
/*
* 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 */
SLIST_INSERT_HEAD(&trayicons, s, next);
return;
}
void
systray_del(Systray *s)
{
if(!conf.systray.active)
return;
SLIST_REMOVE(&trayicons, s, Systray, 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;
while(!SLIST_EMPTY(&trayicons))
{
i = SLIST_FIRST(&trayicons);
SLIST_REMOVE_HEAD(&trayicons, 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;
SLIST_FOREACH(i, &trayicons, 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;
SLIST_FOREACH(i, &trayicons, 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(!SLIST_FIRST(&trayicons))
{
XMoveResizeWindow(dpy, traywin, infobar[conf.systray.screen].bar->geo.width - 1, 0, 1, 1);
return;
}
SLIST_FOREACH(i, &trayicons, 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;
}

650
src/tag.c
View File

@@ -28,7 +28,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wmfs.h"
@@ -39,48 +38,88 @@
void
tag_set(int tag)
{
int otag;
Client *c;
bool al = False;
int i;
if(tag < 0 || tag > MAXTAG)
return;
screen_get_sel();
otag = seltag[selscreen];
if(seltag[selscreen] != tag)
prevseltag[selscreen] = seltag[selscreen];
else if(tag == seltag[selscreen] && tag != prevseltag[selscreen] && conf.tag_auto_prev)
tag = seltag[selscreen] = prevseltag[selscreen];
else
seltag[selscreen] = tag;
if(conf.tag_round)
{
if(tag <= 0)
seltag[selscreen] = conf.ntag[selscreen];
else if(tag > conf.ntag[selscreen])
else if(tag > conf.ntag[selscreen])
seltag[selscreen] = 1;
else
seltag[selscreen] = tag;
}
else
{
if(!tag || tag == seltag[selscreen]
|| tag > conf.ntag[selscreen])
if(!tag || tag > conf.ntag[selscreen])
return;
seltag[selscreen] = tag;
}
ewmh_update_current_tag_prop();
/* Arrange infobar position */
if(tags[selscreen][otag].barpos != tags[selscreen][seltag[selscreen]].barpos)
if(tags[selscreen][prevseltag[selscreen]].barpos != tags[selscreen][seltag[selscreen]].barpos
|| prevseltag[selscreen] == seltag[selscreen])
infobar_set_position(tags[selscreen][seltag[selscreen]].barpos);
arrange(selscreen, False);
if(tags[selscreen][tag].request_update)
/* Check if a layout update is needed with additional tags */
if(tags[selscreen][seltag[selscreen]].tagad)
al = True;
else if(tags[selscreen][seltag[selscreen]].flags & RequestUpdateFlag)
{
tags[selscreen][seltag[selscreen]].layout.func(selscreen);
tags[selscreen][tag].request_update = False;
al = True;
tags[selscreen][seltag[selscreen]].flags &= ~RequestUpdateFlag;
}
/* To focus the first client in the new tag */
for(c = clients; c; c = c->next)
if(c->tag == seltag[selscreen] && c->screen == selscreen)
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 */
SLIST_FOREACH(c, &clients, next)
if(c->tag == MAXTAG + 1 && c->screen == selscreen)
{
al = True;
break;
}
/* To focus selected client of the via focusontag option */
SLIST_FOREACH(c, &clients, next)
if(c->focusontag == tag && c->screen == selscreen)
break;
arrange(selscreen, al);
if(tags[selscreen][tag].flags & RequestUpdateFlag)
{
layout_func(selscreen, tag);
tags[selscreen][tag].flags &= ~RequestUpdateFlag;
}
/* No focusontag option found on any client, try to find the first of the tag */
if(!c)
SLIST_FOREACH(c, &clients, next)
if(c->tag == seltag[selscreen] && c->screen == selscreen)
break;
client_focus((c) ? c : NULL);
@@ -94,24 +133,43 @@ tag_set(int tag)
void
tag_transfert(Client *c, int tag)
{
screen_get_sel();
int s;
CHECK(c);
if(!tag)
screen_get_sel();
if(tag <= 0)
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->screen = selscreen;
if(s != c->screen)
arrange(s, True);
arrange(c->screen, True);
if(c == sel)
client_focus(NULL);
client_focus_next(c);
client_update_attributes(c);
tags[c->screen][tag].request_update = True;
tags[c->screen][tag].flags |= RequestUpdateFlag;
return;
}
@@ -138,6 +196,7 @@ uicb_tag(uicb_t cmd)
void
uicb_tag_next(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
tag_set(seltag[selscreen] + 1);
@@ -151,6 +210,7 @@ uicb_tag_next(uicb_t cmd)
void
uicb_tag_prev(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
tag_set(seltag[selscreen] - 1);
@@ -158,6 +218,184 @@ uicb_tag_prev(uicb_t cmd)
return;
}
/** Set the next visible tag
* \param cmd uicb_t type unused
*/
void
uicb_tag_next_visible(uicb_t cmd)
{
int tag;
Client *c;
uint occupied = 0;
(void)cmd;
screen_get_sel();
if(!conf.tagautohide)
{
tag_set(seltag[selscreen] + 1);
return;
}
SLIST_FOREACH(c, &clients, 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;
}
SLIST_FOREACH(c, &clients, 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;
SLIST_FOREACH(c, &clients, next)
{
if(c->screen == s && c->tag == t1)
c->tag = t2;
else if(c->screen == s && c->tag == 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
* the wanted tag
* \param cmd Wanted tag, uicb_t type
@@ -171,3 +409,373 @@ uicb_tagtransfert(uicb_t cmd)
return;
}
/** Set the previous selected tag
* \param cmd uicb_t type unused
*/
void
uicb_tag_prev_sel(uicb_t cmd)
{
(void)cmd;
screen_get_sel();
tag_set(prevseltag[selscreen]);
return;
}
/** Transfert the selected client to the next tag
* \param cmd uicb_t type unused
*/
void
uicb_tagtransfert_next(uicb_t cmd)
{
CHECK(sel);
int tag = seltag[selscreen] + 1;
(void)cmd;
if(tag > conf.ntag[selscreen])
{
if(!conf.tag_round)
return;
tag = 1;
}
tag_transfert(sel, tag);
return;
}
/** Transfert the selected client to the prev tag
* \param cmd uicb_t type unused
*/
void
uicb_tagtransfert_prev(uicb_t cmd)
{
CHECK(sel);
int tag = seltag[selscreen] - 1;
(void)cmd;
if(tag <= 0)
{
if(!conf.tag_round)
return;
tag = conf.ntag[selscreen];
}
tag_transfert(sel, tag);
return;
}
/** Go to the current urgent tag
*\param cmd uicb_t type unused
*/
void
uicb_tag_urgent(uicb_t cmd)
{
Client *c;
(void)cmd;
/* Check if there is a urgent client */
SLIST_FOREACH(c, &clients, 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;
int i;
memset(&t, 0, sizeof(t));
if(tag < 0 || tag > conf.ntag[s] || conf.ntag[s] == 1)
return;
SLIST_FOREACH(c, &clients, next)
if(c->screen == s && c->tag ==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 < conf.ntag[s] + 1; ++i)
{
/* Set clients tag because of shift */
SLIST_FOREACH(c, &clients, 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(SLIST_FIRST(&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.
*/
#define _GNU_SOURCE
#include "wmfs.h"
/** Calloc with an error message if there is a probleme
* \param element Element
* \param size Size
* \return void pointer
*/
void*
emalloc(uint element, uint size)
/** malloc with error support and size_t overflow protection
* \param nmemb number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xmalloc(size_t nmemb, size_t size)
{
void *ret = calloc(element, size);
void *ret;
if(!ret)
warn("calloc()");
if (SIZE_MAX / nmemb < size)
err(EXIT_FAILURE, "xmalloc(%zu, %zu), "
"size_t overflow detected", nmemb, size);
if ((ret = malloc(nmemb * size)) == NULL)
err(EXIT_FAILURE, "malloc(%zu)", nmemb * size);
return ret;
}
/** calloc with error support
* \param nmemb Number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xcalloc(size_t nmemb, size_t size)
{
void *ret;
if ((ret = calloc(nmemb, size)) == NULL)
err(EXIT_FAILURE, "calloc(%zu * %zu)", nmemb, size);
return ret;
}
/** realloc with error support and size_t overflow check
* \param ptr old pointer
* \param nmemb number of objects
* \param size size of single object
* \return non null void pointer
*/
void *
xrealloc(void *ptr, size_t nmemb, size_t size)
{
void *ret;
if (SIZE_MAX / nmemb < size)
err(EXIT_FAILURE, "xrealloc(%p, %zu, %zu), "
"size_t overflow detected", ptr, nmemb, size);
if ((ret = realloc(ptr, nmemb * size)) == NULL)
err(EXIT_FAILURE, "realloc(%p, %zu)", ptr, nmemb * size);
return ret;
}
/** strdup with error support
* \param str char pointer
* \retun non null void pointer
*/
char *
xstrdup(const char *str)
{
char *ret;
if (str == NULL || (ret = strdup(str)) == NULL)
err(EXIT_FAILURE, "strdup(%s)", str);
return ret;
}
/** asprintf wrapper
* \param strp target string
* \param fmt format
* \return non zero integer
*/
int
xasprintf(char **strp, const char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
ret = vasprintf(strp, fmt, args);
va_end(args);
if (ret == -1)
err(EXIT_FAILURE, "asprintf(%s)", fmt);
return ret;
}
/** Get a color with a string
* \param color Color string
* \return Color pixel
@@ -63,21 +142,6 @@ getcolor(char *color)
return xcolor.pixel;
}
/** Enlight an hexadecimal color
* \param col Color
* \return The clarified color
*/
ulong
color_enlight(ulong col)
{
if((col + 0x330000) < 0xffffff
&& (col + 0x003300) < 0xffffff
&& (col + 0x000033) < 0xffffff)
return col + 0x333333;
else
return col;
}
/** Set the window WM State
* \param win Window target
* \param state WM State
@@ -93,30 +157,16 @@ setwinstate(Window win, long state)
return;
}
/** My strdup. the strdup of string.h isn't ansi compatible..
* Thanks linkdd.
* \param str char pointer
*/
char*
_strdup(const char *str)
{
char *ret = emalloc(strlen(str) + 1, sizeof(char));
strcpy(ret, str);
return ret;
}
/* The following function are for configuration
usage. {{{
*/
void*
name_to_func(char *name, func_name_list_t *l)
name_to_func(char *name, const func_name_list_t *l)
{
int i;
if(name)
for(i = 0; l[i].name ; ++i)
for(i = 0; l[i].name; ++i)
if(!strcmp(name, l[i].name))
return l[i].func;
@@ -150,7 +200,7 @@ char_to_button(char *name, name_to_uint_t blist[])
}
Layout
layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[])
layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[])
{
int i;
@@ -160,84 +210,47 @@ layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[])
return lt[0];
}
char*
alias_to_str(char *conf_choice)
{
int i;
char *tmpchar = NULL;
if(!conf_choice)
return 0;
if(conf.alias)
for(i = 0; conf.alias[i].name; i++)
if(!strcmp(conf_choice, conf.alias[i].name))
tmpchar = conf.alias[i].content;
if(tmpchar)
return _strdup(tmpchar);
else
return _strdup(conf_choice);
return NULL;
}
/* }}} */
/** Get the mouse pointer position.
*/
XRectangle
get_mouse_pos(void)
{
Window dum;
int d, u;
XRectangle ret;
XQueryPointer(dpy, ROOT, &dum, &dum, (int*)&ret.x, (int*)&ret.y, &d, &d, (uint *)&u);
return ret;
}
/** Execute a sh command
* \param cmd Command
* \return child pid
*/
void
pid_t
spawn(const char *format, ...)
{
char *sh = NULL;
char cmd[512];
va_list ap;
if(strlen(format) > 511)
{
warnx("spawn(): Error, command too long.");
return;
}
pid_t pid;
size_t len;
va_start(ap, format);
vsprintf(cmd, format, ap);
len = vsnprintf(cmd, sizeof(cmd), format, ap);
va_end(ap);
if(!strlen(cmd))
return;
if (len >= sizeof(cmd))
{
warnx("command too long (> 512 bytes)");
return -1;
}
if(!(sh = getenv("SHELL")))
sh = "/bin/sh";
if(fork() == 0)
if((pid = fork()) == 0)
{
if(fork() == 0)
{
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execl(sh, sh, "-c", cmd, (char*)NULL);
exit(EXIT_SUCCESS);
}
exit(EXIT_SUCCESS);
if(dpy)
close(ConnectionNumber(dpy));
setsid();
if (execl(sh, sh, "-c", cmd, (char*)NULL) == -1)
warn("execl(sh -c %s)", cmd);
exit(EXIT_FAILURE);
}
else if (pid == -1)
warn("fork");
return;
return pid;
}
/** Swap two pointer.
@@ -262,4 +275,30 @@ void
uicb_spawn(uicb_t cmd)
{
spawn("%s", cmd);
return;
}
/* 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));
}

View File

@@ -1,141 +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"},
{"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,12 @@
#include "wmfs.h"
static volatile bool exiting = False, sig_chld = False;
int
errorhandler(Display *d, XErrorEvent *event)
{
char mess[256];
Client *c;
/* Check if there is another WM running */
if(BadAccess == event->error_code
@@ -48,7 +49,7 @@ errorhandler(Display *d, XErrorEvent *event)
* 42 = X_SetInputFocus
* 28 = X_GrabButton
*/
if((c = client_gb_win(event->resourceid)))
if(client_gb_win(event->resourceid))
if(event->error_code == BadWindow
|| event->request_code == 42
|| event->request_code == 28)
@@ -68,6 +69,8 @@ errorhandler(Display *d, XErrorEvent *event)
int
errorhandlerdummy(Display *d, XErrorEvent *event)
{
(void)d;
(void)event;
return 0;
}
@@ -76,118 +79,96 @@ errorhandlerdummy(Display *d, XErrorEvent *event)
void
quit(void)
{
Client *c;
int i;
size_t i, len;
/* Set the silent error handler */
XSetErrorHandler(errorhandlerdummy);
/* Unmanage all clients */
for(c = clients; c; c = c->next)
while(!SLIST_EMPTY(&clients))
{
Client *c = SLIST_FIRST(&clients);
client_unhide(c);
XReparentWindow(dpy, c->win, ROOT, c->geo.x, c->geo.y);
free(c);
SLIST_REMOVE_HEAD(&clients, next);
}
IFREE(tags);
IFREE(seltag);
free(tags);
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)
XFreeCursor(dpy, cursor[i]);
XFreeGC(dpy, gc_stipple);
infobar_destroy();
IFREE(sgeo);
IFREE(spgeo);
IFREE(infobar);
IFREE(keys);
IFREE(func_list);
IFREE(layout_list);
IFREE(net_atom);
/* BarWindows */
while(!SLIST_EMPTY(&bwhead))
SLIST_REMOVE_HEAD(&bwhead, next);
free(sgeo);
free(spgeo);
free(infobar);
free(keys);
free(net_atom);
/* Clean conf alloced thing */
IFREE(menulayout.item);
free(menulayout.item);
if(conf.menu)
{
for(i = 0; i < LEN(conf.menu); ++i)
IFREE(conf.menu[i].item);
IFREE(conf.menu);
len = LEN(conf.menu);
for(i = 0; i < len; ++i)
free(conf.menu[i].item);
free(conf.menu);
}
IFREE(conf.launcher);
IFREE(conf.ntag);
IFREE(conf.titlebar.mouse);
for(i = 0; i < conf.titlebar.nbutton; ++i)
{
IFREE(conf.titlebar.button[i].mouse);
IFREE(conf.titlebar.button[i].linecoord);
}
free(conf.launcher);
free(conf.rule);
IFREE(conf.bars.mouse);
IFREE(conf.titlebar.button);
IFREE(conf.client.mouse);
IFREE(conf.root.mouse);
free(conf.bars.mouse);
free(conf.selbar.mouse);
free(conf.titlebar.button);
free(conf.client.mouse);
free(conf.root.mouse);
free_conf();
XSync(dpy, False);
XCloseDisplay(dpy);
free(event_handle);
return;
}
void *
thread_process(void *arg)
{
XEvent ev;
/* X event loop */
if(!(int*)arg)
{
while(!exiting && !XNextEvent(dpy, &ev))
getevent(ev);
pthread_exit(0);
}
/* Status checking loop with timing */
else
{
while(!exiting)
{
spawn(status_path);
sleep(conf.status_timing);
}
pthread_exit(0);
}
}
/** WMFS main loop.
*/
void
static void
mainloop(void)
{
XEvent ev;
pthread_t evloop, evstatus;
void *ret;
if(!estatus)
while(!exiting && !XNextEvent(dpy, &ev))
getevent(ev);
else
{
pthread_create(&evloop, NULL, thread_process, "1");
pthread_create(&evstatus, NULL, thread_process, NULL);
(void)pthread_join(evloop, &ret);
(void)pthread_join(evstatus, &ret);
while(!exiting && !XNextEvent(dpy, &ev)) {
if (sig_chld) {
while(waitpid(-1, NULL, WNOHANG) > 0);
sig_chld = False;
}
HANDLE_EVENT(&ev);
}
return;
}
/** Set the exiting variable to True
* for stop the main loop
* \param cmd unused uicb_t
@@ -195,6 +176,7 @@ mainloop(void)
void
uicb_quit(uicb_t cmd)
{
(void)cmd;
exiting = True;
return;
@@ -203,66 +185,70 @@ uicb_quit(uicb_t cmd)
/** Scan if there are windows on X
* for manage it
*/
void
static void
scan(void)
{
uint i, n;
uint n;
XWindowAttributes wa;
Window usl, usl2, *w = NULL;
Atom rt;
int rf, tag = -1, screen = -1, free = -1;
int s, rf, tag = -1, screen = -1, flags = -1, i;
ulong ir, il;
uchar *ret;
Client *c;
s = screen_count();
if(XQueryTree(dpy, ROOT, &usl, &usl2, &w, &n))
for(i = n - 1; i != -1; --i)
if(XGetWindowAttributes(dpy, w[i], &wa)
&& !(wa.override_redirect || XGetTransientForHint(dpy, w[i], &usl))
&& wa.map_state == IsViewable)
{
XGetWindowAttributes(dpy, w[i], &wa);
if(!wa.override_redirect && wa.map_state == IsViewable)
{
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
tag = *ret;
XFree(ret);
}
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
screen = *ret;
XFree(ret);
}
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_ISFREE"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_FLAGS"), 0, 32,
False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
{
free = *ret;
flags = *ret;
XFree(ret);
}
c = client_manage(w[i], &wa, False);
if(tag != -1)
if(tag != -1 && tag != MAXTAG + 1)
c->tag = tag;
if(screen != -1 && screen <= screen_count() - 1)
if(screen != -1 && screen <= s - 1)
c->screen = screen;
if(free != -1)
c->flags |= (free) ? FreeFlag : 0;
if(flags != -1)
c->flags = flags;
client_update_attributes(c);
}
}
/* Set update layout request */
for(c = clients; c; c = c->next)
SLIST_FOREACH(c, &clients, next)
{
if(c->tag > 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 < screen_count(); ++i)
for(i = 0; i < s; ++i)
arrange(i, True);
XFree(w);
@@ -276,11 +262,13 @@ scan(void)
void
uicb_reload(uicb_t cmd)
{
(void)cmd;
quit();
for(; argv_global[0] && argv_global[0] == ' '; ++argv_global);
execlp(argv_global, argv_global, NULL);
/* add -C to always load the same config file */
execvp(argv_global, all_argv);
return;
}
@@ -289,7 +277,7 @@ uicb_reload(uicb_t cmd)
execute when wmfs will be already running).
\return False if wmfs is not running
*/
Bool
bool
check_wmfs_running(void)
{
Atom rt;
@@ -322,15 +310,11 @@ check_wmfs_running(void)
void
exec_uicb_function(char *func, char *cmd)
{
long data[5];
/* Check if wmfs is running (this function is executed when wmfs
is already running normally...) */
if(!check_wmfs_running())
return;
data[4] = True;
XChangeProperty(dpy, ROOT, ATOM("_WMFS_FUNCTION"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)func, strlen(func));
@@ -340,7 +324,7 @@ exec_uicb_function(char *func, char *cmd)
XChangeProperty(dpy, ROOT, ATOM("_WMFS_CMD"), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)cmd, strlen(cmd));
send_client_event(data, "_WMFS_FUNCTION");
ewmh_send_message(ROOT, ROOT, "_WMFS_FUNCTION", 0, 0, 0, 0, True);
return;
}
@@ -348,15 +332,12 @@ exec_uicb_function(char *func, char *cmd)
/** Set statustext
*\param str Statustext string
*/
void
static void
set_statustext(int s, char *str)
{
int i;
long data[5];
char atom_name[64];
data[4] = True;
if(!str)
return;
@@ -369,7 +350,7 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name);
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
}
}
else
@@ -379,37 +360,27 @@ set_statustext(int s, char *str)
XChangeProperty(dpy, ROOT, ATOM(atom_name), ATOM("UTF8_STRING"),
8, PropModeReplace, (uchar*)str, strlen(str));
send_client_event(data, atom_name);
ewmh_send_message(ROOT, ROOT, atom_name, 0, 0, 0, 0, True);
}
return;
}
/** Update status script by ewmh hint
*/
void
update_status(void)
{
long data[5];
if(!check_wmfs_running())
return;
data[4] = True;
send_client_event(data, "_WMFS_UPDATE_STATUS");
return;
}
/** Signal handle function
*/
void
static void
signal_handle(int sig)
{
exiting = True;
quit();
exit(EXIT_SUCCESS);
switch (sig)
{
case SIGQUIT:
case SIGTERM:
exiting = True;
break;
case SIGCHLD:
sig_chld = True;
break;
}
return;
}
@@ -423,12 +394,16 @@ int
main(int argc, char **argv)
{
int i;
char *ol = "csgVS";
char *ol = "cs";
extern char *optarg;
extern int optind;
struct sigaction sa;
argv_global = _strdup(argv[0]);
argv_global = xstrdup(argv[0]);
all_argv = argv;
sprintf(conf.confpath, "%s/"DEF_CONF, getenv("HOME"));
while((i = getopt(argc, argv, "hviSc:s:g:C:V:")) != -1)
while((i = getopt(argc, argv, "hvic:s:C:")) != -1)
{
/* For options who need WMFS running */
@@ -439,13 +414,10 @@ main(int argc, char **argv)
{
case 'h':
default:
printf("usage: %s [-ihvS] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>] [-V <viwmfs cmd]\n"
printf("usage: %s [-ihv] [-C <file>] [-c <uicb function> <cmd> ] [-g <argument>] [-s <screen_num> <string>]\n"
" -C <file> Load a configuration file\n"
" -c <uicb_function> <cmd> Execute an uicb function to control WMFS\n"
" -g <argument> Show information about wmfs status\n"
" -s <screen_num> <string> Set the bar(s) statustext\n"
" -V <viwmfs cmd> Manage WMFS with vi-like command\n"
" -S Update status script\n"
" -h Show this page\n"
" -i Show informations\n"
" -v Show WMFS version\n", argv[0]);
@@ -458,26 +430,16 @@ main(int argc, char **argv)
break;
case 'v':
printf("WMFS version : "WMFS_VERSION"\n"
" Compilation settings :\n"
" - Flags : "WMFS_COMPILE_FLAGS"\n"
" - Linked Libs : "WMFS_LINKED_LIBS"\n"
" - On "WMFS_COMPILE_MACHINE" by "WMFS_COMPILE_BY".\n");
exit(EXIT_SUCCESS);
break;
case 'S':
update_status();
XCloseDisplay(dpy);
printf("wmfs"WMFS_VERSION"\n");
exit(EXIT_SUCCESS);
break;
case 'C':
strcpy(conf.confpath, optarg);
strncpy(conf.confpath, optarg, sizeof(conf.confpath));
break;
case 'c':
exec_uicb_function(argv[2], ((argv[3]) ? argv[3] : NULL));
exec_uicb_function(optarg, argv[optind]);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
@@ -490,17 +452,6 @@ main(int argc, char **argv)
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'g':
getinfo(optarg);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
case 'V':
viwmfs(argc, argv);
XCloseDisplay(dpy);
exit(EXIT_SUCCESS);
break;
}
}
@@ -509,8 +460,12 @@ main(int argc, char **argv)
errx(EXIT_FAILURE, "cannot open X server.");
/* Set signal handler */
(void)signal(SIGTERM, &signal_handle);
(void)signal(SIGINT, &signal_handle);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handle;
sigemptyset(&sa.sa_mask);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
/* Check if an other WM is already running; set the error handler */
XSetErrorHandler(errorhandler);

View File

@@ -1,3 +1,4 @@
/*
* wmfs.h
* Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
@@ -38,28 +39,34 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <time.h>
#include <getopt.h>
#include <dirent.h>
#include <err.h>
#include <pthread.h>
#include <locale.h>
#include <sys/queue.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xft/Xft.h>
/* Local headers */
#include "confparse/confparse.h"
#include "config.h"
#include "structs.h"
/* Optional dependencies */
#ifdef HAVE_XFT
#include <X11/Xft/Xft.h>
#endif /* HAVE_XFT */
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* HAVE_XINERAMA */
@@ -68,6 +75,14 @@
#include <X11/extensions/Xrandr.h>
#endif /* HAVE_XRANDR */
#ifdef HAVE_IMLIB
#include <Imlib2.h>
#endif /* HAVE_IMLIB */
/* Local headers */
#include "parse.h"
#include "structs.h"
/* MACRO */
#define ButtonMask (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
#define MouseMask (ButtonMask | PointerMotionMask)
@@ -76,190 +91,242 @@
#define ROOT RootWindow(dpy, SCREEN)
#define MAXH DisplayHeight(dpy, DefaultScreen(dpy))
#define MAXW DisplayWidth(dpy, DefaultScreen(dpy))
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font->height * 1.5))
#define FHINFOBAR ((font->height - font->descent) + (INFOBARH - font->height) / 2)
#define INFOBARH ((conf.bars.height > 0) ? conf.bars.height : (font.height * 1.5))
#define FHINFOBAR ((font.height - font.de) + (((int)INFOBARH - font.height) >> 1))
#define SHADH (1)
#define SHADC (0x000000) /* 'Cause i don't know how darken a color yet */
#define BORDH conf.client.borderheight
#define TBARH ((conf.titlebar.height < BORDH) ? BORDH : conf.titlebar.height)
#define RESHW (6 * BORDH)
#define BUTTONWH (TBARH / 2)
#define RESHW (6 * (BORDH))
#define BUTTONWH (TBARH >> 1)
#define DEF_CONF ".config/wmfs/wmfsrc"
#define DEF_STATUS ".config/wmfs/status.sh"
#define PAD conf.pad
#define MAXSTATUS (4096)
#define CWIN(win, parent, x, y, w, h, b, mask, col, at) \
do { \
win = XCreateWindow(dpy, (parent), (x), (y), (w), (h), (b), CopyFromParent, \
InputOutput, CopyFromParent, (mask), (at)); \
XSetWindowBackground(dpy, win, (col)); \
} while (/* CONSTCOND */ 0)
} while(/* CONSTCOND */ 0)
#define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + BORDH * 2)
#define FRAMEH(h) ((h) + (BORDH + TBARH))
#define ROUND(x) (float)((x > 0) ? x + (float)0.5 : x - (float)0.5)
#define CHECK(x) if(!(x)) return
#define IFREE(x) if(x) free(x)
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
#define HANDLE_EVENT(e) event_handle[(e)->type](e);
#define ATOM(a) XInternAtom(dpy, (a), False)
#define FRAMEW(w) ((w) + (BORDH << 1))
#define FRAMEH(h) ((h) + (BORDH + TBARH))
#define CHECK(x) if(!(x)) return
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAXCLIST (64)
#define RPOS(x) (x & 1 ? x - 1 : x + 1)
#define LDIR(x) (x < Top)
#define FLAGAPPLY(v, b, f) ((b) ? (v |= (f)) : (v &= ~(f)))
#define INAREA(i, j, a) ((i) >= (a).x && (i) <= (a).x + (a).width && (j) >= (a).y && (j) <= (a).y + (a).height)
/* Cfactor define */
#define CFACTOR_CHECK2(g1, g2, p) (LDIR(p) ? (g1.height == g2.height) : (g1.width == g2.width))
#define CFACTOR_PARENTROW(g1, g2, p) \
(LDIR(p) \
? (p == Left ? (g1.x == g2.x) : (g1.x + g1.width == g2.x + g2.width)) \
: (p == Top ? (g1.y == g2.y) : (g1.y + g1.height == g2.y + g2.height))) \
/* Barwin define, wrappers for simple function */
#define barwin_delete_subwin(bw) XDestroySubwindows(dpy, bw->win)
#define barwin_map_subwin(bw) XMapSubwindows(dpy, bw->win)
#define barwin_unmap_subwin(bw) XUnmapSubwindows(dpy, bw->win)
#define barwin_refresh(bw) XCopyArea(dpy, bw->dr, bw->win, gc, 0, 0, bw->geo.width, bw->geo.height, 0, 0)
#define barwin_map(bw) \
do { \
XMapWindow(dpy, bw->win); \
bw->flags |= MappedFlag; \
} while(/* CONSTCOND */ 0)
#define barwin_unmap(bw) \
do { \
XUnmapWindow(dpy, bw->win); \
bw->flags &= ~MappedFlag; \
} while(/* CONSTCOND */ 0)
/* barwin.c */
BarWindow *barwin_create(Window parent,
int x, int y,
uint w, uint h,
int w, int h,
uint bg, char*fg,
Bool entermask,
Bool stipple,
Bool border);
bool entermask,
bool stipple,
bool border);
void barwin_draw_text(BarWindow *bw, int x, int y, char *text);
void barwin_color_set(BarWindow *bw, uint bg, char *fg);
void barwin_delete(BarWindow *bw);
void barwin_delete_subwin(BarWindow *bw);
void barwin_map(BarWindow *bw);
void barwin_map_subwin(BarWindow *bw);
void barwin_unmap(BarWindow *bw);
void barwin_unmap_subwin(BarWindow *bw);
void barwin_move(BarWindow *bw, int x, int y);
void barwin_resize(BarWindow *bw, uint w, uint h);
void barwin_resize(BarWindow *bw, int w, int h);
void barwin_refresh_color(BarWindow *bw);
void barwin_refresh(BarWindow *bw);
/* draw.c */
void draw_text(Drawable d, int x, int y, char* fg, int pad, char *str);
void draw_rectangle(Drawable dr, int x, int y, uint w, uint h, uint color);
ushort textw(const char *text);
void draw_text(Drawable d, int x, int y, char* fg, char *str);
void draw_rectangle(Drawable dr, int x, int y, int w, int h, uint color);
void draw_graph(Drawable dr, int x, int y, int w, int h, uint color, char *data);
ushort textw(char *text);
/* infobar.c */
void infobar_init(void);
void infobar_draw(int sc);
void infobar_draw_layout(int sc);
void infobar_draw_taglist(int sc);
void infobar_draw_statustext(int sc, char *str);
void infobar_draw_layout(InfoBar *i);
void _infobar_draw(InfoBar *i);
void infobar_draw(InfoBar *i);
void infobar_draw_selbar(InfoBar *i);
void infobar_draw_taglist(InfoBar *i);
void infobar_update_taglist(InfoBar *i);
void infobar_destroy(void);
void infobar_set_position(int pos);
void uicb_infobar_togglepos(uicb_t);
void uicb_infobar_toggledisplay(uicb_t);
void uicb_toggle_tagautohide(uicb_t);
/* cfactor.c */
void cfactor_clean(Client *c);
Geo cfactor_geo(Geo geo, int fact[4], int *err);
void cfactor_set(Client *c, Position p, int fac);
void cfactor_multi_set(Client *c, int fac[4]);
/* Generated with macro {{{ */
void uicb_client_resize_Right(uicb_t cmd);
void uicb_client_resize_Left(uicb_t cmd);
void uicb_client_resize_Top(uicb_t cmd);
void uicb_client_resize_Bottom(uicb_t cmd);
/* }}} */
/* client.c */
void client_attach(Client *c);
void client_configure(Client *c);
void client_detach(Client *c);
void client_above(Client *c);
void client_focus(Client *c);
Client* client_get_next(void);
Client* client_get_prev(void);
Client *client_get_next(void);
Client *client_get_prev(void);
/* client_gb_*() {{{ */
Client* client_gb_win(Window w);
Client* client_gb_frame(Window w);
Client* client_gb_titlebar(Window w);
Client* client_gb_resize(Window w);
Client* client_gb_button(Window w, int *n);
Client* client_gb_pos(Client *c, int x, int y);
/* }}} */
void client_get_name(Client *c);
void client_hide(Client *c);
void client_kill(Client *c);
Bool ishide(Client *c, int screen);
bool ishide(Client *c, int screen);
void client_map(Client *c);
Client* client_manage(Window w, XWindowAttributes *wa, Bool ar);
void client_geo_hints(XRectangle *geo, Client *c);
void client_moveresize(Client *c, XRectangle geo, Bool r);
Client* client_manage(Window w, XWindowAttributes *wa, bool ar);
void client_geo_hints(Geo *geo, Client *c);
void client_moveresize(Client *c, Geo geo, bool r);
void client_maximize(Client *c);
void client_size_hints(Client *c);
void client_swap(Client *c1, Client *c2);
void client_raise(Client *c);
void client_unhide(Client *c);
void client_focus_next(Client *c);
void client_unmanage(Client *c);
void client_unmap(Client *c);
void client_set_wanted_tag(Client *c);
void client_update_attributes(Client *c);
void client_urgent(Client *c, bool u);
Client* client_get_next_with_direction(Client *bc, Position pos);
void uicb_client_raise(uicb_t);
void uicb_client_next(uicb_t);
void uicb_client_prev(uicb_t);
void uicb_client_swap_next(uicb_t);
void uicb_client_swap_prev(uicb_t);
/* Generated with macro {{{ */
void uicb_client_focus_next(uicb_t);
void uicb_client_focus_prev(uicb_t);
void uicb_client_swapsel_next(uicb_t);
void uicb_client_swapsel_prev(uicb_t);
void uicb_client_swapsel_Right(uicb_t);
void uicb_client_swapsel_Left(uicb_t);
void uicb_client_swapsel_Top(uicb_t);
void uicb_client_swapsel_Bottom(uicb_t);
void uicb_client_focus_Right(uicb_t cmd);
void uicb_client_focus_Left(uicb_t cmd);
void uicb_client_focus_Top(uicb_t cmd);
void uicb_client_focus_Bottom(uicb_t cmd);
/* }}} */
void uicb_client_kill(uicb_t);
void uicb_client_screen_next(uicb_t);
void uicb_client_screen_prev(uicb_t);
void uicb_client_screen_set(uicb_t);
void uicb_client_move(uicb_t cmd);
void uicb_client_resize(uicb_t cmd);
void uicb_ignore_next_client_rules(uicb_t cmd);
void uicb_clientlist(uicb_t cmd);
bool uicb_checkclist(uicb_t);
void uicb_client_ignore_tag(uicb_t);
void uicb_client_set_master(uicb_t);
/* ewmh.c */
void ewmh_init_hints(void);
void ewmh_send_message(Window d, Window w, char *atom, long d0, long d1, long d2, long d3, long d4);
long ewmh_get_xembed_state(Window win);
void ewmh_get_number_of_desktop(void);
void ewmh_update_current_tag_prop(void);
void ewmh_get_client_list(void);
void ewmh_get_desktop_names(void);
void ewmh_set_desktop_geometry(void);
void ewmh_set_workarea(void);
void ewmh_manage_net_wm_state(long data_l[], Client *c);
void ewmh_manage_window_type(Client *c);
/* frame.c */
void frame_create(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);
/* config.c */
void init_conf(void);
/* color.c */
uint color_shade(uint, double);
/* event.c */
void buttonpress(XButtonEvent *ev);
void configureevent(XConfigureRequestEvent *ev);
void clientmessageevent(XClientMessageEvent *ev);
void destroynotify(XDestroyWindowEvent *ev);
void enternotify(XCrossingEvent *ev);
void expose(XExposeEvent *ev);
void focusin(XFocusChangeEvent *ev);
void grabkeys(void);
void keypress(XKeyPressedEvent *ev);
void mappingnotify(XMappingEvent *ev);
void maprequest(XMapRequestEvent *ev);
void propertynotify(XPropertyEvent *ev);
void unmapnotify(XUnmapEvent *ev);
void send_client_event(long data[5], char *atom_name);
void getevent(XEvent ev);
void event_make_array(void);
#ifdef HAVE_XRANDR
void xrandrevent(XEvent *e);
#endif /* HAVE_XRANDR */
/* menu.c */
void menu_init(Menu *menu, char *name, int nitem, uint bg_f, char *fg_f, uint bg_n, char *fg_n);
void menu_new_item(MenuItem *mi, char *name, void *func, char *cmd);
void menu_draw(Menu menu, int x, int y);
Bool menu_manage_event(XEvent *ev, Menu *menu, BarWindow *winitem[]);
void menu_focus_item(Menu *menu, int item, BarWindow *winitem[]);
void menu_draw_item_name(Menu *menu, int item, BarWindow *winitem[]);
int menu_get_longer_string(MenuItem *mt, int nitem);
void uicb_menu(uicb_t cmd);
void menu_clear(Menu *menu);
/* launcher.c */
void launcher_execute(Launcher launcher);
void uicb_launcher(uicb_t);
/* mouse.c */
void mouse_dragborder(XRectangle geo, GC g);
void mouse_move_tile_client(Client **c);
void mouse_move_tag_client(Client *c);
void mouse_move(Client *c);
void mouse_resize(Client *c);
void mouse_grabbuttons(Client *c, Bool focused);
void mouse_grabbuttons(Client *c, bool focused);
void uicb_mouse_move(uicb_t);
void uicb_mouse_resize(uicb_t);
/* util.c */
ulong color_enlight(ulong col);
void *emalloc(uint element, uint size);
void *xmalloc(size_t, size_t);
void *xcalloc(size_t, size_t);
void *xrealloc(void *, size_t, size_t);
/* simples wrappers for allocating only one object */
#define zmalloc(size) xmalloc(1, (size))
#define zcalloc(size) xcalloc(1, (size))
#define zrealloc(ptr, size) xrealloc((ptr), 1, (size))
char *xstrdup(const char *);
int xasprintf(char **, const char *, ...);
long getcolor(char *color);
void setwinstate(Window win, long state);
char* _strdup(char const *str);
/* Conf usage {{{ */
void* name_to_func(char *name, func_name_list_t *l);
void* name_to_func(char *name, const func_name_list_t *l);
ulong char_to_modkey(char *name, key_name_list_t key_l[]);
uint char_to_button(char *name, name_to_uint_t blist[]);
Layout layout_name_to_struct(Layout lt[], char *name, int n, func_name_list_t llist[]);
char* alias_to_str(char *conf_choice);
Layout layout_name_to_struct(Layout lt[], char *name, int n, const func_name_list_t llist[]);
/* }}} */
XRectangle get_mouse_pos(void);
char *char_to_str(const char c);
void spawn(const char *str, ...);
pid_t spawn(const char *str, ...);
void swap_ptr(void **x, void **y);
void uicb_spawn(uicb_t);
char* patht(char *path);
int qsort_string_compare (const void * a, const void * b);
/* tag.c */
void tag_set(int tag);
@@ -267,11 +334,28 @@ void tag_transfert(Client *c, int tag);
void uicb_tag(uicb_t);
void uicb_tag_next(uicb_t);
void uicb_tag_prev(uicb_t);
void uicb_tag_next_visible(uicb_t);
void uicb_tag_prev_visible(uicb_t);
void uicb_tagtransfert(uicb_t);
void uicb_tag_prev_sel(uicb_t);
void uicb_tagtransfert_next(uicb_t);
void uicb_tagtransfert_prev(uicb_t);
void uicb_tag_urgent(uicb_t cmd);
void tag_additional(int sc, int tag, int adtag);
void uicb_tag_toggle_additional(uicb_t);
void uicb_tag_swap(uicb_t);
void uicb_tag_swap_next(uicb_t);
void uicb_tag_swap_previous(uicb_t);
void uicb_tag_new(uicb_t);
void uicb_tag_del(uicb_t);
void uicb_tag_rename(uicb_t cmd);
void uicb_tag_last(uicb_t cmd);
void uicb_tag_stay_last(uicb_t cmd);
void uicb_tag_toggle_expose(uicb_t cmd);
/* screen.c */
int screen_count(void);
XRectangle screen_get_geo(int s);
Geo screen_get_geo(int s);
int screen_get_with_geo(int x, int y);
int screen_get_sel(void);
void screen_set_sel(int screen);
@@ -279,22 +363,38 @@ void screen_init_geo(void);
void uicb_screen_select(uicb_t);
void uicb_screen_next(uicb_t);
void uicb_screen_prev(uicb_t);
void uicb_screen_prev_sel(uicb_t);
/* status.c */
void statustext_mouse(char *str, Geo area, InfoBar *infobar);
void statustext_handle(InfoBar *ib);
/* systray.c */
bool systray_acquire(void);
void systray_add(Window win);
void systray_del(Systray *s);
void systray_state(Systray *s);
void systray_freeicons(void);
Systray* systray_find(Window win);
int systray_get_width(void);
void systray_update(void);
/* layout.c */
void arrange(int screen, Bool update_layout);
void freelayout(int screen);
void layoutswitch(Bool b);
void maxlayout(int screen);
void arrange(int screen, bool update_layout);
void layout_func(int screen, int tag);
Client *tiled_client(int screen, Client *c);
void freelayout(int screen);
void layoutswitch(bool b);
void maxlayout(int screen);
/* tile {{{ */
void grid(int screen);
void tile(int screen);
void tile_left(int screen);
void tile_top(int screen);
void tile_bottom(int screen);
void mirror_vertical(int screen);
void mirror_horizontal(int screen);
void layer(int screen);
void grid_vertical(int screen);
void grid_horizontal(int screen);
/* }}} */
void uicb_togglemax(uicb_t);
void uicb_togglefree(uicb_t);
@@ -305,84 +405,107 @@ void uicb_set_nmaster(uicb_t);
void uicb_set_layout(uicb_t);
void uicb_toggle_resizehint(uicb_t);
void uicb_toggle_abovefc(uicb_t cmd);
void uicb_set_layer(uicb_t cmd);
void uicb_set_client_layer(uicb_t cmd);
void layout_set_client_master(Client *c);
void layout_split_client(Client *c, bool p);
void layout_split_apply(Client *c);
void layout_split_arrange_closed(int screen);
void uicb_split_client_vertical(uicb_t);
void uicb_split_client_horizontal(uicb_t);
bool uicb_checkmax(uicb_t);
bool uicb_checkfree(uicb_t);
bool uicb_checklayout(uicb_t);
/* init.c */
void init(void);
void init_root(void);
void init_layout(void);
void init_font(void);
void init_gc(void);
void init_cursor(void);
void init_key(void);
void init_geometry(void);
void init_status(void);
/* getinfo.c */
void getinfo_tag(void);
void getinfo_screen(void);
void getinfo_layout(void);
void getinfo_mwfact(void);
void getinfo_nmaster(void);
void getinfo(char *info);
/* viwmfs.c */
void viwmfs(int argc, char **argv);
/* split.c */
void split_store_geo(int screen, int tag);
void split_set_current(Client *nc, Client *ghost);
void split_apply_current(int screen, int tag);
void split_arrange_closed(Client *ghost);
Geo split_client(Client *c, bool p);
void split_client_fill(Client *c, Geo geo);
void split_client_integrate(Client *c, Client *sc, int screen, int tag);
void split_move_dir(Client *c, Position p);
void uicb_split_toggle(uicb_t cmd);
/* Generated with macro {{{ */
void uicb_split_move_Right(uicb_t);
void uicb_split_move_Left(uicb_t);
void uicb_split_move_Top(uicb_t);
void uicb_split_move_Bottom(uicb_t);
/* }}} */
/* wmfs.c */
int errorhandler(Display *d, XErrorEvent *event);
int errorhandlerdummy(Display *d, XErrorEvent *event);
void quit(void);
void *thread_process(void *arg);
void mainloop(void);
void scan(void);
Bool check_wmfs_running(void);
bool check_wmfs_running(void);
void exec_uicb_function(char *func, char *cmd);
void set_statustext(int s, char *str);
void update_status(void);
void handle_signal(int signum);
void uicb_quit(uicb_t);
void uicb_reload(uicb_t);
/* Variables */
/* Principal */
/* Main */
Display *dpy;
GC gc, gc_stipple;
int selscreen;
int prevselscreen;
Conf conf;
Key *keys;
Bool exiting, estatus;
XRectangle *sgeo;
XRectangle *spgeo;
Geo *sgeo;
Geo *spgeo;
Cursor cursor[CurLast];
char *argv_global, *status_path;
char *argv_global;
char **all_argv;
int xrandr_event;
uint timing;
/* Fonts */
XftFont *font;
FontStruct font;
/* Atoms list */
Atom *net_atom;
Atom trayatom;
/* InfoBar/Tags */
InfoBar *infobar;
Tag **tags;
int *seltag;
int *prevseltag;
Menu menulayout;
/* Important Client */
Client *clients;
/* ClientList */
Menu clientlist;
struct clndx {
char key[4];
Client *client;
} clist_index[MAXCLIST];
/* Client */
SLIST_HEAD(, Client) clients;
Client *sel;
/* Other */
func_name_list_t *func_list;
func_name_list_t *layout_list;
/* Event */
int nevent;
void (**event_handle)(XEvent*);
extern const func_name_list_t func_list[];
extern const func_name_list_t layout_list[];
uint numlockmask;
/* Systray */
SLIST_HEAD(, Systray) trayicons;
Window traywin;
int tray_width;
/* BarWindow */
SLIST_HEAD(, BarWindow) bwhead;
/* Status */
SLIST_HEAD(, StatusMouse) smhead;
#endif /* WMFS_H */

8
wmfs.1
View File

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

View File

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

View File

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

475
wmfsrc Normal file
View File

@@ -0,0 +1,475 @@
#
# 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 = true
opacity = 255
# focus_pointer_click: click on unfocused client area:
# true -- default, set focus
# false -- click go to client; including dockapps
focus_pointer_click = true
[/misc]
[bar]
bg = "#191919"
fg = "#D4D4D4"
border = true
#height = "-1"
light_shade = 0.10
dark_shade = -0.10
# Order of infobar elements:
# t = Tag list
# l = Layout button
# s = Selbar
elements_order = "tls"
[systray]
# Enable/disable systray
active = true
# 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"
# 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]
[/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]

256
wmfsrc.in
View File

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