{-# LANGUAGE ScopedTypeVariables #-}
module System.Taffybar.WindowSwitcher (
windowSwitcherNew
) where
import Control.Monad.Reader
import qualified Data.Map as M
import qualified Graphics.UI.Gtk as Gtk
import Graphics.X11.Xlib.Extras (Event)
import System.Information.EWMHDesktopInfo
import System.Information.X11DesktopInfo
import System.Taffybar.Pager
windowSwitcherNew :: Pager -> IO Gtk.Widget
windowSwitcherNew pager = do
label <- Gtk.labelNew (Nothing :: Maybe String)
Gtk.widgetSetName label "label"
let cfg = config pager
callback = pagerCallback cfg label
subscribe pager (runWithPager pager . callback) "_NET_ACTIVE_WINDOW"
assembleWidget pager label
pagerCallback :: PagerConfig -> Gtk.Label -> Event -> X11Property ()
pagerCallback cfg label _ = do
title <- getActiveWindowTitle
let decorate = activeWindow cfg
lift $ Gtk.postGUIAsync $ Gtk.labelSetMarkup label (decorate $ nonEmpty title)
assembleWidget :: Pager -> Gtk.Label -> IO Gtk.Widget
assembleWidget pager label = do
ebox <- Gtk.eventBoxNew
Gtk.widgetSetName ebox "WindowTitle"
Gtk.containerAdd ebox label
title <- Gtk.menuItemNew
Gtk.widgetSetName title "title"
Gtk.containerAdd title ebox
switcher <- Gtk.menuBarNew
Gtk.widgetSetName switcher "WindowSwitcher"
Gtk.containerAdd switcher title
menu <- Gtk.menuNew
Gtk.widgetSetName menu "menu"
menuTop <- Gtk.widgetGetToplevel menu
Gtk.widgetSetName menuTop "Taffybar_WindowSwitcher"
Gtk.menuItemSetSubmenu title menu
_ <- Gtk.on title Gtk.menuItemActivate $ fillMenu pager menu
_ <- Gtk.on title Gtk.menuItemDeselect $ emptyMenu menu
Gtk.widgetShowAll switcher
return $ Gtk.toWidget switcher
fillMenu :: Gtk.MenuClass menu => Pager -> menu -> IO ()
fillMenu pager menu =
runWithPager pager $ do
handles <- getWindowHandles
if null handles
then return ()
else do
wsNames <- getWorkspaceNames
forM_ handles $ \handle ->
liftIO $ do
let formatEntry = windowSwitcherFormatter $ config pager
item <-
Gtk.menuItemNewWithLabel (formatEntry (M.fromList wsNames) handle)
_ <-
Gtk.on item Gtk.buttonPressEvent $
liftIO $ do
runWithPager pager $ focusWindow $ snd handle
return True
Gtk.menuShellAppend menu item
Gtk.widgetShow item
emptyMenu :: Gtk.MenuClass menu => menu -> IO ()
emptyMenu menu = Gtk.containerForeach menu $ \item ->
Gtk.containerRemove menu item >> Gtk.widgetDestroy item
nonEmpty :: String -> String
nonEmpty x =
case x of
[] -> "(nameless window)"
_ -> x