mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 11:19:26 +02:00
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:
parent
58a04388c9
commit
f1ddc29682
@ -1465,7 +1465,8 @@ type
|
||||
wcfEraseBackground,
|
||||
wcfCreatingHandle, // Set while constructing the handle of this control
|
||||
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;
|
||||
|
||||
@ -1563,6 +1564,7 @@ type
|
||||
procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
|
||||
procedure CMShowingChanged(var Message: TLMessage); message CM_SHOWINGCHANGED;
|
||||
procedure CMVisibleChanged(var TheMessage: TLMessage); message CM_VISIBLECHANGED;
|
||||
procedure DoSendShowHideToInterface; virtual;
|
||||
procedure ControlsAligned; virtual;
|
||||
procedure DoSendBoundsToInterface; virtual;
|
||||
procedure RealizeBounds; virtual;
|
||||
|
@ -398,8 +398,8 @@ type
|
||||
{$ENDIF}
|
||||
|
||||
{ TGraphicsObject
|
||||
In Delphi VCL this is the ancestor of TFon, TPen and TBrush.
|
||||
With FPC 2.0 the LCL uses TFPCanvasHelper. }
|
||||
In Delphi VCL this is the ancestor of TFont, TPen and TBrush.
|
||||
Since FPC 2.0 the LCL uses TFPCanvasHelper as ancestor. }
|
||||
|
||||
TGraphicsObject = class(TPersistent)
|
||||
private
|
||||
|
@ -336,6 +336,7 @@ begin
|
||||
DebugLn('TControl.ChangeBounds A ',Name,':',ClassName,
|
||||
' 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
|
||||
{$ENDIF}
|
||||
// constraint the size
|
||||
DoConstrainedResize(ALeft, ATop, AWidth, AHeight);
|
||||
@ -1212,17 +1213,17 @@ begin
|
||||
Result:=ClientRect.Right;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TControl GetEnabled }
|
||||
{------------------------------------------------------------------------------}
|
||||
{------------------------------------------------------------------------------
|
||||
TControl GetEnabled
|
||||
------------------------------------------------------------------------------}
|
||||
function TControl.GetEnabled: Boolean;
|
||||
begin
|
||||
Result := FEnabled;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TControl GetMouseCapture }
|
||||
{------------------------------------------------------------------------------}
|
||||
{------------------------------------------------------------------------------
|
||||
TControl GetMouseCapture
|
||||
------------------------------------------------------------------------------}
|
||||
Function TControl.GetMouseCapture : Boolean;
|
||||
Begin
|
||||
Result := GetCaptureControl = Self;
|
||||
@ -1236,9 +1237,9 @@ begin
|
||||
Result := UndockHeight;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TControl GetPopupMenu }
|
||||
{------------------------------------------------------------------------------}
|
||||
{------------------------------------------------------------------------------
|
||||
TControl GetPopupMenu
|
||||
------------------------------------------------------------------------------}
|
||||
function TControl.GetPopupMenu: TPopupMenu;
|
||||
begin
|
||||
Result := FPopupMenu;
|
||||
@ -2195,8 +2196,10 @@ end;
|
||||
procedure TControl.SetClientHeight(Value: Integer);
|
||||
begin
|
||||
if csLoading in ComponentState then begin
|
||||
{$IFDEF DisableLoadedClientSize}
|
||||
FLoadedClientSize.Y:=Value;
|
||||
Include(FControlFlags,cfClientHeightLoaded);
|
||||
{$ENDIF}
|
||||
end else begin
|
||||
// during loading the ClientHeight is not used to set the Height of the
|
||||
// control, but only to restore autosizing. For example Anchors=[akBottom]
|
||||
@ -2223,8 +2226,10 @@ end;
|
||||
procedure TControl.SetClientWidth(Value: Integer);
|
||||
begin
|
||||
if csLoading in ComponentState then begin
|
||||
{$IFDEF DisableLoadedClientSize}
|
||||
FLoadedClientSize.X:=Value;
|
||||
Include(FControlFlags,cfClientWidthLoaded);
|
||||
{$ENDIF}
|
||||
end else begin
|
||||
// during loading the ClientWidth is not used to set the Width of the
|
||||
// control, but only to restore autosizing. For example Anchors=[akRight]
|
||||
|
@ -1752,7 +1752,12 @@ procedure TCustomForm.Loaded;
|
||||
var
|
||||
Control: TWinControl;
|
||||
begin
|
||||
inherited Loaded;
|
||||
DisableAlign;
|
||||
try
|
||||
inherited Loaded;
|
||||
finally
|
||||
EnableAlign;
|
||||
end;
|
||||
if (ActiveControl <> nil) and (Parent=nil) then
|
||||
begin
|
||||
Control := ActiveControl;
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
{ $DEFINE CHECK_POSITION}
|
||||
{ $IFDEF CHECK_POSITION}
|
||||
const CheckPostionClassName = 'THintWindow';
|
||||
const CheckPostionName = 'ListBox1';
|
||||
const CheckPostionClassName = 'xxTHintWindow';
|
||||
const CheckPostionName = 'xxListBox1';
|
||||
|
||||
function CheckPosition(AControl: TControl): boolean;
|
||||
begin
|
||||
@ -1065,6 +1065,8 @@ var
|
||||
var
|
||||
NewLeft, NewTop, NewWidth, NewHeight: Integer;
|
||||
ParentBaseClientSize: TPoint;
|
||||
ParentClientWidth: integer;
|
||||
ParentClientHeight: integer;
|
||||
CurBaseBounds: TRect;
|
||||
NewRight: 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);
|
||||
ConstraintHeight(NewTop,NewHeight);
|
||||
end;
|
||||
ParentClientWidth:=Control.Parent.ClientWidth;
|
||||
ParentClientHeight:=Control.Parent.ClientHeight;
|
||||
|
||||
|
||||
InitAnchorSideCache;
|
||||
|
||||
{ Recalculate the anchors
|
||||
@ -1205,7 +1208,7 @@ var
|
||||
This is controlled with the AnchorSide properties.
|
||||
|
||||
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
|
||||
edges to which it is anchored.
|
||||
If a control is anchored to opposite edges of its parent, the control
|
||||
@ -1230,8 +1233,7 @@ var
|
||||
ParentBaseClientSize:=Control.FBaseParentClientSize;
|
||||
if (ParentBaseClientSize.X=0)
|
||||
and (ParentBaseClientSize.Y=0) then
|
||||
ParentBaseClientSize:=Point(Control.Parent.ClientWidth,
|
||||
Control.Parent.ClientHeight);
|
||||
ParentBaseClientSize:=Point(ParentClientWidth,ParentClientHeight);
|
||||
|
||||
// get base bounds of Control
|
||||
CurBaseBounds:=Control.FBaseBounds;
|
||||
@ -1246,7 +1248,7 @@ var
|
||||
' Self='+DbgSName(Self),' Control='+DbgSName(Control),
|
||||
' CurBaseBounds='+dbgs(CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Top)+','+dbgs(CurBaseBounds.Right-CurBaseBounds.Left)+','+dbgs(CurBaseBounds.Bottom-CurBaseBounds.Top),
|
||||
' 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),
|
||||
'');
|
||||
{$ENDIF}
|
||||
@ -1257,7 +1259,7 @@ var
|
||||
if akRight in CurAnchors then begin
|
||||
// keep distance to right side of parent or another sibling
|
||||
// -> change the width
|
||||
NewRight:=Control.Parent.ClientWidth
|
||||
NewRight:=ParentClientWidth
|
||||
-(ParentBaseClientSize.X-CurBaseBounds.Right);
|
||||
if (not (akRight in CurAlignAnchors))
|
||||
and (akRight in Control.Anchors) then
|
||||
@ -1272,7 +1274,7 @@ var
|
||||
if akRight in CurAnchors then begin
|
||||
// keep distance to right side of parent
|
||||
// and keep new width
|
||||
NewRight:=Control.Parent.ClientWidth
|
||||
NewRight:=ParentClientWidth
|
||||
-(ParentBaseClientSize.X-CurBaseBounds.Right);
|
||||
if (not (akRight in CurAlignAnchors))
|
||||
and (akRight in Control.Anchors) then
|
||||
@ -1281,7 +1283,7 @@ var
|
||||
end else begin
|
||||
// do not anchor to the right
|
||||
// -> keep new width and center horizontally
|
||||
NewLeft:=(Control.Parent.ClientWidth-NewWidth) div 2;
|
||||
NewLeft:=(ParentClientWidth-NewWidth) div 2;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2146,21 +2148,11 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TWinControl.DoSetBounds(ALeft, ATop, AWidth, AHeight : integer);
|
||||
begin
|
||||
if wcfClientRectNeedsUpdate in FWinControlFlags then begin
|
||||
GetClientRect;
|
||||
end;
|
||||
{$IFDEF VerboseClientRectBugFix}
|
||||
DbgOut('[TWinControl.DoSetBounds] ',Name,':',ClassName,' OldClient=',DbgS(FClientWidth),',',DbgS(FClientHeight),
|
||||
DbgOut('[TWinControl.DoSetBounds] ',Name,':',ClassName,
|
||||
' OldHeight=',DbgS(FHeight),' NewHeight=',DbgS(AHeight));
|
||||
{$ENDIF}
|
||||
inc(FClientWidth,AWidth-FWidth);
|
||||
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}
|
||||
|
||||
InvalidateClientRectCache(false);
|
||||
inherited DoSetBounds(ALeft,ATop,AWidth,AHeight);
|
||||
end;
|
||||
|
||||
@ -2307,20 +2299,35 @@ function TWinControl.GetClientRect: TRect;
|
||||
var
|
||||
InterfaceWidth, InterfaceHeight: integer;
|
||||
begin
|
||||
if not HandleAllocated then begin
|
||||
Result:=inherited GetClientRect;
|
||||
StoreClientRect(Result);
|
||||
end else if wcfClientRectNeedsUpdate in FWinControlFlags then begin
|
||||
// update clientrect from interface
|
||||
LCLIntf.GetClientRect(Handle, Result);
|
||||
// the LCL is not always in sync with the interface
|
||||
// -> adjust client rect based on LCL bounds
|
||||
// for example: if the Width in LCL differ from the Width of the Interface
|
||||
// object, then adjust the clientwidth accordingly
|
||||
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);
|
||||
if wcfClientRectNeedsUpdate in FWinControlFlags then begin
|
||||
if TWSWinControlClass(WidgetSetClass).GetDefaultClientRect(Self,
|
||||
Left, Top, Width, Height, Result)
|
||||
then begin
|
||||
// the LCL interface provided a ClientRect
|
||||
end
|
||||
else if HandleAllocated then begin
|
||||
// update clientrect from interface
|
||||
LCLIntf.GetClientRect(Handle, Result);
|
||||
// the LCL is not always in sync with the interface
|
||||
// -> adjust client rect based on LCL bounds
|
||||
// for example: if the Width in LCL differ from the Width of the Interface
|
||||
// object, then adjust the clientwidth accordingly
|
||||
// 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);
|
||||
|
||||
{r:=inherited GetClientRect;
|
||||
@ -4509,7 +4516,7 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
constructor TWinControl.Create(TheOwner : TComponent);
|
||||
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
|
||||
// use property that bsNone is zero
|
||||
//FBorderStyle := bsNone;
|
||||
@ -4521,11 +4528,12 @@ begin
|
||||
FParentCtl3D:=true;
|
||||
FTabOrder := -1;
|
||||
FTabStop := False;
|
||||
InvalidateClientRectCache(false);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TWinControl CreateParented }
|
||||
{------------------------------------------------------------------------------}
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl CreateParented
|
||||
------------------------------------------------------------------------------}
|
||||
constructor TWinControl.CreateParented(ParentWindow: hwnd);
|
||||
begin
|
||||
FParentWindow := ParentWindow;
|
||||
@ -4845,8 +4853,8 @@ var
|
||||
begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if CheckPosition(Self) then
|
||||
DebugLn('TWinControl.WMSize A ',Name,':',ClassName,' Message=',dbgs(Message.Width),',',dbgs(Message.Height),
|
||||
' BoundsRealized=',dbgs(FBoundsRealized),' FromIntf=',(Message.SizeType and Size_SourceIsInterface)>0));
|
||||
DebugLn(['TWinControl.WMSize A ',Name,':',ClassName,' Message=',Message.Width,',',Message.Height,
|
||||
' BoundsRealized=',dbgs(FBoundsRealized),' FromIntf=',(Message.SizeType and Size_SourceIsInterface)>0]);
|
||||
{$ENDIF}
|
||||
NewLeft:=Left;
|
||||
NewTop:=Top;
|
||||
@ -4859,7 +4867,7 @@ 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) then exit;
|
||||
FBoundsRealized:=NewBoundsRealized;
|
||||
InvalidatePreferredSize;
|
||||
end;
|
||||
@ -5390,54 +5398,57 @@ var
|
||||
AChild: TControl;
|
||||
LoadedClientSize: TPoint;
|
||||
begin
|
||||
//DebugLn(['TWinControl.Loaded ',DbgSName(Self),' cfWidthLoaded=',cfWidthLoaded in FControlFlags,' cfHeightLoaded=',cfHeightLoaded in FControlFlags,' ']);
|
||||
if cfClientWidthLoaded in FControlFlags then
|
||||
LoadedClientSize.X:=FLoadedClientSize.X
|
||||
else begin
|
||||
LoadedClientSize.X:=ClientWidth;
|
||||
if LoadedClientSize.X<=0 then
|
||||
LoadedClientSize.X:=Width;
|
||||
end;
|
||||
if cfClientHeightLoaded in FControlFlags then
|
||||
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);
|
||||
DisableAlign;
|
||||
try
|
||||
//DebugLn(['TWinControl.Loaded ',DbgSName(Self),' cfWidthLoaded=',cfWidthLoaded in FControlFlags,' cfHeightLoaded=',cfHeightLoaded in FControlFlags,' ']);
|
||||
if cfClientWidthLoaded in FControlFlags then
|
||||
LoadedClientSize.X:=FLoadedClientSize.X
|
||||
else begin
|
||||
LoadedClientSize.X:=ClientWidth;
|
||||
if LoadedClientSize.X<=0 then
|
||||
LoadedClientSize.X:=Width;
|
||||
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];
|
||||
if cfClientHeightLoaded in FControlFlags then
|
||||
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;
|
||||
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;
|
||||
|
||||
inherited Loaded;
|
||||
|
||||
FixupTabList;
|
||||
RealizeBounds;
|
||||
|
||||
// align the childs
|
||||
if wcfReAlignNeeded in FWinControlFlags then
|
||||
ReAlign;
|
||||
end;
|
||||
|
||||
procedure TWinControl.FormEndUpdated;
|
||||
@ -5774,7 +5785,7 @@ end;
|
||||
are relevant.
|
||||
|
||||
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
|
||||
the widgetset.
|
||||
------------------------------------------------------------------------------}
|
||||
@ -5799,7 +5810,7 @@ begin
|
||||
if PreferredHeight>0 then
|
||||
inc(PreferredHeight,BorderSpacing.InnerBorder*2);
|
||||
end;
|
||||
|
||||
|
||||
if ControlCount>0 then begin
|
||||
|
||||
// get the size requirements for the child controls
|
||||
@ -5997,6 +6008,20 @@ begin
|
||||
ResizeDelayedAutoSizeChildren;
|
||||
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;
|
||||
begin
|
||||
|
||||
@ -6052,9 +6077,8 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TWinControl.CMShowingChanged(var Message: TLMessage);
|
||||
begin
|
||||
// ToDo: do not send this while loading, send it after loading.
|
||||
if HandleAllocated and ([csDestroying]*ComponentState=[])then
|
||||
TWSWinControlClass(WidgetSetClass).ShowHide(Self);
|
||||
if HandleAllocated and ([csDestroying,csLoading]*ComponentState=[]) then
|
||||
DoSendShowHideToInterface;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
|
@ -1115,11 +1115,12 @@ begin
|
||||
|
||||
// if iconified in changed then OnIconify...
|
||||
|
||||
if TObject(Data) is TCustomForm then begin
|
||||
TheForm := TCustomForm(Data);
|
||||
//DebugLn(['GTKWindowStateEventCB ',DbgSName(TheForm),' new_window_state=',state^.new_window_state,' changed_mask=',state^.changed_mask]);
|
||||
if TheForm.Parent = nil then begin (* toplevel window, just as a sanity check *)
|
||||
if GTK_WIDGET_REALIZED(Widget) then begin
|
||||
if GTK_WIDGET_REALIZED(Widget) then begin
|
||||
if TObject(Data) is TCustomForm then begin
|
||||
TheForm := TCustomForm(Data);
|
||||
//DebugLn(['GTKWindowStateEventCB ',DbgSName(TheForm),' new_window_state=',state^.new_window_state,' changed_mask=',state^.changed_mask]);
|
||||
if TheForm.Parent = nil then begin
|
||||
// toplevel window
|
||||
// send a WMSize Message (see TCustomForm.WMSize)
|
||||
GtkWidth:=Widget^.Allocation.Width;
|
||||
if GtkWidth<0 then GtkWidth:=0;
|
||||
@ -1130,12 +1131,13 @@ begin
|
||||
{$IFDEF HasX}
|
||||
NetAtom := gdk_atom_intern('_NET_WM_DESKTOP', True);
|
||||
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
|
||||
|
||||
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)
|
||||
then if ADesktop^ <> AIndex^ then begin
|
||||
// form is not on active desktop => ignore
|
||||
g_free(ADesktop);
|
||||
g_free(AIndex);
|
||||
exit;
|
||||
@ -1164,6 +1166,13 @@ begin
|
||||
Width := SmallInt(GtkWidth);
|
||||
Height := SmallInt(GtkHeight);
|
||||
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);
|
||||
end;
|
||||
end;
|
||||
@ -2353,8 +2362,9 @@ begin
|
||||
TControl(Data).Name+':'+TControl(Data).ClassName,
|
||||
' widget='+DbgS(Widget)+WidgetFlagsToString(widget)+
|
||||
' fixwidget=',DbgS(GetFixedWidget(Widget)),
|
||||
' NewSize=',dbgs(Size^.Width),',',dbgs(Size^.Height),
|
||||
' 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),
|
||||
','+dbgs(TControl(Data).Width)+'x'+dbgs(TControl(Data).Height));
|
||||
{$ENDIF}
|
||||
@ -2362,8 +2372,16 @@ begin
|
||||
if TControl(Data) is TCustomForm then
|
||||
DebugLn('VFP gtksize_allocateCB: ',TControl(Data).ClassName,' ',dbgs(Size^.X),',',dbgs(Size^.Y));
|
||||
{$ENDIF}
|
||||
if GTK_WIDGET_REALIZED(Widget) then
|
||||
if GTK_WIDGET_REALIZED(Widget) then begin
|
||||
{$IFDEF Gtk1}
|
||||
SaveSizeNotification(Widget);
|
||||
{$ELSE}
|
||||
if GetFixedWidget(Widget)=Widget then
|
||||
SendSizeNotificationToLCL(Widget)
|
||||
else
|
||||
SaveSizeNotification(Widget);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
|
||||
function gtksize_allocate_client(widget: PGtkWidget; size: pGtkAllocation;
|
||||
@ -2390,8 +2408,13 @@ begin
|
||||
end;
|
||||
MainWidget:=PGtkWidget(TWinControl(Data).Handle);
|
||||
ClientWidget:=GetFixedWidget(MainWidget);
|
||||
if GTK_WIDGET_REALIZED(ClientWidget) then
|
||||
if GTK_WIDGET_REALIZED(ClientWidget) then begin
|
||||
{$IFDEF Gtk1}
|
||||
SaveClientSizeNotification(ClientWidget);
|
||||
{$ELSE}
|
||||
SendSizeNotificationToLCL(MainWidget);
|
||||
{$ENDIF}
|
||||
end;
|
||||
end else begin
|
||||
// owner is not TWinControl -> ignore
|
||||
DebugLn('WARNING: gtksize_allocate_client: Data is not TWinControl. Data=',
|
||||
|
@ -445,6 +445,7 @@ var
|
||||
procedure GtkDefDone;
|
||||
|
||||
function dbgs(g: TGDIType): string; overload;
|
||||
function dbgs(r: TGDKRectangle): string; overload;
|
||||
|
||||
|
||||
implementation
|
||||
@ -830,6 +831,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function dbgs(r: TGDKRectangle): string;
|
||||
begin
|
||||
Result:=dbgs(Rect(r.x,r.y,r.width,r.height));
|
||||
end;
|
||||
|
||||
initialization
|
||||
GtkDefInit;
|
||||
|
||||
|
@ -113,6 +113,7 @@ type
|
||||
lgsStatusBar,
|
||||
lgsHScale,
|
||||
lgsVScale,
|
||||
lgsGroupBox,
|
||||
// user defined
|
||||
lgsUserDefined
|
||||
);
|
||||
@ -138,6 +139,7 @@ const
|
||||
'notebook',
|
||||
'hscale',
|
||||
'vscale',
|
||||
'groupbox',
|
||||
''
|
||||
);
|
||||
|
||||
@ -372,6 +374,7 @@ var
|
||||
// each fixed widget that was resized by the gtk is stored here
|
||||
// (hasharray of PGtkWidget)
|
||||
FFixWidgetsResized: TDynHashArray;
|
||||
FWidgetsWithResizeRequest: TDynHashArray; // hasharray of PGtkWidget
|
||||
|
||||
const
|
||||
aGtkJustification: array[TAlignment] of TGTKJustification =
|
||||
|
@ -92,7 +92,6 @@ type
|
||||
FRCFilename: string;
|
||||
FRCFileParsed: boolean;
|
||||
FRCFileAge: integer;
|
||||
FWidgetsWithResizeRequest: TDynHashArray; // hasharray of PGtkWidget
|
||||
FGTKToolTips: PGtkToolTips;
|
||||
|
||||
FLogHandlerID: guint; // ID returend by set_handler
|
||||
@ -230,8 +229,6 @@ type
|
||||
|
||||
// forms and dialogs
|
||||
procedure BringFormToFront(Sender: TObject);
|
||||
procedure SetWindowSizeAndPosition(Window: PGtkWindow;
|
||||
AWinControl: TWinControl);virtual;
|
||||
procedure UntransientWindow(GtkWindow: PGtkWindow);
|
||||
procedure InitializeFileDialog(FileDialog: TFileDialog;
|
||||
var SelWidget: PGtkWidget; Title: PChar); virtual;
|
||||
@ -273,8 +270,6 @@ type
|
||||
procedure SendPaintMessagesForInternalWidgets(AWinControl: TWinControl);
|
||||
function LCLtoGtkMessagePending: boolean;virtual;
|
||||
procedure SendCachedGtkMessages;virtual;
|
||||
procedure RealizeWidgetSize(Widget: PGtkWidget;
|
||||
NewWidth, NewHeight: integer); virtual;
|
||||
procedure FinishComponentCreate(const ALCLObject: TObject;
|
||||
const AGTKObject: Pointer); virtual;
|
||||
|
||||
|
@ -614,60 +614,6 @@ end;
|
||||
|
||||
{$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;
|
||||
------------------------------------------------------------------------------}
|
||||
@ -935,20 +881,11 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
|
||||
|
||||
procedure SendCachedLCLResizeRequests;
|
||||
var
|
||||
Widget, ParentFixed, ParentWidget: PGtkWidget;
|
||||
LCLControl: TControl;
|
||||
Widget: PGtkWidget;
|
||||
LCLControl: TWinControl;
|
||||
IsTopLevelWidget: boolean;
|
||||
TopologicalList: TFPList; // list of PGtkWidget;
|
||||
i, LCLWidth, LCLHeight: integer;
|
||||
WinWidgetInfo: PWinWidgetInfo;
|
||||
|
||||
procedure WriteBigWarning;
|
||||
begin
|
||||
DebugLn('WARNING: resizing BIG ',
|
||||
' Control=',LCLControl.Name,':',LCLControl.ClassName,
|
||||
' NewSize=',dbgs(LCLWidth),',',dbgs(LCLHeight));
|
||||
//RaiseException('');
|
||||
end;
|
||||
i: integer;
|
||||
|
||||
procedure RaiseWidgetWithoutControl;
|
||||
begin
|
||||
@ -956,16 +893,6 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
|
||||
+DbgS(Widget)+' without LCL control');
|
||||
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
|
||||
if FWidgetsWithResizeRequest.Count=0 then exit;
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
@ -977,12 +904,12 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
|
||||
Widget:=TopologicalList[i];
|
||||
|
||||
// resize widget
|
||||
LCLControl:=TControl(GetLCLObject(Widget));
|
||||
LCLControl:=TWinControl(GetLCLObject(Widget));
|
||||
if (LCLControl=nil) or (not (LCLControl is TControl)) then begin
|
||||
RaiseWidgetWithoutControl;
|
||||
end;
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
if AnsiCompareText(LCLControl.ClassName,'TScrollBar')=0 then
|
||||
if CompareText(LCLControl.ClassName,'TScrollBar')=0 then
|
||||
DebugLn('SendCachedLCLMessages ',LCLControl.Name,':',LCLControl.ClassName,
|
||||
' ',dbgs(LCLControl.Left)+','+dbgs(LCLControl.Top)+','+dbgs(LCLControl.Width)+'x'+dbgs(LCLControl.Height));
|
||||
{$ENDIF}
|
||||
@ -991,38 +918,7 @@ procedure TGtkWidgetSet.SendCachedLCLMessages;
|
||||
and (LCLControl.Parent = nil);
|
||||
|
||||
if not IsTopLevelWidget then 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;
|
||||
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;
|
||||
SetWidgetSizeAndPosition(LCLControl);
|
||||
end
|
||||
else begin
|
||||
// resize form
|
||||
@ -1065,257 +961,6 @@ end;
|
||||
Some Gtk messages are not sent directly to the LCL. Send them now.
|
||||
------------------------------------------------------------------------------}
|
||||
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
|
||||
SendCachedGtkResizeNotifications;
|
||||
end;
|
||||
@ -1502,71 +1147,6 @@ begin
|
||||
{$ENDIF}
|
||||
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(
|
||||
AWinControl: TWinControl);
|
||||
@ -1831,7 +1411,6 @@ begin
|
||||
end;
|
||||
|
||||
// proceed until all messages are handled
|
||||
|
||||
until (not PendingGtkMessagesExists) or Application.Terminated;
|
||||
end;
|
||||
|
||||
@ -3584,16 +3163,35 @@ 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])));
|
||||
|
||||
if Sender is TWinControl then begin
|
||||
if TWinControl(Sender).HandleAllocated then begin
|
||||
Widget := pgtkWidget(TWinControl(Sender).Handle);
|
||||
SetResizeRequest(Widget);
|
||||
LCLControl:=TWinControl(Sender);
|
||||
if LCLControl.HandleAllocated then begin
|
||||
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 AnsiCompareText(Sender.ClassName,'TScrollBar')=0 then
|
||||
//if CompareText(Sender.ClassName,'TScrollBar')=0 then
|
||||
// DebugLn(' FFF ResizeChild ',Sender.ClassName,' ',Left,',',Top,',',Width,',',Height);
|
||||
end;
|
||||
end;
|
||||
@ -5909,11 +5507,13 @@ procedure TGtkWidgetSet.ShowHide(Sender : TObject);
|
||||
end;
|
||||
|
||||
var FormIconGdiObject: PGDIObject;
|
||||
SenderWidget, ParentFixed, ParentWidget: PGTKWidget;
|
||||
SenderWidget: PGTKWidget;
|
||||
LCLControl: TWinControl;
|
||||
Decor, Func : Longint;
|
||||
AWindow: PGdkWindow;
|
||||
ACustomForm: TCustomForm;
|
||||
ParentFixed: PGTKWidget;
|
||||
ParentWidget: PGTKWidget;
|
||||
{$IFDEF Gtk1}
|
||||
AWindowPrivate: PGdkWindowPrivate;
|
||||
{$ENDIF}
|
||||
@ -5941,9 +5541,6 @@ begin
|
||||
ShareWindowAccelGroups(SenderWidget);
|
||||
end;
|
||||
|
||||
if gtk_widget_visible(SenderWidget) then
|
||||
exit;
|
||||
|
||||
// before making the widget visible, set the position and size
|
||||
if FWidgetsWithResizeRequest.Contains(SenderWidget) then begin
|
||||
if (ACustomForm<>nil) and (ACustomForm.Parent=nil) then begin
|
||||
@ -5958,6 +5555,9 @@ begin
|
||||
SetWindowSizeAndPosition(PgtkWindow(SenderWidget),LCLControl);
|
||||
end else if (LCLControl.Parent<>nil) then begin
|
||||
// resize widget
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
DebugLn(['TGtkWidgetSet.ShowHide ',DbgSName(LCLControl)]);
|
||||
{$ENDIF}
|
||||
RealizeWidgetSize(SenderWidget,LCLControl.Width,LCLControl.Height);
|
||||
// move widget on the fixed widget of parent control
|
||||
ParentWidget:=pgtkWidget(LCLControl.Parent.Handle);
|
||||
@ -5994,6 +5594,9 @@ begin
|
||||
ReleaseMouseCapture;
|
||||
end;
|
||||
|
||||
if gtk_widget_visible(SenderWidget) then
|
||||
exit;
|
||||
|
||||
gtk_widget_show(SenderWidget);
|
||||
|
||||
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
|
||||
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 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
|
||||
sent.
|
||||
sent in: TGtkWidgetSet.SendCachedLCLMessages.
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TGtkWidgetSet.SetResizeRequest(Widget: PGtkWidget);
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
@ -7169,15 +6772,11 @@ var
|
||||
begin
|
||||
{$IFDEF VerboseSizeMsg}
|
||||
LCLControl:=TWinControl(GetLCLObject(Widget));
|
||||
DbgOut('PPP TGtkWidgetSet.SetResizeRequest Widget=',DbgS(Widget));
|
||||
if (LCLControl<>nil) then begin
|
||||
if LCLControl is TWinControl then
|
||||
DebugLn(' ',LCLControl.Name,':',LCLControl.ClassName)
|
||||
else
|
||||
DebugLn(' ERROR: ',LCLControl.ClassName);
|
||||
end else begin
|
||||
DebugLn(' ERROR: LCLControl=nil');
|
||||
end;
|
||||
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);
|
||||
@ -7194,6 +6793,11 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
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;
|
||||
|
||||
|
@ -6441,6 +6441,446 @@ begin
|
||||
//debugln('GetGTKDefaultSize PreferredWidth=',dbgs(PreferredWidth),' PreferredHeight=',dbgs(PreferredHeight));
|
||||
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);
|
||||
Begin
|
||||
DebugLn('*********************************************');
|
||||
@ -6932,7 +7372,7 @@ function IndexOfStyleWithName(const WName : String): integer;
|
||||
begin
|
||||
if Styles<>nil then begin
|
||||
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;
|
||||
Result:=-1;
|
||||
end;
|
||||
@ -6946,24 +7386,13 @@ end;
|
||||
'default', checkbox', etc. This should only be called on theme change or on
|
||||
application terminate.
|
||||
------------------------------------------------------------------------------}
|
||||
Type
|
||||
PStyleObject = ^TStyleObject;
|
||||
TStyleObject = Record
|
||||
Style : PGTKStyle;
|
||||
Widget : PGTKWidget;
|
||||
end;
|
||||
|
||||
var
|
||||
StandardStyles: array[TLazGtkStyle] of PStyleObject;
|
||||
|
||||
Function NewStyleObject : PStyleObject;
|
||||
function NewStyleObject : PStyleObject;
|
||||
begin
|
||||
New(Result);
|
||||
Result^.Widget := nil;
|
||||
Result^.Style := nil;
|
||||
FillChar(Result^,SizeOf(TStyleObject),0);
|
||||
end;
|
||||
|
||||
Procedure FreeStyleObject(var StyleObject : PStyleObject);
|
||||
procedure FreeStyleObject(var StyleObject : PStyleObject);
|
||||
// internal function to dispose a styleobject
|
||||
// it does *not* remove it from the style lists
|
||||
begin
|
||||
@ -7066,6 +7495,8 @@ end;
|
||||
of Styles.
|
||||
------------------------------------------------------------------------------}
|
||||
function GetStyleWithName(const WName: String) : PGTKStyle;
|
||||
var
|
||||
StyleObject : PStyleObject;
|
||||
|
||||
function CreateStyleNotebook: PGTKWidget;
|
||||
var
|
||||
@ -7091,11 +7522,29 @@ function GetStyleWithName(const WName: String) : PGTKStyle;
|
||||
NoteBookTabLabel,NoteBookTabMenuLabel);
|
||||
gtk_widget_set_usize(Result,200,200);
|
||||
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
|
||||
Tp : Pointer;
|
||||
l : Longint;
|
||||
StyleObject : PStyleObject;
|
||||
NoName: PGChar;
|
||||
lgs: TLazGtkStyle;
|
||||
WidgetName: String;
|
||||
@ -7111,11 +7560,11 @@ begin
|
||||
exit;
|
||||
{$ENDIF}
|
||||
|
||||
If (WName='') then exit;
|
||||
if (WName='') then exit;
|
||||
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]);
|
||||
Result := StyleObject^.Style;
|
||||
|
||||
@ -7237,17 +7686,24 @@ begin
|
||||
else
|
||||
If CompareText(WName,LazGtkStyleNames[lgsHScale])=0 then begin
|
||||
lgs:=lgsHScale;
|
||||
AddToStyleWindow:=true;
|
||||
TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0));
|
||||
StyleObject^.Widget := gtk_hscale_new (PGTKADJUSTMENT (TP));
|
||||
end
|
||||
else
|
||||
If CompareText(WName,LazGtkStyleNames[lgsVScale])=0 then begin
|
||||
lgs:=lgsVScale;
|
||||
AddToStyleWindow:=true;
|
||||
TP := PGtkWidget( gtk_adjustment_new (0, 0, 100, 1, 10, 0));
|
||||
StyleObject^.Widget := gtk_vscale_new (PGTKADJUSTMENT (TP));
|
||||
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
|
||||
If CompareText(WName,LazGtkStyleNames[lgsGTK_Default])=0 then begin
|
||||
lgs:=lgsGTK_Default;
|
||||
@ -7277,10 +7733,9 @@ begin
|
||||
StyleWindowWidget:=GetStyleWidget(lgsWindow);
|
||||
WindowFixedWidget:=PGTKWidget(
|
||||
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_fixed_put(PGtkFixed(WindowFixedWidget),StyleObject^.Widget,0,0);
|
||||
gtk_widget_set_usize(StyleObject^.Widget,200,200);
|
||||
gtk_fixed_put(PGtkFixed(WindowFixedWidget),StyleObject^.Widget,10,10);
|
||||
end;
|
||||
|
||||
WidgetName:='LazStyle'+WName;
|
||||
@ -7290,19 +7745,24 @@ begin
|
||||
StyleObject^.Style:=gtk_widget_get_style(StyleObject^.Widget);
|
||||
// ToDo: find out, why sometimes the style is not initialized.
|
||||
// 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
|
||||
//DebugLn('GetStyleWithName ',WName);
|
||||
if not GtkWidgetIsA(StyleObject^.Widget,GTK_WINDOW_GET_TYPE) then begin
|
||||
gtk_widget_realize(StyleObject^.Widget);
|
||||
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;
|
||||
|
||||
|
||||
// increase refcount of style
|
||||
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);
|
||||
|
||||
// if successful add to style objects list
|
||||
@ -7312,7 +7772,7 @@ begin
|
||||
StandardStyles[lgs]:=StyleObject;
|
||||
Result:=StyleObject^.Style;
|
||||
If (StyleObject^.Widget <> nil)
|
||||
and (AnsiCompareText(WName,LazGtkStyleNames[lgsWindow])=0) then
|
||||
and (CompareText(WName,LazGtkStyleNames[lgsWindow])=0) then
|
||||
UpdateSysColorMap(StyleObject^.Widget);
|
||||
|
||||
// ToDo: create all gc of the style
|
||||
@ -7878,6 +8338,38 @@ begin
|
||||
RealizeGtkStyleColor(Style,Result);
|
||||
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);
|
||||
var
|
||||
style : PGTKStyle;
|
||||
|
@ -704,6 +704,11 @@ procedure SaveClientSizeNotification(FixWidget: PGtkWidget);
|
||||
function CreateTopologicalSortedWidgets(HashArray: TDynHashArray): TFPList;
|
||||
procedure GetGTKDefaultWidgetSize(AWinControl: TWinControl;
|
||||
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
|
||||
procedure ReportNotObsolete(const Texts: String);
|
||||
@ -723,6 +728,18 @@ function GdkAtomToStr(const Atom: TGdkAtom): string;
|
||||
function CreateFormContents(AForm: TCustomForm; var FormWidget: Pointer): Pointer;
|
||||
|
||||
// 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 IndexOfStyleWithName(const WName: String): integer;
|
||||
procedure ReleaseAllStyles;
|
||||
@ -732,6 +749,9 @@ function GetStyle(aStyle: TLazGtkStyle): PGTKStyle;
|
||||
function GetStyleWithName(const WName: String): PGTKStyle;
|
||||
function GetStyleWidget(aStyle: TLazGtkStyle): PGTKWidget;
|
||||
function GetStyleWidgetWithName(const WName: String): PGTKWidget;
|
||||
{$IFDEF Gtk2}
|
||||
function GetStyleGroupboxFrameBorders: TRect;
|
||||
{$ENDIF}
|
||||
procedure StyleFillRectangle(drawable: PGDKDrawable; GC: PGDKGC;
|
||||
Color: TColorRef; x, y, width, height: gint);
|
||||
function StyleForegroundColor(Color: TColorRef; DefaultColor: PGDKColor): PGDKColor;
|
||||
|
@ -6407,11 +6407,33 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
function TGtkWidgetSet.GetWindowRelativePosition(Handle : hwnd;
|
||||
var Left, Top: integer): boolean;
|
||||
var
|
||||
aWidget: PGtkWidget;
|
||||
{$IFDEF Gtk2}
|
||||
GdkWindow: PGdkWindow;
|
||||
GtkLeft, GtkTop: gint;
|
||||
{$ENDIF}
|
||||
begin
|
||||
if GtkWidgetIsA(PGtkWidget(Handle),GTK_TYPE_WIDGET) then begin
|
||||
aWidget:=PGtkWidget(Handle);
|
||||
if GtkWidgetIsA(aWidget,GTK_TYPE_WIDGET) then begin
|
||||
Result:=true;
|
||||
Left:=PGtkWidget(Handle)^.Allocation.X;
|
||||
Top:=PGtkWidget(Handle)^.Allocation.Y;
|
||||
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}
|
||||
end else
|
||||
Result:=false;
|
||||
end;
|
||||
|
@ -60,10 +60,8 @@ type
|
||||
procedure HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject); override;
|
||||
function LoadStockPixmap(StockID: longint) : HBitmap; 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;
|
||||
MultiSelect, ExtendedSelect: boolean); override;
|
||||
//function SetTopIndex(Sender: TObject; NewTopIndex: integer): integer; override;
|
||||
|
||||
procedure InitializeFileDialog(FileDialog: TFileDialog;
|
||||
var SelWidget: PGtkWidget; Title: PChar); override;
|
||||
|
@ -81,6 +81,9 @@ type
|
||||
private
|
||||
protected
|
||||
public
|
||||
class function GetDefaultClientRect(const AWinControl: TWinControl;
|
||||
const aLeft, aTop, aWidth, aHeight: integer; var aClientRect: TRect
|
||||
): boolean; override;
|
||||
end;
|
||||
|
||||
{ TGtk2WSGroupBox }
|
||||
@ -1259,6 +1262,28 @@ begin
|
||||
inherited DestroyHandle(AWinControl);
|
||||
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
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
@ -1268,7 +1293,7 @@ initialization
|
||||
// which actually implement something
|
||||
////////////////////////////////////////////////////
|
||||
// RegisterWSComponent(TScrollBar, TGtk2WSScrollBar);
|
||||
// RegisterWSComponent(TCustomGroupBox, TGtk2WSCustomGroupBox);
|
||||
RegisterWSComponent(TCustomGroupBox, TGtk2WSCustomGroupBox);
|
||||
// RegisterWSComponent(TGroupBox, TGtk2WSGroupBox);
|
||||
RegisterWSComponent(TCustomComboBox, TGtk2WSCustomComboBox);
|
||||
// RegisterWSComponent(TComboBox, TGtk2WSComboBox);
|
||||
|
@ -86,6 +86,7 @@ type
|
||||
class function GetClientBounds(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 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 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 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;
|
||||
var Left, Top, Width, Height: integer; var SuppressMove: boolean); virtual;
|
||||
|
||||
class procedure ConstraintsChange(const AWinControl: TWinControl); virtual;
|
||||
class function CreateHandle(const AWinControl: TWinControl;
|
||||
const AParams: TCreateParams): TLCLIntfHandle; virtual;
|
||||
@ -202,6 +204,13 @@ class procedure TWSWinControl.GetPreferredSize(const AWinControl: TWinControl;
|
||||
begin
|
||||
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);
|
||||
begin
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user