Skip to content

Instantly share code, notes, and snippets.

@Dmitriusan
Last active November 8, 2018 11:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Dmitriusan/96879d926173badeb58ac5cb430e37ae to your computer and use it in GitHub Desktop.
Save Dmitriusan/96879d926173badeb58ac5cb430e37ae to your computer and use it in GitHub Desktop.
My current xmonad.hs (I use it with Xfce)
import qualified Data.Map as M
import qualified XMonad.StackSet as W
import Data.String
import Data.List
import Data.Maybe
import Data.Ratio
import Control.Monad (liftM2)
import Control.Monad.IO.Class (liftIO)
import System.Environment (setEnv)
import Graphics.X11.ExtraTypes.XF86
import XMonad
import XMonad.Config.Desktop
import XMonad.Config.Xfce
import qualified XMonad.StackSet as W
--import XMonad.Config.Gnome
--import XMonad.Config.Kde
import XMonad.ManageHook
import XMonad.Util.Run
import XMonad.Util.EZConfig
import XMonad.Util.EZConfig(additionalKeys)
import XMonad.Util.Themes
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.SetWMName
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.ICCCMFocus
import XMonad.Hooks.FadeInactive
import XMonad.Hooks.Place
import XMonad.Actions.CycleWS
import XMonad.Actions.CycleRecentWS
import XMonad.Actions.UpdatePointer
import XMonad.Actions.Warp
import XMonad.Actions.UpdateFocus
import XMonad.Actions.FloatKeys
import XMonad.Actions.WindowGo
import XMonad.Actions.SpawnOn
import XMonad.Layout.MouseResizableTile
import XMonad.Layout.Tabbed
import XMonad.Layout.NoBorders
import XMonad.Layout.PerWorkspace
import XMonad.Layout.ResizableTile
import XMonad.Layout.TwoPane
import XMonad.Layout.Spiral
import XMonad.Layout.LayoutHints
import XMonad.Layout.NoBorders
import XMonad.Layout.MosaicAlt
import XMonad.Layout.IM
import XMonad.Layout.PerWorkspace
import XMonad.Layout.Reflect
-- What is done on startup
myStartupHook = do
ewmhDesktopsStartup
-- TODO: after upgrading to newer Haskel (> Ubuntu 14.04) try using a recommended workaround (see env variable below in xmonad config)
setWMName "Metacity"
spawn "/home/i/bin/monitors_off.sh ; sleep 2 ; /home/i/bin/monitors_on.sh"
spawn "pkill redshift; redshift -l 50.450509:30.487061 "
spawnOn "11:w-" "/usr/bin/nuvolaplayer3 -a google_play_music"
spawn "stardict -h"
spawn "slack"
spawn "/usr/bin/skypeforlinux"
spawn "nuvolaplayer3 -a google_play_music"
spawn "thunderbird"
spawnOn "14:wF1" "google-chrome --profile-directory='Profile 1'"
spawnOn "14:wF1" "google-chrome --profile-directory='Profile 4'"
spawnOn "w22:F9" "google-chrome --new-window --profile-directory='Default'"
-- Define amount and names of workspaces
myWorkspaces = [
-- First keyboard row
"1:w1","2:w2","3:w3","4:w4","5:w5","6:w6","7:w7","8:w8","9:w9", "10:w0", "11:w-", "12:w+", "13:wBackspace",
-- Row of Fx keys
"14:wF1", "15:wF2", "16:wF3", "17:wF4", "18:wF5", "19:wF6", "20:wF-new7", "21:wF8", "w22:F9", "23:wF10", "24:wF11", "25:wF12",
-- Hardcore: insert-home block
"26:wInsert", "27:wHome", "28:wPgUp", "29:wDel", "30:wEnd", "31:wPgDown"
]
evernoteAppName = "www.evernote.com__Home.action"
googleTasksAppName = "mail.google.com__tasks_canvas"
skypeWindowClassName = "Skype"
slackWindowClassName = "Slack"
firefoxWindowClassName = "Firefox"
thunderBirdWindowClassName = "Thunderbird"
googlePlayMusicClassName = "eu.tiliado.NuvolaAppGooglePlayMusic"
jetbrainsClassName = "jetbrains-"
-- Define keys to add
keysToAdd x = [
-- System, window and monitor management
-- Run hprop tool
((modMask x .|. mod1Mask, xK_h), spawn "/media/development/environment/dmi-dev/utils/hprop.sh > /tmp/hprop.log")
-- that will open rofi as window switcher
, ((modMask x .|. mod1Mask, xK_Tab), spawn "rofi -show window")
-- Manage monitors
, ((modMask x, xK_slash), spawn "/home/i/bin/monitors_off.sh")
, ((modMask x, xK_backslash), spawn "/home/i/bin/monitors_on.sh")
, ((modMask x .|. mod1Mask, xK_slash), spawn "/home/i/bin/single-view-l.sh")
, ((modMask x .|. mod1Mask, xK_backslash), spawn "/home/i/bin/single-view-r.sh")
-- Shift to previous workspace
, (((modMask x .|. controlMask), xK_Left), prevWS)
-- Shift to next workspace
, (((modMask x .|. controlMask), xK_Right), nextWS)
-- Shift window to previous workspace
, (((modMask x .|. shiftMask), xK_Left), shiftToPrev)
-- Shift window to next workspace
, (((modMask x .|. shiftMask), xK_Right), shiftToNext)
-- close focused window
, ((modMask x, xK_Escape), kill)
-- Cycle through recent workspaces, win+Down=less recent, win+Up=more recent
, ((modMask x, xK_Down), cycleRecentWS_2 [xK_Super_L] xK_Down xK_Up)
-- Show pannels
--, ((modMask, xK_b),sendMessage ToggleStruts)
-- Cycle recent (not visible) workspaces, tab is next, escape previous in history
--, let options w = map (W.greedyView `flip` w) (hiddenTags w)
-- in ("M-<Tab>" , cycleWindowSets options [xK_Super_L] xK_Tab xK_Escape)
-- Cycle through visible screens, a is next, s previous
--, let options w = map (W.view `flip` w) (visibleTags w)
-- in ("M-a" , cycleWindowSets options [xK_Super_L] xK_a xK_s)
-- Swap visible workspaces on current screen, s is next, d previous
--, let options w = map (W.greedyView `flip` w) (visibleTags w)
-- in ("M-s" , cycleWindowSets options [xK_Super_L] xK_s xK_d)
, ((modMask x .|. shiftMask , xK_a ), withFocused (sendMessage . expandWindowAlt))
, ((modMask x .|. shiftMask , xK_z ), withFocused (sendMessage . shrinkWindowAlt))
, ((modMask x .|. shiftMask , xK_s ), withFocused (sendMessage . tallWindowAlt))
, ((modMask x .|. shiftMask , xK_d ), withFocused (sendMessage . wideWindowAlt))
, ((modMask x .|. controlMask, xK_space), sendMessage resetAlt)
-- Key to swap visible screens
, ((modMask x, xK_grave), swapDispl)
-- Restart xmonad
, ((modMask x .|. controlMask .|. shiftMask .|. mod1Mask, xK_q ), spawn "if type xmonad; then xmonad --recompile && xmonad --restart; else xmessage xmonad not in \\$PATH: \"$PATH\"; fi")
-- Log out xfce
, ((modMask x .|. mod1Mask, xK_q ), spawn "xfce4-session-logout")
]
++
-- Workspace configuration
-- mod-{w,e,r} %! Switch to physical/Xinerama screens 1, 2, or 3
-- mod-shift-{w,e,r} %! Move client to screen 1, 2, or 3
[((m .|. mod4Mask, key), screenWorkspace sc >>= flip whenJust (windows . f)) -- Replace 'mod1Mask' with your mod key of choice.
| (key, sc) <- zip [xK_w, xK_e, xK_r] [0,1,2] -- was [0..] *** change to match your screen order ***
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
++
[ -- Music playback
-- Open volume manager
((modMask x .|. mod1Mask, xK_v), unsafeSpawn "/usr/bin/pkill -9 pavucontrol ; /usr/bin/pavucontrol")
-- Mute volume
, ((0,0x1008ff12), spawn "amixer -Dpulse set Master toggle")
-- Launch mpd
-- , ((0,0x1008ff32), spawn "mpd")
-- Control google play music
, ((modMask x .|. mod1Mask, xK_minus), spawn "/usr/bin/nuvolaplayer3ctl action activate")
, ((modMask x .|. mod1Mask .|. controlMask, xK_Left), spawn "/usr/bin/nuvolaplayer3ctl action prev-song")
, ((modMask x .|. mod1Mask .|. controlMask, xK_Right), spawn "/usr/bin/nuvolaplayer3ctl action next-song")
, ((modMask x .|. mod1Mask .|. controlMask, xK_space), spawn "/usr/bin/nuvolaplayer3ctl action toggle-play")
]
++
[ -- Application shortcuts
-- Whisker menu
((modMask x .|. mod1Mask, xK_F2), spawn "/usr/bin/xfce4-popup-whiskermenu")
-- Open stardict
, ((modMask x .|. mod1Mask, xK_s), spawn "/usr/bin/stardict")
-- Start Kate
, ((modMask x .|. mod1Mask, xK_F5), spawn "kate")
-- My_computer
, ((modMask x .|. mod1Mask, xK_F7), spawn "dolphin ~")
-- Start firefox
, ((modMask x .|. mod1Mask, xK_F9), spawn "firefox")
-- Start chrome
, ((modMask x .|. mod1Mask, xK_F10), spawn "google-chrome --profile-directory='Default'")
, ((modMask x .|. mod1Mask .|. shiftMask, xK_F10), spawn "google-chrome --profile-directory='Default' --incognito")
-- Start krusader
, ((modMask x .|. mod1Mask, xK_F11), spawn "krusader")
-- Start VMware
, ((modMask x .|. mod1Mask , xK_F12), spawn "vmware")
-- Screenshot tool
, ((modMask x, xK_Print), spawn "xfce4-screenshooter")
-- Run programs on "-" desktop - messengers and google music
, ((modMask x .|. mod1Mask, xK_1), runOrRaiseNext "skypeforlinux" (className =? skypeWindowClassName))
, ((modMask x .|. mod1Mask, xK_2), runOrRaiseNext "slack" (className =? slackWindowClassName))
-- Switch to window or start new one
, ((modMask x .|. mod1Mask, xK_f), runOrRaiseNext "firefox" (className =? firefoxWindowClassName))
-- Run evernote
, ((modMask x .|. mod1Mask, xK_e), runOrRaiseNext "google-chrome --profile-directory='Default' --app='https://www.evernote.com/Home.action'" (appName =? evernoteAppName))
-- Run google tasks
, ((modMask x .|. mod1Mask, xK_t), runOrRaiseNext "google-chrome --profile-directory='Default' --app='https://mail.google.com/tasks/canvas?pli=1'" (appName =? googleTasksAppName))
]
-- Workspace bindings
workspaceKeys conf@(XConfig {XMonad.modMask = modMask}) = M.fromList $
[ ((m .|. modMask, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1, xK_2, xK_3, xK_4, xK_5, xK_6, xK_7, xK_8, xK_9, xK_0, xK_minus, xK_equal, xK_BackSpace,
xK_F1, xK_F2, xK_F3, xK_F4, xK_F5, xK_F6, xK_F7, xK_F8, xK_F9, xK_F10, xK_F11, xK_F12,
xK_Insert, xK_Home, xK_Prior, xK_Delete, xK_End, xK_Next]
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
-- Mouse bindings: default actions bound to mouse events
myMouseBindings (XConfig {XMonad.modMask = modMask}) = M.fromList $
-- mod-button1 %! Set the window to floating mode and move by dragging
[ ((modMask, button1), (\w -> focus w >> mouseMoveWindow w
>> windows W.shiftMaster))
-- mod-button2 %! Raise the window to the top of the stack
, ((modMask, button2), (\w -> focus w >> windows W.shiftMaster))
-- mod-button3 %! Set the window to floating mode and resize by dragging
, ((modMask, button3), (\w -> focus w >> mouseResizeWindow w
>> windows W.shiftMaster))
-- you may also bind events to the mouse scroll wheel (button4 and button5)
, ((modMask, button5), (\_ -> moveTo Next NonEmptyWS))
, ((modMask, button4), (\_ -> moveTo Prev NonEmptyWS ))
, ((modMask .|. shiftMask, button5), (\w -> focus w >> kill ))
-- lock/unlock desktop with mouse
, ((0, 13), (\w -> spawn "/home/i/bin/monitors_on.sh" ))
, ((modMask, 13), (\w -> spawn "/home/i/bin/monitors_off.sh" ))
]
keysToRemove x = [ -- Old run dialog binding
(modMask x , xK_p)
-- Old close window binding
--, (modMask x, xK_c)
-- Unused gmrun binding
, (modMask x .|. shiftMask, xK_p)
-- Unused gnome session logout dialog
, (modMask x .|. shiftMask, xK_q)
-- Unused close focused window
, (modMask x .|. shiftMask, xK_c)
-- Old quit xmonad binding
, (modMask x , xK_q)
]
-- Delete the keys to remove from existing keys
oldKeys x = keys xfceConfig x
myKeys x = foldr M.delete (oldKeys x) (keysToRemove x)
-- Merge keys to add existing keys
tmpNewKeys x = M.union (myKeys x) (M.fromList (keysToAdd x))
newKeys x = M.union (tmpNewKeys x) (workspaceKeys x)
swapDispl = do
swapNextScreen
-- warpToScreen (1) (0.5) (0.5)
-- UpdateFocus
--takeTopFocus
--updatePointer (Relative 0.5 0.5)
-- Another configuration of cycleRecentWS that skips windows from another screens
-- See https://code.google.com/archive/p/xmonad/issues/546
cycleRecentWS_2 = cycleWindowSets options
where options w = map (W.view `flip` w) (recentTags w)
recentTags w = map W.tag $ W.hidden w ++ [W.workspace (W.current w)]
--Fading
myLogHook = do
-- TODO: for some reason, setWMName here makes AWT windows grey instead of
-- TODO: fixing the issue. Replace with env variable approach (see todo below)
-- setWMName "Metacity"
-- TODO: deprecated, remove sometime later https://hackage.haskell.org/package/xmonad-contrib-0.13/docs/XMonad-Hooks-ICCCMFocus.html
takeTopFocus
-- fadeInactiveLogHook fadeAmount
-- updatePointer (Relative 0.5 0.5)
-- where fadeAmount = 0.45
{- IntelliJ popup fix from http://youtrack.jetbrains.com/issue/IDEA-74679#comment=27-417315 -}
{- and http://youtrack.jetbrains.com/issue/IDEA-101072#comment=27-456320 -}
(~=?) :: Eq a => Query [a] -> [a] -> Query Bool
q ~=? x = fmap (isPrefixOf x) q
myManageHook = composeAll . concat $ -- define actions for newly created windows matching specific properties
[
-- Note: hooks earlier in this list override later ones, so put the
-- role hooks earlier than 'className =? "Gimp" ...' if you use both.
-- Windows to float
[composeOne [ isFullscreen -?> doFullFloat ]]
, [ className =? c --> doFloat | c <- floatsByClassName]
, [ title =? t --> doFloat | t <- floatsByTitle]
-- Windows to ignore
, [className =? t --> doIgnore | t <- ignoredByClassName]
, [title =? t --> doIgnore | t <- ignoredByTitle]
-- Manage application launcher dialogs
, [resource =? "Do" --> doIgnore ] -- Gnome Do
, [className =? "xfrun4" --> placeHook (smart (0.5, 0.5)) <+> doFloat ]
, [title =? "Run Program..." --> placeHook (smart (0.5, 0.5)) <+> doFloat ]
, [title =? "Application Finder" --> placeHook (smart (0.5, 0.5)) <+> doFloat ]
-- Window bindings to desktops
, [className =? thunderBirdWindowClassName --> doShift "18:wF5" ]
, [className =? firefoxWindowClassName --> doShift "1:w1" ]
, [appName =? googleTasksAppName --> doShift "13:wBackspace" ]
, [className =? t --> viewShift "11:w-" | t <- backgroundApps]
-- Gimp
-- Use script dmi-dev/utils/hprop.sh to get these values
, [ (stringProperty "WM_WINDOW_ROLE" =? "gimp-toolbox" <||> role =? "gimp-image-window") --> unfloat
]
, [className =? "Gimp-2.6" --> doShift "*"] -- may be "Gimp" or "Gimp-2.4" instead
, [(className =? "Gimp-2.6" <&&> fmap ("tool" `isSuffixOf`) role) --> doFloat]
-- IntelliJ idea Tweaks
-- Manage idea completion window
---- Also have to enable the "Automatically position cursor on default button" checkbox in IntelliJ Settings -> Appearance & Behaviour -> Appearance.
------ https://www.reddit.com/r/i3wm/comments/5j6old/problem_with_popup_in_idea_intellij/dbdtiub/
-- See why this is commented out https://youtrack.jetbrains.com/issue/IDEA-112015#comment=27-2783552
-- , [ appName =? "sun-awt-X11-XWindowPeer" <&&> className =? "jetbrains-idea" --> doIgnore ]
-- Maximize windows with preview of all changed files in commit
, [ (className ~=? jetbrainsClassName) <&&> (title ~=? ) t --> unfloat | t <- ideaFloatingWindows]
]
where
viewShift = doF . liftM2 (.) W.greedyView W.shift
role = stringProperty "WM_WINDOW_ROLE"
unfloat = ask >>= doF . W.sink
-- Groups by action type
floatsByClassName = ["MPlayer", "Gimp", "Smplayer", "Kget", "kget", "plasma-desktop", "xfrun4", "Run program..."]
floatsByTitle = ["alsamixer"]
ignoredByClassName = [
"Xfce4-notifyd" --Fixing takeTopFocus related issues (notification daemon steals focus)
, "sun-awt-X11-XWindowPeer"]
ignoredByTitle = ["Wrapper-1.0"]
-- Groups by app or desktop
backgroundApps = [skypeWindowClassName, "discord", googlePlayMusicClassName, slackWindowClassName] -- class names of rarely used apps at desktop -
ideaFloatingWindows = [
"Changes ", "Paths Affected by ", "Difference between ", "Files Merged with Conflicts ",
"Merge Revisions for ", "Settings Repository:"]
-- Main palletexmona
colLight = "#2f592a"
colDark = "#343d55"
colVeryDark = "#000000"
colTextLight = "#d8ffe6"
colTextDark = "#bbbbbb"
colTextUrgent = "#e81a0b"
colBorderLight = "#edf9ee" -- "#00FF00"
colBorderDark = colDark
-- Border colors for unfocused and focused windows, respectively.
myNormalBorderColor = colVeryDark
myFocusedBorderColor = "#00FF00"
-- Define a tab theme
-- TODO: determine font size based on hostname (from environment)
--tabFontSize :: String = "8"
myTabTheme = (theme smallClean) { activeColor = colLight
, inactiveColor = colDark
, activeBorderColor = colVeryDark
, inactiveBorderColor = colBorderLight
, urgentTextColor = colTextUrgent
, activeTextColor = colTextLight
, inactiveTextColor = colTextDark
, urgentBorderColor = colBorderDark
, decoHeight = 20
, fontName = "xft:Ubuntu-9"
-- , fontName = "xft:Ubuntu-" ++ tabFontSize
}
-- Define a tab layout
myTabbed = tabbed shrinkText myTabTheme
myTerminal = "konsole"
myLayout = avoidStruts $ smartBorders myTabbed ||| MosaicAlt M.empty |||tiledMirrored ||| tiled ||| tiledTall ||| (TwoPane (3/100) (1/2)) ||| (spiral (3%4))
where
-- default tiling algorithm partitions the screen into two panes
tiled = mouseResizableTile
tiledTall = Tall nmaster delta ratio --slav
-- The default number of windows in the master pane
nmaster = 1
-- Default proportion of screen occupied by master pane
ratio = 4/5
-- Percent of screen to increment by when resizing panes
delta = 3/100
tiledMirrored = mouseResizableTileMirrored
main = do
-- Work around grey Java Swing windows and problems with GTK3-apps https://bugzilla.redhat.com/show_bug.cgi?id=1061568#c9
setEnv "_JAVA_AWT_WM_NONREPARENTING" "1"
xmonad $ ewmh xfceConfig
{ modMask = mod4Mask
, terminal = myTerminal
, layoutHook = desktopLayoutModifiers myLayout
, workspaces = myWorkspaces
, keys = newKeys
, normalBorderColor = myNormalBorderColor
, focusedBorderColor = myFocusedBorderColor
, borderWidth = 2
-- , manageHook = manageHook kde4Config <+> myManageHook
-- , manageHook = manageHook defaultConfig <+> manageSpawn <+> myManageHook <+> manageDocks
-- TODO: uncomment manageSpawnWithGC when using newer Ubuntu (>16.04)
-- , manageHook = manageHook defaultConfig <+> manageSpawnWithGC <+> myManageHook <+> manageDocks
, manageHook = manageSpawn <+> manageHook defaultConfig <+> myManageHook <+> manageDocks
, mouseBindings = myMouseBindings
, logHook = myLogHook
, startupHook = myStartupHook
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment