LCL: added BeginAlign/EndAlign in TWinControl.Loaded to reduce overhead, gtk2 intf: added GetDefaultClientRect for TGroupBox, doing some resizes now immediately

git-svn-id: trunk@11160 -
This commit is contained in:
mattias 2007-05-17 21:43:48 +00:00
parent 58a04388c9
commit f1ddc29682
16 changed files with 838 additions and 605 deletions

View File

@ -1465,7 +1465,8 @@ type
wcfEraseBackground, wcfEraseBackground,
wcfCreatingHandle, // Set while constructing the handle of this control wcfCreatingHandle, // Set while constructing the handle of this control
wcfInitializing, // Set while initializing during handle creation wcfInitializing, // Set while initializing during handle creation
wcfCreatingChildHandles // Set while constructing the handles of the childs wcfCreatingChildHandles, // Set while constructing the handles of the childs
wcfHandleVisible
); );
TWinControlFlags = set of TWinControlFlag; TWinControlFlags = set of TWinControlFlag;
@ -1563,6 +1564,7 @@ type
procedure CMDrag(var Message: TCMDrag); message CM_DRAG; procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
procedure CMShowingChanged(var Message: TLMessage); message CM_SHOWINGCHANGED; procedure CMShowingChanged(var Message: TLMessage); message CM_SHOWINGCHANGED;
procedure CMVisibleChanged(var TheMessage: TLMessage); message CM_VISIBLECHANGED; procedure CMVisibleChanged(var TheMessage: TLMessage); message CM_VISIBLECHANGED;
procedure DoSendShowHideToInterface; virtual;
procedure ControlsAligned; virtual; procedure ControlsAligned; virtual;
procedure DoSendBoundsToInterface; virtual; procedure DoSendBoundsToInterface; virtual;
procedure RealizeBounds; virtual; procedure RealizeBounds; virtual;

View File

@ -398,8 +398,8 @@ type
{$ENDIF} {$ENDIF}
{ TGraphicsObject { TGraphicsObject
In Delphi VCL this is the ancestor of TFon, TPen and TBrush. In Delphi VCL this is the ancestor of TFont, TPen and TBrush.
With FPC 2.0 the LCL uses TFPCanvasHelper. } Since FPC 2.0 the LCL uses TFPCanvasHelper as ancestor. }
TGraphicsObject = class(TPersistent) TGraphicsObject = class(TPersistent)
private private

View File

@ -336,6 +336,7 @@ begin
DebugLn('TControl.ChangeBounds A ',Name,':',ClassName, DebugLn('TControl.ChangeBounds A ',Name,':',ClassName,
' Old='+dbgs(Left)+','+dbgs(Top)+','+dbgs(Width),',',dbgs(Height), ' Old='+dbgs(Left)+','+dbgs(Top)+','+dbgs(Width),',',dbgs(Height),
' New='+dbgs(ALeft)+','+dbgs(ATop)+','+dbgs(AWidth),',',dbgs(AHeight)); ' 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
{$ENDIF} {$ENDIF}
// constraint the size // constraint the size
DoConstrainedResize(ALeft, ATop, AWidth, AHeight); DoConstrainedResize(ALeft, ATop, AWidth, AHeight);
@ -1212,17 +1213,17 @@ begin
Result:=ClientRect.Right; Result:=ClientRect.Right;
end; end;
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------
{ TControl GetEnabled } TControl GetEnabled
{------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TControl.GetEnabled: Boolean; function TControl.GetEnabled: Boolean;
begin begin
Result := FEnabled; Result := FEnabled;
end; end;
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------
{ TControl GetMouseCapture } TControl GetMouseCapture
{------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
Function TControl.GetMouseCapture : Boolean; Function TControl.GetMouseCapture : Boolean;
Begin Begin
Result := GetCaptureControl = Self; Result := GetCaptureControl = Self;
@ -1236,9 +1237,9 @@ begin
Result := UndockHeight; Result := UndockHeight;
end; end;
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------
{ TControl GetPopupMenu } TControl GetPopupMenu
{------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TControl.GetPopupMenu: TPopupMenu; function TControl.GetPopupMenu: TPopupMenu;
begin begin
Result := FPopupMenu; Result := FPopupMenu;
@ -2195,8 +2196,10 @@ end;
procedure TControl.SetClientHeight(Value: Integer); procedure TControl.SetClientHeight(Value: Integer);
begin begin
if csLoading in ComponentState then begin if csLoading in ComponentState then begin
{$IFDEF DisableLoadedClientSize}
FLoadedClientSize.Y:=Value; FLoadedClientSize.Y:=Value;
Include(FControlFlags,cfClientHeightLoaded); Include(FControlFlags,cfClientHeightLoaded);
{$ENDIF}
end else begin end else begin
// during loading the ClientHeight is not used to set the Height of the // during loading the ClientHeight is not used to set the Height of the
// control, but only to restore autosizing. For example Anchors=[akBottom] // control, but only to restore autosizing. For example Anchors=[akBottom]
@ -2223,8 +2226,10 @@ end;
procedure TControl.SetClientWidth(Value: Integer); procedure TControl.SetClientWidth(Value: Integer);
begin begin
if csLoading in ComponentState then begin if csLoading in ComponentState then begin
{$IFDEF DisableLoadedClientSize}
FLoadedClientSize.X:=Value; FLoadedClientSize.X:=Value;
Include(FControlFlags,cfClientWidthLoaded); Include(FControlFlags,cfClientWidthLoaded);
{$ENDIF}
end else begin end else begin
// during loading the ClientWidth is not used to set the Width of the // during loading the ClientWidth is not used to set the Width of the
// control, but only to restore autosizing. For example Anchors=[akRight] // control, but only to restore autosizing. For example Anchors=[akRight]

View File

@ -1752,7 +1752,12 @@ procedure TCustomForm.Loaded;
var var
Control: TWinControl; Control: TWinControl;
begin begin
inherited Loaded; DisableAlign;
try
inherited Loaded;
finally
EnableAlign;
end;
if (ActiveControl <> nil) and (Parent=nil) then if (ActiveControl <> nil) and (Parent=nil) then
begin begin
Control := ActiveControl; Control := ActiveControl;

View File

@ -27,8 +27,8 @@
{ $DEFINE CHECK_POSITION} { $DEFINE CHECK_POSITION}
{ $IFDEF CHECK_POSITION} { $IFDEF CHECK_POSITION}
const CheckPostionClassName = 'THintWindow'; const CheckPostionClassName = 'xxTHintWindow';
const CheckPostionName = 'ListBox1'; const CheckPostionName = 'xxListBox1';
function CheckPosition(AControl: TControl): boolean; function CheckPosition(AControl: TControl): boolean;
begin begin
@ -1065,6 +1065,8 @@ var
var var
NewLeft, NewTop, NewWidth, NewHeight: Integer; NewLeft, NewTop, NewWidth, NewHeight: Integer;
ParentBaseClientSize: TPoint; ParentBaseClientSize: TPoint;
ParentClientWidth: integer;
ParentClientHeight: integer;
CurBaseBounds: TRect; CurBaseBounds: TRect;
NewRight: Integer;// temp variable, not always valid, use with care ! NewRight: Integer;// temp variable, not always valid, use with care !
NewBottom: Integer;// temp variable, not always valid, use with care ! NewBottom: Integer;// temp variable, not always valid, use with care !
@ -1194,8 +1196,9 @@ var
ConstraintWidth(NewLeft,NewWidth); ConstraintWidth(NewLeft,NewWidth);
ConstraintHeight(NewTop,NewHeight); ConstraintHeight(NewTop,NewHeight);
end; end;
ParentClientWidth:=Control.Parent.ClientWidth;
ParentClientHeight:=Control.Parent.ClientHeight;
InitAnchorSideCache; InitAnchorSideCache;
{ Recalculate the anchors { Recalculate the anchors
@ -1205,7 +1208,7 @@ var
This is controlled with the AnchorSide properties. This is controlled with the AnchorSide properties.
1. If AnchorSide[].Control is not set, the distance is kept relative to 1. If AnchorSide[].Control is not set, the distance is kept relative to
the edges of the client are of its parent. the edges of the client area of its parent.
When its parent is resized, the control holds its position relative to the When its parent is resized, the control holds its position relative to the
edges to which it is anchored. edges to which it is anchored.
If a control is anchored to opposite edges of its parent, the control If a control is anchored to opposite edges of its parent, the control
@ -1230,8 +1233,7 @@ var
ParentBaseClientSize:=Control.FBaseParentClientSize; ParentBaseClientSize:=Control.FBaseParentClientSize;
if (ParentBaseClientSize.X=0) if (ParentBaseClientSize.X=0)
and (ParentBaseClientSize.Y=0) then and (ParentBaseClientSize.Y=0) then
ParentBaseClientSize:=Point(Control.Parent.ClientWidth, ParentBaseClientSize:=Point(ParentClientWidth,ParentClientHeight);
Control.Parent.ClientHeight);
// get base bounds of Control // get base bounds of Control
CurBaseBounds:=Control.FBaseBounds; CurBaseBounds:=Control.FBaseBounds;
@ -1246,7 +1248,7 @@ var
' Self='+DbgSName(Self),' Control='+DbgSName(Control), ' Self='+DbgSName(Self),' Control='+DbgSName(Control),
' CurBaseBounds='+dbgs(CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Top)+','+dbgs(CurBaseBounds.Right-CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Bottom-CurBaseBounds.Top), ' CurBaseBounds='+dbgs(CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Top)+','+dbgs(CurBaseBounds.Right-CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Bottom-CurBaseBounds.Top),
' ParentBaseClientSize='+dbgs(ParentBaseClientSize.X)+','+dbgs(ParentBaseClientSize.Y), ' ParentBaseClientSize='+dbgs(ParentBaseClientSize.X)+','+dbgs(ParentBaseClientSize.Y),
' ControlParent.Client='+dbgs(Control.Parent.ClientWidth)+','+dbgs(Control.Parent.ClientHeight), ' ControlParent.Client='+dbgs(ParentClientWidth)+','+dbgs(ParentClientHeight),
' NewBounds='+dbgs(NewLeft)+','+dbgs(NewTop)+','+dbgs(NewWidth)+','+dbgs(NewHeight), ' NewBounds='+dbgs(NewLeft)+','+dbgs(NewTop)+','+dbgs(NewWidth)+','+dbgs(NewHeight),
''); '');
{$ENDIF} {$ENDIF}
@ -1257,7 +1259,7 @@ var
if akRight in CurAnchors then begin if akRight in CurAnchors then begin
// keep distance to right side of parent or another sibling // keep distance to right side of parent or another sibling
// -> change the width // -> change the width
NewRight:=Control.Parent.ClientWidth NewRight:=ParentClientWidth
-(ParentBaseClientSize.X-CurBaseBounds.Right); -(ParentBaseClientSize.X-CurBaseBounds.Right);
if (not (akRight in CurAlignAnchors)) if (not (akRight in CurAlignAnchors))
and (akRight in Control.Anchors) then and (akRight in Control.Anchors) then
@ -1272,7 +1274,7 @@ var
if akRight in CurAnchors then begin if akRight in CurAnchors then begin
// keep distance to right side of parent // keep distance to right side of parent
// and keep new width // and keep new width
NewRight:=Control.Parent.ClientWidth NewRight:=ParentClientWidth
-(ParentBaseClientSize.X-CurBaseBounds.Right); -(ParentBaseClientSize.X-CurBaseBounds.Right);
if (not (akRight in CurAlignAnchors)) if (not (akRight in CurAlignAnchors))
and (akRight in Control.Anchors) then and (akRight in Control.Anchors) then
@ -1281,7 +1283,7 @@ var
end else begin end else begin
// do not anchor to the right // do not anchor to the right
// -> keep new width and center horizontally // -> keep new width and center horizontally
NewLeft:=(Control.Parent.ClientWidth-NewWidth) div 2; NewLeft:=(ParentClientWidth-NewWidth) div 2;
end; end;
end; end;
@ -2146,21 +2148,11 @@ end;
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TWinControl.DoSetBounds(ALeft, ATop, AWidth, AHeight : integer); procedure TWinControl.DoSetBounds(ALeft, ATop, AWidth, AHeight : integer);
begin begin
if wcfClientRectNeedsUpdate in FWinControlFlags then begin
GetClientRect;
end;
{$IFDEF VerboseClientRectBugFix} {$IFDEF VerboseClientRectBugFix}
DbgOut('[TWinControl.DoSetBounds] ',Name,':',ClassName,' OldClient=',DbgS(FClientWidth),',',DbgS(FClientHeight), DbgOut('[TWinControl.DoSetBounds] ',Name,':',ClassName,
' OldHeight=',DbgS(FHeight),' NewHeight=',DbgS(AHeight)); ' OldHeight=',DbgS(FHeight),' NewHeight=',DbgS(AHeight));
{$ENDIF} {$ENDIF}
inc(FClientWidth,AWidth-FWidth); InvalidateClientRectCache(false);
if (FClientWidth<0) then FClientWidth:=0;
inc(FClientHeight,AHeight-FHeight);
if (FClientHeight<0) then FClientHeight:=0;
{$IFDEF VerboseClientRectBugFix}
DebugLn(' NewClient=',DbgS(FClientWidth),',',DbgS(FClientHeight));
{$ENDIF}
inherited DoSetBounds(ALeft,ATop,AWidth,AHeight); inherited DoSetBounds(ALeft,ATop,AWidth,AHeight);
end; end;
@ -2307,20 +2299,35 @@ function TWinControl.GetClientRect: TRect;
var var
InterfaceWidth, InterfaceHeight: integer; InterfaceWidth, InterfaceHeight: integer;
begin begin
if not HandleAllocated then begin if wcfClientRectNeedsUpdate in FWinControlFlags then begin
Result:=inherited GetClientRect; if TWSWinControlClass(WidgetSetClass).GetDefaultClientRect(Self,
StoreClientRect(Result); Left, Top, Width, Height, Result)
end else if wcfClientRectNeedsUpdate in FWinControlFlags then begin then begin
// update clientrect from interface // the LCL interface provided a ClientRect
LCLIntf.GetClientRect(Handle, Result); end
// the LCL is not always in sync with the interface else if HandleAllocated then begin
// -> adjust client rect based on LCL bounds // update clientrect from interface
// for example: if the Width in LCL differ from the Width of the Interface LCLIntf.GetClientRect(Handle, Result);
// object, then adjust the clientwidth accordingly // the LCL is not always in sync with the interface
LCLIntf.GetWindowSize(Handle, InterfaceWidth, InterfaceHeight); // -> adjust client rect based on LCL bounds
//debugln('TWinControl.GetClientRect ',DbgSName(Self),' Interface=',dbgs(InterfaceWidth),',',dbgs(InterfaceHeight),' Result=',dbgs(Result),' Bounds=',dbgs(BoundsRect)); // for example: if the Width in LCL differ from the Width of the Interface
Result.Right:=Width-(InterfaceWidth-Result.Right); // object, then adjust the clientwidth accordingly
Result.Bottom:=Height-(InterfaceHeight-Result.Bottom); // this often anticipates later LM_SIZE messages from the interface
// and reduces resizes
LCLIntf.GetWindowSize(Handle, InterfaceWidth, InterfaceHeight);
//debugln('TWinControl.GetClientRect ',DbgSName(Self),' Interface=',dbgs(InterfaceWidth),',',dbgs(InterfaceHeight),' Result=',dbgs(Result),' Bounds=',dbgs(BoundsRect));
Result.Right:=Width-(InterfaceWidth-Result.Right);
Result.Bottom:=Height-(InterfaceHeight-Result.Bottom);
end else begin
// no handle and no interface help => use defaults
Result:=inherited GetClientRect;
if csLoading in ComponentState then begin
if cfClientWidthLoaded in FControlFlags then
Result.Right:=FLoadedClientSize.X;
if cfClientHeightLoaded in FControlFlags then
Result.Bottom:=FLoadedClientSize.Y;
end;
end;
StoreClientRect(Result); StoreClientRect(Result);
{r:=inherited GetClientRect; {r:=inherited GetClientRect;
@ -4509,7 +4516,7 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
constructor TWinControl.Create(TheOwner : TComponent); constructor TWinControl.Create(TheOwner : TComponent);
begin begin
// do not set borderstyle, as tcustomform needs to set it before calling // do not set borderstyle, because TCustomForm needs to set it before calling
// inherited, to have it set before handle is created via streaming // inherited, to have it set before handle is created via streaming
// use property that bsNone is zero // use property that bsNone is zero
//FBorderStyle := bsNone; //FBorderStyle := bsNone;
@ -4521,11 +4528,12 @@ begin
FParentCtl3D:=true; FParentCtl3D:=true;
FTabOrder := -1; FTabOrder := -1;
FTabStop := False; FTabStop := False;
InvalidateClientRectCache(false);
end; end;
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------
{ TWinControl CreateParented } TWinControl CreateParented
{------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
constructor TWinControl.CreateParented(ParentWindow: hwnd); constructor TWinControl.CreateParented(ParentWindow: hwnd);
begin begin
FParentWindow := ParentWindow; FParentWindow := ParentWindow;
@ -4845,8 +4853,8 @@ var
begin begin
{$IFDEF VerboseSizeMsg} {$IFDEF VerboseSizeMsg}
if CheckPosition(Self) then if CheckPosition(Self) then
DebugLn('TWinControl.WMSize A ',Name,':',ClassName,' Message=',dbgs(Message.Width),',',dbgs(Message.Height), DebugLn(['TWinControl.WMSize A ',Name,':',ClassName,' Message=',Message.Width,',',Message.Height,
' BoundsRealized=',dbgs(FBoundsRealized),' FromIntf=',(Message.SizeType and Size_SourceIsInterface)>0)); ' BoundsRealized=',dbgs(FBoundsRealized),' FromIntf=',(Message.SizeType and Size_SourceIsInterface)>0]);
{$ENDIF} {$ENDIF}
NewLeft:=Left; NewLeft:=Left;
NewTop:=Top; NewTop:=Top;
@ -4859,7 +4867,7 @@ begin
GetWindowRelativePosition(Handle,NewLeft,NewTop); GetWindowRelativePosition(Handle,NewLeft,NewTop);
//DebugLn('TWinControl.WMSize B ',Name,':',ClassName,' ',NewLeft,',',NewTop); //DebugLn('TWinControl.WMSize B ',Name,':',ClassName,' ',NewLeft,',',NewTop);
NewBoundsRealized:=Bounds(NewLeft,NewTop,Message.Width,Message.Height); NewBoundsRealized:=Bounds(NewLeft,NewTop,Message.Width,Message.Height);
If CompareRect(@NewBoundsRealized,@FBoundsRealized) then exit; if CompareRect(@NewBoundsRealized,@FBoundsRealized) then exit;
FBoundsRealized:=NewBoundsRealized; FBoundsRealized:=NewBoundsRealized;
InvalidatePreferredSize; InvalidatePreferredSize;
end; end;
@ -5390,54 +5398,57 @@ var
AChild: TControl; AChild: TControl;
LoadedClientSize: TPoint; LoadedClientSize: TPoint;
begin begin
//DebugLn(['TWinControl.Loaded ',DbgSName(Self),' cfWidthLoaded=',cfWidthLoaded in FControlFlags,' cfHeightLoaded=',cfHeightLoaded in FControlFlags,' ']); DisableAlign;
if cfClientWidthLoaded in FControlFlags then try
LoadedClientSize.X:=FLoadedClientSize.X //DebugLn(['TWinControl.Loaded ',DbgSName(Self),' cfWidthLoaded=',cfWidthLoaded in FControlFlags,' cfHeightLoaded=',cfHeightLoaded in FControlFlags,' ']);
else begin if cfClientWidthLoaded in FControlFlags then
LoadedClientSize.X:=ClientWidth; LoadedClientSize.X:=FLoadedClientSize.X
if LoadedClientSize.X<=0 then else begin
LoadedClientSize.X:=Width; LoadedClientSize.X:=ClientWidth;
end; if LoadedClientSize.X<=0 then
if cfClientHeightLoaded in FControlFlags then LoadedClientSize.X:=Width;
LoadedClientSize.Y:=FLoadedClientSize.Y
else begin
LoadedClientSize.Y:=ClientHeight;
if LoadedClientSize.Y<=0 then
LoadedClientSize.Y:=Height;
end;
for i:=0 to ControlCount-1 do begin
AChild:=Controls[i];
if AChild=nil then ;
AChild.FBaseParentClientSize:=LoadedClientSize;
//DebugLn(['TWinControl.Loaded Self=',DbgSName(Self),' AChild=',AChild,' AChild.FBaseParentClientSize=',dbgs(AChild.FBaseParentClientSize)]);
end;
if HandleAllocated then begin
// Set cached caption
if GetCachedText(CachedText) then
TWSWinControlClass(WidgetSetClass).SetText(Self, CachedText);
InvalidatePreferredSize;
if wcfColorChanged in FWinControlFlags then begin
TWSWinControlClass(WidgetSetClass).SetColor(Self);
Exclude(FWinControlFlags,wcfColorChanged);
end; end;
if wcfFontChanged in FWinControlFlags then begin if cfClientHeightLoaded in FControlFlags then
TWSWinControlClass(WidgetSetClass).SetFont(Self,Font); LoadedClientSize.Y:=FLoadedClientSize.Y
NotifyControls(CM_PARENTCOLORCHANGED); else begin
for i := 0 to ControlCount - 1 do LoadedClientSize.Y:=ClientHeight;
Controls[i].ParentFontChanged; if LoadedClientSize.Y<=0 then
FWinControlFlags:=FWinControlFlags-[wcfFontChanged]; LoadedClientSize.Y:=Height;
end; end;
for i:=0 to ControlCount-1 do begin
AChild:=Controls[i];
if AChild=nil then ;
AChild.FBaseParentClientSize:=LoadedClientSize;
//DebugLn(['TWinControl.Loaded Self=',DbgSName(Self),' AChild=',AChild,' AChild.FBaseParentClientSize=',dbgs(AChild.FBaseParentClientSize)]);
end;
if HandleAllocated then begin
// Set cached caption
if GetCachedText(CachedText) then
TWSWinControlClass(WidgetSetClass).SetText(Self, CachedText);
InvalidatePreferredSize;
if wcfColorChanged in FWinControlFlags then begin
TWSWinControlClass(WidgetSetClass).SetColor(Self);
Exclude(FWinControlFlags,wcfColorChanged);
end;
if wcfFontChanged in FWinControlFlags then begin
TWSWinControlClass(WidgetSetClass).SetFont(Self,Font);
NotifyControls(CM_PARENTCOLORCHANGED);
for i := 0 to ControlCount - 1 do
Controls[i].ParentFontChanged;
FWinControlFlags:=FWinControlFlags-[wcfFontChanged];
end;
end;
inherited Loaded;
FixupTabList;
RealizeBounds;
if HandleAllocated and ([csDestroying]*ComponentState=[]) then
DoSendShowHideToInterface;
finally
EnableAlign;
end; end;
inherited Loaded;
FixupTabList;
RealizeBounds;
// align the childs
if wcfReAlignNeeded in FWinControlFlags then
ReAlign;
end; end;
procedure TWinControl.FormEndUpdated; procedure TWinControl.FormEndUpdated;
@ -5774,7 +5785,7 @@ end;
are relevant. are relevant.
WithThemeSpace: If true, adds space for stacking. For example: TRadioButton WithThemeSpace: If true, adds space for stacking. For example: TRadioButton
has a minimum size. But for staking multiple TRadioButtons there should be has a minimum size. But for stacking multiple TRadioButtons there should be
some space around. This space is theme dependent, so it passed parameter to some space around. This space is theme dependent, so it passed parameter to
the widgetset. the widgetset.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
@ -5799,7 +5810,7 @@ begin
if PreferredHeight>0 then if PreferredHeight>0 then
inc(PreferredHeight,BorderSpacing.InnerBorder*2); inc(PreferredHeight,BorderSpacing.InnerBorder*2);
end; end;
if ControlCount>0 then begin if ControlCount>0 then begin
// get the size requirements for the child controls // get the size requirements for the child controls
@ -5997,6 +6008,20 @@ begin
ResizeDelayedAutoSizeChildren; ResizeDelayedAutoSizeChildren;
end; end;
procedure TWinControl.DoSendShowHideToInterface;
var
NewVisible: Boolean;
begin
NewVisible:=HandleObjectShouldBeVisible;
if NewVisible<>(wcfHandleVisible in FWinControlFlags) then begin
if NewVisible then
Include(FWinControlFlags,wcfHandleVisible)
else
Exclude(FWinControlFlags,wcfHandleVisible);
TWSWinControlClass(WidgetSetClass).ShowHide(Self);
end;
end;
procedure TWinControl.ControlsAligned; procedure TWinControl.ControlsAligned;
begin begin
@ -6052,9 +6077,8 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TWinControl.CMShowingChanged(var Message: TLMessage); procedure TWinControl.CMShowingChanged(var Message: TLMessage);
begin begin
// ToDo: do not send this while loading, send it after loading. if HandleAllocated and ([csDestroying,csLoading]*ComponentState=[]) then
if HandleAllocated and ([csDestroying]*ComponentState=[])then DoSendShowHideToInterface;
TWSWinControlClass(WidgetSetClass).ShowHide(Self);
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------

View File

@ -1115,11 +1115,12 @@ begin
// if iconified in changed then OnIconify... // if iconified in changed then OnIconify...
if TObject(Data) is TCustomForm then begin if GTK_WIDGET_REALIZED(Widget) then begin
TheForm := TCustomForm(Data); if TObject(Data) is TCustomForm then begin
//DebugLn(['GTKWindowStateEventCB ',DbgSName(TheForm),' new_window_state=',state^.new_window_state,' changed_mask=',state^.changed_mask]); TheForm := TCustomForm(Data);
if TheForm.Parent = nil then begin (* toplevel window, just as a sanity check *) //DebugLn(['GTKWindowStateEventCB ',DbgSName(TheForm),' new_window_state=',state^.new_window_state,' changed_mask=',state^.changed_mask]);
if GTK_WIDGET_REALIZED(Widget) then begin if TheForm.Parent = nil then begin
// toplevel window
// send a WMSize Message (see TCustomForm.WMSize) // send a WMSize Message (see TCustomForm.WMSize)
GtkWidth:=Widget^.Allocation.Width; GtkWidth:=Widget^.Allocation.Width;
if GtkWidth<0 then GtkWidth:=0; if GtkWidth<0 then GtkWidth:=0;
@ -1130,12 +1131,13 @@ begin
{$IFDEF HasX} {$IFDEF HasX}
NetAtom := gdk_atom_intern('_NET_WM_DESKTOP', True); NetAtom := gdk_atom_intern('_NET_WM_DESKTOP', True);
if NetAtom > 0 then begin if NetAtom > 0 then begin
if gdk_property_get(Widget^.window, NetAtom, XA_CARDINAL,0, 4, 0, @AtomType, @AFormat, @ALength, @AIndex) if gdk_property_get(Widget^.window, NetAtom, XA_CARDINAL,
0, 4, 0, @AtomType, @AFormat, @ALength, @AIndex)
then begin then begin
NetAtom := gdk_atom_intern('_NET_CURRENT_DESKTOP', True); NetAtom := gdk_atom_intern('_NET_CURRENT_DESKTOP', True);
if gdk_property_get(gdk_get_default_root_window, NetAtom, XA_CARDINAL,0, 4, 0, @AtomType, @AFormat, @ALength, @ADesktop) if gdk_property_get(gdk_get_default_root_window, NetAtom, XA_CARDINAL,0, 4, 0, @AtomType, @AFormat, @ALength, @ADesktop)
then if ADesktop^ <> AIndex^ then begin then if ADesktop^ <> AIndex^ then begin
// form is not on active desktop => ignore
g_free(ADesktop); g_free(ADesktop);
g_free(AIndex); g_free(AIndex);
exit; exit;
@ -1164,6 +1166,13 @@ begin
Width := SmallInt(GtkWidth); Width := SmallInt(GtkWidth);
Height := SmallInt(GtkHeight); Height := SmallInt(GtkHeight);
end; end;
{$IFDEF VerboseSizeMsg}
DebugLn(['GTKWindowStateEventCB ',DbgSName(TheForm),
' GTK=',GtkWidth,'x',GtkHeight,
' LCL=',TheForm.Width,'x',TheForm.Height,
' SizeType=',SizeMsg.SizeType-Size_SourceIsInterface,'+Size_SourceIsInterface'
]);
{$ENDIF}
DeliverMessage(TheForm, SizeMsg); DeliverMessage(TheForm, SizeMsg);
end; end;
end; end;
@ -2353,8 +2362,9 @@ begin
TControl(Data).Name+':'+TControl(Data).ClassName, TControl(Data).Name+':'+TControl(Data).ClassName,
' widget='+DbgS(Widget)+WidgetFlagsToString(widget)+ ' widget='+DbgS(Widget)+WidgetFlagsToString(widget)+
' fixwidget=',DbgS(GetFixedWidget(Widget)), ' fixwidget=',DbgS(GetFixedWidget(Widget)),
' NewSize=',dbgs(Size^.Width),',',dbgs(Size^.Height),
' GtkPos=',dbgs(Widget^.allocation.x)+','+dbgs(Widget^.allocation.y), ' GtkPos=',dbgs(Widget^.allocation.x)+','+dbgs(Widget^.allocation.y),
','+dbgs(Widget^.allocation.width)+'x'+dbgs(Widget^.allocation.width)+ ','+dbgs(Widget^.allocation.width)+'x'+dbgs(Widget^.allocation.height)+
' LCLPos='+dbgs(TControl(Data).Left)+','+dbgs(TControl(Data).Top), ' LCLPos='+dbgs(TControl(Data).Left)+','+dbgs(TControl(Data).Top),
','+dbgs(TControl(Data).Width)+'x'+dbgs(TControl(Data).Height)); ','+dbgs(TControl(Data).Width)+'x'+dbgs(TControl(Data).Height));
{$ENDIF} {$ENDIF}
@ -2362,8 +2372,16 @@ begin
if TControl(Data) is TCustomForm then if TControl(Data) is TCustomForm then
DebugLn('VFP gtksize_allocateCB: ',TControl(Data).ClassName,' ',dbgs(Size^.X),',',dbgs(Size^.Y)); DebugLn('VFP gtksize_allocateCB: ',TControl(Data).ClassName,' ',dbgs(Size^.X),',',dbgs(Size^.Y));
{$ENDIF} {$ENDIF}
if GTK_WIDGET_REALIZED(Widget) then if GTK_WIDGET_REALIZED(Widget) then begin
{$IFDEF Gtk1}
SaveSizeNotification(Widget); SaveSizeNotification(Widget);
{$ELSE}
if GetFixedWidget(Widget)=Widget then
SendSizeNotificationToLCL(Widget)
else
SaveSizeNotification(Widget);
{$ENDIF}
end;
end; end;
function gtksize_allocate_client(widget: PGtkWidget; size: pGtkAllocation; function gtksize_allocate_client(widget: PGtkWidget; size: pGtkAllocation;
@ -2390,8 +2408,13 @@ begin
end; end;
MainWidget:=PGtkWidget(TWinControl(Data).Handle); MainWidget:=PGtkWidget(TWinControl(Data).Handle);
ClientWidget:=GetFixedWidget(MainWidget); ClientWidget:=GetFixedWidget(MainWidget);
if GTK_WIDGET_REALIZED(ClientWidget) then if GTK_WIDGET_REALIZED(ClientWidget) then begin
{$IFDEF Gtk1}
SaveClientSizeNotification(ClientWidget); SaveClientSizeNotification(ClientWidget);
{$ELSE}
SendSizeNotificationToLCL(MainWidget);
{$ENDIF}
end;
end else begin end else begin
// owner is not TWinControl -> ignore // owner is not TWinControl -> ignore
DebugLn('WARNING: gtksize_allocate_client: Data is not TWinControl. Data=', DebugLn('WARNING: gtksize_allocate_client: Data is not TWinControl. Data=',

View File

@ -445,6 +445,7 @@ var
procedure GtkDefDone; procedure GtkDefDone;
function dbgs(g: TGDIType): string; overload; function dbgs(g: TGDIType): string; overload;
function dbgs(r: TGDKRectangle): string; overload;
implementation implementation
@ -830,6 +831,11 @@ begin
end; end;
end; end;
function dbgs(r: TGDKRectangle): string;
begin
Result:=dbgs(Rect(r.x,r.y,r.width,r.height));
end;
initialization initialization
GtkDefInit; GtkDefInit;

View File

@ -113,6 +113,7 @@ type
lgsStatusBar, lgsStatusBar,
lgsHScale, lgsHScale,
lgsVScale, lgsVScale,
lgsGroupBox,
// user defined // user defined
lgsUserDefined lgsUserDefined
); );
@ -138,6 +139,7 @@ const
'notebook', 'notebook',
'hscale', 'hscale',
'vscale', 'vscale',
'groupbox',
'' ''
); );
@ -372,6 +374,7 @@ var
// each fixed widget that was resized by the gtk is stored here // each fixed widget that was resized by the gtk is stored here
// (hasharray of PGtkWidget) // (hasharray of PGtkWidget)
FFixWidgetsResized: TDynHashArray; FFixWidgetsResized: TDynHashArray;
FWidgetsWithResizeRequest: TDynHashArray; // hasharray of PGtkWidget
const const
aGtkJustification: array[TAlignment] of TGTKJustification = aGtkJustification: array[TAlignment] of TGTKJustification =

View File

@ -92,7 +92,6 @@ type
FRCFilename: string; FRCFilename: string;
FRCFileParsed: boolean; FRCFileParsed: boolean;
FRCFileAge: integer; FRCFileAge: integer;
FWidgetsWithResizeRequest: TDynHashArray; // hasharray of PGtkWidget
FGTKToolTips: PGtkToolTips; FGTKToolTips: PGtkToolTips;
FLogHandlerID: guint; // ID returend by set_handler FLogHandlerID: guint; // ID returend by set_handler
@ -230,8 +229,6 @@ type
// forms and dialogs // forms and dialogs
procedure BringFormToFront(Sender: TObject); procedure BringFormToFront(Sender: TObject);
procedure SetWindowSizeAndPosition(Window: PGtkWindow;
AWinControl: TWinControl);virtual;
procedure UntransientWindow(GtkWindow: PGtkWindow); procedure UntransientWindow(GtkWindow: PGtkWindow);
procedure InitializeFileDialog(FileDialog: TFileDialog; procedure InitializeFileDialog(FileDialog: TFileDialog;
var SelWidget: PGtkWidget; Title: PChar); virtual; var SelWidget: PGtkWidget; Title: PChar); virtual;
@ -273,8 +270,6 @@ type
procedure SendPaintMessagesForInternalWidgets(AWinControl: TWinControl); procedure SendPaintMessagesForInternalWidgets(AWinControl: TWinControl);
function LCLtoGtkMessagePending: boolean;virtual; function LCLtoGtkMessagePending: boolean;virtual;
procedure SendCachedGtkMessages;virtual; procedure SendCachedGtkMessages;virtual;
procedure RealizeWidgetSize(Widget: PGtkWidget;
NewWidth, NewHeight: integer); virtual;
procedure FinishComponentCreate(const ALCLObject: TObject; procedure FinishComponentCreate(const ALCLObject: TObject;
const AGTKObject: Pointer); virtual; const AGTKObject: Pointer); virtual;

View File

@ -614,60 +614,6 @@ end;
{$endif} {$endif}
{------------------------------------------------------------------------------
Method: TGtkWidgetSet.SetWindowSizeAndPosition
Params: Widget: PGtkWidget; AWinControl: TWinControl
Returns: Nothing
Set the size and position of a top level window.
------------------------------------------------------------------------------}
procedure TGtkWidgetSet.SetWindowSizeAndPosition(Window: PGtkWindow;
AWinControl: TWinControl);
var
Width, Height: integer;
//Info: PGtkWindowGeometryInfo;
begin
Width:=AWinControl.Width;
// 0 and negative values have a special meaning, so don't use them
if Width<=0 then Width:=1;
Height:=AWinControl.Height;
if Height<=0 then Height:=1;
//DebugLn('TGtkWidgetSet.SetWindowSizeAndPosition ',AWinControl.Name,':',AWinControl.ClassName,' ',AWinControl.Visible,' Old=',PGtkWidget(Window)^.allocation.Width,',',PGtkWidget(Window)^.allocation.Width,' New=',Width,',',Height);
// set geometry default size
//Info:=gtk_window_get_geometry_info(Window, TRUE);
//if (Info^.default_width<>Width) or (Info^.default_height<>Height) then
gtk_window_set_default_size(Window,Width,Height);
{$IFDEF Gtk2}
// resize
gtk_window_set_default_size(Window,Width,Height);
gtk_window_resize(Window,Width,Height);
// reposition
gtk_window_move(Window,AWinControl.Left,AWinControl.Top);
{$ELSE}
// resize
if assigned(PGtkWidget(Window)^.Window) then
// widget is realized, resize gdkwindow directly
gdk_window_move_resize(PGtkWidget(Window)^.Window,AWinControl.Left,
AWinControl.Top,Width,Height)
else begin
// widget is not yet realized, force resize needed for shrinking under gtk1
gtk_widget_set_usize(PGtkWidget(Window), -1,-1);
end;
// reposition
gtk_widget_set_usize(PGtkWidget(Window),Width,Height);
gtk_widget_set_uposition(PGtkWidget(Window),AWinControl.Left,AWinControl.Top);
{$ENDIF}
{$IFDEF VerboseSizeMsg}
DebugLn(['TGtkWidgetSet.SetWindowSizeAndPosition B ',DbgSName(AWinControl),
' Visible=',AWinControl.Visible,
' Old=',PGtkWidget(Window)^.allocation.X,',',PGtkWidget(Window)^.allocation.Y,
' New=',AWinControl.Left,',',AWinControl.Top,',',Width,'x',Height]);
{$ENDIF}
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
procedure TGtkWidgetSet.UpdateTransientWindows; procedure TGtkWidgetSet.UpdateTransientWindows;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
@ -935,20 +881,11 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
procedure SendCachedLCLResizeRequests; procedure SendCachedLCLResizeRequests;
var var
Widget, ParentFixed, ParentWidget: PGtkWidget; Widget: PGtkWidget;
LCLControl: TControl; LCLControl: TWinControl;
IsTopLevelWidget: boolean; IsTopLevelWidget: boolean;
TopologicalList: TFPList; // list of PGtkWidget; TopologicalList: TFPList; // list of PGtkWidget;
i, LCLWidth, LCLHeight: integer; i: integer;
WinWidgetInfo: PWinWidgetInfo;
procedure WriteBigWarning;
begin
DebugLn('WARNING: resizing BIG ',
' Control=',LCLControl.Name,':',LCLControl.ClassName,
' NewSize=',dbgs(LCLWidth),',',dbgs(LCLHeight));
//RaiseException('');
end;
procedure RaiseWidgetWithoutControl; procedure RaiseWidgetWithoutControl;
begin begin
@ -956,16 +893,6 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
+DbgS(Widget)+' without LCL control'); +DbgS(Widget)+' without LCL control');
end; end;
procedure WriteWarningParentWidgetNotFound;
begin
DebugLn('WARNING: TGtkWidgetSet.SendCachedLCLMessages - '
,'Parent''s Fixed Widget not found');
DebugLn(' Control=',LCLControl.Name,':',LCLControl.ClassName,
' Parent=',LCLControl.Parent.Name,':',LCLControl.Parent.ClassName,
' ParentWidget=',DbgS(ParentWidget),
'');
end;
begin begin
if FWidgetsWithResizeRequest.Count=0 then exit; if FWidgetsWithResizeRequest.Count=0 then exit;
{$IFDEF VerboseSizeMsg} {$IFDEF VerboseSizeMsg}
@ -977,12 +904,12 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
Widget:=TopologicalList[i]; Widget:=TopologicalList[i];
// resize widget // resize widget
LCLControl:=TControl(GetLCLObject(Widget)); LCLControl:=TWinControl(GetLCLObject(Widget));
if (LCLControl=nil) or (not (LCLControl is TControl)) then begin if (LCLControl=nil) or (not (LCLControl is TControl)) then begin
RaiseWidgetWithoutControl; RaiseWidgetWithoutControl;
end; end;
{$IFDEF VerboseSizeMsg} {$IFDEF VerboseSizeMsg}
if AnsiCompareText(LCLControl.ClassName,'TScrollBar')=0 then if CompareText(LCLControl.ClassName,'TScrollBar')=0 then
DebugLn('SendCachedLCLMessages ',LCLControl.Name,':',LCLControl.ClassName, DebugLn('SendCachedLCLMessages ',LCLControl.Name,':',LCLControl.ClassName,
' ',dbgs(LCLControl.Left)+','+dbgs(LCLControl.Top)+','+dbgs(LCLControl.Width)+'x'+dbgs(LCLControl.Height)); ' ',dbgs(LCLControl.Left)+','+dbgs(LCLControl.Top)+','+dbgs(LCLControl.Width)+'x'+dbgs(LCLControl.Height));
{$ENDIF} {$ENDIF}
@ -991,38 +918,7 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
and (LCLControl.Parent = nil); and (LCLControl.Parent = nil);
if not IsTopLevelWidget then begin if not IsTopLevelWidget then begin
// resize widget SetWidgetSizeAndPosition(LCLControl);
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;
RealizeWidgetSize(Widget,LCLWidth, LCLHeight);
// move widget on the fixed widget of parent control
if (LCLControl.Parent<>nil) and (LCLControl.Parent.HandleAllocated) then
begin
ParentWidget:=pgtkWidget(LCLControl.Parent.Handle);
ParentFixed := GetFixedWidget(ParentWidget);
if GtkWidgetIsA(ParentFixed,GTK_FIXED_GET_TYPE)
or GtkWidgetIsA(ParentFixed,GTK_LAYOUT_GET_TYPE) then begin
FixedMoveControl(ParentFixed, Widget,
LCLControl.Left,LCLControl.Top);
end else begin
WinWidgetInfo:=GetWidgetInfo(Widget,false);
if (WinWidgetInfo=nil)
or (not (wwiNotOnParentsClientArea in WinWidgetInfo^.Flags)) then
WriteWarningParentWidgetNotFound;
end;
end;
end end
else begin else begin
// resize form // resize form
@ -1065,257 +961,6 @@ end;
Some Gtk messages are not sent directly to the LCL. Send them now. Some Gtk messages are not sent directly to the LCL. Send them now.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TGtkWidgetSet.SendCachedGtkMessages; procedure TGtkWidgetSet.SendCachedGtkMessages;
procedure SendSizeNotificationToLCL(MainWidget: PGtkWidget);
var
LCLControl: TWinControl;
LCLLeft, LCLTop, LCLWidth, LCLHeight: integer;
GtkLeft, GtkTop, GtkWidth, GtkHeight: integer;
TopLeftChanged, WidthHeightChanged, IsTopLevelWidget: boolean;
MessageDelivered: boolean;
PosMsg : TLMWindowPosChanged;
SizeMsg: TLMSize;
MoveMsg: TLMMove;
procedure UpdateLCLRect;
begin
LCLLeft:=LCLControl.Left;
LCLTop:=LCLControl.Top;
LCLWidth:=LCLControl.Width;
LCLHeight:=LCLControl.Height;
TopLeftChanged:=(LCLLeft<>GtkLeft) or (LCLTop<>GtkTop);
WidthHeightChanged:=(LCLWidth<>GtkWidth) or (LCLHeight<>GtkHeight);
end;
begin
if not GTK_WIDGET_REALIZED(MainWidget) then begin
{$IFDEF VerboseSizeMsg}
DebugLn('SendSizeNotificationToLCL ',LCLControl.Name,':',LCLControl.ClassName,' MainWidget=',WidgetFlagsToString(MainWidget),' Ignored, because not realized ');
{$ENDIF}
exit;
end;
LCLControl:=TWinControl(GetLCLObject(MainWidget));
if LCLControl=nil then exit;
{$IFDEF VerboseSizeMsg}
DebugLn('JJJ1 SendSizeNotificationToLCL ',LCLControl.Name,':',LCLControl.ClassName,' MainWidget=',WidgetFlagsToString(MainWidget));
{$ENDIF}
GtkLeft:=MainWidget^.Allocation.X;
GtkTop:=MainWidget^.Allocation.Y;
{$Ifdef GTK2}
if GTK_WIDGET_NO_WINDOW(MainWidget) and GTK_WIDGET_NO_WINDOW(MainWidget^.Parent)
// and (not GtkWidgetIsA(MainWidget,GTKAPIWidget_GetType))
then begin
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;
if GtkHeight<0 then GtkHeight:=0;
IsTopLevelWidget:=(LCLControl is TCustomForm) and (LCLControl.Parent=nil);
if IsTopLevelWidget then begin
if not GTK_WIDGET_VISIBLE(MainWidget) then begin
// size/move messages of invisible windows are not reliable
// -> ignore
exit;
end;
if (GtkWidth=1) and (GtkHeight=1) then begin
// this is default size of the gtk. Ignore.
exit;
end;
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),' ',
GtkLeft,',',GtkTop,',',GtkWidth,',',GtkHeight,' ',GetWidgetDebugReport(MainWidget)]);
{$ENDIF}
end;
UpdateLCLRect;
{$IFDEF VerboseSizeMsg}
DebugLn('SendSizeNotificationToLCL ',DbgSName(LCLControl),
' GTK=',dbgs(GtkLeft)+','+dbgs(GtkTop)+','+dbgs(GtkWidth)+'x'+dbgs(GtkHeight),
' LCL=',dbgs(LCLLeft)+','+dbgs(LCLTop)+','+dbgs(LCLWidth)+'x'+dbgs(LCLHeight)
);
{$ENDIF}
// first send a LM_WINDOWPOSCHANGED message
if TopLeftChanged or WidthHeightChanged then begin
PosMsg.Msg := LM_WINDOWPOSCHANGED; //LM_SIZEALLOCATE;
PosMsg.Result := 0;
New(PosMsg.WindowPos);
try
with PosMsg.WindowPos^ do begin
hWndInsertAfter := 0;
x := GtkLeft;
y := GtkTop;
cx := GtkWidth;
cy := GtkHeight;
flags := 0;
end;
MessageDelivered := DeliverMessage(LCLControl, PosMsg) = 0;
finally
Dispose(PosMsg.WindowPos);
end;
if (not MessageDelivered) then exit;
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
UpdateLCLRect;
end;
// then send a LM_SIZE message
if WidthHeightChanged then begin
{$IFDEF VerboseSizeMsg}
DebugLn('Send LM_SIZE To LCL ',LCLControl.Name,':',LCLControl.ClassName);
{$ENDIF}
with SizeMsg do
begin
Result := 0;
Msg := LM_SIZE;
{$IFDEF GTK1}
if GDK_WINDOW_GET_MAXIMIZED(PGdkWindowPrivate(MainWidget^.window)) then
SizeType := SIZEFULLSCREEN or Size_SourceIsInterface
else
SizeType := SIZENORMAL or Size_SourceIsInterface;
{$ELSE}
if LCLControl is TCustomForm then begin
// if the LCL gets an event without a State it resets it to SIZENORMAL
// so we send it the state it already is
case TCustomForm(LCLControl).WindowState of
wsNormal: SizeType := SIZENORMAL or Size_SourceIsInterface;
wsMinimized: SizeType := SIZEICONIC or Size_SourceIsInterface;
wsMaximized: SizeType := SIZEFULLSCREEN or Size_SourceIsInterface;
end;
end
else
SizeType := Size_SourceIsInterface;
{$ENDIF}
Width := SmallInt(GtkWidth);
Height := SmallInt(GtkHeight);
end;
MessageDelivered := (DeliverMessage(LCLControl, SizeMsg) = 0);
if not MessageDelivered then exit;
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
UpdateLCLRect;
end;
// then send a LM_MOVE message
if TopLeftChanged then begin
{$IFDEF VerboseSizeMsg}
DebugLn('Send LM_MOVE To LCL ',LCLControl.Name,':',LCLControl.ClassName);
{$ENDIF}
with MoveMsg do
begin
Result := 0;
Msg := LM_MOVE;
MoveType := Move_SourceIsInterface;
XPos := SmallInt(GtkLeft);
YPos := SmallInt(GtkTop);
end;
MessageDelivered := (DeliverMessage(LCLControl, MoveMsg) = 0);
if not MessageDelivered then exit;
end;
end;
procedure SendCachedGtkResizeNotifications;
{ This proc sends all cached size messages from the gtk to lcl but in an
optimized order.
When sending the LCL a size/move/windowposchanged messages the LCL will
automatically realign all child controls. This realigning is based on the
clientrect.
Therefore, before a size message is sent to the lcl, all clientrect must be
updated.
If a size message results in resizing a widget that was also resized, then
the message for the dependent widget is not sent to the lcl, because the lcl
resize was after the gtk resize.
}
var
FixWidget, MainWidget: PGtkWidget;
LCLControl: TWinControl;
List: TFPList;
i: integer;
procedure RaiseInvalidLCLControl;
begin
RaiseGDBException(Format('SendCachedGtkResizeNotifications FixWidget=%p MainWidget=%p LCLControl=%p',
[FixWidget, MainWidget, Pointer(LCLControl)]));
end;
begin
if (FFixWidgetsResized.Count=0) and (FWidgetsResized.Count=0) then exit;
List:=TFPList.Create;
{ if any fixed widget was resized then a client area of a LCL control was
resized
-> invalidate client rectangles
}
{$IFDEF VerboseSizeMsg}
DebugLn('HHH1 SendCachedGtkClientResizeNotifications Invalidating ClientRects ... '
,' FixSizeMsgCount=',dbgs(FFixWidgetsResized.Count));
{$ENDIF}
FFixWidgetsResized.AssignTo(List);
for i:=0 to List.Count-1 do begin
FixWidget:=List[i];
MainWidget:=GetMainWidget(FixWidget);
LCLControl:=TWinControl(GetLCLObject(MainWidget));
if (LCLControl=nil) or (not (LCLControl is TWinControl)) then
RaiseInvalidLCLControl;
LCLControl.InvalidateClientRectCache(false);
end;
{ if any main widget (= not fixed widget) was resized
then a LCL control was resized
-> send WMSize, WMMove, and WMWindowPosChanged messages
}
{$IFDEF VerboseSizeMsg}
DebugLn('HHH2 SendCachedGtkClientResizeNotifications SizeMsgCount=',dbgs(FWidgetsResized.Count));
{$ENDIF}
repeat
MainWidget:=FWidgetsResized.First;
if MainWidget<>nil then begin
FWidgetsResized.Remove(MainWidget);
if not FWidgetsWithResizeRequest.Contains(MainWidget) then begin
SendSizeNotificationToLCL(MainWidget);
FixWidget:=GetFixedWidget(MainWidget);
end;
end else break;
until Application.Terminated;
{ if any client area was resized, which MainWidget Size was already in sync
with the LCL, no message was sent. So, tell each changed client area to
check its size.
}
{$IFDEF VerboseSizeMsg}
DebugLn('HHH3 SendCachedGtkClientResizeNotifications Updating ClientRects ...');
{$ENDIF}
repeat
FixWidget:=FFixWidgetsResized.First;
if FixWidget<>nil then begin
FFixWidgetsResized.Remove(FixWidget);
MainWidget:=GetMainWidget(FixWidget);
LCLControl:=TWinControl(GetLCLObject(MainWidget));
LCLControl.DoAdjustClientRectChange;
end else begin
break;
end;
until Application.Terminated;
List.Free;
{$IFDEF VerboseSizeMsg}
DebugLn('HHH4 SendCachedGtkClientResizeNotifications completed.');
{$ENDIF}
end;
begin begin
SendCachedGtkResizeNotifications; SendCachedGtkResizeNotifications;
end; end;
@ -1502,71 +1147,6 @@ begin
{$ENDIF} {$ENDIF}
end; end;
{------------------------------------------------------------------------------
procedure TGtkWidgetSet.RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
NewHeight: integer);
Note: gtk_window is resized in TGtkWidgetSet.SetWindowSizeAndPosition
------------------------------------------------------------------------------}
procedure TGtkWidgetSet.RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
NewHeight: integer);
var
Requisition: TGtkRequisition;
{$IFDEF VerboseSizeMsg}
LCLObject: TObject;
{$ENDIF}
FixedWidget: PGtkWidget;
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)+
' New='+dbgs(NewWidth)+','+dbgs(NewHeight));
if (LCLObject<>nil) and (LCLObject is TControl) then begin
with TControl(LCLObject) do
DebugLn(' LCL=',Name,':',ClassName,' ',dbgs(Left),',',dbgs(Top),',',dbgs(Width),',',dbgs(Height));
end else begin
DebugLn(' LCL=',DbgS(LCLObject));
end;
{$ENDIF}
if GtkWidgetIsA(Widget,GTK_TYPE_SCROLLBAR) then
begin
// the width of a scrollbar is fixed and depends only on the theme
gtk_widget_size_request(widget, @Requisition);
if GtkWidgetIsA(Widget, GTK_TYPE_HSCROLLBAR) then
begin
NewHeight:=Requisition.height;
end else begin
NewWidth:=Requisition.width;
end;
//DebugLn('TGtkWidgetSet.RealizeWidgetSize A ',Newwidth,',',Newheight);
end;
gtk_widget_set_usize(Widget, NewWidth, NewHeight);
//DebugLn(['TGtkWidgetSet.RealizeWidgetSize ',GetWidgetDebugReport(Widget),' NewWidth=',NewWidth,' NewHeight=',NewHeight]);
if GtkWidgetIsA(Widget, GTK_TYPE_COMBO) then
begin
// the combobox has an entry, which height is not resized
// automatically. Do it manually.
gtk_widget_set_usize(PGtkCombo(Widget)^.entry,
PGtkCombo(Widget)^.entry^.allocation.width, NewHeight);
end;
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);
gtk_widget_set_usize(FixedWidget,NewWidth,NewHeight);
end;
end;
end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
procedure TGtkWidgetSet.SendPaintMessagesForInternalWidgets( procedure TGtkWidgetSet.SendPaintMessagesForInternalWidgets(
AWinControl: TWinControl); AWinControl: TWinControl);
@ -1831,7 +1411,6 @@ begin
end; end;
// proceed until all messages are handled // proceed until all messages are handled
until (not PendingGtkMessagesExists) or Application.Terminated; until (not PendingGtkMessagesExists) or Application.Terminated;
end; end;
@ -3584,16 +3163,35 @@ procedure TGtkWidgetSet.ResizeChild(Sender : TObject;
Left, Top, Width, Height : Integer); Left, Top, Width, Height : Integer);
var var
Widget: PGtkWidget; Widget: PGtkWidget;
LCLControl: TWinControl;
Later: boolean;
{$IFDEF Gtk2}
IsTopLevelWidget: Boolean;
{$ENDIF}
begin begin
//DebugLn('[TGtkWidgetSet.ResizeChild] START ',TControl(Sender).Name,':',Sender.Classname,' Left=',Left,' Top=',Top,' Width=',Width,' Height=',Height); //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]))); Assert(false, (Format('trace: [TGtkWidgetSet.ResizeChild] %s --> Resize', [Sender.ClassNAme])));
if Sender is TWinControl then begin if Sender is TWinControl then begin
if TWinControl(Sender).HandleAllocated then begin LCLControl:=TWinControl(Sender);
Widget := pgtkWidget(TWinControl(Sender).Handle); if LCLControl.HandleAllocated then begin
SetResizeRequest(Widget); Widget := pgtkWidget(LCLControl.Handle);
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);
//if (Sender is TCustomForm) then //if (Sender is TCustomForm) then
//if AnsiCompareText(Sender.ClassName,'TScrollBar')=0 then //if CompareText(Sender.ClassName,'TScrollBar')=0 then
// DebugLn(' FFF ResizeChild ',Sender.ClassName,' ',Left,',',Top,',',Width,',',Height); // DebugLn(' FFF ResizeChild ',Sender.ClassName,' ',Left,',',Top,',',Width,',',Height);
end; end;
end; end;
@ -5909,11 +5507,13 @@ procedure TGtkWidgetSet.ShowHide(Sender : TObject);
end; end;
var FormIconGdiObject: PGDIObject; var FormIconGdiObject: PGDIObject;
SenderWidget, ParentFixed, ParentWidget: PGTKWidget; SenderWidget: PGTKWidget;
LCLControl: TWinControl; LCLControl: TWinControl;
Decor, Func : Longint; Decor, Func : Longint;
AWindow: PGdkWindow; AWindow: PGdkWindow;
ACustomForm: TCustomForm; ACustomForm: TCustomForm;
ParentFixed: PGTKWidget;
ParentWidget: PGTKWidget;
{$IFDEF Gtk1} {$IFDEF Gtk1}
AWindowPrivate: PGdkWindowPrivate; AWindowPrivate: PGdkWindowPrivate;
{$ENDIF} {$ENDIF}
@ -5941,9 +5541,6 @@ begin
ShareWindowAccelGroups(SenderWidget); ShareWindowAccelGroups(SenderWidget);
end; end;
if gtk_widget_visible(SenderWidget) then
exit;
// before making the widget visible, set the position and size // before making the widget visible, set the position and size
if FWidgetsWithResizeRequest.Contains(SenderWidget) then begin if FWidgetsWithResizeRequest.Contains(SenderWidget) then begin
if (ACustomForm<>nil) and (ACustomForm.Parent=nil) then begin if (ACustomForm<>nil) and (ACustomForm.Parent=nil) then begin
@ -5958,6 +5555,9 @@ begin
SetWindowSizeAndPosition(PgtkWindow(SenderWidget),LCLControl); SetWindowSizeAndPosition(PgtkWindow(SenderWidget),LCLControl);
end else if (LCLControl.Parent<>nil) then begin end else if (LCLControl.Parent<>nil) then begin
// resize widget // resize widget
{$IFDEF VerboseSizeMsg}
DebugLn(['TGtkWidgetSet.ShowHide ',DbgSName(LCLControl)]);
{$ENDIF}
RealizeWidgetSize(SenderWidget,LCLControl.Width,LCLControl.Height); RealizeWidgetSize(SenderWidget,LCLControl.Width,LCLControl.Height);
// move widget on the fixed widget of parent control // move widget on the fixed widget of parent control
ParentWidget:=pgtkWidget(LCLControl.Parent.Handle); ParentWidget:=pgtkWidget(LCLControl.Parent.Handle);
@ -5994,6 +5594,9 @@ begin
ReleaseMouseCapture; ReleaseMouseCapture;
end; end;
if gtk_widget_visible(SenderWidget) then
exit;
gtk_widget_show(SenderWidget); gtk_widget_show(SenderWidget);
if (ACustomForm<>nil) and (ACustomForm.Parent=nil) then begin if (ACustomForm<>nil) and (ACustomForm.Parent=nil) then begin
@ -7157,9 +6760,9 @@ end;
Because the gtk puts all size requests into a queue, it will process the 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 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 the widget size four times and everytime the LCL gets a message. If the
control has childs, this will result resizing the childs four times. 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 Therefore LCL size requests for a widget are cached and only the final one is
sent. sent in: TGtkWidgetSet.SendCachedLCLMessages.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TGtkWidgetSet.SetResizeRequest(Widget: PGtkWidget); procedure TGtkWidgetSet.SetResizeRequest(Widget: PGtkWidget);
{$IFDEF VerboseSizeMsg} {$IFDEF VerboseSizeMsg}
@ -7169,15 +6772,11 @@ var
begin begin
{$IFDEF VerboseSizeMsg} {$IFDEF VerboseSizeMsg}
LCLControl:=TWinControl(GetLCLObject(Widget)); LCLControl:=TWinControl(GetLCLObject(Widget));
DbgOut('PPP TGtkWidgetSet.SetResizeRequest Widget=',DbgS(Widget)); DbgOut('TGtkWidgetSet.SetResizeRequest Widget=',DbgS(Widget));
if (LCLControl<>nil) then begin if LCLControl is TWinControl then
if LCLControl is TWinControl then DebugLn(' ',DbgSName(LCLControl),' LCLBounds=',dbgs(LCLControl.BoundsRect))
DebugLn(' ',LCLControl.Name,':',LCLControl.ClassName) else
else DebugLn(' ERROR: ',DbgSName(LCLControl));
DebugLn(' ERROR: ',LCLControl.ClassName);
end else begin
DebugLn(' ERROR: LCLControl=nil');
end;
{$ENDIF} {$ENDIF}
if not FWidgetsWithResizeRequest.Contains(Widget) then if not FWidgetsWithResizeRequest.Contains(Widget) then
FWidgetsWithResizeRequest.Add(Widget); FWidgetsWithResizeRequest.Add(Widget);
@ -7194,6 +6793,11 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TGtkWidgetSet.UnsetResizeRequest(Widget: PGtkWidget); procedure TGtkWidgetSet.UnsetResizeRequest(Widget: PGtkWidget);
begin begin
{$IFDEF VerboseSizeMsg}
if FWidgetsWithResizeRequest.Contains(Widget) then begin
DebugLn(['TGtkWidgetSet.UnsetResizeRequest ',GetWidgetDebugReport(Widget)]);
end;
{$ENDIF}
FWidgetsWithResizeRequest.Remove(Widget); FWidgetsWithResizeRequest.Remove(Widget);
end; end;

