mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-11 13:28:04 +02:00
gtk2 intf: improved resizing code to not need the caching trick
git-svn-id: trunk@11212 -
This commit is contained in:
parent
78509220c9
commit
1eff85d939
@ -449,9 +449,8 @@ var
|
||||
Rows: Integer;
|
||||
begin
|
||||
Rows:=Page.ClientHeight div ComponentPaletteBtnHeight;
|
||||
// patch by JernejL 12.11.2006
|
||||
// Ok, this is nice.. this is called when Tnotebook or its pages resize, it will
|
||||
// automaticly set optimal row count and re-position controls to use height optimally
|
||||
//DebugLn(['TComponentPalette.ReAlignButtons ',DbgSName(Page),' PageIndex=',Page.PageIndex,' ClientRect=',dbgs(Page.ClientRect)]);
|
||||
// automatically set optimal row count and re-position controls to use height optimally
|
||||
|
||||
if Rows = 0 then Rows:= 1; // avoid division by zero
|
||||
|
||||
|
@ -337,6 +337,7 @@ begin
|
||||
' Old='+dbgs(Left)+','+dbgs(Top)+','+dbgs(Width),',',dbgs(Height),
|
||||
' New='+dbgs(ALeft)+','+dbgs(ATop)+','+dbgs(AWidth),',',dbgs(AHeight));
|
||||
//if (Parent=nil) and (Left>0) and (ALeft=0) then DumpStack; // This can happen if the interface has not yet moved the window and for some reason something applies the interface coords back to the LCL
|
||||
if AWidth=314 then DumpStack;
|
||||
{$ENDIF}
|
||||
|
||||
// constraint the size
|
||||
|
@ -2125,8 +2125,12 @@ function TWinControl.ClientRectNeedsInterfaceUpdate: boolean;
|
||||
var
|
||||
IntfClientRect: TRect;
|
||||
begin
|
||||
Result:=false;
|
||||
if not HandleAllocated then exit;
|
||||
if (not HandleAllocated) or (csDestroyingHandle in ControlState)
|
||||
or (csDestroying in ComponentState)
|
||||
then
|
||||
exit(false);
|
||||
if wcfClientRectNeedsUpdate in FWinControlFlags then
|
||||
exit(true);
|
||||
LCLIntf.GetClientRect(Handle,IntfClientRect);
|
||||
Result:=(FClientWidth<>IntfClientRect.Right)
|
||||
or (FClientHeight<>IntfClientRect.Bottom);
|
||||
@ -4863,7 +4867,7 @@ var
|
||||
NewBoundsRealized: TRect;
|
||||
begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if CheckPosition(Self) then
|
||||
//if CheckPosition(Self) then
|
||||
DebugLn(['TWinControl.WMSize A ',Name,':',ClassName,' Message=',Message.Width,',',Message.Height,
|
||||
' BoundsRealized=',dbgs(FBoundsRealized),' FromIntf=',(Message.SizeType and Size_SourceIsInterface)>0]);
|
||||
{$ENDIF}
|
||||
@ -4878,12 +4882,15 @@ begin
|
||||
GetWindowRelativePosition(Handle,NewLeft,NewTop);
|
||||
//DebugLn('TWinControl.WMSize B ',Name,':',ClassName,' ',NewLeft,',',NewTop);
|
||||
NewBoundsRealized:=Bounds(NewLeft,NewTop,Message.Width,Message.Height);
|
||||
if CompareRect(@NewBoundsRealized,@FBoundsRealized) then exit;
|
||||
if CompareRect(@NewBoundsRealized,@FBoundsRealized)
|
||||
and (not (wcfClientRectNeedsUpdate in FWinControlFlags)) then exit;
|
||||
FBoundsRealized:=NewBoundsRealized;
|
||||
InvalidatePreferredSize;
|
||||
end;
|
||||
|
||||
SetBoundsKeepBase(NewLeft,NewTop,Message.Width,Message.Height,Parent<>nil);
|
||||
if ClientRectNeedsInterfaceUpdate then
|
||||
DoAdjustClientRectChange;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
|
@ -302,9 +302,6 @@ type
|
||||
procedure SetDesigning(AComponent: TComponent); override;
|
||||
|
||||
// helper routines needed by interface methods
|
||||
procedure UnsetResizeRequest(Widget: PGtkWidget);virtual;
|
||||
procedure SetResizeRequest(Widget: PGtkWidget);virtual;
|
||||
function WidgetSizeIsEditable(Widget: PGtkWidget): boolean;virtual;
|
||||
// |-forms
|
||||
procedure UpdateTransientWindows; virtual;
|
||||
// |-listbox
|
||||
|
@ -3163,12 +3163,7 @@ end;
|
||||
procedure TGtkWidgetSet.ResizeChild(Sender : TObject;
|
||||
Left, Top, Width, Height : Integer);
|
||||
var
|
||||
Widget: PGtkWidget;
|
||||
LCLControl: TWinControl;
|
||||
Later: boolean;
|
||||
{$IFDEF Gtk2}
|
||||
IsTopLevelWidget: Boolean;
|
||||
{$ENDIF}
|
||||
begin
|
||||
//DebugLn('[TGtkWidgetSet.ResizeChild] START ',TControl(Sender).Name,':',Sender.Classname,' Left=',Left,' Top=',Top,' Width=',Width,' Height=',Height);
|
||||
Assert(false, (Format('trace: [TGtkWidgetSet.ResizeChild] %s --> Resize', [Sender.ClassNAme])));
|
||||
@ -3176,22 +3171,7 @@ begin
|
||||
if Sender is TWinControl then begin
|
||||
LCLControl:=TWinControl(Sender);
|
||||
if LCLControl.HandleAllocated then begin
|
||||
Widget := pgtkWidget(LCLControl.Handle);
|
||||
if not WidgetSizeIsEditable(Widget) then exit;
|
||||
Later:=true;
|
||||
{$IFDEF Gtk2}
|
||||
if GTK_WIDGET_REALIZED(Widget) then begin
|
||||
// add resize request immediately
|
||||
IsTopLevelWidget:= (LCLControl is TCustomForm)
|
||||
and (LCLControl.Parent = nil);
|
||||
if not IsTopLevelWidget then begin
|
||||
SetWidgetSizeAndPosition(LCLControl);
|
||||
Later:=false;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
if Later then
|
||||
SetResizeRequest(Widget);
|
||||
ResizeHandle(LCLControl);
|
||||
//if (Sender is TCustomForm) then
|
||||
//if CompareText(Sender.ClassName,'TScrollBar')=0 then
|
||||
// DebugLn(' FFF ResizeChild ',Sender.ClassName,' ',Left,',',Top,',',Width,',',Height);
|
||||
@ -5563,7 +5543,7 @@ begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
DebugLn(['TGtkWidgetSet.ShowHide ',DbgSName(LCLControl)]);
|
||||
{$ENDIF}
|
||||
RealizeWidgetSize(SenderWidget,LCLControl.Width,LCLControl.Height);
|
||||
SetWidgetSize(SenderWidget,LCLControl.Width,LCLControl.Height);
|
||||
// move widget on the fixed widget of parent control
|
||||
ParentWidget:=pgtkWidget(LCLControl.Parent.Handle);
|
||||
ParentFixed := GetFixedWidget(ParentWidget);
|
||||
@ -6749,84 +6729,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TGtkWidgetSet SetResizeRequest
|
||||
Params: Widget: PGtkWidget
|
||||
|
||||
Marks the widget to send a ResizeRequest to the gtk.
|
||||
When the LCL resizes a control the new bounds will not be set directly, but
|
||||
cached. This is needed, because it is common behaviour to set the bounds step
|
||||
by step. For example: Left:=10; Top:=10; Width:=100; Height:=50; results in
|
||||
SetBounds(10,0,0,0);
|
||||
SetBounds(10,10,0,0);
|
||||
SetBounds(10,10,100,0);
|
||||
SetBounds(10,10,100,50);
|
||||
Because the gtk puts all size requests into a queue, it will process the
|
||||
requests not immediately, but _after_ all requests. This results in changing
|
||||
the widget size four times and everytime the LCL gets a message. If the
|
||||
control has childs, this will resize the childs four times.
|
||||
Therefore LCL size requests for a widget are cached and only the final one is
|
||||
sent in: TGtkWidgetSet.SendCachedLCLMessages.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TGtkWidgetSet.SetResizeRequest(Widget: PGtkWidget);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
var
|
||||
LCLControl: TWinControl;
|
||||
{$ENDIF}
|
||||
begin
|
||||
{$IFDEF Gtk2}
|
||||
if not WidgetSizeIsEditable(Widget) then exit;
|
||||
{$ENDIF}
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
LCLControl:=TWinControl(GetLCLObject(Widget));
|
||||
DbgOut('TGtkWidgetSet.SetResizeRequest Widget=',DbgS(Widget));
|
||||
if LCLControl is TWinControl then
|
||||
DebugLn(' ',DbgSName(LCLControl),' LCLBounds=',dbgs(LCLControl.BoundsRect))
|
||||
else
|
||||
DebugLn(' ERROR: ',DbgSName(LCLControl));
|
||||
{$ENDIF}
|
||||
if not FWidgetsWithResizeRequest.Contains(Widget) then
|
||||
FWidgetsWithResizeRequest.Add(Widget);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
function TGTKWidgetSet.WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
|
||||
|
||||
True if the widget can be resized.
|
||||
False if the size is under complete control of the gtk.
|
||||
------------------------------------------------------------------------------}
|
||||
function TGTKWidgetSet.WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
|
||||
begin
|
||||
if Widget=nil then exit(false);
|
||||
if (GtkWidgetIsA(Widget,GTK_TYPE_WINDOW))
|
||||
or (GtkWidgetIsA(Widget^.Parent,GTK_TYPE_FIXED))
|
||||
or (GtkWidgetIsA(Widget^.Parent,GTK_TYPE_LAYOUT))
|
||||
then
|
||||
Result:=true
|
||||
else
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TGtkWidgetSet UnsetResizeRequest
|
||||
Params: Widget: PGtkWidget
|
||||
|
||||
Unset the mark for the Widget to send a ResizeRequest to the gtk.
|
||||
LCL size requests for a widget are cached and only the last one is sent. Some
|
||||
widgets like forms send a resize request immediately. To avoid sending resize
|
||||
requests multiple times they can unset the mark with this procedure.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TGtkWidgetSet.UnsetResizeRequest(Widget: PGtkWidget);
|
||||
begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if FWidgetsWithResizeRequest.Contains(Widget) then begin
|
||||
DebugLn(['TGtkWidgetSet.UnsetResizeRequest ',GetWidgetDebugReport(Widget)]);
|
||||
end;
|
||||
{$ENDIF}
|
||||
FWidgetsWithResizeRequest.Remove(Widget);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: SetClipboardWidget
|
||||
Params: TargetWidget: PGtkWidget - This widget will be connected to all
|
||||
|
@ -6459,15 +6459,23 @@ var
|
||||
MainWidget: PGtkWidget;
|
||||
FixedWidget: PGtkWidget;
|
||||
|
||||
procedure UpdateLCLRect;
|
||||
procedure UpdateLCLPos;
|
||||
begin
|
||||
LCLLeft:=LCLControl.Left;
|
||||
LCLTop:=LCLControl.Top;
|
||||
TopLeftChanged:=(LCLLeft<>GtkLeft) or (LCLTop<>GtkTop);
|
||||
end;
|
||||
|
||||
procedure UpdateLCLSize;
|
||||
begin
|
||||
LCLWidth:=LCLControl.Width;
|
||||
LCLHeight:=LCLControl.Height;
|
||||
|
||||
TopLeftChanged:=(LCLLeft<>GtkLeft) or (LCLTop<>GtkTop);
|
||||
WidthHeightChanged:=(LCLWidth<>GtkWidth) or (LCLHeight<>GtkHeight);
|
||||
if LCLControl.ClientRectNeedsInterfaceUpdate then begin
|
||||
WidthHeightChanged:=true;
|
||||
//DebugLn(['UpdateLCLSize InvalidateClientRectCache ',DbgSName(LCLControl)]);
|
||||
LCLControl.InvalidateClientRectCache(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
@ -6492,18 +6500,8 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
GtkLeft:=MainWidget^.Allocation.X;
|
||||
GtkTop:=MainWidget^.Allocation.Y;
|
||||
GetWidgetRelativePosition(MainWidget,GtkLeft,GtkTop);
|
||||
|
||||
{$Ifdef GTK2}
|
||||
if GTK_WIDGET_NO_WINDOW(MainWidget) and GTK_WIDGET_NO_WINDOW(MainWidget^.Parent)
|
||||
// and (not GtkWidgetIsA(MainWidget,GTKAPIWidget_GetType))
|
||||
then begin
|
||||
//DebugLn(['SendSizeNotificationToLCL widget has no gdkwindow, fixing coords by adding parent coords: MainWidget^.Allocation=',MainWidget^.Allocation.X,',',MainWidget^.Allocation.Y,' MainWidget^.parent^.Allocation=',MainWidget^.parent^.Allocation.X,',',MainWidget^.parent^.Allocation.Y,' ',GetWidgetDebugReport(MainWidget)]);
|
||||
Dec(GtkLeft, MainWidget^.parent^.Allocation.X);
|
||||
Dec(GtkTop, MainWidget^.parent^.Allocation.Y);
|
||||
end;
|
||||
{$EndIf}
|
||||
GtkWidth:=MainWidget^.Allocation.Width;
|
||||
if GtkWidth<0 then GtkWidth:=0;
|
||||
GtkHeight:=MainWidget^.Allocation.Height;
|
||||
@ -6521,12 +6519,6 @@ begin
|
||||
exit;
|
||||
end;
|
||||
//DebugLn(['SendSizeNotificationToLCL FORM ',GetWidgetDebugReport(MainWidget)]);
|
||||
if GetControlWindow(MainWidget)<>nil then begin
|
||||
gdk_window_get_root_origin(GetControlWindow(MainWidget), @GtkLeft, @GtkTop);
|
||||
end else begin
|
||||
GtkLeft:=LCLControl.Left;
|
||||
GtkTop:=LCLControl.Top;
|
||||
end;
|
||||
|
||||
{$IFDEF VerboseFormPositioning}
|
||||
DebugLn(['VFP SendSizeNotificationToLCL ',DbgSName(LCLControl),' ',
|
||||
@ -6534,7 +6526,8 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
UpdateLCLRect;
|
||||
UpdateLCLPos;
|
||||
UpdateLCLSize;
|
||||
|
||||
// first send a LM_WINDOWPOSCHANGED message
|
||||
if TopLeftChanged or WidthHeightChanged then begin
|
||||
@ -6562,7 +6555,8 @@ begin
|
||||
end;
|
||||
if (not MessageDelivered) then exit;
|
||||
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
|
||||
UpdateLCLRect;
|
||||
UpdateLCLPos;
|
||||
UpdateLCLSize;
|
||||
end;
|
||||
|
||||
// then send a LM_SIZE message
|
||||
@ -6599,7 +6593,7 @@ begin
|
||||
MessageDelivered := (DeliverMessage(LCLControl, SizeMsg) = 0);
|
||||
if not MessageDelivered then exit;
|
||||
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
|
||||
UpdateLCLRect;
|
||||
UpdateLCLPos;
|
||||
end;
|
||||
|
||||
// then send a LM_MOVE message
|
||||
@ -6711,13 +6705,37 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure ResizeHandle(LCLControl: TWinControl);
|
||||
var
|
||||
Widget: PGtkWidget;
|
||||
Later: Boolean;
|
||||
{$IFDEF Gtk2}
|
||||
IsTopLevelWidget: Boolean;
|
||||
{$ENDIF}
|
||||
begin
|
||||
Widget:=PGtkWidget(LCLControl.Handle);
|
||||
if not WidgetSizeIsEditable(Widget) then exit;
|
||||
Later:=true;
|
||||
{$IFDEF Gtk2}
|
||||
// add resize request immediately
|
||||
IsTopLevelWidget:= (LCLControl is TCustomForm)
|
||||
and (LCLControl.Parent = nil);
|
||||
if not IsTopLevelWidget then begin
|
||||
SetWidgetSizeAndPosition(LCLControl);
|
||||
Later:=false;
|
||||
end;
|
||||
{$ENDIF}
|
||||
if Later then
|
||||
SetResizeRequest(Widget);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
|
||||
procedure SetWidgetSize(Widget: PGtkWidget; NewWidth,
|
||||
NewHeight: integer);
|
||||
|
||||
Note: gtk_window is resized in SetWindowSizeAndPosition
|
||||
------------------------------------------------------------------------------}
|
||||
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
|
||||
procedure SetWidgetSize(Widget: PGtkWidget; NewWidth,
|
||||
NewHeight: integer);
|
||||
var
|
||||
Requisition: TGtkRequisition;
|
||||
@ -6725,13 +6743,16 @@ var
|
||||
LCLObject: TObject;
|
||||
{$ENDIF}
|
||||
FixedWidget: PGtkWidget;
|
||||
{$IFDEF Gtk2}
|
||||
allocation: TGtkAllocation;
|
||||
{$ENDIF}
|
||||
begin
|
||||
if NewWidth<=0 then NewWidth:=1;
|
||||
if NewHeight<=0 then NewHeight:=1;
|
||||
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
LCLObject:=GetNearestLCLObject(Widget);
|
||||
DbgOut('TGtkWidgetSet.RealizeWidgetSize Widget='+DbgS(Widget)+WidgetFlagsToString(Widget)+
|
||||
DbgOut('TGtkWidgetSet.SetWidgetSize Widget='+DbgS(Widget)+WidgetFlagsToString(Widget)+
|
||||
' New='+dbgs(NewWidth)+','+dbgs(NewHeight));
|
||||
if (LCLObject<>nil) and (LCLObject is TControl) then begin
|
||||
with TControl(LCLObject) do
|
||||
@ -6751,11 +6772,11 @@ begin
|
||||
end else begin
|
||||
NewWidth:=Requisition.width;
|
||||
end;
|
||||
//DebugLn('TGtkWidgetSet.RealizeWidgetSize A ',Newwidth,',',Newheight);
|
||||
//DebugLn('TGtkWidgetSet.SetWidgetSize A ',Newwidth,',',Newheight);
|
||||
end;
|
||||
|
||||
gtk_widget_set_usize(Widget, NewWidth, NewHeight);
|
||||
//DebugLn(['TGtkWidgetSet.RealizeWidgetSize ',GetWidgetDebugReport(Widget),' NewWidth=',NewWidth,' NewHeight=',NewHeight]);
|
||||
//DebugLn(['TGtkWidgetSet.SetWidgetSize ',GetWidgetDebugReport(Widget),' NewWidth=',NewWidth,' NewHeight=',NewHeight]);
|
||||
|
||||
{$IFDEF Gtk1}
|
||||
if GtkWidgetIsA(Widget, GTK_TYPE_COMBO) then
|
||||
@ -6770,10 +6791,18 @@ begin
|
||||
if GtkWidgetIsA(Widget,gtk_toolbar_get_type) then begin
|
||||
FixedWidget:=GetFixedWidget(Widget);
|
||||
if (FixedWidget<>nil) and (FixedWidget<>Widget) then begin
|
||||
//DebugLn('WARNING: ToDo TGtkWidgetSet.RealizeWidgetSize for TToolBar ',NewWidth,',',NewHeight);
|
||||
//DebugLn('WARNING: ToDo TGtkWidgetSet.SetWidgetSize for TToolBar ',NewWidth,',',NewHeight);
|
||||
gtk_widget_set_usize(FixedWidget,NewWidth,NewHeight);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF Gtk2}
|
||||
// commit size
|
||||
allocation:=Widget^.allocation;
|
||||
allocation.width:=NewWidth;
|
||||
allocation.height:=NewHeight;
|
||||
gtk_widget_size_allocate(Widget,@allocation);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);
|
||||
@ -6804,25 +6833,10 @@ var
|
||||
end;
|
||||
|
||||
begin
|
||||
// resize widget
|
||||
LCLWidth:=LCLControl.Width;
|
||||
if LCLWidth<=0 then
|
||||
LCLWidth:=1;
|
||||
LCLHeight:=LCLControl.Height;
|
||||
if LCLHeight<=0 then
|
||||
LCLHeight:=1;
|
||||
if (LCLWidth>10000) or (LCLHeight>10000) then begin
|
||||
WriteBigWarning;
|
||||
if LCLWidth>10000 then
|
||||
LCLWidth:=10000
|
||||
else
|
||||
LCLHeight:=10000;
|
||||
end;
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
DebugLn(['SetWidgetSizeAndPosition ',DbgSName(LCLControl)]);
|
||||
{$ENDIF}
|
||||
Widget:=PGtkWidget(LCLControl.Handle);
|
||||
RealizeWidgetSize(Widget,LCLWidth, LCLHeight);
|
||||
|
||||
// move widget on the fixed widget of parent control
|
||||
if (LCLControl.Parent<>nil) and (LCLControl.Parent.HandleAllocated) then
|
||||
@ -6840,6 +6854,22 @@ begin
|
||||
WriteWarningParentWidgetNotFound;
|
||||
end;
|
||||
end;
|
||||
|
||||
// resize widget
|
||||
LCLWidth:=LCLControl.Width;
|
||||
if LCLWidth<=0 then
|
||||
LCLWidth:=1;
|
||||
LCLHeight:=LCLControl.Height;
|
||||
if LCLHeight<=0 then
|
||||
LCLHeight:=1;
|
||||
if (LCLWidth>10000) or (LCLHeight>10000) then begin
|
||||
WriteBigWarning;
|
||||
if LCLWidth>10000 then
|
||||
LCLWidth:=10000
|
||||
else
|
||||
LCLHeight:=10000;
|
||||
end;
|
||||
SetWidgetSize(Widget,LCLWidth, LCLHeight);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
@ -6895,6 +6925,121 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
GetWidgetRelativePosition
|
||||
|
||||
Returns the Left, Top, relative to the client origin of its parent
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure GetWidgetRelativePosition(aWidget: PGtkWidget; var Left, Top: integer);
|
||||
var
|
||||
GdkWindow: PGdkWindow;
|
||||
LCLControl: TWinControl;
|
||||
GtkLeft, GtkTop: GInt;
|
||||
begin
|
||||
Left:=aWidget^.allocation.X;
|
||||
Top:=aWidget^.allocation.Y;
|
||||
{$IFDEF Gtk2}
|
||||
if (aWidget^.parent<>nil)
|
||||
and (not GtkWidgetIsA(aWidget^.parent,GTK_TYPE_FIXED))
|
||||
and (not GtkWidgetIsA(aWidget^.parent,GTK_TYPE_LAYOUT))
|
||||
then begin
|
||||
// widget is not on a normal client area. e.g. TPage
|
||||
Left:=0;
|
||||
Top:=0;
|
||||
end;
|
||||
{$ENDIF}
|
||||
if GtkWidgetIsA(aWidget,GTK_TYPE_WINDOW) then begin
|
||||
GdkWindow:=GetControlWindow(aWidget);
|
||||
if GdkWindow<>nil then begin
|
||||
gdk_window_get_root_origin(GdkWindow, @GtkLeft, @GtkTop);
|
||||
Left:=GtkLeft;
|
||||
Top:=GtkTop;
|
||||
end else begin
|
||||
LCLControl:=GetLCLObject(aWidget) as TWinControl;
|
||||
Left:=LCLControl.Left;
|
||||
Top:=LCLControl.Top;
|
||||
end;
|
||||
end;
|
||||
//DebugLn(['TGtkWidgetSet.GetWindowRelativePosition ',GetWidgetDebugReport(aWidget),' Left=',Left,' Top=',Top]);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
UnsetResizeRequest
|
||||
Params: Widget: PGtkWidget
|
||||
|
||||
Unset the mark for the Widget to send a ResizeRequest to the gtk.
|
||||
LCL size requests for a widget are cached and only the last one is sent. Some
|
||||
widgets like forms send a resize request immediately. To avoid sending resize
|
||||
requests multiple times they can unset the mark with this procedure.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure UnsetResizeRequest(Widget: PGtkWidget);
|
||||
begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if FWidgetsWithResizeRequest.Contains(Widget) then begin
|
||||
DebugLn(['UnsetResizeRequest ',GetWidgetDebugReport(Widget)]);
|
||||
end;
|
||||
{$ENDIF}
|
||||
FWidgetsWithResizeRequest.Remove(Widget);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TGtkWidgetSet SetResizeRequest
|
||||
Params: Widget: PGtkWidget
|
||||
|
||||
Marks the widget to send a ResizeRequest to the gtk.
|
||||
When the LCL resizes a control the new bounds will not be set directly, but
|
||||
cached. This is needed, because it is common behaviour to set the bounds step
|
||||
by step. For example: Left:=10; Top:=10; Width:=100; Height:=50; results in
|
||||
SetBounds(10,0,0,0);
|
||||
SetBounds(10,10,0,0);
|
||||
SetBounds(10,10,100,0);
|
||||
SetBounds(10,10,100,50);
|
||||
Because the gtk puts all size requests into a queue, it will process the
|
||||
requests not immediately, but _after_ all requests. This results in changing
|
||||
the widget size four times and everytime the LCL gets a message. If the
|
||||
control has childs, this will resize the childs four times.
|
||||
Therefore LCL size requests for a widget are cached and only the final one is
|
||||
sent in: TGtkWidgetSet.SendCachedLCLMessages.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure SetResizeRequest(Widget: PGtkWidget);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
var
|
||||
LCLControl: TWinControl;
|
||||
{$ENDIF}
|
||||
begin
|
||||
{$IFDEF Gtk2}
|
||||
if not WidgetSizeIsEditable(Widget) then exit;
|
||||
{$ENDIF}
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
LCLControl:=TWinControl(GetLCLObject(Widget));
|
||||
DbgOut('SetResizeRequest Widget=',DbgS(Widget));
|
||||
if LCLControl is TWinControl then
|
||||
DebugLn(' ',DbgSName(LCLControl),' LCLBounds=',dbgs(LCLControl.BoundsRect))
|
||||
else
|
||||
DebugLn(' ERROR: ',DbgSName(LCLControl));
|
||||
{$ENDIF}
|
||||
if not FWidgetsWithResizeRequest.Contains(Widget) then
|
||||
FWidgetsWithResizeRequest.Add(Widget);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
function WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
|
||||
|
||||
True if the widget can be resized.
|
||||
False if the size is under complete control of the gtk.
|
||||
------------------------------------------------------------------------------}
|
||||
function WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
|
||||
begin
|
||||
if Widget=nil then exit(false);
|
||||
if (GtkWidgetIsA(Widget,GTK_TYPE_WINDOW))
|
||||
or (GtkWidgetIsA(Widget^.Parent,gtk_fixed_get_type))
|
||||
or (GtkWidgetIsA(Widget^.Parent,gtk_layout_get_type))
|
||||
then
|
||||
Result:=true
|
||||
else
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
Procedure ReportNotObsolete(const Texts : String);
|
||||
Begin
|
||||
DebugLn('*********************************************');
|
||||
@ -7769,7 +7914,12 @@ begin
|
||||
gtk_menu_append(GetStyleWidget(lgsMenu),StyleObject^.Widget);
|
||||
end else if GtkWidgetIsA(StyleObject^.Widget,GTK_TYPE_MENU_ITEM) then begin
|
||||
DebugLn(['GetStyleWithName adding menuitem to menubar']);
|
||||
gtk_menu_bar_append(GetStyleWidget(lgsMenuBar),StyleObject^.Widget);
|
||||
gtk_menu_bar_append({$IFDEF Gtk1}
|
||||
PGtkMenuBar(GetStyleWidget(lgsMenuBar)),
|
||||
{$ELSE}
|
||||
GetStyleWidget(lgsMenuBar),
|
||||
{$ENDIF}
|
||||
StyleObject^.Widget);
|
||||
end else begin
|
||||
StyleWindowWidget:=GetStyleWidget(lgsWindow);
|
||||
// add widget on client area of form
|
||||
|
@ -701,14 +701,19 @@ function gtkListGetSelectionMode(list: PGtkList): TGtkSelectionMode;cdecl;
|
||||
// sizing
|
||||
procedure SaveSizeNotification(Widget: PGtkWidget);
|
||||
procedure SaveClientSizeNotification(FixWidget: PGtkWidget);
|
||||
procedure SendSizeNotificationToLCL(aWidget: PGtkWidget);
|
||||
function CreateTopologicalSortedWidgets(HashArray: TDynHashArray): TFPList;
|
||||
procedure GetGTKDefaultWidgetSize(AWinControl: TWinControl;
|
||||
var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean);
|
||||
procedure SendSizeNotificationToLCL(aWidget: PGtkWidget);
|
||||
procedure SendCachedGtkResizeNotifications;
|
||||
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth, NewHeight: integer);
|
||||
procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);
|
||||
procedure SetWindowSizeAndPosition(Window: PGtkWindow; AWinControl: TWinControl);
|
||||
procedure ResizeHandle(LCLControl: TWinControl);
|
||||
procedure SetWidgetSize(Widget: PGtkWidget; NewWidth, NewHeight: integer);
|
||||
procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);// for child controls
|
||||
procedure SetWindowSizeAndPosition(Window: PGtkWindow; AWinControl: TWinControl);// for top level control
|
||||
procedure GetWidgetRelativePosition(aWidget: PGtkWidget; var Left, Top: integer);
|
||||
procedure UnsetResizeRequest(Widget: PGtkWidget);
|
||||
procedure SetResizeRequest(Widget: PGtkWidget);
|
||||
function WidgetSizeIsEditable(Widget: PGtkWidget): boolean;
|
||||
|
||||
// debug
|
||||
procedure ReportNotObsolete(const Texts: String);
|
||||
|
@ -4581,10 +4581,11 @@ var
|
||||
Widget, ClientWidget: PGtkWidget;
|
||||
{$IFDEF Gtk1}
|
||||
MainOrigin: TPoint;
|
||||
{$ELSE}
|
||||
CurGDKWindow: PGdkWindow;
|
||||
{$ENDIF}
|
||||
ClientOrigin: TPoint;
|
||||
ClientWindow, MainWindow: PGdkWindow;
|
||||
CurGDKWindow: PGdkWindow;
|
||||
begin
|
||||
Result := False;
|
||||
if Handle = 0 then Exit;
|
||||
@ -4675,6 +4676,42 @@ end;
|
||||
Function TGtkWidgetSet.GetClientRect(handle : HWND; var ARect : TRect) : Boolean;
|
||||
var
|
||||
Widget, ClientWidget: PGtkWidget;
|
||||
|
||||
{$IFDEF Gtk2}
|
||||
procedure GetNoteBookClientRect(NBWidget: PGtkNotebook);
|
||||
var
|
||||
PageIndex: LongInt;
|
||||
PageWidget: PGtkWidget;
|
||||
FrameBorders: TRect;
|
||||
aWidth: LongInt;
|
||||
aHeight: LongInt;
|
||||
begin
|
||||
// get current page
|
||||
PageIndex:=gtk_notebook_get_current_page(NBWidget);
|
||||
if PageIndex>=0 then
|
||||
PageWidget:=gtk_notebook_get_nth_page(NBWidget,PageIndex)
|
||||
else
|
||||
PageWidget:=nil;
|
||||
if (PageWidget<>nil)
|
||||
and ((PageWidget^.Allocation.Width>1) or (PageWidget^.Allocation.Height>1))
|
||||
then begin
|
||||
// get the size of the current page
|
||||
ARect.Right:=PageWidget^.Allocation.Width;
|
||||
ARect.Bottom:=PageWidget^.Allocation.Height;
|
||||
//DebugLn(['GetNoteBookClientRect using pagewidget: ',GetWidgetDebugReport(Widget),' ARect=',dbgs(aRect)]);
|
||||
end else begin
|
||||
// use defaults
|
||||
FrameBorders:=GetStyleNotebookFrameBorders;
|
||||
aWidth:=Widget^.allocation.width;
|
||||
aHeight:=Widget^.allocation.height;
|
||||
ARect:=Rect(0,0,
|
||||
Max(0,AWidth-FrameBorders.Left-FrameBorders.Right),
|
||||
Max(0,aHeight-FrameBorders.Top-FrameBorders.Bottom));
|
||||
//DebugLn(['GetNoteBookClientRect using defaults: ',GetWidgetDebugReport(Widget),' ARect=',dbgs(aRect)]);
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
begin
|
||||
Result := false;
|
||||
if Handle = 0 then Exit;
|
||||
@ -4691,6 +4728,10 @@ begin
|
||||
ARect.Right:=0;
|
||||
ARect.Bottom:=0;
|
||||
end;
|
||||
{$IFDEF Gtk2}
|
||||
if GtkWidgetIsA(Widget,GTK_TYPE_NOTEBOOK) then
|
||||
GetNoteBookClientRect(PGtkNoteBook(Widget));
|
||||
{$ENDIF}
|
||||
{$IfDef VerboseGetClientRect}
|
||||
if ClientWidget<>nil then begin
|
||||
DebugLn('GetClientRect Widget=',DbgS(handle),
|
||||
@ -6431,31 +6472,11 @@ function TGtkWidgetSet.GetWindowRelativePosition(Handle : hwnd;
|
||||
var Left, Top: integer): boolean;
|
||||
var
|
||||
aWidget: PGtkWidget;
|
||||
{$IFDEF Gtk2}
|
||||
GdkWindow: PGdkWindow;
|
||||
GtkLeft, GtkTop: gint;
|
||||
{$ENDIF}
|
||||
begin
|
||||
aWidget:=PGtkWidget(Handle);
|
||||
if GtkWidgetIsA(aWidget,GTK_TYPE_WIDGET) then begin
|
||||
Result:=true;
|
||||
Left:=aWidget^.allocation.X;
|
||||
Top:=aWidget^.allocation.Y;
|
||||
{$IFDEF Gtk2}
|
||||
if (aWidget^.window=nil) and (aWidget^.parent<>nil) then begin
|
||||
inc(Left,aWidget^.parent^.allocation.X);
|
||||
inc(Top,aWidget^.parent^.allocation.Y);
|
||||
end;
|
||||
if GtkWidgetIsA(aWidget,GTK_TYPE_WINDOW) then begin
|
||||
GdkWindow:=GetControlWindow(aWidget);
|
||||
if GdkWindow<>nil then begin
|
||||
gdk_window_get_root_origin(GdkWindow, @GtkLeft, @GtkTop);
|
||||
Left:=GtkLeft;
|
||||
Top:=GtkTop;
|
||||
end;
|
||||
end;
|
||||
//DebugLn(['TGtkWidgetSet.GetWindowRelativePosition ',GetWidgetDebugReport(aWidget),' Left=',Left,' Top=',Top]);
|
||||
{$ENDIF}
|
||||
GetWidgetRelativePosition(aWidget,Left,Top);
|
||||
end else
|
||||
Result:=false;
|
||||
end;
|
||||
|
@ -282,12 +282,13 @@ begin
|
||||
TGtkWidgetSet(WidgetSet).ShowHide(AWinControl);
|
||||
end;
|
||||
|
||||
class procedure TGtkWSWinControl.SetBounds(const AWinControl: TWinControl; const ALeft, ATop, AWidth, AHeight: Integer);
|
||||
class procedure TGtkWSWinControl.SetBounds(const AWinControl: TWinControl;
|
||||
const ALeft, ATop, AWidth, AHeight: Integer);
|
||||
begin
|
||||
if not WSCheckHandleAllocated(AWinControl, 'SetBounds')
|
||||
then Exit;
|
||||
|
||||
TGtkWidgetSet(WidgetSet).SetResizeRequest(PGtkWidget(AWinControl.Handle));
|
||||
ResizeHandle(AWinControl);
|
||||
end;
|
||||
|
||||
class procedure TGtkWSWinControl.SetBorderStyle(const AWinControl: TWinControl;
|
||||
@ -634,7 +635,7 @@ end;
|
||||
procedure GtkWindowShowModal(GtkWindow: PGtkWindow);
|
||||
begin
|
||||
if (GtkWindow=nil) then exit;
|
||||
TGtkWidgetSet(WidgetSet).UnsetResizeRequest(PgtkWidget(GtkWindow));
|
||||
UnsetResizeRequest(PgtkWidget(GtkWindow));
|
||||
|
||||
if ModalWindows=nil then ModalWindows:=TFPList.Create;
|
||||
ModalWindows.Add(GtkWindow);
|
||||
|
@ -262,7 +262,7 @@ class procedure TGtkWSCustomNotebook.AddPage(const ANotebook: TCustomNotebook;
|
||||
Inserts a new page to a notebook at position Index. The ANotebook is a
|
||||
TCustomNoteBook, the AChild one of its TCustomPage. Both handles must already
|
||||
be created. ANoteBook Handle is a PGtkNoteBook and APage handle is a
|
||||
PGtkFixed.
|
||||
PGtkHBox.
|
||||
This procedure creates a new tab with an optional image, the page caption and
|
||||
an optional close button. The image and the caption will also be added to the
|
||||
tab popup menu.
|
||||
@ -330,7 +330,7 @@ begin
|
||||
// remove the dummy page (a gtk_notebook needs at least one page)
|
||||
RemoveDummyNoteBookPage(PGtkNotebook(NoteBookWidget));
|
||||
// insert the page
|
||||
gtk_notebook_insert_page_menu(GTK_NOTEBOOK(NotebookWidget), PageWidget,
|
||||
gtk_notebook_insert_page_menu(PGtkNotebook(NotebookWidget), PageWidget,
|
||||
TabWidget, MenuWidget, AIndex);
|
||||
|
||||
UpdateNotebookPageTab(ANoteBook, AChild);
|
||||
@ -341,7 +341,7 @@ begin
|
||||
allocation.y:=ANoteBook.Top;
|
||||
allocation.width:=ANoteBook.Width;
|
||||
allocation.height:=ANoteBook.Height;
|
||||
gtk_widget_size_allocate(PageWidget^.parent,@allocation);
|
||||
gtk_widget_size_allocate(NotebookWidget,@allocation);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
DebugLn(['TGtkWSCustomNotebook.AddPage PageWidget^.allocation=',dbgs(PageWidget^.allocation),' NotebookWidget=',dbgs(NotebookWidget^.allocation)]);
|
||||
{$ENDIF}
|
||||
|
@ -264,7 +264,9 @@ begin
|
||||
Max(0,aHeight-FrameBorders.Top-FrameBorders.Bottom));
|
||||
Result:=true;
|
||||
end;
|
||||
//if Result then DebugLn(['TGtk2WSCustomNotebook.GetDefaultClientRect END FrameBorders=',dbgs(FrameBorders),' aClientRect=',dbgs(aClientRect)]);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if Result then DebugLn(['TGtk2WSCustomNotebook.GetDefaultClientRect END FrameBorders=',dbgs(FrameBorders),' aClientRect=',dbgs(aClientRect)]);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
|
||||
@ -277,14 +279,17 @@ begin
|
||||
Result:=false;
|
||||
if AWinControl.Parent=nil then exit;
|
||||
if AWinControl.HandleAllocated and AWinControl.Parent.HandleAllocated
|
||||
and (PGtkWidget(AWinControl.Handle)^.parent=nil) then
|
||||
and (PGtkWidget(AWinControl.Handle)^.parent<>nil) then
|
||||
begin
|
||||
|
||||
end else begin
|
||||
Result:=true;
|
||||
aClientRect:=AWinControl.Parent.ClientRect;
|
||||
//DebugLn(['TGtk2WSCustomPage.GetDefaultClientRect ',DbgSName(AWinControl),' Parent=',DbgSName(AWinControl.Parent),' ParentBounds=',dbgs(AWinControl.Parent.BoundsRect),' ParentClient=',dbgs(AWinControl.Parent.ClientRect)]);
|
||||
end;
|
||||
//if Result then DebugLn(['TGtk2WSCustomPage.GetDefaultClientRect ',DbgSName(AWinControl),' aClientRect=',dbgs(aClientRect)]);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if Result then DebugLn(['TGtk2WSCustomPage.GetDefaultClientRect ',DbgSName(AWinControl),' aClientRect=',dbgs(aClientRect)]);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user