Hi,
I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. So, play with me… you need to create this: SystemWindow subclass: #XSystemWindow instanceVariableNames: 'iteration' classVariableNames: '' package: ‘XXX' XSystemWindow>>initialize super initialize. iteration := 0. XSystemWindow>>drawOn: aCanvas “Do not use transcript because it does even more crazy stuff" Stdio stdout << (iteration := iteration + 1) asString; cr; lf. super drawOn: aCanvas Then execute this in a playground: XSystemWindow new addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; openInWorld. and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. IMO, this is not acceptable. What do you think? Esteban |
Hi Esteban,
To see the damage live: SystemSettings->Tools->Debugging->Flash damaged morphic region. Redrawing: Only morphs whose area is within the visible draw region of the canvas (the damaged area) needs to be redrawn, so if a morph fullbounds is not intersecting with this area it will not be drawn, and its submorphs will not check deeper in this submorph hierarchy. The exclusion is done in #fullDrawOn: by "(aCanvas isVisible: self fullbounds) ifFalse: [ ^self ]. So if the cursor reports a damage rectangle only morphs intersecting with that area needs to be redrawn (there is also some layering mechanism IIRC so that it should only re-draw the visible layers in that area, and not morphs which are covered by their submorphs). DamageRecorder: The damage recorder do not know about any layering of morphs when it records damage. This means that if there is two overlapping windows in the World, and the window in the back triggers an invalid area which intersects with the window above, it will have to be redraw for that area as well even though it is not necessary. There is also the issue where multiple small areas close to each other need multiple passes to be completed. If the damage recorder has damage in (10@10 corner: 20@20) and (10@30 corner: 20@40) a morph with bounds (0@0 corner: 50@50) will be redrawn twice during that cycle. Rubric: There is some issues with how rubric handle changes, which causes blinking the cursor to do way to much work that it actually have to do, I think it also invalidates the whole selection and needs to redraw that as well. Best regards, Henrik -----Original Message----- From: Pharo-dev [mailto:[hidden email]] On Behalf Of Esteban Lorenzano Sent: Sunday, May 22, 2016 8:36 PM To: Pharo Development List <[hidden email]> Subject: [Pharo-dev] weird tales about cursors and rectangle invalidations Hi, I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. So, play with me… you need to create this: SystemWindow subclass: #XSystemWindow instanceVariableNames: 'iteration' classVariableNames: '' package: ‘XXX' XSystemWindow>>initialize super initialize. iteration := 0. XSystemWindow>>drawOn: aCanvas “Do not use transcript because it does even more crazy stuff" Stdio stdout << (iteration := iteration + 1) asString; cr; lf. super drawOn: aCanvas Then execute this in a playground: XSystemWindow new addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; openInWorld. and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. IMO, this is not acceptable. What do you think? Esteban |
Le 22/5/16 à 21:28, Henrik Nergaard a écrit : > Hi Esteban, > > To see the damage live: > SystemSettings->Tools->Debugging->Flash damaged morphic region. > > Redrawing: > Only morphs whose area is within the visible draw region of the canvas (the damaged area) needs to be redrawn, so if a morph fullbounds is not intersecting with this area it will not be drawn, and its submorphs will not check deeper in this submorph hierarchy. > The exclusion is done in #fullDrawOn: by "(aCanvas isVisible: self fullbounds) ifFalse: [ ^self ]. > So if the cursor reports a damage rectangle only morphs intersecting with that area needs to be redrawn (there is also some layering mechanism IIRC so that it should only re-draw the visible layers in that area, and not morphs which are covered by their submorphs). > > DamageRecorder: > The damage recorder do not know about any layering of morphs when it records damage. This means that if there is two overlapping windows in the World, and the window in the back triggers an invalid area which intersects with the window above, it will have to be redraw for that area as well even though it is not necessary. > > There is also the issue where multiple small areas close to each other need multiple passes to be completed. If the damage recorder has damage in (10@10 corner: 20@20) and (10@30 corner: 20@40) a morph with bounds (0@0 corner: 50@50) will be redrawn twice during that cycle. I thought that they were merged into a larger one. > > Rubric: > There is some issues with how rubric handle changes, which causes blinking the cursor to do way to much work that it actually have to do, I think it also invalidates the whole selection and needs to redraw that as well. > > > > Best regards, > Henrik > > > -----Original Message----- > From: Pharo-dev [mailto:[hidden email]] On Behalf Of Esteban Lorenzano > Sent: Sunday, May 22, 2016 8:36 PM > To: Pharo Development List <[hidden email]> > Subject: [Pharo-dev] weird tales about cursors and rectangle invalidations > > Hi, > > I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. > So, play with me… you need to create this: > > SystemWindow subclass: #XSystemWindow > instanceVariableNames: 'iteration' > classVariableNames: '' > package: ‘XXX' > > XSystemWindow>>initialize > super initialize. > iteration := 0. > > XSystemWindow>>drawOn: aCanvas > “Do not use transcript because it does even more crazy stuff" > Stdio stdout << (iteration := iteration + 1) asString; cr; lf. > super drawOn: aCanvas > > > Then execute this in a playground: > > XSystemWindow new > addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; > openInWorld. > > and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). > > This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. > I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. > With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). > I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. > When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. > IMO, this is not acceptable. > > What do you think? > > Esteban |
In reply to this post by Henrik Nergaard
Hi,
flash damaged areas is not showing me anything :( but still, you seems to be in agreement with me and what is happening *should not* happen, isn’t? (drawing is being called for the full window) btw, this is not just a rubric problem, it happens if I put a PluggableTextMorph as well. cheers! Esteban > On 22 May 2016, at 21:28, Henrik Nergaard <[hidden email]> wrote: > > Hi Esteban, > > To see the damage live: > SystemSettings->Tools->Debugging->Flash damaged morphic region. > > Redrawing: > Only morphs whose area is within the visible draw region of the canvas (the damaged area) needs to be redrawn, so if a morph fullbounds is not intersecting with this area it will not be drawn, and its submorphs will not check deeper in this submorph hierarchy. > The exclusion is done in #fullDrawOn: by "(aCanvas isVisible: self fullbounds) ifFalse: [ ^self ]. > So if the cursor reports a damage rectangle only morphs intersecting with that area needs to be redrawn (there is also some layering mechanism IIRC so that it should only re-draw the visible layers in that area, and not morphs which are covered by their submorphs). > > DamageRecorder: > The damage recorder do not know about any layering of morphs when it records damage. This means that if there is two overlapping windows in the World, and the window in the back triggers an invalid area which intersects with the window above, it will have to be redraw for that area as well even though it is not necessary. > > There is also the issue where multiple small areas close to each other need multiple passes to be completed. If the damage recorder has damage in (10@10 corner: 20@20) and (10@30 corner: 20@40) a morph with bounds (0@0 corner: 50@50) will be redrawn twice during that cycle. > > Rubric: > There is some issues with how rubric handle changes, which causes blinking the cursor to do way to much work that it actually have to do, I think it also invalidates the whole selection and needs to redraw that as well. > > > > Best regards, > Henrik > > > -----Original Message----- > From: Pharo-dev [mailto:[hidden email]] On Behalf Of Esteban Lorenzano > Sent: Sunday, May 22, 2016 8:36 PM > To: Pharo Development List <[hidden email]> > Subject: [Pharo-dev] weird tales about cursors and rectangle invalidations > > Hi, > > I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. > So, play with me… you need to create this: > > SystemWindow subclass: #XSystemWindow > instanceVariableNames: 'iteration' > classVariableNames: '' > package: ‘XXX' > > XSystemWindow>>initialize > super initialize. > iteration := 0. > > XSystemWindow>>drawOn: aCanvas > “Do not use transcript because it does even more crazy stuff" > Stdio stdout << (iteration := iteration + 1) asString; cr; lf. > super drawOn: aCanvas > > > Then execute this in a playground: > > XSystemWindow new > addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; > openInWorld. > > and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). > > This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. > I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. > With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). > I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. > When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. > IMO, this is not acceptable. > > What do you think? > > Esteban |
Le 22/05/2016 21:49, Esteban Lorenzano a écrit :
> Hi, > > flash damaged areas is not showing me anything :( > but still, you seems to be in agreement with me and what is happening *should not* happen, isn’t? (drawing is being called for the full window) > > btw, this is not just a rubric problem, it happens if I put a PluggableTextMorph as well. > Hi, I tried to make a stdout on the drawOn: of FastTable and let the text area blink but there was no new lines on the stdout. So it seems that the lists from Nautilus are not updated when the cursor blink. > cheers! > Esteban > > > -- Cyril Ferlicot http://www.synectique.eu 165 Avenue Bretagne Lille 59000 France signature.asc (836 bytes) Download Attachment |
In reply to this post by stepharo
I thought that they were merged into a larger one.
Only if there is significant overlap between a new damage and current recorded damages, or if the amount of invalid rectangles size is >= 50. (see DamageRecorder >>#recordInvalidRect:) -----Original Message----- From: Pharo-dev [mailto:[hidden email]] On Behalf Of stepharo Sent: Sunday, May 22, 2016 9:49 PM To: Pharo Development List <[hidden email]> Subject: Re: [Pharo-dev] weird tales about cursors and rectangle invalidations Le 22/5/16 à 21:28, Henrik Nergaard a écrit : > Hi Esteban, > > To see the damage live: > SystemSettings->Tools->Debugging->Flash damaged morphic region. > > Redrawing: > Only morphs whose area is within the visible draw region of the canvas (the damaged area) needs to be redrawn, so if a morph fullbounds is not intersecting with this area it will not be drawn, and its submorphs will not check deeper in this submorph hierarchy. > The exclusion is done in #fullDrawOn: by "(aCanvas isVisible: self fullbounds) ifFalse: [ ^self ]. > So if the cursor reports a damage rectangle only morphs intersecting with that area needs to be redrawn (there is also some layering mechanism IIRC so that it should only re-draw the visible layers in that area, and not morphs which are covered by their submorphs). > > DamageRecorder: > The damage recorder do not know about any layering of morphs when it records damage. This means that if there is two overlapping windows in the World, and the window in the back triggers an invalid area which intersects with the window above, it will have to be redraw for that area as well even though it is not necessary. > > There is also the issue where multiple small areas close to each other need multiple passes to be completed. If the damage recorder has damage in (10@10 corner: 20@20) and (10@30 corner: 20@40) a morph with bounds (0@0 corner: 50@50) will be redrawn twice during that cycle. I thought that they were merged into a larger one. > > Rubric: > There is some issues with how rubric handle changes, which causes blinking the cursor to do way to much work that it actually have to do, I think it also invalidates the whole selection and needs to redraw that as well. > > > > Best regards, > Henrik > > > -----Original Message----- > From: Pharo-dev [mailto:[hidden email]] On Behalf Of Esteban Lorenzano > Sent: Sunday, May 22, 2016 8:36 PM > To: Pharo Development List <[hidden email]> > Subject: [Pharo-dev] weird tales about cursors and rectangle invalidations > > Hi, > > I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. > So, play with me… you need to create this: > > SystemWindow subclass: #XSystemWindow > instanceVariableNames: 'iteration' > classVariableNames: '' > package: ‘XXX' > > XSystemWindow>>initialize > super initialize. > iteration := 0. > > XSystemWindow>>drawOn: aCanvas > “Do not use transcript because it does even more crazy stuff" > Stdio stdout << (iteration := iteration + 1) asString; cr; lf. > super drawOn: aCanvas > > > Then execute this in a playground: > > XSystemWindow new > addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; > openInWorld. > > and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). > > This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. > I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. > With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). > I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. > When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. > IMO, this is not acceptable. > > What do you think? > > Esteban |
In reply to this post by EstebanLM
If the cursor uses a solid fill (color) only it should be redrawn, and when it blinks "off" only the RubScrolledTextMorph (if it has a solid fill), and any of it submorphs which intersects with the damage area should be redrawn.
(drawing is being called for the full window) The only area modified is that within the clipping rect of the canvas (damaged area). For non-complex drawing (system window only draws a rectangle with border) filling over a small area should not be noticeable performance wise (as long as the submorph tree is not too deep), but should be fixed. I think the best place to start looking at and improving is in WorldState >>#drawWorld:submorphs:invalidAreasOn: Best regards, Henrik -----Original Message----- From: Pharo-dev [mailto:[hidden email]] On Behalf Of Esteban Lorenzano Sent: Sunday, May 22, 2016 9:50 PM To: Pharo Development List <[hidden email]> Subject: Re: [Pharo-dev] weird tales about cursors and rectangle invalidations Hi, flash damaged areas is not showing me anything :( but still, you seems to be in agreement with me and what is happening *should not* happen, isn’t? (drawing is being called for the full window) btw, this is not just a rubric problem, it happens if I put a PluggableTextMorph as well. cheers! Esteban > On 22 May 2016, at 21:28, Henrik Nergaard <[hidden email]> wrote: > > Hi Esteban, > > To see the damage live: > SystemSettings->Tools->Debugging->Flash damaged morphic region. > > Redrawing: > Only morphs whose area is within the visible draw region of the canvas (the damaged area) needs to be redrawn, so if a morph fullbounds is not intersecting with this area it will not be drawn, and its submorphs will not check deeper in this submorph hierarchy. > The exclusion is done in #fullDrawOn: by "(aCanvas isVisible: self fullbounds) ifFalse: [ ^self ]. > So if the cursor reports a damage rectangle only morphs intersecting with that area needs to be redrawn (there is also some layering mechanism IIRC so that it should only re-draw the visible layers in that area, and not morphs which are covered by their submorphs). > > DamageRecorder: > The damage recorder do not know about any layering of morphs when it records damage. This means that if there is two overlapping windows in the World, and the window in the back triggers an invalid area which intersects with the window above, it will have to be redraw for that area as well even though it is not necessary. > > There is also the issue where multiple small areas close to each other need multiple passes to be completed. If the damage recorder has damage in (10@10 corner: 20@20) and (10@30 corner: 20@40) a morph with bounds (0@0 corner: 50@50) will be redrawn twice during that cycle. > > Rubric: > There is some issues with how rubric handle changes, which causes blinking the cursor to do way to much work that it actually have to do, I think it also invalidates the whole selection and needs to redraw that as well. > > > > Best regards, > Henrik > > > -----Original Message----- > From: Pharo-dev [mailto:[hidden email]] On Behalf > Of Esteban Lorenzano > Sent: Sunday, May 22, 2016 8:36 PM > To: Pharo Development List <[hidden email]> > Subject: [Pharo-dev] weird tales about cursors and rectangle > invalidations > > Hi, > > I’ve been playing a bit today with something that is puzzling me and I need some more eyes in what I’m doing, because it might be that I’m understanding everything wrong… but if not, then, huston, we have a bug. > So, play with me… you need to create this: > > SystemWindow subclass: #XSystemWindow > instanceVariableNames: 'iteration' > classVariableNames: '' > package: ‘XXX' > > XSystemWindow>>initialize > super initialize. > iteration := 0. > > XSystemWindow>>drawOn: aCanvas > “Do not use transcript because it does even more crazy stuff" > Stdio stdout << (iteration := iteration + 1) asString; cr; lf. > super drawOn: aCanvas > > > Then execute this in a playground: > > XSystemWindow new > addMorph: (RubScrolledTextModel new newScrolledText) fullFrame: LayoutFrame identity; > openInWorld. > > and then you can watch in your stdout how full window redraws with cursor blinking (it stops when window loses focus). > > This happens because cursor is displayed with lapsus of 700ms and is just a draw of a line with a color who is set to it’s opposite each time. Then it does "color: shownColor” and #color: sends #changed who finalise in #invalidRect. > I always thought that this invalidation mechanism works by recording “damaged areas”, then collecting morphs with that area and triggering the redraw of that morph. > With this in mind, cursor should trigger an invalidation of it’s own area (a small portion of the screen, as you can see). > I could understand that a cursor triggers the text area redraw (but that would be a “design flaw”, IMO)… now, what I cannot understand is why blink a cursor triggers the redraw of a FULL WINDOW. > When in Nautilus, that means each cursor blink triggers the redraw of one tree, four lists, some buttons and finally, the text area. > IMO, this is not acceptable. > > What do you think? > > Esteban |
Free forum by Nabble | Edit this page |