Sign in Join

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

Mailing lists / lazarus / 2014-09

GetWindowSize misleading documentation or bug?

14 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Luca Olivetti

I was looking for a (hopefullyuuuuu) cross platform way to know the whole size of a window, including its decoration and I found this:

http://lazarus-ccr.sourceforge.net/docs/lcl/lclintf/getwindowsize.html

the documentation on that page reflect what I see on the tooltip in lazarus (1.2.4), *but* the implementation (at least win32) actually removes the size of the borders and the caption.
Is the documentation wrong or is it a bug?
Btw: GetWindowRect returns the whole size in windows but not with gtk2.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Giuliano Colla
to Luca Olivetti

Il 26/09/2014 13:03, Luca Olivetti ha scritto:

Show quoted text 10 lines
I was looking for a (hopefullyuuuuu) cross platform way to know the whole size of a window, including its decoration and I found this: http://lazarus-ccr.sourceforge.net/docs/lcl/lclintf/getwindowsize.html the documentation on that page reflect what I see on the tooltip in lazarus (1.2.4), *but* the implementation (at least win32) actually removes the size of the borders and the caption. Is the documentation wrong or is it a bug? Btw: GetWindowRect returns the whole size in windows but not with gtk2.

AFAIK getting the whole size of a window, decorations included, in a general way, is almost hopeless.

The entity taking care of providing borders and decoration is the window manager, something neither the compiler nor the widgetset are aware of. On a given platform you may change your window manager and run the same program seamlessly.

Each window manager would require a specific implementation to provide the information, and the application should obtain the information about the window manager in use, to use the appropriate function, provided the platform makes it possible.

On Windows the task is somewhat easier, because there's just one window manager, but it may change from one version to the next. What works with Vista may not work anymore under Windows 7 or Windows 8. I tested the GetWindowRect function with the last stable Lazarus version in an old Windows XP VM, and it returns just the window client area, like it happens under Linux both with gtk2 and Qt.

Giuliano

Reply by email

Giuliano Colla
to Giuliano Colla

Il 26/09/2014 19:32, Giuliano Colla ha scritto:

Show quoted text 16 lines
Il 26/09/2014 13:03, Luca Olivetti ha scritto: > I was looking for a (hopefullyuuuuu) cross platform way to know the > whole size of a window, including its decoration and I found this: > > http://lazarus-ccr.sourceforge.net/docs/lcl/lclintf/getwindowsize.html > > the documentation on that page reflect what I see on the tooltip in > lazarus (1.2.4), *but* the implementation (at least win32) actually > removes the size of the borders and the caption. > Is the documentation wrong or is it a bug? > Btw: GetWindowRect returns the whole size in windows but not with gtk2. AFAIK getting the whole size of a window, decorations included, in a general way, is almost hopeless.

I was too hasty in my reply. After some tests here are the results:

GetWindowSize returns the window client area in all platforms.

GetWindowRect here returns the full window area (decoration and borders included) in all the configurations tested:

Windows XP running in a VM under Linux, with Lazarus 1.2.4 Linux CentOs 6, Gtk2 and Qt, desktop KDE and XFce, Lazarus 1.2.2 and Lazarus 1.3 (trunk)

Apparently the documentation isn't accurate, and there's a mix-up of the two functions

Giuliano

Giuliano Colla Project planning question: when it's 90% done, are we halfway or not yet?

Reply by email

Luca Olivetti
to Giuliano Colla

El 26/09/14 20:47, Giuliano Colla ha escrit:

I was too hasty in my reply. After some tests here are the results:

Yes, I was puzzled when you said it didn't work in an xp vm, since that's exactly the configuration I tested

Show quoted text 9 lines
GetWindowSize returns the window client area in all platforms. GetWindowRect here returns the full window area (decoration and borders included) in all the configurations tested: Windows XP running in a VM under Linux, with Lazarus 1.2.4 Linux CentOs 6, Gtk2 and Qt, desktop KDE and XFce, Lazarus 1.2.2 and Lazarus 1.3 (trunk)

Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm trying to do is to tile windows one next to the other. Using GetWindowRect under windows I can do it properly, while on linux gtk the windows overlap (i.e. with this layout

A B C
D E

A overlaps D and B overlaps E, the amount of overlap seems to be equal to the height of the title bar).

Apparently the documentation isn't accurate, and there's a mix-up of the two functions

