Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorEric Williams2018-06-20 13:58:02 +0000
committerEric Williams2018-06-29 18:00:35 +0000
commit70cce8be1320532905ef82171b46309da5c59bc7 (patch)
treebde8e406c26458b6507fc582318cb4b6f1ce2eb4 /tests
parent10147cdc9461fbde754a8d336f6c426653ca43c0 (diff)
downloadeclipse.platform.swt-70cce8be1320532905ef82171b46309da5c59bc7.tar.gz
eclipse.platform.swt-70cce8be1320532905ef82171b46309da5c59bc7.tar.xz
eclipse.platform.swt-70cce8be1320532905ef82171b46309da5c59bc7.zip
Bug 475784: half transparent composite as overlay composite not work
with gtk3 We have to handle some corner case drawing situations, since Control.setRegion() now uses Cairo entirely. In particular, we need to handle the case where a user is using an SWT.NO_BACKGROUND Composite as an overlay. This means the Composite has a region set, and a paintListener attached to perform custom drawing. Previously, Control.setRegion() "physically" manipulate the Composite's GdkWindow to prevent any drawing outside the given region. Since Cairo is now responsible for drawing the set region we have to handle this geometry ourselves. This patch fixes numerous issues all rolled into one. First, it adds a field in GCData which corresponds to the Cairo region. This is set in gtk_draw() so that GC.fill* methods will clip themselves accordingly and not fill where they aren't supposed to. Second, it checks for a PaintListener, NO_BACKGROUND, and a region being set. If these conditions are met, we draw a transparent background in Control.drawBackground() to ensure the region and custom drawing succeeds. Last, we copy the region at the Cairo level to ensure there are no crashes when calling setRegion(region) followed by region.dispose(). Tested on GTK3.22 using the snippet attached and a child Eclipse. No AllNonBrowser JUnit tests fail. Change-Id: Icdd04d8a4e0e504a5ee69688ba304af3956e4f77 Signed-off-by: Eric Williams <ericwill@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug475784_TransparentComposite.java248
1 files changed, 248 insertions, 0 deletions
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug475784_TransparentComposite.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug475784_TransparentComposite.java
new file mode 100644
index 0000000000..800ad78429
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug475784_TransparentComposite.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Red Hat and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+public class Bug475784_TransparentComposite extends Shell
+{
+ public static int RADIUS_OF_ROUND_EDGES = 30;
+
+ /**
+ * Launch the application.
+ * @param args
+ */
+ public static void main(String args[])
+ {
+ try
+ {
+ Display display = Display.getDefault();
+ Bug475784_TransparentComposite shell = new Bug475784_TransparentComposite(display);
+ shell.open();
+ shell.layout();
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create the shell.
+ * @param display
+ */
+ public Bug475784_TransparentComposite(final Display display)
+ {
+ super(display, SWT.SHELL_TRIM);
+ setLayout(new GridLayout(1, false));
+ final Composite composite = new Composite(this, SWT.NONE);
+ composite.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+ composite.setLayout(new GridLayout(1, false));
+ //overlay composite
+ final Composite overlay = new Composite(composite, SWT.NO_BACKGROUND | SWT.NO_FOCUS);
+ overlay.setLayout(new FillLayout());
+ overlay.setVisible(false);
+ //label
+ Label textLabel = new Label(composite, SWT.NONE);
+ textLabel.setText("Hello World!\nHello World!");
+ Button btnCheckButton = new Button(composite, SWT.CHECK);
+ btnCheckButton.setText("Check Button");
+ Button btnRadioButton = new Button(composite, SWT.RADIO);
+ btnRadioButton.setText("Radio Button");
+ //Composite for drawings
+ Composite compDraws = new Composite(composite, SWT.NONE);
+ compDraws.addPaintListener(e -> {
+ e.gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
+ e.gc.fillArc(0, 0, 50, 50, 0, 360);
+ });
+ //exclude overlay composite
+ GridData gData = new GridData();
+ gData.exclude = true;
+ overlay.setLayoutData(gData);
+ //set region
+ Region reg = new Region();
+ getRegionForRoundRectangle(reg, 0, 0, 200, 200, RADIUS_OF_ROUND_EDGES);
+ overlay.setRegion(reg);
+ reg.dispose();
+ //toggle overlay button
+ final Button btnNewButton = new Button(composite, SWT.NONE);
+ btnNewButton.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, true, 1, 1));
+ btnNewButton.setText("Toggle overlay");
+ GridData gdDataButton = new GridData(GridData.VERTICAL_ALIGN_END);
+ gdDataButton.horizontalAlignment = SWT.LEFT;
+ gdDataButton.verticalAlignment = SWT.BOTTOM;
+ gdDataButton.grabExcessVerticalSpace = true;
+ btnNewButton.setLayoutData(gdDataButton);
+ btnNewButton.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ int width = composite.getSize().x;
+ int height = composite.getSize().y - btnNewButton.getSize().y - 10;
+ overlay.setSize(width, height);
+ overlay.setVisible(!overlay.isVisible());
+ }
+ });
+ overlay.moveAbove(null);
+ overlay.addPaintListener(e -> {
+ e.gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_YELLOW));
+ e.gc.setAlpha(150);
+ e.gc.fillRectangle(new Rectangle(0, 0, overlay.getSize().x, overlay.getSize().y));
+ });
+ createContents();
+ }
+
+ /**
+ * Create contents of the shell.
+ */
+ protected void createContents()
+ {
+ setText("SWT Application");
+ setSize(450, 300);
+ }
+
+ @Override
+ protected void checkSubclass()
+ {
+ // Disable the check that prevents subclassing of SWT components
+ }
+
+ public static void getCircleRegion(Region region, int r, int offsetX, int offsetY)
+ {
+ int[] polygon = new int[8 * r + 4];
+ // x^2 + y^2 = r^2
+ for (int i = 0; i < 2 * r + 1; i++)
+ {
+ int x = i - r;
+ int y = (int) Math.sqrt(r * r - x * x);
+ polygon[2 * i] = offsetX + x;
+ polygon[2 * i + 1] = offsetY + y;
+ polygon[8 * r - 2 * i - 2] = offsetX + x;
+ polygon[8 * r - 2 * i - 1] = offsetY - y;
+ }
+ region.add(polygon);
+ }
+
+ public static void drawRoundFrame(GC gc, int width, int height)
+ {
+ Rectangle tmpClippingRect = gc.getClipping();
+ Region reg = new Region();
+ gc.getClipping(reg);
+ Region roundReg = new Region();
+ getRegionForRoundRectangle(roundReg, 1, 1, width, height, RADIUS_OF_ROUND_EDGES - 1);
+ reg.subtract(roundReg);
+ gc.setClipping(reg);
+ gc.fillRectangle(0, 0, width + 1, height + 1);
+ reg.dispose();
+ roundReg.dispose();
+ gc.setClipping(tmpClippingRect);
+ }
+
+ public static void loadPath(Region region, float[] points, byte[] types)
+ {
+ int start = 0, end = 0;
+ for (int i = 0; i < types.length; i++)
+ {
+ switch (types[i])
+ {
+ case SWT.PATH_MOVE_TO:
+ {
+ if (start != end)
+ {
+ int n = 0;
+ int[] temp = new int[end - start];
+ for (int k = start; k < end; k++)
+ {
+ temp[n++] = Math.round(points[k]);
+ }
+ region.add(temp);
+ }
+ start = end;
+ end += 2;
+ break;
+ }
+ case SWT.PATH_LINE_TO:
+ {
+ end += 2;
+ break;
+ }
+ case SWT.PATH_CLOSE:
+ {
+ if (start != end)
+ {
+ int n = 0;
+ int[] temp = new int[end - start];
+ for (int k = start; k < end; k++)
+ {
+ temp[n++] = Math.round(points[k]);
+ }
+ region.add(temp);
+ }
+ start = end;
+ break;
+ }
+ }
+ }
+ }
+
+ public static Path getPathForRoundRectangle(int x, int y, int width, int height, int r)
+ {
+ Path path = new Path(Display.getDefault());
+ path.addArc(x, y, 2 * r, 2 * r, 0, 360);
+ path.addArc(width - 2 * r, y, 2 * r, 2 * r, 0, 360);
+ path.addArc(x, height - 2 * r, 2 * r, 2 * r, 0, 360);
+ path.addArc(width - 2 * r, height - 2 * r, 2 * r, 2 * r, 0, 360);
+ path.addRectangle(x, r - y, width - x, height - 2 * r);
+ path.addRectangle(r - x, y, width - 2 * r, height - y);
+ Path path2 = new Path(Display.getDefault(), path, 0.0001f);
+ path.dispose();
+ return path2;
+ }
+
+ public static void drawRoundRectangleByPath(GC gc, int x, int y, int width, int height)
+ {
+ Path path = getPathForRoundRectangle(x, y, width, height, RADIUS_OF_ROUND_EDGES - 1);
+ gc.drawPath(path);
+ path.dispose();
+ }
+
+ public static void getRegionForRoundRectangle(Region reg, int x, int y, int width, int height, int r)
+ {
+ Path tmpPath = getPathForRoundRectangle(x, y, width, height, r);
+ PathData data = tmpPath.getPathData();
+ tmpPath.dispose();
+ loadPath(reg, data.points, data.types);
+ }
+} \ No newline at end of file

Back to the top