View Issue Details

IDProjectCategoryView StatusLast Update
0020952LazarusLCLpublic2016-03-24 14:21
ReporterZex AtillaAssigned ToOndrej Pokorny 
PrioritynormalSeverityfeatureReproducibilityalways
Status assignedResolutionopen 
Product VersionProduct Build 
Target VersionFixed in Version 
Summary0020952: Form ClientWidth
DescriptionI know that Form.ClientWidth = Form.Width is by design, caused by GTK incompleteness, but this definitely shouldn't be the case. This is a big issue, since TForm is the most important GUI component in a program.

If GTK has problems getting its outer window size (which is ridiculous by itself), then only under GTK should be ClientWidth = Width. Other windowing systems shouldn't be punished for GTK's incompleteness.

Window dimensions can be handled manually, by calling OS functions separately for each OS / windowing system, but this kinda defeats the purpose of LCL. Please consider reimplementing this important functionality.
TagsNo tags attached.
Fixed in Revision51818,51819
LazTarget-
Widgetset
Attached Files

Relationships

has duplicate 0001794 resolvedBart Broersma Height property of a Form is Clientheight 
related to 0027771 resolvedOndrej Pokorny Position "screen center" don't give vert-center 
related to 0029371 closedOndrej Pokorny Error location in the form Form.Position: = poScreenCenter; 
related to 0029887 closedOndrej Pokorny Form position "poMainFormCenter" don't work correctly 

Activities

Felipe Monteiro de Carvalho

2011-12-22 20:47

developer   ~0055232

I don't think this will be changed since that affects backwards compatibility with existing Lazarus code quite severely. But I am open to adding a new property for this, like FrameWidth, FrameHeight.

But, to start with: What do you want to use this for?

And second, if you think it is so easy to implement this in X11, why dodn't you send a patch? =D If you can make it work in X11, then for sure it will work everywhere else where window decorations exist.

Felipe Monteiro de Carvalho

2011-12-24 11:40

developer   ~0055253

Last edited: 2011-12-24 11:40

Actually we already have:

function GetWindowSize(Handle: hwnd; var Width, Height: Integer): boolean; override;

In InterfaceBase.Widgetset, possibly in LCLIntf too.

But I don't know if it works in gtk2

Zeljan Rikalo

2011-12-24 19:29

developer   ~0055262

It should work only when window is mapped by wm.

Zex Atilla

2011-12-26 15:51

reporter   ~0055296

GetWindowSize? Ok, but I don't see SetWindowSize.
And it's not in the spirit of object programming. It should be a property of TForm. How about Form.OuterBounds := Rect (x, y, w, h)?

Why would anyone need this? For example, to set a window to be some distance from another window, or to snap to another window, or to fit window inside a certain region. One must set EXACT dimensions and position, not approximate. This is not luxury, it's a need.

I don't say I can make it work under X11, but should all platforms be punished just because one cannot do it? Should Lazarus use 15-bit images as its base because some platforms cannot display 24-bit or 32-bit images? No. For those platforms the image will be reduced to 15-bit, but on all others it will look smooth and nice.

Even making Form.Width to work properly (as in VCL) shouldn't cause much problems to majority of programs written in Lazarus. Why? Because they already don't use Form.Width since it's always wrong for windows with border. For outside dimensions one must use the window manager functions directly.

Please note that Lazarus download count for Windows far outnumbers all other downloads combined. So many Lazarus users would profit from it. MacOS programmers too. X11 doesn't support it, but that shouldn't freeze Lazarus progress forever.

Zex Atilla

2011-12-26 15:57

reporter   ~0055297

How about a flag? For example: Form.RealOuterDimensions := True.
After that Form.Width and Form.Height return real outer size, if possible on that platform.

Felipe Monteiro de Carvalho

2011-12-27 00:04

developer   ~0055303

> GetWindowSize? Ok, but I don't see SetWindowSize.

There is:

function SetWindowPos(hWnd: HWND; hWndInsertAfter: HWND;
       X, Y, cx, cy: Integer; uFlags: UINT): Boolean; {$IFDEF IF_BASE_MEMBER}virtual;{$ENDIF}

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx

> And it's not in the spirit of object programming. It should be a property of TForm.

You are lacking the overview of how things work in the LCL. We add interface-dependent routines first in LCLIntf and then afterwards we can add things in cross-platform classes when it works correctly in all major platforms.

> How about Form.OuterBounds := Rect (x, y, w, h)?

Yes, sure, but only if it works in X11. Until then, people that needs this can use LCLIntf.GetWindowSize and LCLIntf.SetWindowPos

>I don't say I can make it work under X11, but should all platforms be punished just because one cannot do it?

If you don't want to send a patch for X11 then use GetWindowSize / SetWindowPos

> Even making Form.Width to work properly (as in VCL) shouldn't cause much problems to majority of
> programs written in Lazarus. Why? Because they already don't use Form.Width since it's always wrong
> for windows with border. For outside dimensions one must use the window manager functions directly.

No chance for that, I know very well how changes affect user software badly even when you think it is safe. Here I already know from the start it will be a major problem.

> How about a flag? For example: Form.RealOuterDimensions := True.

This proposal has some pros and cons ... we would have to discuss this among developers to see if a patch for that would be accepted.

Zeljan Rikalo

2012-02-04 11:35

developer   ~0056333

Too heavy for 1.0, so target 1.2

Zex Atilla

2012-03-06 16:50

reporter   ~0057327

Thanks. Anybody knows approximate date for that?

Bart Broersma

2012-03-06 23:27

developer   ~0057333

> I don't think this will be changed since that affects backwards compatibility
> with existing Lazarus code quite severely

I quote from the FAQ (http://wiki.freepascal.org/Lazarus_Faq#Why_are_TForm.ClientWidth.2FClientHeight_the_same_as_TForm.Width.2FHeight):
"Eventually when there is a reliable way to get the size and position of a window with its frame on all platforms, then it will be changed. To keep compatibility with older LCL forms, a version number and some extra methods will be added."

Current implementation is wrong and if we can fix it on all platforms we should do so.

If the core developers decide not to change this behaviour (given the above condition), then please update the wiki.

> But I am open to adding a new property for this, like FrameWidth, FrameHeight.

Introducing yet another Delphi incompatibility.

Felipe Monteiro de Carvalho

2012-03-09 17:02

developer   ~0057440

> If the core developers decide not to change this behaviour (given the above
> condition), then please update the wiki.

Clearly there is a disagreement about how it should be handled.

I won't make this backwards compatibility break, I learned by experience that even minor changes in pieces of code which should not be used by 3rd party developers can break a lot of code, so this one which is not at all minor would certainly be a major problem. But if another core developer wants to do it and take responsability for people complaining afterwards, then he can do it. So I will simply unassign from myself.

Zeljan Rikalo

2014-10-09 16:22

developer   ~0078106

Last edited: 2014-10-09 16:23

View 2 revisions

Maybe new x11 implementations can return frame size of decorated windows ... someone should look into docs ...
EDIT: First "normal" window with decorations can return frame size after show on x11.

Bart Broersma

2014-10-22 13:14

developer   ~0078513

At this point in time, what is still missing that prevents us from trying to implement Width/Height in a Delphi compatible way?
If we can reliably implement it on the major widgetsets (Windows, GTK2, QT, Carbon) shouldn't we just go for it?
This will give us plenty time to fix bugs/regressions before we start rolling out 1.4 release.

Zeljan Rikalo

2016-01-02 11:17

developer   ~0088523

Nothing, let someone start it in different branch than trunk.
I can fix X11 WS as much as possible to get real sizes. Then when it's ready we can merge it in trunk. Of course there will be bugs, but not so much as if we start such changes in trunk which might get unuseable for weeks.

Ondrej Pokorny

2016-01-02 11:38

reporter   ~0088525

@Zeljan: can the real FrameBounds be reliably retrieved from every WM at every time?

I see that GetWindowRect works reliably for visible windows but fails for invisible windows in X11 - both Gtk2 and Qt.

If the real FrameBounds cannot be retrieved reliably, I am strongly for not implementing it at all and keep the current state (ClientWidth=Width).

Everybody who needs FrameBounds should use GetWindowRect (not GetWindowSize as this returns ClientWidth and ClientHeight!) and be aware of the limitation.

Zeljan Rikalo

2016-01-03 13:03

developer   ~0088539

@Ondrej, I said that I can fix X11 WS as much as possible, so that means not 100% sure. My idea on X11 is: get any opened window on system (with decorations) and take frame and title bar from there. First trial is to ask our running application for that. If there's no opened forms, then iterate X11 opened windows.
Of course this will fail when our application is started and there's no other applications opened :). It's shame that there's no such stuff in XOrg specs - window border size and window title bar size. If we know that values, then there won't be problem to fix it.

Ondrej Pokorny

2016-03-02 16:13

reporter   ~0090564

@Zeljko: maybe you could use the same approach as in TQtWidgetSet.GetMenuHeight - create a dummy form, get the size you need (can be BorderStyle dependent) and save it in a variable for further usage.

Zeljan Rikalo

2016-03-02 19:04

developer   ~0090566

@Onderj: it's not same. Form must be mapped (visible) to get decorations from wm. So we'll have "flash" when start any lcl application.

Ondrej Pokorny

2016-03-03 02:08

reporter   ~0090569

>> Form must be mapped (visible) to get decorations from wm. So we'll have "flash" when start any lcl application.

There are 2 common possibilities how to make the dummy form not flash:
1.) Show it outside the screen area.
2.) Show it with full transparency.
(Also a combination of both is possible.)

It could have other side effects, though - it has to be investigated first to tell if this approach is really usable. For now it is just an idea.

Zeljan Rikalo

2016-03-03 09:49

developer   ~0090576

@Ondrej, your idea about showing it outside screen area is very nice, honestly I didn't think about such easy solution, but somewho I'm pretty sure that Qt devels will fix it in that way and not write such warning about problems with geometry on X11. Such stuff depends on window manager and it can work on eg. kwin but will not work on metacitiy, and we are again at the beginning - possible solution(s) can work but not 100% sure that it'll work on all window managers, that's anyway what I have been writing about btw. on my kwin (Fedora 14, KDE 4) such solution works fine - showing widget off screen gives frame distance and borders :)
Problematic part with this (at least under qt) is that such off screen form must be created before application main form, so I don't know what problems can come from there.

Ondrej Pokorny

2016-03-03 13:40

reporter   ~0090591

>> Qt devels will fix it in that way and not write such warning about problems with geometry on X11

Maybe they don't want to use such hacks - I completely understand why.

>> Such stuff depends on window manager and it can work on eg. kwin but will not work on metacitiy, and we are again at the beginning - possible solution(s) can work but not 100% sure

Of course you cannot be 100% sure with such hacks. But I am pretty sure it will work everywhere - the window manager doesn't care if the window is in screen or outside.
A possible problem could be that the WM ignores the off-screen position and forces the form to display on screen and then you'll have the flash.
There may be a possible performance penalty, too.

>> Problematic part with this (at least under qt) is that such off screen form must be created before application main form, so I don't know what problems can come from there.

No problem with that - even LCL forms (splash dialogs like in Lazarus, login dialogs...) can be created before the main form. There should be no problem with non-LCL dialogs there.

Maybe you'll get some extra messages that could cause trouble but they can be filtered out if the hack is executing.

Zeljan Rikalo

2016-03-03 14:00

