Содержание сайта
Главная Новичку Цитаты Реализации Статьи Документация
Компании Программы Ссылки Обсуждение Обсуждение 2 Гостевая

Flickers-Free

Alex Baran
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 



Есть комментарии? Пишите.