Dwm, xinitrc, autostart help

Maybe I have this in the right place, maybe not.

I am working to create a dwm setup and want to use a simple autostart for sxhkd, picom, conky and the like. Based on what I have read it looks to me like using .xinitrc would be the easiest most secure method for accessing dwm but in my use case I have a few items I don’t know ow to address if I use .xinitrc:

  1. I’d actually like to have a selectable start function such as I have with LightDM. I run a fe wm managers and want to start any/each from the same selection point.
  2. I plan to use conky, sxhkd, and picom on all my wms.

Pointers, suggestions, comments about my lack of schmartness are appreciated. :partying_face:

Not really an answer, but you could consider the autostart patch.

Can do it all in xinitrc (or a wrapper to it if there are issues) since it’s just a script, eg:

#!/bin/bash

set -e  # bail on the first error encountered

typeset -A sessions
sessions=(
	[bspwm]='bspwm'
	[dwm]='dwm'
	[i3]='i3'
	[openbox]='openbox-session'
)

PS3=$'\nSession: '
select session in "${!sessions[@]}"; do
	[ -n "$session" ] && break
done
# now ${sessions[$session]} is our session startup command



# add your standard ~/.xinitrc script here



# lastly we exec the chosen session
exec "${sessions[$session]}"

I’m assuming bash (or bash compliant) and using some bash specifics which will be fine on most systems
that link /bin/sh -> /bin/bash but it could be posix-ified to work in other shells/systems too.

2 Likes

For #2 -

Place everything you want to start with each window manager in a ~/.xprofile file (ArchLabs actually does this by default).

then, for #1

In the ~/.xinitrc have a line that sources the ~/.xprofile file before the window manager starts.

There are some bash scripts that will list available window managers once the ~/.xinitrc is configured properly - I think one or two are actually offered during the ArchLabs install so they may be in the AUR if you search there.

What window managers are you running?

If you’re already using LightDM or similar, you can create the /usr/share/xsessions/dwm.desktop file so that the “Exec” and “TryExec” lines direct to a dwm startup script:

[Desktop Entry]
Name=spectrwm
Comment=The spectrwm window manager
Type=Application
Exec=start-dwm
TryExec=start-dwm
Keywords=tiling;window;manager;wm;

Create the start-dwm file (see ArchWiki for insights) make it executable and copy it to somewhere on your PATH like /usr/bin.

If you stick with LightDM, you can use the other window managers’ native autostart features.

2 Likes

One problem you may have there is that conky needs to be configured differently for tilers like dwm than stacking window managers like openbox. I’m not sure you’ll be able to use one conkyrc for all your window managers. I suspect picom settings will be similar.

@natemaia @nwg @PackRat I’m giving nate’s pre-pend .xinitrc a go right now. I assume I run something like startx dwm from the cli. I’ll bash away a bit. Thanks!

No you’d just run startx like normal, it should display a selection list populated from the sessions array. Try it out with echo instead of exec and you can just run it from a terminal to see what it does.

Okay… my first attempt was “not too” slick.

Here’s what the .xinitrc looked like.

#!/bin/bash
#
# ~/.xinitrc
#
# Executed by startx (run your window manager from here)

set -e  # bail on the first error encountered

typeset -A sessions
sessions=(
	[bspwm]='bspwm'
	[dwm]='dwm'
	[i3]='i3'
	[openbox]='openbox-session'
)

PS3=$'\nSession: '
select session in "${!sessions[@]}"; do
	[ -n "$session" ] && break
done
# now ${sessions[$session]} is our session startup command

userresources=$HOME/.Xresources
usermodmap=$HOME/.Xmodmap
sysresources=/etc/X11/xinit/.Xresources
sysmodmap=/etc/X11/xinit/.Xmodmap

SESSION=${1:-xfce}

# merge in defaults and keymaps

if [ -f $sysresources ]; then
    xrdb -merge $sysresources
fi

if [ -f $sysmodmap ]; then
    xmodmap $sysmodmap
fi

if [ -f "$userresources" ]; then
    xrdb -merge "$userresources"
fi

if [ -f "$usermodmap" ]; then
    xmodmap "$usermodmap"
fi

# start some nice programs

if [ -d /etc/X11/xinit/xinitrc.d ] ; then
    for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do
        [ -x "$f" ] && . "$f"
    done
    unset f
    picom &
    sxhkd &
fi

get_session(){
	local dbus_args=(--sh-syntax --exit-with-session)
	case "$SESSION" in
		awesome) dbus_args+=(awesome) ;;
		bspwm) dbus_args+=(bspwm-session) ;;
		budgie) dbus_args+=(budgie-desktop) ;;
		cinnamon) dbus_args+=(cinnamon-session) ;;
		deepin) dbus_args+=(startdde) ;;
		dwm) dbus_args+=(dwm) ;;
		enlightenment) dbus_args+=(enlightenment_start) ;;
		fluxbox) dbus_args+=(startfluxbox) ;;
		gnome) dbus_args+=(gnome-session) ;;
		i3|i3wm) dbus_args+=(i3 --shmlog-size 0) ;;
		jwm) dbus_args+=(jwm) ;;
		kde) dbus_args+=(startkde) ;;
		lxde) dbus_args+=(startlxde) ;;
		lxqt) dbus_args+=(lxqt-session) ;;
		mate) dbus_args+=(mate-session) ;;
		xfce) dbus_args+=(xfce4-session) ;;
		openbox) dbus_args+=(openbox-session) ;;
		*) dbus_args+=("$SESSION") ;;
	esac

	echo "dbus-launch ${dbus_args[*]}"
}

#exec $(get_session)

# lastly we exec the chosen session
exec "${sessions[$session]}"

My wife and I are headed for a walk (masks and all). Thanks!