developer   ~0090592

No, I was wrong about correct sizes with your idea. Even after QWidget_show() there's no real frame size...it comes later...just as it says in Qt documentation. Just played with simple example and indeed it's just like in Qt docs about X11 problems. LCL sets inner form size eg when you say form=340x280, then real frame size (on my KDE with plastique style) becomes 348x311 and that's not info which I can see in FormShow()...so that means that WM still did not decorated form.
So for test:
in OnFormCreate() -> put HandleNeeded, and below writeln LCLIntf.GetWindowRect and LCLIntf.GetClientRect .... put same stuff into OnShow , put some button on form and put same writeln there - now when you click button you'll see real bounds. In one sentence: your idea with moving off screen does not work.

Ondrej Pokorny

2016-03-03 14:14

reporter   ~0090593

Well let's see, I still can give a quick try: http://stackoverflow.com/questions/7408082/how-to-get-the-width-of-a-window-frame-before-creating-any-windows

Zeljan Rikalo

2016-03-03 14:39

developer   ~0090599

Look here first, this is the way to go: https://bugreports.qt.io/browse/QTBUG-2280

Zeljan Rikalo

2016-03-03 14:41

developer   ~0090600

You'll waste your time with solutions from that site.

Ondrej Pokorny

2016-03-03 14:47

reporter   ~0090601

First, I'll fix it for win32 with a compiler define UseRealFormBounds. So people targeting win32 can take use of it if they want to (default will stay unchanged).
It is not that important if UseRealFormBounds won't be supported by other WS. It will be good that the feature will be supported by the LCL on OS/WS that can do that. If a WS doesn't support it, nothing changes.

Zeljan Rikalo

2016-03-03 15:50

developer   ~0090610

Maybe better approach would be to add LCLWidgetsetCapability enum (maybe after UseRealFormBounds define works ok), so then define won't be needed anymore.

Ondrej Pokorny

2016-03-03 16:19

reporter   ~0090612

The idea with TLCLCapability is good as well. But we still need a conditional define for backwards compatibility in any case. It's the same that was done with EnableUTF8RTL/DisableUTF8RTL.

I implemented it in r51818 with the define LCLRealFormBounds. For now win32 only. In the future, if we decide so (I don't have a preference) it can be switched into LCLClientFormBounds, if we decide that real form bounds should be default. (The same like EnableUTF8RTL was changed into DisableUTF8RTL.)

If other WS are made to support this feature, they should use the same compiler define.

Please test all.

Zeljan Rikalo

2016-03-06 15:01

developer   ~0090687

Started Qt on X11 r51835, already works if QtUseAccurateFrame define is enabled in qtdefines.inc, so one step closer to use UseRealFormBounds on qt x11. Relies on pure X11 implementation.

Zeljan Rikalo

2016-03-06 19:41

developer   ~0090706

As of r51837 qt have full support for real form Width & Height via QtUseAccurateFrame define in qtdefines.inc

Ondrej Pokorny

2016-03-07 13:06

reporter   ~0090721

@Zeljko: great news! I'll check it soon.

Zeljan Rikalo

2016-03-07 13:47

developer   ~0090723

Works like a charm :), but fighting with compositing window managers with shadow decoration, so if you test it under such wm results won't be good or disable compositor and use pure wm.

Zeljan Rikalo

2016-03-07 18:18

developer   ~0090737

Compositing WMs are real mess. eg cinnamon: normal form title bar = 40, constrained eg. maxHeight=50 title bar=24, modal form title bar = 33.

Issue History

