-
Notifications
You must be signed in to change notification settings - Fork 190
Description
Describe the bug
Working on a HiDPI monitor with an active zoom (of e.g. 125%) on Windows results in a Table's horizontal ScrollBar returning unscaled values for the following API calls:
- ScrollBar.getMinimum()
- ScrollBar.getMaximum()
- ScrollBar.getSelection()
While working with a zoom of 100% (no scaling), these values seem to correspond to pixels of the table's total content width (not just the visible viewport area). This results in ScrollBar.setIncrement() and ScrollBar.setPageIncrement() to become unpredictable.
To Reproduce
See below snipplet for reproduction. The snipplet simply creates a Shell with a Table having one column. It enforces the Shell to have a width of 640 pixels. The Table's width is forced to be 640 pixels through the FillLayout of the Shell. However, the Table has one single Column with a width of 1024 pixels. When you start scrolling, the very first console output you will see looks like this:
public static void main(final String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
// initialize to a specific width in order to set
// the column width so that horizontal scroll bar
// is definitely there.
shell.setSize(640, 480);
final Table table = new Table(shell, SWT.H_SCROLL);
table.setHeaderVisible(true);
final TableColumn column = new TableColumn(table, SWT.NONE);
column.setText("Column");
column.setWidth(1024);
// attach a listener which will output the dimensions upon scrolling
// to see what the total width is and what the ScrollBar values are
table.getHorizontalBar().addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
final ScrollBar bar = (ScrollBar) e.widget;
System.out.println(String.format("""
Table {
view-width: %d,
total-width: %d
}
ScrollBar {
minimum: %d,
maximum: %d,
thumb: %d,
selection: %d
}
""",
table.getSize().x, Arrays.stream(table.getColumns()).collect(Collectors.summingInt(TableColumn::getWidth)),
bar.getMinimum(), bar.getMaximum(), bar.getThumb(), bar.getSelection()));
}));
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}Zoom: 100%:
Table {
view-width: 640,
total-width: 1024
}
ScrollBar {
minimum: 0,
maximum: 1024,
thumb: 640,
selection: 0
}
So, the thumb size equals the table's view port size (which make sense) and the ScrollBar's selection range is from zero to maximum - minimum - thumb, which also makes sense because that's the area missing in the view port.
Zoom: 125%:
Table {
view-width: 622,
total-width: 1024
}
ScrollBar {
minimum: 0,
maximum: 1024,
thumb: 622,
selection: 0
}
The above is weird because it takes the scaled view port width (and again uses that as thumb size) but then it uses the unscaled column width as the maximum value thus making the range of ScrollBar's selection value a weird combination of scaled thumb and unscaled width.
Expected behavior
Either the ScrollBar's values (minimum, maximum, thumb, selection, increment, pageIncrement) are always scaled to match the zoom factor or they are not, but having a mix of scaled and unscaled values is unpredictable for usage.
Environment:
-
- All OS
-
- Windows
-
- Linux
-
- macOS
Tested on Windows 10 and 11, both have the same problem.
Version since
SWT v3.131.0, win32.x86_64
Workaround (or) Additional context
A workaround in that specific case would be to use Win32DPIUtils.pixelToPoint() methods but these are not public API.