View File

@ -6441,6 +6441,446 @@ begin
//debugln('GetGTKDefaultSize PreferredWidth=',dbgs(PreferredWidth),' PreferredHeight=',dbgs(PreferredHeight)); //debugln('GetGTKDefaultSize PreferredWidth=',dbgs(PreferredWidth),' PreferredHeight=',dbgs(PreferredHeight));
end; end;
procedure SendSizeNotificationToLCL(MainWidget: PGtkWidget);
var
LCLControl: TWinControl;
LCLLeft, LCLTop, LCLWidth, LCLHeight: integer;
GtkLeft, GtkTop, GtkWidth, GtkHeight: integer;
TopLeftChanged, WidthHeightChanged, IsTopLevelWidget: boolean;
MessageDelivered: boolean;
SizeMsg: TLMSize;
MoveMsg: TLMMove;
PosMsg : TLMWindowPosChanged;
procedure UpdateLCLRect;
begin
LCLLeft:=LCLControl.Left;
LCLTop:=LCLControl.Top;
LCLWidth:=LCLControl.Width;
LCLHeight:=LCLControl.Height;
TopLeftChanged:=(LCLLeft<>GtkLeft) or (LCLTop<>GtkTop);
WidthHeightChanged:=(LCLWidth<>GtkWidth) or (LCLHeight<>GtkHeight);
end;
begin
if not GTK_WIDGET_REALIZED(MainWidget) then begin
{$IFDEF VerboseSizeMsg}
LCLControl:=TWinControl(GetLCLObject(MainWidget));
DebugLn('SendSizeNotificationToLCL ',DbgSName(LCLControl),' MainWidget=',WidgetFlagsToString(MainWidget),' Ignored, because not realized ');
{$ENDIF}
exit;
end;
LCLControl:=TWinControl(GetLCLObject(MainWidget));
if LCLControl=nil then exit;
{$IFDEF VerboseSizeMsg}
DebugLn('SendSizeNotificationToLCL checking ... ',DbgSName(LCLControl),' MainWidget=',WidgetFlagsToString(MainWidget));
{$ENDIF}
GtkLeft:=MainWidget^.Allocation.X;
GtkTop:=MainWidget^.Allocation.Y;
{$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;
if GtkHeight<0 then GtkHeight:=0;
IsTopLevelWidget:=(LCLControl is TCustomForm) and (LCLControl.Parent=nil);
if IsTopLevelWidget then begin
if not GTK_WIDGET_VISIBLE(MainWidget) then begin
// size/move messages of invisible windows are not reliable
// -> ignore
exit;
end;
if (GtkWidth=1) and (GtkHeight=1) then begin
// this is default size of the gtk. Ignore.
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),' ',
GtkLeft,',',GtkTop,',',GtkWidth,'x',GtkHeight,' ',GetWidgetDebugReport(MainWidget)]);
{$ENDIF}
end;
UpdateLCLRect;
// first send a LM_WINDOWPOSCHANGED message
if TopLeftChanged or WidthHeightChanged then begin
{$IFDEF VerboseSizeMsg}
DebugLn('SendSizeNotificationToLCL ',DbgSName(LCLControl),
' GTK=',dbgs(GtkLeft)+','+dbgs(GtkTop)+','+dbgs(GtkWidth)+'x'+dbgs(GtkHeight),
' LCL=',dbgs(LCLLeft)+','+dbgs(LCLTop)+','+dbgs(LCLWidth)+'x'+dbgs(LCLHeight)
);
{$ENDIF}
PosMsg.Msg := LM_WINDOWPOSCHANGED; //LM_SIZEALLOCATE;
PosMsg.Result := 0;
New(PosMsg.WindowPos);
try
with PosMsg.WindowPos^ do begin
hWndInsertAfter := 0;
x := GtkLeft;
y := GtkTop;
cx := GtkWidth;
cy := GtkHeight;
flags := 0;
end;
MessageDelivered := DeliverMessage(LCLControl, PosMsg) = 0;
finally
Dispose(PosMsg.WindowPos);
end;
if (not MessageDelivered) then exit;
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
UpdateLCLRect;
end;
// then send a LM_SIZE message
if WidthHeightChanged then begin
{$IFDEF VerboseSizeMsg}
DebugLn('Send LM_SIZE To LCL ',LCLControl.Name,':',LCLControl.ClassName);
{$ENDIF}
with SizeMsg do
begin
Result := 0;
Msg := LM_SIZE;
{$IFDEF GTK1}
if GDK_WINDOW_GET_MAXIMIZED(PGdkWindowPrivate(MainWidget^.window)) then
SizeType := SIZEFULLSCREEN
else
SizeType := SIZENORMAL;
{$ELSE}
if LCLControl is TCustomForm then begin
// if the LCL gets an event without a State it resets it to SIZENORMAL
// so we send it the state it already is
case TCustomForm(LCLControl).WindowState of
wsNormal: SizeType := SIZENORMAL;
wsMinimized: SizeType := SIZEICONIC;
wsMaximized: SizeType := SIZEFULLSCREEN;
end;
end
else
SizeType := 0;
{$ENDIF}
SizeType := SizeType or Size_SourceIsInterface;
Width := SmallInt(GtkWidth);
Height := SmallInt(GtkHeight);
end;
MessageDelivered := (DeliverMessage(LCLControl, SizeMsg) = 0);
if not MessageDelivered then exit;
if FWidgetsWithResizeRequest.Contains(MainWidget) then exit;
UpdateLCLRect;
end;
// then send a LM_MOVE message
if TopLeftChanged then begin
{$IFDEF VerboseSizeMsg}
DebugLn('Send LM_MOVE To LCL ',LCLControl.Name,':',LCLControl.ClassName);
{$ENDIF}
with MoveMsg do
begin
Result := 0;
Msg := LM_MOVE;
MoveType := Move_SourceIsInterface;
XPos := SmallInt(GtkLeft);
YPos := SmallInt(GtkTop);
end;
MessageDelivered := (DeliverMessage(LCLControl, MoveMsg) = 0);
if not MessageDelivered then exit;
end;
end;
procedure SendCachedGtkResizeNotifications;
{ This proc sends all cached size messages from the gtk to lcl but in an
optimized order.
When sending the LCL a size/move/windowposchanged messages the LCL will
automatically realign all child controls. This realigning is based on the
clientrect.
Therefore, before a size message is sent to the lcl, all clientrect must be
updated.
If a size message results in resizing a widget that was also resized, then
the message for the dependent widget is not sent to the lcl, because the lcl
resize was after the gtk resize.
}
var
FixWidget, MainWidget: PGtkWidget;
LCLControl: TWinControl;
List: TFPList;
i: integer;
procedure RaiseInvalidLCLControl;
begin
RaiseGDBException(Format('SendCachedGtkResizeNotifications FixWidget=%p MainWidget=%p LCLControl=%p',
[FixWidget, MainWidget, Pointer(LCLControl)]));
end;
begin
if (FWidgetsResized.Count=0) and (FFixWidgetsResized.Count=0) then exit;
List:=TFPList.Create;
{ if any fixed widget was resized then a client area of a LCL control was
resized
-> invalidate client rectangles
}
{$IFDEF VerboseSizeMsg}
DebugLn('HHH1 SendCachedGtkClientResizeNotifications Invalidating ClientRects ... '
,' FixSizeMsgCount=',dbgs(FFixWidgetsResized.Count));
{$ENDIF}
FFixWidgetsResized.AssignTo(List);
for i:=0 to List.Count-1 do begin
FixWidget:=List[i];
MainWidget:=GetMainWidget(FixWidget);
LCLControl:=TWinControl(GetLCLObject(MainWidget));
if (LCLControl=nil) or (not (LCLControl is TWinControl)) then
RaiseInvalidLCLControl;
LCLControl.InvalidateClientRectCache(false);
end;
{ if any main widget (= not fixed widget) was resized
then a LCL control was resized
-> send WMSize, WMMove, and WMWindowPosChanged messages
}
{$IFDEF VerboseSizeMsg}
if FWidgetsResized.First<>nil then
DebugLn('HHH2 SendCachedGtkClientResizeNotifications SizeMsgCount=',dbgs(FWidgetsResized.Count));
{$ENDIF}
repeat
MainWidget:=FWidgetsResized.First;
if MainWidget<>nil then begin
FWidgetsResized.Remove(MainWidget);
if not FWidgetsWithResizeRequest.Contains(MainWidget) then begin
SendSizeNotificationToLCL(MainWidget);
end;
end else break;
until Application.Terminated;
{ if any client area was resized, which MainWidget Size was already in sync
with the LCL, no message was sent. So, tell each changed client area to
check its size.
}
{$IFDEF VerboseSizeMsg}
if FFixWidgetsResized.First<>nil then
DebugLn('HHH3 SendCachedGtkClientResizeNotifications Updating ClientRects ...');
{$ENDIF}
repeat
FixWidget:=FFixWidgetsResized.First;
if FixWidget<>nil then begin
FFixWidgetsResized.Remove(FixWidget);
MainWidget:=GetMainWidget(FixWidget);
LCLControl:=TWinControl(GetLCLObject(MainWidget));
LCLControl.DoAdjustClientRectChange;
end else begin
break;
end;
until Application.Terminated;
List.Free;
{$IFDEF VerboseSizeMsg}
DebugLn('HHH4 SendCachedGtkClientResizeNotifications completed.');
{$ENDIF}
end;
{------------------------------------------------------------------------------
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
NewHeight: integer);
Note: gtk_window is resized in SetWindowSizeAndPosition
------------------------------------------------------------------------------}
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth,
NewHeight: integer);
var
Requisition: TGtkRequisition;
{$IFDEF VerboseSizeMsg}
LCLObject: TObject;
{$ENDIF}
FixedWidget: PGtkWidget;
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)+
' New='+dbgs(NewWidth)+','+dbgs(NewHeight));
if (LCLObject<>nil) and (LCLObject is TControl) then begin
with TControl(LCLObject) do
DebugLn(' LCL=',Name,':',ClassName,' ',dbgs(Left),',',dbgs(Top),',',dbgs(Width),',',dbgs(Height));
end else begin
DebugLn(' LCL=',DbgS(LCLObject));
end;
{$ENDIF}
if GtkWidgetIsA(Widget,GTK_TYPE_SCROLLBAR) then
begin
// the width of a scrollbar is fixed and depends only on the theme
gtk_widget_size_request(widget, @Requisition);
if GtkWidgetIsA(Widget, GTK_TYPE_HSCROLLBAR) then
begin
NewHeight:=Requisition.height;
end else begin
NewWidth:=Requisition.width;
end;
//DebugLn('TGtkWidgetSet.RealizeWidgetSize A ',Newwidth,',',Newheight);
end;
gtk_widget_set_usize(Widget, NewWidth, NewHeight);
//DebugLn(['TGtkWidgetSet.RealizeWidgetSize ',GetWidgetDebugReport(Widget),' NewWidth=',NewWidth,' NewHeight=',NewHeight]);
{$IFDEF Gtk1}
if GtkWidgetIsA(Widget, GTK_TYPE_COMBO) then
begin
// the combobox has an entry, which height is not resized
// automatically. Do it manually.
gtk_widget_set_usize(PGtkCombo(Widget)^.entry,
PGtkCombo(Widget)^.entry^.allocation.width, NewHeight);
end;
{$ENDIF}
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);
gtk_widget_set_usize(FixedWidget,NewWidth,NewHeight);
end;
end;
end;
procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);
var
LCLWidth: LongInt;
LCLHeight: LongInt;
Widget: PGtkWidget;
ParentWidget: PGtkWidget;
ParentFixed: PGtkWidget;
WinWidgetInfo: PWidgetInfo;
procedure WriteBigWarning;
begin
DebugLn('WARNING: SetWidgetSizeAndPosition: resizing BIG ',
' Control=',LCLControl.Name,':',LCLControl.ClassName,
' NewSize=',dbgs(LCLWidth),',',dbgs(LCLHeight));
//RaiseException('');
end;
procedure WriteWarningParentWidgetNotFound;
begin
DebugLn('WARNING: SetWidgetSizeAndPosition - '
,'Parent''s Fixed Widget not found');
DebugLn(' Control=',LCLControl.Name,':',LCLControl.ClassName,
' Parent=',LCLControl.Parent.Name,':',LCLControl.Parent.ClassName,
' ParentWidget=',DbgS(ParentWidget),
'');
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
begin
ParentWidget:=pgtkWidget(LCLControl.Parent.Handle);
ParentFixed := GetFixedWidget(ParentWidget);
if GtkWidgetIsA(ParentFixed,GTK_FIXED_GET_TYPE)
or GtkWidgetIsA(ParentFixed,GTK_LAYOUT_GET_TYPE) then begin
FixedMoveControl(ParentFixed, Widget,
LCLControl.Left,LCLControl.Top);
end else begin
WinWidgetInfo:=GetWidgetInfo(Widget,false);
if (WinWidgetInfo=nil)
or (not (wwiNotOnParentsClientArea in WinWidgetInfo^.Flags)) then
WriteWarningParentWidgetNotFound;
end;
end;
end;
{------------------------------------------------------------------------------
Method: SetWindowSizeAndPosition
Params: Widget: PGtkWidget; AWinControl: TWinControl
Returns: Nothing
Set the size and position of a top level window.
------------------------------------------------------------------------------}
procedure SetWindowSizeAndPosition(Window: PGtkWindow;
AWinControl: TWinControl);
var
Width, Height: integer;
//Info: PGtkWindowGeometryInfo;
begin
Width:=AWinControl.Width;
// 0 and negative values have a special meaning, so don't use them
if Width<=0 then Width:=1;
Height:=AWinControl.Height;
if Height<=0 then Height:=1;
//DebugLn('TGtkWidgetSet.SetWindowSizeAndPosition ',AWinControl.Name,':',AWinControl.ClassName,' ',AWinControl.Visible,' Old=',PGtkWidget(Window)^.allocation.Width,',',PGtkWidget(Window)^.allocation.Width,' New=',Width,',',Height);
// set geometry default size
//Info:=gtk_window_get_geometry_info(Window, TRUE);
//if (Info^.default_width<>Width) or (Info^.default_height<>Height) then
gtk_window_set_default_size(Window,Width,Height);
{$IFDEF Gtk2}
// resize
gtk_window_resize(Window,Width,Height);
// reposition
gtk_window_move(Window,AWinControl.Left,AWinControl.Top);
{$ELSE}
// resize
if assigned(PGtkWidget(Window)^.Window) then
// widget is realized, resize gdkwindow directly
gdk_window_move_resize(PGtkWidget(Window)^.Window,AWinControl.Left,
AWinControl.Top,Width,Height)
else begin
// widget is not yet realized, force resize needed for shrinking under gtk1
gtk_widget_set_usize(PGtkWidget(Window), -1,-1);
end;
// reposition
gtk_widget_set_usize(PGtkWidget(Window),Width,Height);
gtk_widget_set_uposition(PGtkWidget(Window),AWinControl.Left,AWinControl.Top);
{$ENDIF}
{$IFDEF VerboseSizeMsg}
DebugLn(['SetWindowSizeAndPosition B ',DbgSName(AWinControl),
' Visible=',AWinControl.Visible,
' Old=',PGtkWidget(Window)^.allocation.X,',',PGtkWidget(Window)^.allocation.Y,
' New=',AWinControl.Left,',',AWinControl.Top,',',Width,'x',Height]);
{$ENDIF}
end;
Procedure ReportNotObsolete(const Texts : String); Procedure ReportNotObsolete(const Texts : String);
Begin Begin
DebugLn('*********************************************'); DebugLn('*********************************************');
@ -6932,7 +7372,7 @@ function IndexOfStyleWithName(const WName : String): integer;
begin begin
if Styles<>nil then begin if Styles<>nil then begin
for Result:=0 to Styles.Count-1 do for Result:=0 to Styles.Count-1 do
if AnsiCompareText(WName,Styles[Result])=0 then exit; if CompareText(WName,Styles[Result])=0 then exit;
end; end;
Result:=-1; Result:=-1;
end; end;
@ -6946,24 +7386,13 @@ end;
'default', checkbox', etc. This should only be called on theme change or on 'default', checkbox', etc. This should only be called on theme change or on
application terminate. application terminate.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
Type function NewStyleObject : PStyleObject;
PStyleObject = ^TStyleObject;
TStyleObject = Record
Style : PGTKStyle;
Widget : PGTKWidget;
end;
var
StandardStyles: array[TLazGtkStyle] of PStyleObject;
Function NewStyleObject : PStyleObject;
begin begin
New(Result); New(Result);
Result^.Widget := nil; FillChar(Result^,SizeOf(TStyleObject),0);
Result^.Style := nil;
end; end;
Procedure FreeStyleObject(var StyleObject : PStyleObject); procedure FreeStyleObject(var StyleObject : PStyleObject);
// internal function to dispose a styleobject // internal function to dispose a styleobject
// it does *not* remove it from the style lists // it does *not* remove it from the style lists
begin begin
@ -7066,6 +7495,8 @@ end;
of Styles. of Styles.
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function GetStyleWithName(const WName: String) : PGTKStyle; function GetStyleWithName(const WName: String) : PGTKStyle;
var
StyleObject : PStyleObject;
function CreateStyleNotebook: PGTKWidget; function CreateStyleNotebook: PGTKWidget;
var var
@ -7091,11 +7522,29 @@ function GetStyleWithName(const WName: String) : PGTKStyle;
NoteBookTabLabel,NoteBookTabMenuLabel); NoteBookTabLabel,NoteBookTabMenuLabel);
gtk_widget_set_usize(Result,200,200); gtk_widget_set_usize(Result,200,200);
end; end;
procedure ResizeWidget(CurWidget: PGTKWidget; NewWidth, NewHeight: integer);
{$IFDEF Gtk1}
begin
gtk_widget_set_usize(StyleObject^.Widget,NewWidth,NewHeight);
end;
{$ELSE}
var
allocation: TGtkAllocation;
begin
allocation.x:=0;
allocation.y:=0;
allocation.width:=NewWidth;
allocation.height:=NewHeight;
//gtk_widget_set_usize(StyleObject^.Widget,NewWidth,NewHeight);
gtk_widget_size_allocate(CurWidget,@allocation);
StyleObject^.FrameBordersValid:=false;
end;
{$ENDIF}
var var
Tp : Pointer; Tp : Pointer;
l : Longint; l : Longint;
StyleObject : PStyleObject;
NoName: PGChar; NoName: PGChar;
lgs: TLazGtkStyle; lgs: TLazGtkStyle;
WidgetName: String; WidgetName: String;
@ -7111,11 +7560,11 @@ begin
exit; exit;
{$ENDIF} {$ENDIF}
If (WName='') then exit; if (WName='') then exit;
l:=IndexOfStyleWithName(WName); l:=IndexOfStyleWithName(WName);
//DebugLn('GetStyleWithName START ',WName,' ',l); //DebugLn(['GetStyleWithName START ',WName,' ',l]);
If l >= 0 then begin if l >= 0 then begin
StyleObject:=PStyleObject(Styles.Objects[l]); StyleObject:=PStyleObject(Styles.Objects[l]);
Result := StyleObject^.Style; Result := StyleObject^.Style;
@ -7237,17 +7686,24 @@ begin
else else
If CompareText(WName,LazGtkStyleNames[lgsHScale])=0 then begin If CompareText(WName,LazGtkStyleNames[lgsHScale])=0 then begin
lgs:=lgsHScale; lgs:=lgsHScale;
AddToStyleWindow:=true;
TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0)); TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0));
StyleObject^.Widget := gtk_hscale_new (PGTKADJUSTMENT (TP)); StyleObject^.Widget := gtk_hscale_new (PGTKADJUSTMENT (TP));
end end
else else
If CompareText(WName,LazGtkStyleNames[lgsVScale])=0 then begin If CompareText(WName,LazGtkStyleNames[lgsVScale])=0 then begin
lgs:=lgsVScale; lgs:=lgsVScale;
AddToStyleWindow:=true;
TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0)); TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0));
StyleObject^.Widget := gtk_vscale_new (PGTKADJUSTMENT (TP)); StyleObject^.Widget := gtk_vscale_new (PGTKADJUSTMENT (TP));
end end
else
If CompareText(WName,LazGtkStyleNames[lgsGroupBox])=0 then begin
lgs:=lgsGroupBox;
StyleObject^.Widget := gtk_frame_new('GroupBox');
WindowFixedWidget:=CreateFixedClientWidget;
gtk_widget_show(WindowFixedWidget);
gtk_container_add(PGtkContainer(StyleObject^.Widget), WindowFixedWidget);
gtk_object_set_data(PGtkObject(StyleObject^.Widget),'fixedwidget',WindowFixedWidget);
end
else else
If CompareText(WName,LazGtkStyleNames[lgsGTK_Default])=0 then begin If CompareText(WName,LazGtkStyleNames[lgsGTK_Default])=0 then begin
lgs:=lgsGTK_Default; lgs:=lgsGTK_Default;
@ -7277,10 +7733,9 @@ begin
StyleWindowWidget:=GetStyleWidget(lgsWindow); StyleWindowWidget:=GetStyleWidget(lgsWindow);
WindowFixedWidget:=PGTKWidget( WindowFixedWidget:=PGTKWidget(
gtk_object_get_data(PGtkObject(StyleWindowWidget),'fixedwidget')); gtk_object_get_data(PGtkObject(StyleWindowWidget),'fixedwidget'));
//DebugLn('AddToStyleWindow A ',GetWidgetDebugReport(StyleObject^.Widget)); //DebugLn('AddToStyleWindow adding on hidden stylewindow ',WName,' ',GetWidgetDebugReport(StyleObject^.Widget));
//gtk_box_pack_end(PGTKBox(VBox), WindowFixedWidget, True, True, 0); //gtk_box_pack_end(PGTKBox(VBox), WindowFixedWidget, True, True, 0);
gtk_fixed_put(PGtkFixed(WindowFixedWidget),StyleObject^.Widget,0,0); gtk_fixed_put(PGtkFixed(WindowFixedWidget),StyleObject^.Widget,10,10);
gtk_widget_set_usize(StyleObject^.Widget,200,200);
end; end;
WidgetName:='LazStyle'+WName; WidgetName:='LazStyle'+WName;
@ -7290,19 +7745,24 @@ begin
StyleObject^.Style:=gtk_widget_get_style(StyleObject^.Widget); StyleObject^.Style:=gtk_widget_get_style(StyleObject^.Widget);
// ToDo: find out, why sometimes the style is not initialized. // ToDo: find out, why sometimes the style is not initialized.
// for example: why the following occurs: // for example: why the following occurs:
If CompareText(WName,'button')=0 then begin if CompareText(WName,'button')=0 then begin
if StyleObject^.Style^.light_gc[GTK_STATE_NORMAL]=nil then begin if StyleObject^.Style^.light_gc[GTK_STATE_NORMAL]=nil then begin
//DebugLn('GetStyleWithName ',WName); //DebugLn('GetStyleWithName ',WName);
if not GtkWidgetIsA(StyleObject^.Widget,GTK_WINDOW_GET_TYPE) then begin
gtk_widget_realize(StyleObject^.Widget);
end;
end; end;
end; end;
if AddToStyleWindow then begin
if not GtkWidgetIsA(StyleObject^.Widget,GTK_WINDOW_GET_TYPE) then begin
//DebugLn(['GetStyleWithName realizing ...']);
gtk_widget_realize(StyleObject^.Widget);
//DebugLn('AddToStyleWindow realized: ',WName,' ',GetWidgetDebugReport(StyleObject^.Widget));
end;
ResizeWidget(StyleObject^.Widget,200,200);
end;
end; end;
// increase refcount of style // increase refcount of style
If StyleObject^.Style <> nil then If StyleObject^.Style <> nil then
If AnsiCompareText(WName,LazGtkStyleNames[lgsGTK_Default])<>0 then If CompareText(WName,LazGtkStyleNames[lgsGTK_Default])<>0 then
StyleObject^.Style:=GTK_Style_Ref(StyleObject^.Style); StyleObject^.Style:=GTK_Style_Ref(StyleObject^.Style);
// if successful add to style objects list // if successful add to style objects list
@ -7312,7 +7772,7 @@ begin
StandardStyles[lgs]:=StyleObject; StandardStyles[lgs]:=StyleObject;
Result:=StyleObject^.Style; Result:=StyleObject^.Style;
If (StyleObject^.Widget <> nil) If (StyleObject^.Widget <> nil)
and (AnsiCompareText(WName,LazGtkStyleNames[lgsWindow])=0) then and (CompareText(WName,LazGtkStyleNames[lgsWindow])=0) then
UpdateSysColorMap(StyleObject^.Widget); UpdateSysColorMap(StyleObject^.Widget);
// ToDo: create all gc of the style // ToDo: create all gc of the style
@ -7878,6 +8338,38 @@ begin
RealizeGtkStyleColor(Style,Result); RealizeGtkStyleColor(Style,Result);
end; end;
{$IFDEF Gtk2}
function GetStyleGroupboxFrameBorders: TRect;
var
StyleObject: PStyleObject;
allocation: TGtkAllocation;
FrameWidget: PGtkFrame;
f: TRect;
begin
GetStyleWidget(lgsGroupBox);
StyleObject:=StandardStyles[lgsGroupBox];
if not StyleObject^.FrameBordersValid then begin
allocation.x:=0;
allocation.y:=0;
allocation.width:=200;
allocation.height:=200;
gtk_widget_size_allocate(StyleObject^.Widget,@allocation);
FrameWidget:=pGtkFrame(StyleObject^.Widget);
GTK_FRAME_GET_CLASS(FrameWidget)^.compute_child_allocation(
FrameWidget,@allocation);
//DebugLn(['GetStyleGroupboxFrame BBB2 ',dbgs(allocation)]);
f.Left:=Min(200,Max(0,allocation.x));
f.Top:=Min(200,Max(0,allocation.y));
f.Right:=Max(0,Min(200-f.Left,200-allocation.x-allocation.width));
f.Bottom:=Max(0,Min(200-f.Top,200-allocation.x-allocation.width));
StyleObject^.FrameBorders:=f;
//DebugLn(['GetStyleGroupboxFrame FrameBorders=',dbgs(StyleObject^.FrameBorders)]);
StyleObject^.FrameBordersValid:=true;
end;
Result:=StyleObject^.FrameBorders
end;
{$ENDIF}
procedure StyleFillRectangle(drawable : PGDKDrawable; GC : PGDKGC; Color : TColorRef; x, y, width, height : gint); procedure StyleFillRectangle(drawable : PGDKDrawable; GC : PGDKGC; Color : TColorRef; x, y, width, height : gint);
var var
style : PGTKStyle; style : PGTKStyle;

