Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-07

gtk2 TCustomControl.Paint, InvalidateRect

11 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Armin Diehl

I have a problem with InvalidateRect with gtk2 on linux, Canvas.ClipRect always returns the full area and not the rect that needs to be updated. Under windows, everything works fine.
My problem is that within a terminal emulation program i have to draw a blinking cursor (250 ms) and blinking chars (500 ms). Under gtk2, invalidating the area with the cursor (InvalidateRect(Handle, @rect, FALSE)) does not work and my paint will always repaint the whole terminal area and this causes a high cpu utilization. Under windows it works fine and only the cursor or other invalid parts will be drawn within paint.
Any idea what i can do under linux gtk2 ?

Thx

Armin

Reply by email

Armin Diehl
to Armin Diehl

I have tried the same under gtk1, works fine, ClipRect returns only the rect to be updated and not the rect of the full window. Looks like a bug in gtk2 since it works fine under windows and gtk1.

Any idea what i can do ?

Armin Diehl wrote 22 lines
I have a problem with InvalidateRect with gtk2 on linux, Canvas.ClipRect always returns the full area and not the rect that needs to be updated. Under windows, everything works fine. My problem is that within a terminal emulation program i have to draw a blinking cursor (250 ms) and blinking chars (500 ms). Under gtk2, invalidating the area with the cursor (InvalidateRect(Handle, @rect, FALSE)) does not work and my paint will always repaint the whole terminal area and this causes a high cpu utilization. Under windows it works fine and only the cursor or other invalid parts will be drawn within paint. Any idea what i can do under linux gtk2 ? Thx Armin -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

zeljko
to Armin Diehl
Armin Diehl wrote 5 lines
I have tried the same under gtk1, works fine, ClipRect returns only the rect to be updated and not the rect of the full window. Looks like a bug in gtk2 since it works fine under windows and gtk1. Any idea what i can do ?

How to get an idea with such informations ? What's wrong a) TGtk2WidgetSet.InvalidateRect
b) Canvas.ClipRect
?

zeljko

Show quoted text 23 lines
On 07/01/2011 04:37 PM, Armin Diehl wrote: > I have a problem with InvalidateRect with gtk2 on linux, > Canvas.ClipRect always returns the full area and not the rect that > needs to be updated. Under windows, everything works fine. > My problem is that within a terminal emulation program i have to draw > a blinking cursor (250 ms) and blinking chars (500 ms). Under gtk2, > invalidating the area with the cursor (InvalidateRect(Handle, @rect, > FALSE)) does not work and my paint will always repaint the whole > terminal area and this causes a high cpu utilization. Under windows it > works fine and only the cursor or other invalid parts will be drawn > within paint. > Any idea what i can do under linux gtk2 ? > > Thx > > Armin -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110707/3d197949/attachment.html>

Reply by email

Ludo Brands
to zeljko: How to get an idea with such informations ? What's wrong a) TGtk2WidgetSet.InvalidateRect…
Show quoted text 9 lines
> > Any idea what i can do ? How to get an idea with such informations ? What's wrong a) TGtk2WidgetSet.InvalidateRect b) Canvas.ClipRect ?

A little bit more information would be indeed helpfull.

One thing I noticed on ubuntu gnome is that Canvas.ClipRect is always the full region even when the region was only partially masked by another window. On solaris 10 with Java Desktop System, also gtk2, Canvas.ClipRect returns the area masked by the other window. So, this could even be a window manager "thing".

Ludo

Reply by email

Armin Diehl
to Ludo Brands

Sorry for not providing enough information, i thought this would be a general problem with the gtk2 interface, this is not the case.

i have tried to track it down with a small test program that invalidates a square of 11 pixels and this worked. I compared the test program with the real one and the real one has a TScrollBar created in the TCustomControl. Without that scroll bar is works fine with gtk2, when i call InvalidateRect, paint will get called only with that rect (of cause, the first time will be the full control):
FormCreate
Paint ClipRect: Top:0 Right: 500 Bottom: 500 Left:0 Paint ClipRect: Top:0 Right: 10 Bottom: 10 Left:0
...

now i add the ScrollBar in TPaintTest.Create:

FormCreate
Paint ClipRect: Top:0 Right: 481 Bottom: 500 Left:0 Paint ClipRect: Top:0 Right: 481 Bottom: 500 Left:0 Paint ClipRect: Top:0 Right: 481 Bottom: 500 Left:0 ...

now we always get the full area to be updated with gtk2. With gtk1 and windows i also get 0,10,10,0 as expected.

Test program (complete project @ http://www.ardiehl.de/temp/painttest.zip)

unit Unit1;
{$mode objfpc}{$H+}
interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLintf,

   StdCtrls, ExtCtrls, ComCtrls;
type
   TPaintTest = class (TCustomControl)
   protected
     procedure paint; override;
   private
     t : TTimer;
     ScrollBar : TScrollBar;
   public
     constructor Create(AOwner: TComponent); override;
     procedure invalidateTest(Sender:TObject);
   end;
   { TForm1 }
   TForm1 = class(TForm)
     Panel1: TPanel;
     StatusBar1: TStatusBar;
     procedure FormCreate(Sender: TObject);
   private
     { private declarations }
   public
     { public declarations }
   end;
var
   Form1: TForm1;
implementation

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var t : TPaintTest;
begin
   writeln('FormCreate');
   width := 600; height := 600;
   t := TPaintTest.Create(self);
   t.Parent := panel1;
end;
constructor TPaintTest.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   // with this scroll bar, Canvas.ClipRect always returns full area
   ScrollBar:= TScrollBar.Create(Self);
   ScrollBar.Kind := sbVertical;  ScrollBar.Align := alRight;
   ScrollBar.LargeChange := 100;  ScrollBar.Max := 1000;
   ScrollBar.Parent := Self;
   self.width := 500; self.height := 500;
   t := TTimer.create(self);  t.interval := 1000;
   t.onTimer := @invalidateTest;  t.enabled := true;
end;
procedure TPaintTest.paint;
var r : TRect;
begin
   r := Canvas.ClipRect;
   writeln ('Paint ClipRect: Top:',r.top,' Right: ',r.right,' Bottom:
',R.Bottom,' Left:',r.Left);
end;
procedure TPaintTest.invalidateTest(Sender:TObject);
var r : TRect;
begin
   r.top := 0; r.Left:=0; r.Right:=10; r.Bottom:=10;
   if assigned(Parent) then
     InvalidateRect(Handle, @r, FALSE);
end;
{$R *.lfm}
end.
Show quoted text 24 lines
>> Any idea what i can do ? > > > How to get an idea with such informations ? What's wrong > a) TGtk2WidgetSet.InvalidateRect > b) Canvas.ClipRect > ? A little bit more information would be indeed helpfull. One thing I noticed on ubuntu gnome is that Canvas.ClipRect is always the full region even when the region was only partially masked by another window. On solaris 10 with Java Desktop System, also gtk2, Canvas.ClipRect returns the area masked by the other window. So, this could even be a window manager "thing". Ludo -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
---------------- Gr?sse Armin Diehl

Reply by email

Ludo Brands
to Armin Diehl

The scrollbar invalidates indeed the whole region, even if it is located outside the customcontrol (and thus invisible). If nobody else has another idea I would suggest to create a bug report.

In the mean time, a workaround is to parent the scrollbox to the parent of TPaintTest. The constructor becomes then

constructor TPaintTest.Create(AOwner: Tcomponent; ParentControl:
TWinControl);
begin
   inherited Create(AOwner);
   self.Parent:=ParentControl;
   self.width := 500; self.height := 500;
   ScrollBar:= TScrollBar.Create(Self);
   ScrollBar.Kind := sbVertical;
   ScrollBar.left:=self.width+self.left;
   ScrollBar.height :=self.height+self.top;
   ScrollBar.LargeChange := 100;  ScrollBar.Max := 1000;
   ScrollBar.Parent := ParentControl;
   t := TTimer.create(self);  t.interval := 1000;
   t.onTimer := @invalidateTest;  t.enabled := true;
end;
Create it as t:=TPaintTest.Create(self,panel1);

Downside is that you have to create the code to move/resize the scrollbar when TPaintTest moves or resizes.

Ludo

Reply by email

Armin Diehl
to Ludo Brands

Hi Ludo,

have tried setting the parent of the scrollbar to panal1 and this works fine.

Many thanks for the solution.

Show quoted text 38 lines
The scrollbar invalidates indeed the whole region, even if it is located outside the customcontrol (and thus invisible). If nobody else has another idea I would suggest to create a bug report. In the mean time, a workaround is to parent the scrollbox to the parent of TPaintTest. The constructor becomes then constructor TPaintTest.Create(AOwner: Tcomponent; ParentControl: TWinControl); begin inherited Create(AOwner); self.Parent:=ParentControl; self.width := 500; self.height := 500; ScrollBar:= TScrollBar.Create(Self); ScrollBar.Kind := sbVertical; ScrollBar.left:=self.width+self.left; ScrollBar.height :=self.height+self.top; ScrollBar.LargeChange := 100; ScrollBar.Max := 1000; ScrollBar.Parent := ParentControl; t := TTimer.create(self); t.interval := 1000; t.onTimer := @invalidateTest; t.enabled := true; end; Create it as t:=TPaintTest.Create(self,panel1); Downside is that you have to create the code to move/resize the scrollbar when TPaintTest moves or resizes. Ludo -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
---------------- Gr?sse Armin Diehl

Reply by email

zeljko
to Armin Diehl
Armin Diehl wrote 13 lines
Hi Ludo, have tried setting the parent of the scrollbar to panal1 and this works fine. Many thanks for the solution. > The scrollbar invalidates indeed the whole region, even if it is located > outside the customcontrol (and thus invisible). If nobody else has > another idea I would suggest to create a bug report. > > In the mean time, a workaround is to parent the scrollbox to the parent > of TPaintTest. The constructor becomes then

OK, let's stop a bit here.
It invalidates some area (parent in this case), and part of that area isn't exposed (visible) then gtk2 will not paint that part. if it's opposite then it's an ugly gtk2 bug.
Let me see one more time what's exact problem:
Any visible scrollbar in TCustomControl sends update for whole parent (eg. form) ? IMO, it's fixable under gtk2lcl by intercepting expose event in scrollbar and reduce area which is marked as exposed, but then another question raises , what if I move scrollbar by mouse (and I have already cutted exposed area to the size of scrollbar) ? My TCustomControl will get an update since it's viewport is moved ?

zeljko

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110709/0e2e7f8e/attachment.html>

Reply by email

Ludo Brands
to zeljko
Show quoted text 11 lines
> The scrollbar invalidates indeed the whole region, even if it is located > outside the customcontrol (and thus invisible). If nobody else has > another idea I would suggest to create a bug report. > > In the mean time, a workaround is to parent the scrollbox to the parent > of TPaintTest. The constructor becomes then

OK, let's stop a bit here.

It invalidates some area (parent in this case), and part of that area isn't exposed (visible) then gtk2 will not paint that part. if it's opposite then it's an ugly gtk2 bug.

No, "it" in " if it is located outside the customcontrol "is the scrollbar. In Armin's testprogram change ScrollBar.Align := alRight; to ScrollBar.Left:=510, ScrollBar.Height :=500 , so that scrollbar doesn't cover any area of TPaintTest and isn't in this extreme case, the whole TPaintTest area is invalidated.

Let me see one more time what's exact problem:

Any visible scrollbar in TCustomControl sends update for whole parent (eg. form) ? IMO, it's fixable under gtk2lcl by intercepting expose event in scrollbar and reduce area which is marked as exposed, but then another question raises , what if I move scrollbar by mouse (and I have already cutted exposed area to the size of scrollbar) ? My TCustomControl will get an update since it's viewport is moved ?

Why does a scrollbar invalidate the complete parent area if nothing has changed for the scrollbar (exposition, location, scroll, mouseclick,...)?

Having the area under the scrollbar marked as exposed isn't an issue, I think. The parent is aware of the scrollbar position and wouldn't draw underneath anyways. So, no reason to reduce the exposed area.

Aren't scrollbar mouse movements signaled by special gtk events? That is where I would expect the whole parent area to be invalidated. How are windows and gtk solving this?

Ludo

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110709/c8135e74/attachment.html>

Reply by email

Ludo Brands
to Ludo Brands
Aren't scrollbar mouse movements signaled by special gtk events? That is

where

I would expect the whole parent area to be invalidated. How are windows

and gtk

solving this?

Thinking of it, isn't the onscroll event meant to handle how the scrolled area is repainted? I'm not talking about repainting the scrollbar itself but the area it is supposed to control. If I want fe. to update only the record number or page number while scrolling and repaint the full page/table when scrolling stops, there is no reason to invalidate the whole area. Actually, I'm still having a problem finding an example where Tscrollbar has to invalidate the whole or part of the parent area.

Ludo

Reply by email