Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Williams2019-05-27 14:25:24 -0400
committerEric Williams2019-06-11 15:41:28 -0400
commitf7637e66ba1a0e60c7e4919d99cfaf4e62663d20 (patch)
treeed1c30057b928ff942baf08aafccf40ce6815616
parentaedb93fcdacf0c965a697676566985de1ac16f45 (diff)
downloadeclipse.platform.swt-f7637e66ba1a0e60c7e4919d99cfaf4e62663d20.tar.gz
eclipse.platform.swt-f7637e66ba1a0e60c7e4919d99cfaf4e62663d20.tar.xz
eclipse.platform.swt-f7637e66ba1a0e60c7e4919d99cfaf4e62663d20.zip
Bug 547557: [GTK] Shell.print(GC) not implemented
Implement Shell.print(GC) using a GdkPixbuf obtained from the root GdkWindow. This only works on GTK3 + X11, Wayland and GTK4 will likely need a different approach which will take more time to investigate. Tested on GTK3.24 on X11, both inside a flatpak and not. Output behaves as expected, no AllNonBrowser JUnit tests fail. Change-Id: Ibf39d60f2e97c1ecf8e45c9cdda6da3e9d7e160e Signed-off-by: Eric Williams <ericwill@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c12
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java13
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java21
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug547557_ShellPrintGC.java81
7 files changed, 130 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index f88e3fd40d..9783370d4a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
@@ -1657,6 +1657,18 @@ JNIEXPORT jlong JNICALL GDK_NATIVE(_1gdk_1pixbuf_1get_1byte_1length)
}
#endif
+#ifndef NO__1gdk_1pixbuf_1get_1from_1window
+JNIEXPORT jlong JNICALL GDK_NATIVE(_1gdk_1pixbuf_1get_1from_1window)
+ (JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2, jint arg3, jint arg4)
+{
+ jlong rc = 0;
+ GDK_NATIVE_ENTER(env, that, _1gdk_1pixbuf_1get_1from_1window_FUNC);
+ rc = (jlong)gdk_pixbuf_get_from_window((GdkWindow *)arg0, arg1, arg2, arg3, arg4);
+ GDK_NATIVE_EXIT(env, that, _1gdk_1pixbuf_1get_1from_1window_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1gdk_1pixbuf_1get_1has_1alpha
JNIEXPORT jboolean JNICALL GDK_NATIVE(_1gdk_1pixbuf_1get_1has_1alpha)
(JNIEnv *env, jclass that, jlong arg0)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
index 98f86dd750..11abf15d99 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h
@@ -274,6 +274,7 @@
#define NO__1gtk_1widget_1style_1get__J_3B_3JJ
#define NO__1gtk_1css_1provider_1load_1from_1data__I_3BI_3I
#define NO__1gtk_1css_1provider_1load_1from_1data__J_3BJ_3J
+#define NO__1gdk_1pixbuf_1get_1from_1window
// Some GtkContainer functions don't exist on GTK4
#define NO__1gtk_1container_1propagate_1draw
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index 3d9d40141a..9218cda91e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
@@ -136,6 +136,7 @@ char * GDK_nativeFunctionNames[] = {
"_1gdk_1pixbuf_1format_1get_1name",
"_1gdk_1pixbuf_1get_1bits_1per_1sample",
"_1gdk_1pixbuf_1get_1byte_1length",
+ "_1gdk_1pixbuf_1get_1from_1window",
"_1gdk_1pixbuf_1get_1has_1alpha",
"_1gdk_1pixbuf_1get_1height",
"_1gdk_1pixbuf_1get_1n_1channels",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index acb253ec53..8fa62cb8c8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
@@ -146,6 +146,7 @@ typedef enum {
_1gdk_1pixbuf_1format_1get_1name_FUNC,
_1gdk_1pixbuf_1get_1bits_1per_1sample_FUNC,
_1gdk_1pixbuf_1get_1byte_1length_FUNC,
+ _1gdk_1pixbuf_1get_1from_1window_FUNC,
_1gdk_1pixbuf_1get_1has_1alpha_FUNC,
_1gdk_1pixbuf_1get_1height_FUNC,
_1gdk_1pixbuf_1get_1n_1channels_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
index 6132c5c132..e8072b71f8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java
@@ -1548,6 +1548,19 @@ public class GDK extends OS {
lock.unlock();
}
}
+ /**
+ * @param window cast=(GdkWindow *)
+ */
+ public static final native long _gdk_pixbuf_get_from_window(long window, int x, int y, int width, int height);
+ /** [GTK3 only, if-def'd in os.h] */
+ public static final long gdk_pixbuf_get_from_window(long window, int x, int y, int width, int height) {
+ lock.lock();
+ try {
+ return _gdk_pixbuf_get_from_window(window, x, y, width, height);
+ } finally {
+ lock.unlock();
+ }
+ }
/** @param pixbuf cast=(const GdkPixbuf *) */
public static final native int _gdk_pixbuf_get_height(long pixbuf);
public static final int gdk_pixbuf_get_height(long pixbuf) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
index caa4466520..99f514f3f6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
@@ -1978,6 +1978,27 @@ public boolean print (GC gc) {
checkWidget ();
if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+ // Needs to be implemented on GTK4/Wayland
+ if (!GTK.GTK4 && OS.isX11()) {
+ Rectangle clipping = gc.getClipping();
+ long shellWindow = gtk_widget_get_window(shellHandle);
+ GdkRectangle rect = new GdkRectangle ();
+ GDK.gdk_window_get_frame_extents (shellWindow, rect);
+ if (clipping.height < rect.height || clipping.width < rect.width) {
+ System.err.println("Warning: the GC provided to Shell.print() has a smaller"
+ + " clipping than what is needed to print the Shell trimmings"
+ + " and content. Only the client area will be printed.");
+ return super.print(gc);
+ }
+ long rootWindow = GDK.gdk_get_default_root_window();
+ long pixbuf = GDK.gdk_pixbuf_get_from_window(rootWindow, rect.x, rect.y, rect.width, rect.height);
+ if (pixbuf != 0) {
+ GDK.gdk_cairo_set_source_pixbuf(gc.handle, pixbuf, 0, 0);
+ Cairo.cairo_paint(gc.handle);
+ OS.g_object_unref(pixbuf);
+ return true;
+ }
+ }
return false;
}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug547557_ShellPrintGC.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug547557_ShellPrintGC.java
new file mode 100644
index 0000000000..d8ace87a95
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug547557_ShellPrintGC.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Patrick Tasse and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Patrick Tasse - 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.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+public class Bug547557_ShellPrintGC {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ String gtkVersion = System.getProperty("org.eclipse.swt.internal.gtk.version");
+ Shell shell = new Shell(display);
+ shell.setText(gtkVersion);
+
+ shell.setLayout(new RowLayout(SWT.VERTICAL));
+
+ Label label = new Label(shell, SWT.NONE);
+ label.setText(gtkVersion);
+
+ Button button = new Button(shell, SWT.PUSH);
+ button.setText("Take Snapshot...");
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ // Add your path here i.e.:
+ // String filename = "/home/<user>/shell_test.png";
+ String filename = "";
+ if ((filename != null) && !filename.isEmpty()) {
+ saveImage(shell, filename, SWT.IMAGE_PNG);
+ }
+ }
+ });
+ shell.pack();
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+
+ private static void saveImage(Shell shell, String filename, int format) {
+ Rectangle bounds = shell.getBounds();
+ Image image = new Image(shell.getDisplay(), bounds);
+ // Printing the client area will result in a warning and only the client area being printed
+// Image image = new Image(shell.getDisplay(), shell.getClientArea());
+ GC gc = new GC(image);
+ shell.print(gc);
+ gc.dispose();
+ ImageData data = image.getImageData();
+ ImageLoader loader = new ImageLoader();
+ loader.data = new ImageData[] { data };
+ loader.save(filename, format);
+ image.dispose();
+ }
+} \ No newline at end of file

Back to the top