Compare commits

...

128 commits

Author SHA1 Message Date
2a7e15ea63
feat: applay notitle patch 2023-11-20 01:52:33 +02:00
23e9813c88 refactor: remove the spawn function declation 2023-11-20 01:50:07 +02:00
9b9fd452f2 feat(keys): update the keybindings 2023-11-20 01:50:07 +02:00
faa9d49509 chore: remove the screenshots dir 2023-11-20 01:50:07 +02:00
2c9716c05f chore: remove the patches dir 2023-11-20 01:50:07 +02:00
bec37f54b7 refactor: delete mouse.c 2023-11-20 01:50:07 +02:00
6bfa127871 feat: incress the factor of master area to 60% 2023-11-20 01:50:07 +02:00
43871cc01e feat(colorscheme): merge the gruvbox theme with the config 2023-11-20 01:50:07 +02:00
6a38e1171d chore: re-organize code 2023-11-20 01:50:07 +02:00
3ad6c14c6d fix(colorschemme): use darker forground 2023-11-20 01:50:07 +02:00
0dce78d77f feat(spawn): remove the spawn function
Window Manager is just to manage the windows, nothing else.
2023-11-20 01:50:07 +02:00
ab0aea1d09 refactor: re-organize 2023-11-20 01:50:07 +02:00
c09bde1f8d core(pkg): remove the aur package
It has a separate repo
2023-11-20 01:50:07 +02:00
7ddb9c82bf refactor: re-organize 2023-11-20 01:49:57 +02:00
mergify[bot]
c282e960fc
Merge pull request #26 from 0xyosef/applay-notitle-patch
applay notitle patch
2023-09-14 16:37:12 +00:00
YosefJoo
9df191bd1f
applay notitle patch 2023-09-14 09:49:38 +03:00
mergify[bot]
306b3149d8
Merge pull request #23 from archy-linux/renovate/actions-checkout-4.x
chore(deps): update actions/checkout action to v4
2023-09-05 21:24:52 +00:00
renovate[bot]
97133f2383
chore(deps): update actions/checkout action to v4 2023-09-05 05:57:43 +00:00
dd8295212a
fix: update the wm name length 2023-09-02 12:25:25 +03:00
46705d8d43
chore(version): bump the major version 2023-08-30 08:34:08 +03:00
97055fdf2f
feat(keys): update the keybindings 2023-08-30 08:27:53 +03:00
1b6ddb9726
Merge pull request #22 from archy-linux/patch/unpatch-keychain
patch/unpatch keychain
2023-08-30 08:12:32 +03:00
139e337b91
revert(keys): un-apply keychain patch 2023-08-30 08:11:12 +03:00
1adcb169c3
revert(keys): remove the useless keybindings 2023-08-30 07:26:54 +03:00
a6cec51475
feat(dwm): complete rebranding (dwm -> archy-dwm) 2023-08-30 06:42:11 +03:00
5e4a0bb79b
feat(theme): use gurvbox dark hard color scheme 2023-08-30 06:40:12 +03:00
8fbfe9006d
feat(rules): remove the discord rule, i just wanna be abel to open it in any tag 2023-08-30 06:38:06 +03:00
f8a0930e65
feat(terminal): use st 2023-08-30 06:34:57 +03:00
d785d51e2d
[improve] Improve the PKGBUILD 2023-05-11 22:41:01 +03:00
d86ffd3813
[deploy] Add the git aur submodule 2023-05-11 22:27:34 +03:00
feb819c903
[deploy] Add the aur submodule 2023-05-11 22:03:06 +03:00
453b07f4d6
[vcs] ignore the dist dir 2023-05-11 21:51:29 +03:00
f367518443
[fix/add] improve the dist task 2023-05-11 21:46:45 +03:00
fa1aa3e444
[fix/add] improve the dist task and create the archy-dwm.desktop task 2023-05-11 21:16:12 +03:00
8f4a20dd4e
[fix/debloy] set the version 2023-05-11 19:02:33 +03:00
38d85133c4 Merge branch 'master' of github.com:archy-linux/archy-dwm 2023-05-11 18:59:23 +03:00
5e289b8438
[fix/update] Update the slstatus name 2023-05-11 18:52:06 +03:00
952526f495
[doc] Add the mirror actions badges 2023-05-11 18:35:58 +03:00
fd829d6d88
[ci/fix] Fix yaml 2023-05-11 18:26:35 +03:00
8d49ee09de
[ci] Seprate the mirror action 2023-05-11 18:18:47 +03:00
540a9eff7f
[doc] Update the readme 2023-05-11 14:14:46 +03:00
89adca6574
Merge pull request #19 from archy-linux/change-binary-name
change binary name
2023-05-11 14:05:20 +03:00
53da160f0a
[update] Change the binary file name from yo-dwm to archy-dwm 2023-05-11 14:04:24 +03:00
7208347361
Merge pull request #18 from archy-linux/change-binary-name
change the binary name
2023-05-11 14:02:20 +03:00
7baddde619
[clean] Remove the cmake garbage 2023-05-11 13:43:13 +03:00
f3b2844966
[improve] Move the makefile into the prolect scope 2023-05-11 03:22:27 +03:00
a86f296efc
[update] Remove the unsercy atuo start programs 2023-05-11 02:18:04 +03:00
0a99c90162
[doc] Update the readme 2023-05-11 02:06:09 +03:00
75ec761539
[fix] Remove the outdated color.h from CMakeLists.txt 2023-05-11 01:59:46 +03:00
8c61745f12
Merge pull request #17 from anas-elgarhy/change-binary-name
[update] Change the binary file name from `dwm` to `yo-dwm`
2023-05-11 01:53:15 +03:00
55540e5b4f
[update] Change the binary file name from dwm to yo-dwm 2023-05-11 01:49:12 +03:00
cfaef82513
[fix] fix the helpers scripts path 2023-05-10 02:55:06 +03:00
0aa1ecc3ef
[update] Make the status bar at the bottom and make the font even smaller and remove the unproper autostart programs 2023-05-10 02:45:18 +03:00
7d4a8b9999
[config/update] Update setxkbmap options 2023-04-29 16:34:48 +02:00
248f2db087
[config/update] Just add picom to autostat array 2023-04-29 16:27:42 +02:00
a23133608a
[update] Use the dracula theam 2023-04-17 08:25:20 +02:00
639c18a095
Return the mod key to the super key agine :) 2023-03-04 12:12:51 +02:00
19e9f24391
Merge branch 'master' of github.com:anas-elgarhy/yo-dwm 2023-03-01 12:24:42 +02:00
cd8f5d4709
Update cmus startup command for convenience 2023-03-01 12:23:49 +02:00
mergify[bot]
c3cf0921ca
Merge pull request #14 from anas-elgarhy/renovate/configure
Configure Renovate
2023-03-01 09:59:38 +00:00
3d3786d1e6
Remove outdated keybindings section from README.md 2023-03-01 11:57:49 +02:00
706bf5e4fb
Remove screenshots from README.md 2023-03-01 11:57:11 +02:00
cb6f0a2a8d
Merge remote-tracking branch 'origin/master' 2023-03-01 11:49:10 +02:00
0a5df92d57
Update modifier key to Caps Lock 2023-03-01 11:46:36 +02:00
8b3f357191
Merge pull request #15 from anas-elgarhy/mergify/anas-elgarhy/config-update
ci(Mergify): configuration update
2023-01-29 00:26:22 +02:00
4cf5dccdf0 ci(Mergify): configuration update
Signed-off-by: Anas Elgarhy <anas.elgarhy.dev@gmail.com>
2023-01-29 00:25:59 +02:00
renovate[bot]
0f989c8121
Add renovate.json 2023-01-28 21:56:17 +00:00
e18c162967 Fix some worinnigs 2022-11-01 19:48:08 +02:00
989751701d Improve the keybindings :} 2022-11-01 19:47:19 +02:00
37ce41dd6d Add more rules :n 2022-11-01 18:26:31 +02:00
5bb7487b40 Remove unused keys :) 2022-11-01 14:09:23 +02:00
20b68c338c Add spotify rule 2022-11-01 14:08:42 +02:00
Anas Elgarhy
0f72e5c31c
Merge pull request #13 from anas-elgarhy/improve-code
Improve the code and re format it :]
2022-10-31 19:29:07 +02:00
66047b2404 Remove the webbrowser macro 2022-10-31 19:25:39 +02:00
40b65a0171 Fixx the rules :P 2022-10-31 19:10:19 +02:00
5c398adf74 Remove garbage files 2022-10-31 17:19:51 +02:00
a7d9d11968 Add dracula theme and fix the rules 2022-10-31 17:08:04 +02:00
99f899be42 Create a basice run configration 2022-10-31 16:05:04 +02:00
50e80e07ed :\ 2022-10-31 15:44:30 +02:00
46dc9cead8 Create git ignore file :U 2022-10-31 15:40:19 +02:00
6eb5fee7de Remove the garbage files :) 2022-10-31 15:35:46 +02:00
6099f19a49 More format and more improve :D 2022-10-31 15:25:39 +02:00
44f85c76ec Improve yoo 2022-10-31 13:32:01 +02:00
0f156ff3a9 Improve the code and reformat it 2022-10-31 07:53:51 +02:00
Hiltjo Posthuma
ba56fe9fea Revert "Remove dmenumon variable"
This reverts commit c2b748e793.

Revert back this change. It seems to not be an edge-case anymore since
multiple users have asked about this new behaviour now.
2022-10-28 16:37:56 +02:00
59fa9423b5 Update stuff :) 2022-10-27 19:34:21 +02:00
c3cc2c4567 Remove the garbage files 2022-10-27 17:57:09 +02:00
b1e403689f Merge branch 'master' of git://git.suckless.org/dwm 2022-10-27 17:54:10 +02:00
Hiltjo Posthuma
50ad171eea bump version to 6.4 2022-10-04 19:35:13 +02:00
9cf8ec6fa8 Merge branch 'master' of git://git.suckless.org/dwm 2022-09-26 16:36:10 +02:00
Hiltjo Posthuma
970f376973 remove workaround for a crash with color emojis on some systems, now fixed in libXft 2.3.5
https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS
2022-09-17 15:32:41 +02:00
3d6ccec653 Use cmus-rpc-rs yoo 🥰 2022-08-31 16:12:07 +02:00
Stein
c2b748e793 Remove dmenumon variable
Reasoning: Since 2011 dmenu has been capable of working out which
monitor currently has focus in a Xinerama setup, making the use
of the -m flag more or less redundant.

This is easily demonstrated by using dmenu in any other window
manager.

There used to be a nodmenu patch that provided these changes:
https://git.suckless.org/sites/commit/ed68e3629de4ef2ca2d3f8893a79fb570b4c0cbc.html

but this was removed on the basis that it was very easy to work
out and apply manually if needed.

The proposal here is to remove this dependency from dwm. The
mechanism of the dmenumon variable could be provided via a patch
if need be.

The edge case scenario that dmenu does not handle on its own, and
the effect of removing this mechanism, is that if the user trigger
focusmon via keybindings to change focus to another monitor that
has no clients, then dmenu will open on the monitor containing the
window with input focus (or the monitor with the mouse cursor if
no windows have input focus).

If this edge case is important to cover then this can be addressed
by setting input focus to selmon->barwin in the focus function if
there is no client to give focus to (rather than giving focus back
to the root window).
2022-08-28 11:39:43 +02:00
NRK
84d7322113 config.def.h: make keys and buttons const
pretty much all other variables are declared as const when they're not
modified.
2022-08-19 11:47:22 +02:00
Stein
5799dd1fca Remove blw variable in favour of calculating the value when needed
The purpose and reasoning behind the bar layout width (blw) variable
in dwm the way it is today may not be immediately obvious.

The use of the variable makes more sense when looking at commit
2ce37bc from 2009 where blw was initialised in the setup function
and it represented the maximum of all available layout symbols.

	for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
		w = TEXTW(layouts[i].symbol);
		blw = MAX(blw, w);
	}

As such the layout symbol back then was fixed in size and both drawbar
and buttonpress depended on this variable.

The the way the blw variable is set today in drawbar means that it
merely caches the size of the layout symbol for the last bar drawn.

While unlikely to happen in practice it is possible that the last bar
drawn is not that of the currently selected monitor, which can result
in misaligned button clicks if there is a difference in layout symbol
width between monitors.
2022-08-17 13:33:57 +02:00
Stein
44adafe006 Make floating windows spawn within the monitor's window area
This is a follow-up on this thread:
https://lists.suckless.org/hackers/2208/18462.html

The orginal code had constraints such that if a window's starting
attributes (position and size) were to place the window outside of
the edges of the monitor, then the window would be moved into view
at the closest monitor edge.

There was an exception to this where if a top bar is used then the
window should not obscure the bar if present, which meant to place
the window within the window area instead.

The proposed change here makes it the general rule that floating
windows should spawn within the window area rather than within the
monitor area. This makes it simple and consistent with no
exceptions and it makes the intention of the code clear.

This has the benefit of making the behaviour consistent regardless
of whether the user is using a top bar or a bottom bar.

Additionally this will have an effect on patches that modify the
size of the window area. For example if the insets patch is used to
reserve space on the left hand side of the monitor for a dock or a
vertical bar then new floating clients will not obscure that area.
2022-08-12 09:02:34 +02:00
Stein
a859676ead Simplify client y-offset correction
The reasoning behind the original line may be lost to time as
it does not make much sense checking the position on the x-axis
to determine how to position the client on the y-axis.

In the context of multi-monitor setups the monitor y position
(m->my) may be greater than 0 (say 500), in which case the window
could be placed out of view if:
   - the window attributes have a 0 value for the y position and
   - we end up using the y position of bh (e.g. 22)

If the aim is to avoid a new floating client covering the bar then
restricting y position to be at least that of the window area
(m->wy) should cover the two cases of using a top bar and using a
bottom bar.
2022-08-10 15:31:21 +02:00
Hiltjo Posthuma
e0dee91145 sync code-style patch from libsl 2022-08-08 10:43:09 +02:00
NRK
5e76e7e21d code-style: simplify some checks
main change here is making the `zoom()` logic saner. the rest of the
changes are just small stuff which accumulated on my local branch.

pop() must not be called with NULL. and `zoom()` achieves this, but in a
very (unnecessarily) complicated way:

if c == NULL then nexttiled() will return NULL as well, so we enter this
branch:

	if (c == nexttiled(selmon->clients))

in here the !c check fails and the function returns before calling pop()

		if (!c || !(c = nexttiled(c->next)))
			return;

however, none of this was needed. we can simply return early if c was NULL.
Also `c` is set to `selmon->sel` so we can use `c` in the first check
instead which makes things shorter.
2022-08-06 16:09:01 +02:00
eb4c01d478 Change the main terminal from alacritty -> kitty 🥰 2022-08-05 21:44:03 +02:00
explosion-mental
5b2e5e7a40 spawn: reduce 2 lines, change fprintf() + perror() + exit() to die("... :")
when calling die and the last character of the string corresponds to
':', die() will call perror(). See util.c

Also change EXIT_SUCCESS to EXIT_FAILURE
2022-08-02 18:08:51 +02:00
Stein
786f6e2a6f unmanage: stop listening for events for unmanaged windows
This is in particular to avoid flickering in dwm (and high CPU usage)
when hovering the mouse over a tabbed window that was previously
managed by dwm.

Consider the following two scenarios:

1)

We start tabbed (window 0xc000003), tabbed is managed by the
window manager.
We start st being embedded into tabbed.

$ st -w 0xc000003

What happens here is that:
   - tabbed gets a MapRequest for the st window
   - tabbed reparents the st window
   - tabbed will receive X events for the window

The window manager will have no awareness of the st window and the
X server will not send X events to the window manager relating to
the st window.

There is no flickering or any other issues relating to focus.

2)

We start tabbed (window 0xc000003), tabbed is managed by the
window manager.
We start st as normal (window 0xd400005).

What happens here is that:
   - the window manager gets a MapRequest for the st window
   - dwm manages the st window as a normal client
   - dwm will receive X events for the window

Now we use xdotool to trigger a reparenting of the st window into
tabbed.

$ xdotool windowreparent 0xd400005 0xc000003

What happens here is that:
   - tabbed gets a MapRequest for the st window
   - tabbed reparents the st window
   - the window manager gets an UnmapNotify
   - the window manager no longer manages the st window
   - both the window manager and tabbed will receive X events
     for the st window

In dwm move the mouse cursor over the tabbed window.

What happens now is that:
   - dwm will receive a FocusIn event for the tabbed window
   - dwm will set input focus for the tabbed window
   - tabbed will receive a FocusIn event for the main window
   - tabbed will give focus to the window on the currently selected
     tab
   - which again triggers a FocusIn event which dwm receives
   - dwm determines that the window that the FocusIn event is for
     (0xd400005) is not the currently selected client (tabbed)
   - dwm sets input focus for the tabbed window
   - this causes an infinite loop as long as the mouse cursor hovers
     the tabbed window, resulting in flickering and high CPU usage

The fix here is to tell the X server that we are no longer interested
in receiving events for this window when the window manager stops
managing the window.
2022-08-02 18:04:56 +02:00
202d939a66
Merge pull request #11 from anas-elgarhy/fix-freez-issue
Fix freez issue
2022-08-02 12:00:52 +02:00
4ecc0d3c9e
Merge pull request #12 from anas-elgarhy/revert-9-revert-8-fix-freez-issue
Revert "Revert "Fix freez issue""
2022-08-02 12:00:18 +02:00
Anas Elgarhy
d1afe016d7
Revert "Revert "Fix freez issue"" 2022-08-02 11:59:09 +02:00
Anas Elgarhy
55e33220a7
Merge pull request #10 from anas-elgarhy/applay-keychain-patch
Fix the table
2022-08-02 11:56:36 +02:00
9260a252e1 Fix table 🥰 2022-08-02 11:51:05 +02:00
e19cff5a96
Merge pull request #9 from anas-elgarhy/revert-8-fix-freez-issue
Revert "Fix freez issue"
2022-08-01 18:58:25 +02:00
Anas Elgarhy
1ef2014240
Revert "Fix freez issue" 2022-08-01 18:58:03 +02:00
1e36145313
Merge pull request #8 from anas-elgarhy/fix-freez-issue
Fix freez issue
2022-08-01 18:56:42 +02:00
c3c5da0ae4
Merge pull request #7 from anas-elgarhy/applay-keychain-patch
Replace the keychord patch with keychain patch
2022-08-01 18:50:57 +02:00
0d2fe14e25 Test only 2022-07-31 12:48:12 +02:00
fbaab1bbe3 Up the version 🥰 2022-07-31 05:52:37 +02:00
aa5d8a8c22 🥰 2022-07-30 17:42:37 +02:00
5d3af206be Delete keychord diff file 🗑 2022-07-28 12:22:42 +02:00
b726853f33 Applay applay keychain patch 🥰 2022-07-28 12:04:30 +02:00
138bb0bb41 Merge branch 'fix-freez-issue' into applay-keychain-patch 2022-07-28 09:36:17 +02:00
0c224e26f6 Merge add stuff branch 2022-07-28 09:32:55 +02:00
11f2af9ce1 Merge branch 'update-stuff' into fix-freez-issue
# Conflicts:
#	src/keys/keys.c
2022-07-28 09:31:15 +02:00
25a26c2a9e Add the diff file 2022-07-28 08:15:53 +02:00
214668b975 Reove keyChord patch 2022-07-28 08:08:20 +02:00
bf3ce283ca o_o 2022-07-28 05:29:35 +02:00
8eafb095d2 Improve emoji picker command 🥰 2022-07-24 18:00:13 +02:00
71981a7941 Change mode + shift + f -> r to ... -> t for open the ranger 😀 2022-07-24 17:55:33 +02:00
2d0dd05de5 Create refrences section 🥰 2022-07-24 17:45:13 +02:00
c089ee61e3 Add screet tag key ㊙️ 2022-07-24 17:39:02 +02:00
6288fd7d0c Lock the screen whin press on XF86XK_Suspend key 2022-07-24 17:37:15 +02:00
Hiltjo Posthuma
e03248a4d5 Revert "do not call signal-unsafe function inside sighanlder"
This reverts commit 6613d9f9a1.

