Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Williams2018-03-28 19:55:38 +0000
committerEric Williams2018-04-11 15:48:53 +0000
commitf6cd30d358f78f2fea020a56b9310faf02b437da (patch)
tree3c3473f4e17661d34c32789185ece8df8dbb70ba
parent91e7a4611c140836a2adf847a30418a3df660a42 (diff)
downloadeclipse.platform.swt-f6cd30d358f78f2fea020a56b9310faf02b437da.tar.gz
eclipse.platform.swt-f6cd30d358f78f2fea020a56b9310faf02b437da.tar.xz
eclipse.platform.swt-f6cd30d358f78f2fea020a56b9310faf02b437da.zip
Bug 529431: [GTK3.10+] Snippet294 fails to draw Region
This patch fixes drawing issues when setRegion is called on widgets that are children of Scrollable (like List, for example). The fix is to check if there are incoming draw events for paintHandle() in Control. If this is the case, and setRegion has been defined, we call gtk_draw(). This ensures that the clipping is applied to the right handle and that the region is drawn. Tested on GTK3.22. Compared behaviour with GTK3.8: most widgets work with the exception of Table/Tree and a few others. No AllNonBrowser JUnit tests fail. Functionality for Shell.setRegion() remains functional. Change-Id: Ife9a1688e58eef3c98cc6f74ff7d1bac1eac9986 Signed-off-by: Eric Williams <ericwill@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java58
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug529431_SetRegionTesting.java103
2 files changed, 140 insertions, 21 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index b16a51a9b7..4fad46995e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
@@ -3531,6 +3531,37 @@ long /*int*/ gtk_event_after (long /*int*/ widget, long /*int*/ gdkEvent) {
return 0;
}
+/**
+ * Convenience method that applies a region to the Control using cairo_clip.
+ *
+ * @param cairo the cairo context to apply the region to
+ */
+void cairoClipRegion (long /*int*/ cairo) {
+ GdkRectangle rect = new GdkRectangle ();
+ GDK.gdk_cairo_get_clip_rectangle (cairo, rect);
+ long /*int*/ regionHandle = this.region.handle;
+ GdkRectangle regionRect = new GdkRectangle();
+ /*
+ * These gdk_region_* functions actually map to the proper
+ * cairo_* functions in os.h.
+ */
+ GDK.gdk_region_get_clipbox(regionHandle, regionRect);
+ long /*int*/ actualRegion = GDK.gdk_region_rectangle(rect);
+ GDK.gdk_region_subtract(actualRegion, regionHandle);
+ // Draw the Shell bg using cairo, only if it's a different color
+ Shell shell = getShell();
+ Color shellBg = shell.getBackground();
+ if (shellBg != this.getBackground()) {
+ GdkRGBA rgba = shellBg.handleRGBA;
+ Cairo.cairo_set_source_rgba (cairo, rgba.red, rgba.green, rgba.blue, rgba.alpha);
+ } else {
+ Cairo.cairo_set_source_rgba (cairo, 0.0, 0.0, 0.0, 0.0);
+ }
+ GDK.gdk_cairo_region(cairo, actualRegion);
+ Cairo.cairo_clip(cairo);
+ Cairo.cairo_paint(cairo);
+}
+
@Override
long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
if ((state & OBSCURED) != 0) return 0;
@@ -3542,27 +3573,7 @@ long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
* See bug 529431.
*/
if (drawRegion) {
- long /*int*/ regionHandle = this.region.handle;
- GdkRectangle regionRect = new GdkRectangle();
- /*
- * These gdk_region_* functions actually map to the proper
- * cairo_* functions in os.h.
- */
- GDK.gdk_region_get_clipbox(regionHandle, regionRect);
- long /*int*/ actualRegion = GDK.gdk_region_rectangle(rect);
- GDK.gdk_region_subtract(actualRegion, regionHandle);
- // Draw the Shell bg using cairo, only if it's a different color
- Shell shell = getShell();
- Color shellBg = shell.getBackground();
- if (shellBg != this.getBackground()) {
- GdkRGBA rgba = shellBg.handleRGBA;
- Cairo.cairo_set_source_rgba (cairo, rgba.red, rgba.green, rgba.blue, rgba.alpha);
- } else {
- Cairo.cairo_set_source_rgba (cairo, 0.0, 0.0, 0.0, 0.0);
- }
- GDK.gdk_cairo_region(cairo, actualRegion);
- Cairo.cairo_clip(cairo);
- Cairo.cairo_paint(cairo);
+ cairoClipRegion(cairo);
}
if (!hooksPaint ()) return 0;
Event event = new Event ();
@@ -6352,6 +6363,11 @@ long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ us
}
break;
}
+ case DRAW: {
+ if (GTK.GTK_VERSION >= OS.VERSION(3, 10, 0) && paintHandle() == handle && drawRegion) {
+ return gtk_draw(handle, arg0);
+ }
+ }
}
return super.windowProc (handle, arg0, user_data);
}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug529431_SetRegionTesting.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug529431_SetRegionTesting.java
new file mode 100644
index 0000000000..135afdc265
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug529431_SetRegionTesting.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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.graphics.Region;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Shell;
+
+/*
+ * Title: Bug 529431: [GTK3.10+] Snippet294 fails to draw Region
+ * How to run: launch snippet and look for the region set
+ * Bug description: anything without a red bg and circular inner regions is broken
+ * Expected results: the region is applied correctly
+ * GTK Version(s): GTK3.10+
+ */
+public class Bug529431_SetRegionTesting {
+
+ static int[] circle(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;
+ }
+ return polygon;
+ }
+
+ public static void main(String[] args) {
+ final Display display = new Display();
+
+ final Shell shell = new Shell(display);
+ shell.setText("Regions on a Control");
+ shell.setLayout(new FillLayout());
+ shell.setBackground(display.getSystemColor(SWT.COLOR_DARK_RED));
+
+
+ /*
+ * Working: Canvas, Button, Shell, Combo, List, Spinner, DateTime, Text, ToolBar,
+ * CCombo, TabFolder
+ * Broken on 3.8: Link, Label, Scale, ProgressBar, ExpandBar, StyledText
+ * Broken on 3.22 (i.e. different from 3.8): Group, ProgressBar, Table/Tree, StyledText
+ */
+
+ // Common widget with text case
+ List widget = new List (shell, SWT.None);
+// widget.setText("Basic widget test");
+ widget.add("Basic widget test");
+
+ // Uncomment below to test a widget with items (ExpandBar, Table/Tree, etc)
+// ExpandItem item = new ExpandItem (widget, SWT.None);
+// item.setText("Item test");
+
+ // Original case form Snippet294
+// Button b2 = new Button(widget, SWT.PUSH);
+// b2.setText("Button with Regions");
+// item.setControl(b2);
+
+ // Table/Tree type cases
+// TableItem tableItem = new TableItem (widget, SWT.None);
+// tableItem.setText("This is a table/tree item test with a longer string");
+// TableItem tableItem2 = new TableItem (widget, SWT.None);
+// tableItem2.setText("This is a second table/tree item test with a longer string");
+
+
+ // define a region that looks like a circle with two holes in ot
+ Region region = new Region();
+ region.add(circle(67, 87, 77));
+ region.subtract(circle(20, 87, 47));
+ region.subtract(circle(20, 87, 113));
+
+ // define the shape of the button using setRegion
+ widget.setRegion(region);
+
+ // Uncomment to test input handling
+// b2.addListener(SWT.Selection, e -> shell.close());
+
+ shell.setSize(200,200);
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ region.dispose();
+ display.dispose();
+ }
+
+}

Back to the top