Date Modified Username Field Change
2011-12-22 19:47 Zex Atilla New Issue
2011-12-22 20:47 Felipe Monteiro de Carvalho Note Added: 0055232
2011-12-24 11:40 Felipe Monteiro de Carvalho Note Added: 0055253
2011-12-24 11:40 Felipe Monteiro de Carvalho Note Edited: 0055253
2011-12-24 19:29 Zeljan Rikalo Note Added: 0055262
2011-12-26 15:51 Zex Atilla Note Added: 0055296
2011-12-26 15:57 Zex Atilla Note Added: 0055297
2011-12-27 00:04 Felipe Monteiro de Carvalho Note Added: 0055303
2011-12-27 00:05 Felipe Monteiro de Carvalho Status new => assigned
2011-12-27 00:05 Felipe Monteiro de Carvalho Assigned To => Felipe Monteiro de Carvalho
2012-02-04 11:35 Zeljan Rikalo LazTarget => 1.2
2012-02-04 11:35 Zeljan Rikalo Note Added: 0056333
2012-03-06 16:50 Zex Atilla Note Added: 0057327
2012-03-06 23:27 Bart Broersma Note Added: 0057333
2012-03-09 17:02 Felipe Monteiro de Carvalho Note Added: 0057440
2012-03-09 17:03 Felipe Monteiro de Carvalho Assigned To Felipe Monteiro de Carvalho =>
2012-03-09 17:04 Felipe Monteiro de Carvalho Status assigned => acknowledged
2014-01-14 15:16 Martin Friebe LazTarget 1.2 => 1.4
2014-05-01 14:32 Bart Broersma Relationship added duplicate of 0001794
2014-09-09 23:27 Juha Manninen LazTarget 1.4 => -
2014-10-09 16:22 Zeljan Rikalo Note Added: 0078106
2014-10-09 16:23 Zeljan Rikalo Note Edited: 0078106 View Revisions
2014-10-22 13:14 Bart Broersma Note Added: 0078513
2015-04-03 16:16 Bart Broersma Relationship added related to 0027771
2016-01-02 11:17 Zeljan Rikalo Note Added: 0088523
2016-01-02 11:38 Ondrej Pokorny Note Added: 0088525
2016-01-02 15:27 Bart Broersma Relationship replaced has duplicate 0001794
2016-01-03 13:03 Zeljan Rikalo Note Added: 0088539
2016-01-11 13:45 Ondrej Pokorny Relationship added related to 0029371
2016-03-02 16:13 Ondrej Pokorny Note Added: 0090564
2016-03-02 19:04 Zeljan Rikalo Note Added: 0090566
2016-03-03 02:08 Ondrej Pokorny Note Added: 0090569
2016-03-03 09:49 Zeljan Rikalo Note Added: 0090576
2016-03-03 13:31 Ondrej Pokorny Assigned To => Ondrej Pokorny
2016-03-03 13:31 Ondrej Pokorny Status acknowledged => assigned
2016-03-03 13:40 Ondrej Pokorny Note Added: 0090591
2016-03-03 14:00 Zeljan Rikalo Note Added: 0090592
2016-03-03 14:14 Ondrej Pokorny Note Added: 0090593
2016-03-03 14:39 Zeljan Rikalo Note Added: 0090599
2016-03-03 14:41 Zeljan Rikalo Note Added: 0090600
2016-03-03 14:47 Ondrej Pokorny Note Added: 0090601
2016-03-03 15:50 Zeljan Rikalo Note Added: 0090610
2016-03-03 16:19 Ondrej Pokorny Note Added: 0090612
2016-03-03 16:20 Ondrej Pokorny Fixed in Revision => 51818
2016-03-03 16:52 Ondrej Pokorny Fixed in Revision 51818 => 51818,51819
2016-03-06 15:01 Zeljan Rikalo Note Added: 0090687
2016-03-06 19:41 Zeljan Rikalo Note Added: 0090706
2016-03-07 13:06 Ondrej Pokorny Note Added: 0090721
2016-03-07 13:47 Zeljan Rikalo Note Added: 0090723
2016-03-07 18:18 Zeljan Rikalo Note Added: 0090737
2016-03-24 14:21 Ondrej Pokorny Relationship added related to 0029887