Discussed on the mailinglist:
https://lists.suckless.org/hackers/2207/18405.html
2022-07-22 09:18:52 +02:00
65 changed files with 3913 additions and 6351 deletions

17
.github/workflows/bitbucket-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to bitbucket
on: [push]
jobs:
bitbucket-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in bitbucket
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://anas-elgarhy@bitbucket.org/anas_elgarhy/archy-dwm.git'
REMOTE_NAME: bitbucket
GIT_USERNAME: anas_elgarhy
GIT_PASSWORD: ${{ secrets.BITBUCKET_TOKEN }}

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: install libs - name: install libs
run: sudo apt-get install libxinerama1 libxinerama-dev run: sudo apt-get install libxinerama1 libxinerama-dev
- name: make install test - name: make install test

17
.github/workflows/codeberg-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to codeberg
on: [push]
jobs:
codeberg-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in codeberg
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://codeberg.org/archy-linux/archy-dwm.git'
REMOTE_NAME: codeberg
GIT_USERNAME: anas-elgarhy
GIT_PASSWORD: ${{ secrets.CODEBERG_TOKEN }}

17
.github/workflows/disroot-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to disroot
on: [push]
jobs:
disroot-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in git.disroot
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://git.disroot.org/archy-linux/archy-dwm.git'
REMOTE_NAME: disroot
GIT_USERNAME: anas-elgarhy
GIT_PASSWORD: ${{ secrets.DISROOT_TOKEN }}

17
.github/workflows/gitdab-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to Gitdab
on: [ push ]
jobs:
gitdab-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in Gitdab
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://gitdab.com/archy-linux/archy-dwm.git'
REMOTE_NAME: gitdab
GIT_USERNAME: anas-elgarhy
GIT_PASSWORD: ${{ secrets.GITDAB_TOKEN }}

17
.github/workflows/gitea-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to Gitea
on: [ push ]
jobs:
gitea-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in Gitea
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://gitea.com/archy-linux/archy-dwm.git'
REMOTE_NAME: gitea
GIT_USERNAME: anas-elgarhy
GIT_PASSWORD: ${{ secrets.GITEA_TOKEN }}

16
.github/workflows/gitlab-mirror.yml vendored Normal file
View file

@ -0,0 +1,16 @@
name: Mirror the repo to gitlab
on: [push]
jobs:
gitlab-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in gitlab
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://gitlab.com/archy-linux/archy-dwm'
GIT_USERNAME: Anas-Elgarhy
GIT_PASSWORD: ${{ secrets.GITLAP_TOKEN }}

View file

@ -1,39 +0,0 @@
# This is a basic workflow that is manually triggered
name: Mirror repo
on: [push]
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in gitlab
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://gitlab.com/anas-elgarhy/dwm-anas.git'
GIT_USERNAME: Anas-Elgarhy
GIT_PASSWORD: ${{ secrets.GITLAP_TOKEN }}
# - name: mirror in bitbucket
# uses: actions/checkout@v3
# with:
# fetch-depth: 0
# - uses: yesolutions/mirror-action@master
# with:
# REMOTE: 'https://anas_elgarhy@bitbucket.org/anas_elgarhy/dwm-anas.git'
# REMOTE_NAME: bitbucket
# GIT_USERNAME: anas_elgarhy
# GIT_PASSWORD: ${{ secrets.BITBUCKET_TOKEN }}
- name: mirror in codeberg
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://codeberg.org/anas-elgarhy/dwm-anas.git'
REMOTE_NAME: codeberg
GIT_USERNAME: anas-elgarhy
GIT_PASSWORD: ${{ secrets.CODEBERG_TOKEN }}

17
.github/workflows/pagure-mirror.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Mirror the repo to pagure
on: [ push ]
jobs:
gitdab-mirror:
runs-on: ubuntu-latest
steps:
- name: mirror in Gitdab
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yesolutions/mirror-action@master
with:
REMOTE: 'https://gitdab.com/archy-linux/archy-dwm.git'
REMOTE_NAME: gitdab
GIT_USERNAME: anas-elgarhy

69
.gitignore vendored
View file

@ -1,3 +1,68 @@
*.o ### C template
dwm # Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### CMake template
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
build/
dist/

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "archpackage/archy-dwm/archy-dwm-aur"]
path = archpackage/archy-dwm/archy-dwm-aur
url = ssh://aur@aur.archlinux.org/archy-dwm.git
[submodule "archpackage/archy-dwm-git/archy-dwm-git-aur"]
path = archpackage/archy-dwm-git/archy-dwm-git-aur
url = ssh://aur@aur.archlinux.org/archy-dwm-git.git

7
.mergify.yml Normal file
View file

@ -0,0 +1,7 @@
pull_request_rules:
- name: Automatic merge on approval
conditions:
- "#approved-reviews-by>=1"
actions:
merge:
method: merge

72
Makefile Normal file
View file

@ -0,0 +1,72 @@
# dwm - dynamic window manager
# See LICENSE file for copyright and license details.
include config.mk
SRC = src/drw.c src/archy_dwm.c src/util.c
OBJ_DIR = build
OBJ = ${SRC:%.c=$(OBJ_DIR)/%.o}
BUILD_DIR = ${OBJ_DIR}/archy-dwm
all: options ${BUILD_DIR}
options:
@echo archy-dwm build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
${OBJ_DIR}/%.o: %.c
mkdir -p $(@D)
${CC} -c ${CFLAGS} $< -o $@
${OBJ}: src/config/config.h config.mk
config.h:
cp config.def.h $@
${BUILD_DIR}: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
rm -rf ${OBJ_DIR}
dist: ${BUILD_DIR} archy-dwm.desktop
mkdir -p archy-dwm_${VERSION}
cp -R LICENSE README.md ${BUILD_DIR} ${OBJ_DIR}/archy-dwm.desktop archy-dwm.1 dwm.png archy-dwm_${VERSION}
tar -cf archy-dwm_${VERSION}.tar archy-dwm_${VERSION}
gzip archy-dwm_${VERSION}.tar
rm -rf archy-dwm_${VERSION}
mkdir -p dist
mv archy-dwm_${VERSION}.tar.gz dist
echo "The tarball is ready."
printf "Tarball size: %s\n" $$(du -h dist/archy-dwm_${VERSION}.tar.gz | cut -f1)
printf "Tarball hash: %s\n" $$(sha256sum dist/archy-dwm_${VERSION}.tar.gz)
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${BUILD_DIR} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/archy-dwm
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < archy-dwm.1 > ${DESTDIR}${MANPREFIX}/man1/archy-dwm.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/archy-dwm.1
archy-dwm.desktop:
mkdir -p "$(OBJ_DIR)"
echo "[Desktop Entry]" > "$(OBJ_DIR)/archy-dwm.desktop"
echo "Type=XSession" >> "$(OBJ_DIR)/archy-dwm.desktop"
echo "Exec=$(DESTDIR)$(PREFIX)/bin/archy-dwm" >> "$(OBJ_DIR)/archy-dwm.desktop"
echo "DesktopNames=archy-dwm" >> "$(OBJ_DIR)/archy-dwm.desktop"
echo "Name=archy-dwm" >> "$(OBJ_DIR)/archy-dwm.desktop"
echo "Comment=\"A dynamic window manager for X\"" >> "$(OBJ_DIR)/archy-dwm.desktop"
desktop: archy-dwm.desktop
mkdir -p ${DESTDIR}${PREFIX}/share/xsessions
cp "$(OBJ_DIR)/archy-dwm.desktop" ${DESTDIR}${PREFIX}/share/xsessions/archy-dwm.desktop
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/archy-dwm \
${DESTDIR}${MANPREFIX}/man1/archy-dwm.1 \
${DESTDIR}${PREFIX}/share/xsessions/archy-dwm.desktop
.PHONY: all options clean dist install uninstall

48
README
View file

@ -1,48 +0,0 @@
dwm - dynamic window manager
============================
dwm is an extremely fast, small, and dynamic window manager for X.
Requirements
------------
In order to build dwm you need the Xlib header files.
Installation
------------
Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if
necessary as root):
make clean install
Running dwm
-----------
Add the following line to your .xinitrc to start dwm using startx:
exec dwm
In order to connect dwm to a specific display, make sure that
the DISPLAY environment variable is set correctly, e.g.:
DISPLAY=foo.bar:1 exec dwm
(This will start dwm on display :1 of the host foo.bar.)
In order to display status info in the bar, you can do something
like this in your .xinitrc:
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
do
sleep 1
done &
exec dwm
Configuration
-------------
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.

144
README.md
View file

