Dwm on CentOS

Aus RZ-Amper Wiki
Zur Navigation springen Zur Suche springen

This article is not about dmw only but about setting up a simple Linux Workstation based on CentOS 7.

Packages

First things first. You need the following to get packages installed.

yum install -y ncurses-term epel-release xterm ftp libX11-devel libXinerama-devel

If you want to get gnome-terminal version 3.6.2 running you will have to install the following packages.

yum install -y glib2-devel gtk2-devel gtk3-devel GConf2-devel vte3-devel gsettings-desktop-schemas-devel libSM-devel itstool

If you want to use feh (image viewer) you need the followig packages to get it compiled.

yum install -y imlib2-devel libcurl-devel libXt libXt-devel libXft libXft-devel

Personalization

Bash and VI

~/.bashrc

# .bashrc
PS1='\h\w\$ '
export EDITOR=vi
export TERM=dtterm
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# User specific aliases and functions
alias vi='/usr/bin/vim -X'
alias l='/bin/ls --group-directories-first -lah | more'

~/.vim

syntax on
filetype indent plugin off
filetype indent off

"set number              "show line numbers
set nowrap                "dont wrap lines
"set linebreak           "wrap lines at convenient points
set t_Co=256            "tell the term has 256 colors

"vertical/horizontal scroll off settings
set scrolloff=3
set sidescrolloff=7
set sidescroll=1

"mouse support
"set mouse=a
"set ttymouse=xterm2

"default indent settings
set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
"set autoindent

set backspace=2
set incsearch           "find the next match as we type the search
set nohlsearch          "no hilight of search string
set ruler

XDMCP

It seems that XDMCP is working on CentOS 6/6.5 but does not work on CentOS 7 anymore. However, a configuration similar to the following should do the trick.
/etc/gdm/custom.conf

# GDM configuration storage

[daemon]
User=gdm
Group=gdm

[security]
DisallowTCP=false
AllowRemoteRoot=true

[xdmcp]
Enable=true
DisplayPerHost=10
HonorIndirect=false
MaxPending=4
MaxSessions=32
MaxWait=30
MaxWaitIndirect=30
Port=177

[greeter]
IncludeAll=true

[chooser]
Multicast=false

[debug]
Enable=false

dwm Configuration

config.h

Keep in mind to get patches installed first.

/* See LICENSE file for copyright and license details. */

/* appearance */
// static const char font[] = "-*-courier-*-*-*--14-*-*-*-*-*-*-*";

static const char font[] = "-*-xbmicons-medium-r-*-*-12-*-*-*-*-*-*-*" ","
                           "-*-terminus-medium-r-*-*-12-*-*-*-*-*-*-*";

#define NUMCOLORS 12
static const char colors[NUMCOLORS][ColLast][9] = {
  // border foreground background
  { "#282a2e", "#999999", "#1d1f21" }, // 1 = normal (grey on black)
  { "#f0c674", "#ffffff", "#1d1f21" }, // 2 = selected (white on black)
  { "#dc322f", "#1d1f21", "#f0c674" }, // 3 = urgent (black on yellow)
  { "#282a2e", "#282a2e", "#1d1f21" }, // 4 = darkgrey on black (for glyphs)
  { "#282a2e", "#1d1f21", "#282a2e" }, // 5 = black on darkgrey (for glyphs)
  { "#282a2e", "#cc6666", "#1d1f21" }, // 6 = red on black
  { "#282a2e", "#b5bd68", "#1d1f21" }, // 7 = green on black
  { "#282a2e", "#de935f", "#1d1f21" }, // 8 = orange on black
  { "#282a2e", "#f0c674", "#282a2e" }, // 9 = yellow on darkgrey
  { "#282a2e", "#81a2be", "#282a2e" }, // A = blue on darkgrey
  { "#282a2e", "#b294bb", "#282a2e" }, // B = magenta on darkgrey
  { "#282a2e", "#8abeb7", "#282a2e" }, // C = cyan on darkgrey
};
  // border foreground background
  // { "#282a2e", "#373b41", "#1d1f21" }, // 1 = normal (grey on black)
  // { "#f0c674", "#c5c8c6", "#1d1f21" }, // 2 = selected (white on black)
  // { "#dc322f", "#1d1f21", "#f0c674" }, // 3 = urgent (black on yellow)
  // { "#282a2e", "#282a2e", "#1d1f21" }, // 4 = darkgrey on black (for glyphs)
  // { "#282a2e", "#1d1f21", "#282a2e" }, // 5 = black on darkgrey (for glyphs)
  // { "#282a2e", "#cc6666", "#1d1f21" }, // 6 = red on black
  // { "#282a2e", "#b5bd68", "#1d1f21" }, // 7 = green on black
  // { "#282a2e", "#de935f", "#1d1f21" }, // 8 = orange on black
  // { "#282a2e", "#f0c674", "#282a2e" }, // 9 = yellow on darkgrey
  // { "#282a2e", "#81a2be", "#282a2e" }, // A = blue on darkgrey
  // { "#282a2e", "#b294bb", "#282a2e" }, // B = magenta on darkgrey
  // { "#282a2e", "#8abeb7", "#282a2e" }, // C = cyan on darkgrey
  // };
  //