View File

@ -704,6 +704,11 @@ procedure SaveClientSizeNotification(FixWidget: PGtkWidget);
function CreateTopologicalSortedWidgets(HashArray: TDynHashArray): TFPList; function CreateTopologicalSortedWidgets(HashArray: TDynHashArray): TFPList;
procedure GetGTKDefaultWidgetSize(AWinControl: TWinControl; procedure GetGTKDefaultWidgetSize(AWinControl: TWinControl;
var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean);
procedure SendSizeNotificationToLCL(MainWidget: PGtkWidget);
procedure SendCachedGtkResizeNotifications;
procedure RealizeWidgetSize(Widget: PGtkWidget; NewWidth, NewHeight: integer);
procedure SetWidgetSizeAndPosition(LCLControl: TWinControl);
procedure SetWindowSizeAndPosition(Window: PGtkWindow; AWinControl: TWinControl);
// debug // debug
procedure ReportNotObsolete(const Texts: String); procedure ReportNotObsolete(const Texts: String);
@ -723,6 +728,18 @@ function GdkAtomToStr(const Atom: TGdkAtom): string;
function CreateFormContents(AForm: TCustomForm; var FormWidget: Pointer): Pointer; function CreateFormContents(AForm: TCustomForm; var FormWidget: Pointer): Pointer;
// styles // styles
type
PStyleObject = ^TStyleObject;
TStyleObject = Record
Style : PGTKStyle;
Widget : PGTKWidget;
FrameBordersValid: boolean;
FrameBorders: TRect;
end;
var
StandardStyles: array[TLazGtkStyle] of PStyleObject;
function IndexOfStyle(aStyle: TLazGtkStyle): integer; function IndexOfStyle(aStyle: TLazGtkStyle): integer;
function IndexOfStyleWithName(const WName: String): integer; function IndexOfStyleWithName(const WName: String): integer;
procedure ReleaseAllStyles; procedure ReleaseAllStyles;
@ -732,6 +749,9 @@ function GetStyle(aStyle: TLazGtkStyle): PGTKStyle;
function GetStyleWithName(const WName: String): PGTKStyle; function GetStyleWithName(const WName: String): PGTKStyle;
function GetStyleWidget(aStyle: TLazGtkStyle): PGTKWidget; function GetStyleWidget(aStyle: TLazGtkStyle): PGTKWidget;
function GetStyleWidgetWithName(const WName: String): PGTKWidget; function GetStyleWidgetWithName(const WName: String): PGTKWidget;
{$IFDEF Gtk2}
function GetStyleGroupboxFrameBorders: TRect;
{$ENDIF}
procedure StyleFillRectangle(drawable: PGDKDrawable; GC: PGDKGC; procedure StyleFillRectangle(drawable: PGDKDrawable; GC: PGDKGC;
Color: TColorRef; x, y, width, height: gint); Color: TColorRef; x, y, width, height: gint);
function StyleForegroundColor(Color: TColorRef; DefaultColor: PGDKColor): PGDKColor; function StyleForegroundColor(Color: TColorRef; DefaultColor: PGDKColor): PGDKColor;

View File

@ -6407,11 +6407,33 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
function TGtkWidgetSet.GetWindowRelativePosition(Handle : hwnd; function TGtkWidgetSet.GetWindowRelativePosition(Handle : hwnd;
var Left, Top: integer): boolean; var Left, Top: integer): boolean;
var
aWidget: PGtkWidget;
{$IFDEF Gtk2}
GdkWindow: PGdkWindow;
GtkLeft, GtkTop: gint;
{$ENDIF}
begin begin
if GtkWidgetIsA(PGtkWidget(Handle),GTK_TYPE_WIDGET) then begin aWidget:=PGtkWidget(Handle);
if GtkWidgetIsA(aWidget,GTK_TYPE_WIDGET) then begin
Result:=true; Result:=true;
Left:=PGtkWidget(Handle)^.Allocation.X; Left:=aWidget^.allocation.X;
Top:=PGtkWidget(Handle)^.Allocation.Y; 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}
end else end else
Result:=false; Result:=false;
end; end;