@ -1,141 +1,35 @@
# Anas Elgarhy's dwm # archy-dwm
## My fork from dwm 🍴, with a lot of beautiful patches 🥰 ## DWM but cleaner and more usable
![dwm screenshot](./screenshots/dwm-6.3-0.1.0.png) ### Patches
![dwm and 2 alacritty](./screenshots/dwm_bpytop_and_ufetch_tile_layout-6.3-0.1.0.png)
![dwm and alacritty](./screenshots/dwm_alacritty-6.3-0.1.0.png)
![dwm and alacritty and cmus and cava](./screenshots/dwm_alacritty_cmus_cava-6.3-0.1.1.png)
### Applayed patches:
- [alwayscenter](https://dwm.suckless.org/patches/alwayscenter) - [alwayscenter](https://dwm.suckless.org/patches/alwayscenter)
- [cool autostart](https://dwm.suckless.org/patches/cool_autostart) - [cool autostart](https://dwm.suckless.org/patches/cool_autostart)
- [fullscreen](https://dwm.suckless.org/patches/fullscreen) - [fullscreen](https://dwm.suckless.org/patches/fullscreen)
- [gridmode](https://dwm.suckless.org/patches/gridmode) - [gridmode](https://dwm.suckless.org/patches/gridmode)
- [keychord](https://dwm.suckless.org/patches/keychord)
- [movestack](https://dwm.suckless.org/patches/movestack) - [movestack](https://dwm.suckless.org/patches/movestack)
- [pertag](https://dwm.suckless.org/patches/pertag) - [pertag](https://dwm.suckless.org/patches/pertag)
- [systray](https://dwm.suckless.org/patches/systray) - [systray](https://dwm.suckless.org/patches/systray)
- [sticky](https://dwm.suckless.org/patches/sticky) - [sticky](https://dwm.suckless.org/patches/sticky)
- [noborder](https://dwm.suckless.org/patches/noborder) - [noborder](https://dwm.suckless.org/patches/noborder)
- [notitle](https://dwm.suckless.org/patches/notitle)
- [fibonacci layouts](https://dwm.suckless.org/patches/fibonacci) - [fibonacci layouts](https://dwm.suckless.org/patches/fibonacci)
- [centeredmaster](https://dwm.suckless.org/patches/centeredmaster) - [centeredmaster](https://dwm.suckless.org/patches/centeredmaster)
### Keys ### Dependencies
| Keys | Function | - `libxinerama-dev`
|--------------------------------|-----------------------------------------------------------------------|
| modkey + shift + d | Open dmenu (launcher) |
| modkey + shift + ctrl + d | Open rofi launcher (small size) |
| modkey + enter | Launche the main terminal (alacritty by default) |
| modkey + t -> a | Launche the alacritty terminal |
| modkey + t -> shift + a | Launche the alacritty terminal with tmux |
| modkey + t -> k | Launche the kitty terminal |
| modkey + t -> shift + k | Launche the kitty terminal with tmux |
| modkey + shift + f -> g | Launche the GUI file manger (pcmanfm by default) |
| modkey + shift + f -> f | Launche rofi file file browser (small size) |
| modkey + shift + f -> r | Launche ranger in the main terminal |
| modkey + w -> g | Launche google chrome browser |
| modkey + w -> t | Launche tor browser |
| modkey + c -> d | Launche discord |
| modkey + c -> o | Launche obsidian |
| modkey + a -> j | Launche jetbrains-toolbox |
| modkey + a -> n | Launche NeoVim in the main terminal |
| modkey + a -> v | Launche Vim in the main terminal |
| modkey + a -> e | Launche emacs |
| modkey + p -> b | Launche the background manger (nitrogen by default) |
| modkey + p -> n | Lanuche the network manager (nm-connection-editor) |
| modkey + e | Launche rofi emoji selector |
| modkey + f | Toggle full screen mode |
| modkey + b | Toggle the status bar (hide/show) |
| modkey + j | Change the focus to privus window in the stack |
| modkey + k | Change the focus to the next window in the stack |
| modkey + i | Change the stack layout to virtecal |
| modkey + d | Change the stack layout to horizontal |
| modkey + h | Decrease the focus window size |
| modkey + l | Increase the focus window size |
| modkey + Tab | Toggle between the curent tag and the privus tag |
| modkey + shift + j | Move the focus window down in the stack |
| modkey + shift + k | Move the focus window up in the stack |
| modkey + q -> q | Quit from the focus window (kill it) |
| modkey + s -> t | Use the tile layout |
| modkey + s -> f | Use the float layout |
| modkey + s -> m | Use the monocle layout |
| modkey + s -> g | Use the grid layout |
| modkey + s -> r | Use the spial layout (part from fibonacci layouts) |
| modkey + s -> shift + r | Use the dwindle layout (part from fibonacci layouts) |
| modkey + s -> c | Use the centerd master layout |
| modkey + s -> shift + s | Use the centerd floating master layout |
| modkey + s -> space | Toggle between current layout and tile layout |
| modkey + shift + s | Toggle sticky mode |
| modkey + alt + f | Toggle floating window |
| modkey + m -> c | Launche the cmus player |
| modkey + m -> v | Launche vlc video player |
| modkey + m -> shift + v | Lanuche nvlc in the main terminal |
| modkey + 0 | View all tags |
| modkey + shift + 0 | Mirror the current tag in all tags |
| modkey + comma (,) | - |
| modkey + period (.) | - |
| modkey + shift + comma (,) | - |
| modkey + shift + period (.) | - |
| modkey + (1..9) | Navigate between tags |
| modkey + shift + (1..9) | Move the focus window to specific tag |
| modkey + control + (1..9) | - |
| modkey + shift + ctrl + (1..9) | Mirror the current tag in specific tag |
| superkey + space | Change the keyboard layout (ar, en) |
| PrtSc | Take a screenshot using default screenshot tool (spectacle) |
| modkey + shift + x | Lock the screen (using betterlockscreen) |
| modkey + shift + alt + q | Kill dwm |
> modkey = win key or super key
### Dependencies (apps)
- `google-chrome-stable` the main web browser
- `alacritty` the main terminal
- `spectacle` the main screenshot tool
- `pcmanfm` the GUI file manger
- `rofi`
- `dmenu`
- `libxinerama-dev`\*\*
- `tmux`\*
- `tor-browser`
- `discord`
- `libxft-bgra` for color emojies support - `libxft-bgra` for color emojies support
- `jetbrains-toolbox` - `archy-slstatus` the status bar
- `nvim`\*
- `vim`\*
- `xbacklight` for control in the screen brightness
- `pamixer` for control in the audio level
- `playerctl` for control in the media
- `pactl` for control in the mic
- `betterlockscreen` for lock screen
- `setxkbmap` for switch between keyboard layouts, like (ar, en)
- `slstatus` the status bar
- `network-manager-applet`
- `picom` compositor , for transparency
- `nitrogen` for set the wallpaper
- `copyq` clipboard manager
- `obsidian`
> \*\*: build dependencie.
### Install
- Manual:
1. Run this command to install all avilable dependencies in standerd arch repostory
```bash
sudo pacman -S google-chrome libxft-bgra rofi dmenu tmux tor-browser discord neovim jetbrains-toolbox vim pamixer playerctl betterlockscreen pcmanfm spectacle alacritty picom nitrogen libxinerama network-manager-applet copyq obsidian
```
2. Install yay if you not installed it.
3. Run this command to install all avilable dependencies in the AUR repostory `yay -S xkblayout`
4. Clone this repostory `git clone https://github.com/anas-elgarhy/dwm-anas.git`
5. Go to the source directory `cd dwm-anas/src`
6. Build and install `sudo make install clean`
7. Enjoy 😉
### Available in
[![GitHub](https://img.shields.io/badge/GitHub-Main%20repo-brightgreen?style=for-the-badge&logo=GitHub)](https://github.com/anas-elgarhy/dwm-anas)
[![GitLab](https://img.shields.io/badge/GitLab-Mirror%20repo-brightgreen?style=for-the-badge&logo=GitLab)](https://gitlab.com/anas-elgarhy/dwm-anas)
[![BitBucket](https://img.shields.io/badge/BitBucket-Mirror%20repo-brightgreen?style=for-the-badge&logo=BitBucket)](https://bitbucket.org/anas_elgarhy/dwm-anas)
[![Codeberg](https://img.shields.io/badge/Codeberg-Mirror%20repo-brightgreen?style=for-the-badge&logo=Codeberg)](https://codeberg.org/anas-elgarhy/dwm-anas)
### Mirrors
* [GitHub](https://github.com/archy-linux/archy-dwm) - The upstream repository
* [GitLab](https://gitlab.com/archy-linux/archy-dwm) - [![Mirror the repo to gitlab](https://github.com/archy-linux/archy-dwm/actions/workflows/gitlab-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/gitlab-mirror.yml)
* [NotABug](https://notabug.org/archy-linux/archy-dwm) - Not instant updates
* [Codeberg](https://codeberg.org/archy-linux/archy-dwm) - [![Mirror the repo to codeberg](https://github.com/archy-linux/archy-dwm/actions/workflows/codeberg-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/codeberg-mirror.yml)
* [Gitea](https://gitea.com/archy-linux/archy-dwm) - [![Mirror the repo to Gitea](https://github.com/archy-linux/archy-dwm/actions/workflows/gitea-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/gitea-mirror.yml)
* [Gitdab](https://gitdab.com/archy-linux/archy-dwm) - [![Mirror the repo to Gitdab](https://github.com/archy-linux/archy-dwm/actions/workflows/gitdab-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/gitdab-mirror.yml)
* [Pagure](https://pagure.io/archy-dwm) - [![Mirror the repo to pagure](https://github.com/archy-linux/archy-dwm/actions/workflows/pagure-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/pagure-mirror.yml)
* [Bitbucket](https://bitbucket.org/anas_elgarhy/archy-dwm) - [![Mirror the repo to bitbucket](https://github.com/archy-linux/archy-dwm/actions/workflows/bitbucket-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/bitbucket-mirror.yml)
* [disroot](https://git.disroot.org/archy-linux/archy-dwm) - [![Mirror the repo to disroot](https://github.com/archy-linux/archy-dwm/actions/workflows/disroot-mirror.yml/badge.svg)](https://github.com/archy-linux/archy-dwm/actions/workflows/disroot-mirror.yml)
### References:
- [XF86keysym](https://cgit.freedesktop.org/xorg/proto/x11proto/tree/XF86keysym.h)

View file

View file

@ -1,5 +1,5 @@
# dwm-anas version # Archy DWM version
VERSION = 6.3-0.1.2 VERSION = 2.0.0
# Customize below to fit your system # Customize below to fit your system

View file

@ -1,562 +0,0 @@
diff --git a/src/config.def.h.rej b/src/config.def.h.rej
new file mode 100644
index 0000000..82ea963
--- /dev/null
+++ b/src/config.def.h.rej
@@ -0,0 +1,13 @@
+--- config.def.h
++++ config.def.h
+@@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
+ static const int showbar = 1; /* 0 means no bar */
+ static const int topbar = 1; /* 0 means bottom bar */
++static const int usealtbar = 1; /* 1 means use non-dwm status bar */
++static const char *altbarclass = "Polybar"; /* Alternate bar class name */
++static const char *alttrayname = "tray"; /* Polybar tray instance name */
++static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
+ static const char *fonts[] = { "monospace:size=10" };
+ static const char dmenufont[] = "monospace:size=10";
+ static const char col_gray1[] = "#222222";
diff --git a/src/config.h b/src/config.h
index 1e3fec2..43aa1e2 100644
--- a/src/config.h
+++ b/src/config.h
@@ -17,6 +17,12 @@ static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display
static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
+
+static const int usealtbar = 1; /* 1 means use non-dwm status bar */
+static const char *altbarclass = "Polybar"; /* Alternate bar class name */
+static const char *alttrayname = "tray"; /* Polybar tray instance name */
+static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
+
static const char *fonts[] = { "monospace:size=11", "Noto Color Emoji:size=11", "Nerd Font Mono:weight=bold:size=15:antialias=true:hinting=true" };
static const char dmenufont[] = "monospace:size=11";
@@ -24,8 +30,6 @@ static const char dmenufont[] = "monospace:size=11";
// Autostart programs
static const char *const autostart[] = {
- // Start my build of slstatus
- "slstatus", NULL,
// Keyboard layouts switch (requires setxkbmap)
"setxkbmap", "-model", "pc101", "-layout", "us,ar", "-variant", ",,", "-option", "grp:win_space_toggle", NULL,
// "xkbset", "exp", "=sticky", "-twokey", "-latchlock", NULL, // sticky keys
diff --git a/src/dwm.c b/src/dwm.c
index eb423c5..0499e58 100644
--- a/src/dwm.c
+++ b/src/dwm.c
@@ -47,8 +47,8 @@
/* macros */
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
+#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
+ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
@@ -137,7 +137,8 @@ struct Monitor {
float mfact;
int nmaster;
int num;
- int by; /* bar geometry */
+ int by, bh; /* bar geometry */
+ int tx, tw; /* bar tray geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
@@ -150,6 +151,7 @@ struct Monitor {
Client *stack;
Monitor *next;
Window barwin;
+ Window traywin;
const Layout *lt[2];
Pertag *pertag;
};
@@ -208,6 +210,8 @@ static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
+static void managealtbar(Window win, XWindowAttributes *wa);
+static void managetray(Window win, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
@@ -227,6 +231,7 @@ static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
+static void scantray(void);
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
@@ -240,6 +245,7 @@ static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
+static void spawnbar();
static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
@@ -251,6 +257,8 @@ static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
+static void unmanagealtbar(Window w);
+static void unmanagetray(Window w);
static void unmapnotify(XEvent *e);
static void updatebarpos(Monitor *m);
static void updatebars(void);
@@ -269,6 +277,7 @@ static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static Client *wintosystrayicon(Window w);
+static int wmclasscontains(Window win, const char *class, const char *name);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
@@ -595,8 +604,10 @@ cleanupmon(Monitor *mon)
for (m = mons; m && m->next != mon; m = m->next);
m->next = mon->next;
}
- XUnmapWindow(dpy, mon->barwin);
- XDestroyWindow(dpy, mon->barwin);
+ if (!usealtbar) {
+ XUnmapWindow(dpy, mon->barwin);
+ XDestroyWindow(dpy, mon->barwin);
+ }
free(mon);
}
@@ -779,6 +790,7 @@ createmon(void)
m->nmaster = nmaster;
m->showbar = showbar;
m->topbar = topbar;
+ m->bh = bh;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@@ -803,10 +815,15 @@ void
destroynotify(XEvent *e)
{
Client *c;
+ Monitor *m;
XDestroyWindowEvent *ev = &e->xdestroywindow;
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
+ unmanagealtbar(ev->window);
+ else if (m->traywin == ev->window)
+ unmanagetray(ev->window);
else if ((c = wintosystrayicon(ev->window))) {
removesystrayicon(c);
resizebarwin(selmon);
@@ -855,6 +872,8 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
+ if (usealtbar) return;
+
int x, w, tw = 0, stw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
@@ -1325,6 +1344,8 @@ maprequest(XEvent *e)
return;
if (wa.override_redirect)
return;
+ if (wmclasscontains(ev->window, altbarclass, ""))
+ managealtbar(ev->window, &wa);
if (!wintoclient(ev->window))
manage(ev->window, &wa);
}
@@ -1525,7 +1546,7 @@ resizebarwin(Monitor *m) {
unsigned int w = m->ww;
if (showsystray && m == systraytomon(m) && !systrayonleft)
w -= getsystraywidth();
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
}
void
@@ -1668,8 +1689,10 @@ scan(void)
for (i = 0; i < num; i++) {
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
- continue;
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
+ continue;
+ if (wmclasscontains(wins[i], altbarclass, ""))
+ managealtbar(wins[i], &wa);
+ else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
manage(wins[i], &wa);
}
for (i = 0; i < num; i++) { /* now the transients */
@@ -1684,6 +1707,28 @@ scan(void)
}
}
+
+void
+scantray(void)
+{
+ unsigned int num;
+ Window d1, d2, *wins = NULL;
+ XWindowAttributes wa;
+
+ if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
+ for (unsigned int i = 0; i < num; i++) {
+ if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
+ if (!XGetWindowAttributes(dpy, wins[i], &wa))
+ break;
+ managetray(wins[i], &wa);
+ }
+ }
+ }
+
+ if (wins)
+ XFree(wins);
+}
+
void
sendmon(Client *c, Monitor *m)
{
@@ -1848,7 +1893,7 @@ setup(void)
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
- bh = drw->fonts->h + 2;
+ bh = usealtbar ? 0 : drw->fonts->h + 2;
updategeom();
/* init atoms */
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
@@ -1906,6 +1951,7 @@ setup(void)
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
focus(NULL);
+ spawnbar();
}
@@ -1980,6 +2026,13 @@ spawn(const Arg *arg)
}
}
+void
+spawnbar()
+{
+ if (*altbarcmd)
+ system(altbarcmd);
+}
+
void
tag(const Arg *arg)
{
@@ -2001,9 +2054,19 @@ tagmon(const Arg *arg)
void
togglebar(const Arg *arg)
{
+ /**
+ * Polybar tray does not raise maprequest event. It must be manually scanned
+ * for. Scanning it too early while the tray is being populated would give
+ * wrong dimensions.
+ */
+ if (!selmon->traywin)
+ scantray();
+
selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
updatebarpos(selmon);
resizebarwin(selmon);
+ //TODO: 2022-07-17 Test
+ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
if (showsystray) {
XWindowChanges wc;
if (!selmon->showbar)
@@ -2018,6 +2081,38 @@ togglebar(const Arg *arg)
arrange(selmon);
}
+
+void
+unmanagealtbar(Window w)
+{
+ Monitor *m = wintomon(w);
+
+ if (!m)
+ return;
+
+ m->barwin = 0;
+ m->by = 0;
+ m->bh = 0;
+ updatebarpos(m);
+ arrange(m);
+}
+
+void
+unmanagetray(Window w)
+{
+ Monitor *m = wintomon(w);
+
+ if (!m)
+ return;
+
+ m->traywin = 0;
+ m->tx = 0;
+ m->tw = 0;
+ updatebarpos(m);
+ arrange(m);
+}
+
+
void
togglefloating(const Arg *arg)
{
@@ -2134,6 +2229,7 @@ void
unmapnotify(XEvent *e)
{
Client *c;
+ Monitor *m;
XUnmapEvent *ev = &e->xunmap;
if ((c = wintoclient(ev->window))) {
@@ -2141,7 +2237,10 @@ unmapnotify(XEvent *e)
setclientstate(c, WithdrawnState);
else
unmanage(c, 0);
- }
+ } else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
+ unmanagealtbar(ev->window);
+ else if (m->traywin == ev->window)
+ unmanagetray(ev->window);
else if ((c = wintosystrayicon(ev->window))) {
/* KLUDGE! sometimes icons occasionally unmap their windows, but do
* _not_ destroy them. We map those windows back */
@@ -2153,6 +2252,8 @@ unmapnotify(XEvent *e)
void
updatebars(void)
{
+ if (usealtbar) return;
+
unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
@@ -2184,11 +2285,11 @@ updatebarpos(Monitor *m)
m->wy = m->my;
m->wh = m->mh;
if (m->showbar) {
- m->wh -= bh;
+ m->wh -= m->bh;
m->by = m->topbar ? m->wy : m->wy + m->wh;
- m->wy = m->topbar ? m->wy + bh : m->wy;
+ m->wy = m->topbar ? m->wy + m->bh : m->wy;
} else
- m->by = -bh;
+ m->by = -m->bh;
}
void
@@ -2491,6 +2592,45 @@ updatewindowtype(Client *c)
c->isfloating = 1;
}
+
+void
+managealtbar(Window win, XWindowAttributes *wa)
+{
+ Monitor *m;
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
+ return;
+
+ m->barwin = win;
+ m->by = wa->y;
+ bh = m->bh = wa->height;
+ updatebarpos(m);
+ arrange(m);
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
+ XMapWindow(dpy, win);
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &win, 1);
+}
+
+void
+managetray(Window win, XWindowAttributes *wa)
+{
+ Monitor *m;
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
+ return;
+
+ m->traywin = win;
+ m->tx = wa->x;
+ m->tw = wa->width;
+ updatebarpos(m);
+ arrange(m);
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
+ XMapWindow(dpy, win);
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &win, 1);
+}
+
void
updatewmhints(Client *c)
{
@@ -2581,13 +2721,36 @@ wintomon(Window w)
if (w == root && getrootptr(&x, &y))
return recttomon(x, y, 1, 1);
for (m = mons; m; m = m->next)
- if (w == m->barwin)
+ if (w == m->barwin || w == m->traywin)
return m;
if ((c = wintoclient(w)))
return c->mon;
return selmon;
}
+
+int
+wmclasscontains(Window win, const char *class, const char *name)
+{
+ XClassHint ch = { NULL, NULL };
+ int res = 1;
+
+ if (XGetClassHint(dpy, win, &ch)) {
+ if (ch.res_name && strstr(ch.res_name, name) == NULL)
+ res = 0;
+ if (ch.res_class && strstr(ch.res_class, class) == NULL)
+ res = 0;
+ } else
+ res = 0;
+
+ if (ch.res_class)
+ XFree(ch.res_class);
+ if (ch.res_name)
+ XFree(ch.res_name);
+
+ return res;
+}
+
/* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which may call exit. */
diff --git a/src/dwm.c.rej b/src/dwm.c.rej
new file mode 100644
index 0000000..7e375c6
--- /dev/null
+++ b/src/dwm.c.rej
@@ -0,0 +1,112 @@
+--- dwm.c
++++ dwm.c
+@@ -47,8 +47,8 @@
+ /* macros */
+ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
+ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
+- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
++#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
++ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
+ #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+@@ -199,6 +203,7 @@ static void resizemouse(const Arg *arg);
+ static void restack(Monitor *m);
+ static void run(void);
+ static void scan(void);
++static void scantray(void);
+ static int sendevent(Client *c, Atom proto);
+ static void sendmon(Client *c, Monitor *m);
+ static void setclientstate(Client *c, long state);
+@@ -211,6 +216,7 @@ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
+ static void sigchld(int unused);
+ static void spawn(const Arg *arg);
++static void spawnbar();
+ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+ static void tile(Monitor *);
+@@ -236,6 +244,7 @@ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
++static int wmclasscontains(Window win, const char *class, const char *name);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+@@ -576,7 +587,7 @@ configurenotify(XEvent *e)
+ for (c = m->clients; c; c = c->next)
+ if (c->isfullscreen)
+ resizeclient(c, m->mx, m->my, m->mw, m->mh);
+- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
+ }
+ focus(NULL);
+ arrange(NULL);
+@@ -658,10 +670,15 @@ void
+ destroynotify(XEvent *e)
+ {
+ Client *c;
++ Monitor *m;
+ XDestroyWindowEvent *ev = &e->xdestroywindow;
+
+ if ((c = wintoclient(ev->window)))
+ unmanage(c, 1);
++ else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
++ unmanagealtbar(ev->window);
++ else if (m->traywin == ev->window)
++ unmanagetray(ev->window);
+ }
+
+ void
+@@ -705,6 +722,9 @@ dirtomon(int dir)
+ void
+ drawbar(Monitor *m)
+ {
++ if (usealtbar)
++ return;
++
+ int x, w, tw = 0;
+ int boxs = drw->fonts->h / 9;
+ int boxw = drw->fonts->h / 6 + 2;
+@@ -1785,9 +1879,18 @@ tile(Monitor *m)
+ void
+ togglebar(const Arg *arg)
+ {
++ /**
++ * Polybar tray does not raise maprequest event. It must be manually scanned
++ * for. Scanning it too early while the tray is being populated would give
++ * wrong dimensions.
++ */
++ if (!selmon->traywin)
++ scantray();
++
+ selmon->showbar = !selmon->showbar;
+ updatebarpos(selmon);
+- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
++ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
+ arrange(selmon);
+ }
+
+@@ -1912,12 +2046,18 @@ unmapnotify(XEvent *e)
+ setclientstate(c, WithdrawnState);
+ else
+ unmanage(c, 0);
+- }
++ } else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
++ unmanagealtbar(ev->window);
++ else if (m->traywin == ev->window)
++ unmanagetray(ev->window);
+ }
+
+ void
+ updatebars(void)
+ {
++ if (usealtbar)
++ return;
++
+ Monitor *m;
+ XSetWindowAttributes wa = {
+ .override_redirect = True,

View file

@ -1,12 +0,0 @@
diff -up dwm/dwm.c dwmmod/dwm.c
--- dwm/dwm.c 2020-06-25 00:21:30.383692180 -0300
+++ dwmmod/dwm.c 2020-06-25 00:20:35.643692330 -0300
@@ -1057,6 +1057,8 @@ manage(Window w, XWindowAttributes *wa)
updatewindowtype(c);
updatesizehints(c);
updatewmhints(c);
+ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2;
+ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2;
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
grabbuttons(c, 0);
if (!c->isfloating)

View file

@ -1,142 +0,0 @@
diff --git a/config.def.h b/config.def.h
index fd77a07..f025619 100644
--- a/config.def.h
+++ b/config.def.h
@@ -41,6 +41,8 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "|M|", centeredmaster },
+ { ">M>", centeredfloatingmaster },
};
/* key definitions */
@@ -76,6 +78,8 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
+ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/dwm.c b/dwm.c
index b2bc9bd..9ecabae 100644
--- a/dwm.c
+++ b/dwm.c
@@ -234,6 +234,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+static void centeredmaster(Monitor *m);
+static void centeredfloatingmaster(Monitor *m);
/* variables */
static const char broken[] = "broken";
@@ -2138,3 +2140,106 @@ main(int argc, char *argv[])
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
+
+void
+centeredmaster(Monitor *m)
+{
+ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize areas */
+ mw = m->ww;
+ mx = 0;
+ my = 0;
+ tw = mw;
+
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ tw = m->ww - mw;
+
+ if (n - m->nmaster > 1) {
+ /* only one client */
+ mx = (m->ww - mw) / 2;
+ tw = (m->ww - mw) / 2;
+ }
+ }
+
+ oty = 0;
+ ety = 0;
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked vertically, in the center
+ * of the screen */
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
+ h - (2*c->bw), 0);
+ my += HEIGHT(c);
+ } else {
+ /* stack clients are stacked vertically */
+ if ((i - m->nmaster) % 2 ) {
+ h = (m->wh - ety) / ( (1 + n - i) / 2);
+ resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
+ h - (2*c->bw), 0);
+ ety += HEIGHT(c);
+ } else {
+ h = (m->wh - oty) / ((1 + n - i) / 2);
+ resize(c, m->wx + mx + mw, m->wy + oty,
+ tw - (2*c->bw), h - (2*c->bw), 0);
+ oty += HEIGHT(c);
+ }
+ }
+}
+
+void
+centeredfloatingmaster(Monitor *m)
+{
+ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize nmaster area */
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ if (m->ww > m->wh) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ mh = m->nmaster ? m->wh * 0.9 : 0;
+ } else {
+ mh = m->nmaster ? m->wh * m->mfact : 0;
+ mw = m->nmaster ? m->ww * 0.9 : 0;
+ }
+ mx = mxo = (m->ww - mw) / 2;
+ my = myo = (m->wh - mh) / 2;
+ } else {
+ /* go fullscreen if all clients are in the master area */
+ mh = m->wh;
+ mw = m->ww;
+ mx = mxo = 0;
+ my = myo = 0;
+ }
+
+ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked horizontally, in the center
+ * of the screen */
+ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
+ mh - (2*c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ /* stack clients are stacked horizontally */
+ w = (m->ww - tx) / (n - i);
+ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
+ m->wh - (2*c->bw), 0);
+ tx += WIDTH(c);
+ }
+}

View file

@ -1,116 +0,0 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..ed056a4 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,6 +18,11 @@ static const char *colors[][3] = {
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
+static const char *const autostart[] = {
+ "st", NULL,
+ NULL /* terminate */
+};
+
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
diff --git a/dwm.c b/dwm.c
index 9fd0286..1facd56 100644
--- a/dwm.c
+++ b/dwm.c
@@ -234,6 +234,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+static void autostart_exec(void);
/* variables */
static const char broken[] = "broken";
@@ -275,6 +276,34 @@ static Window root, wmcheckwin;
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+/* dwm will keep pid's of processes from autostart array and kill them at quit */
+static pid_t *autostart_pids;
+static size_t autostart_len;
+
+/* execute command from autostart array */
+static void
+autostart_exec() {
+ const char *const *p;
+ size_t i = 0;
+
+ /* count entries */
+ for (p = autostart; *p; autostart_len++, p++)
+ while (*++p);
+
+ autostart_pids = malloc(autostart_len * sizeof(pid_t));
+ for (p = autostart; *p; i++, p++) {
+ if ((autostart_pids[i] = fork()) == 0) {
+ setsid();
+ execvp(*p, (char *const *)p);
+ fprintf(stderr, "dwm: execvp %s\n", *p);
+ perror(" failed");
+ _exit(EXIT_FAILURE);
+ }
+ /* skip arguments */
+ while (*++p);
+ }
+}
+
/* function implementations */
void
applyrules(Client *c)
@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e)
void
quit(const Arg *arg)
{
+ size_t i;
+
+ /* kill child processes */
+ for (i = 0; i < autostart_len; i++) {
+ if (0 < autostart_pids[i]) {
+ kill(autostart_pids[i], SIGTERM);
+ waitpid(autostart_pids[i], NULL, 0);
+ }
+ }
+
running = 0;
}
@@ -1632,9 +1671,25 @@ showhide(Client *c)
void
sigchld(int unused)
{
+ pid_t pid;
+
if (signal(SIGCHLD, sigchld) == SIG_ERR)
die("can't install SIGCHLD handler:");
- while (0 < waitpid(-1, NULL, WNOHANG));
+ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
+ pid_t *p, *lim;
+
+ if (!(p = autostart_pids))
+ continue;
+ lim = &p[autostart_len];
+
+ for (; p < lim; p++) {
+ if (*p == pid) {
+ *p = -1;
+ break;
+ }
+ }
+
+ }
}
void
@@ -2139,6 +2194,7 @@ main(int argc, char *argv[])
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
checkotherwm();
+ autostart_exec();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)

View file

@ -1,114 +0,0 @@
From ec9f55b6005cfa3b025b3d700c61af3ce539d057 Mon Sep 17 00:00:00 2001
From: Niki Yoshiuchi <nyoshiuchi@gmail.com>
Date: Sat, 18 Apr 2020 09:55:26 -0700
Subject: [PATCH] Adding the fibonacci layout patch
---
config.def.h | 5 ++++
fibonacci.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+)
create mode 100644 fibonacci.c
diff --git a/config.def.h b/config.def.h
index 1c0b587..5708487 100644
--- a/config.def.h
+++ b/config.def.h
@@ -36,11 +36,14 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+#include "fibonacci.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "[@]", spiral },
+ { "[\\]", dwindle },
};
/* key definitions */
@@ -76,6 +79,8 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_r, setlayout, {.v = &layouts[3]} },
+ { MODKEY|ShiftMask, XK_r, setlayout, {.v = &layouts[4]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/fibonacci.c b/fibonacci.c
new file mode 100644
index 0000000..fce0a57
--- /dev/null
+++ b/fibonacci.c
@@ -0,0 +1,66 @@
+void
+fibonacci(Monitor *mon, int s) {
+ unsigned int i, n, nx, ny, nw, nh;
+ Client *c;
+
+ for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++);
+ if(n == 0)
+ return;
+
+ nx = mon->wx;
+ ny = 0;
+ nw = mon->ww;
+ nh = mon->wh;
+
+ for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) {
+ if((i % 2 && nh / 2 > 2 * c->bw)
+ || (!(i % 2) && nw / 2 > 2 * c->bw)) {
+ if(i < n - 1) {
+ if(i % 2)
+ nh /= 2;
+ else
+ nw /= 2;
+ if((i % 4) == 2 && !s)
+ nx += nw;
+ else if((i % 4) == 3 && !s)
+ ny += nh;
+ }
+ if((i % 4) == 0) {
+ if(s)
+ ny += nh;
+ else
+ ny -= nh;
+ }
+ else if((i % 4) == 1)
+ nx += nw;
+ else if((i % 4) == 2)
+ ny += nh;
+ else if((i % 4) == 3) {
+ if(s)
+ nx += nw;
+ else
+ nx -= nw;
+ }
+ if(i == 0)
+ {
+ if(n != 1)
+ nw = mon->ww * mon->mfact;
+ ny = mon->wy;
+ }
+ else if(i == 1)
+ nw = mon->ww - nw;
+ i++;
+ }
+ resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
+ }
+}
+
+void
+dwindle(Monitor *mon) {
+ fibonacci(mon, 1);
+}
+
+void
+spiral(Monitor *mon) {
+ fibonacci(mon, 0);
+}
--
2.20.1

View file

@ -1,56 +0,0 @@
From 54719285bd1a984e2efce6e8a8eab184fec11abf Mon Sep 17 00:00:00 2001
From: Sermak <sermak@jarvis.com>
Date: Mon, 8 Jul 2019 01:06:44 +0200
Subject: [PATCH] Simulate toggleable fullscreen mode
---
config.def.h | 1 +
dwm.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/config.def.h b/config.def.h
index 1c0b587..f774cc5 100644
--- a/config.def.h
+++ b/config.def.h
@@ -76,6 +76,7 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY|ShiftMask, XK_f, fullscreen, {0} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/dwm.c b/dwm.c
index 4465af1..04b1e06 100644
--- a/dwm.c
+++ b/dwm.c
@@ -199,6 +199,7 @@ static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
+static void fullscreen(const Arg *arg);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
@@ -1497,6 +1498,19 @@ setfullscreen(Client *c, int fullscreen)
}
}
+Layout *last_layout;
+void
+fullscreen(const Arg *arg)
+{
+ if (selmon->showbar) {
+ for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++);
+ setlayout(&((Arg) { .v = &layouts[2] }));
+ } else {
+ setlayout(&((Arg) { .v = last_layout }));
+ }
+ togglebar(arg);
+}
+
void
setlayout(const Arg *arg)
{
--
2.22.0

View file

@ -1,73 +0,0 @@
From b04bb473cf9818277d33a591f7fe2dfae96afaaf Mon Sep 17 00:00:00 2001
From: Joshua Haase <hahj87@gmail.com>
Date: Mon, 15 Aug 2016 17:06:18 -0500
Subject: [PATCH] Apply modified gridmode patch.
---
config.def.h | 3 +++
layouts.c | 27 +++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 layouts.c
diff --git a/config.def.h b/config.def.h
index a9ac303..30b7c4a 100644
--- a/config.def.h
+++ b/config.def.h
@@ -36,11 +36,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+#include "layouts.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "HHH", grid },
};
/* key definitions */
@@ -76,6 +78,7 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_g, setlayout, {.v = &layouts[3]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/layouts.c b/layouts.c
new file mode 100644
index 0000000..d26acf3
--- /dev/null
+++ b/layouts.c
@@ -0,0 +1,27 @@
+void
+grid(Monitor *m) {
+ unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next))
+ n++;
+
+ /* grid dimensions */
+ for(rows = 0; rows <= n/2; rows++)
+ if(rows*rows >= n)
+ break;
+ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
+
+ /* window geoms (cell height/width) */
+ ch = m->wh / (rows ? rows : 1);
+ cw = m->ww / (cols ? cols : 1);
+ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
+ cx = m->wx + (i / rows) * cw;
+ cy = m->wy + (i % rows) * ch;
+ /* adjust height/width of last row/column's windows */
+ ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0;
+ aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0;
+ resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False);
+ i++;
+ }
+}
--
2.14.1

View file

@ -1,217 +0,0 @@
From e61a957ff8b7e14219b5fbaab9da794b722e7874 Mon Sep 17 00:00:00 2001
From: Hai Nguyen <hhai2105@gmail.com>
Date: Fri, 10 Dec 2021 21:45:00 -0500
Subject: [PATCH] add Keychord struct, change keypress() and grabkeys() to be
able to grab a sequence of keystroke
---
config.def.h | 67 ++++++++++++++++++++++++++------------------------
dwm.c | 69 ++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 88 insertions(+), 48 deletions(-)
diff --git a/config.def.h b/config.def.h
index a2ac963..15a3e05 100644
--- a/config.def.h
+++ b/config.def.h
@@ -46,11 +46,12 @@ static const Layout layouts[] = {
/* key definitions */
#define MODKEY Mod1Mask
-#define TAGKEYS(KEY,TAG) \
- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
+
+#define TAGKEYS(KEY,TAG) \
+ {1, {{MODKEY, KEY}}, view, {.ui = 1 << TAG} }, \
+ {1, {{MODKEY|ControlMask, KEY}}, toggleview, {.ui = 1 << TAG} }, \
+ {1, {{MODKEY|ShiftMask, KEY}}, tag, {.ui = 1 << TAG} }, \
+ {1, {{MODKEY|ControlMask|ShiftMask, KEY}}, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
@@ -59,32 +60,34 @@ static const Layout layouts[] = {
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
+static const char *emacs[] = { "emacs", NULL };
-static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_j, focusstack, {.i = +1 } },
- { MODKEY, XK_k, focusstack, {.i = -1 } },
- { MODKEY, XK_i, incnmaster, {.i = +1 } },
- { MODKEY, XK_d, incnmaster, {.i = -1 } },
- { MODKEY, XK_h, setmfact, {.f = -0.05} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY, XK_Return, zoom, {0} },
- { MODKEY, XK_Tab, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY, XK_comma, focusmon, {.i = -1 } },
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+static Keychord keychords[] = {
+ /* Keys function argument */
+ {1, {{MODKEY, XK_p}}, spawn, {.v = dmenucmd } },
+ {1, {{MODKEY|ShiftMask, XK_Return}}, spawn, {.v = termcmd } },
+ {2, {{MODKEY, XK_e}, {MODKEY, XK_e}}, spawn, {.v = termcmd } },
+ {1, {{MODKEY, XK_b}}, togglebar, {0} },
+ {1, {{MODKEY, XK_j}}, focusstack, {.i = +1 } },
+ {1, {{MODKEY, XK_k}}, focusstack, {.i = -1 } },
+ {1, {{MODKEY, XK_i}}, incnmaster, {.i = +1 } },
+ {1, {{MODKEY, XK_d}}, incnmaster, {.i = -1 } },
+ {1, {{MODKEY, XK_h}}, setmfact, {.f = -0.05} },
+ {1, {{MODKEY, XK_l}}, setmfact, {.f = +0.05} },
+ {1, {{MODKEY, XK_Return}}, zoom, {0} },
+ {1, {{MODKEY, XK_Tab}}, view, {0} },
+ {1, {{MODKEY|ShiftMask, XK_c}}, killclient, {0} },
+ {1, {{MODKEY, XK_t}}, setlayout, {.v = &layouts[0]} },
+ {1, {{MODKEY, XK_f}}, setlayout, {.v = &layouts[1]} },
+ {1, {{MODKEY, XK_m}}, setlayout, {.v = &layouts[2]} },
+ {1, {{MODKEY, XK_space}}, setlayout, {0} },
+ {1, {{MODKEY|ShiftMask, XK_space}}, togglefloating, {0} },
+ {1, {{MODKEY, XK_0}}, view, {.ui = ~0 } },
+ {1, {{MODKEY|ShiftMask, XK_0}}, tag, {.ui = ~0 } },
+ {1, {{MODKEY, XK_comma}}, focusmon, {.i = -1 } },
+ {1, {{MODKEY, XK_period}}, focusmon, {.i = +1 } },
+ {1, {{MODKEY|ShiftMask, XK_comma}}, tagmon, {.i = -1 } },
+ {1, {{MODKEY|ShiftMask, XK_period}}, tagmon, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@@ -92,9 +95,9 @@ static Key keys[] = {
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
+ TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_q, quit, {0} },
+ {1, {{MODKEY|ShiftMask, XK_q}}, quit, {0} },
};
/* button definitions */
diff --git a/dwm.c b/dwm.c
index 5e4d494..56c4661 100644
--- a/dwm.c
+++ b/dwm.c
@@ -102,9 +102,14 @@ struct Client {
typedef struct {
unsigned int mod;
KeySym keysym;
+} Key;
+
+typedef struct {
+ unsigned int n;
+ const Key keys[5];
void (*func)(const Arg *);
const Arg arg;
-} Key;
+} Keychord;
typedef struct {
const char *symbol;
@@ -268,6 +273,7 @@ static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
static Window root, wmcheckwin;
+unsigned int currentkey = 0;
/* configuration, allows nested code to access above variables */
#include "config.h"
@@ -951,16 +957,16 @@ grabkeys(void)
{
updatenumlockmask();
{
- unsigned int i, j;
+ unsigned int i, k;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (i = 0; i < LENGTH(keys); i++)
- if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
- for (j = 0; j < LENGTH(modifiers); j++)
- XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
+ for (i = 0; i < LENGTH(keychords); i++)
+ if ((code = XKeysymToKeycode(dpy, keychords[i].keys[currentkey].keysym)))
+ for (k = 0; k < LENGTH(modifiers); k++)
+ XGrabKey(dpy, code, keychords[i].keys[currentkey].mod | modifiers[k], root,
+ True, GrabModeAsync, GrabModeAsync);
}
}
@@ -986,17 +992,48 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
void
keypress(XEvent *e)
{
- unsigned int i;
+ XEvent event = *e;
+ Keychord *keychord;
+ unsigned int ran = 0;
KeySym keysym;
XKeyEvent *ev;
-
- ev = &e->xkey;
- keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
- for (i = 0; i < LENGTH(keys); i++)
- if (keysym == keys[i].keysym
- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
- keys[i].func(&(keys[i].arg));
+ Keychord *newoptions;
+ Keychord *oldoptions = (Keychord *)malloc(sizeof(keychords));
+
+ memcpy(oldoptions, keychords, sizeof(keychords));
+ size_t numoption = 0;
+ while(!ran){
+ ev = &event.xkey;
+ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+ newoptions = (Keychord *)malloc(0);
+ numoption = 0;
+ for (keychord = oldoptions; keychord->n != 0 && currentkey < 5; keychord = (Keychord *)((char *)keychord + sizeof(Keychord))){
+ if(keysym == keychord->keys[currentkey].keysym
+ && CLEANMASK(keychord->keys[currentkey].mod) == CLEANMASK(ev->state)
+ && keychord->func){
+ if(keychord->n == currentkey +1){
+ keychord->func(&(keychord->arg));
+ ran = 1;
+ }else{
+ numoption++;
+ newoptions = (Keychord *)realloc(newoptions, numoption * sizeof(Keychord));
+ memcpy((char *)newoptions + (numoption -1) * sizeof(Keychord),keychord, sizeof(Keychord));
+ }
+ }
+ }
+ currentkey++;
+ if(numoption == 0)
+ break;
+ grabkeys();
+ while (running && !XNextEvent(dpy, &event) && !ran)
+ if(event.type == KeyPress)
+ break;
+ free(oldoptions);
+ oldoptions = newoptions;
+ }
+ free(newoptions);
+ currentkey = 0;
+ grabkeys();
}
void
--
2.34.1

View file

@ -1,95 +0,0 @@
From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001
From: BrunoCooper17 <BrunoCooper17@outlook.com>
Date: Mon, 15 Nov 2021 14:04:53 -0600
Subject: [PATCH] MoveStack patch
This plugin allows you to move clients around in the stack and swap them
with the master. It emulates the behavior off mod+shift+j and mod+shift+k
in Xmonad. movestack(+1) will swap the client with the current focus with
the next client. movestack(-1) will swap the client with the current focus
with the previous client.
---
config.def.h | 3 +++
movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
create mode 100644 movestack.c
diff --git a/config.def.h b/config.def.h
index a2ac963..33efa5b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn()
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
+#include "movestack.c"
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
@@ -71,6 +72,8 @@ static Key keys[] = {
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
diff --git a/movestack.c b/movestack.c
new file mode 100644
index 0000000..520f4ae
--- /dev/null
+++ b/movestack.c
@@ -0,0 +1,48 @@
+void
+movestack(const Arg *arg) {
+ Client *c = NULL, *p = NULL, *pc = NULL, *i;
+
+ if(arg->i > 0) {
+ /* find the client after selmon->sel */
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+ if(!c)
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+
+ }
+ else {
+ /* find the client before selmon->sel */
+ for(i = selmon->clients; i != selmon->sel; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ if(!c)
+ for(; i; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ }
+ /* find the client before selmon->sel and c */
+ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
+ if(i->next == selmon->sel)
+ p = i;
+ if(i->next == c)
+ pc = i;
+ }
+
+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
+ if(c && c != selmon->sel) {
+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
+ selmon->sel->next = c->next==selmon->sel?c:c->next;
+ c->next = temp;
+
+ if(p && p != c)
+ p->next = c;
+ if(pc && pc != selmon->sel)
+ pc->next = selmon->sel;
+
+ if(selmon->sel == selmon->clients)
+ selmon->clients = c;
+ else if(c == selmon->clients)
+ selmon->clients = selmon->sel;
+
+ arrange(selmon);
+ }
+}
\ No newline at end of file
--
2.33.1

View file

@ -1,31 +0,0 @@
From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001
From: Aidan Hall <aidan.hall@outlook.com>
Date: Tue, 2 Jun 2020 14:41:53 +0000
Subject: [PATCH] Prevents hiding the border if layout is floating.
---
dwm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/dwm.c b/dwm.c
index 4465af1..2dd959d 100644
--- a/dwm.c
+++ b/dwm.c
@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
wc.border_width = c->bw;
+ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
+ || &monocle == c->mon->lt[c->mon->sellt]->arrange)
+ && !c->isfullscreen && !c->isfloating
+ && NULL != c->mon->lt[c->mon->sellt]->arrange) {
+ c->w = wc.width += c->bw * 2;
+ c->h = wc.height += c->bw * 2;
+ wc.border_width = 0;
+ }
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
--
2.26.2

View file

@ -1,177 +0,0 @@
diff --git a/dwm.c b/dwm.c
index 664c527..ac8e4ec 100644
--- a/dwm.c
+++ b/dwm.c
@@ -111,6 +111,7 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
+typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
@@ -130,6 +131,7 @@ struct Monitor {
Monitor *next;
Window barwin;
const Layout *lt[2];
+ Pertag *pertag;
};
typedef struct {
@@ -272,6 +274,15 @@ static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
+struct Pertag {
+ unsigned int curtag, prevtag; /* current and previous tag */
+ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
+ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
+ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
+ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */
+ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
+};
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
@@ -632,6 +643,7 @@ Monitor *
createmon(void)
{
Monitor *m;
+ unsigned int i;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
@@ -642,6 +654,20 @@ createmon(void)
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+ m->pertag = ecalloc(1, sizeof(Pertag));
+ m->pertag->curtag = m->pertag->prevtag = 1;
+
+ for (i = 0; i <= LENGTH(tags); i++) {
+ m->pertag->nmasters[i] = m->nmaster;
+ m->pertag->mfacts[i] = m->mfact;
+
+ m->pertag->ltidxs[i][0] = m->lt[0];
+ m->pertag->ltidxs[i][1] = m->lt[1];
+ m->pertag->sellts[i] = m->sellt;
+
+ m->pertag->showbars[i] = m->showbar;
+ }
+
return m;
}
@@ -967,7 +993,7 @@ grabkeys(void)
void
incnmaster(const Arg *arg)
{
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
arrange(selmon);
}
@@ -1502,9 +1528,9 @@ void
setlayout(const Arg *arg)
{
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- selmon->sellt ^= 1;
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
if (arg && arg->v)
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
if (selmon->sel)
arrange(selmon);
@@ -1523,7 +1549,7 @@ setmfact(const Arg *arg)
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
if (f < 0.05 || f > 0.95)
return;
- selmon->mfact = f;
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
arrange(selmon);
}
@@ -1702,7 +1728,7 @@ tile(Monitor *m)
void
togglebar(const Arg *arg)
{
- selmon->showbar = !selmon->showbar;
+ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
updatebarpos(selmon);
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
arrange(selmon);
@@ -1741,9 +1767,33 @@ void
toggleview(const Arg *arg)
{
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+ int i;
if (newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
+
+ if (newtagset == ~0) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = 0;
+ }
+
+ /* test if the user did not select the same tag */
+ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ for (i = 0; !(newtagset & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+
+ /* apply settings for this view */
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}
@@ -2038,11 +2088,37 @@ updatewmhints(Client *c)
void
view(const Arg *arg)
{
+ int i;
+ unsigned int tmptag;
+
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
selmon->seltags ^= 1; /* toggle sel tagset */
- if (arg->ui & TAGMASK)
+ if (arg->ui & TAGMASK) {
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+
+ if (arg->ui == ~0)
+ selmon->pertag->curtag = 0;
+ else {
+ for (i = 0; !(arg->ui & 1 << i); i++) ;
+ selmon->pertag->curtag = i + 1;
+ }
+ } else {
+ tmptag = selmon->pertag->prevtag;
+ selmon->pertag->prevtag = selmon->pertag->curtag;
+ selmon->pertag->curtag = tmptag;
+ }
+
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
+
+ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
+ togglebar(NULL);
+
focus(NULL);
arrange(selmon);
}

View file

@ -1,58 +0,0 @@
diff --git a/config.def.h b/config.def.h
index 7054c06..9b5d5b8 100644
--- a/config.def.h
+++ b/config.def.h
@@ -76,6 +76,7 @@ static Key keys[] = {
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY, XK_s, togglesticky, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
diff --git a/dwm.c b/dwm.c
index 0362114..0ef5c7f 100644
--- a/dwm.c
+++ b/dwm.c
@@ -49,7 +49,7 @@
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@@ -92,7 +92,7 @@ struct Client {
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky;
Client *next;
Client *snext;
Monitor *mon;
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglesticky(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -1713,6 +1714,15 @@ togglefloating(const Arg *arg)
}
void
+togglesticky(const Arg *arg)
+{
+ if (!selmon->sel)
+ return;
+ selmon->sel->issticky = !selmon->sel->issticky;
+ arrange(selmon);
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;

View file

@ -1,763 +0,0 @@
diff --git a/config.def.h b/config.def.h
index a2ac963..4be4c06 100644
--- a/config.def.h
+++ b/config.def.h
@@ -2,9 +2,14 @@
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
-static const unsigned int snap = 32; /* snap pixel */
-static const int showbar = 1; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
+static const int showbar = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
@@ -101,8 +106,8 @@ static Key keys[] = {
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ { ClkTagBar, MODKEY, Button1, tag, {0} },
+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
diff --git a/dwm.c b/dwm.c
index a96f33c..941c1c0 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,12 +57,27 @@
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+/* XEMBED messages */
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_FOCUS_IN 4
+#define XEMBED_MODALITY_ON 10
+#define XEMBED_MAPPED (1 << 0)
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_WINDOW_DEACTIVATE 2
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 0
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
+
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -141,6 +156,12 @@ typedef struct {
int monitor;
} Rule;
+typedef struct Systray Systray;
+struct Systray {
+ Window win;
+ Client *icons;
+};
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -172,6 +193,7 @@ static void focusstack(const Arg *arg);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
+static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -189,13 +211,16 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
+static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
+static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
+static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
-static int sendevent(Client *c, Atom proto);
+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
+static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
@@ -224,18 +250,23 @@ static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
+static void updatesystray(void);
+static void updatesystrayicongeom(Client *i, int w, int h);
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
+static Client *wintosystrayicon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
/* variables */
+static Systray *systray = NULL;
static const char broken[] = "broken";
static char stext[256];
static int screen;
@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
+ [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
-static Atom wmatom[WMLast], netatom[NetLast];
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
@@ -440,7 +472,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
+ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -483,7 +515,14 @@ cleanup(void)
XUngrabKey(dpy, AnyKey, AnyModifier, root);
while (mons)
cleanupmon(mons);
- for (i = 0; i < CurLast; i++)
+
+ if (showsystray) {
+ XUnmapWindow(dpy, systray->win);
+ XDestroyWindow(dpy, systray->win);
+ free(systray);
+ }
+
+ for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
@@ -513,9 +552,58 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
+ XWindowAttributes wa;
+ XSetWindowAttributes swa;
XClientMessageEvent *cme = &e->xclient;
Client *c = wintoclient(cme->window);
+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
+ /* add systray icons */
+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if (!(c = (Client *)calloc(1, sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+ if (!(c->win = cme->data.l[2])) {
+ free(c);
+ return;
+ }
+ c->mon = selmon;
+ c->next = systray->icons;
+ systray->icons = c;
+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
+ /* use sane defaults */
+ wa.width = bh;
+ wa.height = bh;
+ wa.border_width = 0;
+ }
+ c->x = c->oldx = c->y = c->oldy = 0;
+ c->w = c->oldw = wa.width;
+ c->h = c->oldh = wa.height;
+ c->oldbw = wa.border_width;
+ c->bw = 0;
+ c->isfloating = True;
+ /* reuse tags field as mapped status */
+ c->tags = 1;
+ updatesizehints(c);
+ updatesystrayicongeom(c, wa.width, wa.height);
+ XAddToSaveSet(dpy, c->win);
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
+ /* use parents background color */
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ /* FIXME not sure if I have to send these events, too */
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ XSync(dpy, False);
+ resizebarwin(selmon);
+ updatesystray();
+ setclientstate(c, NormalState);
+ }
+ return;
+ }
+
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
@@ -568,7 +656,7 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ resizebarwin(m);
}
focus(NULL);
arrange(NULL);
@@ -653,6 +741,11 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((c = wintosystrayicon(ev->window))) {
+ removesystrayicon(c);
+ resizebarwin(selmon);
+ updatesystray();
+ }
}
void
@@ -696,7 +789,7 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- int x, w, tw = 0;
+ int x, w, tw = 0, stw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
@@ -705,13 +798,17 @@ drawbar(Monitor *m)
if (!m->showbar)
return;
+ if(showsystray && m == systraytomon(m) && !systrayonleft)
+ stw = getsystraywidth();
+
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]);
- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */
+ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0);
}
+ resizebarwin(m);
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
@@ -732,7 +829,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
- if ((w = m->ww - tw - x) > bh) {
+ if ((w = m->ww - tw - stw - x) > bh) {
if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
@@ -743,7 +840,7 @@ drawbar(Monitor *m)
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
}
void
@@ -780,8 +877,11 @@ expose(XEvent *e)
Monitor *m;
XExposeEvent *ev = &e->xexpose;
- if (ev->count == 0 && (m = wintomon(ev->window)))
+ if (ev->count == 0 && (m = wintomon(ev->window))) {
drawbar(m);
+ if (m == selmon)
+ updatesystray();
+ }
}
void
@@ -867,9 +967,17 @@ getatomprop(Client *c, Atom prop)
unsigned char *p = NULL;
Atom da, atom = None;
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
+ /* FIXME getatomprop should return the number of items and a pointer to
+ * the stored data instead of this workaround */
+ Atom req = XA_ATOM;
+ if (prop == xatom[XembedInfo])
+ req = xatom[XembedInfo];
+
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
+ if (da == xatom[XembedInfo] && dl == 2)
+ atom = ((Atom *)p)[1];
XFree(p);
}
return atom;
@@ -903,6 +1011,16 @@ getstate(Window w)
return result;
}
+unsigned int
+getsystraywidth()
+{
+ unsigned int w = 0;
+ Client *i;
+ if(showsystray)
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
+ return w ? w + systrayspacing : 1;
+}
+
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1007,7 +1125,8 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
+
+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
@@ -1096,6 +1215,13 @@ maprequest(XEvent *e)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ Client *i;
+ if ((i = wintosystrayicon(ev->window))) {
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+
if (!XGetWindowAttributes(dpy, ev->window, &wa))
return;
if (wa.override_redirect)
@@ -1219,7 +1345,18 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
+ if ((c = wintosystrayicon(ev->window))) {
+ if (ev->atom == XA_WM_NORMAL_HINTS) {
+ updatesizehints(c);
+ updatesystrayicongeom(c, c->w, c->h);
+ }
+ else
+ updatesystrayiconstate(c, ev);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
return; /* ignore */
@@ -1269,6 +1406,19 @@ recttomon(int x, int y, int w, int h)
return r;
}
+void
+removesystrayicon(Client *i)
+{
+ Client **ii;
+
+ if (!showsystray || !i)
+ return;
+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
+ if (ii)
+ *ii = i->next;
+ free(i);
+}
+
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
@@ -1276,6 +1426,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
resizeclient(c, x, y, w, h);
}
+void
+resizebarwin(Monitor *m) {
+ unsigned int w = m->ww;
+ if (showsystray && m == systraytomon(m) && !systrayonleft)
+ w -= getsystraywidth();
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+}
+
void
resizeclient(Client *c, int x, int y, int w, int h)
{
@@ -1348,6 +1506,19 @@ resizemouse(const Arg *arg)
}
}
+void
+resizerequest(XEvent *e)
+{
+ XResizeRequestEvent *ev = &e->xresizerequest;
+ Client *i;
+
+ if ((i = wintosystrayicon(ev->window))) {
+ updatesystrayicongeom(i, ev->width, ev->height);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+}
+
void
restack(Monitor *m)
{
@@ -1437,26 +1608,37 @@ setclientstate(Client *c, long state)
}
int
-sendevent(Client *c, Atom proto)
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
{
int n;
- Atom *protocols;
+ Atom *protocols, mt;
int exists = 0;
XEvent ev;
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
+ mt = wmatom[WMProtocols];
+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
+ while (!exists && n--)
+ exists = protocols[n] == proto;
+ XFree(protocols);
+ }
}
+ else {
+ exists = True;
+ mt = proto;
+ }
+
if (exists) {
ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
+ ev.xclient.window = w;
+ ev.xclient.message_type = mt;
ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
+ ev.xclient.data.l[0] = d0;
+ ev.xclient.data.l[1] = d1;
+ ev.xclient.data.l[2] = d2;
+ ev.xclient.data.l[3] = d3;
+ ev.xclient.data.l[4] = d4;
+ XSendEvent(dpy, w, False, mask, &ev);
}
return exists;
}
@@ -1470,7 +1652,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
- sendevent(c, wmatom[WMTakeFocus]);
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
}
void
@@ -1558,15 +1740,22 @@ setup(void)
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
- /* init cursors */
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
+ /* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
@@ -1574,6 +1763,8 @@ setup(void)
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
+ /* init system tray */
+ updatesystray();
/* init bars */
updatebars();
updatestatus();
@@ -1707,7 +1898,18 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ resizebarwin(selmon);
+ if (showsystray) {
+ XWindowChanges wc;
+ if (!selmon->showbar)
+ wc.y = -bh;
+ else if (selmon->showbar) {
+ wc.y = 0;
+ if (!selmon->topbar)
+ wc.y = selmon->mh - bh;
+ }
+ XConfigureWindow(dpy, systray->win, CWY, &wc);
+ }
arrange(selmon);
}
@@ -1802,11 +2004,18 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
+ else if ((c = wintosystrayicon(ev->window))) {
+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
+ * _not_ destroy them. We map those windows back */
+ XMapRaised(dpy, c->win);
+ updatesystray();
+ }
}
void
updatebars(void)
{
+ unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -1817,10 +2026,15 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
+ if (showsystray && m == systraytomon(m))
+ XMapRaised(dpy, systray->win);
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
@@ -1996,6 +2210,125 @@ updatestatus(void)
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
+ updatesystray();
+}
+
+
+void
+updatesystrayicongeom(Client *i, int w, int h)
+{
+ if (i) {
+ i->h = bh;
+ if (w == h)
+ i->w = bh;
+ else if (h == bh)
+ i->w = w;
+ else
+ i->w = (int) ((float)bh * ((float)w / (float)h));
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
+ /* force icons into the systray dimensions if they don't want to */
+ if (i->h > bh) {
+ if (i->w == i->h)
+ i->w = bh;
+ else
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
+ i->h = bh;
+ }
+ }
+}
+
+void
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
+{
+ long flags;
+ int code = 0;
+
+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
+ !(flags = getatomprop(i, xatom[XembedInfo])))
+ return;
+
+ if (flags & XEMBED_MAPPED && !i->tags) {
+ i->tags = 1;
+ code = XEMBED_WINDOW_ACTIVATE;
+ XMapRaised(dpy, i->win);
+ setclientstate(i, NormalState);
+ }
+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
+ i->tags = 0;
+ code = XEMBED_WINDOW_DEACTIVATE;
+ XUnmapWindow(dpy, i->win);
+ setclientstate(i, WithdrawnState);
+ }
+ else
+ return;
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
+ systray->win, XEMBED_EMBEDDED_VERSION);
+}
+
+void
+updatesystray(void)
+{
+ XSetWindowAttributes wa;
+ XWindowChanges wc;
+ Client *i;
+ Monitor *m = systraytomon(NULL);
+ unsigned int x = m->mx + m->mw;
+ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing;
+ unsigned int w = 1;
+
+ if (!showsystray)
+ return;
+ if (systrayonleft)
+ x -= sw + lrpad / 2;
+ if (!systray) {
+ /* init systray */
+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
+ wa.event_mask = ButtonPressMask | ExposureMask;
+ wa.override_redirect = True;
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
+ XMapRaised(dpy, systray->win);
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
+ XSync(dpy, False);
+ }
+ else {
+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
+ free(systray);
+ systray = NULL;
+ return;
+ }
+ }
+ for (w = 0, i = systray->icons; i; i = i->next) {
+ /* make sure the background color stays the same */
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
+ XMapRaised(dpy, i->win);
+ w += systrayspacing;
+ i->x = w;
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
+ w += i->w;
+ if (i->mon != m)
+ i->mon = m;
+ }
+ w = w ? w + systrayspacing : 1;
+ x -= w;
+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
+ wc.stack_mode = Above; wc.sibling = m->barwin;
+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
+ XMapWindow(dpy, systray->win);
+ XMapSubwindows(dpy, systray->win);
+ /* redraw background */
+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
+ XSync(dpy, False);
}
void
@@ -2063,6 +2396,16 @@ wintoclient(Window w)
return NULL;
}
+Client *
+wintosystrayicon(Window w) {
+ Client *i = NULL;
+
+ if (!showsystray || !w)
+ return i;
+ for (i = systray->icons; i && i->win != w; i = i->next) ;
+ return i;
+}
+
Monitor *
wintomon(Window w)
{
@@ -2116,6 +2459,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
return -1;
}
+Monitor *
+systraytomon(Monitor *m) {
+ Monitor *t;
+ int i, n;
+ if(!systraypinning) {
+ if(!m)
+ return selmon;
+ return m == selmon ? m : NULL;
+ }
+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
+ if(systraypinningfailfirst && n < systraypinning)
+ return mons;
+ return t;
+}
+
void
zoom(const Arg *arg)
{

6
renovate.json Normal file
View file

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -1,51 +0,0 @@
# dwm - dynamic window manager
# See LICENSE file for copyright and license details.
include config.mk
SRC = drw.c dwm.c util.c
OBJ = ${SRC:.c=.o}
all: options dwm
options:
@echo dwm build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
config.h:
cp config.def.h $@
dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
dist: clean
mkdir -p dwm-${VERSION}
cp -R LICENSE Makefile README config.def.h config.mk\
dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwm ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < ../dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall

44
src/actions.h Normal file
View file

@ -0,0 +1,44 @@
//
// Created by anas on 10/31/22.
//
#ifndef ACTIONS_H
#define ACTIONS_H
#include "archy_dwm.h"
static void focusmon(const Arg *arg);
static void fullscreen(const Arg *arg);
static void focusstack(const Arg *arg);
static void tagmon(const Arg *arg);
static void incnmaster(const Arg *arg);
static void killclient(const Arg *arg);
static void movemouse(const Arg *arg);
static void togglebar(const Arg *arg);
static void togglesticky(const Arg *arg);
static void togglefloating(const Arg *arg);
static void setmfact(const Arg *arg);
static void view(const Arg *arg);
static void movestack(const Arg *arg);
static void setlayout(const Arg *arg);
static void tag(const Arg *arg);
static void zoom(const Arg *arg);
static void quit(const Arg *arg);
#endif //ACTIONS_H

2327
src/archy_dwm.c Normal file

File diff suppressed because it is too large Load diff

273
src/archy_dwm.h Normal file
View file

@ -0,0 +1,273 @@
//
// Created by anas on 10/31/22.
//
#ifndef ARCHY_DWM_H
#define ARCHY_DWM_H
/* enums */
enum {
CurNormal, CurResize, CurMove, CurLast
}; /* cursor */
enum {
SchemeNorm, SchemeSel, SchemeUrg
}; /* color schemes */
enum {
NetSupported, NetWMName, NetWMState, NetWMCheck,
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast
}; /* EWMH atoms */
enum {
Manager, Xembed, XembedInfo, XLast
}; /* Xembed atoms */
enum {
WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast
}; /* default atoms */
typedef union {
int i;
unsigned int ui;
float f;
const void *v;
} Arg;
typedef struct Monitor Monitor;
typedef struct Client Client;
struct Client {
char name[256];
float mina, maxa;
int x, y, w, h;
int oldx, oldy, oldw, oldh;
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky;
Client *next;
Client *snext;
Monitor *mon;
Window win;
};
typedef struct {
const char *symbol;
void (*arrange)(Monitor *);
} Layout;
typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
int nmaster;
int num;
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
int showbar;
int topbar;
Client *clients;
Client *sel;
Client *stack;
Monitor *next;
Window barwin;
const Layout *lt[2];
Pertag *pertag;
};
typedef struct {
const char *class;
const char *instance;
const char *title;
unsigned int tags;
int isfloating;
int monitor;
} Rule;
typedef struct Systray Systray;
struct Systray {
Window win;
Client *icons;
};
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static Monitor *createmon(void);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
static Monitor *dirtomon(int dir);
static void drawbar(Monitor *m);
static void drawbars(void);
static void enternotify(XEvent *e);
static void expose(XEvent *e);
static void focus(Client *c);
static void focusin(XEvent *e);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
static void keypress(XEvent *e);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void motionnotify(XEvent *e);
static Client *nexttiled(Client *c);
static void pop(Client *);
static void propertynotify(XEvent *e);
static Monitor *recttomon(int x, int y, int w, int h);
static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static Monitor *systraytomon(Monitor *m);
static void tile(Monitor *);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
static void unmapnotify(XEvent *e);
static void updatebarpos(Monitor *m);
static void updatebars(void);
static void updateclientlist(void);
static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
static void updatesystray(void);
static void updatesystrayicongeom(Client *i, int w, int h);
static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static Client *wintosystrayicon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void autostart_exec(void);
#endif //ARCHY_DWM_H

View file

@ -1,29 +0,0 @@
#ifndef colors_H
#define colors_H
// #define wal "/home/anas/.cache/wal/colors-wal-dwm.h"
// #if __has_include(wal)
// #include wal
// #else
static const char norm_fg[] = "#e4ded4";
static const char norm_bg[] = "#191b1f";
static const char norm_border[] = "#282c34";
static const char sel_fg[] = "#e4ded4";
static const char sel_bg[] = "#3f2124";
static const char sel_border[] = "#e4ded4";
static const char urg_fg[] = "#e4ded4";
static const char urg_bg[] = "#313036";
static const char urg_border[] = "#312e36";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { norm_fg, norm_bg, norm_border }, // unfocused wins
[SchemeSel] = { sel_fg, sel_bg, sel_border }, // the focused win
[SchemeUrg] = { urg_fg, urg_bg, urg_border },
};
// #endif
#endif // !colors.h

23
src/colors/defualt.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef colors_H
#define colors_H
static const char norm_fg[] = "#e4ded4";
static const char norm_bg[] = "#191b1f";
static const char norm_border[] = "#282c34";
static const char sel_fg[] = "#e4ded4";
static const char sel_bg[] = "#3f2124";
static const char sel_border[] = "#e4ded4";
static const char urg_fg[] = "#e4ded4";
static const char urg_bg[] = "#313036";
static const char urg_border[] = "#312e36";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {norm_fg, norm_bg, norm_border}, // unfocused wins
[SchemeSel] = {sel_fg, sel_bg, sel_border}, // the focused win
[SchemeUrg] = {urg_fg, urg_bg, urg_border},
};
#endif // colors_H

28
src/colors/dracula.h Normal file
View file

@ -0,0 +1,28 @@
//
// Created by anas on 10/31/22.
//
// inspired from: https://github.com/0x73hahd/dwm-config/blob/dev/source/colors/dracula.h
#ifndef DRACULA_H
#define DRACULA_H
static const char norm_fg[] = "#ff79c6";
static const char norm_bg[] = "#282a36";
static const char norm_border[] = "#282a36";
static const char sel_fg[] = "#ffb86c";
static const char sel_bg[] = "#282a36";
static const char sel_border[] = "#ffb86c";
static const char urg_fg[] = "#e4ded4";
static const char urg_bg[] = "#313036";
static const char urg_border[] = "#312e36";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {norm_fg, norm_bg, norm_border}, // unfocused wins
[SchemeSel] = {sel_fg, sel_bg, sel_border}, // the focused win
[SchemeUrg] = {urg_fg, urg_bg, urg_border},
};
#endif //DRACULA_H

