Skip to content

Commit

Permalink
Adding setup example
Browse files Browse the repository at this point in the history
  • Loading branch information
jzbor committed Nov 7, 2023
1 parent 8814a6c commit e3704fd
Show file tree
Hide file tree
Showing 5 changed files with 668 additions and 0 deletions.
157 changes: 157 additions & 0 deletions SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Setup Guide
This guide shows you how to build a fully functional desktop environment with marswm.


## Assumptions
There are a few assumptions made in these scripts with regards to your system in this guide and in the scripts:
* `marswm`, `marsbar` and `mars-relay` are already installed (see [`INSTALLATION.md`](./INSTALLATION.md))
* You use either [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) or [pipewire](https://pipewire.org/) with `pactl` installed (probably in the `pulseaudio` package)
* Your distro uses [systemd](https://systemd.io/)

No worries, if one of those does not apply to your setup.
It should be straightforward to adjust the scripts for example for a non-systemd distro, but you have to do so on your own.


## Startup Script
First of all it makes sense to create a startup script in which we can put programs to run when our WM starts.
Create a file called `mars-startup` in your `$PATH`) (e.g. `~/.local/bin/mars-startup`):
```sh
#/bin/sh

# helper function to detect if a program is already running
is_running () {
pgrep --uid "$UID" "$1" > /dev/null
}

# load default layout (use arandr to set it)
[ -f ~/.screenlayout/default.sh ] && /bin/sh ~/.screenlayout/default.sh;

# programs to automatically start
is_running marsbar || marsbar &
```

We will add further lines to this script later on.


## Status Script
`marsbar` can use scripts to display status information and generate menus.

An example script is provided in the marswm repo to get you started.
You can simply install the [`mars-status`](examples/mars-status.sh) script into your `$PATH` (e.g. `~/.local/bin/mars-status`) and make it executable (`chmod +x mars-status`).
You will also have to make sure to have the following dependencies installed:
* `canberra-gtk-play` ([`libcanberra-gtk3`](https://pkgs.org/search/?q=libcanberra-gtk3))
* `notify-send` ([`libnotify`](https://pkgs.org/search/?q=libnotify))
* `powerprofilesctl` ([`power-profiles-daemon`](https://pkgs.org/search/?q=power-profiles-daemon))
* `pactl` ([`pulseaudio`](https://pkgs.org/search/?q=pulseaudio))
* `xmenu` ([`xmenu`](https://github.com/phillbush/xmenu))

Now you can add the script to your `marsbar` config in `~/.config/marswm/marsbar.yaml`:
```yaml
status_cmd: "mars-status"
action_cmd: "mars-status action"
```
## Wallpaper
This repo also contains a simple script to set your wallpaper: [`wallpaper-daemon`](examples/wallpaper-daemon.sh).
It automatically adjusts your wallpaper whenever your screen configuration changes.
Make sure to install its dependencies `xev` and `xwallpaper`.
Add it to your `$PATH` (e.g. `~/.local/bin/wallpaper-daemon`) and make it executable (`chmod +x wallpaper-daemon`).

Now we can add it to our autostart script:
```sh
is_running wallpaper-daem || wallpaper-daemon &
```

It will load whatever wallpaper you put in `~/.background-image`.


## Application Menu(s)
Another script provided in `examples/` is [`xdg-xmenu.py`](examples/xdg-xmenu.py).
Put it in your `$PATH` (e.g. `~/.local/bin/xdg-xmenu`) and make it executable.

Now we can add it to our button bindings.
It is suggested to put it in `~/.config/marswm/buttonbindings_ext.yaml` as this way it does not interfere with other default bindings:
```yaml
- modifiers: []
button: 3
targets: [root]
action: !execute xdg-xmenu -m | xmenu | /bin/sh
```
Make sure to restart the WM for the bindings to take effect.

After installing the script you can generate the icon cache it by running `xdg-xmenu -f`.
Now you should be able to access the menu when right-clicking the desktop.

### Rofi /dmenu
You will probably also want a keyboard-driven option to access your applications.
By default `marswm` comes with keybindings for [`Rofi`](https://github.com/davatorium/rofi) preconfigured.
Make sure to install and customize it to your liking, then you should be able to run it by pressing `MOD + d`.

A lightweight alternative is [dmenu](https://tools.suckless.org/dmenu/), but you will have to add your own keybindings for it to work properly.


## Audio, Media and Brightness Key Bindings
A modern desktop should also provide working key bindings for audio, media and brightness control, so let's add these (`~/.config/marswm/keybindings_ext.yaml`):
```yaml
# Volume Control
- key: XF86AudioRaiseVolume
action: !execute pactl set-sink-volume @DEFAULT_SINK@ +5% && canberra-gtk-play -i audio-volume-change
- key: XF86AudioLowerVolume
action: !execute pactl set-sink-volume @DEFAULT_SINK@ -5% && canberra-gtk-play -i audio-volume-change
- key: XF86AudioMute
action: !execute pactl set-sink-mute @DEFAULT_SINK@ toggle
- key: XF86AudioMicMute
action: !execute pactl set-source-mute @DEFAULT_SOURCE@ toggle
# Media Control
- key: XF86AudioPlay
action: !execute playerctl play-pause -p Lollypop,spotify
- key: XF86AudioPause
action: !execute playerctl play-pause -p Lollypop,spotify
- key: XF86AudioPrev
action: !execute playerctl previous -p Lollypop,spotify
- key: XF86AudioNext
action: !execute playerctl next -p Lollypop,spotify
# Brightness Control
- key: XF86MonBrightnessUp
action: !execute light -A 10
- key: XF86MonBrightnessDown
action: !execute light -U 10
```

Note that these keybindings depend on `pactl`, `playerctl` and `light`, so make sure to install these.


## Screenshots
Surely you will want to be able to take screenshots, so lets set up a key binding for them.
We will use [`maim`](https://github.com/naelstrof/maim), `tee` and `xclip` so make sure to have them installed.
You will also want to create a directory for your screenshots (e.g. `~/Pictures/Screenshots`).

The key binding (add to `~/.config/marswm/keybindings_ext.yaml`) looks like this:
```yaml
# Screenshots
- modifiers: [ Mod4 ]
key: Print
action: !execute maim -s | tee "$HOME/Pictures/Screenshots/$(date '+%Y-%m-%d_%H-%M-%S.png')" | xclip -selection clipboard -t image/png -i
```

Now once you press `Alt + Print` you will be able to select an area to take a screenshot from.
The image will be saved and copied to your clipboard.
You may want to test this once to make sure everything works.


## Touch Gestures
There is an [example config](examples/touchegg.xml) for [Touchégg](https://github.com/JoseExposito/touchegg) provided along with this repo.
Copy the file to `~/.config/touchegg/touchegg.conf`.
Then [install and setup](https://github.com/JoseExposito/touchegg#installation) touchegg (it requires a server daemon to run, as well as a client).

You will then be able to cycle through workspaces using three fingers on your touchpad, as well as accessing the window menu (swipe down).


## Additional Suggestions
These are additional programs suggested to complete your desktop setup:
* `nmapplet` - applet for managing your network (e.g. Wifi setup) (only works if your machine uses NetworkManager)
* `blueman` + `blueman-applet` - GUI and applet for managing your Bluetooth connections
* `arandr` - GUI to setup screen configurations
171 changes: 171 additions & 0 deletions examples/mars-status.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
#/bin/sh

set +o nounset

SEPARATOR='\x1f'
BATTERY_PATH="$(find /sys/class/power_supply -maxdepth 1 -mindepth 1 | grep -i bat | head -n 1)"


### HELPERS

confirmation_submenu () {
printf "\n\tYou sure?\n\t\t%s" "$1"
}

gen_media_menu () {
for player in $(playerctl -l); do
gen_player_menu "$player"
done
}

gen_player_menu () {
echo "$1"
printf "\t%s - %s\n" "$(property_for_player "$1" title)" "$(property_for_player "$1" artist)"
printf "\t%s\tplayerctl play-pause -p \"%s\"\n" "$(play_pause_label "$1")" "$1"
printf "\tnext\tplayerctl next -p \"%s\"\n" "$1"
printf "\tprevious\tplayerctl prev -p \"%s\"\n" "$1"
}

pa_volume () {
pactl get-sink-volume @DEFAULT_SINK@ | grep "Volume" | sed 's/.*\/\s*\(.*\) \s*\/.*/\1/;'
}

pa_muted () {
if pactl get-sink-mute @DEFAULT_SINK@ | grep no > /dev/null; then
return 1
else
return 0
fi
}

pa_loop () {
pactl subscribe | grep --line-buffered "Event 'change' on sink " | while read -r _; do
update_blocks
done
}

play_pause_label () {
if [ "$(playerctl status -p "$1")" = "Playing" ]; then
echo "pause"
else
echo "play"
fi
}

property_for_player () {
playerctl metadata -p "$1" | grep "xesam:$2" | sed 's/^\([a-zA-Z]*\) xesam:\([a-zA-Z]*\) *\(.*\)/\3/'
}

audio_menu () {
SINK_MENU="$(pactl list sinks | grep "Name: \|Description:" \
| sed 'N; s/\t*Name: \(.*\)\n\t*Description: \(.*\)/\t\2\tpactl set-default-sink \1/')"
SOURCE_MENU="$(pactl list sources | grep "Name: \|Description:" \
| sed 'N; s/\t*Name: \(.*\)\n\t*Description: \(.*\)/\t\2\tpactl set-default-source \1/')"
printf "Change default output\n%s\nChange default input\n%s" "$SINK_MENU" "$SOURCE_MENU" | xmenu | sh
}

media_menu () {
gen_media_menu | xmenu | sh
}

system_menu () {
SYSTEM_MENU="Logout $(confirmation_submenu 'pkill marswm')
Suspend $(confirmation_submenu 'systemctl suspend')
Poweroff $(confirmation_submenu poweroff)
Reboot $(confirmation_submenu reboot)
Output Profile
$(find ~/.screenlayout -type f | sed 's/^\(.*\)\/\(.*\)\(\.sh\)/\t\2\tsh \1\/\2\3/')"
echo "$SYSTEM_MENU" | xmenu | sh
}


### BUTTON HANDLERS

battery_button () {
profile="$(powerprofilesctl list | sed '/^ /d;/^$/d;s/\(.*\):/\1/' | xmenu | sed 's/.* //')"
if [ -n "$profile" ]; then
powerprofilesctl set "$profile"
fi
# case "$BUTTON" in
# 1) pademelon-widgets ppd-dialog ;;
# esac
}

volume_button () {
case "$BUTTON" in
1) media_menu ;;
2) pactl set-sink-mute @DEFAULT_SINK@ toggle ;;
3) audio_menu ;;
4) pactl set-sink-volume @DEFAULT_SINK@ +5% \
&& canberra-gtk-play -i audio-volume-change ;;
5) pactl set-sink-volume @DEFAULT_SINK@ -5% \
&& canberra-gtk-play -i audio-volume-change ;;
esac
}

date_button () {
case "$BUTTON" in
3) system_menu ;;
*) notify-send "$(date)" ;;
esac
}


### STATUS BLOCKS

volume_block () {
if pa_muted; then
printf 'volume: muted'
else
printf 'volume: %s' "$(pa_volume)"
fi
}

battery_block () {
if [ -e "$BATTERY_PATH" ]; then
status="$(cat "$BATTERY_PATH/status")"
if [ "$status" = 'Charging' ]; then
printf 'charging: %s' "$(cat "$BATTERY_PATH/capacity")%"
else
printf 'battery: %s' "$(cat "$BATTERY_PATH/capacity")%"
fi
else
echo "plugged in"
fi
}

date_block () {
printf 'date: %s' "$(date +%H:%M)"
}

blocks () {
printf "%s$SEPARATOR" "$(volume_block)"
printf "%s$SEPARATOR" "$(battery_block)"
printf "%s" "$(date_block)"
}

update_blocks () {
mars-relay set-status "$(blocks)"
}


loop () {
(pa_loop) &

while true; do
update_blocks
sleep 10
done
}

if [ "$1" = "action" ]; then
case "$BLOCK" in
0) volume_button ;;
1) battery_button ;;
2) date_button ;;
_) echo unhandled ;;
esac
else
loop
fi
34 changes: 34 additions & 0 deletions examples/touchegg.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<touchégg>

<settings>
</settings>


<application name="All">


<gesture type="SWIPE" fingers="3" direction="RIGHT">
<action type="RUN_COMMAND">
<repeat>false</repeat>
<command>mars-relay switch-workspace-prev &</command>
<on>begin</on>
</action>
</gesture>

<gesture type="SWIPE" fingers="3" direction="LEFT">
<action type="RUN_COMMAND">
<repeat>false</repeat>
<command>mars-relay switch-workspace-next &</command>
<on>begin</on>
</action>
</gesture>

<gesture type="SWIPE" fingers="3" direction="DOWN">
<action type="RUN_COMMAND">
<repeat>false</repeat>
<command>mars-relay menu &</command>
<on>begin</on>
</action>
</gesture>
</application>
</touchégg>
11 changes: 11 additions & 0 deletions examples/wallpaper-daemon.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh

WALLPAPER_FILE="$HOME/.background-image"

xwallpaper --zoom "$WALLPAPER_FILE"

xev -root -event randr \
| grep --line-buffered XRROutputChangeNotifyEvent \
| while read -r; do
xwallpaper --zoom "$WALLPAPER_FILE"
done
Loading

0 comments on commit e3704fd

Please sign in to comment.