233 lines
8.1 KiB
Haskell
Raw Normal View History

2017-08-23 12:43:25 -07:00
module Main where
import qualified Control.Concurrent.MVar as MV
2017-03-04 12:03:10 -08:00
import Control.Exception.Base
2017-03-28 22:16:08 -07:00
import Control.Monad
2017-09-12 01:58:47 -07:00
import Control.Monad.Reader
import Data.List
import Data.List.Split
import qualified Data.Map as M
2017-03-28 22:16:08 -07:00
import Data.Maybe
import qualified Graphics.UI.Gtk as Gtk
import qualified Graphics.UI.Gtk.Abstract.Widget as W
import qualified Graphics.UI.Gtk.Layout.Table as T
import System.Directory
import System.Environment
import System.FilePath.Posix
import System.Information.CPU
import System.Information.EWMHDesktopInfo
import System.Information.Memory
import System.Information.X11DesktopInfo
import System.Process
import System.Taffybar
2017-09-12 01:58:47 -07:00
import System.Taffybar.IconImages
2017-03-05 18:30:55 -08:00
import System.Taffybar.LayoutSwitcher
import System.Taffybar.MPRIS2
2017-03-29 18:53:03 -07:00
import System.Taffybar.NetMonitor
import System.Taffybar.Pager
import System.Taffybar.SimpleClock
import System.Taffybar.Systray
2017-05-24 21:56:34 -07:00
import System.Taffybar.ToggleMonitor
import System.Taffybar.Widgets.PollingGraph
2017-03-05 18:30:55 -08:00
import System.Taffybar.WindowSwitcher
import System.Taffybar.WorkspaceHUD
import Text.Printf
2017-09-12 01:58:47 -07:00
import Text.Read hiding (get, lift)
2017-09-12 01:58:47 -07:00
data ConstantIconController = ConstantIconController { cicImage :: Gtk.Image }
instance WorkspaceWidgetController ConstantIconController where
updateWidget cic _ = return cic
getWidget = Gtk.toWidget . cicImage
2016-09-16 14:11:52 -07:00
2017-05-24 21:56:34 -07:00
memCfg =
defaultGraphConfig
{graphDataColors = [(0.129, 0.588, 0.953, 1)], graphLabel = Just "mem"}
memCallback :: Gtk.Widget -> IO [Double]
memCallback widget = do
2016-09-16 14:11:52 -07:00
mi <- parseMeminfo
2017-05-24 21:56:34 -07:00
let tooltip = printf "%s/%s" (show $ memoryUsed mi) (show $ memoryTotal mi) :: String
Gtk.postGUIAsync $ do
_ <- Gtk.widgetSetTooltipText widget (Just tooltip)
return ()
2016-09-16 14:11:52 -07:00
return [memoryUsedRatio mi]
getFullWorkspaceNames :: X11Property [(WorkspaceIdx, String)]
getFullWorkspaceNames = go <$> readAsListOfString Nothing "_NET_DESKTOP_FULL_NAMES"
where go = zip [WSIdx i | i <- [0..]]
workspaceNamesLabelSetter workspace = do
2017-10-13 22:09:08 -07:00
fullNames <- liftX11Def [] getFullWorkspaceNames
return $ fromMaybe "" $ lookup (workspaceIdx workspace) fullNames
2017-05-24 21:56:34 -07:00
mem :: IO Gtk.Widget
mem = do
ebox <- Gtk.eventBoxNew
btn <- pollingGraphNew memCfg 1 $ memCallback $ Gtk.toWidget ebox
Gtk.containerAdd ebox btn
_ <- Gtk.on ebox Gtk.buttonPressEvent systemEvents
Gtk.widgetShowAll ebox
return $ Gtk.toWidget ebox
systemEvents :: Gtk.EventM Gtk.EButton Bool
2017-07-27 19:59:23 -07:00
systemEvents = return True
2017-05-24 21:56:34 -07:00
2016-09-16 14:11:52 -07:00
cpuCallback = do
(_, systemLoad, totalLoad) <- cpuLoad
2016-09-16 14:11:52 -07:00
return [totalLoad, systemLoad]
2017-03-04 13:13:03 -08:00
underlineWidget cfg buildWidget name = do
w <- buildWidget
t <- T.tableNew 2 1 False
u <- Gtk.eventBoxNew
2017-03-04 13:13:03 -08:00
W.widgetSetSizeRequest u (-1) $ underlineHeight cfg
T.tableAttach t w 0 1 0 1 [T.Expand] [T.Expand] 0 0
T.tableAttach t u 0 1 1 2 [T.Fill] [T.Shrink] 0 0
2017-03-05 18:30:55 -08:00
Gtk.widgetSetName u (printf "%s-underline" name :: String)
Gtk.widgetShowAll t
return $ Gtk.toWidget t
movableWidget builder =
do
-- Delay creation of the widget or else failure from trying to get screen
widVar <- MV.newEmptyMVar
let moveWidget = do
isEmpty <- MV.isEmptyMVar widVar
when isEmpty $
do
putwid <- builder
MV.putMVar widVar putwid
wid <- MV.readMVar widVar
hbox <- Gtk.hBoxNew False 0
parent <- Gtk.widgetGetParent wid
if isJust parent
then
Gtk.widgetReparent wid hbox
else
Gtk.containerAdd hbox wid
2017-04-08 02:50:49 -07:00
Gtk.widgetShowAll hbox
return $ Gtk.toWidget hbox
return moveWidget
myFormatEntry wsNames ((ws, wtitle, wclass), _) =
printf "%s: %s - %s" wsName (head $ splitOn "\NUL" wclass) wtitle
where
wsName = M.findWithDefault ("WS#" ++ show wsN) ws wsNames
WSIdx wsN = ws
getInterfaces = do
(_, output, _) <- readCreateProcessWithExitCode (shell "list_interfaces.sh") ""
return $ splitOn "\n" output
2016-09-16 14:11:52 -07:00
main = do
interfaceNames <- getInterfaces
2017-03-05 18:30:55 -08:00
homeDirectory <- getHomeDirectory
2017-05-30 18:23:13 -07:00
let resourcesDirectory = homeDirectory </> ".lib" </> "resources"
inResourcesDirectory file = resourcesDirectory </> file
2017-10-13 22:09:08 -07:00
highContrastDirectory =
"/" </> "usr" </> "share" </> "icons" </> "HighContrast" </> "256x256"
inHighContrastDirectory file = highContrastDirectory </> file
getWorkspacePixBuf size Workspace {workspaceIdx = WSIdx wsId} =
2017-09-12 02:55:32 -07:00
pixBufFromFile size . inHighContrastDirectory <$>
2017-10-13 22:09:08 -07:00
case wsId + 1 of
1 -> Just $ "apps" </> "utilities-terminal.png"
2 -> Just $ "emblems" </> "emblem-documents.png"
3 -> Just $ "actions" </> "bookmark-add.png"
4 -> Just $ "devices" </> "video-display.png"
_ -> Nothing
2017-09-12 01:58:47 -07:00
buildConstantIconController :: ControllerConstructor
buildConstantIconController ws = do
2017-10-13 22:09:08 -07:00
cfg <- asks hudConfig
lift $ do
img <- Gtk.imageNew
pb <- sequence $ getWorkspacePixBuf (windowIconSize cfg) ws
setImage (windowIconSize cfg) img pb
return $ WWC ConstantIconController {cicImage = img}
makeIcon = return . IIFilePath . inResourcesDirectory
myGetIconInfo w@WindowData {windowTitle = title, windowClass = klass}
2017-05-30 18:23:13 -07:00
| "URxvt" `isInfixOf` klass = makeIcon "urxvt.png"
| "Termite" `isInfixOf` klass = makeIcon "urxvt.png"
2017-05-30 18:23:13 -07:00
| "Kodi" `isInfixOf` klass = makeIcon "kodi.png"
| "@gmail.com" `isInfixOf` title &&
"chrome" `isInfixOf` klass && "Gmail" `isInfixOf` title =
makeIcon "gmail.png"
| otherwise = do
res <- defaultGetIconInfo w
return $
case res of
IINone -> IIFilePath $ inResourcesDirectory "exe-icon.png"
_ -> res
cpuCfg =
defaultGraphConfig
{ graphDataColors = [(0, 1, 0, 1), (1, 0, 1, 0.5)]
, graphLabel = Just "cpu"
}
2017-03-05 18:30:55 -08:00
clock = textClockNew Nothing "%a %b %_d %r" 1
2016-09-19 12:08:25 -07:00
mpris = mpris2New
2016-09-16 14:11:52 -07:00
cpu = pollingGraphNew cpuCfg 0.5 cpuCallback
2017-09-12 01:58:47 -07:00
myHUDConfig =
defaultWorkspaceHUDConfig
{ underlineHeight = 3
2017-07-27 19:59:23 -07:00
, underlinePadding = 2
, minWSWidgetSize = Nothing
, minIcons = 1
, getIconInfo = myGetIconInfo
2017-10-13 22:09:08 -07:00
, windowIconSize = 32
, widgetGap = 0
2017-10-13 22:09:08 -07:00
, widgetBuilder =
buildButtonController $
buildUnderlineController $
buildContentsController
[ buildConstantIconController
, buildLabelController
, buildIconController
]
, showWorkspaceFn = hideEmpty
, updateRateLimitMicroseconds = 100000
, updateIconsOnTitleChange = True
, updateOnWMIconChange = True
2017-03-04 14:13:49 -08:00
, debugMode = False
2017-03-04 03:45:10 -08:00
, redrawIconsOnStateChange = True
2017-03-05 18:30:55 -08:00
, innerPadding = 5
, outerPadding = 5
, labelSetter = workspaceNamesLabelSetter
}
netMonitor = netMonitorMultiNew 1.5 interfaceNames
pagerConfig =
defaultPagerConfig
{useImages = True, windowSwitcherFormatter = myFormatEntry}
2017-09-12 01:58:47 -07:00
makeUnderline = underlineWidget myHUDConfig
2017-03-05 18:30:55 -08:00
pgr <- pagerNew pagerConfig
2017-10-13 22:09:08 -07:00
-- tray2 <- movableWidget tray
2017-09-12 01:58:47 -07:00
let hud = buildWorkspaceHUD myHUDConfig pgr
2017-03-05 18:30:55 -08:00
los = makeUnderline (layoutSwitcherNew pgr) "red"
wnd = makeUnderline (windowSwitcherNew pgr) "teal"
2017-03-12 21:25:59 -07:00
taffyConfig =
defaultTaffybarConfig
{ startWidgets = [hud, los, wnd]
, endWidgets =
[ makeUnderline clock "teal"
-- , makeUnderline systrayNew "yellow"
-- , makeUnderline mem "blue"
-- , makeUnderline cpu "green"
-- , makeUnderline netMonitor "yellow"
2017-03-12 21:25:59 -07:00
, makeUnderline mpris "red"
]
, barPosition = Top
2017-10-18 19:34:01 -07:00
, barPadding = 10
, barHeight = (underlineHeight myHUDConfig + windowIconSize myHUDConfig) +
(2 * (innerPadding myHUDConfig + outerPadding myHUDConfig))
2017-03-12 21:25:59 -07:00
, widgetSpacing = 5
}
2017-04-08 02:50:49 -07:00
withToggleSupport taffyConfig
2016-09-16 14:11:52 -07:00
-- Local Variables:
-- flycheck-ghc-args: ("-Wno-missing-signatures")
-- End: