This afternoon I tagged Lazarus 0.9.24. The coming days we will build all the windows installers, rpms, debs and dmgs for the suported OS-es and CPU's.
As part of the release testing, I created an ubuntu lazarus-testing repository at http://www.hu.freepascal.org/lazarus/dists/lazarus-testing/. Currently it still contains Lazarus 0.9.22 and FPC 2.0.4, but as soon as the Lazarus 0.9.24 and debs are ready they will be put there, until the Lazarus 0.9.24 release can be announced. After the announcement, they will be available in the lazarus-stable repository too. For more information about how to get debs from the Lazarus testing repostitory, see the wiki.
Please, let us know if you have problems using the testing repository and during the upgrade from 0.9.22 to 0.9.24.
Monday, November 5, 2007
Monday, October 29, 2007
New poll on the lazarus site about Windows versions
Lately I have been trying to fix recompiling the Lazarus (needed to install components) from the IDE. On windows 2000 and higher, using .rc files is working OK if windres is not on the path, but on windows 98 there are still some problems.
Marc has done a large graphic rewrite in Lazarus 0.9.23 and he also noticed that there are noticeable difference between Windows 98 and Windows XP.
I wondered if there still many people using Windows 98 and Windows ME for Lazarus development or as target for LCL application. Therefore I created a new poll on the Lazarus website, asking people about the oldest Windows version is, that they use for Lazarus development.
Currently when we program on the win32 interface we try to use only functions available in windows 95, or provide a fall back if we want to use a function not available on windows 95. Some features like graphics, Unicode support, the shell provided by cmd32.exe and the availability of console (used for the debugger) are better and easier in Windows 2000 and later. So it would be nice if we could restrict ourselves to these newer Windows versions.
Personally, I don't think we can drop support for windows 98 yet, but I doubt anybody is using Windows 95 to program with Lazarus. Let us know where you stand and cast your votes in the poll. This poll is about the OS you use for Lazarus, a future poll may be held about the Windows versions you want your developed applications to run on.
Note: people who don't use Lazarus on Windows, don't need to vote.
Marc has done a large graphic rewrite in Lazarus 0.9.23 and he also noticed that there are noticeable difference between Windows 98 and Windows XP.
I wondered if there still many people using Windows 98 and Windows ME for Lazarus development or as target for LCL application. Therefore I created a new poll on the Lazarus website, asking people about the oldest Windows version is, that they use for Lazarus development.
Currently when we program on the win32 interface we try to use only functions available in windows 95, or provide a fall back if we want to use a function not available on windows 95. Some features like graphics, Unicode support, the shell provided by cmd32.exe and the availability of console (used for the debugger) are better and easier in Windows 2000 and later. So it would be nice if we could restrict ourselves to these newer Windows versions.
Personally, I don't think we can drop support for windows 98 yet, but I doubt anybody is using Windows 95 to program with Lazarus. Let us know where you stand and cast your votes in the poll. This poll is about the OS you use for Lazarus, a future poll may be held about the Windows versions you want your developed applications to run on.
Note: people who don't use Lazarus on Windows, don't need to vote.
Sunday, October 28, 2007
How TPageControl tab switching in designer has been solved
I think most users who used TPageControl in windows ide suffered from the inability to stitch its Tabs by clicking them in the designer. Indeed, the gtk ide had no such bug while the windows one had. I got annoyed by the fact too and as result I started my research of the problem.
My first assumption was that somewhere a csDesigning (you know that usual "if csDesigning in BlaBla.ComponentState" ;) ) condition was written and I spent much time (searching code) to prove myself that I am wrong.
Ok, if I am wrong (I thought) then it is by design or by the designer :) So I started my research of how the win32 designer works. Usually my research consists of Alt+F7 in Far manager for some search key (in this case for 'designer') and if Alt+F7 doesn't help, then in debugging the code. I suppose on that occasion I had been satisfied by search in files. First of all I found 'TWin32WidgetSet.GetDesignerDC' method and later I've checked that this method is indeed what I searched for. Look at TDesigner.DrawDesignerItems and you'll find that yourself.
So, I've known the enemy by sight :) If you notice GetDesignerDC creates a visually transparent window over WindowHandle and returns the Device Context for that overlay window. The Device Context is not a interesting thing for us, but the overlay window is. That overlay window is placed on top of a form (and all child controls). And the most interesting thing in that overlay window is the window procedure OverlayWindowProc.
Inside OverlayWindowProc we can find that overlay window easts all messages except WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST and that bunch of messages it redirects to the parent (look at Windows.GetParent(Window)). If you look at TDesigner.DrawDesignerItems then you'll know that the Parent of OverlayWindow is the Form. So nothing wondering now that the PageControl Tabs cannot be switched in designer - PageControl gets no clicks (they are caught by our overlay window).
Hmm ... I thought about a solution. The first thing that flashed through my mind was sending those mouse clicks to the underlying control. But it is so easy to forget about some messages or make other errors if you want to emulate windows behaviour. So I rejected that way as defective. Another way is to make some parts of our overlay window transparent for mouse. Windows has a special message WM_NCHITTEST to check what a given coordinate means. And a window can return HTTRANSPARENT as result of a message to indicate that message must be sent to the underlying window (so this point is transparent for the window).
As result the whole solution consisted of handling WM_NCHITTEST in OverlayWindowProc and return HTTRANSPARENT if underlying control wanted mouse messages for that point at design time. I've added a new method GetDesignInteractive to TWSWinControl.
class function GetDesignInteractive(const AWinControl: TWinControl; AClientPos: TPoint): Boolean;
Now I had a method to check, but of course I needed the implementation of that method for TPageControl (which checked that mouse is over control Tabs). So I've added TWin32WSCustomNotebook.GetDesignInteractive, rebuilt the win32 ide and hurray - I switched PageControl tabs in designer w/o problems.
You can look at implementation in revisions: 12245, 12620 (method has been renamed).
My first assumption was that somewhere a csDesigning (you know that usual "if csDesigning in BlaBla.ComponentState" ;) ) condition was written and I spent much time (searching code) to prove myself that I am wrong.
Ok, if I am wrong (I thought) then it is by design or by the designer :) So I started my research of how the win32 designer works. Usually my research consists of Alt+F7 in Far manager for some search key (in this case for 'designer') and if Alt+F7 doesn't help, then in debugging the code. I suppose on that occasion I had been satisfied by search in files. First of all I found 'TWin32WidgetSet.GetDesignerDC' method and later I've checked that this method is indeed what I searched for. Look at TDesigner.DrawDesignerItems and you'll find that yourself.
So, I've known the enemy by sight :) If you notice GetDesignerDC creates a visually transparent window over WindowHandle and returns the Device Context for that overlay window. The Device Context is not a interesting thing for us, but the overlay window is. That overlay window is placed on top of a form (and all child controls). And the most interesting thing in that overlay window is the window procedure OverlayWindowProc.
Inside OverlayWindowProc we can find that overlay window easts all messages except WM_KEYFIRST..WM_KEYLAST, WM_MOUSEFIRST..WM_MOUSELAST and that bunch of messages it redirects to the parent (look at Windows.GetParent(Window)). If you look at TDesigner.DrawDesignerItems then you'll know that the Parent of OverlayWindow is the Form. So nothing wondering now that the PageControl Tabs cannot be switched in designer - PageControl gets no clicks (they are caught by our overlay window).
Hmm ... I thought about a solution. The first thing that flashed through my mind was sending those mouse clicks to the underlying control. But it is so easy to forget about some messages or make other errors if you want to emulate windows behaviour. So I rejected that way as defective. Another way is to make some parts of our overlay window transparent for mouse. Windows has a special message WM_NCHITTEST to check what a given coordinate means. And a window can return HTTRANSPARENT as result of a message to indicate that message must be sent to the underlying window (so this point is transparent for the window).
As result the whole solution consisted of handling WM_NCHITTEST in OverlayWindowProc and return HTTRANSPARENT if underlying control wanted mouse messages for that point at design time. I've added a new method GetDesignInteractive to TWSWinControl.
class function GetDesignInteractive(const AWinControl: TWinControl; AClientPos: TPoint): Boolean;
Now I had a method to check, but of course I needed the implementation of that method for TPageControl (which checked that mouse is over control Tabs). So I've added TWin32WSCustomNotebook.GetDesignInteractive, rebuilt the win32 ide and hurray - I switched PageControl tabs in designer w/o problems.
You can look at implementation in revisions: 12245, 12620 (method has been renamed).
Saturday, September 29, 2007
Fight for Synedit speed under qt widgetset
One or two weeks ago our qt-ide was almost fine (if form designer was not taken into account) except one important detail - the speed of the unit editor. Yes, you were able to edit source, but the speed .... it was deadly slow. You could type a key and wait second or two before that key was printed in editor. So we started the fight for speed.
The core of the unit editor is the Synedit component. Lazarus uses an early version of Synedit but it is heavily changed for our needs (adopted, extended). Synedit is a TCustomControl, so it does all its painting and event handling itself. When I looked at the source for the first time, I found nothing criminal. A well done component which repaints only changed areas.
I tried to find out what piece of code makes the component so slow under qt. And I found that it is the qt QPainter.DrawText method. My first assumption was that in the OnPaint event we were repainting the whole Synedit, not only the changed area.
I checked how invalidateRect was done and there was no error - QWidget.Update(Rect) was called. My next assumption was that we were ignoring that Rect in the OnPaint event, but no - we did clip the paint area by that rect. What was it - a mystery?
I checked how clipping worked and found, that in DrawText the clipping was gone. The reason was in Synedit - it used double buffered painting and as result DrawText performed on a non clipped bitmap instead of a clipped window. Revision 12175 changed things. There was no more bitmap, but painting was still as slow as before.
My next assumption was that qt doesn't check the clipping region before DrawText. And bingo - manual check of clipping rect before DrawText gave us no bad speed (revision 12183). But cpu usage was very big in spite of the achieved speed. So something was still wrong, but what?
Zeljan noticed that caret eats too much cpu time. It was because of a not optimal use of timer and widget repainting. After fixing those things in revisions 12198-12200 there was not so high cpu rate as before.
I was already happy but Zeljan was at his best and found one more speed killer. That was our ExtTextOut implementation. ExtTextOut have 2 arguments related to text: Str - the text and Count - count of chars. We made the assumption that Pascal components pass Str arguments that are already trimmed to count chars, but this was not true (at least for Synedit). There were cases where count was equal to 1, but Length of Str equal to 300 (or 400 chars). After an appropriate patch (revisions 12201,12205)the speed of Synedit has become really fast.
Now qt-ide as fast as it should be.
The core of the unit editor is the Synedit component. Lazarus uses an early version of Synedit but it is heavily changed for our needs (adopted, extended). Synedit is a TCustomControl, so it does all its painting and event handling itself. When I looked at the source for the first time, I found nothing criminal. A well done component which repaints only changed areas.
I tried to find out what piece of code makes the component so slow under qt. And I found that it is the qt QPainter.DrawText method. My first assumption was that in the OnPaint event we were repainting the whole Synedit, not only the changed area.
I checked how invalidateRect was done and there was no error - QWidget.Update(Rect) was called. My next assumption was that we were ignoring that Rect in the OnPaint event, but no - we did clip the paint area by that rect. What was it - a mystery?
I checked how clipping worked and found, that in DrawText the clipping was gone. The reason was in Synedit - it used double buffered painting and as result DrawText performed on a non clipped bitmap instead of a clipped window. Revision 12175 changed things. There was no more bitmap, but painting was still as slow as before.
My next assumption was that qt doesn't check the clipping region before DrawText. And bingo - manual check of clipping rect before DrawText gave us no bad speed (revision 12183). But cpu usage was very big in spite of the achieved speed. So something was still wrong, but what?
Zeljan noticed that caret eats too much cpu time. It was because of a not optimal use of timer and widget repainting. After fixing those things in revisions 12198-12200 there was not so high cpu rate as before.
I was already happy but Zeljan was at his best and found one more speed killer. That was our ExtTextOut implementation. ExtTextOut have 2 arguments related to text: Str - the text and Count - count of chars. We made the assumption that Pascal components pass Str arguments that are already trimmed to count chars, but this was not true (at least for Synedit). There were cases where count was equal to 1, but Length of Str equal to 300 (or 400 chars). After an appropriate patch (revisions 12201,12205)the speed of Synedit has become really fast.
Now qt-ide as fast as it should be.
Friday, September 21, 2007
The Lazarus 0.9.24 release date
One of the best held secrets in the Lazarus community is the release date of Lazarus 0.9.24. Sometimes people ask when the next Lazarus release will be. The only correct answer is: "When it is finished". And even the Lazarus developers don't know when that is.
Fortunately, we have a criterium for finished. We want our next release as good as the previous one, so things that work in 0.9.22, must work in 0.9.24 too. If soemthing stops working and it is found out by people using the snapshots, we ask create a bug report for it in the Lazarus bug tracker. Such regressions are marked with "LazTarget 0.9.24". On the view issues page, you can filter on those issues. The list of 0.9.24 issues is currently 23 long, most them are already assigned to some developer. The list also contains patches contributed by Lazarus users, we want to include in the next release. Currently the list is too long to give a reliable estimate of the next Lazarus release date.
In the final stages before a release and during the release preparation we use the Detailed todo page on the wiki as a kind of check list.
You might wonder if nothing is happening on the Lazarus front. The truth is, that very much has been done since 0.9.22. Almost 200 bugs have been fixed (see Changelog in the bug tracker) in Lazarus 0.9.23 and more than 1300 svn commits have been made. You can track the svn commits to the Lazarus svn repository though rss or at the Lazarus page at CIA.vc.
Fortunately, we have a criterium for finished. We want our next release as good as the previous one, so things that work in 0.9.22, must work in 0.9.24 too. If soemthing stops working and it is found out by people using the snapshots, we ask create a bug report for it in the Lazarus bug tracker. Such regressions are marked with "LazTarget 0.9.24". On the view issues page, you can filter on those issues. The list of 0.9.24 issues is currently 23 long, most them are already assigned to some developer. The list also contains patches contributed by Lazarus users, we want to include in the next release. Currently the list is too long to give a reliable estimate of the next Lazarus release date.
In the final stages before a release and during the release preparation we use the Detailed todo page on the wiki as a kind of check list.
You might wonder if nothing is happening on the Lazarus front. The truth is, that very much has been done since 0.9.22. Almost 200 bugs have been fixed (see Changelog in the bug tracker) in Lazarus 0.9.23 and more than 1300 svn commits have been made. You can track the svn commits to the Lazarus svn repository though rss or at the Lazarus page at CIA.vc.
Thursday, September 20, 2007
Lazarus snapshot are using fpc 2.2.0
In the last couple of days I have made changes to the build servers and the mirrors. All snapshots that were using fpc 2.0.4 are now using fpc 2.2.0.
The next Lazarus release (version 0.9.24) will be based on fpc 2.2.0 too, so these snapshots give a good preview of the next release. At his moment there are still about 20 bugs open that need to be fixed before the release, so there is still plenty time for testing Lazarus 0.9.23. Download it from one of the snapshot mirrors:
The next Lazarus release (version 0.9.24) will be based on fpc 2.2.0 too, so these snapshots give a good preview of the next release. At his moment there are still about 20 bugs open that need to be fixed before the release, so there is still plenty time for testing Lazarus 0.9.23. Download it from one of the snapshot mirrors:
Tuesday, September 18, 2007
Reviewing a patch for the chart component
The chart component in Lazarus was written two years ago by Philippe Martinole for his TeleAuto project. He submitted the component to the Lazarus Code and Component Repository. Later Luis Rodrigues extended it and made it more Delphi compatible. The component was considered stable and useful enough to add it to the default installation of Lazarus. Luis Rodrigues now is the main maintainer of the component.
A couple of weeks ago Luis submitted a patch for the chart component. Because I don't know the inner workings of the chart components and don't have a test program, I usually do two things:
This particular patch contained the following code to fix clipping:
I don't know how clipping works and what LPtoDP exactly does, but having a {$IFDEF} here in the middle of a procedure, doesn't look like good portable code. There seemed to be some inconstencies between the CreateRectRgn functions for win32 widgetset and the gtk widgetset: one expects logical points and the other device points.
Even if we wanted to use a {$IFDEF} the current one is probably not correct. The difference is not the OS, but the used widget set, so using {$IFDEF LCLwin32} would have been better. Remember, that the qt and the gtk2 widget can be compiled on windows too.
I asked Luis to find a better solution and maybe some people on the mailing list could help (unfortunately I had no clue how to fix this properly). Luis found another way without IFDEFS:
This patch I happily applied after I tested the compilation.
A couple of weeks ago Luis submitted a patch for the chart component. Because I don't know the inner workings of the chart components and don't have a test program, I usually do two things:
- Do a visual inspection of the patch to see if it contains sensible things.
- Check if the patched version compiles on under windows, my main development OS.
This particular patch contained the following code to fix clipping:
//set cliping region so we don't draw outsite
- Rgn := CreateRectRgn(XImageMin, YImageMax, XImageMax, YImageMin);
+ p[0].x := XImageMin;
+ p[0].y := YImageMax;
+ p[1].x := XImageMax;
+ p[1].y := YImageMin;
+
+ {$IFDEF windows}
+ LPtoDP(Canvas.Handle, p, 2);
+ {$ENDIF}
+ Rgn := CreateRectRgn(p[0].x, p[0].y, p[1].x, p[1].y);
SelectClipRgn (Canvas.Handle, Rgn);
I don't know how clipping works and what LPtoDP exactly does, but having a {$IFDEF} here in the middle of a procedure, doesn't look like good portable code. There seemed to be some inconstencies between the CreateRectRgn functions for win32 widgetset and the gtk widgetset: one expects logical points and the other device points.
Even if we wanted to use a {$IFDEF} the current one is probably not correct. The difference is not the OS, but the used widget set, so using {$IFDEF LCLwin32} would have been better. Remember, that the qt and the gtk2 widget can be compiled on windows too.
I asked Luis to find a better solution and maybe some people on the mailing list could help (unfortunately I had no clue how to fix this properly). Luis found another way without IFDEFS:
//set cliping region so we don't draw outsite
- Rgn := CreateRectRgn(XImageMin, YImageMax, XImageMax, YImageMin);
- SelectClipRgn (Canvas.Handle, Rgn);
+ IntersectClipRect(Canvas.Handle, XImageMin, YImageMax, XImageMax, YImageMin);
This patch I happily applied after I tested the compilation.
Subscribe to:
Posts (Atom)