gtk2 intf: improved resizing code to not need the caching trick

git-svn-id: trunk@11212 -
This commit is contained in:
mattias 2007-05-29 00:30:26 +00:00
parent 78509220c9
commit 1eff85d939
11 changed files with 278 additions and 190 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
{------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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}

View File

@ -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