View Issue Details

IDProjectCategoryView StatusLast Update
0035861LazarusWidgetsetpublic2019-08-09 21:19
ReporterChris RordenAssigned ToJuha Manninen 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformSystem76 Oryx ProOSUbuntuOS Version18.04
Product Version2.0.3 (SVN)Product Build61601 
Target VersionFixed in Version 
Summary0035861: GTK2: TTrackBar does not AutoSize for hi-dpi
DescriptionThe combination of the "AutoSize" property and the "AnchorEditor" are fantastic features of Lazarus. Most of the widgets scale correctly based on the screen's DPI. However, with the GTK2 widgetset the TTrackBars are not scaled. This means that they tend to look tiny relative to other components when displayed on a high-dpi display.
Steps To ReproducePut a TTrackBar on a form. Build on High-DPI Linux system: note the Trackbar looks very small.
TagsNo tags attached.
Fixed in Revisionr61676
LazTarget-
WidgetsetGTK 2
Attached Files
  • autoTrack.png (24,556 bytes)
    autoTrack.png (24,556 bytes)
  • AutoSizeTrackBar.zip (109,855 bytes)
  • ttrackbar-hidpi-etc.patch (3,605 bytes)
    --- lcl/include/trackbar.inc
    +++ lcl/include/trackbar.inc
    @@ -93,6 +93,20 @@
       ApplyChanges;
     end;
     
    +procedure TCustomTrackBar.ShouldAutoAdjust(var AWidth, AHeight: Boolean);
    +begin
    +  if Orientation = trHorizontal then
    +    begin
    +      AWidth := True;
    +      AHeight := not AutoSize;
    +    end
    +  else
    +    begin
    +      AWidth := not AutoSize;
    +      AHeight := True;
    +    end
    +end;
    +
     {------------------------------------------------------------------------------
       Method: TCustomTrackBar.SetTick
       Params: Value : new tick
    --- lcl/interfaces/gtk2/gtk2wscomctrls.pp
    +++ lcl/interfaces/gtk2/gtk2wscomctrls.pp
    @@ -263,7 +263,6 @@
         class procedure ApplyChanges(const ATrackBar: TCustomTrackBar); override;
         class function  GetPosition(const ATrackBar: TCustomTrackBar): integer; override;
         class procedure SetPosition(const ATrackBar: TCustomTrackBar; const NewPosition: integer); override;
    -    class procedure SetOrientation(const ATrackBar: TCustomTrackBar; const {%H-}AOrientation: TTrackBarOrientation); override;
         class procedure GetPreferredSize(const {%H-}AWinControl: TWinControl;
                             var {%H-}PreferredWidth, PreferredHeight: integer;
                             {%H-}WithThemeSpace: Boolean); override;
    @@ -428,23 +427,6 @@
       Dec(WidgetInfo^.ChangeLock);
     end;
     
    -class procedure TGtk2WSTrackBar.SetOrientation(
    -  const ATrackBar: TCustomTrackBar; const AOrientation: TTrackBarOrientation);
    -var
    -  B: Boolean;
    -begin
    -  if not WSCheckHandleAllocated(ATrackBar, 'SetOrientation') then
    -    Exit;
    -  B := ATrackBar.Visible;
    -  if B then
    -    ATrackBar.Hide;
    -  try
    -    RecreateWnd(ATrackBar);
    -  finally
    -    if B then
    -      ATrackBar.Show;
    -  end;
    -end;
     
     class procedure TGtk2WSTrackBar.GetPreferredSize(
       const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer;
    @@ -453,20 +435,25 @@
       TrackBarWidget: PGtkWidget;
       Requisition: TGtkRequisition;
     begin
    -  if TCustomTrackBar(AWinControl).Orientation = trHorizontal then
    -    TrackBarWidget := GetStyleWidget(lgsHScale)
    -  else
    -    TrackBarWidget := GetStyleWidget(lgsVScale);
    +  TrackBarWidget := {%H-}PGtkWidget(AWinControl.Handle);
    +  // if vertical, measure width without ticks
    +  if TCustomTrackBar(AWinControl).Orientation = trVertical then
    +    gtk_scale_set_draw_value(PGtkScale(TrackBarWidget), False);
       // set size to default
    -  gtk_scale_set_draw_value(PGtkScale(TrackBarWidget),
    -                           TCustomTrackBar(AWinControl).TickStyle <> tsNone);
       gtk_widget_set_size_request(TrackBarWidget, -1, -1);
       // ask default size
       gtk_widget_size_request(TrackBarWidget, @Requisition);
       if TCustomTrackBar(AWinControl).Orientation = trHorizontal then
    -    PreferredHeight := Requisition.height
    +    PreferredHeight := Requisition.Height
       else
    -    PreferredWidth := Requisition.width;
    +    begin
    +      // gtk_widget_size_request() always returns size of a HScale,
    +      // so we use the height for the width
    +      PreferredWidth := Requisition.Height;
    +      // restore TickStyle
    +      gtk_scale_set_draw_value(PGtkScale(TrackBarWidget),
    +                               TCustomTrackBar(AWinControl).TickStyle <> tsNone);
    +    end;
     end;
     
     { TGtk2WSProgressBar }
    --- lcl/comctrls.pp
    +++ lcl/comctrls.pp
    @@ -2717,6 +2717,7 @@
         class function GetControlClassDefaultSize: TSize; override;
         procedure InitializeWnd; override;
         procedure Loaded; override;
    +    procedure ShouldAutoAdjust(var AWidth, AHeight: Boolean); override;
       public
         constructor Create(AOwner: TComponent); override;
         procedure SetTick(Value: Integer);
    
    

Relationships

related to 0034418 resolvedJuha Manninen GTK2 autosize incorrect for TTrackBar if TickStyle := tsNone 

Activities

Chris Rorden

2019-07-18 22:06

reporter  

autoTrack.png (24,556 bytes)
autoTrack.png (24,556 bytes)
AutoSizeTrackBar.zip (109,855 bytes)

Chris Rorden

2019-08-01 18:05

reporter   ~0117535

Joeny Ang sent me the attached patch. I have tested it on svn 61598 and it appears to resolve this issue. I would be grateful is one of the developers would apply this patch to close this issue.

I thought you were referring to the small thumb and track. (but... they are
really small on HiDPI, aren't they?) hehe my bad.

Please try the attached patch (vs trunk). The following were changed/fixed:
1. added TTrackbar.ShouldAutoAdjust() function to scale width of horiz
trackbars; and scale height of vert trackbars
2. removed TGtk2WSTrackbar.SetOrientation(). Not sure why the function
is hiding the control before calling RecreateWnd(). This function causes the
Visible property to be set to false when you alter the Orientation property
at design time. The fallback TWSTrackbar.SetOrientation() will be used instead.
3. modified TGtk2WSTrackBar.GetPreferredSize() to get the right size
for HiDPI.

Problem remains for vertical trackbars. Since the gtk_get_size function does not
work for vertical trackbars, we're using horiz trackbar height for its width. And
for large ranges, the position value will not fit the width when displayed.

Thanks,
Joeny

ttrackbar-hidpi-etc.patch (3,605 bytes)
--- lcl/include/trackbar.inc
+++ lcl/include/trackbar.inc
@@ -93,6 +93,20 @@
   ApplyChanges;
 end;
 
+procedure TCustomTrackBar.ShouldAutoAdjust(var AWidth, AHeight: Boolean);
+begin
+  if Orientation = trHorizontal then
+    begin
+      AWidth := True;
+      AHeight := not AutoSize;
+    end
+  else
+    begin
+      AWidth := not AutoSize;
+      AHeight := True;
+    end
+end;
+
 {------------------------------------------------------------------------------
   Method: TCustomTrackBar.SetTick
   Params: Value : new tick
--- lcl/interfaces/gtk2/gtk2wscomctrls.pp
+++ lcl/interfaces/gtk2/gtk2wscomctrls.pp
@@ -263,7 +263,6 @@
     class procedure ApplyChanges(const ATrackBar: TCustomTrackBar); override;
     class function  GetPosition(const ATrackBar: TCustomTrackBar): integer; override;
     class procedure SetPosition(const ATrackBar: TCustomTrackBar; const NewPosition: integer); override;
-    class procedure SetOrientation(const ATrackBar: TCustomTrackBar; const {%H-}AOrientation: TTrackBarOrientation); override;
     class procedure GetPreferredSize(const {%H-}AWinControl: TWinControl;
                         var {%H-}PreferredWidth, PreferredHeight: integer;
                         {%H-}WithThemeSpace: Boolean); override;
@@ -428,23 +427,6 @@
   Dec(WidgetInfo^.ChangeLock);
 end;
 
-class procedure TGtk2WSTrackBar.SetOrientation(
-  const ATrackBar: TCustomTrackBar; const AOrientation: TTrackBarOrientation);
-var
-  B: Boolean;
-begin
-  if not WSCheckHandleAllocated(ATrackBar, 'SetOrientation') then
-    Exit;
-  B := ATrackBar.Visible;
-  if B then
-    ATrackBar.Hide;
-  try
-    RecreateWnd(ATrackBar);
-  finally
-    if B then
-      ATrackBar.Show;
-  end;
-end;
 
 class procedure TGtk2WSTrackBar.GetPreferredSize(
   const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer;
@@ -453,20 +435,25 @@
   TrackBarWidget: PGtkWidget;
   Requisition: TGtkRequisition;
 begin
-  if TCustomTrackBar(AWinControl).Orientation = trHorizontal then
-    TrackBarWidget := GetStyleWidget(lgsHScale)
-  else
-    TrackBarWidget := GetStyleWidget(lgsVScale);
+  TrackBarWidget := {%H-}PGtkWidget(AWinControl.Handle);
+  // if vertical, measure width without ticks
+  if TCustomTrackBar(AWinControl).Orientation = trVertical then
+    gtk_scale_set_draw_value(PGtkScale(TrackBarWidget), False);
   // set size to default
-  gtk_scale_set_draw_value(PGtkScale(TrackBarWidget),
-                           TCustomTrackBar(AWinControl).TickStyle <> tsNone);
   gtk_widget_set_size_request(TrackBarWidget, -1, -1);
   // ask default size
   gtk_widget_size_request(TrackBarWidget, @Requisition);
   if TCustomTrackBar(AWinControl).Orientation = trHorizontal then
-    PreferredHeight := Requisition.height
+    PreferredHeight := Requisition.Height
   else
-    PreferredWidth := Requisition.width;
+    begin
+      // gtk_widget_size_request() always returns size of a HScale,
+      // so we use the height for the width
+      PreferredWidth := Requisition.Height;
+      // restore TickStyle
+      gtk_scale_set_draw_value(PGtkScale(TrackBarWidget),
+                               TCustomTrackBar(AWinControl).TickStyle <> tsNone);
+    end;
 end;
 
 { TGtk2WSProgressBar }
--- lcl/comctrls.pp
+++ lcl/comctrls.pp
@@ -2717,6 +2717,7 @@
     class function GetControlClassDefaultSize: TSize; override;
     procedure InitializeWnd; override;
     procedure Loaded; override;
+    procedure ShouldAutoAdjust(var AWidth, AHeight: Boolean); override;
   public
     constructor Create(AOwner: TComponent); override;
     procedure SetTick(Value: Integer);

Juha Manninen

2019-08-01 21:38

developer   ~0117537

Where is ShouldAutoAdjust used?
The patch must be joined with fixing 0034418. See notes there.

Joeny Ang

2019-08-02 04:47

reporter   ~0117540

ShouldAutoAdjust() is called by AutoAdjustLayout() (part of LCL scaling). The 2 parameters determines whether the width and/or height should be scaled or not. For a TPanel, AutoSize is always false, thus the 2 parameters will be true, thus the width and height will be scaled. For TTrackBar with AutoSize=True, it will depend on the Orientation; for horizontal, only the width will be scaled; and height for vertical. For AutoSize=False, both will be scaled.

Juha Manninen

2019-08-09 21:19

developer   ~0117616

I applied the patch and reverted the AutoSize=True thing.
Please check.
Thanks for the patch and sorry for the delay.

Issue History

Date Modified Username Field Change
2019-07-18 22:06 Chris Rorden New Issue
2019-07-18 22:06 Chris Rorden File Added: autoTrack.png
2019-07-18 22:06 Chris Rorden File Added: AutoSizeTrackBar.zip
2019-08-01 18:05 Chris Rorden File Added: ttrackbar-hidpi-etc.patch
2019-08-01 18:05 Chris Rorden Note Added: 0117535
2019-08-01 21:26 Juha Manninen Relationship added related to 0034418
2019-08-01 21:38 Juha Manninen Note Added: 0117537
2019-08-01 21:39 Juha Manninen Assigned To => Juha Manninen
2019-08-01 21:39 Juha Manninen Status new => assigned
2019-08-02 04:47 Joeny Ang Note Added: 0117540
2019-08-09 21:19 Juha Manninen Status assigned => resolved
2019-08-09 21:19 Juha Manninen Resolution open => fixed
2019-08-09 21:19 Juha Manninen Fixed in Revision => r61676
2019-08-09 21:19 Juha Manninen LazTarget => -
2019-08-09 21:19 Juha Manninen Widgetset GTK 2 => GTK 2
2019-08-09 21:19 Juha Manninen Note Added: 0117616