View file

@ -0,0 +1,26 @@
//
// Created by anas on 08/28/23.
//
#ifndef GRUVBOX_DARK_HARD_H
#define GRUVBOX_DARK_HARD_H
static const char norm_fg[] = "#D5C4A1"; // light2
static const char norm_bg[] = "#1D2021"; // dark0_hard
static const char norm_border[] = "#504945"; // dark2
static const char sel_fg[] = "#D79921"; // neutral_yellow
static const char sel_bg[] = "#1D2021"; // dark0_hard
static const char sel_border[] = "#7C6F64"; // dark4
static const char urg_fg[] = "#D5C4A1"; // light4
static const char urg_bg[] = "#FB4934"; // bright_red
static const char urg_border[] = "#458588"; // neutral_blue
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {norm_fg, norm_bg, norm_border}, // unfocused wins
[SchemeSel] = {sel_fg, sel_bg, sel_border}, // the focused win
[SchemeUrg] = {urg_fg, urg_bg, urg_border},
};
#endif //GRUVBOX_DARK_HARD_H

View file

@ -1,68 +0,0 @@
/* See LICENSE file for copyright and license details. */
/* def */
#define WEBBROWSER "google-chrome-stable"
#define TERMINAL "alacritty"
#define SCREENSHOT "spectacle"
#define GUI_FILEMANAGER "pcmanfm"
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 3; /* gaps size between windows */
static const unsigned int snap = 32; /* snap pixel */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=11", "Noto Color Emoji:size=11", "Nerd Font Mono:weight=bold:size=15:antialias=true:hinting=true" };
static const char dmenufont[] = "monospace:size=11";
static const char col_1[] = "#282c34"; // Background color of bar
static const char col_2[] = "#282c34"; // Background color of unfocused windows border
static const char col_3[] = "#d7d7d7";
static const char col_4[] = "#018858"; // Background color of focused windows border and tags (main color acent)
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_3, col_1, col_2 },
[SchemeSel] = { col_3, col_4, col_4 },
};
// Autostart programs
static const char *const autostart[] = {
// Start my build of slstatus
"slstatus", NULL,
// Keyboard layouts switch (requires setxkbmap)
"setxkbmap", "-model", "pc101", "-layout", "us,ar", "-variant", ",,", "-option", "grp:win_space_toggle", NULL,
// "xkbset", "exp", "=sticky", "-twokey", "-latchlock", NULL, // sticky keys
"/bin/stickykeys", NULL, // sticky keys script
"picom", NULL, // Start compositor , for transparency
"nitrogen", "--restore", NULL, // Restores the wallpaper
"nm-applet", NULL, // Start the network manger
"copyq", NULL, // clipboard manger
NULL /* terminate */
};
/* tagging */
// static const char *tags[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ WEBBROWSER, NULL, NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
#include "layouts/layouts.h"
#include "movestack.c"
#include "keys/keys.h"

