Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSimeon Andreev2018-03-20 22:39:17 +0000
committerAndrey Loskutov2018-04-06 13:46:31 +0000
commitd7ce5978d32a9dd4bf77dfa77e4b1c696992af4a (patch)
tree9bcac037e565f993c35890507e0797588f2a4600 /tests
parentd0fd89b3ff82408d3222b5b8dffada99a3471f65 (diff)
downloadeclipse.platform.swt-d7ce5978d32a9dd4bf77dfa77e4b1c696992af4a.tar.gz
eclipse.platform.swt-d7ce5978d32a9dd4bf77dfa77e4b1c696992af4a.tar.xz
eclipse.platform.swt-d7ce5978d32a9dd4bf77dfa77e4b1c696992af4a.zip
Bug 531667 - GTK drawing and clipping issues after Control.print(GC) fix
With the fix for bug 531667, at least the following regressions were introduced: 1. and 2. CTabFolder with SWT.RIGHT_TO_LEFT flag is not drawn and code using GC.setTransform()/GC.getTransform() was broken in some cases. E.g. caused drawing artifacts in tools based on GEF, such as figures drawn with wrong coordinates and starting with 0,0 in a global window space. We observe these regressions, since the Cairo transformation matrix is overwritten on some occasions, causing Cairo to lose the current (x,y) translation relative to the widget parents. 3. Further drawing artifacts are seen when scrolling in a GEF editor, or when resizing neighboring part stacks so that they land over specific GEF editor elements (e.g. LED). Namely, some elements are painted over neighboring composites (e.g. ports of a LED). This is caused by bad clipping set by client code and GC.setClipping(0) removing current Cairo clipping. Since GC is able to to draw at any point in the shell after the fix for bug 531667 (as the Cairo handle is shared by all composites), this results in client code being able to draw over other unrelated composites. 4. Bug 478618 was re-introduced on GTK > 3.20, i.e. ControlDecoration of e.g. text fields would paint its error decoration at a wrong location. In result, two decorations per ControlDecoration are painted; one of which is misplaced while the other will not be repainted on correcting input. On GTK 3.14 the ControlDecorations aren't drawn at all independently from bug 531667 or this patch, see bug 533241. We resolve the first two issues by remembering the original Cairo transformation matrix in GC and applying this matrix on every transform set by the client code. The third regression is fixed by remembering the original Cairo clipping and intersecting the client clipping with it. The last regression in ControlDecoration is fixed by applying the patch for bug 478618 also for GTK 3.20 and above. For GTK 3.14 see bug 533241, because this is not a regression from the Control.print(GC) fix. Manual bug snippets are provided for all of the regressions. Change-Id: I1bcc3c72d14fc37b05c51ff6f0845667a95d160c Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com> Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Diffstat (limited to 'tests')
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted.java71
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted_nested.java90
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_GC_transform_is_wrong.java155
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_Group_drawing_with_paint_listener_is_wrong.java75
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_PaintListener_paints_despite_empty_GC_clipping.java180
5 files changed, 571 insertions, 0 deletions
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted.java
new file mode 100644
index 0000000000..e2b0b56cc4
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Description: {@link CTabItem} in {@link CTabFolder} are not drawn if {@link CTabFolder} is placed
+ * below some other widget and is using {@link SWT#RIGHT_TO_LEFT}.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * <li>Observe tabs of tab folder.</li>
+ * </ol>
+ * Expected results: The tabs of the tab folder are seen.
+ * Actual results: The tabs of the tab folder are not seen.
+ */
+public class Bug531667_CTabFolder_right_to_left_tabs_are_not_painted {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(400, 300);
+ shell.setLayout(new FillLayout(SWT.VERTICAL));
+ shell.setText("Bug 531667: tab painting is broken");
+
+ Composite c = new Composite(shell, SWT.NONE);
+ c.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
+
+ CTabFolder tabFolder = new CTabFolder(shell, SWT.NONE | SWT.RIGHT_TO_LEFT);
+ createTab(tabFolder, "Tab 1", SWT.COLOR_GREEN);
+ createTab(tabFolder, "Tab 2", SWT.COLOR_YELLOW);
+
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+
+ private static CTabItem createTab(CTabFolder parent, String text, int color) {
+ CTabItem tab1 = new CTabItem(parent, SWT.NONE);
+ tab1.setText(text);
+ Composite comp = new Composite(parent, SWT.NONE);
+ comp.setBackground(comp.getDisplay().getSystemColor(color));
+ tab1.setControl(comp);
+ return tab1;
+ }
+
+}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted_nested.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted_nested.java
new file mode 100644
index 0000000000..98217c9cf2
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CTabFolder_right_to_left_tabs_are_not_painted_nested.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Description: {@link CTabItem} in {@link CTabFolder} are not drawn if {@link CTabFolder} is placed
+ * below some other widget and is using {@link SWT#RIGHT_TO_LEFT}.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * <li>Observe tabs of tab folder.</li>
+ * </ol>
+ * Expected results: The tabs of the tab folders are seen.
+ * Actual results: The tabs of the tab folders are not seen.
+ */
+public class Bug531667_CTabFolder_right_to_left_tabs_are_not_painted_nested {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(400, 300);
+ shell.setLayout(new FillLayout(SWT.VERTICAL));
+ shell.setText("Bug 531667: tab painting is broken");
+
+ Composite c = new Composite(shell, SWT.NONE);
+ c.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
+
+ Composite c1 = new Composite(shell, SWT.NONE);
+ c1.setLayout(new FillLayout(SWT.HORIZONTAL));
+ Composite c2 = new Composite(shell, SWT.NONE);
+ c2.setLayout(new FillLayout(SWT.HORIZONTAL));
+
+ Composite c3 = new Composite(c1, SWT.NONE);
+ c3.setLayout(new FillLayout());
+ Composite c4 = new Composite(c1, SWT.NONE);
+ c4.setLayout(new FillLayout());
+ Composite c5 = new Composite(c2, SWT.NONE);
+ c5.setLayout(new FillLayout());
+ Composite c6 = new Composite(c2, SWT.NONE);
+ c6.setLayout(new FillLayout());
+
+ Composite[] co = { c4, c3, c5, c6 };
+ for (int i = 0; i < co.length; ++i) {
+ Composite comp = co[i];
+ int alignmentStyle = i % 2 == 0 ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT;
+ CTabFolder tabFolder = new CTabFolder(comp, alignmentStyle);
+ createTab(tabFolder, "Tab 1", SWT.COLOR_GREEN);
+ createTab(tabFolder, "Tab 2", SWT.COLOR_YELLOW);
+ }
+
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+
+ private static CTabItem createTab(CTabFolder parent, String text, int color) {
+ CTabItem tab1 = new CTabItem(parent, SWT.NONE);
+ tab1.setText(text);
+ Composite comp = new Composite(parent, SWT.NONE);
+ comp.setBackground(comp.getDisplay().getSystemColor(color));
+ tab1.setControl(comp);
+ return tab1;
+ }
+
+}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_GC_transform_is_wrong.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_GC_transform_is_wrong.java
new file mode 100644
index 0000000000..f923d9659f
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_GC_transform_is_wrong.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.swt.tests.gtk.snippets;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.graphics.Transform;
+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;
+
+/**
+ * Description: {@link GC#setTransform(Transform)} is wrong. Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * <li>Resize the shell, so that figures are clipped by the composite.</li>
+ * </ol>
+ * Expected results: Each square in the composite has a fully visible red figure, which is contained in its composite.
+ * Actual results: Only the top left square has a visible figure, the figure is drawn over other composites on resize.
+ */
+public class Bug531667_GC_transform_is_wrong {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(400, 400);
+ shell.setText("Bug 531667 GC transform is wrong");
+ shell.setLayout(new FillLayout());
+ Composite main = new Composite(shell, SWT.NONE);
+ main.setLayout(new FillLayout());
+
+ Composite[] squares = showCaseTransform(main);
+ for (Composite square : squares) {
+ square.layout();
+ }
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ }
+
+ private static Composite[] showCaseTransform(Composite main) {
+ Composite composite = new Composite(main, SWT.NONE);
+ composite.setLayout(new FillLayout());
+
+ Composite left = new Composite(composite, SWT.NONE);
+ left.setLayout(new FillLayout(SWT.VERTICAL));
+ Composite upperLeft = new Composite(left, SWT.BORDER);
+ Composite bottomLeft = new Composite(left, SWT.BORDER);
+
+ Composite right = new Composite(composite, SWT.NONE);
+ right.setLayout(new FillLayout(SWT.VERTICAL));
+ Composite upperRight = new Composite(right, SWT.BORDER);
+ Composite bottomRight = new Composite(right, SWT.BORDER);
+
+ Consumer<Transform> upperLeftTransform = t -> transform(t, 100.f, 25.f, 1.5f, 1.25f, 45.f);
+ Consumer<Transform> upperRightTransform = t -> transform(t, 150.f, 25.f, 1.f, 1.5f, 75.f);
+ Consumer<Transform> bottomLeftTransform = t -> transform(t, 50.f, 25.f, 0.75f, 0.5f, 15.f);
+ Consumer<Transform> bottomRightTransform = t -> transform(t, 150.f, 75.f, 0.5f, 0.75f, 45.f);
+
+ Composite[] squares = { upperLeft, upperRight, bottomLeft, bottomRight };
+ List<Consumer<Transform>> transformations = Arrays.asList(upperLeftTransform, upperRightTransform,
+ bottomLeftTransform, bottomRightTransform);
+
+ for (int i = 0; i < squares.length; ++i) {
+ Composite square = squares[i];
+ square.setLayout(new FillLayout(SWT.VERTICAL));
+
+ Consumer<Transform> transformation = transformations.get(i);
+ PaintListener paint = new TransformSquare(transformation);
+ Canvas canvas = new Canvas(square, SWT.BORDER);
+ canvas.addPaintListener(paint);
+ }
+
+ return squares;
+ }
+
+ private static GC gc(PaintEvent event) {
+ if (event != null) {
+ return event.gc;
+ }
+ return null;
+ }
+
+ private static void transform(Transform transform, float translateX, float translateY, float scaleX, float scaleY, float rotationAngle) {
+ transform.translate(translateX, translateY);
+ transform.scale(scaleX, scaleY);
+ transform.rotate(rotationAngle);
+ }
+
+ private static class TransformSquare implements PaintListener {
+
+ private final Consumer<Transform> transformation;
+
+ TransformSquare(Consumer<Transform> transformation) {
+ this.transformation = transformation;
+ }
+
+ @Override
+ public void paintControl(PaintEvent event) {
+ GC gc = gc(event);
+
+ Device device = gc.getDevice();
+ Transform transform = new Transform(device);
+ transformation.accept(transform);
+
+ // set / get the transformation a few times, to see that this has no unexpected effect
+ gc.setTransform(transform);
+ gc.getTransform(transform);
+ gc.setTransform(transform);
+
+ // set some clipping to ensure we didn't break something clipping+transform related
+ Region region = new Region();
+ region.add(new Rectangle(0, 0, 200, 200));
+ region.subtract(new Rectangle(50, 50, 50, 50));
+ gc.setClipping(region);
+
+ int width = 80;
+ int height = 80;
+ gc.setAlpha(155);
+ gc.setBackground(device.getSystemColor(SWT.COLOR_RED));
+ int[] points = { 0, 0, width, 0, width, height, 0, height };
+ gc.fillPolygon(points);
+
+ gc.setTransform(null);
+ }
+ }
+}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_Group_drawing_with_paint_listener_is_wrong.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_Group_drawing_with_paint_listener_is_wrong.java
new file mode 100644
index 0000000000..f4850eefe4
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_Group_drawing_with_paint_listener_is_wrong.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Description: Drawing an image with a paint listener of a {@link Group} yields wrong results,
+ * namely the drawing is done in the group area and not in client area of the group.
+ * This causes problems e.g. with JFace ControlDecoration.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * </ol>
+ * Expected results: The shell contains a group, with a square fully within the group area.
+ * Actual results: The shell contains a group, with a square painted partially outside of the group area.
+ */
+public class Bug531667_Group_drawing_with_paint_listener_is_wrong {
+
+ public static void main(String[] args) {
+ final Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setLayout(new FillLayout());
+ shell.setSize(200, 200);
+ shell.setText("Bug 531667 paint inside a Group is wrong");
+
+ final Group group = new Group(shell, SWT.NONE);
+ group.setText("some group");
+ group.setLayout(new FillLayout());
+
+ final Image image = new Image(display, 40, 40);
+ GC gc = new GC(image);
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+ gc.fillRectangle(0, 0, 40, 40);
+ gc.dispose();
+
+ class DrawSquare implements PaintListener {
+ @Override
+ public void paintControl(PaintEvent e) {
+ GC gc = e.gc;
+ gc.drawImage(image, 0, 0);
+ }
+ }
+ group.addPaintListener(new DrawSquare());
+
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_PaintListener_paints_despite_empty_GC_clipping.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_PaintListener_paints_despite_empty_GC_clipping.java
new file mode 100644
index 0000000000..64f4d7ac4e
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_PaintListener_paints_despite_empty_GC_clipping.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiConsumer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Path;
+import org.eclipse.swt.graphics.PathData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+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.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Description: {@link Canvas#print(GC)} does not print the canvas.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * </ol>
+ * Expected results: The are no red figures drawn.
+ * Actual results: Red figures are drawn on each of the bottom composites,
+ * resulted from drawing on top of other composites due to bad clipping.
+ */
+public class Bug531667_PaintListener_paints_despite_empty_GC_clipping {
+
+ public static void main(String[] args) {
+ final Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(500, 250);
+ shell.setText("Bug 531667 paint listener paints despite empty clipping");
+ shell.setLayout(new FillLayout());
+
+ /*
+ * Some paint listeners which will paint a figure on their own composite,
+ * then set clipping in the area of another composite and try to draw over it.
+ * We should be seeing only figures in the upper composites.
+ */
+
+ class RectangleClipping implements BiConsumer<GC, Rectangle> {
+ @Override
+ public void accept(GC gc, Rectangle boundsOfComposite2) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_GREEN));
+ Rectangle rectangle = new Rectangle(0, 0, 50, 50);
+ gc.setClipping(rectangle);
+ gc.fillRectangle(0, 0, 200, 200);
+
+ Rectangle rectangleInComposite2 = new Rectangle(boundsOfComposite2.x, boundsOfComposite2.y, 50, 50);
+ gc.setClipping(rectangleInComposite2);
+
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+ gc.fillRectangle(rectangleInComposite2);
+ }
+ }
+
+ class BoundsClipping implements BiConsumer<GC, Rectangle> {
+ @Override
+ public void accept(GC gc, Rectangle boundsOfComposite2) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_GREEN));
+ gc.setClipping(50, 50, 50, 50);
+ gc.fillRectangle(0, 0, 200, 200);
+
+ gc.setClipping(boundsOfComposite2.x, boundsOfComposite2.y, 100, 100);
+
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+ gc.fillRectangle(boundsOfComposite2.x + 50, boundsOfComposite2.y + 50, 50, 50);
+ }
+ }
+
+ class PathClipping implements BiConsumer<GC, Rectangle> {
+ @Override
+ public void accept(GC gc, Rectangle boundsOfComposite2) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_GREEN));
+ Rectangle clipping = gc.getClipping();
+ Path path = triangle(0, 0, 100, display);
+ gc.setClipping(path);
+ gc.fillRectangle(0, 0, 100, 100);
+ gc.setClipping(clipping);
+
+ Rectangle rectangle = new Rectangle(boundsOfComposite2.x, boundsOfComposite2.y, 100, 100);
+ Path pathInComposite22 = triangle(rectangle.x, rectangle.y, 100, display);
+ gc.setClipping(pathInComposite22);
+
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+ gc.fillPath(pathInComposite22);
+ }
+ }
+
+ class RegionClipping implements BiConsumer<GC, Rectangle> {
+ @Override
+ public void accept(GC gc, Rectangle boundsOfComposite2) {
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_GREEN));
+ Region region = new Region();
+ region.add(new Rectangle(0, 0, 50, 50));
+ region.add(new Rectangle(50, 50, 50, 50));
+ gc.setClipping(region);
+ gc.fillRectangle(0, 0, 200, 200);
+
+ region.translate(boundsOfComposite2.x, boundsOfComposite2.y);
+ gc.setClipping(region);
+
+ gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+ gc.fillRectangle(boundsOfComposite2);
+ }
+ }
+
+ List<BiConsumer<GC, Rectangle> > paints = Arrays.asList(
+ new RectangleClipping(),
+ new BoundsClipping(),
+ new PathClipping(),
+ new RegionClipping()
+ );
+
+ for (BiConsumer<GC, Rectangle> paint : paints) {
+ paintedComposite(shell, paint);
+ }
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) display.sleep();
+ }
+ display.dispose();
+ }
+
+ private static void paintedComposite(Shell shell, final BiConsumer<GC, Rectangle> paint) {
+ Composite composite = new Composite(shell, SWT.BORDER);
+ composite.setLayout(new FillLayout(SWT.VERTICAL));
+
+ Composite composite1 = new Composite(composite, SWT.BORDER);
+ Composite composite2 = new Composite(composite, SWT.BORDER);
+ composite2.setLayout(new FillLayout(SWT.VERTICAL));
+
+ class PaintComposites implements PaintListener {
+ @Override
+ public void paintControl(PaintEvent e) {
+ e.gc.setAlpha(125);
+ paint.accept(e.gc, composite2.getBounds());
+ }
+ }
+
+ composite1.addPaintListener(new PaintComposites());
+
+
+ new Composite(composite2, SWT.NONE);
+ Label label21 = new Label(composite2, SWT.NONE);
+ label21.setText(paint.getClass().getSimpleName());
+ Label label22 = new Label(composite2, SWT.NONE);
+ label22.setText("should be empty");
+
+ }
+
+ private static Path triangle(int x, int y, int size, Display display) {
+ PathData pathData = new PathData();
+ pathData.types = new byte[] { SWT.PATH_MOVE_TO, SWT.PATH_LINE_TO, SWT.PATH_LINE_TO, SWT.PATH_CLOSE };
+ pathData.points = new float[] { x + 0.f, y + 0.f, x + size, y + 0.f, x + (size / 2), y + size };
+ Path path = new Path(display, pathData);
+ return path;
+ }
+} \ No newline at end of file

Back to the top