// static const char normbordercolor[] = "#bbbbbb";
// static const char normbgcolor[]     = "#222222";
// static const char normfgcolor[]     = "#999999";
// static const char selbordercolor[]  = "#005577";
// static const char selbgcolor[]      = "#005577";
// static const char selfgcolor[]      = "#ffffff";
static const char normbordercolor[]     = "#073642";
static const char normbgcolor[]         = "#002b36";
static const char normfgcolor[]         = "#fdf6e3";
static const char selbordercolor[]      = "#586e75";
static const char selbgcolor[]          = "#073642";
static const char selfgcolor[]          = "#fdf6e3";
static const unsigned int borderpx  = 0;        /* border pixel of windows */
static const unsigned int snap      = 5;       /* snap pixel */
static const Bool showbar           = True;     /* False means no bar */
static const Bool topbar            = True;     /* False means bottom bar */

/* tagging */
static const char *tags[] = { "Geile Terminals", "2", "3", "4", "RDP", "Windows", "Citrix", "Mail", "Web" };

static const Rule rules[] = {
        /* class                  instance          title                   tags mask     isfloating   monitor */
        { "Gimp",                 NULL,             NULL,                   0,            True,         -1 },
        { "Xfce4-terminal",       NULL,             NULL,                   0,            False,        -1 },
        { "VirtualBox",           "VirtualBox",     NULL,                   0,            True,         -1 },
        { "Firefox",              "Navigator",      NULL,                   1 << 8,       False,        -1 },
        { "Firefox",              "Browser",        "Firefox Preferences",  1 << 8,       True,         -1 },
        { "Thunderbird",          NULL,             NULL,                   1 << 7,       False,        -1 },
        { "Thunderbird",          "Msgcompose",     NULL,                   1 << 7,       True,         -1 },
        { "Wfica",                NULL,             NULL,                   1 << 6,       True,         -1 },
        { "xfreerdp",             NULL,             NULL,                   1 << 4,       True,         -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 Bool resizehints = True; /* True means respect size hints in tiled resizals */

#include "bstack.c"
#include "bstackhoriz.c"

static const Layout layouts[] = {
       /* symbol     arrange function */
       { "[]=",      tile },    /* first entry is default */
       { "><>",      NULL },    /* no layout function means floating behavior */
       { "[M]",      monocle },
};

/* 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} },

/* 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 const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
static const char *termcmd[]  = { "gnome-terminal", 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,                       XK_q,      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 } },
       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)
       { MODKEY|ShiftMask,             XK_q,      quit,           {0} },
};

/* button definitions */
/* click can be 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]} },
       { 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} },
};

X Session

Create a .desktop file so you can choose dwm from the gdm greeter. /usr/share/xsessions/dwm.desktop

[Desktop Entry]
Name=dwm
Comment=The dwm tiling window manager
Exec=/usr/local/bin/dwm-wrapper
# no icon yet, only the top three are currently used
Icon=
Type=Application

dwm-wrapper

The .desktop file will call the dwm-wrapper, which sets the top menu bar. /usr/local/bin/dwm-wrapper

#! /bin/sh
# setxkbmap -option terminate:ctrl_alt_bksp
# feh --bg-scale /home/shaun/img/arch.png
# conky -x 0 -y 0 -d
# Colour codes from dwm/config.h
colour_gry="\x01" # grey on black
colour_wht="\x02" # white on black
colour_dgry="\x04" # darkgrey on black
colour_blk="\x05" # black on darkgrey
colour_red="\x06" # colour_red on black
colour_grn="\x07" # green on black
colour_dylw="\x08" # orange on black
colour_ylw="\x09" # yellow on black
colour_blu="\x0A" # colour_blue on darkgrey
colour_mag="\x0B" # colour_magenta on darkgrey
colour_cyn="\x0C" # cyan on darkgrey

# Icon glyphs from font xbmicons.pcf
glyph_msc="\uE00E"
glyph_cpu="\uE00F"
glyph_mem="\uE010"
glyph_dl="\uE011"
glyph_ul="\uE012"
glyph_com="\uE013"
glyph_eml="\uE014"
glyph_vol="\uE015"
glyph_tim="\uE016"
glyph_tor="\uE017"
sep_solid="\uE01A"
sep_line="\uE01B"
sep_bar="\uE020"

print_mem_used() {
    mem_used="$(free -m | awk 'NR==3 {print $3}')"
    echo -ne "${sep_line} ${glyph_mem} ${mem_used}M "
}

print_volume() {
    volume="$(amixer get IEC958 | tail -n1 | sed -r 's/.*\[(.*)%\].*/\1/')"
    echo -ne "${colour_dgry}${sep_solid}${colour_mag} ${glyph_vol} ${volume}% "
}

print_datetime() {
    datetimeloc="$(date "+%A %d.%m.%Y %Z=%H:%M")"
    datetimeusc="$(TZ=US/Central date "+%Z=%H:%M")"
    datetime="$(date "+%a %d %b ${sep_line} %H:%M")"
    echo -ne "${colour_blk}${sep_solid}${colour_wht} ${glyph_tim} ${datetimeloc} ${datetimeusc}"
}

rx_old=$(cat /sys/class/net/em1/statistics/rx_bytes)
tx_old=$(cat /sys/class/net/em1/statistics/tx_bytes)

while true; do
    # get new cpu idle and total usage
    eval $(awk '/^cpu /{print "cpu_idle_now=" $5 "; cpu_total_now=" $2+$3+$4+$5 }' /proc/stat)
    cpu_interval=$((cpu_total_now-${cpu_total_old:-0}))

    # calculate cpu usage (%)
    let cpu_used="100 * ($cpu_interval - ($cpu_idle_now-${cpu_idle_old:-0})) / $cpu_interval"

    # get new rx/tx counts
    rx_now=$(cat /sys/class/net/em1/statistics/rx_bytes)
    tx_now=$(cat /sys/class/net/em1/statistics/tx_bytes)

    # calculate the rate (K) and total (M)
    let rx_rate=($rx_now-$rx_old)/1024
    let tx_rate=($tx_now-$tx_old)/1024
    # let rx_total=$rx_now/1048576
    # let tx_total=$tx_now/1048576

    # output vars
    print_cpu_used() {
        printf "%-14b" "${colour_dgry}${sep_solid}${colour_blu} ${glyph_cpu} ${cpu_used}%"
    }
    print_rx_rate() {
        printf "%-15b" "${colour_blk}${sep_solid}${colour_grn} ${glyph_dl} ${rx_rate}K"
    }
    print_tx_rate() {
        printf "%-14b" "${colour_gry}${sep_line}${colour_red} ${glyph_ul} ${tx_rate}K"
    }

    # Pipe to status bar, not indented due to printing extra spaces/tabs
    xsetroot -name "$(print_cpu_used)$(print_mem_used)\
    $(print_rx_rate)$(print_tx_rate)\
    $(print_volume)\
    $(print_datetime)"

    # reset old rates
    rx_old=$rx_now
    tx_old=$tx_now
    cpu_idle_old=$cpu_idle_now
    cpu_total_old=$cpu_total_now

    # loop stats every 1 second
    sleep 1s
done &

/bin/xset fp+ /usr/share/fonts/terminus &
/bin/xset fp+ /usr/share/fonts/terminus2 &
/bin/xset fp+ /usr/share/fonts/xbmicons_pcf &
/bin/xset fp rehash &
/usr/local/bin/feh --bg-scale /usr/share/backgrounds/funeral.jpg &
/bin/sleep 1; /bin/xset dpms force off &
/bin/xrandr --output DP2 --rotate left

exec /usr/local/bin/dwm

.Xresources

In my .Xresources, I'm setting the UXTerm color to white on black, as well as fixing a bug with the Alt key in SSH sessions. The last line is to set the window URGENT flag when the window uses the system bell.

UXTerm*eightBitInput: false
UXTerm*metaSendsEscape: true
UXTerm*reverseVideo: true
UXTerm*bellIsUrgent: true

Tweaking dwm

Rules

What does ‘rules’ do?

The rules array allows to treat certain applications (clients) in a special way. A rule has a matching and an action part. When a new client appears (sends a maprequest), it is matched against the rules based on its class, instance (WM_CLASS) and title (WM_NAME) properties and then the given tag and floating mode setting actions are performed. The default tag mask is 0, which means the currently viewed tags, and the default mode is tiled so isfloating is False. Example from the default config:

static Rule rules[] = {
   /* class      instance    title       tags mask     isfloating   monitor */
   { "Gimp",     NULL,       NULL,       0,            True,        -1 },
   { "Firefox",  NULL,       NULL,       1 << 8,       True,        -1 },
};

These rules make every Gimp and Firefox window floating and makes Firefox windows appear on tag 9 instead of the currently viewed tags.

How does the matching work?

A client is matched if its properties contain the given strings as substrings (case-sensitively) or NULL is given (which means anything is matched there). More than one rule can be applied to a client, the rules are matched in order.

How to check these properties of a client?

The xprop utility can be used to get this information: WM_CLASS is (instance, class) WM_NAME (or _NET_WM_NAME) is the title. For example this shell script prints the relevant properties of the selected client (if the properties does not contain ‘=’ or ‘,’):

xprop |awk '
   /^WM_CLASS/{sub(/.* =/, "instance:"); sub(/,/, "\nclass:"); print}
   /^WM_NAME/{sub(/.* =/, "title:"); print}'

Hints and Tips

Battery status

upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep 'percentage' | sed -r 's/^\s*percentage:\s*([0-9]*)\.?.*$/bat: \1%/'
upower -i /org/freedesktop/UPower/devices/battery_BAT0 | grep 'state' | awk '{print $2}'

Links to usefull web sites

https://github.com/chjj/dwm/blob/master/dwm-status