View file

@ -1,63 +0,0 @@
/* See LICENSE file for copyright and license details. */
/* def */
#define WEBBROWSER "google-chrome-stable"
#define TERMINAL "alacritty"
#define SCREENSHOT "spectacle"
#define GUI_FILEMANAGER "pcmanfm"
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 3; /* gaps size between windows */
static const unsigned int snap = 32; /* snap pixel */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 0; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=7", "Noto Color Emoji:size=8", "Nerd Font Mono:size=16:antialias=true:hinting=true" };
static const char dmenufont[] = "monospace:size=8";
#include "colors.h"
// Autostart programs
static const char *const autostart[] = {
// Start my build of slstatus
"slstatus", NULL,
// Keyboard layouts switch (requires setxkbmap)
"setxkbmap", "-model", "pc101", "-layout", "us,ar", "-variant", ",,", "-option", "grp:win_space_toggle", NULL,
// "xkbset", "exp", "=sticky", "-twokey", "-latchlock", NULL, // sticky keys
"/bin/stickykeys", NULL, // sticky keys script
"picom", NULL, // Start compositor , for transparency
"nitrogen", "--restore", NULL, // Restores the wallpaper
"nm-applet", NULL, // Start the network manger
"copyq", NULL, // clipboard manger
NULL /* terminate */
};
/* tagging */
// static const char *tags[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
// static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
static const char *tags[] = { "www", "dev", "sys", "chat", "img", "vid", "mus", "vbox", "gfx", ";" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ WEBBROWSER, NULL, NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
#include "layouts/layouts.h"
#include "movestack.c"
#include "keys/keys.h"

100
src/config/config.h Normal file
View file

@ -0,0 +1,100 @@
#ifndef CONFIG_H
#define CONFIG_H
/* def */
#define TERMINAL "st"
#ifndef STDDEF_H
#include <stddef.h>
#endif
#ifndef ARCHY_DWM_H
#include "../archy_dwm.h"
#endif
#include "keys.h"
#include "mouse.h"
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 3; /* gaps size between windows */
static const unsigned int snap = 32; /* snap pixel */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayonleft = -1; /* 0: systray in the right corner, >0: systray on left of status text */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 0; /* 0 means bottom bar */
static const char *fonts[] = {
"monospace:size=6", "Noto Color Emoji:size=7",
"Nerd Font Mono:size=10:antialias=true:hinting=true"};
static const char dmenufont[] = "monospace:size=8";
/* Colors - Gruvbox dark hard */
static const char norm_fg[] = "#D5C4A1"; // light2
static const char norm_bg[] = "#1D2021"; // dark0_hard
static const char norm_border[] = "#504945"; // dark2
static const char sel_fg[] = "#D79921"; // neutral_yellow
static const char sel_bg[] = "#1D2021"; // dark0_hard
static const char sel_border[] = "#7C6F64"; // dark4
static const char urg_fg[] = "#D5C4A1"; // light4
static const char urg_bg[] = "#FB4934"; // bright_red
static const char urg_border[] = "#458588"; // neutral_blue
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = {norm_fg, norm_bg, norm_border}, // unfocused wins
[SchemeSel] = {sel_fg, sel_bg, sel_border}, // the focused win
[SchemeUrg] = {urg_fg, urg_bg, urg_border},
};
// Autostart programs
static const char *const autostart[] = {
// Start my build of slstatus
"archy-slstatus", NULL,
NULL /* terminate */
};
/* tagging */
// static const char *tags[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
// static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
static const char *tags[] = {"www", "dev", "sys", "chat", "lab", "vid", "mus", "vbox", "gfx", ";"};
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
* It's just a bitwise shift. Binary of 5 is 101, then you shift it left on
*6 and get 101000000, which means 7 and 9 in dwm ( because 1-s are on 7 and
*9 position from right).
* https://www.reddit.com/r/dwm/comments/f2omo9/comment/fjr93yt/?utm_source=share&utm_medium=web2x&context=3
*/
/* class instance title tags mask isfloating monitor */
{"Gimp", NULL, NULL, 9 << 8, 1, -1}, // 0100000000 (gfx tag)
{"Tor Browser", "Navigator", NULL, 9 << 9, 0,-1}, // Open it in tag 10 (9 in array) (; tag)
{"KeePassXC", "keepassxc", NULL, 9 << 9, 0, -1}, // 1000000000 (; tag)
{"firefoxdeveloperedition", "Navigator", NULL, 1 << 0, 0,-1}, // 0000000001 (www tag)
//{"discord", NULL, NULL, 4 << 1, 0, -1}, // 0000001000 (chat tag)
{"Virt-manager", "virt-manager", NULL, 9 << 7, 0,-1}, // 0010000000 (vbox tag)
{"VirtualBox Manager", "VirtualBox Manager", NULL, 9 << 7, 0,1}, // 0010000000 (vbox tag)
{NULL, "open.spotify.com", NULL, 8 << 3, 0, -1}, // 0001000000 (mus tag)
{"cmus", NULL, NULL, 8 << 3, 0, -1}, // 0001000000 (mus tag)
{"jetbrains-clion", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-idea", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-pycharm", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-studio", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-webstorm", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-phpstorm", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-rubymine", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-goland", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"jetbrains-datagrip", NULL, NULL, 1 << 1, 0, -1}, // 0000000010 (dev tag)
{"PacketTracer", NULL, NULL, 1 << 4, 0, -1} // 0000010000 (lab tag)
};
/* layout(s) */
static const float mfact = 0.60f; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
#endif // CONFIG_H