View File

@ -60,10 +60,8 @@ type
procedure HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject); override; procedure HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject); override;
function LoadStockPixmap(StockID: longint) : HBitmap; override; function LoadStockPixmap(StockID: longint) : HBitmap; override;
procedure SetCallbackEx(const AMsg: LongInt; const AGTKObject: PGTKObject; const ALCLObject: TObject; Direct: boolean);override; procedure SetCallbackEx(const AMsg: LongInt; const AGTKObject: PGTKObject; const ALCLObject: TObject; Direct: boolean);override;
//procedure SetLabel(Sender : TObject; Data : Pointer);
procedure SetSelectionMode(Sender: TObject; Widget: PGtkWidget; procedure SetSelectionMode(Sender: TObject; Widget: PGtkWidget;
MultiSelect, ExtendedSelect: boolean); override; MultiSelect, ExtendedSelect: boolean); override;
//function SetTopIndex(Sender: TObject; NewTopIndex: integer): integer; override;
procedure InitializeFileDialog(FileDialog: TFileDialog; procedure InitializeFileDialog(FileDialog: TFileDialog;
var SelWidget: PGtkWidget; Title: PChar); override; var SelWidget: PGtkWidget; Title: PChar); override;

View File

@ -81,6 +81,9 @@ type
private private
protected protected
public public
class function GetDefaultClientRect(const AWinControl: TWinControl;
const aLeft, aTop, aWidth, aHeight: integer; var aClientRect: TRect
): boolean; override;
end; end;
{ TGtk2WSGroupBox } { TGtk2WSGroupBox }
@ -1259,6 +1262,28 @@ begin
inherited DestroyHandle(AWinControl); inherited DestroyHandle(AWinControl);
end; end;
{ TGtk2WSCustomGroupBox }
class function TGtk2WSCustomGroupBox.GetDefaultClientRect(
const AWinControl: TWinControl; const aLeft, aTop, aWidth, aHeight: integer;
var aClientRect: TRect): boolean;
var
FrameBorders: TRect;
begin
Result:=false;
//DebugLn(['TGtk2WSCustomGroupBox.GetDefaultClientRect ',DbgSName(AWinControl),' ',aWidth,'x',aHeight]);
if AWinControl.HandleAllocated then begin
end else begin
FrameBorders:=GetStyleGroupboxFrameBorders;
aClientRect:=Rect(0,0,
Max(0,aWidth-FrameBorders.Left-FrameBorders.Right),
Max(0,aHeight-FrameBorders.Top-FrameBorders.Bottom));
Result:=true;
end;
//if Result then DebugLn(['TGtk2WSCustomGroupBox.GetDefaultClientRect AAA2 FrameBorders=',dbgs(FrameBorders),' aClientRect=',dbgs(aClientRect)]);
end;
initialization initialization
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
@ -1268,7 +1293,7 @@ initialization
// which actually implement something // which actually implement something
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
// RegisterWSComponent(TScrollBar, TGtk2WSScrollBar); // RegisterWSComponent(TScrollBar, TGtk2WSScrollBar);
// RegisterWSComponent(TCustomGroupBox, TGtk2WSCustomGroupBox); RegisterWSComponent(TCustomGroupBox, TGtk2WSCustomGroupBox);
// RegisterWSComponent(TGroupBox, TGtk2WSGroupBox); // RegisterWSComponent(TGroupBox, TGtk2WSGroupBox);
RegisterWSComponent(TCustomComboBox, TGtk2WSCustomComboBox); RegisterWSComponent(TCustomComboBox, TGtk2WSCustomComboBox);
// RegisterWSComponent(TComboBox, TGtk2WSComboBox); // RegisterWSComponent(TComboBox, TGtk2WSComboBox);

