Last active
November 8, 2018 11:16
-
-
Save Dmitriusan/96879d926173badeb58ac5cb430e37ae to your computer and use it in GitHub Desktop.
My current xmonad.hs (I use it with Xfce)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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