97
src/config/keys.h Normal file
View file

@ -0,0 +1,97 @@
#ifndef KEYS_H
#define KEYS_H
#include "../archy_dwm.h"
#include <X11/X.h>
typedef struct {
unsigned int mod;
KeySym keysym;
void (*func)(const Arg *);
const Arg arg;
} Key;
/* key definitions */
#define MODKEY Mod4Mask // The super key
#define TAGKEYS(KEY, TAG) \
{MODKEY, KEY, view, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \
{MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \
{MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}},
#ifndef ACTIONS_H
#include "../actions.h"
#endif //ACTIONS_H
#ifndef LAYOUTS_H
#include "../layouts/layouts.h"
#endif //LAYOUTS_H
// X11 keysym definitions
#include <X11/XF86keysym.h> // req (libxinerama1 and libxinerama-dev)
#include <X11/keysym.h>
static Key keys[] = {
/* modifier key function argument */
{MODKEY, XK_f, fullscreen, {0}},
{MODKEY|ShiftMask, XK_b, togglebar, {0}},
// Change the focus
{MODKEY, XK_e, focusstack, {.i = +1}},
{MODKEY, XK_a, focusstack, {.i = -1}},
// incress and decrees the masters
{MODKEY, XK_i, incnmaster, {.i = +1}},
{MODKEY, XK_d, incnmaster, {.i = -1}},
// Change the focus window size (in the tile mode)
{MODKEY, XK_equal, setmfact, {.f = -0.05f}},
{MODKEY, XK_minus, setmfact, {.f = +0.05f}},
{MODKEY, XK_Tab, view, {0}},
{MODKEY | ShiftMask, XK_e, movestack, {.i = +1}},
{MODKEY | ShiftMask, XK_a, movestack, {.i = -1}},
// Toogle styky mode
{MODKEY | ShiftMask, XK_s, togglesticky, {0}},
// Quit from the foucsed window (kill)
{MODKEY|ShiftMask, XK_q, killclient, {0}},
/************************* Switch between layouts *************************/
// Tiled layout
{MODKEY, XK_t, setlayout, {.v = &layouts[0]}},
// Floating layout
{MODKEY, XK_f, setlayout, {.v = &layouts[1]}},
// Monocle layout
{MODKEY, XK_m, setlayout, {.v = &layouts[2]}},
// Grid layout
{MODKEY, XK_g, setlayout, {.v = &layouts[3]}},
// Spiral layout
{MODKEY, XK_r, setlayout, {.v = &layouts[4]}},
// Dwindle layout
{MODKEY, XK_d, setlayout, {.v = &layouts[5]}},
// Centerd master layout
{MODKEY, XK_c, setlayout, {.v = &layouts[6]}},
// Centerd floating master layout
{MODKEY, XK_x, setlayout, {.v = &layouts[7]}},
// Toggle between current layout and tile layout
{MODKEY, XK_s, setlayout, {0}},
// Toggle floating window
{MODKEY | ShiftMask, XK_f, togglefloating, {0}},
// Mirror the current tagg in all tags
{MODKEY, XK_0, tag, {.ui = ~0}},
// Multi monitor stuff
{MODKEY, XK_comma, focusmon, {.i = -1}},
{MODKEY, XK_period, focusmon, {.i = +1}},
{MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}},
{MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}},
/************************* Tag keys *************************/
TAGKEYS(XK_1, 0)
TAGKEYS(XK_2, 1)
TAGKEYS(XK_3, 2)
TAGKEYS(XK_4, 3)
TAGKEYS(XK_5, 4)
TAGKEYS(XK_6, 5)
TAGKEYS(XK_7, 6)
TAGKEYS(XK_8, 7)
TAGKEYS(XK_9, 8)
TAGKEYS(XK_semicolon, 9)
};
#endif // keys_H

40
src/config/mouse.h Normal file
View file

@ -0,0 +1,40 @@
//
// Created by anas on 10/31/22.
//
#ifndef MOUSE_H
#define MOUSE_H
#include <X11/X.h>
typedef struct {
unsigned int click;
unsigned int mask;
unsigned int button;
void (*func)(const Arg *arg);
const Arg arg;
} Button;
enum {
ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast
}; /* clicks */
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ClkTagBar, MODKEY, Button1, tag, {0}},
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
{ClkClientWin, MODKEY, Button1, movemouse, {0}},
{ClkClientWin, MODKEY, Button2, togglefloating, {0}},
{ClkClientWin, MODKEY, Button3, resizemouse, {0}},
{ClkTagBar, 0, Button1, view, {0}},
{ClkTagBar, 0, Button3, toggleview, {0}},
{ClkTagBar, MODKEY, Button1, tag, {0}},
{ClkTagBar, MODKEY, Button3, toggletag, {0}},
};
#endif //MOUSE_H

642
src/drw.c
View file

