View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0036127 | Lazarus | LCL | public | 2019-10-02 09:55 | 2020-12-26 16:52 |
Reporter | Joeny Ang | Assigned To | Juha Manninen | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | x86_64 | OS | Arch Linux | ||
Product Version | 2.0.4 | ||||
Summary | 0036127: [Patch] TForm's bounds and restored bounds are inconsistent | ||||
Description | The attached patch tries to fix the following issues: When form is designed with WindowState=wsMaximized: 1. Restored dimension is wrong (related to 0027894, 0022771, 0027375) 2. Width/Height in OnShow() and OnActivate() events are wrong (related to 0021119) Under Delphi 3: - OnCreate(): design time restored width/height - OnShow() and OnActivate(): maximized width/height When form's WindowsState=not maximized 3. Restored bounds in OnResize() and OnChangeBounds() events are wrong or not updated (related to 0032631) Note: Expanded on the idea of Yuichiro Takahashi from Issue 0008576 to use Application.QueueAsyncCall() to "queue" the procedure to update the restored values, to the main event loop, thus delaying it until the form is properly moved or resized. The first calls to OnShow() and OnActivate() are also moved to this procedure so that querying Width/Height during these events will return the correct values. Tested on GTK2 and Win32. | ||||
Tags | No tags attached. | ||||
Fixed in Revision | r61997, r62113, r63218, r63577, r63842, r63888 | ||||
LazTarget | - | ||||
Widgetset | GTK 2, Win32/Win64 | ||||
Attached Files |
|
related to | 0027894 | closed | Juha Manninen | Lazarus | TForm RestoredWidth and RestoredHeight updated incorrectly if window maximized under Gtk2 |
related to | 0022771 | resolved | Juha Manninen | Lazarus | When FormStyle = wsMaximized, after restore Widht/Height have wrong values |
related to | 0027375 | resolved | Juha Manninen | Lazarus | If a Form is started with wsMaximized (set in OI), it does not restore to designed Size |
related to | 0021119 | resolved | Zeljan Rikalo | Lazarus | When a form is started as wsMaximized height and width report design time values |
related to | 0032631 | resolved | Juha Manninen | Packages | "restoredLeft, restoredTop, restoredWidth, restoredHeight" of TForm returned wrong value |
related to | 0008576 | closed | Juha Manninen | Lazarus | After Mini/Maximizing window 'RestoredLeft/Top' values changes to "unreal" values |
related to | 0037647 | closed | Juha Manninen | Lazarus | It does not raise an OnShow event if the form is maximized and ... - since rev 63577 (changed from 62892) |
related to | 0036877 | closed | Zeljan Rikalo | Lazarus | LCL: Regression TCustomForm.OnActivate |
related to | 0037467 | resolved | Juha Manninen | Lazarus | Form Resize Not Firing Correctly |
related to | 0037732 | resolved | Juha Manninen | Lazarus | Win32: bad window behavior after Restore from minimized state |
related to | 0037688 | new | Lazarus | Form Resize, Controls sizing very slow | |
related to | 0038004 | resolved | Bart Broersma | Lazarus | Not executing the "OnResize" method in an embedded TForm |
related to | 0038261 | resolved | Michl | Lazarus | After revision 63888 SpartaDockedFormEditor is not refreshed after bounds change |
|
tform-wrong-bounds-and-restored-bounds.patch (9,834 bytes)
--- lcl/forms.pp +++ lcl/forms.pp @@ -490,6 +490,8 @@ FRestoredHeight: integer; FShowInTaskbar: TShowInTaskbar; FWindowState: TWindowState; + FMovedCtr: Integer; + FIsFirstOnShow, FIsFirstOnActivate: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; function GetMonitor: TMonitor; @@ -590,7 +592,6 @@ procedure VisibleChanged; override; procedure WndProc(var TheMessage : TLMessage); override; function VisibleIsStored: boolean; - procedure DoSendBoundsToInterface; override; procedure DoAutoSize; override; procedure SetAutoSize(Value: Boolean); override; procedure SetAutoScroll(Value: Boolean); override; @@ -649,7 +650,8 @@ function CanFocus: Boolean; override; procedure SetFocus; override; function SetFocusedControl(Control: TWinControl): Boolean ; virtual; - procedure SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer); + procedure SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer; const + ADefaultPosition: Boolean = False); procedure Show; function ShowModal: Integer; virtual; --- lcl/include/customform.inc +++ lcl/include/customform.inc @@ -16,6 +16,8 @@ const BorderStylesAllowAutoScroll = [bsSizeable, bsSizeToolWin]; + ShowCommands: array[TWindowState] of Integer = + (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_SHOWFULLSCREEN); { TCustomForm } @@ -68,93 +70,10 @@ Gets called after the construction of the object ------------------------------------------------------------------------------} procedure TCustomForm.AfterConstruction; -var - NewWidth, NewHeight: Integer; - OldWindowState: TWindowState; - - procedure ChangeFormDimensions(AIsBeforeOnCreate: Boolean); - begin - if (WindowState = wsMaximized) and (FormStyle <> fsMDIChild) then - begin - {$IFDEF DEBUG_SM_LCLMAXIMIZED} - DebugLn('TCustomForm.AfterConstruction: SM_CYCAPTION ', - dbgs(GetSystemMetrics(SM_CYCAPTION)), - ' SM_CYSIZEFRAME ',dbgs(GetSystemMetrics(SM_CYSIZEFRAME)), - ' SM_CXMAXIMIZED ',dbgs(GetSystemMetrics(SM_CXMAXIMIZED)), - ' SM_CYMAXIMIZED ',dbgs(GetSystemMetrics(SM_CYMAXIMIZED)), - ' SM_LCLMAXIMIZEDHEIGHT ',dbgs(GetSystemMetrics(SM_LCLMAXIMIZEDHEIGHT)), - ' SM_LCLMAXIMIZEDWIDTH ',dbgs(GetSystemMetrics(SM_LCLMAXIMIZEDWIDTH)), - ' AIsBeforeOnCreate ',dbgs(AIsBeforeOnCreate)); - {$ENDIF} - - if (BorderStyle <> bsNone) and (FormStyle <> fsSplash) then - begin - NewHeight := GetSystemMetrics(SM_LCLMAXIMIZEDHEIGHT); - NewWidth := GetSystemMetrics(SM_LCLMAXIMIZEDWIDTH); - // if some ws does not implement this then provide normal metrics. - if NewHeight <= 0 then - NewHeight := GetSystemMetrics(SM_CYMAXIMIZED); - if NewWidth <= 0 then - NewHeight := GetSystemMetrics(SM_CXMAXIMIZED); - end else - begin - NewHeight := GetSystemMetrics(SM_CYMAXIMIZED); - NewWidth := GetSystemMetrics(SM_CXMAXIMIZED); - end; - - if Constraints.MaxWidth > 0 then - NewWidth := Min(Constraints.MaxWidth, NewWidth); - if Constraints.MaxHeight > 0 then - NewHeight := Min(Constraints.MaxHeight, NewHeight); - - // for unknown reasons on some systems SM_*MAXIMIZED* system metrics - // (tested xubuntu,64bits) return 0 or negative values, in this case - // a maximized window is expected to have at least WorkArea width/height. - // - // Reproduced again under Debian Wheezy. - // mistery solved, it ocurrs under gtk2/64-bit, fixed at the place - // the checks doesn't hurt though - // - // see bug #21634 - if NewWidth<=0 then - NewWidth := Screen.WorkAreaWidth; - if NewHeight<=0 then - NewHeight := Screen.WorkAreaHeight; - - if NewWidth>0 then - Width := NewWidth; - if NewHeight>0 then - Height := NewHeight; - end; - - if (WindowState = wsFullScreen) and (FormStyle <> fsMDIChild) then - begin - NewWidth := LCLIntf.GetSystemMetrics(SM_CXFULLSCREEN); - NewHeight := LCLIntf.GetSystemMetrics(SM_CYFULLSCREEN); - if Constraints.MaxWidth > 0 then - NewWidth := Min(Constraints.MaxWidth, NewWidth); - if Constraints.MaxHeight > 0 then - NewHeight := Min(Constraints.MaxHeight, NewHeight); - Width := NewWidth; - Height := NewHeight; - end; - end; -begin - // issue #21119, prepare maximized or fullscreen form to accurate dimensions. - // we avoid flickering also in this case. - if not (csDesigning in ComponentState) then - ChangeFormDimensions(True); - - OldWindowState := WindowState; +begin + SetRestoredBounds(Left, Top, Width, Height, True); + DoCreate; - - // if we change WindowState in constructor and handle isn't allocated - // then change our dimensions to accurate one - if not (csDesigning in ComponentState) and not HandleAllocated and - (OldWindowState <> WindowState) and - not (OldWindowState in [wsMaximized, wsFullScreen]) and - (WindowState in [wsMaximized, wsFullScreen]) then - ChangeFormDimensions(False); EndFormUpdate; // the BeginFormUpdate is in CreateNew inherited AfterConstruction; @@ -677,6 +596,9 @@ ------------------------------------------------------------------------------} procedure TCustomForm.Activate; begin + if FIsFirstOnActivate and (WindowState = wsMaximized) then + Exit; + FIsFirstOnActivate := False; if Assigned(FOnActivate) then FOnActivate(Self); end; @@ -732,28 +654,47 @@ end; inherited WMSize(Message); - - if (Message.SizeType and not SIZE_SourceIsInterface) = SIZE_RESTORED then - begin - FRestoredWidth := Width; - FRestoredHeight := Height; - //DebugLn('[TCustomForm.WMSize] saving restored bounds ',DbgSName(Self),' ',dbgs(FRestoredWidth),'x',dbgs(FRestoredHeight)); - end; + Inc(FMovedCtr); + Application.QueueAsyncCall(@Moved, 1); // 1 = resized end; procedure TCustomForm.WMMove(var Message: TLMMove); begin inherited WMMove(Message); - Application.QueueAsyncCall(@Moved, 0); + Inc(FMovedCtr); + Application.QueueAsyncCall(@Moved, 0); // 0 = moved end; procedure TCustomForm.Moved(Data: PtrInt); begin + Dec(FMovedCtr); + if FMovedCtr > 0 then + Exit; if WindowState = wsNormal then begin - FRestoredLeft := Left; - FRestoredTop := Top; - end; + if Data = 0 then + begin + FRestoredLeft := Left; + FRestoredTop := Top; + end + else + begin + FRestoredWidth := Width; + FRestoredHeight := Height; + DoOnResize; + end; + DoOnChangeBounds; + end; + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + Activate; + end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -1016,6 +957,9 @@ ------------------------------------------------------------------------------} procedure TCustomForm.DoShow; begin + if FIsFirstOnShow and (WindowState = wsMaximized) then + Exit; + FIsFirstOnShow := False; if Assigned(FOnShow) then FOnShow(Self); end; @@ -1338,7 +1282,7 @@ AForm := TCustomForm(Owner) else AForm := Application.MainForm; - if (Self <> AForm) then + if (Self <> AForm) and Assigned(AForm) then begin if FormStyle = fsMDIChild then begin @@ -1487,18 +1431,6 @@ Result := (Color <> {$ifdef UseCLDefault}clDefault{$else}clBtnFace{$endif}); end; -procedure TCustomForm.DoSendBoundsToInterface; -begin - inherited DoSendBoundsToInterface; - if WindowState = wsNormal then - begin - FRestoredLeft := Left; - FRestoredTop := Top; - FRestoredWidth := Width; - FRestoredHeight := Height; - end; -end; - procedure TCustomForm.GetPreferredSize(var PreferredWidth, PreferredHeight: integer; Raw: boolean; WithThemeSpace: boolean); begin @@ -1851,9 +1783,6 @@ TCustomForm SetWindowState ------------------------------------------------------------------------------} procedure TCustomForm.SetWindowState(Value : TWindowState); -const - ShowCommands: array[TWindowState] of Integer = - (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_SHOWFULLSCREEN); begin if FWindowState <> Value then begin @@ -1864,7 +1793,8 @@ end; end; -procedure TCustomForm.SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer); +procedure TCustomForm.SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer; + const ADefaultPosition: Boolean); var prevWindowState: TWindowState; begin @@ -1874,7 +1804,14 @@ prevWindowState := WindowState; WindowState := wsNormal; SetBounds(ALeft, ATop, AWidth, AHeight); + // override + if ADefaultPosition then + MoveToDefaultPosition; WindowState := prevWindowState; + FRestoredLeft := Left; + FRestoredTop := Top; + FRestoredWidth := Width; + FRestoredHeight := Height; end; procedure TCustomForm.SetScaled(const AScaled: Boolean); @@ -2047,6 +1984,9 @@ ------------------------------------------------------------------------------} constructor TCustomForm.Create(AOwner: TComponent); begin + FMovedCtr := 0; + FIsFirstOnShow := True; + FIsFirstOnActivate := True; GlobalNameSpace.BeginWrite; try CreateNew(AOwner, 1); // this calls BeginFormUpdate, which is ended in AfterConstruction @@ -2328,6 +2268,9 @@ Width, MulDiv(Width, Monitor.PixelsPerInch, PixelsPerInch)); Visible := True; + { wxMaximized secondary forms are not being shown maximized } + if (not (csDesigning in ComponentState)) and Showing then + ShowWindow(Handle, ShowCommands[WindowState]); BringToFront; end; |
|
Updated the patch (v2) with the following fixes: - because the queued procedure is shared between WMMove and WMSize events, an event is sometimes missed because duplicate calls are discarded. tform-wrong-bounds-and-restored-bounds-v2.patch (10,758 bytes)
--- lcl/forms.pp +++ lcl/forms.pp @@ -490,6 +490,9 @@ FRestoredHeight: integer; FShowInTaskbar: TShowInTaskbar; FWindowState: TWindowState; + FDelayedEventCtr: Integer; + FDelayedWMMove, FDelayedWMSize: Boolean; + FIsFirstOnShow, FIsFirstOnActivate: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; function GetMonitor: TMonitor; @@ -499,7 +502,7 @@ procedure CloseModal; procedure FreeIconHandles; procedure IconChanged(Sender: TObject); - procedure Moved(Data: PtrInt); + procedure DelayedEvent(Data: PtrInt); procedure SetActive(AValue: Boolean); procedure SetActiveControl(AWinControl: TWinControl); procedure SetActiveDefaultControl(AControl: TControl); @@ -590,7 +593,6 @@ procedure VisibleChanged; override; procedure WndProc(var TheMessage : TLMessage); override; function VisibleIsStored: boolean; - procedure DoSendBoundsToInterface; override; procedure DoAutoSize; override; procedure SetAutoSize(Value: Boolean); override; procedure SetAutoScroll(Value: Boolean); override; @@ -649,7 +651,8 @@ function CanFocus: Boolean; override; procedure SetFocus; override; function SetFocusedControl(Control: TWinControl): Boolean ; virtual; - procedure SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer); + procedure SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer; const + ADefaultPosition: Boolean = False); procedure Show; function ShowModal: Integer; virtual; --- lcl/include/customform.inc +++ lcl/include/customform.inc @@ -16,6 +16,8 @@ const BorderStylesAllowAutoScroll = [bsSizeable, bsSizeToolWin]; + ShowCommands: array[TWindowState] of Integer = + (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_SHOWFULLSCREEN); { TCustomForm } @@ -68,93 +70,10 @@ Gets called after the construction of the object ------------------------------------------------------------------------------} procedure TCustomForm.AfterConstruction; -var - NewWidth, NewHeight: Integer; - OldWindowState: TWindowState; - - procedure ChangeFormDimensions(AIsBeforeOnCreate: Boolean); - begin - if (WindowState = wsMaximized) and (FormStyle <> fsMDIChild) then - begin - {$IFDEF DEBUG_SM_LCLMAXIMIZED} - DebugLn('TCustomForm.AfterConstruction: SM_CYCAPTION ', - dbgs(GetSystemMetrics(SM_CYCAPTION)), - ' SM_CYSIZEFRAME ',dbgs(GetSystemMetrics(SM_CYSIZEFRAME)), - ' SM_CXMAXIMIZED ',dbgs(GetSystemMetrics(SM_CXMAXIMIZED)), - ' SM_CYMAXIMIZED ',dbgs(GetSystemMetrics(SM_CYMAXIMIZED)), - ' SM_LCLMAXIMIZEDHEIGHT ',dbgs(GetSystemMetrics(SM_LCLMAXIMIZEDHEIGHT)), - ' SM_LCLMAXIMIZEDWIDTH ',dbgs(GetSystemMetrics(SM_LCLMAXIMIZEDWIDTH)), - ' AIsBeforeOnCreate ',dbgs(AIsBeforeOnCreate)); - {$ENDIF} - - if (BorderStyle <> bsNone) and (FormStyle <> fsSplash) then - begin - NewHeight := GetSystemMetrics(SM_LCLMAXIMIZEDHEIGHT); - NewWidth := GetSystemMetrics(SM_LCLMAXIMIZEDWIDTH); - // if some ws does not implement this then provide normal metrics. - if NewHeight <= 0 then - NewHeight := GetSystemMetrics(SM_CYMAXIMIZED); - if NewWidth <= 0 then - NewHeight := GetSystemMetrics(SM_CXMAXIMIZED); - end else - begin - NewHeight := GetSystemMetrics(SM_CYMAXIMIZED); - NewWidth := GetSystemMetrics(SM_CXMAXIMIZED); - end; - - if Constraints.MaxWidth > 0 then - NewWidth := Min(Constraints.MaxWidth, NewWidth); - if Constraints.MaxHeight > 0 then - NewHeight := Min(Constraints.MaxHeight, NewHeight); - - // for unknown reasons on some systems SM_*MAXIMIZED* system metrics - // (tested xubuntu,64bits) return 0 or negative values, in this case - // a maximized window is expected to have at least WorkArea width/height. - // - // Reproduced again under Debian Wheezy. - // mistery solved, it ocurrs under gtk2/64-bit, fixed at the place - // the checks doesn't hurt though - // - // see bug #21634 - if NewWidth<=0 then - NewWidth := Screen.WorkAreaWidth; - if NewHeight<=0 then - NewHeight := Screen.WorkAreaHeight; - - if NewWidth>0 then - Width := NewWidth; - if NewHeight>0 then - Height := NewHeight; - end; - - if (WindowState = wsFullScreen) and (FormStyle <> fsMDIChild) then - begin - NewWidth := LCLIntf.GetSystemMetrics(SM_CXFULLSCREEN); - NewHeight := LCLIntf.GetSystemMetrics(SM_CYFULLSCREEN); - if Constraints.MaxWidth > 0 then - NewWidth := Min(Constraints.MaxWidth, NewWidth); - if Constraints.MaxHeight > 0 then - NewHeight := Min(Constraints.MaxHeight, NewHeight); - Width := NewWidth; - Height := NewHeight; - end; - end; -begin - // issue #21119, prepare maximized or fullscreen form to accurate dimensions. - // we avoid flickering also in this case. - if not (csDesigning in ComponentState) then - ChangeFormDimensions(True); - - OldWindowState := WindowState; +begin + SetRestoredBounds(Left, Top, Width, Height, True); + DoCreate; - - // if we change WindowState in constructor and handle isn't allocated - // then change our dimensions to accurate one - if not (csDesigning in ComponentState) and not HandleAllocated and - (OldWindowState <> WindowState) and - not (OldWindowState in [wsMaximized, wsFullScreen]) and - (WindowState in [wsMaximized, wsFullScreen]) then - ChangeFormDimensions(False); EndFormUpdate; // the BeginFormUpdate is in CreateNew inherited AfterConstruction; @@ -677,6 +596,9 @@ ------------------------------------------------------------------------------} procedure TCustomForm.Activate; begin + if FIsFirstOnActivate and (WindowState = wsMaximized) then + Exit; + FIsFirstOnActivate := False; if Assigned(FOnActivate) then FOnActivate(Self); end; @@ -733,27 +655,55 @@ inherited WMSize(Message); - if (Message.SizeType and not SIZE_SourceIsInterface) = SIZE_RESTORED then - begin - FRestoredWidth := Width; - FRestoredHeight := Height; - //DebugLn('[TCustomForm.WMSize] saving restored bounds ',DbgSName(Self),' ',dbgs(FRestoredWidth),'x',dbgs(FRestoredHeight)); - end; + FDelayedWMSize := True; + Inc(FDelayedEventCtr); + Application.QueueAsyncCall(@DelayedEvent, 0); end; procedure TCustomForm.WMMove(var Message: TLMMove); begin inherited WMMove(Message); - Application.QueueAsyncCall(@Moved, 0); -end; - -procedure TCustomForm.Moved(Data: PtrInt); -begin + + FDelayedWMMove := True; + Inc(FDelayedEventCtr); + Application.QueueAsyncCall(@DelayedEvent, 0); +end; + +procedure TCustomForm.DelayedEvent(Data: PtrInt); +begin + { discard duplicate calls, accept last call only } + Dec(FDelayedEventCtr); + if FDelayedEventCtr > 0 then + Exit; + { update restored bounds } if WindowState = wsNormal then - begin - FRestoredLeft := Left; - FRestoredTop := Top; - end; + begin + if FDelayedWMMove then + begin + FRestoredLeft := Left; + FRestoredTop := Top; + end; + if FDelayedWMSize then + begin + FRestoredWidth := Width; + FRestoredHeight := Height; + DoOnResize; // delayed onResize() + end; + DoOnChangeBounds; // delayed onChangeBounds() + end; + FDelayedWMMove := False; + FDelayedWMSize := False; + { call onShow() or onActivate() for the first time } + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + Activate; + end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -1016,6 +966,9 @@ ------------------------------------------------------------------------------} procedure TCustomForm.DoShow; begin + if FIsFirstOnShow and (WindowState = wsMaximized) then + Exit; + FIsFirstOnShow := False; if Assigned(FOnShow) then FOnShow(Self); end; @@ -1338,7 +1291,7 @@ AForm := TCustomForm(Owner) else AForm := Application.MainForm; - if (Self <> AForm) then + if (Self <> AForm) and Assigned(AForm) then begin if FormStyle = fsMDIChild then begin @@ -1487,18 +1440,6 @@ Result := (Color <> {$ifdef UseCLDefault}clDefault{$else}clBtnFace{$endif}); end; -procedure TCustomForm.DoSendBoundsToInterface; -begin - inherited DoSendBoundsToInterface; - if WindowState = wsNormal then - begin - FRestoredLeft := Left; - FRestoredTop := Top; - FRestoredWidth := Width; - FRestoredHeight := Height; - end; -end; - procedure TCustomForm.GetPreferredSize(var PreferredWidth, PreferredHeight: integer; Raw: boolean; WithThemeSpace: boolean); begin @@ -1851,9 +1792,6 @@ TCustomForm SetWindowState ------------------------------------------------------------------------------} procedure TCustomForm.SetWindowState(Value : TWindowState); -const - ShowCommands: array[TWindowState] of Integer = - (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_SHOWFULLSCREEN); begin if FWindowState <> Value then begin @@ -1864,7 +1802,8 @@ end; end; -procedure TCustomForm.SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer); +procedure TCustomForm.SetRestoredBounds(ALeft, ATop, AWidth, AHeight: integer; + const ADefaultPosition: Boolean); var prevWindowState: TWindowState; begin @@ -1874,7 +1813,14 @@ prevWindowState := WindowState; WindowState := wsNormal; SetBounds(ALeft, ATop, AWidth, AHeight); + // override + if ADefaultPosition then + MoveToDefaultPosition; WindowState := prevWindowState; + FRestoredLeft := Left; + FRestoredTop := Top; + FRestoredWidth := Width; + FRestoredHeight := Height; end; procedure TCustomForm.SetScaled(const AScaled: Boolean); @@ -2047,6 +1993,11 @@ ------------------------------------------------------------------------------} constructor TCustomForm.Create(AOwner: TComponent); begin + FDelayedEventCtr := 0; + FDelayedWMMove := False; + FDelayedWMSize := False; + FIsFirstOnShow := True; + FIsFirstOnActivate := True; GlobalNameSpace.BeginWrite; try CreateNew(AOwner, 1); // this calls BeginFormUpdate, which is ended in AfterConstruction @@ -2328,6 +2279,9 @@ Width, MulDiv(Width, Monitor.PixelsPerInch, PixelsPerInch)); Visible := True; + { wxMaximized secondary forms are not being shown maximized } + if (not (csDesigning in ComponentState)) and Showing then + ShowWindow(Handle, ShowCommands[WindowState]); BringToFront; end; |
|
Interesting! How many of the related issues this would fix? I think this should be applied and tested in trunk. |
|
I applied the patch in r61997 for everybody to test. Let's see if somebody finds bugs in it. |
|
delayedevent-wait-for-wmsize-before-onshow-onactivate.patch (922 bytes)
--- lcl/include/customform.inc +++ lcl/include/customform.inc @@ -691,19 +691,22 @@ end; DoOnChangeBounds; // delayed onChangeBounds() end; + { call onShow() or onActivate() for the first time, after first WMSize } + if FDelayedWMSize then + begin + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + Activate; + end; + end; FDelayedWMMove := False; FDelayedWMSize := False; - { call onShow() or onActivate() for the first time } - if FIsFirstOnShow then - begin - FIsFirstOnShow := False; - DoShow; - end; - if FIsFirstOnActivate then - begin - FIsFirstOnActivate := False; - Activate; - end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); |
|
Another one :) GTK2 only: When a form is designed so as part of it is clipped off the screen, and WindowState=wsMaximized, width and height during onShow()/onActivate() is wrong. Reason: After creation (?), the window manager automatically moves the form so that the whole form is visible. This will trigger WMMove() events, thus triggering the delayed onShow()/onActivate() even before the form is maxmimized. Solution is to wait for the first WMSize() before triggering onShow()/onActivate(). Apply patch after the v2 patch. |
|
I applied the new patch in r62113. Thanks. Please test everybody. |
|
Resolving. Thank you Joeny Ang for the patches. |
|
At least it breaks the usage of SpartaDockedFormEditor. After revision 61997 it isn't possible to change the bounds of a form anymore. Too bad, just Windows seems to be affected. Just tried GTK2 and QT, both are working fine. I'll try to look at it. |
|
I fixed the problem with SpartaDockedFormEditor in revision 63218 |
|
I have to reopen the issue. I could fix one problem with SpartaDockedFormEditor, but there is a other one, what can't be fixed there. If there are more than one form opened and resized, the frame got corrupted. Before I can search for the problem, one main problem has to be fixed: After the revision 61997, OnChangeBounds of a form is called twice. See added project TestChangeBoundsEvent.zip. (tested on Windows 7) |
|
Changes made by this patch: - fixed sequence of events (based on Delphi 3... create, show, activate, resize) - OnResize() and OnChangeBounds() are being called twice :: moved code queueing delayed events to overriden DoOnResize() and DoOnChangeBounds() - removed TCustomForm.WMMove() - added check for wsFullScreen in TCustomForm.Activate() and TCustomForm.DoShow() - renamed some variables fix-duplicate-onresize-onchangebounds.patch (4,523 bytes)
--- lcl/forms.pp +++ lcl/forms.pp @@ -491,7 +491,7 @@ FShowInTaskbar: TShowInTaskbar; FWindowState: TWindowState; FDelayedEventCtr: Integer; - FDelayedWMMove, FDelayedWMSize: Boolean; + FDelayedOnChangeBounds, FDelayedOnResize: Boolean; FIsFirstOnShow, FIsFirstOnActivate: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; @@ -535,7 +535,6 @@ procedure WMActivate(var Message : TLMActivate); message LM_ACTIVATE; procedure WMCloseQuery(var message: TLMessage); message LM_CLOSEQUERY; procedure WMHelp(var Message: TLMHelp); message LM_HELP; - procedure WMMove(var Message: TLMMove); message LM_MOVE; procedure WMShowWindow(var message: TLMShowWindow); message LM_SHOWWINDOW; procedure WMSize(var message: TLMSize); message LM_Size; procedure WMWindowPosChanged(var Message: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED; @@ -581,6 +580,8 @@ procedure Resizing(State: TWindowState); override; procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); override; + procedure DoOnResize; override; + procedure DoOnChangeBounds; override; procedure SetZOrder(Topmost: Boolean); override; procedure SetParent(NewParent: TWinControl); override; procedure MoveToDefaultPosition; virtual; --- lcl/include/customform.inc +++ lcl/include/customform.inc @@ -604,7 +604,7 @@ ------------------------------------------------------------------------------} procedure TCustomForm.Activate; begin - if FIsFirstOnActivate and (WindowState = wsMaximized) then + if FIsFirstOnActivate and (WindowState in [wsMaximized, wsFullScreen]) then Exit; FIsFirstOnActivate := False; if Assigned(FOnActivate) then FOnActivate(Self); @@ -662,22 +662,23 @@ end; inherited WMSize(Message); - +end; + +procedure TCustomForm.DoOnResize; +begin if not (csDestroying in ComponentState) then begin - FDelayedWMSize := True; + FDelayedOnResize := True; Inc(FDelayedEventCtr); Application.QueueAsyncCall(@DelayedEvent, 0); end; end; -procedure TCustomForm.WMMove(var Message: TLMMove); -begin - inherited WMMove(Message); - +procedure TCustomForm.DoOnChangeBounds; +begin if not (csDestroying in ComponentState) then begin - FDelayedWMMove := True; + FDelayedOnChangeBounds := True; Inc(FDelayedEventCtr); Application.QueueAsyncCall(@DelayedEvent, 0); end; @@ -692,21 +693,20 @@ { update restored bounds } if WindowState = wsNormal then begin - if FDelayedWMMove then + if FDelayedOnChangeBounds then begin FRestoredLeft := Left; FRestoredTop := Top; end; - if FDelayedWMSize then + if FDelayedOnResize then begin FRestoredWidth := Width; FRestoredHeight := Height; - DoOnResize; // delayed onResize() end; - DoOnChangeBounds; // delayed onChangeBounds() - end; - { call onShow() or onActivate() for the first time, after first WMSize } - if FDelayedWMSize then + end; + { call onShow() or onActivate() for the first time, after first OnResize() + and OnChangeBounds() } + if FDelayedOnResize and FDelayedOnChangeBounds then begin if FIsFirstOnShow then begin @@ -720,8 +720,14 @@ Activate; end; end; - FDelayedWMMove := False; - FDelayedWMSize := False; + { delayed onResize() } + if FDelayedOnResize then + inherited DoOnResize; + { delayed onChangeBounds() } + if FDelayedOnResize or FDelayedOnChangeBounds then + inherited DoOnChangeBounds; + FDelayedOnChangeBounds := False; + FDelayedOnResize := False; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -992,7 +998,7 @@ ------------------------------------------------------------------------------} procedure TCustomForm.DoShow; begin - if FIsFirstOnShow and (WindowState = wsMaximized) then + if FIsFirstOnShow and (WindowState in [wsMaximized, wsFullScreen]) then Exit; FIsFirstOnShow := False; if Assigned(FOnShow) then FOnShow(Self); @@ -2020,8 +2026,8 @@ constructor TCustomForm.Create(AOwner: TComponent); begin FDelayedEventCtr := 0; - FDelayedWMMove := False; - FDelayedWMSize := False; + FDelayedOnChangeBounds := False; + FDelayedOnResize := False; FIsFirstOnShow := True; FIsFirstOnActivate := True; GlobalNameSpace.BeginWrite; |
|
Thanks for the patch. I applied it in r63577. Michl and others, please test. |
|
No complaints. I guess this is fixed now. Resolving... |
|
r63577 caused a regression, see the related issue 0037467. How to fix it? |
|
In my trunk I reverted to r62745. Reason : Unit2.Form2 of example has Position = poMainFormCenter. I would expect that when restoring Form2 from initial wsMaximized to wsNomal the first time, it would place form2 at poMainFormCenter. Afterwards, the new position of the modal form2 goes tracks the the last size/position. Failing event FormResize beeing tracked is no good. Also avoiding excessive messages in DelayedEvent seems reasonabéy neat in its currrent state. |
|
How is r62745 related to this one? It says: "LCL: implement MDI for win32. Issue 36582, based on patch by Kostas Michalopoulos, attempt 2" |
|
Juha: https://bugs.freepascal.org/view.php?id=37647 |
|
@Juha Manninen 2020-08-26 21:45 I picked up the lcl\forms.pp and lcl\include\customform.inc from r62745 and replaced the trunk r63577 version of these files in my installation. At r62745 these two files seem to be OK . Issue 0037467 does not show with this version. The logic of the various resizing events are a bit dispersed but still usable, I remember that in Delphi [ed. BDS 2007] BDS 2006 I had already difficulties figuring out how those things worked. Here after a modified Unit2 from TestChangeBoundsEvent.zip that gives a bit more information about how the related sizing events works. Also if you change the Position = poMainFormCenter to Position = poDesigned, form2 will show at the designed position. |
|
Another patch :) - if form is designed maximized or fullscreen, first restore will now honor Position property - setting WindowState property will now trigger onWindowStateChange() - win32: moving/resizing via mouse will now trigger onResize/onChangeBounds :: the async queue is not being processed while the mouse button is down - gtk2: switching (via code) between wsFullscreen and other states now works properly Tested: Widgetsets: Gtk2, Qt5, Win32 (WinXP) Window managers: Metacity, Mutter tform-wrong-bounds-and-restored-bounds-part4.patch (5,701 bytes)
--- lazarus/lcl/forms.pp.63838 +++ lazarus/lcl/forms.pp @@ -492,7 +492,7 @@ FWindowState: TWindowState; FDelayedEventCtr: Integer; FDelayedOnChangeBounds, FDelayedOnResize: Boolean; - FIsFirstOnShow, FIsFirstOnActivate: Boolean; + FIsFirstOnShow, FIsFirstOnActivate, FIsFirstRestore: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; function GetMonitor: TMonitor; --- lazarus/lcl/include/customform.inc.63838 +++ lazarus/lcl/include/customform.inc @@ -692,42 +692,45 @@ Exit; { update restored bounds } if WindowState = wsNormal then - begin - if FDelayedOnChangeBounds then - begin - FRestoredLeft := Left; - FRestoredTop := Top; - end; - if FDelayedOnResize then - begin - FRestoredWidth := Width; - FRestoredHeight := Height; - end; - end; + begin + if FDelayedOnChangeBounds then + begin + FRestoredLeft := Left; + FRestoredTop := Top; + end; + if FDelayedOnResize then + begin + FRestoredWidth := Width; + FRestoredHeight := Height; + end; + end; { call onShow() or onActivate() for the first time, after first OnResize() and OnChangeBounds() } if FDelayedOnResize and FDelayedOnChangeBounds then - begin - if FIsFirstOnShow then - begin - FIsFirstOnShow := False; - DoShow; - end; - if FIsFirstOnActivate then - begin - FIsFirstOnActivate := False; - if FActive then - Activate; - end; - end; - { delayed onResize() } - if FDelayedOnResize then - inherited DoOnResize; - { delayed onChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then - inherited DoOnChangeBounds; - FDelayedOnChangeBounds := False; - FDelayedOnResize := False; + begin + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + if FActive then + Activate; + end; + end; + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + { delayed onResize() } + if FDelayedOnResize then + inherited DoOnResize; + { delayed onChangeBounds() } + if FDelayedOnResize or FDelayedOnChangeBounds then + inherited DoOnChangeBounds; + FDelayedOnChangeBounds := False; + FDelayedOnResize := False; + end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -1001,6 +1004,7 @@ if FIsFirstOnShow and (WindowState in [wsMaximized, wsFullScreen]) then Exit; FIsFirstOnShow := False; + FIsFirstRestore := WindowState in [wsMaximized, wsFullScreen]; if Assigned(FOnShow) then FOnShow(Self); end; @@ -1139,17 +1143,15 @@ if Showing and not (csDesigning in ComponentState) then begin OldState := FWindowState; - FWindowState := State; if OldState <> State then begin + WindowState := State; if (State = wsMinimized) and (Application.MainForm = Self) and (WidgetSet.GetLCLCapability(lcNeedMininimizeAppWithMainForm) <> LCL_CAPABILITY_NO) then Application.Minimize; if (OldState = wsMinimized) and (Application.MainForm = Self) and (WidgetSet.GetLCLCapability(lcNeedMininimizeAppWithMainForm) <> LCL_CAPABILITY_NO) then Application.Restore; - if Assigned(OnWindowStateChange) then - OnWindowStateChange(Self); end; end; end; @@ -1830,7 +1832,19 @@ FWindowState := Value; //DebugLn(['TCustomForm.SetWindowState ',DbgSName(Self),' ',ord(FWindowState),' csDesigning=',csDesigning in ComponentState,' Showing=',Showing]); if (not (csDesigning in ComponentState)) and Showing then + begin ShowWindow(Handle, ShowCommands[Value]); + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + if FIsFirstRestore then + begin + MoveToDefaultPosition; + FIsFirstRestore := False; + end; + if Assigned(OnWindowStateChange) then + OnWindowStateChange(Self); + end; + end; end; end; @@ -2030,6 +2044,7 @@ FDelayedOnResize := False; FIsFirstOnShow := True; FIsFirstOnActivate := True; + FIsFirstRestore := False; GlobalNameSpace.BeginWrite; try CreateNew(AOwner, 1); // this calls BeginFormUpdate, which is ended in AfterConstruction --- lcl/interfaces/win32/win32callback.inc.63838 +++ lcl/interfaces/win32/win32callback.inc @@ -15,6 +15,7 @@ {$ENDIF} type TWinControlAccess = class(TWinControl); + TApplicationAccess = class(TApplication); {*************************************************************} { callback routines } {*************************************************************} @@ -2054,6 +2055,8 @@ begin CheckSynchronize; TWin32Widgetset(Widgetset).CheckPipeEvents; + if Assigned(Application) then + TApplicationAccess(Application).ProcessAsyncCallQueue; end; WM_ENTERIDLE: Application.Idle(False); WM_ACTIVATE: SetLMessageAndParams(LM_ACTIVATE); --- lcl/interfaces/gtk2/gtk2callback.inc.63838 +++ lcl/interfaces/gtk2/gtk2callback.inc @@ -1121,6 +1121,8 @@ {$ENDIF} SizeMsg.SizeType := SIZE_MINIMIZED; end + else if (GDK_WINDOW_STATE_FULLSCREEN and state^.new_window_state)>0 then + SizeMsg.SizeType := SIZE_FULLSCREEN else if (GDK_WINDOW_STATE_MAXIMIZED and state^.new_window_state)>0 then begin // it can be both maximized + iconified and just loose iconified state |
|
Oooppss... updated the patch. :) tform-wrong-bounds-and-restored-bounds-part4v2.patch (5,669 bytes)
--- lcl/forms.pp.63838 +++ lcl/forms.pp @@ -492,7 +492,7 @@ FWindowState: TWindowState; FDelayedEventCtr: Integer; FDelayedOnChangeBounds, FDelayedOnResize: Boolean; - FIsFirstOnShow, FIsFirstOnActivate: Boolean; + FIsFirstOnShow, FIsFirstOnActivate, FIsFirstRestore: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; function GetMonitor: TMonitor; --- lcl/include/customform.inc.63838 +++ lcl/include/customform.inc @@ -692,42 +692,45 @@ Exit; { update restored bounds } if WindowState = wsNormal then - begin - if FDelayedOnChangeBounds then - begin - FRestoredLeft := Left; - FRestoredTop := Top; - end; - if FDelayedOnResize then - begin - FRestoredWidth := Width; - FRestoredHeight := Height; - end; - end; + begin + if FDelayedOnChangeBounds then + begin + FRestoredLeft := Left; + FRestoredTop := Top; + end; + if FDelayedOnResize then + begin + FRestoredWidth := Width; + FRestoredHeight := Height; + end; + end; { call onShow() or onActivate() for the first time, after first OnResize() and OnChangeBounds() } if FDelayedOnResize and FDelayedOnChangeBounds then - begin - if FIsFirstOnShow then - begin - FIsFirstOnShow := False; - DoShow; - end; - if FIsFirstOnActivate then - begin - FIsFirstOnActivate := False; - if FActive then - Activate; - end; - end; - { delayed onResize() } - if FDelayedOnResize then - inherited DoOnResize; - { delayed onChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then - inherited DoOnChangeBounds; - FDelayedOnChangeBounds := False; - FDelayedOnResize := False; + begin + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + if FActive then + Activate; + end; + end; + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + { delayed onResize() } + if FDelayedOnResize then + inherited DoOnResize; + { delayed onChangeBounds() } + if FDelayedOnResize or FDelayedOnChangeBounds then + inherited DoOnChangeBounds; + FDelayedOnChangeBounds := False; + FDelayedOnResize := False; + end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -1001,6 +1004,7 @@ if FIsFirstOnShow and (WindowState in [wsMaximized, wsFullScreen]) then Exit; FIsFirstOnShow := False; + FIsFirstRestore := WindowState in [wsMaximized, wsFullScreen]; if Assigned(FOnShow) then FOnShow(Self); end; @@ -1139,17 +1143,15 @@ if Showing and not (csDesigning in ComponentState) then begin OldState := FWindowState; - FWindowState := State; if OldState <> State then begin + WindowState := State; if (State = wsMinimized) and (Application.MainForm = Self) and (WidgetSet.GetLCLCapability(lcNeedMininimizeAppWithMainForm) <> LCL_CAPABILITY_NO) then Application.Minimize; if (OldState = wsMinimized) and (Application.MainForm = Self) and (WidgetSet.GetLCLCapability(lcNeedMininimizeAppWithMainForm) <> LCL_CAPABILITY_NO) then Application.Restore; - if Assigned(OnWindowStateChange) then - OnWindowStateChange(Self); end; end; end; @@ -1830,7 +1832,19 @@ FWindowState := Value; //DebugLn(['TCustomForm.SetWindowState ',DbgSName(Self),' ',ord(FWindowState),' csDesigning=',csDesigning in ComponentState,' Showing=',Showing]); if (not (csDesigning in ComponentState)) and Showing then + begin ShowWindow(Handle, ShowCommands[Value]); + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + if FIsFirstRestore then + begin + MoveToDefaultPosition; + FIsFirstRestore := False; + end; + if Assigned(OnWindowStateChange) then + OnWindowStateChange(Self); + end; + end; end; end; @@ -2030,6 +2044,7 @@ FDelayedOnResize := False; FIsFirstOnShow := True; FIsFirstOnActivate := True; + FIsFirstRestore := False; GlobalNameSpace.BeginWrite; try CreateNew(AOwner, 1); // this calls BeginFormUpdate, which is ended in AfterConstruction --- lcl/interfaces/win32/win32callback.inc.63838 +++ lcl/interfaces/win32/win32callback.inc @@ -15,6 +15,7 @@ {$ENDIF} type TWinControlAccess = class(TWinControl); + TApplicationAccess = class(TApplication); {*************************************************************} { callback routines } {*************************************************************} @@ -2054,6 +2055,8 @@ begin CheckSynchronize; TWin32Widgetset(Widgetset).CheckPipeEvents; + if Assigned(Application) then + TApplicationAccess(Application).ProcessAsyncCallQueue; end; WM_ENTERIDLE: Application.Idle(False); WM_ACTIVATE: SetLMessageAndParams(LM_ACTIVATE); --- lcl/interfaces/gtk2/gtk2callback.inc.63838 +++ lcl/interfaces/gtk2/gtk2callback.inc @@ -1121,6 +1121,8 @@ {$ENDIF} SizeMsg.SizeType := SIZE_MINIMIZED; end + else if (GDK_WINDOW_STATE_FULLSCREEN and state^.new_window_state)>0 then + SizeMsg.SizeType := SIZE_FULLSCREEN else if (GDK_WINDOW_STATE_MAXIMIZED and state^.new_window_state)>0 then begin // it can be both maximized + iconified and just loose iconified state |
|
I applied the latest patch in r63842. Thanks. Note: I split the unindent formatting part to another commit, r63843. Easier to figure out what happens. @BrunoK, you mean r62745 did not change the behavior? It was just a random pick. Please write here only about revisions that are relevant for this issue. We already have many revisions and many reports to deal with. No need to complicate it more. You can bisect guilty revisions. I recommend "git bisect" command for that. |
|
Juha Manninen 2020-08-29 16:46 I only meant : At r62745 these two files seem to be OK . Issue 0037467 does not show with this version. NOTHING MORE. I will test with at r63842 and report how it looks. |
|
ITs strange because I just tested a variety of versions here, not the trunk and they all work correctly ? So why all of this ? I too have Delphi 3 and they work exactly like D3 so like I said why ? |
|
This patch broke the Restore action https://bugs.freepascal.org/view.php?id=37732 |
|
r63842 caused a regression. I had to revert it. |
|
I reverted to \lcl\include\Forms.pp at r62745, \lcl\include\customform.inc at r62892. Attached patch on 63882 Reason : r63882 makes 0037467 still broken : Form Resize Not Firing Correctly and its attached demos. I have not critics about improving excessive messaging but think we should try, using Joeny Ang's ideas, to design a safer way to rework the code. We should consider what is Widget set dependent and what is pure /lcl and /lcl/include stuff. There has been recently quite a few issues in the bugtracker that I could not reproduce in Win10 2004 / 10.0.19041.508 (example > 0037706: [Regression] IDE extremely slow when adding a new control to a heavily populated form < ) so it is a bit difficult to understand what is going on. revert_form_200912.patch (7,604 bytes)
Index: lcl/forms.pp =================================================================== --- lcl/forms.pp (revision 63882) +++ lcl/forms.pp (working copy) @@ -491,7 +491,7 @@ FShowInTaskbar: TShowInTaskbar; FWindowState: TWindowState; FDelayedEventCtr: Integer; - FDelayedOnChangeBounds, FDelayedOnResize: Boolean; + FDelayedWMMove, FDelayedWMSize: Boolean; FIsFirstOnShow, FIsFirstOnActivate: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; @@ -535,6 +535,7 @@ procedure WMActivate(var Message : TLMActivate); message LM_ACTIVATE; procedure WMCloseQuery(var message: TLMessage); message LM_CLOSEQUERY; procedure WMHelp(var Message: TLMHelp); message LM_HELP; + procedure WMMove(var Message: TLMMove); message LM_MOVE; procedure WMShowWindow(var message: TLMShowWindow); message LM_SHOWWINDOW; procedure WMSize(var message: TLMSize); message LM_Size; procedure WMWindowPosChanged(var Message: TLMWindowPosChanged); message LM_WINDOWPOSCHANGED; @@ -580,8 +581,6 @@ procedure Resizing(State: TWindowState); override; procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); override; - procedure DoOnResize; override; - procedure DoOnChangeBounds; override; procedure SetZOrder(Topmost: Boolean); override; procedure SetParent(NewParent: TWinControl); override; procedure MoveToDefaultPosition; virtual; @@ -1192,7 +1191,7 @@ property Forms[Index: Integer]: TForm read GetForms; property DataModuleCount: Integer read GetDataModuleCount; property DataModules[Index: Integer]: TDataModule read GetDataModules; - + property HintFont: TFont read GetHintFont write SetHintFont; property IconFont: TFont read GetIconFont write SetIconFont; property MenuFont: TFont read GetMenuFont write SetMenuFont; Index: lcl/include/customform.inc =================================================================== --- lcl/include/customform.inc (revision 63882) +++ lcl/include/customform.inc (working copy) @@ -240,7 +240,7 @@ if Assigned(OldCancelControl) then OldCancelControl.UpdateRolesForForm; // notify new control - if Assigned(FCancelControl) then + if Assigned(FCancelControl) then begin FreeNotification(FCancelControl); FCancelControl.UpdateRolesForForm; @@ -604,7 +604,7 @@ ------------------------------------------------------------------------------} procedure TCustomForm.Activate; begin - if FIsFirstOnActivate and (WindowState in [wsMaximized, wsFullScreen]) then + if FIsFirstOnActivate and (WindowState = wsMaximized) then Exit; FIsFirstOnActivate := False; if Assigned(FOnActivate) then FOnActivate(Self); @@ -662,23 +662,22 @@ end; inherited WMSize(Message); -end; -procedure TCustomForm.DoOnResize; -begin if not (csDestroying in ComponentState) then begin - FDelayedOnResize := True; + FDelayedWMSize := True; Inc(FDelayedEventCtr); Application.QueueAsyncCall(@DelayedEvent, 0); end; end; -procedure TCustomForm.DoOnChangeBounds; +procedure TCustomForm.WMMove(var Message: TLMMove); begin + inherited WMMove(Message); + if not (csDestroying in ComponentState) then begin - FDelayedOnChangeBounds := True; + FDelayedWMMove := True; Inc(FDelayedEventCtr); Application.QueueAsyncCall(@DelayedEvent, 0); end; @@ -692,42 +691,37 @@ Exit; { update restored bounds } if WindowState = wsNormal then - begin - if FDelayedOnChangeBounds then begin - FRestoredLeft := Left; - FRestoredTop := Top; + if FDelayedWMMove then + begin + FRestoredLeft := Left; + FRestoredTop := Top; + end; + if FDelayedWMSize then + begin + FRestoredWidth := Width; + FRestoredHeight := Height; + DoOnResize; // delayed onResize() + end; + DoOnChangeBounds; // delayed onChangeBounds() end; - if FDelayedOnResize then + { call onShow() or onActivate() for the first time, after first WMSize } + if FDelayedWMSize then begin - FRestoredWidth := Width; - FRestoredHeight := Height; + if FIsFirstOnShow then + begin + FIsFirstOnShow := False; + DoShow; + end; + if FIsFirstOnActivate then + begin + FIsFirstOnActivate := False; + if FActive then + Activate; + end; end; - end; - { call onShow() or onActivate() for the first time, - after first OnResize() and OnChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then - begin - if FIsFirstOnShow then - begin - FIsFirstOnShow := False; - DoShow; - end; - if FIsFirstOnActivate then - begin - FIsFirstOnActivate := False; - if FActive then - Activate; - end; - end; - { delayed onResize() } - if FDelayedOnResize then - inherited DoOnResize; - { delayed onChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then - inherited DoOnChangeBounds; - FDelayedOnChangeBounds := False; - FDelayedOnResize := False; + FDelayedWMMove := False; + FDelayedWMSize := False; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -998,7 +992,7 @@ ------------------------------------------------------------------------------} procedure TCustomForm.DoShow; begin - if FIsFirstOnShow and (WindowState in [wsMaximized, wsFullScreen]) then + if FIsFirstOnShow and (WindowState = wsMaximized) then Exit; FIsFirstOnShow := False; if Assigned(FOnShow) then FOnShow(Self); @@ -1625,7 +1619,7 @@ end; Result := False; end; - + begin // don't execute action while designing or when form is not visible if (csDesigning in ComponentState) or not Visible then @@ -1634,9 +1628,9 @@ // assume it gets handled somewhere Result := True; if Assigned(ActiveControl) and ActiveControl.ExecuteAction(ExeAction) then Exit; - + if ExecuteAction(ExeAction) then Exit; - + if DoExecuteActionInChildControls(Self, ExeAction) then Exit; // not handled anywhere, return false @@ -1748,7 +1742,7 @@ Value := nil; FMenu := Value; - if FMenu <> nil then + if FMenu <> nil then begin FMenu.FreeNotification(Self); FMenu.Parent := Self; @@ -1790,7 +1784,7 @@ AdaptBorderIcons := not (csLoading in ComponentState) and (BorderIcons = DefaultBorderIcons[FFormBorderStyle]); FFormBorderStyle := NewStyle; - + if not (csDesigning in ComponentState) then begin // if Form had default border icons before change, it should keep the default @@ -1939,7 +1933,7 @@ begin if AValue = FAllowDropFiles then Exit; FAllowDropFiles := AValue; - + if HandleAllocated and not (csDesigning in ComponentState) then TWSCustomFormClass(WidgetSetClass).SetAllowDropFiles(Self, AValue); end; @@ -2026,8 +2020,8 @@ constructor TCustomForm.Create(AOwner: TComponent); begin FDelayedEventCtr := 0; - FDelayedOnChangeBounds := False; - FDelayedOnResize := False; + FDelayedWMMove := False; + FDelayedWMSize := False; FIsFirstOnShow := True; FIsFirstOnActivate := True; GlobalNameSpace.BeginWrite; @@ -2661,7 +2655,7 @@ procedure TCustomForm.IntfHelp(AComponent: TComponent); begin if csDesigning in ComponentState then exit; - + if AComponent is TControl then begin TControl(AComponent).ShowHelp; end else begin |
|
@BrunoK, did you test issue 0037732 with your patch? I will look at it later. |
|
@Juha Manninen > did you test issue 0037732 with your patch? Tested 0037732 on Win 10 64 / PFC 3.0.4 i386/win32. Works for me. My patch is a revert to a reasonable stable state so we can reassert what and where something should be done. Note that 0037467 does show (in debug mode) some duplicates OnResize but the problem demo is maybe not optimally written. |
|
Hi all :) Updated the last patch: - Issue 0037732 was caused by the attempt to fix onWindowStateChange() not triggering when setting WindowState via code. This is now fixed. - Fixed code to honor Position property on first restore when form was designed maximized. - Tweaked DelayedEvent() for QT5 sometimes triggering onChangeBounds() twice on first show. Patched against r63882 tform-wrong-bounds-and-restored-bounds-part4-fix.patch (5,616 bytes)
--- lcl/forms.pp.63882 +++ lcl/forms.pp @@ -493,6 +493,7 @@ FDelayedEventCtr: Integer; FDelayedOnChangeBounds, FDelayedOnResize: Boolean; FIsFirstOnShow, FIsFirstOnActivate: Boolean; + FIsFirstRestore, FWindowStateChanged: Boolean; function GetClientHandle: HWND; function GetEffectiveShowInTaskBar: TShowInTaskBar; function GetMonitor: TMonitor; --- lcl/include/customform.inc.63882 +++ lcl/include/customform.inc @@ -706,7 +706,7 @@ end; { call onShow() or onActivate() for the first time, after first OnResize() and OnChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then + if FDelayedOnResize and FDelayedOnChangeBounds and FActive then begin if FIsFirstOnShow then begin @@ -716,18 +716,20 @@ if FIsFirstOnActivate then begin FIsFirstOnActivate := False; - if FActive then - Activate; - end; - end; - { delayed onResize() } - if FDelayedOnResize then - inherited DoOnResize; - { delayed onChangeBounds() } - if FDelayedOnResize or FDelayedOnChangeBounds then - inherited DoOnChangeBounds; - FDelayedOnChangeBounds := False; - FDelayedOnResize := False; + Activate; + end; + end; + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + { delayed onResize() } + if FDelayedOnResize then + inherited DoOnResize; + { delayed onChangeBounds() } + if FDelayedOnResize or FDelayedOnChangeBounds then + inherited DoOnChangeBounds; + FDelayedOnChangeBounds := False; + FDelayedOnResize := False; + end; end; procedure TCustomForm.WMWindowPosChanged(var Message: TLMWindowPosChanged); @@ -1001,6 +1003,7 @@ if FIsFirstOnShow and (WindowState in [wsMaximized, wsFullScreen]) then Exit; FIsFirstOnShow := False; + FIsFirstRestore := WindowState in [wsMaximized, wsFullScreen]; if Assigned(FOnShow) then FOnShow(Self); end; @@ -1148,8 +1151,28 @@ if (OldState = wsMinimized) and (Application.MainForm = Self) and (WidgetSet.GetLCLCapability(lcNeedMininimizeAppWithMainForm) <> LCL_CAPABILITY_NO) then Application.Restore; - if Assigned(OnWindowStateChange) then - OnWindowStateChange(Self); + end; + + if (OldState <> State) or FWindowStateChanged then + begin + { honor Position property on first restore when form was designed maximized } + if not (FIsFirstOnShow or FIsFirstOnActivate) then + begin + if FIsFirstRestore and (State = wsNormal) then + begin + { Need to check width/height before calling MoveToDefaultPosition. + QT5 triggers Resizing() twice: one for position change, and + another for size change. This check should not affect other + widgetsets. } + if (Width <> RestoredWidth) or (Height <> RestoredHeight) then + Exit; + MoveToDefaultPosition; + FIsFirstRestore := False; + end; + if Assigned(OnWindowStateChange) then + OnWindowStateChange(Self); + end; + FWindowStateChanged := False; end; end; end; @@ -1830,7 +1853,10 @@ FWindowState := Value; //DebugLn(['TCustomForm.SetWindowState ',DbgSName(Self),' ',ord(FWindowState),' csDesigning=',csDesigning in ComponentState,' Showing=',Showing]); if (not (csDesigning in ComponentState)) and Showing then + begin + FWindowStateChanged := True; ShowWindow(Handle, ShowCommands[Value]); + end; end; end; @@ -2030,6 +2056,8 @@ FDelayedOnResize := False; FIsFirstOnShow := True; FIsFirstOnActivate := True; + FIsFirstRestore := False; + FWindowStateChanged := False; GlobalNameSpace.BeginWrite; try CreateNew(AOwner, 1); // this calls BeginFormUpdate, which is ended in AfterConstruction --- lcl/interfaces/gtk2/gtk2callback.inc.63882 +++ lcl/interfaces/gtk2/gtk2callback.inc @@ -1121,6 +1121,8 @@ {$ENDIF} SizeMsg.SizeType := SIZE_MINIMIZED; end + else if (GDK_WINDOW_STATE_FULLSCREEN and state^.new_window_state)>0 then + SizeMsg.SizeType := SIZE_FULLSCREEN else if (GDK_WINDOW_STATE_MAXIMIZED and state^.new_window_state)>0 then begin // it can be both maximized + iconified and just loose iconified state @@ -1133,7 +1135,8 @@ // don't bother the LCL if nothing changed case SizeMsg.SizeType of SIZE_RESTORED: if TheForm.WindowState=wsNormal then exit; - SIZE_MINIMIZED: if TheForm.WindowState=wsMinimized then exit; + // Need to send LM_SIZE message to LCL if wsMinimized to trigger onWindowStateChange() + //SIZE_MINIMIZED: if TheForm.WindowState=wsMinimized then exit; SIZE_MAXIMIZED: if TheForm.WindowState=wsMaximized then exit; SIZE_FULLSCREEN: if TheForm.WindowState=wsFullScreen then exit; end; --- lcl/interfaces/win32/win32callback.inc.63882 +++ lcl/interfaces/win32/win32callback.inc @@ -15,6 +15,7 @@ {$ENDIF} type TWinControlAccess = class(TWinControl); + TApplicationAccess = class(TApplication); {*************************************************************} { callback routines } {*************************************************************} @@ -2054,6 +2055,8 @@ begin CheckSynchronize; TWin32Widgetset(Widgetset).CheckPipeEvents; + if Assigned(Application) then + TApplicationAccess(Application).ProcessAsyncCallQueue; end; WM_ENTERIDLE: Application.Idle(False); WM_ACTIVATE: SetLMessageAndParams(LM_ACTIVATE); |
|
Sorry for the delay. I had other stuff going on. In r63888 I applied the latest patch from Joeny Ang with one important change. In customform.inc the patch has : + if FDelayedOnResize and FDelayedOnChangeBounds and FActive then which reverts my fix for issue 0037647 (after lots of debugging :) . I changed it to : + if (FDelayedOnResize or FDelayedOnChangeBounds) and FActive then Everybody please test and verify it works. If it works then I would like to resolve this issue ASAP. It is getting long and difficult to follow with all the revisions involved. New related issues can have their own reports. |
|
Thanks for the fix |
|
Hi Just tested Rev 63888. it has fixed that the form.resize is being fired. form.OnResize appears now not to be re-entrent, if you run the attached test with rev 63888, and compare against rev 63556, you will see some big differneces in the time my re-size take to complete. The attached project; now keeps track of how many time the on-reize is called when it is allready in the re-size code. rev 63556 (resizing the form via the corner tab, slowly upto full screen and back again) Use processmessages re-entrant called 48 times, max time in code 94ms average time in resize code 20ms use ProcessMessages and Begin/End Update Re-entrent 88, max 94 avg 13 Use Begin/Endupdate Re-entrant 0, Max 16, Avg 3. use None Re-Entrant 0, Max 31, AVg 5 rev 63888 Use processmessages re-entrant called 0, max time in code 344ms average time in resize code 141ms use ProcessMessages and Begin/End Update Re-entrent 0, max 234 avg 37 Use Begin/Endupdate Re-entrant 0, Max 62, Avg 12. use None Re-Entrant 0, Max 281, Avg 38 I get similar figures when testing on WIn/32/64 and linux Mint. Not yet tried on MacOS yet Can anyone else confirm similar impacts? You may think that its a strange test; but a few of my applications use the resize event to calculate what is displayed on the screen and in what location; based on the size of active form etc. These forms do not use anchor docking because visual components can be moved, made visible etc based on screen size and user preferences. Also they keeps a track if it in a re-entrant state so that any cpu/gpu intensive scaling etc can be ignored; until its not in a re-entrent state; it might complicated; but it does keep the application extrememly responsive and smooth. THought I would explain the issue. Also the current way it works is not very compatible with Delphi |
|
@josh, please open a new report for your speed issue. It can have this issue, 0037467 and maybe 0037706 as related issues. Resolving this one. |
|
@Juha Manninen I will add this to my previous report. 0037688 I still make the issue of the form.onresize not be re-entrant? was this introduced in this report? |
|
r63888 break my app(( Unfortunately, I can't give a minimal example. I use the progress bar to display the progress of long actions. To update it when the program is busy, I use application.ProcessMessages. After r63888 my app began hang, if at time of application.ProcessMessages execution there are controls created but not yet shown |
Date Modified | Username | Field | Change |
---|---|---|---|
2019-10-02 09:55 | Joeny Ang | New Issue | |
2019-10-02 09:55 | Joeny Ang | File Added: tform-wrong-bounds-and-restored-bounds.patch | |
2019-10-02 09:55 | Joeny Ang | File Added: tform-restoredbounds.zip | |
2019-10-03 03:52 | Joeny Ang | File Added: tform-wrong-bounds-and-restored-bounds-v2.patch | |
2019-10-03 03:52 | Joeny Ang | Note Added: 0118263 | |
2019-10-03 14:33 | Juha Manninen | Relationship added | related to 0027894 |
2019-10-03 14:33 | Juha Manninen | Relationship added | related to 0022771 |
2019-10-03 14:33 | Juha Manninen | Relationship added | related to 0027375 |
2019-10-03 14:34 | Juha Manninen | Relationship added | related to 0021119 |
2019-10-03 14:42 | Juha Manninen | Relationship added | related to 0032631 |
2019-10-03 14:44 | Juha Manninen | Relationship added | related to 0008576 |
2019-10-03 14:45 | Juha Manninen | Description Updated | View Revisions |
2019-10-03 14:45 | Juha Manninen | LazTarget | => - |
2019-10-03 14:45 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2019-10-03 16:01 | Juha Manninen | Note Added: 0118278 | |
2019-10-05 22:26 | Juha Manninen | Assigned To | => Juha Manninen |
2019-10-05 22:26 | Juha Manninen | Status | new => assigned |
2019-10-05 22:28 | Juha Manninen | Note Added: 0118358 | |
2019-10-07 08:00 | Joeny Ang | File Added: delayedevent-wait-for-wmsize-before-onshow-onactivate.patch | |
2019-10-07 08:00 | Joeny Ang | Note Added: 0118386 | |
2019-10-25 00:37 | Juha Manninen | Note Added: 0118793 | |
2019-10-25 00:38 | Juha Manninen | Fixed in Revision | => r61997, r62113 |
2019-10-25 00:38 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-03-16 19:29 | Juha Manninen | Status | assigned => resolved |
2020-03-16 19:29 | Juha Manninen | Resolution | open => fixed |
2020-03-16 19:29 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-03-16 19:29 | Juha Manninen | Note Added: 0121628 | |
2020-04-05 18:44 | Juha Manninen | Relationship added | related to 0036877 |
2020-05-24 15:56 | Michl | Note Added: 0123037 | |
2020-05-24 15:59 | Michl | Note Edited: 0123037 | View Revisions |
2020-05-24 17:33 | Michl | Note Edited: 0123037 | View Revisions |
2020-05-25 15:16 | Michl | Fixed in Revision | r61997, r62113 => r61997, r62113, r63218 |
2020-05-25 15:16 | Michl | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-05-25 15:17 | Michl | Note Added: 0123059 | |
2020-05-25 21:04 | Michl | Status | resolved => assigned |
2020-05-25 21:04 | Michl | Resolution | fixed => reopened |
2020-05-25 21:05 | Michl | Note Added: 0123062 | |
2020-05-25 21:05 | Michl | File Added: TestChangeBoundsEvent.zip | |
2020-05-25 21:07 | Michl | Note Edited: 0123062 | View Revisions |
2020-05-25 21:08 | Michl | Note Edited: 0123062 | View Revisions |
2020-07-15 10:26 | Joeny Ang | Note Added: 0124030 | |
2020-07-15 10:26 | Joeny Ang | File Added: fix-duplicate-onresize-onchangebounds.patch | |
2020-07-15 10:27 | Joeny Ang | Note Edited: 0124030 | View Revisions |
2020-07-17 01:01 | Juha Manninen | Note Added: 0124110 | |
2020-07-17 01:02 | Juha Manninen | Fixed in Revision | r61997, r62113, r63218 => r61997, r62113, r63218, r63577 |
2020-07-17 01:02 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-07-22 19:35 | Juha Manninen | Status | assigned => resolved |
2020-07-22 19:35 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-07-22 19:35 | Juha Manninen | Note Added: 0124233 | |
2020-08-26 11:10 | Juha Manninen | Relationship added | related to 0037467 |
2020-08-26 11:12 | Juha Manninen | Status | resolved => assigned |
2020-08-26 11:12 | Juha Manninen | Resolution | reopened => open |
2020-08-26 11:12 | Juha Manninen | Note Added: 0125129 | |
2020-08-26 11:13 | Juha Manninen | Note Edited: 0125129 | View Revisions |
2020-08-26 15:44 | BrunoK | Note Added: 0125133 | |
2020-08-26 21:45 | Juha Manninen | Note Added: 0125143 | |
2020-08-27 11:24 | Paweł Dmitruk | Note Added: 0125150 | |
2020-08-27 11:54 | BrunoK | Note Added: 0125151 | |
2020-08-27 11:54 | BrunoK | File Added: tform-restoredbounds-unit2.zip | |
2020-08-27 12:09 | BrunoK | Note Edited: 0125151 | View Revisions |
2020-08-28 03:17 | Joeny Ang | Note Added: 0125163 | |
2020-08-28 03:17 | Joeny Ang | File Added: tform-wrong-bounds-and-restored-bounds-part4.patch | |
2020-08-28 03:17 | Joeny Ang | File Added: tform-restoredbounds2-2020.08.28.zip | |
2020-08-28 11:16 | Joeny Ang | Note Added: 0125170 | |
2020-08-28 11:16 | Joeny Ang | File Added: tform-wrong-bounds-and-restored-bounds-part4v2.patch | |
2020-08-29 15:46 | Juha Manninen | Relationship added | related to 0037647 |
2020-08-29 16:46 | Juha Manninen | Note Added: 0125202 | |
2020-08-29 16:47 | Juha Manninen | Fixed in Revision | r61997, r62113, r63218, r63577 => r61997, r62113, r63218, r63577, r63842 |
2020-08-29 16:47 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-08-29 16:51 | Juha Manninen | Note Edited: 0125202 | View Revisions |
2020-08-29 17:24 | Juha Manninen | Note Edited: 0125202 | View Revisions |
2020-08-30 15:01 | BrunoK | Note Added: 0125216 | |
2020-09-02 17:39 | Juha Manninen | Status | assigned => resolved |
2020-09-02 17:39 | Juha Manninen | Resolution | open => fixed |
2020-09-02 17:39 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-09-10 23:49 | wp | Relationship added | related to 0037732 |
2020-09-11 01:14 | jamie philbrook | Note Added: 0125470 | |
2020-09-11 15:40 | CudaText man_ | Note Added: 0125482 | |
2020-09-11 20:05 | Juha Manninen | Status | resolved => assigned |
2020-09-11 20:05 | Juha Manninen | Resolution | fixed => open |
2020-09-11 20:05 | Juha Manninen | Note Added: 0125488 | |
2020-09-12 16:15 | BrunoK | Note Added: 0125511 | |
2020-09-12 16:15 | BrunoK | File Added: revert_form_200912.patch | |
2020-09-13 12:12 | Juha Manninen | Note Added: 0125523 | |
2020-09-13 13:03 | BrunoK | Note Added: 0125525 | |
2020-09-14 12:02 | Joeny Ang | Note Added: 0125536 | |
2020-09-14 12:02 | Joeny Ang | File Added: tform-wrong-bounds-and-restored-bounds-part4-fix.patch | |
2020-09-18 11:49 | Juha Manninen | Note Added: 0125609 | |
2020-09-18 11:50 | Juha Manninen | Status | assigned => feedback |
2020-09-18 13:14 | CudaText man_ | Note Added: 0125613 | |
2020-09-18 21:49 | josh | Note Added: 0125631 | |
2020-09-18 21:49 | josh | File Added: Form_events_3.zip | |
2020-09-18 23:21 | Juha Manninen | Status | feedback => resolved |
2020-09-18 23:21 | Juha Manninen | Resolution | open => fixed |
2020-09-18 23:21 | Juha Manninen | Fixed in Revision | r61997, r62113, r63218, r63577, r63842 => r61997, r62113, r63218, r63577, r63842, r63888 |
2020-09-18 23:21 | Juha Manninen | Widgetset | GTK 2, Win32/Win64 => GTK 2, Win32/Win64 |
2020-09-18 23:21 | Juha Manninen | Note Added: 0125632 | |
2020-09-18 23:35 | josh | Note Added: 0125634 | |
2020-09-19 10:56 | Juha Manninen | Relationship added | related to 0037688 |
2020-09-30 21:47 | Andrey Zubarev | Note Added: 0126009 | |
2020-10-29 11:53 | Juha Manninen | Relationship added | related to 0038004 |
2020-12-26 16:52 | Michl | Relationship added | related to 0038261 |