Flickers-Free
email: 'bmfycApqujnb/dpn/vb' collect: [:e | Character value: e asInteger - 1]
Andrei N.Sobchuck
email: 'boesfjAnbsu/dl/vb' collect: [:e | Character value: e asInteger - 1]
Flickers show up when widgets draw themselves directly on screen. Drawing begins with erasing. Erasing is actually drawing of rectangle with some background. Rectangle background can be different from widget background. Quick successions of backgrounds forms flickers.
To avoid flickers one can do all paints on invisible medium and show on screen already painted medium. This technique called "double buffering". VisualWorks has double buffering but it's not work properly. There are situations when double buffering is turned on but painting is happened directly on screen.
You can find fix to current double buffering implementation here
or at Cincom public repository (package DoubleBufferingFix).
Load parcel. Use "Settings->System->Repair policy" page to turn double buffering on. Your change will take effect only for new windows.
So what's wrong with double buffering?
When widget want to repaint itself it send some sort of invalidate message. At invalidate message widget say if he wants immediate repaint (invalidate message with repairNowNoFill: true), or can wait until window initiate repaint of all damaged areas (repairNowNoFill: false). Current double buffering implementation works only with deferred repaints (repairNowNoFill: false). In case of immediate repaint (repairNowNoFill: true) you can see flickers. This flickers is result of painting directly on screen.
Consider Aragon DataSet. When Aragon DataSet want to repaint some row it ask for immediate repaint (repairNowNoFill: true). Because of this you can see row flickers even with double buffering turned on.
For those interested in source code:
ApplicationWindow >> invalidateRectangle: aRectangle repairNow: aBooleanOrSymbol forComponent: aVisualComponent "Damage is coming up from below. Resolve with outstanding damage and redisplay if aBoolean is true, otherwise just accumulate. In adition to true and false for aBooleanOrSymbol the reciever handles #repairNowNoFill which can keep flashing out of the picture when the visual component needing repair is opaque." | box gc| self isOpen ifFalse: [^self]. "Check for invalidation suppression. See comment in extentEvent: for details." self sensor invalidationSuppressed ifTrue: [^self]. self sensor pseudoEvent. box := self bounds. (aRectangle intersects: box ) ifTrue: [ | dbox | dbox := aRectangle intersect: box. (damageRepairIsLazy and: [aBooleanOrSymbol == false]) ifTrue: [^self sensor addDamage: dbox]. self sensor hasDamage ifTrue: [self displayPendingInvalidation]. >>>Code below use direct draw on graphicsContext instead of >>>redrawing through damageRepairPolicy gc := self graphicsContext. gc clippingRectangle: dbox. aBooleanOrSymbol == #repairNowNoFill ifFalse: [gc paint: self backgroundColor. gc displayRectangle: dbox]. gc paint: self foregroundColor. self component displayOn: gc. ^self flush]
If you look at fixed code you can see that repaint performed by damageRepairPolicy
self damageRepairPolicy displayArea: dbox in: self repairNowNoFill: aBooleanOrSymbol