mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 14:09:31 +02:00
Gtk3: finally fixed gtk philosophy how content size and adjustments should be calculate so gtk is happy, now TCustomControl have correct scrollbars calculations.
This commit is contained in:
parent
315ee83f9e
commit
66a50ddd0e
@ -532,9 +532,13 @@ type
|
|||||||
class function RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
class function RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
||||||
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl; static;
|
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl; static;
|
||||||
public
|
public
|
||||||
|
LCLVAdj: PGtkAdjustment; // used to keep LCL values
|
||||||
|
LCLHAdj: PGtkAdjustment; // used to keep LCL values
|
||||||
|
procedure DestroyWidget; override;
|
||||||
{result = true if scrollbar is pressed by mouse, AMouseOver if mouse is over scrollbar pressed or not.}
|
{result = true if scrollbar is pressed by mouse, AMouseOver if mouse is over scrollbar pressed or not.}
|
||||||
class function CheckIfScrollbarPressed(scrollbar: PGtkWidget; out AMouseOver:
|
class function CheckIfScrollbarPressed(scrollbar: PGtkWidget; out AMouseOver:
|
||||||
boolean; const ACheckModifier: TGdkModifierTypeIdx): boolean;
|
boolean; const ACheckModifier: TGdkModifierTypeIdx): boolean;
|
||||||
|
procedure InitializeWidget; override;
|
||||||
procedure SetScrollBarsSignalHandlers(const AIsHorizontalScrollBar: boolean);
|
procedure SetScrollBarsSignalHandlers(const AIsHorizontalScrollBar: boolean);
|
||||||
function getClientBounds: TRect; override;
|
function getClientBounds: TRect; override;
|
||||||
function getViewport: PGtkViewport; virtual;
|
function getViewport: PGtkViewport; virtual;
|
||||||
@ -838,6 +842,8 @@ type
|
|||||||
|
|
||||||
TGtk3CustomControl = class(TGtk3ScrollableWin)
|
TGtk3CustomControl = class(TGtk3ScrollableWin)
|
||||||
strict private
|
strict private
|
||||||
|
class procedure CustomControlLayoutSizeAllocate(AWidget: PGtkWidget;
|
||||||
|
AGdkRect: PGdkRectangle; Data: gpointer); cdecl; static; {very important, see note inside method}
|
||||||
class procedure RangeValueChanged(range: PGtkRange; data: gpointer); cdecl; static;
|
class procedure RangeValueChanged(range: PGtkRange; data: gpointer); cdecl; static;
|
||||||
protected
|
protected
|
||||||
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
function CreateWidget(const {%H-}Params: TCreateParams):PGtkWidget; override;
|
||||||
@ -5935,6 +5941,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk3ScrollableWin.InitializeWidget;
|
||||||
|
begin
|
||||||
|
LCLVAdj := nil;
|
||||||
|
LCLHAdj := nil;
|
||||||
|
inherited InitializeWidget;
|
||||||
|
end;
|
||||||
|
|
||||||
class function TGtk3ScrollableWin.RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
class function TGtk3ScrollableWin.RangeChangeValue(ARange: PGtkRange; AScrollType: TGtkScrollType;
|
||||||
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl;
|
AValue: gdouble; AData: TGtk3Widget): gboolean; cdecl;
|
||||||
var
|
var
|
||||||
@ -5996,6 +6009,17 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk3ScrollableWin.DestroyWidget;
|
||||||
|
begin
|
||||||
|
if Assigned(LCLHAdj) then
|
||||||
|
LCLHAdj^.unref;
|
||||||
|
if Assigned(LCLVAdj) then
|
||||||
|
LCLVAdj^.unref;
|
||||||
|
LCLHAdj := nil;
|
||||||
|
LCLVAdj := nil;
|
||||||
|
inherited DestroyWidget;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TGtk3ScrollableWin.SetScrollBarsSignalHandlers(const
|
procedure TGtk3ScrollableWin.SetScrollBarsSignalHandlers(const
|
||||||
AIsHorizontalScrollBar:boolean);
|
AIsHorizontalScrollBar:boolean);
|
||||||
begin
|
begin
|
||||||
@ -8775,6 +8799,41 @@ end;
|
|||||||
|
|
||||||
{ TGtk3CustomControl }
|
{ TGtk3CustomControl }
|
||||||
|
|
||||||
|
class procedure TGtk3CustomControl.CustomControlLayoutSizeAllocate(AWidget: PGtkWidget;
|
||||||
|
AGdkRect: PGdkRectangle; Data: gpointer); cdecl;
|
||||||
|
var
|
||||||
|
hadj, vadj: PGtkAdjustment;
|
||||||
|
AScrollWin: PGtkScrolledWindow;
|
||||||
|
begin
|
||||||
|
{Note: Gtk expects that we set content size and then it calculates scrollbar values. LCL
|
||||||
|
is doing opposite, it sets scrollbar values eg via SetScrollInfo and then content should
|
||||||
|
be automatically calculated by widgetset. Gtk is crazy about it.
|
||||||
|
So, we are in charge here to help both. We save adjusted values
|
||||||
|
in setscrollinfo in LCLVAdj and LCLHAdj, so after GtkLayout sends size-allocate with accurate
|
||||||
|
content size we apply LCL values to adjustments and everybody is happy.
|
||||||
|
TODO: eg TTreeView editor, if scrollbar position is not at lower pos, showing
|
||||||
|
editor moves scrollbar to pos 0, if we apply LCL saved value here, then
|
||||||
|
editor won't show at all. Maybe moving editor and showing should take into
|
||||||
|
account scrollbar position and calculate x,y offset.}
|
||||||
|
|
||||||
|
hadj := PGtkScrollable(aWidget)^.get_hadjustment;
|
||||||
|
vadj := PGtkScrollable(aWidget)^.get_vadjustment;
|
||||||
|
|
||||||
|
PGtkLayout(aWidget)^.set_size(AGdkRect^.width, AGdkRect^.height);
|
||||||
|
{TODO: eg treeview editor, if scrollbar value > 0 then editor resets position to 0,
|
||||||
|
to fix this we must position editor at y pos - adjustment.value}
|
||||||
|
if Assigned(TGtk3CustomControl(Data).LCLVAdj) and Gtk3IsAdjustment(vadj) then
|
||||||
|
with TGtk3CustomControl(Data).LCLVAdj^ do
|
||||||
|
vadj^.configure(vadj^.value, lower, upper, step_increment, page_increment, page_size);
|
||||||
|
|
||||||
|
if Assigned(TGtk3CustomControl(Data).LCLHAdj) and Gtk3IsAdjustment(hadj) then
|
||||||
|
with TGtk3CustomControl(Data).LCLHAdj^ do
|
||||||
|
hadj^.configure(hadj^.value, lower, upper, step_increment, page_increment, page_size);
|
||||||
|
|
||||||
|
if TGtk3CustomControl(Data).LCLObject.ClientRectNeedsInterfaceUpdate then
|
||||||
|
TGtk3CustomControl(Data).LCLObject.DoAdjustClientRectChange;
|
||||||
|
end;
|
||||||
|
|
||||||
function TGtk3CustomControl.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
function TGtk3CustomControl.CreateWidget(const Params: TCreateParams): PGtkWidget;
|
||||||
begin
|
begin
|
||||||
FHasPaint := True;
|
FHasPaint := True;
|
||||||
@ -8802,6 +8861,13 @@ begin
|
|||||||
if not (csDesigning in LCLObject.ComponentState) then
|
if not (csDesigning in LCLObject.ComponentState) then
|
||||||
g_object_set(PGObject(FCentralWidget), 'resize-mode', [GTK_RESIZE_QUEUE, nil]);
|
g_object_set(PGObject(FCentralWidget), 'resize-mode', [GTK_RESIZE_QUEUE, nil]);
|
||||||
gtk_layout_set_size(PGtkLayout(FCentralWidget), 1, 1);
|
gtk_layout_set_size(PGtkLayout(FCentralWidget), 1, 1);
|
||||||
|
|
||||||
|
g_signal_connect_data(FCentralWidget,'size-allocate',TGCallback(@CustomControlLayoutSizeAllocate), Self, nil, G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
|
with PGtkScrolledWindow(Result)^.get_vadjustment^ do
|
||||||
|
LCLVAdj := gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
|
||||||
|
with PGtkScrolledWindow(Result)^.get_hadjustment^ do
|
||||||
|
LCLHAdj := gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGtk3CustomControl.EatArrowKeys(const AKey: Word): Boolean;
|
function TGtk3CustomControl.EatArrowKeys(const AKey: Word): Boolean;
|
||||||
@ -8987,6 +9053,10 @@ begin
|
|||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
Result := Rect(0, 0, PGtkLayout(GetContainerWidget)^.get_allocated_width, PGtkLayout(GetContainerWidget)^.get_allocated_height);
|
Result := Rect(0, 0, PGtkLayout(GetContainerWidget)^.get_allocated_width, PGtkLayout(GetContainerWidget)^.get_allocated_height);
|
||||||
|
//we are not ready, provide at least scrolledwindow size as clientrect for now.
|
||||||
|
//TODO: check scrollbar policy here, and if it's < GTK_POLICY_NEVER apply scrollbars sizes from GetSystemMetrics.
|
||||||
|
if (Result.Width <= 1) and (Result.Height <= 1) then
|
||||||
|
Result := Rect(0, 0, Widget^.get_allocated_width, Widget^.get_allocated_height);
|
||||||
end;
|
end;
|
||||||
//writeln('CustomControl clientRect=',dbgs(Result));
|
//writeln('CustomControl clientRect=',dbgs(Result));
|
||||||
exit;
|
exit;
|
||||||
|
@ -4040,6 +4040,22 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if SBStyle = SB_VERT then
|
||||||
|
begin
|
||||||
|
if (AControl is TGtk3CustomControl) and Assigned(TGtk3CustomControl(AControl).LCLVAdj) then
|
||||||
|
begin
|
||||||
|
with Adjustment^ do
|
||||||
|
TGtk3CustomControl(AControl).LCLVAdj^.configure(value, lower, upper, step_increment, page_increment, page_size);
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
if SBStyle = SB_HORZ then
|
||||||
|
begin
|
||||||
|
if (AControl is TGtk3CustomControl) and Assigned(TGtk3CustomControl(AControl).LCLHAdj) then
|
||||||
|
begin
|
||||||
|
with Adjustment^ do
|
||||||
|
TGtk3CustomControl(AControl).LCLHAdj^.configure(value, lower, upper, step_increment, page_increment, page_size);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
gtk_adjustment_changed(Adjustment);
|
gtk_adjustment_changed(Adjustment);
|
||||||
{$IFDEF GTK3DEBUGSCROLL}
|
{$IFDEF GTK3DEBUGSCROLL}
|
||||||
DebugLn(Format('Updated Adjustment: lower=%.2f, upper=%.2f, page_size=%.2f, value=%.2f, page_increment=%.2f InUpdate %s',
|
DebugLn(Format('Updated Adjustment: lower=%.2f, upper=%.2f, page_size=%.2f, value=%.2f, page_increment=%.2f InUpdate %s',
|
||||||
@ -4065,11 +4081,9 @@ var
|
|||||||
if AHorzPolicy <> POLICY[IsScrollbarVis] then
|
if AHorzPolicy <> POLICY[IsScrollbarVis] then
|
||||||
ScrollWin^.set_policy(POLICY[IsScrollbarVis], AVertPolicy);
|
ScrollWin^.set_policy(POLICY[IsScrollbarVis], AVertPolicy);
|
||||||
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
||||||
ScrollBar^.get_visible and
|
ScrollBar^.get_visible then
|
||||||
Gtk3IsGdkWindow(ScrollBar^.window) then
|
|
||||||
begin
|
begin
|
||||||
ScrollBar^.set_can_focus(False);
|
ScrollBar^.set_can_focus(False);
|
||||||
ScrollBar^.window^.raise_;
|
|
||||||
if (csDesigning in AControl.LCLObject.ComponentState) then
|
if (csDesigning in AControl.LCLObject.ComponentState) then
|
||||||
ScrollBar^.sensitive := false;
|
ScrollBar^.sensitive := false;
|
||||||
end;
|
end;
|
||||||
@ -4079,11 +4093,9 @@ var
|
|||||||
if AVertPolicy <> POLICY[IsScrollbarVis] then
|
if AVertPolicy <> POLICY[IsScrollbarVis] then
|
||||||
ScrollWin^.set_policy(AHorzPolicy, POLICY[IsScrollbarVis]);
|
ScrollWin^.set_policy(AHorzPolicy, POLICY[IsScrollbarVis]);
|
||||||
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
if Gtk3WidgetSet.OverlayScrolling and Gtk3IsWidget(Scrollbar) and
|
||||||
ScrollBar^.get_visible and
|
ScrollBar^.get_visible then
|
||||||
Gtk3IsGdkWindow(ScrollBar^.window) then
|
|
||||||
begin
|
begin
|
||||||
ScrollBar^.set_can_focus(False);
|
ScrollBar^.set_can_focus(False);
|
||||||
ScrollBar^.window^.raise_;
|
|
||||||
if (csDesigning in AControl.LCLObject.ComponentState) then
|
if (csDesigning in AControl.LCLObject.ComponentState) then
|
||||||
ScrollBar^.sensitive := false;
|
ScrollBar^.sensitive := false;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user