Yea I kinda suspected as much and why I mentioned a wrapper. Here’s what I did (this time I actually tested it XD)

~/.xinitrc

#!/bin/sh

if [ -n "$1" ]; then
	session="$1"
else
	session="yaxwm" # used when no session given *no wrapper*
fi

# standard xinitrc stuff here

exec "$session" > ~/.local/share/xorg/"$session.log" 2>&1

~/.zprofile (whatever ~/.*profile matches your shell)

# standard profile stuff here

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && ~/bin/startxwrapper

~/bin/startxwrapper

#!/bin/bash

typeset -A sessions
sessions=(
	[yaxwm]='yaxwm'
	[bspwm]='bspwm'
	[dwm]='dwm'
	[i3]='i3'
	[openbox]='openbox-session'
)

clear
PS3=$'\nSession: '
select session in "${!sessions[@]}"; do
	run=0
	for i in "${!sessions[@]}"; do
		if [ "$i" == "$session" ]; then
			run=1
			break;
		fi
	done
	[ "$run" -eq 0 ] && echo "invalid session, try again" && continue
	break
done

if [ "$run" -eq 0 ]; then
	echo "invalid session, exiting"
else
	startx ~/.xinitrc "${sessions[$session]}" > ~/.local/share/xorg/Xorg.0.log 2>&1
fi

Upon login I get prompted with

1) openbox
2) dwm
3) yaxwm
4) bspwm
5) i3

Session: |

After entering a valid number for which session I want, it’s started.


You could do a lot more as well, like searching for known executables or packages and offering selections for them rather than hardcoded, but this serves the purpose of the op.

2 Likes

It’s official I’m feeling really dumb.

Here’s my .xinitrc:

#!/bin/bash
#
# ~/.xinitrc
#
# Executed by startx (run your window manager from here)

#!/bin/sh

if [ -n "$1" ]; then
	session="$1"
else
	session="bspwm" # used when no session given *no wrapper*
fi

# standard xinitrc stuff here


# merge in defaults and keymaps

if [ -f $sysresources ]; then
    xrdb -merge $sysresources
fi

if [ -f $sysmodmap ]; then
    xmodmap $sysmodmap
fi

if [ -f "$userresources" ]; then
    xrdb -merge "$userresources"
fi

if [ -f "$usermodmap" ]; then
    xmodmap "$usermodmap"
fi

# start some nice programs

if [ -d /etc/X11/xinit/xinitrc.d ] ; then
    for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do
        [ -x "$f" ] && . "$f"
    done
    unset f
    picom &
    sxhkd &
fi

get_session(){
	local dbus_args=(--sh-syntax --exit-with-session)
	case "$SESSION" in
		awesome) dbus_args+=(awesome) ;;
		bspwm) dbus_args+=(bspwm-session) ;;
		budgie) dbus_args+=(budgie-desktop) ;;
		cinnamon) dbus_args+=(cinnamon-session) ;;
		deepin) dbus_args+=(startdde) ;;
		dwm) dbus_args+=(dwm) ;;
		enlightenment) dbus_args+=(enlightenment_start) ;;
		fluxbox) dbus_args+=(startfluxbox) ;;
		gnome) dbus_args+=(gnome-session) ;;
		i3|i3wm) dbus_args+=(i3 --shmlog-size 0) ;;
		jwm) dbus_args+=(jwm) ;;
		kde) dbus_args+=(startkde) ;;
		lxde) dbus_args+=(startlxde) ;;
		lxqt) dbus_args+=(lxqt-session) ;;
		mate) dbus_args+=(mate-session) ;;
		xfce) dbus_args+=(xfce4-session) ;;
		openbox) dbus_args+=(openbox-session) ;;
		*) dbus_args+=("$SESSION") ;;
	esac

	echo "dbus-launch ${dbus_args[*]}"
}

#exec $(get_session)

exec "$session" > ~/.local/share/xorg/"$session.log" 2>&1

My .profile reads:

# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
	. "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

# .xinitrc wrapper

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && ~/bin/startxwrapper

When I select Ctl-Alt-F2 from LightDM to access cli, I get terminal login after login I get a command prompt. No little list (table) appears. If I type startx, the whole shebang hangsup. Ctl-Alt-F7 gets me back to LightDM.

I did set the scripts to execute… I have even tried placing the startxwrapper in /bin/ at the system level; as well as in my /home area.

Obviously I am a loose nut on the keyboard. I’m certain I’m doing something dumb. I just don’t really know what. Thanks for your patience. :slight_smile:

Well that’s very simple, the wrapper script is only run if no other graphical session is running and we’re on tty1, this line in profile

[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && ~/bin/startxwrapper

If you just always want it to run regardless than remove the check and just run the wrapper. Or increase the check and allow tty2 etc.

I’m sorry I didn’t realize this earlier but if you’re using lightdm then adding a session entry like @PackRat posted would be a much simpler option, rather than hacking around multiple login managers.

I do seem to be looping… the last fix did not work. I suppose I could remove LightDM and just use .xinitrc (not that I have done that before…)

So my question would be, what is cleanest in the end? Should I just use xinitrc or fix up LightDM?

I think you’d need to in the very least disable lightdm as xinit will not work otherwise.

Can you point me to instructions on how-to disable LightDM? I can give that a go…

Unless you’re comfortable scripting and fiddling/hacking things to get them working I think adding a session to start [insert wm here] from lightdm would be easiest.

To disable lightdm you can use

systemctl disable lightdm

Then reboot.

To (re)enable

systemctl enable lightdm

I should have remembered that… sorry to be so thick.

I tried the disable LightDM and it failed as well.

Next I’ll try @PackRat’s solution, methinks…

1 Like

Did you get a prompt to enter your password when trying to disable lightdm?

Yes I did…