Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid infinite resize loop in multiline label #233

Merged
merged 3 commits into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/Monomer/Main/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import Control.Monad.Extra
import Control.Monad.State
import Control.Monad.STM (atomically)
import Data.Default
import Data.Maybe
import Data.Either (isLeft)
import Data.Maybe (fromMaybe)
import Data.Map (Map)
import Data.List (foldl')
import Data.Text (Text)
Expand Down Expand Up @@ -348,14 +349,14 @@ mainLoop window fontManager config loopArgs = do

-- Rendering
renderCurrentReq <- checkRenderCurrent startTs _mlLatestRenderTs
renderMethod <- use L.renderMethod

let actionEvt = any isActionEvent eventsPayload
let windowRenderEvt = windowResized || any isWindowRenderEvent eventsPayload
let renderResize = windowResized && (isLinux wenv || isLeft renderMethod)
let windowRenderEvt = renderResize || any isWindowRenderEvent eventsPayload
let renderNeeded = windowRenderEvt || actionEvt || renderCurrentReq

when (prevRenderNeeded || renderNeeded) $ do
renderMethod <- use L.renderMethod

when (prevRenderNeeded || renderNeeded) $
case renderMethod of
Right renderChan -> do
liftIO . atomically $ writeTChan renderChan (MsgRender newWenv newRoot)
Expand Down
31 changes: 18 additions & 13 deletions src/Monomer/Widgets/Singles/Label.hs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ data LabelState = LabelState {
_lstStyle :: StyleState,
_lstTextRect :: Rect,
_lstTextLines :: Seq TextLine,
_lstPrevResize :: (Millisecond, Bool)
_lstResizeStep :: (Millisecond, Bool)
} deriving (Eq, Show, Generic)

-- | Creates a label using the provided 'Text'.
Expand Down Expand Up @@ -201,7 +201,7 @@ makeLabel config state = widget where
| otherwise = SingleLine
maxLines = _lscTextMaxLines config
labelCurrentStyle = fromMaybe currentStyle (_lscCurrentStyle config)
LabelState caption textStyle textRect textLines prevResize = state
LabelState caption textStyle textRect textLines resizeStep = state

getBaseStyle wenv node
| ignoreTheme = Nothing
Expand All @@ -216,11 +216,12 @@ makeLabel config state = widget where
& L.widget .~ makeLabel config newState

merge wenv newNode oldNode oldState = result where
LabelState prevCaption prevStyle prevRect prevLines prevResize = oldState
(tsResized, alreadyResized) = prevResize

widgetId = newNode ^. L.info . L.widgetId
style = labelCurrentStyle wenv newNode
prevStyle = _lstStyle oldState

captionChanged = _lstCaption oldState /= caption
captionChanged = prevCaption /= caption
styleChanged = prevStyle ^. L.text /= style ^. L.text
|| prevStyle ^. L.padding /= style ^. L.padding
|| prevStyle ^. L.border /= style ^. L.border
Expand All @@ -231,11 +232,13 @@ makeLabel config state = widget where
-- This is used in resize to know if glyphs have to be recalculated
newRect
| changeReq = def
| otherwise = _lstTextRect oldState
newState = oldState {
| otherwise = prevRect
newState = LabelState {
_lstCaption = caption,
_lstStyle = style,
_lstTextRect = newRect
_lstTextRect = newRect,
_lstTextLines = prevLines,
_lstResizeStep = (tsResized, alreadyResized && not captionChanged)
}

reqs = [ ResizeWidgets widgetId | changeReq ]
Expand All @@ -246,7 +249,7 @@ makeLabel config state = widget where
getSizeReq wenv node = (sizeW, sizeH) where
ts = wenv ^. L.timestamp
caption = _lstCaption state
prevResize = _lstPrevResize state
prevResize = _lstResizeStep state
style = labelCurrentStyle wenv node

cw = getContentArea node style ^. L.w
Expand Down Expand Up @@ -286,18 +289,20 @@ makeLabel config state = widget where
= fitTextToSize fontMgr style overflow mode trim maxLines size caption
newTextLines = alignTextLines style alignRect fittedLines

(prevTs, prevStep) = prevResize
needsSndResize = mode == MultiLine && (prevTs /= ts || not prevStep)
rectEq = textRect == crect
(tsResized, alreadyResized) = resizeStep
resizeAgain = mode == MultiLine && (tsResized /= ts || not alreadyResized)
isResized = (alreadyResized && rectEq) || (resizeAgain && tsResized == ts)

newState = state {
_lstStyle = style,
_lstTextRect = crect,
_lstTextLines = newTextLines,
_lstPrevResize = (ts, needsSndResize && prevTs == ts)
_lstResizeStep = (ts, isResized)
}
newNode = node
& L.widget .~ makeLabel config newState
result = resultReqs newNode [ResizeWidgets widgetId | needsSndResize]
result = resultReqs newNode [ResizeWidgets widgetId | resizeAgain]

render wenv node renderer = do
drawInScissor renderer True scissorVp $
Expand Down