Bug #10423
Scrollbar is clipped by frame after a virtual width assignment
100%
History
#1 Updated by Șerban Bursuc 11 months ago
- File 10377_resize_showcase_swing.flv added
- File 10377_resize_showcase_2.flv added
Testcase (from #10377-6):
define frame fr_main.
define frame fr_parent.
define frame fr1.
frame fr_parent:frame = frame fr_main:handle.
frame fr1:frame = frame fr_parent:handle.
define button btn.
enable btn with frame fr_main.
current-window:width-pixels = 900.
current-window:height-pixels = 500.
frame fr_main:scrollable = true.
frame fr_main:width-pixels = 900.
frame fr_main:height-pixels = 400.
frame fr_main:bgcolor = 7.
frame fr_parent:scrollable = true.
frame fr_parent:width-pixels = 900.
frame fr_parent:height-pixels = 300.
frame fr_parent:virtual-width-pixels = 900.
frame fr_parent:virtual-height-pixels = 600.
frame fr_parent:BGCOLOR = 5.
frame fr1:width-pixels = 300.
frame fr1:height-pixels = 250.
frame fr1:bgcolor = 6.
btn:row = 18.
on choose of btn do:
frame fr1:width-pixels = 600.
frame fr_parent:width-pixels = 600.
end.
on window-resized of current-window do:
/* frame fr_parent:virtual-width-pixels = current-window:width-pixels.*/
frame fr_main:width-pixels = current-window:width-pixels.
frame fr_parent:width-pixels = current-window:width-pixels + 20.
frame fr_main:virtual-width-pixels = current-window:width-pixels.
frame fr_parent:VIRTUAL-WIDTH-PIXELS = current-window:width-pixels.
end.
wait-for close of current-window.
Steps to reproduce are in the attached videos.
FWD behaves the same as OE as long as this assignment frame fr_parent:VIRTUAL-WIDTH-PIXELS = current-window:width-pixels. does not exist, if it does, OE doesn't clip the scrollbar anymore but FWD still does. Previously this had a workaround in FrameWidth.setWidthImpl where the maxWidth was the ancestorWidth and not the virtualWidth, but that is incorrect.
#3 Updated by Razvan-Nicolae Chichirau 8 months ago
As far as I can tell, the client correctly draws the vertical scrollbar. The problem is that it has an incorrect position which comes from the server.
Spent some time in ThinClient.pushWidgetAttr() and observed that when making the window bigger, the width value of the frame is sent correctly from the server and updated accordingly on the client. If I make the window smaller, this value seems to not change, so the problem may not be related to the actual drawing, but rather with the attributes which are sent to the client.
#4 Updated by Șerban Bursuc 8 months ago
Razvan-Nicolae Chichirau wrote:
As far as I can tell, the client correctly draws the vertical scrollbar. The problem is that it has an incorrect position which comes from the server.
Spent some time in
ThinClient.pushWidgetAttr()and observed that when making the window bigger, the width value of the frame is sent correctly from the server and updated accordingly on the client. If I make the window smaller, this value seems to not change, so the problem may not be related to the actual drawing, but rather with the attributes which are sent to the client.
That would explain why limiting the width assignment fixed the issue in the past. I think the +20 width is still being applied when resizing to the left.
Also, to be more clear about the previous fix for this that was in trunk, this was the patch:
=== modified file 'src/com/goldencode/p2j/ui/FrameWidget.java'
--- old/src/com/goldencode/p2j/ui/FrameWidget.java 2025-09-30 10:41:57 +0000
+++ new/src/com/goldencode/p2j/ui/FrameWidget.java 2025-11-19 08:44:10 +0000
@@ -2988,7 +2988,7 @@
final PaneEntity paneEntity = (PaneEntity) f;
final int virtualWidth = paneEntity.getVirtWidthPixels().intValue();
final int ancestorWidth = paneEntity.getWidthPixels().intValue();
- int maxWidth = virtualWidth - x;
+ int maxWidth = ancestorWidth - x;
if (virtualWidth > 0 && restrictedWidth > maxWidth)
{
If this width assignment frame fr_parent:VIRTUAL-WIDTH-PIXELS = current-window:width-pixels. takes place after the resize, that explains the bug entirely and why the workaround works.
#5 Updated by Razvan-Nicolae Chichirau 8 months ago
Discovered why the server pushes wrong values to the client. So when making the window bigger, the WIDTH-CHARS is not set because of this code in PaneEntity.setVirtWidthCharsWorker():
if (width < _getWidthChars().doubleValue())
{
// decreasing below regular size also affects regular size
setWidthChars(width);
}
When making the window smaller, WIDTH-CHARS is set due to the same code. This will end up calling FrameWidget.setWidthImpl() -> config.widthPixels = restrictedWidth;, where restrictedWidth has the newly updated value. After this assignment, SyncCoordinatesAspect.afterSetWidthPixels() kicks in:
public void afterSetWidthPixels(BaseConfig cfg)
{
if (isSuspended())
return;
WorkArea wa = contextData.get();
cfg.widthChars = wa.cc.columnFromPixels(cfg.widthPixels);
}
, where isSuspended() returns true, preventing the update of cfg.widthChars. This is important because widthChars (and not widthPixels) is used on the client when setting the frame dimensions.
I've tested by manually making isSuspended() return false while executing frame fr_parent:VIRTUAL-WIDTH-PIXELS = current-window:width-pixels. and the vertical scrollbar is set now in the right position.
#6 Updated by Șerban Bursuc 8 months ago
Well I didn't think of checking aspect assignments so great job, but adding unexpected behaviors in aspects seems like an awful idea exactly due to scenarios like this. We expect aspects to do a basic assignment and no more.
Once the bug is solved I would document this somewhere in the width assignment functions.
#7 Updated by Razvan-Nicolae Chichirau 8 months ago
The suspend part is intentional because BaseEntity.setSizePixels() is defined as such:
@NoSyncCoordinates
protected void setSizePixels(Integer value, SizeAttribute attr)
This triggers SyncCoordinatesAspect.suspend() on method entry and SyncCoordinatesAspect.resume() on method exit. I think this was implemented to avoid side-effects while modifying any dimension-related attributes.
#8 Updated by Razvan-Nicolae Chichirau 8 months ago
- % Done changed from 0 to 100
- Status changed from New to WIP
- Assignee set to Razvan-Nicolae Chichirau
- reviewer Hynek Cihlar added
Hynek: Please review 10423a/rev. 16278.
#9 Updated by Razvan-Nicolae Chichirau 8 months ago
- Status changed from WIP to Review
#10 Updated by Hynek Cihlar 8 months ago
Razvan-Nicolae Chichirau wrote:
I think this was implemented to avoid side-effects while modifying any dimension-related attributes.
Correct.
#11 Updated by Hynek Cihlar 8 months ago
Code review 10423a.
Instead of widthFromNative use columnFromPixels. The value truly represents pixels so in ChUI the conversion wouldn't work correct.
Should the assignment be done only when SCA.isSuspended()?
Also should the same modification be done for setHeightImpl?
#12 Updated by Razvan-Nicolae Chichirau 8 months ago
Hynek Cihlar wrote:
Code review 10423a.
Instead of
widthFromNativeusecolumnFromPixels. The value truly represents pixels so in ChUI the conversion wouldn't work correct.Should the assignment be done only when
SCA.isSuspended()?Also should the same modification be done for
setHeightImpl?
Right, it should also hold for setHeightImpl. I've tested with the following procedure: Show
Please check 10423a/rev. 16279.
#13 Updated by Hynek Cihlar 8 months ago
Hynek Cihlar wrote:
Should the assignment be done only when
SCA.isSuspended()?
Otherwise the assignment triggers the aspect, I don't think this is desired.
#14 Updated by Hynek Cihlar 7 months ago
Hynek Cihlar wrote:
Hynek Cihlar wrote:
Should the assignment be done only when
SCA.isSuspended()?Otherwise the assignment triggers the aspect, I don't think this is desired.
Razvan, please reply to "Should the assignment be done only when SCA.isSuspended()?".
#15 Updated by Razvan-Nicolae Chichirau 7 months ago
If we would remove the if statement, heightChars would be basically updated twice: once when setting heightPixels by SCA.afterSetHeightPixels(), and once from the explicit assignment.
So, the answer is yes. The assignment should be done only when SCA.isSuspended() to avoid setting the config field twice.
#16 Updated by Hynek Cihlar 7 months ago
- % Done changed from 100 to 90
- Status changed from Review to WIP
Code review 10423a. The changes look good, just please move CoordinatesConversion cc = LogicalTerminal.coordinates() inside the isSuspended branch.
#17 Updated by Razvan-Nicolae Chichirau 6 months ago
- Status changed from WIP to Review
- % Done changed from 90 to 100
Hynek: Please check 10423a/rev. 16280.
#18 Updated by Hynek Cihlar 6 months ago
- Status changed from Review to Internal Test
Razvan-Nicolae Chichirau wrote:
Hynek: Please check 10423a/rev. 16280.
It's good. Please regression-test.
#19 Updated by Razvan-Nicolae Chichirau 6 months ago
- ChUI regression tests
- tests from
testcasesprojects related toHEIGHT-CHARS,HEIGHT-PIXELS,WIDTH-CHARSandWIDTH-PIXELS - smoke-tests for Hotel GUI + 2 other customer apps
- unit-tests from a customer
- isolated testcases, such as #10423-1
If this is enough, we should merge 10423a.
#20 Updated by Hynek Cihlar 6 months ago
- Status changed from Internal Test to Merge Pending
Please merge 10423a to trunk.
#21 Updated by Razvan-Nicolae Chichirau 6 months ago
- Status changed from Merge Pending to Test
Branch 10423a was merged into trunk as rev. 16360 and archived.
#22 Updated by Vladimir Tsichevski 6 months ago
Hynek,
side question: What exactly is Aspect4J used for in the FWD runtime?
IMO this makes development, debugging and maintenance harder:
- FWD building takes a lot of time, incremental building is not available
- the FWD build scenario cannot be reliable reproduced in Eclipse
- debugging stepping is often broken
What would it realistically cost to move away from byte-code instrumentation / Aspect4J completely?
Any internal docs / old tickets discussing alternatives to Aspect4J weaving?
#23 Updated by Hynek Cihlar 6 months ago
Vladimir Tsichevski wrote:
Hynek,
side question: What exactly is Aspect4J used for in the FWD runtime?
IMO this makes development, debugging and maintenance harder:
Agree. But we are so deep in it that moving away from it would not be an easy task. Search for all the classes *Aspect in the project, you will see what I mean.
- FWD building takes a lot of time, incremental building is not available
- the FWD build scenario cannot be reliable reproduced in Eclipse
- debugging stepping is often broken
For development it helps to switch to runtime time weaving.