Bug 578340 - [GTK3] Canvas inside ScrolledComposite draws over unrelated composite
Summary: [GTK3] Canvas inside ScrolledComposite draws over unrelated composite
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.22   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: needinfo
Depends on:
Blocks:
 
Reported: 2022-01-24 05:25 EST by Dominic Scharfe CLA
Modified: 2022-01-24 08:54 EST (History)
1 user (show)

See Also:


Attachments
Canvas inside a composite (50.20 KB, image/png)
2022-01-24 05:25 EST, Dominic Scharfe CLA
no flags Details
Canvas inside a scrolled composite (43.53 KB, image/png)
2022-01-24 05:27 EST, Dominic Scharfe CLA
no flags Details
Example EditorPart project to reproduce (6.13 KB, application/zip)
2022-01-24 05:40 EST, Dominic Scharfe CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dominic Scharfe CLA 2022-01-24 05:25:04 EST
Created attachment 287880 [details]
Canvas inside a composite

I'm experiencing a strange behavior where drawing inside a canvas which is the content of a ScrolledComposite results in drawing over unrelated composites.

This seems similar to bug 531667.
Comment 1 Dominic Scharfe CLA 2022-01-24 05:27:58 EST
Created attachment 287881 [details]
Canvas inside a scrolled composite
Comment 2 Dominic Scharfe CLA 2022-01-24 05:33:45 EST
The effect can be reproduced creating a simple EditorPart:

	public void createPartControl(Composite parent, boolean scroll) {
		Composite main = scroll ? new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL)
				: new Composite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
		Canvas canvas = new Canvas(main, SWT.NONE);

		canvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				e.gc.setClipping((Rectangle) null);
				e.gc.setForeground(canvas.getDisplay().getSystemColor(SWT.COLOR_WHITE));
				e.gc.setBackground(canvas.getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
				e.gc.fillGradientRectangle(0, 0, 2000, 2000, true);
			}
		});

		canvas.setSize(2000, 2000);

		if (scroll) {
			((ScrolledComposite) main).setContent(canvas);
		}

		main.setLayout(new FillLayout());
	}
Comment 3 Andrey Loskutov CLA 2022-01-24 05:38:30 EST
Thanks for the report.

Can you please:
1) Provide Eclipse/SWT/GTK3 versions used
2) Provide small self contained SWT snippet that shows the problem (without workbench API)
3) Give a hint if that ever worked for you or is this a regression - and if that is a regression, in which release do you see it failing first?
Comment 4 Dominic Scharfe CLA 2022-01-24 05:40:32 EST
Created attachment 287882 [details]
Example EditorPart project to reproduce

To reproduce the behavior see the attached Eclipse project.

