Cache windows in taskbar
This commit is contained in:
parent
37538aa626
commit
7ed869fcf1
2 changed files with 66 additions and 33 deletions
|
@ -98,12 +98,12 @@ type RenderCache w s = IOCache (w, s, Int, Int, Int, Int, Xlib.Rectangle) Surfac
|
||||||
createIOCache :: Eq a => (a -> IO b) -> IOCache a b
|
createIOCache :: Eq a => (a -> IO b) -> IOCache a b
|
||||||
createIOCache = lift . Kleisli
|
createIOCache = lift . Kleisli
|
||||||
|
|
||||||
runIOCache :: Eq a => a -> StateT (IOCache a b) IO (b, Bool)
|
runIOCache :: Eq a => a -> StateT (IOCache a b) IO b
|
||||||
runIOCache a = do
|
runIOCache a = do
|
||||||
cache <- get
|
cache <- get
|
||||||
(b, updated, cache') <- liftIO $ runKleisli (runCache' cache) a
|
(b, cache') <- liftIO $ runKleisli (runCache cache) a
|
||||||
put cache'
|
put cache'
|
||||||
return (b, updated)
|
return b
|
||||||
|
|
||||||
createRenderCache :: (w -> s -> Int -> Int -> Int -> Int -> Xlib.Rectangle -> Render ())
|
createRenderCache :: (w -> s -> Int -> Int -> Int -> Int -> Xlib.Rectangle -> Render ())
|
||||||
-> CacheArrow (Kleisli IO) (w, s, Int, Int, Int, Int, Xlib.Rectangle) Surface
|
-> CacheArrow (Kleisli IO) (w, s, Int, Int, Int, Int, Xlib.Rectangle) Surface
|
||||||
|
|
|
@ -51,13 +51,15 @@ import Phi.Widget
|
||||||
import Phi.X11.Atoms
|
import Phi.X11.Atoms
|
||||||
|
|
||||||
|
|
||||||
type IconStyle = Surface -> Render ()
|
newtype IconStyle = IconStyle { withIconStyle :: Surface -> Render () }
|
||||||
|
instance Eq IconStyle where
|
||||||
|
_ == _ = True
|
||||||
|
|
||||||
idIconStyle :: IconStyle
|
idIconStyle :: IconStyle
|
||||||
idIconStyle = flip withPatternForSurface setSource
|
idIconStyle = IconStyle $ flip withPatternForSurface setSource
|
||||||
|
|
||||||
desaturateIconStyle :: Double -> IconStyle
|
desaturateIconStyle :: Double -> IconStyle
|
||||||
desaturateIconStyle v icon = do
|
desaturateIconStyle v = IconStyle $ \icon -> do
|
||||||
w <- imageSurfaceGetWidth icon
|
w <- imageSurfaceGetWidth icon
|
||||||
h <- imageSurfaceGetHeight icon
|
h <- imageSurfaceGetHeight icon
|
||||||
|
|
||||||
|
@ -104,7 +106,7 @@ data TaskStyle = TaskStyle { taskFont :: !String
|
||||||
, taskColor :: !Color
|
, taskColor :: !Color
|
||||||
, taskBorder :: !BorderConfig
|
, taskBorder :: !BorderConfig
|
||||||
, taskIconStyle :: !IconStyle
|
, taskIconStyle :: !IconStyle
|
||||||
}
|
} deriving Eq
|
||||||
|
|
||||||
data DesktopStyle = DesktopStyle { desktopFont :: !String
|
data DesktopStyle = DesktopStyle { desktopFont :: !String
|
||||||
, desktopLabelWidth :: !Int
|
, desktopLabelWidth :: !Int
|
||||||
|
@ -159,13 +161,24 @@ data WindowState = WindowState { windowTitle :: !String
|
||||||
, windowScreen :: !Xlib.Rectangle
|
, windowScreen :: !Xlib.Rectangle
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
data WindowCache = WindowCache { createScaledIconCached :: !(IOCache ([Icon], Int) (Maybe Surface))
|
data WindowCache = WindowCache { createScaledIconCached :: !(IOCache ([Icon], Int) (Maybe Icon))
|
||||||
|
, renderWindowCached :: !(IOCache (String, Maybe Icon, TaskStyle, Int, Int) Surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createScaledIconCached' = A.fromSetGet (\a cache -> cache {createScaledIconCached = a}) createScaledIconCached
|
||||||
|
renderWindowCached' = A.fromSetGet (\a cache -> cache {renderWindowCached = a}) renderWindowCached
|
||||||
|
|
||||||
|
|
||||||
|
newtype DesktopCache = DesktopCache (IOCache () ())
|
||||||
|
|
||||||
emptyWindowCache :: WindowCache
|
emptyWindowCache :: WindowCache
|
||||||
emptyWindowCache = WindowCache { createScaledIconCached = createIOCache createScaledIcon
|
emptyWindowCache = WindowCache { createScaledIconCached = createIOCache createScaledIcon
|
||||||
|
, renderWindowCached = createIOCache doRenderWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
data TaskbarCache = TaskbarCache { desktopCaches :: !(M.Map Int DesktopCache)
|
||||||
|
, windowCaches :: !(M.Map Window WindowCache)
|
||||||
}
|
}
|
||||||
createScaledIconCached' = A.fromSetGet (\a cache -> cache {createScaledIconCached = a}) createScaledIconCached
|
|
||||||
|
|
||||||
-- substitute for the liftT function in Data.Accessor.MonadState that uses the strict StateT variant
|
-- substitute for the liftT function in Data.Accessor.MonadState that uses the strict StateT variant
|
||||||
liftT :: (Monad m) => A.T r s -> StateT s m a -> StateT r m a
|
liftT :: (Monad m) => A.T r s -> StateT s m a -> StateT r m a
|
||||||
|
@ -182,6 +195,9 @@ liftIOStateT m = do
|
||||||
put s1
|
put s1
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
cached :: (MonadIO m, Eq a) => A.T s (IOCache a b) -> a -> StateT s m b
|
||||||
|
cached t = liftT t . liftIOStateT . runIOCache
|
||||||
|
|
||||||
data TaskbarMessage = WindowListUpdate ![Xlib.Window] !(M.Map Window WindowState)
|
data TaskbarMessage = WindowListUpdate ![Xlib.Window] !(M.Map Window WindowState)
|
||||||
| DesktopCountUpdate !Int
|
| DesktopCountUpdate !Int
|
||||||
| CurrentDesktopUpdate !Int
|
| CurrentDesktopUpdate !Int
|
||||||
|
@ -259,8 +275,14 @@ instance Widget Taskbar TaskbarState (M.Map Window WindowCache) where
|
||||||
y = (borderTop $ margin $ desktopBorder ds) + (borderWidth $ desktopBorder ds) + (borderTop $ padding $ desktopBorder ds)
|
y = (borderTop $ margin $ desktopBorder ds) + (borderWidth $ desktopBorder ds) + (borderTop $ padding $ desktopBorder ds)
|
||||||
|
|
||||||
case mstate of
|
case mstate of
|
||||||
Just state ->
|
Just state -> do
|
||||||
liftT (AC.mapDefault emptyWindowCache window) $ renderTask state style x y windowWidth h'
|
windowSurface <- liftT (AC.mapDefault emptyWindowCache window) . liftIOStateT $ renderWindow state style windowWidth h'
|
||||||
|
lift $ do
|
||||||
|
save
|
||||||
|
translate (fromIntegral $ x - 5) (fromIntegral $ y - 5)
|
||||||
|
withPatternForSurface windowSurface setSource
|
||||||
|
paint
|
||||||
|
restore
|
||||||
|
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
|
|
||||||
|
@ -296,36 +318,47 @@ renderText font x y w h text = do
|
||||||
moveTo ((fromIntegral x) + ((fromIntegral w) - textWidth)/2) ((fromIntegral y) + ((fromIntegral h) - textHeight)/2)
|
moveTo ((fromIntegral x) + ((fromIntegral w) - textWidth)/2) ((fromIntegral y) + ((fromIntegral h) - textHeight)/2)
|
||||||
showLayout layout
|
showLayout layout
|
||||||
|
|
||||||
renderTask :: WindowState -> TaskStyle -> Int -> Int -> Int -> Int -> StateT WindowCache Render ()
|
renderWindow :: WindowState -> TaskStyle -> Int -> Int -> StateT WindowCache IO Surface
|
||||||
renderTask state style x y w h = do
|
renderWindow state style w h = do
|
||||||
|
let h' = h - (borderV $ margin $ taskBorder style)
|
||||||
|
|
||||||
|
scaledIcon <- cached createScaledIconCached' (windowIcons state, h')
|
||||||
|
cached renderWindowCached' (windowTitle state, scaledIcon, style, w, h)
|
||||||
|
|
||||||
|
doRenderWindow :: (String, Maybe Icon, TaskStyle, Int, Int) -> IO Surface
|
||||||
|
doRenderWindow (title, scaledIcon, style, w, h) = do
|
||||||
let (r, g, b, a) = taskColor style
|
let (r, g, b, a) = taskColor style
|
||||||
leftBorder = (borderLeft $ margin $ taskBorder style) + (borderWidth $ taskBorder style) + (borderLeft $ padding $ taskBorder style)
|
leftBorder = (borderLeft $ margin $ taskBorder style) + (borderWidth $ taskBorder style) + (borderLeft $ padding $ taskBorder style)
|
||||||
rightBorder = (borderRight $ margin $ taskBorder style) + (borderWidth $ taskBorder style) + (borderRight $ padding $ taskBorder style)
|
rightBorder = (borderRight $ margin $ taskBorder style) + (borderWidth $ taskBorder style) + (borderRight $ padding $ taskBorder style)
|
||||||
h' = h - (borderV $ margin $ taskBorder style)
|
h' = h - (borderV $ margin $ taskBorder style)
|
||||||
|
|
||||||
lift $ do
|
surface <- createImageSurface FormatARGB32 (w+10) (h+10)
|
||||||
|
renderWith surface $ do
|
||||||
|
translate 5 5
|
||||||
|
|
||||||
save
|
save
|
||||||
drawBorder (taskBorder style) x y w h
|
drawBorder (taskBorder style) 0 0 w h
|
||||||
clip
|
clip
|
||||||
|
|
||||||
setSourceRGBA r g b a
|
setSourceRGBA r g b a
|
||||||
renderText (taskFont style) (fromIntegral (x + leftBorder + h' + 3)) y (w - leftBorder - h' - 3 - rightBorder) h $ windowTitle state
|
renderText (taskFont style) (fromIntegral (leftBorder + h' + 3)) 0 (w - leftBorder - h' - 3 - rightBorder) h title
|
||||||
|
|
||||||
restore
|
restore
|
||||||
|
|
||||||
(scaledIcon, updated) <- liftT createScaledIconCached' $ liftIOStateT $ runIOCache (windowIcons state, h')
|
|
||||||
case scaledIcon of
|
case scaledIcon of
|
||||||
Just icon -> lift $ do
|
Just (Icon _ _ icon) -> do
|
||||||
save
|
save
|
||||||
translate (fromIntegral $ x + leftBorder) (fromIntegral $ y + (borderTop $ margin $ taskBorder style))
|
translate (fromIntegral leftBorder) (fromIntegral . borderTop . margin . taskBorder $ style)
|
||||||
taskIconStyle style icon
|
withIconStyle (taskIconStyle style) icon
|
||||||
paint
|
paint
|
||||||
restore
|
restore
|
||||||
|
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
|
return surface
|
||||||
|
|
||||||
createScaledIcon :: ([Icon], Int) -> IO (Maybe Surface)
|
|
||||||
|
createScaledIcon :: ([Icon], Int) -> IO (Maybe Icon)
|
||||||
createScaledIcon (icons, h) = do
|
createScaledIcon (icons, h) = do
|
||||||
case bestIcon of
|
case bestIcon of
|
||||||
Just (Icon _ _ icon) -> do
|
Just (Icon _ _ icon) -> do
|
||||||
|
@ -342,7 +375,7 @@ createScaledIcon (icons, h) = do
|
||||||
|
|
||||||
downscaled scalef icon
|
downscaled scalef icon
|
||||||
paint
|
paint
|
||||||
return $ Just scaledIcon
|
fmap Just $ createIcon h scaledIcon
|
||||||
|
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
|
|
||||||
|
|
Reference in a new issue