taffybar-4.0.0: src/System/Taffybar/Widget/SNITray.hs
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module : System.Taffybar.Widget.SNITray
-- Copyright : (c) Ivan A. Malison
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Ivan A. Malison
-- Stability : unstable
-- Portability : unportable
--
-- This module exports functions for the construction of
-- StatusNotifierItem/AppIndicator tray widgets, supplied by the
-- "StatusNotifier.Tray" module from the gtk-sni-tray library. These widgets do
-- not support the older XEMBED protocol, although bridges like
-- xembed-sni-proxy do allow sni trays to provide limited support for XEMBED
-- tray icons.
--
-- Unless 'sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt' is used it is
-- necessary to run status-notifier-watcher from the
-- [status-notifier-item](https://github.com/taffybar/status-notifier-item)
-- package before starting taffybar when using the functions defined in this
-- module. Using 'sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt' is
-- generally not recommended, because it can lead to issues with the
-- registration of tray icons if taffybar crashes/restarts, or if tray icon
-- providing applications are ever started before taffybar.
-----------------------------------------------------------------------------
module System.Taffybar.Widget.SNITray
( TrayParams
, module System.Taffybar.Widget.SNITray
) where
import Control.Monad.Trans.Class
import Control.Monad.Trans.Reader
import qualified GI.Gtk
import qualified StatusNotifier.Host.Service as H
import StatusNotifier.Tray
import System.Posix.Process
import System.Taffybar.Context
import System.Taffybar.Widget.Util
import Text.Printf
-- | Build a new StatusNotifierItem tray that will share a host with any other
-- trays that are constructed automatically
sniTrayNew :: TaffyIO GI.Gtk.Widget
sniTrayNew = sniTrayNewFromParams defaultTrayParams
-- | Build a new StatusNotifierItem tray from the provided 'TrayParams'.
sniTrayNewFromParams :: TrayParams -> TaffyIO GI.Gtk.Widget
sniTrayNewFromParams params =
getTrayHost False >>= sniTrayNewFromHostParams params
-- | Build a new StatusNotifierItem tray from the provided 'TrayParams' and
-- 'H.Host'.
sniTrayNewFromHostParams :: TrayParams -> H.Host -> TaffyIO GI.Gtk.Widget
sniTrayNewFromHostParams params host = do
client <- asks sessionDBusClient
lift $ do
tray <- buildTray host client params
_ <- widgetSetClassGI tray "sni-tray"
GI.Gtk.widgetShowAll tray
GI.Gtk.toWidget tray
-- | Build a new StatusNotifierItem tray that also starts its own watcher,
-- without depending on status-notifier-icon. This will not register applets
-- started before the watcher is started.
sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt :: TaffyIO GI.Gtk.Widget
sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt =
getTrayHost True >>= sniTrayNewFromHostParams defaultTrayParams
-- | Get a 'H.Host' from 'TaffyIO' internal state, that can be used to construct
-- SNI tray widgets. The boolean parameter determines whether or not a watcher
-- will be started the first time 'getTrayHost' is invoked.
getTrayHost :: Bool -> TaffyIO H.Host
getTrayHost startWatcher = getStateDefault $ do
pid <- lift getProcessID
client <- asks sessionDBusClient
Just host <- lift $ H.build H.defaultParams
{ H.dbusClient = Just client
, H.uniqueIdentifier = printf "taffybar-%s" $ show pid
, H.startWatcher = startWatcher
}
return host