@ -11,441 +11,421 @@
#define UTF_INVALID 0xFFFD #define UTF_INVALID 0xFFFD
#define UTF_SIZ 4 #define UTF_SIZ 4
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; static const long utfmin[UTF_SIZ + 1] = {0, 0, 0x80, 0x800, 0x10000};
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
static long static long
utf8decodebyte(const char c, size_t *i) utf8decodebyte(const char c, size_t *i) {
{ for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) if (((unsigned char) c & utfmask[*i]) == utfbyte[*i])
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) return (unsigned char) c & ~utfmask[*i];
return (unsigned char)c & ~utfmask[*i]; return 0;
return 0;
} }
static size_t static size_t
utf8validate(long *u, size_t i) utf8validate(long *u, size_t i) {
{ if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) *u = UTF_INVALID;
*u = UTF_INVALID; for (i = 1; *u > utfmax[i]; ++i);
for (i = 1; *u > utfmax[i]; ++i) return i;
;
return i;
} }
static size_t static size_t
utf8decode(const char *c, long *u, size_t clen) utf8decode(const char *c, long *u, size_t clen) {
{ size_t i, j, len, type;
size_t i, j, len, type; long udecoded;
long udecoded;
*u = UTF_INVALID; *u = UTF_INVALID;
if (!clen) if (!clen)
return 0; return 0;
udecoded = utf8decodebyte(c[0], &len); udecoded = utf8decodebyte(c[0], &len);
if (!BETWEEN(len, 1, UTF_SIZ)) if (!BETWEEN(len, 1, UTF_SIZ))
return 1; return 1;
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
if (type) if (type)
return j; return j;
} }
if (j < len) if (j < len)
return 0; return 0;
*u = udecoded; *u = udecoded;
utf8validate(u, len); utf8validate(u, len);
return len; return len;
} }
Drw * Drw *
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) {
{ Drw *drw = ecalloc(1, sizeof(Drw));
Drw *drw = ecalloc(1, sizeof(Drw));
drw->dpy = dpy; drw->dpy = dpy;
drw->screen = screen; drw->screen = screen;
drw->root = root; drw->root = root;
drw->w = w; drw->w = w;
drw->h = h; drw->h = h;
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
drw->gc = XCreateGC(dpy, root, 0, NULL); drw->gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw; return drw;
} }
void void
drw_resize(Drw *drw, unsigned int w, unsigned int h) drw_resize(Drw *drw, unsigned int w, unsigned int h) {
{ if (!drw)
if (!drw) return;
return;
drw->w = w; drw->w = w;
drw->h = h; drw->h = h;
if (drw->drawable) if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable); XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
} }
void void
drw_free(Drw *drw) drw_free(Drw *drw) {
{ XFreePixmap(drw->dpy, drw->drawable);
XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc);
XFreeGC(drw->dpy, drw->gc); drw_fontset_free(drw->fonts);
drw_fontset_free(drw->fonts); free(drw);
free(drw);
} }
/* This function is an implementation detail. Library users should use /* This function is an implementation detail. Library users should use
* drw_fontset_create instead. * drw_fontset_create instead.
*/ */
static Fnt * static Fnt *
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) {
{ Fnt *font;
Fnt *font; XftFont *xfont = NULL;
XftFont *xfont = NULL; FcPattern *pattern = NULL;
FcPattern *pattern = NULL;
if (fontname) { if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield the /* Using the pattern found at font->xfont->pattern does not yield the
* same substitution results as using the pattern returned by * same substitution results as using the pattern returned by
* FcNameParse; using the latter results in the desired fallback * FcNameParse; using the latter results in the desired fallback
* behaviour whereas the former just results in missing-character * behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */ * rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
return NULL; return NULL;
} }
if (!(pattern = FcNameParse((FcChar8 *) fontname))) { if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
XftFontClose(drw->dpy, xfont); XftFontClose(drw->dpy, xfont);
return NULL; return NULL;
} }
} else if (fontpattern) { } else if (fontpattern) {
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
fprintf(stderr, "error, cannot load font from pattern.\n"); fprintf(stderr, "error, cannot load font from pattern.\n");
return NULL; return NULL;
} }
} else { } else {
die("no font specified."); die("no font specified.");
} }
font = ecalloc(1, sizeof(Fnt)); font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont; font->xfont = xfont;
font->pattern = pattern; font->pattern = pattern;
font->h = xfont->ascent + xfont->descent; font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy; font->dpy = drw->dpy;
return font; return font;
} }
static void static void
xfont_free(Fnt *font) xfont_free(Fnt *font) {
{ if (!font)
if (!font) return;
return; if (font->pattern)
if (font->pattern) FcPatternDestroy(font->pattern);
FcPatternDestroy(font->pattern); XftFontClose(font->dpy, font->xfont);
XftFontClose(font->dpy, font->xfont); free(font);
free(font);
} }
Fnt* Fnt *
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount) {
{ Fnt *cur, *ret = NULL;
Fnt *cur, *ret = NULL; size_t i;
size_t i;
if (!drw || !fonts) if (!drw || !fonts)
return NULL; return NULL;
for (i = 1; i <= fontcount; i++) { for (i = 1; i <= fontcount; i++) {
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
cur->next = ret; cur->next = ret;
ret = cur; ret = cur;
} }
} }
return (drw->fonts = ret); return (drw->fonts = ret);
} }
void void
drw_fontset_free(Fnt *font) drw_fontset_free(Fnt *font) {
{ if (font) {
if (font) { drw_fontset_free(font->next);
drw_fontset_free(font->next); xfont_free(font);
xfont_free(font); }
}
} }
void void
drw_clr_create(Drw *drw, Clr *dest, const char *clrname) drw_clr_create(Drw *drw, Clr *dest, const char *clrname) {
{ if (!drw || !dest || !clrname)
if (!drw || !dest || !clrname) return;
return;
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen),
clrname, dest)) clrname, dest))
die("error, cannot allocate color '%s'", clrname); die("error, cannot allocate color '%s'", clrname);
} }
/* Wrapper to create color schemes. The caller has to call free(3) on the /* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */ * returned color scheme when done using it. */
Clr * Clr *
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) {
{ size_t i;
size_t i; Clr *ret;
Clr *ret;
/* need at least two colors for a scheme */ /* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL; return NULL;
for (i = 0; i < clrcount; i++) for (i = 0; i < clrcount; i++)
drw_clr_create(drw, &ret[i], clrnames[i]); drw_clr_create(drw, &ret[i], clrnames[i]);
return ret; return ret;
} }
void void
drw_setfontset(Drw *drw, Fnt *set) drw_setfontset(Drw *drw, Fnt *set) {
{ if (drw)
if (drw) drw->fonts = set;
drw->fonts = set;
} }
void void
drw_setscheme(Drw *drw, Clr *scm) drw_setscheme(Drw *drw, Clr *scm) {
{ if (drw)
if (drw) drw->scheme = scm;
drw->scheme = scm;
} }
void void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) {
{ if (!drw || !drw->scheme)
if (!drw || !drw->scheme) return;
return; XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); if (filled)
if (filled) XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); else
else XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
} }
int int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) {
{ int i, ty, ellipsis_x = 0;
int i, ty, ellipsis_x = 0; unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len; XftDraw *d = NULL;
XftDraw *d = NULL; Fnt *usedfont, *curfont, *nextfont;
Fnt *usedfont, *curfont, *nextfont; int utf8strlen, utf8charlen, render = x || y || w || h;
int utf8strlen, utf8charlen, render = x || y || w || h; long utf8codepoint = 0;
long utf8codepoint = 0; const char *utf8str;
const char *utf8str; FcCharSet *fccharset;
FcCharSet *fccharset; FcPattern *fcpattern;
FcPattern *fcpattern; FcPattern *match;
FcPattern *match; XftResult result;
XftResult result; int charexists = 0, overflow = 0;
int charexists = 0, overflow = 0; /* keep track of a couple codepoints for which we have no match. */
/* keep track of a couple codepoints for which we have no match. */ enum {
enum { nomatches_len = 64 }; nomatches_len = 64
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; };
static unsigned int ellipsis_width = 0; static struct {
long codepoint[nomatches_len];
unsigned int idx;
} nomatches;
static unsigned int ellipsis_width = 0;
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0; return 0;
if (!render) { if (!render) {
w = invert ? invert : ~invert; w = invert ? invert : ~invert;
} else { } else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable, d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen), DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen)); DefaultColormap(drw->dpy, drw->screen));
x += lpad; x += lpad;
w -= lpad; w -= lpad;
} }
usedfont = drw->fonts; usedfont = drw->fonts;
if (!ellipsis_width && render) if (!ellipsis_width && render)
ellipsis_width = drw_fontset_getwidth(drw, "..."); ellipsis_width = drw_fontset_getwidth(drw, "...");
while (1) { while (1) {
ew = ellipsis_len = utf8strlen = 0; ew = ellipsis_len = utf8strlen = 0;
utf8str = text; utf8str = text;
nextfont = NULL; nextfont = NULL;
while (*text) { while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (curfont = drw->fonts; curfont; curfont = curfont->next) { for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) { if (charexists) {
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
if (ew + ellipsis_width <= w) { if (ew + ellipsis_width <= w) {
/* keep track where the ellipsis still fits */ /* keep track where the ellipsis still fits */
ellipsis_x = x + ew; ellipsis_x = x + ew;
ellipsis_w = w - ew; ellipsis_w = w - ew;
ellipsis_len = utf8strlen; ellipsis_len = utf8strlen;
} }
if (ew + tmpw > w) { if (ew + tmpw > w) {
overflow = 1; overflow = 1;
/* called from drw_fontset_getwidth_clamp(): /* called from drw_fontset_getwidth_clamp():
* it wants the width AFTER the overflow * it wants the width AFTER the overflow
*/ */
if (!render) if (!render)
x += tmpw; x += tmpw;
else else
utf8strlen = ellipsis_len; utf8strlen = ellipsis_len;
} else if (curfont == usedfont) { } else if (curfont == usedfont) {
utf8strlen += utf8charlen; utf8strlen += utf8charlen;
text += utf8charlen; text += utf8charlen;
ew += tmpw; ew += tmpw;
} else { } else {
nextfont = curfont; nextfont = curfont;
} }
break; break;
} }
} }
if (overflow || !charexists || nextfont) if (overflow || !charexists || nextfont)
break; break;
else else
charexists = 0; charexists = 0;
} }
if (utf8strlen) { if (utf8strlen) {
if (render) { if (render) {
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); usedfont->xfont, x, ty, (XftChar8 *) utf8str, utf8strlen);
} }
x += ew; x += ew;
w -= ew; w -= ew;
} }
if (render && overflow) if (render && overflow)
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
if (!*text || overflow) { if (!*text || overflow) {
break; break;
} else if (nextfont) { } else if (nextfont) {
charexists = 0; charexists = 0;
usedfont = nextfont; usedfont = nextfont;
} else { } else {
/* Regardless of whether or not a fallback font is found, the /* Regardless of whether or not a fallback font is found, the
* character must be drawn. */ * character must be drawn. */
charexists = 1; charexists = 1;
for (i = 0; i < nomatches_len; ++i) { for (i = 0; i < nomatches_len; ++i) {
/* avoid calling XftFontMatch if we know we won't find a match */ /* avoid calling XftFontMatch if we know we won't find a match */
if (utf8codepoint == nomatches.codepoint[i]) if (utf8codepoint == nomatches.codepoint[i])
goto no_match; goto no_match;
} }
fccharset = FcCharSetCreate(); fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint); FcCharSetAddChar(fccharset, utf8codepoint);
if (!drw->fonts->pattern) { if (!drw->fonts->pattern) {
/* Refer to the comment in xfont_create for more information. */ /* Refer to the comment in xfont_create for more information. */
die("the first font in the cache must be loaded from a font string."); die("the first font in the cache must be loaded from a font string.");
} }
fcpattern = FcPatternDuplicate(drw->fonts->pattern); fcpattern = FcPatternDuplicate(drw->fonts->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern); FcDefaultSubstitute(fcpattern);
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
FcCharSetDestroy(fccharset); FcCharSetDestroy(fccharset);
FcPatternDestroy(fcpattern); FcPatternDestroy(fcpattern);
if (match) { if (match) {
usedfont = xfont_create(drw, NULL, match); usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->fonts; curfont->next; curfont = curfont->next) for (curfont = drw->fonts; curfont->next; curfont = curfont->next); /* NOP */
; /* NOP */ curfont->next = usedfont;
curfont->next = usedfont; } else {
} else { xfont_free(usedfont);
xfont_free(usedfont); nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint; no_match:
no_match: usedfont = drw->fonts;
usedfont = drw->fonts; }
} }
} }
} }
} if (d)
if (d) XftDrawDestroy(d);
XftDrawDestroy(d);
return x + (render ? w : 0); return x + (render ? w : 0);
} }
void void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) {
{ if (!drw)
if (!drw) return;
return;
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
XSync(drw->dpy, False); XSync(drw->dpy, False);
} }
unsigned int unsigned int
drw_fontset_getwidth(Drw *drw, const char *text) drw_fontset_getwidth(Drw *drw, const char *text) {
{ if (!drw || !drw->fonts || !text)
if (!drw || !drw->fonts || !text) return 0;
return 0; return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
} }
unsigned int unsigned int
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) {
{ unsigned int tmp = 0;
unsigned int tmp = 0; if (drw && drw->fonts && text && n)
if (drw && drw->fonts && text && n) tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); return MIN(n, tmp);
return MIN(n, tmp);
} }
void void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) {
{ XGlyphInfo ext;
XGlyphInfo ext;
if (!font || !text) if (!font || !text)
return; return;
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *) text, len, &ext);
if (w) if (w)
*w = ext.xOff; *w = ext.xOff;
if (h) if (h)
*h = font->h; *h = font->h;
} }
Cur * Cur *
drw_cur_create(Drw *drw, int shape) drw_cur_create(Drw *drw, int shape) {
{ Cur *cur;
Cur *cur;
if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
return NULL; return NULL;
cur->cursor = XCreateFontCursor(drw->dpy, shape); cur->cursor = XCreateFontCursor(drw->dpy, shape);
return cur; return cur;
} }
void void
drw_cur_free(Drw *drw, Cur *cursor) drw_cur_free(Drw *drw, Cur *cursor) {
{ if (!cursor)
if (!cursor) return;
return;
XFreeCursor(drw->dpy, cursor->cursor); XFreeCursor(drw->dpy, cursor->cursor);
free(cursor); free(cursor);
} }

View file

@ -1,57 +1,69 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
typedef struct { typedef struct {
Cursor cursor; Cursor cursor;
} Cur; } Cur;
typedef struct Fnt { typedef struct Fnt {
Display *dpy; Display *dpy;
unsigned int h; unsigned int h;
XftFont *xfont; XftFont *xfont;
FcPattern *pattern; FcPattern *pattern;
struct Fnt *next; struct Fnt *next;
} Fnt; } Fnt;
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ enum {
ColFg, ColBg, ColBorder
}; /* Clr scheme index */
typedef XftColor Clr; typedef XftColor Clr;
typedef struct { typedef struct {
unsigned int w, h; unsigned int w, h;
Display *dpy; Display *dpy;
int screen; int screen;
Window root; Window root;
Drawable drawable; Drawable drawable;
GC gc; GC gc;
Clr *scheme; Clr *scheme;
Fnt *fonts; Fnt *fonts;
} Drw; } Drw;
/* Drawable abstraction */ /* Drawable abstraction */
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw); void drw_free(Drw *drw);
/* Fnt abstraction */ /* Fnt abstraction */
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); Fnt *drw_fontset_create(Drw *drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set);
void drw_fontset_free(Fnt *set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text); unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */ /* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
/* Cursor abstraction */ /* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape); Cur *drw_cur_create(Drw *drw, int shape);
void drw_cur_free(Drw *drw, Cur *cursor); void drw_cur_free(Drw *drw, Cur *cursor);
/* Drawing context manipulation */ /* Drawing context manipulation */
void drw_setfontset(Drw *drw, Fnt *set); void drw_setfontset(Drw *drw, Fnt *set);
void drw_setscheme(Drw *drw, Clr *scm); void drw_setscheme(Drw *drw, Clr *scm);
/* Drawing functions */ /* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
/* Map functions */ /* Map functions */

2678
src/dwm.c

File diff suppressed because it is too large Load diff

View file

