Qt: refactored TQtCustomControl and TQtTabWidget size messages.issue #26120

git-svn-id: trunk@44969 -
This commit is contained in:
zeljko 2014-05-07 16:22:29 +00:00
parent 4b1ac8df58
commit 975e523a89
2 changed files with 177 additions and 73 deletions

View File

@ -274,6 +274,8 @@ const
LCLQt_ItemViewAfterMouseRelease = QEventType(Ord(QEventUser) + $1008);
// used by TQtTabWidget
LCLQt_DelayLayoutRequest = QEventType(Ord(QEventUser) + $1009);
// delayed resize event if wincontrol is computing bounds
LCLQt_DelayResizeEvent = QEventType(Ord(QEventUser) + $1010);
QtTextSingleLine = $0100;

View File

@ -2168,8 +2168,7 @@ end;
Params: None
Returns: Boolean
Checks if our control can call LCLObject.DoAdjustClientRect from SlotResize.
eg. TQtCustomControl does not call it since DoAdjustClientRect is called
from TQtViewport.EventFilter.This avoids deadlocks with autosizing.
This avoids deadlocks with autosizing.
------------------------------------------------------------------------------}
function TQtWidget.CanAdjustClientRectOnResize: Boolean;
begin
@ -2375,6 +2374,8 @@ var
QtEdit: IQtEdit;
R: TRect;
Pt: TQtPoint;
ANewSize: TSize;
AResizeEvent: QResizeEventH;
begin
BeginEventProcessing;
Result := False;
@ -2390,6 +2391,24 @@ begin
if LCLObject <> nil then
begin
case QEvent_type(Event) of
LCLQt_DelayResizeEvent:
begin
ANewSize.cx := Lo(QLCLMessageEvent_getWParam(QLCLMessageEventH(Event)));
ANewSize.cy := Hi(QLCLMessageEvent_getWParam(QLCLMessageEventH(Event)));
AResizeEvent := QResizeEvent_create(@ANewSize, @ANewSize);
try
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('>LCLQt_DelayResizeEvent: ',dbgsName(LCLObject),' casp=',dbgs(caspComputingBounds in LCLObject.AutoSizePhases));
{$ENDIF}
SlotResize(AResizeEvent);
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('<LCLQt_DelayResizeEvent: ',dbgsName(LCLObject),' casp=',dbgs(caspComputingBounds in LCLObject.AutoSizePhases));
{$ENDIF}
finally
QResizeEvent_destroy(AResizeEvent);
end;
Result := True;
end;
QEventFontChange:
begin
//explanation for this event usage: issue #19695
@ -2510,7 +2529,17 @@ begin
end;
QEventMove: SlotMove(Event);
QEventResize: SlotResize(Event);
QEventContentsRectChange: LCLObject.DoAdjustClientRectChange(False);
QEventContentsRectChange:
begin
if LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('WARNING: QEventContentsRectChange adjusting rect for ',dbgsName(LCLObject),' PHASE ? ',dbgs(caspComputingBounds in LCLObject.AutoSizePhases),' inUpdate=',dbgs(inUpdate),' Time: ',dbgs(GetTickCount));
{$ENDIF}
if not (caspComputingBounds in LCLObject.AutoSizePhases) then
LCLObject.DoAdjustClientRectChange(True);
end;
end;
QEventPaint:
begin
if canPaintBackground and (LCLObject.Color <> clDefault) then
@ -3983,6 +4012,16 @@ procedure TQtWidget.SlotResize(Event: QEventH); cdecl;
var
Msg: TLMSize;
NewSize: TSize;
R: TRect;
procedure DelayResizeEvent;
var
ALCLResizeEvent: QLCLMessageEventH;
begin
ALCLResizeEvent := QLCLMessageEvent_create(LCLQt_DelayResizeEvent, 0, MakeWParam(Word(NewSize.cx), Word(NewSize.cy)), 0, 0);
QCoreApplication_postEvent(Widget, ALCLResizeEvent);
end;
begin
{$ifdef VerboseQt}
WriteLn('TQtWidget.SlotResize');
@ -4012,9 +4051,20 @@ begin
exit;
if CanAdjustClientRectOnResize and
((NewSize.cx <> LCLObject.Width) or (NewSize.cy <> LCLObject.Height) or
LCLObject.ClientRectNeedsInterfaceUpdate) then
LCLObject.DoAdjustClientRectChange;
LCLObject.ClientRectNeedsInterfaceUpdate then
begin
// postpone resize event if we are computingbounds otherwise
// we can run into infinite size loop.
if (caspComputingBounds in LCLObject.AutoSizePhases) then
begin
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('WARNING: *TQtWidget.SlotResize caspComputingBounds=true* ! ',dbgsname(LCLObject),' inUpdate=',dbgs(inUpdate),' Time: ',dbgs(GetTickCount));
{$ENDIF}
DelayResizeEvent;
exit;
end else
LCLObject.DoAdjustClientRectChange;
end;
FillChar(Msg, SizeOf(Msg), #0);
@ -6093,7 +6143,7 @@ end;
function TQtWindowArea.CanAdjustClientRectOnResize: Boolean;
begin
Result := False;
Result := True;
end;
procedure TQtWindowArea.DetachEvents;
@ -6143,6 +6193,8 @@ end;
function TQtWindowArea.ScrollViewEventFilter(Sender: QObjectH; Event: QEventH
): Boolean; cdecl;
var
ASize: TSize;
AResizeEvent: QResizeEventH;
HaveVertBar, HaveHorzBar: Boolean;
ScrollBar: QScrollBarH;
begin
@ -6158,24 +6210,17 @@ begin
case QEvent_type(Event) of
QEventResize:
begin
// immediate update clientRect !
if FOwner <> nil then
begin
HaveVertBar := Assigned(FVScrollbar);
HaveHorzBar := Assigned(FHScrollbar);
if (caspComputingBounds in LCLObject.AutoSizePhases) then
begin
{$IF DEFINED(VerboseQt) OR DEFINED(VerboseQtCustomControlResizeDeadlock)}
writeln('*** INTERCEPTED RESIZE DEADLOCK *** ',LCLObject.ClassName,
':',LCLObject.Name);
{$ENDIF}
{$IFDEF QTSCROLLABLEFORMS}
// do not invalidate clientRectCache if we are embedded (eg. docked)
if not Assigned(LCLObject.Parent) then
LCLObject.InvalidateClientRectCache(True);
{$ENDIF}
end else
LCLObject.DoAdjustClientRectChange(HaveVertBar or HaveHorzBar);
{TQtMainWindow does not send resize event if ScrollArea is assigned,
it is done here when viewport geometry is finally updated by Qt.}
ASize := FOwner.getSize;
AResizeEvent := QResizeEvent_create(@ASize, @ASize);
try
SlotResize(AResizeEvent);
finally
QEvent_destroy(AResizeEvent);
end;
end else
LCLObject.DoAdjustClientRectChange;
end;
@ -6213,10 +6258,15 @@ begin
QEventLayoutRequest:
begin
with TQtMainWindow(FOwner) do
if FOwner <> nil then
begin
if Self.LCLObject.ClientRectNeedsInterfaceUpdate then
Self.LCLObject.DoAdjustClientRectChange(True);
if LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('TQtWindowArea.Viewport: ',dbgsName(LCLObject),' QEventLayoutRequest calling DoAdjustClientRectChange CASP=',dbgs(caspComputingBounds in LCLObject.AutoSizePhases),' ***** !!!! ');
{$ENDIF}
Self.LCLObject.DoAdjustClientRectChange(True);
end;
end;
end;
end;
@ -6777,9 +6827,16 @@ begin
if (Result) and (QEvent_type(Event) = QEventDrop) then
Result := slotDropFiles(Sender, Event);
end;
QEventResize:
begin
{$IFDEF QTSCROLLABLEFORMS}
if not Assigned(ScrollArea) then
{$ENDIF}
Result := inherited EventFilter(Sender, Event);
end;
QEventPaint:
begin
{do not send paint event to LCL if we are pure TCustomForm,
{do not send paint or resize event to LCL if we are pure TCustomForm,
CWEvent or ScrollArea.EventFilter will process it.
So call SlotPaint only if we are eg TQtHintWindow.}
if (FCentralWidget = nil) or (FCentralWidget = Widget) then
@ -7052,15 +7109,13 @@ begin
begin
{first must get contents rect - all except main menu}
QWidget_contentsRect(FCentralWidget, @R);
{TODO: find better way to find out which controls are top,left,right & bottom aligned ...}
for i := 0 to LCLObject.ComponentCount - 1 do
begin
{find statusbars}
if LCLObject.Components[i] is TStatusBar then
begin
R2 := TWinControl(LCLObject.Components[i]).ClientRect;
R2 := TWinControl(LCLObject.Components[i]).BoundsRect;
case TWinControl(LCLObject.Components[i]).Align of
alLeft: R.Left := R.Left + (R2.Right - R2.Left);
alTop: R.Top := R.Top + (R2.Bottom - R2.Top);
@ -7072,7 +7127,7 @@ begin
{find toolbars}
if LCLObject.Components[i] is TToolBar then
begin
R2 := TWinControl(LCLObject.Components[i]).ClientRect;
R2 := TWinControl(LCLObject.Components[i]).BoundsRect;
case TWinControl(LCLObject.Components[i]).Align of
alLeft: R.Left := R.Left + (R2.Right - R2.Left);
alTop: R.Top := R.Top + (R2.Bottom - R2.Top);
@ -7082,11 +7137,9 @@ begin
end;
end; {components loop}
QWidget_setGeometry(MDIAreaHandle.Widget, @R);
end;
{mdi area part end}
end;
end;
end;
@ -7724,17 +7777,6 @@ begin
{$ifdef VerboseQt}
writeln('TQtAbstractSlider.rangeChanged() to min=',minimum,' max=',maximum);
{$endif}
{$IFDEF QTSCROLLABLEFORMS}
if (FOwner <> nil) and Assigned(FOwner.LCLObject) and
(FOwner is TQtWindowArea) and
not (caspComputingBounds in FOwner.LCLObject.AutoSizePhases) then
LCLObject.InvalidateClientRectCache(True)
else
{$ENDIF}
if (FOwner <> nil) and Assigned(FOwner.LCLObject) and
(FOwner.FChildOfComplexWidget = ccwScrollingWinControl) and
not (caspComputingBounds in FOwner.LCLObject.AutoSizePhases) then
LCLObject.InvalidateClientRectCache(True);
end;
{------------------------------------------------------------------------------
@ -7953,13 +7995,10 @@ begin
if not InUpdate or (getVisible and ((p1=getMin) or b)) then
begin
if b and (FChildOfComplexWidget = ccwAbstractScrollArea) then
begin
LCLObject.DoAdjustClientRectChange;
if not InUpdate and getVisible then
if b and (FChildOfComplexWidget = ccwAbstractScrollArea) and
not InUpdate and getVisible then
QAbstractSlider_triggerAction(QAbstractSliderH(Widget),
QAbstractSliderSliderToMaximum);
end;
end;
end;
@ -8212,8 +8251,18 @@ begin
end;
end;
end;
QEventHide:
QEventHide, QEventShow:
begin
{$IFDEF VerboseQtResize}
if (FOwner <> nil) then
begin
if (QEvent_type(Event) = QEventShow) then
DebugLn('>>>>>>>>>>>>>>>>> TQtScrollbar QEventShow orientation=',dbgs(getOrientation),' ',dbgsName(LCLObject))
else
DebugLn('>>>>>>>>>>>>>>>>> TQtScrollbar QEventHide orientation=',dbgs(getOrientation),' ',dbgsName(LCLObject));
end;
{$ENDIF}
{$IFDEF QTSCROLLABLEFORMS}
if Assigned(FOwner) and (FOwner is TQtWindowArea) then
begin
@ -8227,11 +8276,42 @@ begin
if Assigned(FOwner) and (FOwner is TQtCustomControl) then
begin
if Assigned(TQtCustomControl(FOwner).FViewPortWidget) then
begin
case getOrientation of
QtVertical: TQtCustomControl(FOwner).FViewPortWidget.FScrollY := 0;
QtHorizontal: TQtCustomControl(FOwner).FViewPortWidget.FScrollX := 0;
end;
// this can fail with infinite loop like in gtk2 in case of ide main bar resizing
// don't know what to do since ClientRectNeedsInterfaceUpdate and caspComputing is true.
// So we just set result according to the caspComputingBounds result.
if not (csDestroying in LCLObject.ComponentState) and
LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IFDEF VerboseQtResize}
if QEvent_Type(Event) = QEventShow then
writeln('***** TQtScrollBar.EventFilter(SHOW) for bar ',getOrientation,' cliRect ',LCLObject.ClientRectNeedsInterfaceUpdate,' caps ',caspComputingBounds in LCLObject.AutoSizePhases,
' QtWaVisible ',testAttribute(QtWA_WState_Visible),' QtWAHidden ',testAttribute(QtWA_WState_Hidden),
' QtWaExpl ',testAttribute(QtWA_WState_ExplicitShowHide),' VtoP=',getVisibleTo(getParent))
else
writeln('***** TQtScrollBar.EventFilter(HIDE) for bar ',getOrientation,' cliRect ',LCLObject.ClientRectNeedsInterfaceUpdate,' caps ',caspComputingBounds in LCLObject.AutoSizePhases,
' QtWaVisible ',testAttribute(QtWA_WState_Visible),' QtWAHidden ',testAttribute(QtWA_WState_Hidden),
' QtWaExpl ',testAttribute(QtWA_WState_ExplicitShowHide),' VtoP=',getVisibleTo(getParent));
{$ENDIF}
// LCLObject.DoAdjustClientRectChange(not (caspComputingBounds in LCLObject.AutoSizePhases));
Result := caspComputingBounds in LCLObject.AutoSizePhases;
end;
end;
end;
{$IFDEF VerboseQtResize}
if (FOwner <> nil) then
begin
if (QEvent_type(Event) = QEventShow) then
DebugLn('<<<<<<<<<<<<<<<<< TQtScrollbar QEventShow orientation=',dbgs(getOrientation),' ',dbgsName(LCLObject))
else
DebugLn('<<<<<<<<<<<<<<<<< TQtScrollbar QEventHide orientation=',dbgs(getOrientation),' ',dbgsName(LCLObject));
end;
{$ENDIF}
if FOwnWidget then
Result := inherited EventFilter(Sender, Event);
end;
@ -9501,6 +9581,8 @@ var
Pt: TPoint;
{$ENDIF}
ALCLEvent: QLCLMessageEventH;
ASize: TSize;
AResizeEvent: QResizeEventH;
begin
Result := False;
@ -9516,15 +9598,24 @@ begin
' Event=', EventTypeToStr(Event),' inUpdate=',inUpdate);
{$endif}
{
we don't use QEventResize and QEventLayoutRequest of StackedWidget anymore.
see commited revision for issue #21805.
We are leaving this part for debugging purposes.
main resize event should come from FStackWidget, not from QTabWidget,
after FStackWidget is resized by Qt to it's final size.
QTabWidget don't send QResizeEvent to LCL.
}
ASize := getSize;
AResizeEvent := QResizeEvent_create(@ASize, @ASize);
try
SlotResize(AResizeEvent);
finally
QEvent_destroy(AResizeEvent);
end;
exit;
end;
BeginEventProcessing;
case QEvent_type(Event) of
QEventResize: ; // stackwidget does that, look above
{$IFDEF QT_ENABLE_LCL_PAINT_TABS}
QEventPaint:
begin
@ -9545,7 +9636,7 @@ begin
begin
if LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IFDEF VerboseQtEvents}
{$IF DEFINED(VerboseQtEvents) OR DEFINED(VerboseQtResize)}
DebugLn('<*><*> TQtTabWidget calling DoAdjustClientRectChange() from LCLQt_DelayLayoutRequest ...');
{$ENDIF}
LCLObject.DoAdjustClientRectChange(True);
@ -14834,12 +14925,12 @@ function TQtMenuBar.EventFilter(Sender: QObjectH; Event: QEventH): Boolean;
ACtl := TQtMainWindow(Window).LCLObject;
if Assigned(ACtl) and not (csDestroying in ACtl.ComponentState) then
begin
{$IFDEF VerboseQtEvents}
{$IF DEFINED(VerboseQtEvents) OR DEFINED(VerboseQtResize)}
DebugLn('TQtMenuBar.EventFilter: before DoAdjustClientRecChange=',
dbgs(ACtl.ClientRect));
{$ENDIF}
ACtl.DoAdjustClientRectChange(True);
{$IFDEF VerboseQtEvents}
{$IF DEFINED(VerboseQtEvents) OR DEFINED(VerboseQtResize)}
DebugLn('TQtMenuBar.EventFilter: after DoAdjustClientRecChange=',
dbgs(ACtl.ClientRect));
{$ENDIF}
@ -15338,9 +15429,9 @@ end;
function TQtViewPort.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
var
HaveVertBar: Boolean;
HaveHorzBar: Boolean;
ScrollBar: QScrollBarH;
ASize: TSize;
AResizeEvent: QResizeEventH;
begin
Result := False;
{$IF DEFINED(VerboseQt) OR DEFINED(VerboseQtEvents)}
@ -15357,17 +15448,22 @@ begin
// immediate update clientRect !
if FOwner <> nil then
begin
HaveVertBar := Assigned(TQtCustomControl(FOwner).FVScrollbar);
HaveHorzBar := Assigned(TQtCustomControl(FOwner).FHScrollbar);
if (caspComputingBounds in LCLObject.AutoSizePhases) then
{$IF DEFINED(VerboseQt) OR DEFINED(VerboseQtCustomControlResizeDeadlock)}
writeln('*** INTERCEPTED RESIZE DEADLOCK *** ',LCLObject.ClassName,
':',LCLObject.Name)
{$ENDIF}
else
LCLObject.DoAdjustClientRectChange(HaveVertBar or HaveHorzBar);
{TQtCustomControl does not send resize event, it is done here
when viewport geometry is finally updated by Qt.}
ASize := FOwner.getSize;
AResizeEvent := QResizeEvent_create(@ASize, @ASize);
try
SlotResize(AResizeEvent);
finally
QEvent_destroy(AResizeEvent);
end;
end else
begin
{$IF DEFINED(VerboseQtEvents) OR DEFINED(VerboseQtResize)}
DebugLn('TQtViewport: QEventResize wrong call....possible ERROR');
{$ENDIF}
LCLObject.DoAdjustClientRectChange;
end;
end;
QEventWheel:
if not getEnabled then
@ -15403,11 +15499,16 @@ begin
QEventLayoutRequest:
begin
with TQtCustomControl(FOwner) do
if FOwner <> nil then
begin
if (ChildOfComplexWidget = ccwScrollingWinControl) and
Self.LCLObject.ClientRectNeedsInterfaceUpdate then
Self.LCLObject.DoAdjustClientRectChange(True);
if LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IF DEFINED(VerboseQtEvents) OR DEFINED(VerboseQtResize) OR DEFINED(VerboseSizeMsg)}
if caspComputingBounds in LCLObject.AutoSizePhases then
DebugLn('TQtViewport of ',dbgsName(LCLObject),' QEventLayoutRequest calling DoAdjustClientRectChange. CASP=TRUE *** !!!!');
{$ENDIF}
LCLObject.DoAdjustClientRectChange(True);
end;
end;
end;
else
@ -15800,6 +15901,7 @@ begin
if (QEvent_type(Event) in [
QEventPaint,
QEventResize, // TQtViewport.EventFilter sends resize !
QEventMouseButtonPress,
QEventMouseButtonRelease,
QEventMouseButtonDblClick,
@ -15894,7 +15996,7 @@ end;
function TQtCustomControl.CanAdjustClientRectOnResize: Boolean;
begin
// DoAdjustClientRectChange(); is called from TQtViewport resize event !
Result := False;
Result := True;
end;
{------------------------------------------------------------------------------
@ -16587,7 +16689,7 @@ begin
//behaviour is changed because of issue #21805.
if LCLObject.ClientRectNeedsInterfaceUpdate then
begin
{$IFDEF VerboseQtEvents}
{$IF DEFINED(VerboseSizeMsg) OR DEFINED(VerboseQtResize)}
DebugLn('<*><*> TQtPage resize event invalidating clientrect cache !!!');
{$ENDIF}
LCLObject.InvalidateClientRectCache(False);