View File

@ -86,6 +86,7 @@ type
class function GetClientBounds(const AWincontrol: TWinControl; var ARect: TRect): Boolean; virtual; class function GetClientBounds(const AWincontrol: TWinControl; var ARect: TRect): Boolean; virtual;
class function GetClientRect(const AWincontrol: TWinControl; var ARect: TRect): Boolean; virtual; class function GetClientRect(const AWincontrol: TWinControl; var ARect: TRect): Boolean; virtual;
class procedure GetPreferredSize(const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); virtual; class procedure GetPreferredSize(const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); virtual;
class function GetDefaultClientRect(const AWinControl: TWinControl; const aLeft, aTop, aWidth, aHeight: integer; var aClientRect: TRect): boolean; virtual;
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; virtual; class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; virtual;
class function GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean; virtual; class function GetTextLen(const AWinControl: TWinControl; var ALength: Integer): Boolean; virtual;
@ -99,9 +100,10 @@ type
class procedure SetText(const AWinControl: TWinControl; const AText: String); virtual; class procedure SetText(const AWinControl: TWinControl; const AText: String); virtual;
class procedure SetCursor(const AWinControl: TWinControl; const ACursor: HCursor); virtual; class procedure SetCursor(const AWinControl: TWinControl; const ACursor: HCursor); virtual;
{ TODO: this procedure is only used in win32 interface } { TODO: move AdaptBounds: it is only used in winapi interfaces }
class procedure AdaptBounds(const AWinControl: TWinControl; class procedure AdaptBounds(const AWinControl: TWinControl;
var Left, Top, Width, Height: integer; var SuppressMove: boolean); virtual; var Left, Top, Width, Height: integer; var SuppressMove: boolean); virtual;
class procedure ConstraintsChange(const AWinControl: TWinControl); virtual; class procedure ConstraintsChange(const AWinControl: TWinControl); virtual;
class function CreateHandle(const AWinControl: TWinControl; class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle; virtual; const AParams: TCreateParams): TLCLIntfHandle; virtual;
@ -202,6 +204,13 @@ class procedure TWSWinControl.GetPreferredSize(const AWinControl: TWinControl;
begin begin
end; end;
class function TWSWinControl.GetDefaultClientRect(
const AWinControl: TWinControl; const aLeft, aTop, aWidth, aHeight: integer;
var aClientRect: TRect): boolean;
begin
Result:=false;
end;
class procedure TWSWinControl.Invalidate(const AWinControl: TWinControl); class procedure TWSWinControl.Invalidate(const AWinControl: TWinControl);
begin begin
end; end;