1) Import as project (tested with Eclipse IDE for Committers 2012-12)
2) Run as Eclipse Application
3) In the runtime workspace: Create a project with an empty file and open it with the "EditorWithCanvas"
Comment 5 Andrey Loskutov CLA 2022-01-24 05:46:34 EST
(In reply to Dominic Scharfe from comment #4)
> Created attachment 287882 [details]
> Example EditorPart project to reproduce
> 
> To reproduce the behavior see the attached Eclipse project.

Thanks. Now could you please create a standalone SWT snippet *without* using workbench API?
Comment 6 Andrey Loskutov CLA 2022-01-24 06:06:54 EST
(In reply to Dominic Scharfe from comment #2)
> 		canvas.addPaintListener(new PaintListener() {
> 			public void paintControl(PaintEvent e) {
> 				e.gc.setClipping((Rectangle) null);

Not sure this is a valid bug. If you unset the clipping, you have to expect that other widgets are affected too? Just remove this line and everything should work.
Comment 7 Dominic Scharfe CLA 2022-01-24 06:27:32 EST
> Thanks for the report.
Wow, that reply was fast :)

Can you please:
1) Provide Eclipse/SWT/GTK3 versions used
- Eclipse IDE for Committers 2012-12
- Rocky Linux 8 with gtk3 3.22.30-8.el8

2) Provide small self contained SWT snippet that shows the problem (without workbench API)
Sorry didn't read that before posting the workbench API dependent example. I'll try to create something. However in my first quick attempt I couldn't reproduce it.

3) Give a hint if that ever worked for you or is this a regression - and if that is a regression, in which release do you see it failing first?
In Eclipse Neon (4.6.3) using GTK2 we didn't have this issue.

> Not sure this is a valid bug. If you unset the clipping, you have to expect that other widgets are affected too? Just remove this line and everything should work.
I'm not sure either, the only thing I know is that the SWT behavior is now different than it was before. 
However it's not just when setting the clipping to null, but generally by setting the clipping to bounds which exceed the bounds of the containing ScrolledComposite, e.g:
e.gc.setClipping(new Rectangle(0,0,1000,1000));
Comment 8 Andrey Loskutov CLA 2022-01-24 08:03:42 EST
(In reply to Dominic Scharfe from comment #7)
> 3) Give a hint if that ever worked for you or is this a regression - and if
> that is a regression, in which release do you see it failing first?
> In Eclipse Neon (4.6.3) using GTK2 we didn't have this issue.

:) GTK2... That was long ago... Did it ever worked with GTK3? The two implementations have a lot of differences.

But back again to the original question - why do you want to expand the clipping over your widget area and why do you think it is a bug if there are paint artifacts after that *on another* widgets that are inside the expanded clipping area? That this per occasion worked under GTK2 is not a reason to be a "bug" for GTK3.
Comment 9 Dominic Scharfe CLA 2022-01-24 08:53:07 EST
> :) GTK2... That was long ago... Did it ever worked with GTK3? The two implementations have a lot of differences.
True. I have no proof it ever worked with GTK3, neither do I know if it should :)

>But back again to the original question - why do you want to expand the clipping over your widget area and why do you think it is a bug if there are paint artifacts after that *on another* widgets that are inside the expanded clipping area? 
There is a canvas which has a certain size. This canvas is embedded in a ScrolledComposite which is smaller, so the canvas is shown with scroll bars. Now when painting on the canvas, clipping is used. The clipping coordinates are inside the bounds of the canvas, but outside the bounds of the ScrolledComposite (the canvas cannot "know" theses bounds).
This use case sounds reasonable to me, but I might be wrong.

> That this per occasion worked under GTK2 is not a reason to be a "bug" for GTK3.
I totally agree. 
The indicators for me that this *might* be a bug were
1) it works when using Composite instead of ScrolledComposite
2) it used to work before

In the meantime I was able to create a standalone SWT snippet.
Comment 10 Dominic Scharfe CLA 2022-01-24 08:54:30 EST
See the snippet below.
To compare with the behavior of the "standard" composite, change createPartControl(shell, true);
to 
createPartControl(shell, false);


package bug_578340_java;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Bug {
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("Shell");

		shell.setLayout(new FillLayout(SWT.VERTICAL));

		createPartControl(shell, true);
		new Composite(shell, SWT.NONE);

		shell.setSize(500, 500);
		shell.open();

		while (!shell.isDisposed()) {

			if (!display.readAndDispatch())
				display.sleep();

		}
	}

	public static void createPartControl(Composite parent, boolean scroll) {
		Composite main = scroll ? new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL)
				: new Composite(parent, SWT.NONE);
		Canvas canvas = new Canvas(main, SWT.NONE);

		canvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				e.gc.setClipping(new Rectangle(0, 0, 500, 2000));
				e.gc.setForeground(canvas.getDisplay().getSystemColor(SWT.COLOR_WHITE));
				e.gc.setBackground(canvas.getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
				e.gc.fillGradientRectangle(0, 0, 500, 2000, true);
			}
		});

		canvas.setSize(500,2000);

		if (scroll) {
			((ScrolledComposite) main).setContent(canvas);
		}

		main.setLayout(new FillLayout());
	}
}