So in theory GetWindowRect is the "right" function while GetWindowSize is redundant (since there's already width and height)?

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Luca Olivetti
to Luca Olivetti

El 26/09/14 22:45, Luca Olivetti ha escrit:

Show quoted text 28 lines
El 26/09/14 20:47, Giuliano Colla ha escrit: > I was too hasty in my reply. After some tests here are the results: Yes, I was puzzled when you said it didn't work in an xp vm, since that's exactly the configuration I tested > > GetWindowSize returns the window client area in all platforms. > > GetWindowRect here returns the full window area (decoration and borders > included) in all the configurations tested: > > Windows XP running in a VM under Linux, with Lazarus 1.2.4 > Linux CentOs 6, Gtk2 and Qt, desktop KDE and XFce, Lazarus 1.2.2 and > Lazarus 1.3 (trunk) Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm trying to do is to tile windows one next to the other. Using GetWindowRect under windows I can do it properly, while on linux gtk the windows overlap (i.e. with this layout A B C D E A overlaps D and B overlaps E, the amount of overlap seems to be equal to the height of the title bar).

Oh, and there's also a slight overlap between A-B, B-C and D-E

Show quoted text 12 lines
> > Apparently the documentation isn't accurate, and there's a mix-up of the > two functions So in theory GetWindowRect is the "right" function while GetWindowSize is redundant (since there's already width and height)? Bye
Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Giuliano Colla
to Luca Olivetti

Il 26/09/2014 22:47, Luca Olivetti ha scritto:

Show quoted text 14 lines
El 26/09/14 22:45, Luca Olivetti ha escrit: > Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm > trying to do is to tile windows one next to the other. Using > GetWindowRect under windows I can do it properly, while on linux gtk the > windows overlap (i.e. with this layout > > > A B C > D E > > A overlaps D and B overlaps E, the amount of overlap seems to be equal > to the height of the title bar). Oh, and there's also a slight overlap between A-B, B-C and D-E

Something which could affect your results is the timing. The window manager takes a time to add the decorations. Different window managers take different time. It's meant for human observers, which don't perceive a delay of some tens of milliseconds. Therefore it's given a low priority (and the mechanism is quite different from Windows to Linux). If you ask the size too early, you get a size which has not yet been adjusted.

You may verify if the function works properly by adding somewhere in your form a button and a label, and with the onClick of the button write in the label caption both the result of GetWindowSize and of GetWindowRect. You can't possibly push the button faster than the time it takes the window manager to decorate your window!

If you get the expected result, (i.e. size of client area and size with decorations) then you know that the problem is just of timing. If you add a delay of let's say 50ms from window paint, or window show to getting its size and positioning the next window, you should be out of trouble. A total delay of 200ms should be unnoticeable and harmless, even if maybe useless in Windows.

> So in theory GetWindowRect is the "right" function while GetWindowSize > is redundant (since there's already width and height)? >

That's at least what I gather by comparing documentation with actual results.

Giuliano

Giuliano Colla Project planning question: when it's 90% done, are we halfway or not yet?

Reply by email

Hans-Peter Diettrich
to Luca Olivetti: El 26/09/14 20:47, Giuliano Colla ha escrit: Yes, I was puzzled when you said it didn't…
Show quoted text 11 lines
Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm trying to do is to tile windows one next to the other. Using GetWindowRect under windows I can do it properly, while on linux gtk the windows overlap (i.e. with this layout A B C D E A overlaps D and B overlaps E, the amount of overlap seems to be equal to the height of the title bar).

IIRC the Linux (X11) window managers communicate only the size of the client area to the widgetsets, so that attempts to derive the total window extent from this information are subject to assumptions about the extent of the window "decoration" (caption, theme...). They also don't allow (offer no means for) ownerdraw of the NC area of a window.

On Windows instead the owner of a form can paint the entire area of a window (in WM_NCPAINT), so that the Windows window manager allows access to the full extent of a window. Also note that Windows uses distinct windows for every TWinControl, while these are ordinary controls in X11, under exclusive management of the widgetset.

DoDi

Reply by email

Luca Olivetti
to Giuliano Colla: Il 26/09/2014 22:47, Luca Olivetti ha scritto: Something which could affect your results…

El 27/09/14 00:05, Giuliano Colla ha escrit:

Show quoted text 30 lines
Il 26/09/2014 22:47, Luca Olivetti ha scritto: > El 26/09/14 22:45, Luca Olivetti ha escrit: >> Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm >> trying to do is to tile windows one next to the other. Using >> GetWindowRect under windows I can do it properly, while on linux gtk the >> windows overlap (i.e. with this layout >> >> >> A B C >> D E >> >> A overlaps D and B overlaps E, the amount of overlap seems to be equal >> to the height of the title bar). > Oh, and there's also a slight overlap between A-B, B-C and D-E > Something which could affect your results is the timing. The window manager takes a time to add the decorations. Different window managers take different time. It's meant for human observers, which don't perceive a delay of some tens of milliseconds. Therefore it's given a low priority (and the mechanism is quite different from Windows to Linux). If you ask the size too early, you get a size which has not yet been adjusted. You may verify if the function works properly by adding somewhere in your form a button and a label, and with the onClick of the button write in the label caption both the result of GetWindowSize and of GetWindowRect. You can't possibly push the button faster than the time it takes the window manager to decorate your window!

I'm puzzled: with a test program I see no difference in the size in both cases (right after showing the form and after pressing the button) *and* the size is the right one (in FormShow is always 1,1 btw). I must be doing something else wrong (though the tiling is the correct on under windows, mmmh..).
Oh, well, this program has to work in windows only, so I'll just consider it a documentation error and go on with my life ;-)

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Luca Olivetti
to Hans-Peter Diettrich: IIRC the Linux (X11) window managers communicate only the size of the client area to the…

El 27/09/14 11:48, Hans-Peter Diettrich ha escrit:

Show quoted text 19 lines
Luca Olivetti schrieb: > Strange, on mageia 4, kde, lazarus 1.2.4 it doesn't work. What I'm > trying to do is to tile windows one next to the other. Using > GetWindowRect under windows I can do it properly, while on linux gtk the > windows overlap (i.e. with this layout > > > A B C > D E > > A overlaps D and B overlaps E, the amount of overlap seems to be equal > to the height of the title bar). IIRC the Linux (X11) window managers communicate only the size of the client area to the widgetsets, so that attempts to derive the total window extent from this information are subject to assumptions about the extent of the window "decoration" (caption, theme...). They also don't allow (offer no means for) ownerdraw of the NC area of a window.

Yes, but see my other mail to Giuliano: GetWindowRect seems to be finding the correct total size (including decoration).

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Luca Olivetti
to Luca Olivetti: El 27/09/14 00:05, Giuliano Colla ha escrit: I'm puzzled: with a test program I see no…

El 27/09/14 12:09, Luca Olivetti ha escrit:

Show quoted text 6 lines
I'm puzzled: with a test program I see no difference in the size in both cases (right after showing the form and after pressing the button) *and* the size is the right one (in FormShow is always 1,1 btw). I must be doing something else wrong (though the tiling is the correct on under windows, mmmh..).

Found it, nothing wrong on my part: the test program used an auto created form, the real application creates the form at run time *and* right after creating the form, after the show GetWindowRect only returns the client size. I have to introduce a delay for it to return the whole window's size (and even then, from time to time, it only returns the client size), so you were correct and this is insane.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

Luca Olivetti
to Luca Olivetti

El 27/09/14 12:23, Luca Olivetti ha escrit:

Show quoted text 14 lines
El 27/09/14 12:09, Luca Olivetti ha escrit: > > I'm puzzled: with a test program I see no difference in the size in both > cases (right after showing the form and after pressing the button) *and* > the size is the right one (in FormShow is always 1,1 btw). > I must be doing something else wrong (though the tiling is the correct > on under windows, mmmh..). Found it, nothing wrong on my part: the test program used an auto created form, the real application creates the form at run time *and* right after creating the form, after the show GetWindowRect only returns the client size. I have to introduce a delay for it to return the whole window's size (and even then, from time to time, it only returns the client size), so you were correct and this is insane.

And, for the record, with qt it's the same (only it seems the delay have to be bigger).

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

zeljko
to Luca Olivetti
Luca Olivetti wrote 18 lines
El 27/09/14 12:23, Luca Olivetti ha escrit: > El 27/09/14 12:09, Luca Olivetti ha escrit: >> >> I'm puzzled: with a test program I see no difference in the size in both >> cases (right after showing the form and after pressing the button) *and* >> the size is the right one (in FormShow is always 1,1 btw). >> I must be doing something else wrong (though the tiling is the correct >> on under windows, mmmh..). > > Found it, nothing wrong on my part: the test program used an auto > created form, the real application creates the form at run time *and* > right after creating the form, after the show GetWindowRect only returns > the client size. I have to introduce a delay for it to return the whole > window's size (and even then, from time to time, it only returns the > client size), so you were correct and this is insane. And, for the record, with qt it's the same (only it seems the delay have to be bigger).

Under X11 nobody knows exact window size (except client size setted up by LCL or widgetset) until window is decorated by wm (read mapped - shown on screen). See
http://qt-project.org/doc/qt-4.8/application-windows.html#x11-peculiarities It's almost same for gtk2 and other X11 widgetsets. Problem is that you cannot query wm for eg. title bar height,form borders separately so then it will be easy to calculate everything. Hope that wayland will address this problems.

zeljko

Reply by email

Luca Olivetti
to zeljko

El 27/09/14 14:32, zeljko ha escrit:

Show quoted text 26 lines
On 09/27/2014 12:26 PM, Luca Olivetti wrote: > El 27/09/14 12:23, Luca Olivetti ha escrit: >> El 27/09/14 12:09, Luca Olivetti ha escrit: >>> >>> I'm puzzled: with a test program I see no difference in the size in >>> both >>> cases (right after showing the form and after pressing the button) >>> *and* >>> the size is the right one (in FormShow is always 1,1 btw). >>> I must be doing something else wrong (though the tiling is the correct >>> on under windows, mmmh..). >> >> Found it, nothing wrong on my part: the test program used an auto >> created form, the real application creates the form at run time *and* >> right after creating the form, after the show GetWindowRect only returns >> the client size. I have to introduce a delay for it to return the whole >> window's size (and even then, from time to time, it only returns the >> client size), so you were correct and this is insane. > > And, for the record, with qt it's the same (only it seems the delay have > to be bigger). Under X11 nobody knows exact window size (except client size setted up by LCL or widgetset) until window is decorated by wm (read mapped - shown on screen). See http://qt-project.org/doc/qt-4.8/application-windows.html#x11-peculiarities

Yes, I understand, the "insanity" I referred to was about the underlying environment, not Lazarus.
Anyway, I tried with this snipped of code to measure the decoration

procedure TForm1.Button1Click(Sender: TObject);
var f:TForm;
    i:integer;
    wr: TRect;
    h: Integer;
    w: Integer;
begin
  f:=TForm.Create(nil);
  f.top:=10000;
  f.left:=10000;
  f.width:=100;
  f.height:=100;
  f.show;
  i:=0;
  while true do
  begin
    Application.ProcessMessages;
    GetWindowRect(f.Handle,wr);
    h:=wr.bottom-wr.top;
    w:=wr.Right-wr.left;
    if (wf.width) and (hf.height) then
      break;
    i:=i+1;
    if i>1000 then
      break;
  end;
  Label1.Caption:=format('%d  w:%d h:%d',[i,w-f.width,h-f.height]);
  f.free;
end;

The f.top and f.left assignment was a (futile) attempt to avoid flashing the form on screen.
With gtk2 2 I consistently get the result at the first iteration (i=0), while with qt it takes at least 2 cycles, on occasions i counted up to 20. Just FYI.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 Fax +34 935883007

Reply by email

zeljko
to Luca Olivetti
Luca Olivetti wrote 68 lines
El 27/09/14 14:32, zeljko ha escrit: > On 09/27/2014 12:26 PM, Luca Olivetti wrote: >> El 27/09/14 12:23, Luca Olivetti ha escrit: >>> El 27/09/14 12:09, Luca Olivetti ha escrit: >>>> >>>> I'm puzzled: with a test program I see no difference in the size in >>>> both >>>> cases (right after showing the form and after pressing the button) >>>> *and* >>>> the size is the right one (in FormShow is always 1,1 btw). >>>> I must be doing something else wrong (though the tiling is the correct >>>> on under windows, mmmh..). >>> >>> Found it, nothing wrong on my part: the test program used an auto >>> created form, the real application creates the form at run time *and* >>> right after creating the form, after the show GetWindowRect only returns >>> the client size. I have to introduce a delay for it to return the whole >>> window's size (and even then, from time to time, it only returns the >>> client size), so you were correct and this is insane. >> >> And, for the record, with qt it's the same (only it seems the delay have >> to be bigger). > > Under X11 nobody knows exact window size (except client size setted up > by LCL or widgetset) until window is decorated by wm (read mapped - > shown on screen). See > http://qt-project.org/doc/qt-4.8/application-windows.html#x11-peculiarities Yes, I understand, the "insanity" I referred to was about the underlying environment, not Lazarus. Anyway, I tried with this snipped of code to measure the decoration procedure TForm1.Button1Click(Sender: TObject); var f:TForm; i:integer; wr: TRect; h: Integer; w: Integer; begin f:=TForm.Create(nil); f.top:=10000; f.left:=10000; f.width:=100; f.height:=100; f.show; i:=0; while true do begin Application.ProcessMessages; GetWindowRect(f.Handle,wr); h:=wr.bottom-wr.top; w:=wr.Right-wr.left; if (wf.width) and (hf.height) then break; i:=i+1; if i>1000 then break; end; Label1.Caption:=format('%d w:%d h:%d',[i,w-f.width,h-f.height]); f.free; end; The f.top and f.left assignment was a (futile) attempt to avoid flashing the form on screen. With gtk2 2 I consistently get the result at the first iteration (i=0), while with qt it takes at least 2 cycles, on occasions i counted up to 20. Just FYI.

I know about it. It's explained at the mentioned link, also gtk2lcl puts size events in queue and process it via Application.ProcessMessages, qt provides such event when it's ready.

zeljko

Reply by email