@ -1,184 +0,0 @@
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", norm_bg,
"-nf", norm_fg, "-sb", sel_bg, "-sf", sel_fg, NULL };
static const char *termcmd[] = { TERMINAL, NULL };
/* key definitions */
#define MODKEY Mod4Mask // win/super key
#define TAGKEYS(KEY,TAG) \
{1, {{MODKEY, KEY}}, view, {.ui = 1 << TAG} }, \
{1, {{MODKEY|ControlMask, KEY}}, toggleview, {.ui = 1 << TAG} }, \
{1, {{MODKEY|ShiftMask, KEY}}, tag, {.ui = 1 << TAG} }, \
{1, {{MODKEY|ControlMask|ShiftMask, KEY}}, toggletag, {.ui = 1 << TAG} },
// X11 keysym definitions
#include <X11/XF86keysym.h> // req (libxinerama1 and libxinerama-dev)
static Keychord keychords[] = {
/* modifier key function argument */
/* ---------------------------------- Apps Keys ---------------------------------- */
// Dmenu (launcher)
{1, {{MODKEY|ShiftMask, XK_d}}, spawn, {.v = dmenucmd } },
// Rofi launcher (small)
{1, {{MODKEY|ShiftMask|ControlMask, XK_d}}, spawn, SHCMD("rofi -show drun") },
// Start the main terminal
{1, {{MODKEY, XK_Return}}, spawn, {.v = termcmd } },
// Start the alacritty terminal
{2, {{MODKEY, XK_t}, {0, XK_a}}, spawn, SHCMD("alacritty") },
// Start the alacritty terminal with tmux
{2, {{MODKEY, XK_t}, {ShiftMask, XK_a}}, spawn, SHCMD("alacritty -e tmux") },
// kitty
{2, {{MODKEY, XK_t}, {0, XK_k}}, spawn, SHCMD("kitty") },
// kitty with tmux
{2, {{MODKEY, XK_t}, {ShiftMask, XK_k}}, spawn, SHCMD("kitty -e tmux") },
/************************************* File browsers *************************************/
// GUI filebrowser (pcmanfm)
{2, {{MODKEY|ShiftMask, XK_f}, {0, XK_g}}, spawn, SHCMD(GUI_FILEMANAGER) },
// Rofi file browser (small)
{2, {{MODKEY|ShiftMask, XK_f}, {0, XK_f}}, spawn, SHCMD("rofi -show filebrowser") },
// ranger
{2, {{MODKEY|ShiftMask, XK_f}, {0, XK_r}}, spawn, SHCMD(TERMINAL " -e ranger") },
/************************************* Start the web browers *************************************/
// Google chrome stable
{2, {{MODKEY, XK_w}, {0, XK_g}}, spawn, SHCMD(WEBBROWSER) },
// Tor brower
{2, {{MODKEY, XK_w}, {0, XK_t}}, spawn, SHCMD("tor-browser") },
/************************************* Start the caht/email/\* apps *************************************/
// Discord
{2, {{MODKEY, XK_c}, {0, XK_d}}, spawn, SHCMD("discord") },
// Obsidian
{2, {{MODKEY, XK_c}, {0, XK_o}}, spawn, SHCMD("obsidian") },
/************************************* Start the dev apps *************************************/
// Jetbrains toolbox
{2, {{MODKEY, XK_a}, {0, XK_j}}, spawn, SHCMD("jetbrains-toolbox") },
// NeoVim
{2, {{MODKEY, XK_a}, {0, XK_n}}, spawn, SHCMD(TERMINAL " -e nvim") },
// Vim
{2, {{MODKEY, XK_a}, {0, XK_v}}, spawn, SHCMD(TERMINAL " -e vim") },
// emacs
{2, {{MODKEY, XK_a}, {0, XK_e}}, spawn, SHCMD("emacs") },
/************************************* Start personalize apps *************************************/
// nitrogen
{2, {{MODKEY, XK_p}, {0, XK_b}}, spawn, SHCMD("nitrogen") },
// nm-connection-editor
{2, {{MODKEY, XK_p}, {0, XK_n}}, spawn, SHCMD("nm-connection-editor") },
/************************************* Start multi media apps *************************************/
// cmus
{2, {{MODKEY, XK_m}, {0, XK_c}}, spawn, SHCMD("sh -c \"" TERMINAL " -e cmus\" & sh -c \"cmus-rpc --link\"") },
// vlc
{2, {{MODKEY, XK_m}, {0, XK_v}}, spawn, SHCMD("vlc") },
// vlc in the main terminal
{2, {{MODKEY, XK_m}, {ShiftMask, XK_v}}, spawn, SHCMD(TERMINAL "nvlc") },
/************************************* Start the emoji piker apps *************************************/
// Emoji selector (rofi)
{1, {{Mod4Mask, XK_e}}, spawn, SHCMD("rofi -show emoji") },
/************************************* dwm keys *************************************/
// Full screen mode
{1, {{MODKEY, XK_f}}, fullscreen, {0} },
// Toggle the slstatus bar (hide/show)
{1, {{MODKEY, XK_b}}, togglebar, {0} },
// Change the focus
{1, {{MODKEY, XK_j}}, focusstack, {.i = +1 } },
{1, {{MODKEY, XK_k}}, focusstack, {.i = -1 } },
// Change the stack layout (horizontal/virtecal)
{1, {{MODKEY, XK_i}}, incnmaster, {.i = +1 } },
{1, {{MODKEY, XK_d}}, incnmaster, {.i = -1 } },
// Change the focus window size (in the tile mode)
{1, {{MODKEY, XK_h}}, setmfact, {.f = -0.05} },
{1, {{MODKEY, XK_l}}, setmfact, {.f = +0.05} },
// { MODKEY, XK_Return, zoom, {0} },
{1, {{MODKEY, XK_Tab}}, view, {0} },
{1, {{MODKEY|ShiftMask, XK_j}}, movestack, {.i = +1 } },
{1, {{MODKEY|ShiftMask, XK_k}}, movestack, {.i = -1 } },
// Toogle styky mode
{1, {{MODKEY|ShiftMask, XK_s}}, togglesticky, {0} },
// Quit from the foucsed window (kill)
{2, {{MODKEY, XK_q}, {0, XK_q}}, killclient, {0} },
/************************* Switch between layouts *************************/
// Tiled layout
{2, {{MODKEY, XK_s}, {0, XK_t}}, setlayout, {.v = &layouts[0]} },
// Floating layout
{2, {{MODKEY, XK_s}, {0, XK_f}}, setlayout, {.v = &layouts[1]} },
// Monocle layout
{2, {{MODKEY, XK_s}, {0, XK_m}}, setlayout, {.v = &layouts[2]} },
// Grid layout
{2, {{MODKEY, XK_s}, {0, XK_g}}, setlayout, {.v = &layouts[3]} },
// Spiral layout
{2, {{MODKEY, XK_s}, {0, XK_r}}, setlayout, {.v = &layouts[4]} },
// Dwindle layout
{2, {{MODKEY, XK_s}, {ShiftMask, XK_r}}, setlayout, {.v = &layouts[5]} },
// Centerd master layout
{2, {{MODKEY, XK_s}, {0, XK_c}}, setlayout, {.v = &layouts[6]} },
// Centerd floating master layout
{2, {{MODKEY, XK_s}, {ShiftMask, XK_c}}, setlayout, {.v = &layouts[7]} },
// Toggle between current layout and tile layout
{2, {{MODKEY, XK_s}, {0, XK_space}}, setlayout, {0} },
// Toggle floating window
{1, {{MODKEY|Mod1Mask, XK_f}}, togglefloating, {0} },
// View all tags
{1, {{MODKEY, XK_0}}, view, {.ui = ~0 } },
// Mirror the current tagg in all tags
{1, {{MODKEY|ShiftMask, XK_0}}, tag, {.ui = ~0 } },
// I don't know
{1, {{MODKEY, XK_comma}}, focusmon, {.i = -1 } },
{1, {{MODKEY, XK_period}}, focusmon, {.i = +1 } },
{1, {{MODKEY|ShiftMask, XK_comma}}, tagmon, {.i = -1 } },
{1, {{MODKEY|ShiftMask, XK_period}}, tagmon, {.i = +1 } },
/************************* Tag keys *************************/
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
/* ---------------------------------- Control Keys ---------------------------------- */
// Brightness controllers (requires xbacklight)
{1, {{0, XF86XK_MonBrightnessUp}}, spawn, SHCMD("xbacklight -inc 5") },
{1, {{0, XF86XK_MonBrightnessDown}}, spawn, SHCMD("xbacklight -dec 5") },
// Sound controllers (requires pamixer)
{1, {{0, XF86XK_AudioRaiseVolume}}, spawn, SHCMD("pamixer --allow-boost -i 4") },
{1, {{0, XF86XK_AudioLowerVolume}}, spawn, SHCMD("pamixer --allow-boost -d 4") },
{1, {{0, XF86XK_AudioMute}}, spawn, SHCMD("pamixer -t") },
// Media controls (requires playerctl)
{1, {{0, XF86XK_AudioPlay}}, spawn, SHCMD("playerctl play-pause") },
{1, {{0, XF86XK_AudioStop}}, spawn, SHCMD("playerctl stop") },
{1, {{0, XF86XK_AudioNext}}, spawn, SHCMD("playerctl next") },
{1, {{0, XF86XK_AudioPrev}}, spawn, SHCMD("playerctl previous") },
// Mute and unmute mic
{1, {{0, XF86XK_AudioMicMute}}, spawn, SHCMD("pactl set-source-mute @DEFAULT_SOURCE@ toggle") },
// Take a screenshot
{1, {{0, XK_Print}}, spawn, SHCMD(SCREENSHOT) },
/* ---------------------------------- lock Keys ---------------------------------- */
// Lock the screen
{1, {{MODKEY|ShiftMask, XK_x}}, spawn, SHCMD("betterlockscreen -l dim") },
// Kill dwm (super + shift + alt + q)
{1, {{MODKEY|ShiftMask|Mod1Mask, XK_q}}, quit, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

View file

@ -1,6 +0,0 @@
#ifndef keys_H
#define keys_H
#include "keys.c"
#endif // !keys.h

View file

@ -1,102 +1,103 @@
#include "../archy_dwm.h"
#include "../util.h"
void void
centeredmaster(Monitor *m) centeredmaster(Monitor *m) {
{ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
unsigned int i, n, h, mw, mx, my, oty, ety, tw; Client *c;
Client *c;
/* count number of clients in the selected monitor */ /* count number of clients in the selected monitor */
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
if (n == 0) if (n == 0)
return; return;
/* initialize areas */ /* initialize areas */
mw = m->ww; mw = m->ww;
mx = 0; mx = 0;
my = 0; my = 0;
tw = mw; tw = mw;
if (n > m->nmaster) { if (n > m->nmaster) {
/* go mfact box in the center if more than nmaster clients */ /* go mfact box in the center if more than nmaster clients */
mw = m->nmaster ? m->ww * m->mfact : 0; mw = m->nmaster ? m->ww * m->mfact : 0;
tw = m->ww - mw; tw = m->ww - mw;
if (n - m->nmaster > 1) { if (n - m->nmaster > 1) {
/* only one client */ /* only one client */
mx = (m->ww - mw) / 2; mx = (m->ww - mw) / 2;
tw = (m->ww - mw) / 2; tw = (m->ww - mw) / 2;
} }
} }
oty = 0; oty = 0;
ety = 0; ety = 0;
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < m->nmaster) { if (i < m->nmaster) {
/* nmaster clients are stacked vertically, in the center /* nmaster clients are stacked vertically, in the center
* of the screen */ * of the screen */
h = (m->wh - my) / (MIN(n, m->nmaster) - i); h = (m->wh - my) / (MIN(n, m->nmaster) - i);
resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), resize(c, m->wx + mx, m->wy + my, mw - (2 * c->bw),
h - (2*c->bw), 0); h - (2 * c->bw), 0);
my += HEIGHT(c); my += HEIGHT(c);
} else { } else {
/* stack clients are stacked vertically */ /* stack clients are stacked vertically */
if ((i - m->nmaster) % 2 ) { if ((i - m->nmaster) % 2) {
h = (m->wh - ety) / ( (1 + n - i) / 2); h = (m->wh - ety) / ((1 + n - i) / 2);
resize(c, m->wx, m->wy + ety, tw - (2*c->bw), resize(c, m->wx, m->wy + ety, tw - (2 * c->bw),
h - (2*c->bw), 0); h - (2 * c->bw), 0);
ety += HEIGHT(c); ety += HEIGHT(c);
} else { } else {
h = (m->wh - oty) / ((1 + n - i) / 2); h = (m->wh - oty) / ((1 + n - i) / 2);
resize(c, m->wx + mx + mw, m->wy + oty, resize(c, m->wx + mx + mw, m->wy + oty,
tw - (2*c->bw), h - (2*c->bw), 0); tw - (2 * c->bw), h - (2 * c->bw), 0);
oty += HEIGHT(c); oty += HEIGHT(c);
} }
} }
} }
void void
centeredfloatingmaster(Monitor *m) centeredfloatingmaster(Monitor *m) {
{ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; Client *c;
Client *c;
/* count number of clients in the selected monitor */ /* count number of clients in the selected monitor */
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
if (n == 0) if (n == 0)
return; return;
/* initialize nmaster area */ /* initialize nmaster area */
if (n > m->nmaster) { if (n > m->nmaster) {
/* go mfact box in the center if more than nmaster clients */ /* go mfact box in the center if more than nmaster clients */
if (m->ww > m->wh) { if (m->ww > m->wh) {
mw = m->nmaster ? m->ww * m->mfact : 0; mw = m->nmaster ? m->ww * m->mfact : 0;
mh = m->nmaster ? m->wh * 0.9 : 0; mh = m->nmaster ? m->wh * 0.9 : 0;
} else { } else {
mh = m->nmaster ? m->wh * m->mfact : 0; mh = m->nmaster ? m->wh * m->mfact : 0;
mw = m->nmaster ? m->ww * 0.9 : 0; mw = m->nmaster ? m->ww * 0.9 : 0;
} }
mx = mxo = (m->ww - mw) / 2; mx = mxo = (m->ww - mw) / 2;
my = myo = (m->wh - mh) / 2; my = myo = (m->wh - mh) / 2;
} else { } else {
/* go fullscreen if all clients are in the master area */ /* go fullscreen if all clients are in the master area */
mh = m->wh; mh = m->wh;
mw = m->ww; mw = m->ww;
mx = mxo = 0; mx = mxo = 0;
my = myo = 0; my = myo = 0;
} }
for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) for (i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < m->nmaster) { if (i < m->nmaster) {
/* nmaster clients are stacked horizontally, in the center /* nmaster clients are stacked horizontally, in the center
* of the screen */ * of the screen */
w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), resize(c, m->wx + mx, m->wy + my, w - (2 * c->bw),
mh - (2*c->bw), 0); mh - (2 * c->bw), 0);
mx += WIDTH(c); mx += WIDTH(c);
} else { } else {
/* stack clients are stacked horizontally */ /* stack clients are stacked horizontally */
w = (m->ww - tx) / (n - i); w = (m->ww - tx) / (n - i);
resize(c, m->wx + tx, m->wy, w - (2*c->bw), resize(c, m->wx + tx, m->wy, w - (2 * c->bw),
m->wh - (2*c->bw), 0); m->wh - (2 * c->bw), 0);
tx += WIDTH(c); tx += WIDTH(c);
} }
} }

View file

@ -7,4 +7,4 @@ static void centeredfloatingmaster(Monitor *m);
#include "centeredmaster.c" #include "centeredmaster.c"
#endif // !centeredmaster.h #endif // centeredmaster_H

View file

@ -1,66 +1,65 @@
#include "../archy_dwm.h"
void void
fibonacci(Monitor *mon, int s) { fibonacci(Monitor *mon, int s) {
unsigned int i, n, nx, ny, nw, nh; unsigned int i, n, nx, ny, nw, nh;
Client *c; Client *c;
for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++); for (n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++);
if(n == 0) if (n == 0)
return; return;
nx = mon->wx; nx = mon->wx;
ny = 0; ny = 0;
nw = mon->ww; nw = mon->ww;
nh = mon->wh; nh = mon->wh;
for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) { for (i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) {
if((i % 2 && nh / 2 > 2 * c->bw) if ((i % 2 && nh / 2 > 2 * c->bw)
|| (!(i % 2) && nw / 2 > 2 * c->bw)) { || (!(i % 2) && nw / 2 > 2 * c->bw)) {
if(i < n - 1) { if (i < n - 1) {
if(i % 2) if (i % 2)
nh /= 2; nh /= 2;
else else
nw /= 2; nw /= 2;
if((i % 4) == 2 && !s) if ((i % 4) == 2 && !s)
nx += nw; nx += nw;
else if((i % 4) == 3 && !s) else if ((i % 4) == 3 && !s)
ny += nh; ny += nh;
} }
if((i % 4) == 0) { if ((i % 4) == 0) {
if(s) if (s)
ny += nh; ny += nh;
else else
ny -= nh; ny -= nh;
} } else if ((i % 4) == 1)
else if((i % 4) == 1) nx += nw;
nx += nw; else if ((i % 4) == 2)
else if((i % 4) == 2) ny += nh;
ny += nh; else if ((i % 4) == 3) {
else if((i % 4) == 3) { if (s)
if(s) nx += nw;
nx += nw; else
else nx -= nw;
nx -= nw; }
} if (i == 0) {
if(i == 0) if (n != 1)
{ nw = mon->ww * mon->mfact;
if(n != 1) ny = mon->wy;
nw = mon->ww * mon->mfact; } else if (i == 1)
ny = mon->wy; nw = mon->ww - nw;
} i++;
else if(i == 1) }
nw = mon->ww - nw; resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
i++; }
}
resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
}
} }
void void
dwindle(Monitor *mon) { dwindle(Monitor *mon) {
fibonacci(mon, 1); fibonacci(mon, 1);
} }
void void
spiral(Monitor *mon) { spiral(Monitor *mon) {
fibonacci(mon, 0); fibonacci(mon, 0);
} }

View file

@ -1,27 +1,29 @@
#include "../archy_dwm.h"
void void
grid(Monitor *m) { grid(Monitor *m) {
unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows; unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows;
Client *c; Client *c;
for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next))
n++; n++;
/* grid dimensions */ /* grid dimensions */
for(rows = 0; rows <= n/2; rows++) for (rows = 0; rows <= n / 2; rows++)
if(rows*rows >= n) if (rows * rows >= n)
break; break;
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
/* window geoms (cell height/width) */ /* window geoms (cell height/width) */
ch = m->wh / (rows ? rows : 1); ch = m->wh / (rows ? rows : 1);
cw = m->ww / (cols ? cols : 1); cw = m->ww / (cols ? cols : 1);
for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
cx = m->wx + (i / rows) * cw; cx = m->wx + (i / rows) * cw;
cy = m->wy + (i % rows) * ch; cy = m->wy + (i % rows) * ch;
/* adjust height/width of last row/column's windows */ /* adjust height/width of last row/column's windows */
ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0; ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0;
aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0; aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0;
resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False); resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False);
i++; i++;
} }
} }

View file

@ -10,15 +10,15 @@
// Layouts array // Layouts array
static const Layout layouts[] = { static const Layout layouts[] = {
/* symbol arrange function */ /* symbol arrange function */
{ "[]=", tile }, /* first entry is default */ {"[]=", tile}, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */ {"><>", NULL}, /* no layout function means floating behavior */
{ "[M]", monocle }, // 2 {"[M]", monocle}, // 2
{ "HHH", grid }, // 3 {"HHH", grid}, // 3
{ "[@]", spiral }, // 4 {"[@]", spiral}, // 4
{ "[\\]", dwindle }, // 5 {"[\\]", dwindle}, // 5
{ "|M|", centeredmaster }, // 6 {"|M|", centeredmaster}, // 6
{ ">M>", centeredfloatingmaster }, // 7 {">M>", centeredfloatingmaster}, // 7
}; };
#endif // !layouts.h #endif // layouts_H

View file

@ -1,14 +1,16 @@
void #include "../archy_dwm.h"
monocle(Monitor *m) #include "../util.h"
{
unsigned int n = 0;
Client *c;
for (c = m->clients; c; c = c->next) void
if (ISVISIBLE(c)) monocle(Monitor *m) {
n++; unsigned int n = 0;
if (n > 0) /* override layout symbol */ Client *c;
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) for (c = m->clients; c; c = c->next)
resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); if (ISVISIBLE(c))
n++;
if (n > 0) /* override layout symbol */
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
} }

View file

@ -1,27 +1,29 @@
#include "../archy_dwm.h"
#include "../util.h"
void void
tile(Monitor *m) tile(Monitor *m) {
{ unsigned int i, n, h, mw, my, ty;
unsigned int i, n, h, mw, my, ty; Client *c;
Client *c;
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
if (n == 0) if (n == 0)
return; return;
if (n > m->nmaster) if (n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0; mw = m->nmaster ? m->ww * m->mfact : 0;
else else
mw = m->ww; mw = m->ww;
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if (i < m->nmaster) { if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i); h = (m->wh - my) / (MIN(n, m->nmaster) - i);
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); resize(c, m->wx, m->wy + my, mw - (2 * c->bw), h - (2 * c->bw), 0);
if (my + HEIGHT(c) < m->wh) if (my + HEIGHT(c) < m->wh)
my += HEIGHT(c); my += HEIGHT(c);
} else { } else {
h = (m->wh - ty) / (n - i); h = (m->wh - ty) / (n - i);
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2 * c->bw), h - (2 * c->bw), 0);
if (ty + HEIGHT(c) < m->wh) if (ty + HEIGHT(c) < m->wh)
ty += HEIGHT(c); ty += HEIGHT(c);
} }
} }

View file

@ -1,48 +1,50 @@
void #include "archy_dwm.h"
#include "util.h"
static void
movestack(const Arg *arg) { movestack(const Arg *arg) {
Client *c = NULL, *p = NULL, *pc = NULL, *i; Client *c = NULL, *p = NULL, *pc = NULL, *i;
if(arg->i > 0) { if (arg->i > 0) {
/* find the client after selmon->sel */ /* find the client after selmon->sel */
for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); for (c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
if(!c) if (!c)
for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); for (c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
} } else {
else { /* find the client before selmon->sel */
/* find the client before selmon->sel */ for (i = selmon->clients; i != selmon->sel; i = i->next)
for(i = selmon->clients; i != selmon->sel; i = i->next) if (ISVISIBLE(i) && !i->isfloating)
if(ISVISIBLE(i) && !i->isfloating) c = i;
c = i; if (!c)
if(!c) for (; i; i = i->next)
for(; i; i = i->next) if (ISVISIBLE(i) && !i->isfloating)
if(ISVISIBLE(i) && !i->isfloating) c = i;
c = i; }
} /* find the client before selmon->sel and c */
/* find the client before selmon->sel and c */ for (i = selmon->clients; i && (!p || !pc); i = i->next) {
for(i = selmon->clients; i && (!p || !pc); i = i->next) { if (i->next == selmon->sel)
if(i->next == selmon->sel) p = i;
p = i; if (i->next == c)
if(i->next == c) pc = i;
pc = i; }
}
/* swap c and selmon->sel selmon->clients in the selmon->clients list */ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
if(c && c != selmon->sel) { if (c && c != selmon->sel) {
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; Client *temp = selmon->sel->next == c ? selmon->sel : selmon->sel->next;
selmon->sel->next = c->next==selmon->sel?c:c->next; selmon->sel->next = c->next == selmon->sel ? c : c->next;
c->next = temp; c->next = temp;
if(p && p != c) if (p && p != c)
p->next = c; p->next = c;
if(pc && pc != selmon->sel) if (pc && pc != selmon->sel)
pc->next = selmon->sel; pc->next = selmon->sel;
if(selmon->sel == selmon->clients) if (selmon->sel == selmon->clients)
selmon->clients = c; selmon->clients = c;
else if(c == selmon->clients) else if (c == selmon->clients)
selmon->clients = selmon->sel; selmon->clients = selmon->sel;
arrange(selmon); arrange(selmon);
} }
} }

View file

@ -6,37 +6,37 @@
#include <X11/Xutil.h> #include <X11/Xutil.h>
int main(void) { int main(void) {
Display *d; Display *d;
Window r, f, t = None; Window r, f, t = None;
XSizeHints h; XSizeHints h;
XEvent e; XEvent e;
d = XOpenDisplay(NULL); d = XOpenDisplay(NULL);
if (!d) if (!d)
exit(1); exit(1);
r = DefaultRootWindow(d); r = DefaultRootWindow(d);
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
h.min_width = h.max_width = h.min_height = h.max_height = 400; h.min_width = h.max_width = h.min_height = h.max_height = 400;
h.flags = PMinSize | PMaxSize; h.flags = PMinSize | PMaxSize;
XSetWMNormalHints(d, f, &h); XSetWMNormalHints(d, f, &h);
XStoreName(d, f, "floating"); XStoreName(d, f, "floating");
XMapWindow(d, f); XMapWindow(d, f);
XSelectInput(d, f, ExposureMask); XSelectInput(d, f, ExposureMask);
while (1) { while (1) {
XNextEvent(d, &e); XNextEvent(d, &e);
if (t == None) { if (t == None) {
sleep(5); sleep(5);
t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0);
XSetTransientForHint(d, t, f); XSetTransientForHint(d, t, f);
XStoreName(d, t, "transient"); XStoreName(d, t, "transient");
XMapWindow(d, t); XMapWindow(d, t);
XSelectInput(d, t, ExposureMask); XSelectInput(d, t, ExposureMask);
} }
} }
XCloseDisplay(d); XCloseDisplay(d);
exit(0); exit(0);
} }

View file

@ -6,18 +6,9 @@
#include "util.h" #include "util.h"
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
void void
die(const char *fmt, ...) { die(const char *fmt, ...)
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -33,3 +24,13 @@ die(const char *fmt, ...) {
exit(1); exit(1);
} }
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}

View file

@ -1,8 +1,25 @@
/* See LICENSE file for copyright and license details. */ #ifndef UTIL_H
#define UTIL_H
/* macros */
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INTERSECT(x, y, w, h, m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
#define XEMBED_EMBEDDED_VERSION ((VERSION_MAJOR << 16) | VERSION_MINOR)
#define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
void die(const char *fmt, ...); void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size); void *ecalloc(size_t nmemb, size_t size);
#endif // util_H