Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXi Yan2018-11-01 14:36:20 +0000
committerAlexander Kurtakov2018-11-05 15:32:53 +0000
commitf23577f6c6622ec6291ce641439c3c80d35e9ca5 (patch)
tree60ebb826aba487b937348fa0a3d8c914cfc1e3ef
parent492144bd4e220e6daeac4fcc4a3f65f4ffef6f95 (diff)
downloadeclipse.platform.swt-f23577f6c6622ec6291ce641439c3c80d35e9ca5.tar.gz
eclipse.platform.swt-f23577f6c6622ec6291ce641439c3c80d35e9ca5.tar.xz
eclipse.platform.swt-f23577f6c6622ec6291ce641439c3c80d35e9ca5.zip
Bug 540692 - [GTK] Replace GtkFileChooserDialog with
GtkFileChooserNative Replace GtkFileChooserDialog with GtkFileChooserNative for GTK3.20+. Change-Id: If705c899098d2598eb4400b96d1cf48474c53629 Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c42
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c2
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h2
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java28
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DirectoryDialog.java108
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/FileDialog.java55
6 files changed, 236 insertions, 1 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 f0e00540c2..2b2e90c7da 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
@@ -4854,6 +4854,36 @@ JNIEXPORT jintLong JNICALL GTK_NATIVE(_1gtk_1file_1chooser_1get_1uris)
}
#endif
+#ifndef NO__1gtk_1file_1chooser_1native_1new
+JNIEXPORT jintLong JNICALL GTK_NATIVE(_1gtk_1file_1chooser_1native_1new)
+ (JNIEnv *env, jclass that, jbyteArray arg0, jintLong arg1, jint arg2, jbyteArray arg3, jbyteArray arg4)
+{
+ jbyte *lparg0=NULL;
+ jbyte *lparg3=NULL;
+ jbyte *lparg4=NULL;
+ jintLong rc = 0;
+ GTK_NATIVE_ENTER(env, that, _1gtk_1file_1chooser_1native_1new_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ if (arg3) if ((lparg3 = (*env)->GetByteArrayElements(env, arg3, NULL)) == NULL) goto fail;
+ if (arg4) if ((lparg4 = (*env)->GetByteArrayElements(env, arg4, NULL)) == NULL) goto fail;
+/*
+ rc = (jintLong)gtk_file_chooser_native_new((const gchar *)lparg0, (GtkWindow *)arg1, arg2, (const gchar *)lparg3, (const gchar *)lparg4);
+*/
+ {
+ GTK_LOAD_FUNCTION(fp, gtk_file_chooser_native_new)
+ if (fp) {
+ rc = (jintLong)((jintLong (CALLING_CONVENTION*)(const gchar *, GtkWindow *, jint, const gchar *, const gchar *))fp)((const gchar *)lparg0, (GtkWindow *)arg1, arg2, (const gchar *)lparg3, (const gchar *)lparg4);
+ }
+ }
+fail:
+ if (arg4 && lparg4) (*env)->ReleaseByteArrayElements(env, arg4, lparg4, JNI_ABORT);
+ if (arg3 && lparg3) (*env)->ReleaseByteArrayElements(env, arg3, lparg3, JNI_ABORT);
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ GTK_NATIVE_EXIT(env, that, _1gtk_1file_1chooser_1native_1new_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1gtk_1file_1chooser_1set_1current_1folder
JNIEXPORT void JNICALL GTK_NATIVE(_1gtk_1file_1chooser_1set_1current_1folder)
(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1)
@@ -6539,6 +6569,18 @@ JNIEXPORT void JNICALL GTK_NATIVE(_1gtk_1misc_1set_1alignment)
}
#endif
+#ifndef NO__1gtk_1native_1dialog_1run
+JNIEXPORT jint JNICALL GTK_NATIVE(_1gtk_1native_1dialog_1run)
+ (JNIEnv *env, jclass that, jintLong arg0)
+{
+ jint rc = 0;
+ GTK_NATIVE_ENTER(env, that, _1gtk_1native_1dialog_1run_FUNC);
+ rc = (jint)gtk_native_dialog_run((GtkNativeDialog *)arg0);
+ GTK_NATIVE_EXIT(env, that, _1gtk_1native_1dialog_1run_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1gtk_1notebook_1get_1current_1page
JNIEXPORT jint JNICALL GTK_NATIVE(_1gtk_1notebook_1get_1current_1page)
(JNIEnv *env, jclass that, jintLong arg0)
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 1fab85850f..87fadcaa98 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
@@ -424,6 +424,7 @@ char * GTK_nativeFunctionNames[] = {
"_1gtk_1file_1chooser_1get_1filter",
"_1gtk_1file_1chooser_1get_1uri",
"_1gtk_1file_1chooser_1get_1uris",
+ "_1gtk_1file_1chooser_1native_1new",
"_1gtk_1file_1chooser_1set_1current_1folder",
"_1gtk_1file_1chooser_1set_1current_1folder_1uri",
"_1gtk_1file_1chooser_1set_1current_1name",
@@ -566,6 +567,7 @@ char * GTK_nativeFunctionNames[] = {
"_1gtk_1micro_1version",
"_1gtk_1minor_1version",
"_1gtk_1misc_1set_1alignment",
+ "_1gtk_1native_1dialog_1run",
"_1gtk_1notebook_1get_1current_1page",
"_1gtk_1notebook_1get_1scrollable",
"_1gtk_1notebook_1insert_1page",
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 1c158c076a..3f279b26bb 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
@@ -422,6 +422,7 @@ typedef enum {
_1gtk_1file_1chooser_1get_1filter_FUNC,
_1gtk_1file_1chooser_1get_1uri_FUNC,
_1gtk_1file_1chooser_1get_1uris_FUNC,
+ _1gtk_1file_1chooser_1native_1new_FUNC,
_1gtk_1file_1chooser_1set_1current_1folder_FUNC,
_1gtk_1file_1chooser_1set_1current_1folder_1uri_FUNC,
_1gtk_1file_1chooser_1set_1current_1name_FUNC,
@@ -564,6 +565,7 @@ typedef enum {
_1gtk_1micro_1version_FUNC,
_1gtk_1minor_1version_FUNC,
_1gtk_1misc_1set_1alignment_FUNC,
+ _1gtk_1native_1dialog_1run_FUNC,
_1gtk_1notebook_1get_1current_1page_FUNC,
_1gtk_1notebook_1get_1scrollable_FUNC,
_1gtk_1notebook_1insert_1page_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
index 1f7ce3e475..2236ca1f4d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
@@ -100,6 +100,8 @@ public class GTK extends OS {
public static final int GTK_RESPONSE_APPLY = 0xfffffff6;
public static final int GTK_RESPONSE_CANCEL = 0xfffffffa;
public static final int GTK_RESPONSE_OK = 0xfffffffb;
+ public static final int GTK_RESPONSE_ACCEPT = -3;
+ public static final int GTK_RESPONSE_DELETE_EVENT = -4;
public static final int GTK_SCROLL_NONE = 0;
public static final int GTK_SCROLL_JUMP = 1;
public static final int GTK_SCROLL_STEP_BACKWARD = 2;
@@ -2392,6 +2394,22 @@ public class GTK extends OS {
}
/**
* @method flags=dynamic
+ * @param title cast=(const gchar *),flags=no_out
+ * @param parent cast=(GtkWindow *)
+ * @param accept_label cast=(const gchar *),flags=no_out
+ * @param cancel_label cast=(const gchar *),flags=no_out
+ */
+ public static final native long /*int*/ _gtk_file_chooser_native_new(byte[] title, long /*int*/ parent, int action, byte[] accept_label, byte[] cancel_label);
+ public static final long /*int*/ gtk_file_chooser_native_new(byte[] title, long /*int*/ parent, int action, byte[] accept_label, byte[] cancel_label) {
+ lock.lock();
+ try {
+ return _gtk_file_chooser_native_new(title, parent, action, accept_label, cancel_label);
+ } finally {
+ lock.unlock();
+ }
+ }
+ /**
+ * @method flags=dynamic
*/
public static final native void _gtk_event_controller_handle_event(long /*int*/ gesture, long /*int*/ event);
public static final void gtk_event_controller_handle_event(long /*int*/ gesture, long /*int*/ event) {
@@ -3932,6 +3950,16 @@ public class GTK extends OS {
lock.unlock();
}
}
+ /** @param dialog cast=(GtkNativeDialog *) */
+ public static final native int _gtk_native_dialog_run(long /*int*/ dialog);
+ public static final int gtk_native_dialog_run(long /*int*/ dialog) {
+ lock.lock();
+ try {
+ return _gtk_native_dialog_run(dialog);
+ } finally {
+ lock.unlock();
+ }
+ }
/** @param notebook cast=(GtkNotebook *) */
public static final native int _gtk_notebook_get_current_page(long /*int*/ notebook);
public static final int gtk_notebook_get_current_page(long /*int*/ notebook) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DirectoryDialog.java
index 22eb5e7e23..b5aa7bf88d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DirectoryDialog.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/DirectoryDialog.java
@@ -121,7 +121,115 @@ public String getMessage () {
* </ul>
*/
public String open () {
+ if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0)) {
+ return openNativeChooserDialog();
+ } else {
return openChooserDialog ();
+ }
+}
+/**
+ * Open the file chooser dialog using the GtkFileChooserNative API (GTK3.20+) for running applications
+ * without direct filesystem access (such as Flatpak). API for GtkFileChoosernative does not
+ * give access to any GtkWindow or GtkWidget for the dialog, thus this method omits calls that
+ * requires such access. These are be handled by the GtkNativeDialog API.
+ *
+ * @return a string describing the absolute path of the first selected file, or null
+ */
+String openNativeChooserDialog () {
+ byte [] titleBytes = Converter.wcsToMbcs (title, true);
+ long /*int*/ shellHandle = parent.topHandle ();
+ Display display = parent != null ? parent.getDisplay (): Display.getCurrent ();
+ long /*int*/ handle = 0;
+ handle = GTK.gtk_file_chooser_native_new(titleBytes, shellHandle, GTK.GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK.GTK_NAMED_LABEL_OK, GTK.GTK_NAMED_LABEL_CANCEL);
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+
+ if (filterPath != null && filterPath.length () > 0) {
+ StringBuilder stringBuilder = new StringBuilder ();
+ /* filename must be a full path */
+ if (!filterPath.startsWith (SEPARATOR)) {
+ stringBuilder.append (SEPARATOR);
+ }
+ stringBuilder.append (filterPath);
+ byte [] buffer = Converter.wcsToMbcs (stringBuilder.toString (), true);
+ /*
+ * in GTK version 2.10, gtk_file_chooser_set_current_folder requires path
+ * to be true canonical path. So using realpath to convert the path to
+ * true canonical path.
+ */
+ if (OS.IsAIX) {
+ byte [] outputBuffer = new byte [PATH_MAX];
+ long /*int*/ ptr = OS.realpath (buffer, outputBuffer);
+ if (ptr != 0) {
+ GTK.gtk_file_chooser_set_current_folder (handle, ptr);
+ }
+ /* We are not doing free here because realpath returns the address of outputBuffer
+ * which is created in this code and we let the garbage collector to take care of this
+ */
+ } else {
+ long /*int*/ ptr = OS.realpath (buffer, null);
+ if (ptr != 0) {
+ GTK.gtk_file_chooser_set_current_folder (handle, ptr);
+ OS.g_free (ptr);
+ }
+ }
+ }
+ if (message.length () > 0) {
+ byte [] buffer = Converter.wcsToMbcs (message, true);
+ long /*int*/ box = GTK.gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, 0);
+ GTK.gtk_box_set_homogeneous (box, false);
+ if (box == 0) error (SWT.ERROR_NO_HANDLES);
+ long /*int*/ label = GTK.gtk_label_new (buffer);
+ if (label == 0) error (SWT.ERROR_NO_HANDLES);
+ GTK.gtk_container_add (box, label);
+ GTK.gtk_widget_show (label);
+ GTK.gtk_label_set_line_wrap (label, true);
+ GTK.gtk_label_set_justify (label, GTK.GTK_JUSTIFY_CENTER);
+ GTK.gtk_file_chooser_set_extra_widget (handle, box);
+ }
+ String answer = null;
+ display.addIdleProc ();
+ int signalId = 0;
+ long /*int*/ hookId = 0;
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+ signalId = OS.g_signal_lookup (OS.map, GTK.GTK_TYPE_WIDGET());
+ hookId = OS.g_signal_add_emission_hook (signalId, 0, display.emissionProc, handle, 0);
+ }
+ display.sendPreExternalEventDispatchEvent ();
+ int response = GTK.gtk_native_dialog_run (handle);
+ /*
+ * This call to gdk_threads_leave() is a temporary work around
+ * to avoid deadlocks when gdk_threads_init() is called by native
+ * code outside of SWT (i.e AWT, etc). It ensures that the current
+ * thread leaves the GTK lock acquired by the function above.
+ */
+ GDK.gdk_threads_leave();
+ display.sendPostExternalEventDispatchEvent ();
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+ OS.g_signal_remove_emission_hook (signalId, hookId);
+ }
+ if (response == GTK.GTK_RESPONSE_ACCEPT) {
+ long /*int*/ path = GTK.gtk_file_chooser_get_filename (handle);
+ if (path != 0) {
+ long /*int*/ utf8Ptr = OS.g_filename_to_utf8 (path, -1, null, null, null);
+ if (utf8Ptr == 0) utf8Ptr = OS.g_filename_display_name (path);
+ if (path != utf8Ptr) OS.g_free (path);
+ if (utf8Ptr != 0) {
+ long /*int*/ [] items_written = new long /*int*/ [1];
+ long /*int*/ utf16Ptr = OS.g_utf8_to_utf16 (utf8Ptr, -1, null, items_written, null);
+ OS.g_free (utf8Ptr);
+ if (utf16Ptr != 0) {
+ int clength = (int)/*64*/items_written [0];
+ char [] chars = new char [clength];
+ C.memmove (chars, utf16Ptr, clength * 2);
+ OS.g_free (utf16Ptr);
+ answer = new String (chars);
+ filterPath = answer;
+ }
+ }
+ }
+ }
+ display.removeIdleProc ();
+ return answer;
}
String openChooserDialog () {
byte [] titleBytes = Converter.wcsToMbcs (title, true);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/FileDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/FileDialog.java
index 892ef19c4c..e5fb1bfc44 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/FileDialog.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/FileDialog.java
@@ -302,7 +302,60 @@ public boolean getOverwrite () {
* </ul>
*/
public String open () {
- return openChooserDialog ();
+ if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0)) {
+ return openNativeChooserDialog();
+ } else {
+ return openChooserDialog();
+ }
+}
+/**
+ * Open the file chooser dialog using the GtkFileChooserNative API (GTK3.20+) for running applications
+ * without direct filesystem access (such as Flatpak). API for GtkFileChoosernative does not
+ * give access to any GtkWindow or GtkWidget for the dialog, thus this method omits calls that
+ * requires such access. These are be handled by the GtkNativeDialog API.
+ *
+ * @return a string describing the absolute path of the first selected file, or null
+ */
+String openNativeChooserDialog () {
+ assert GTK.GTK_VERSION >= OS.VERSION(3, 20, 0);
+ byte [] titleBytes = Converter.wcsToMbcs (title, true);
+ int action = (style & SWT.SAVE) != 0 ? GTK.GTK_FILE_CHOOSER_ACTION_SAVE : GTK.GTK_FILE_CHOOSER_ACTION_OPEN;
+ long /*int*/ shellHandle = parent.topHandle ();
+ Display display = parent != null ? parent.getDisplay (): Display.getCurrent ();
+ handle = GTK.gtk_file_chooser_native_new(titleBytes, shellHandle, action, GTK.GTK_NAMED_LABEL_OK, GTK.GTK_NAMED_LABEL_CANCEL);
+ if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+
+ if (uriMode) {
+ GTK.gtk_file_chooser_set_local_only (handle, false);
+ }
+ presetChooserDialog ();
+ display.addIdleProc ();
+ String answer = null;
+ int signalId = 0;
+ long /*int*/ hookId = 0;
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+ signalId = OS.g_signal_lookup (OS.map, GTK.GTK_TYPE_WIDGET());
+ hookId = OS.g_signal_add_emission_hook (signalId, 0, display.emissionProc, handle, 0);
+ }
+ display.sendPreExternalEventDispatchEvent ();
+ int response = 0;
+ response = GTK.gtk_native_dialog_run(handle);
+ /*
+ * This call to gdk_threads_leave() is a temporary work around
+ * to avoid deadlocks when gdk_threads_init() is called by native
+ * code outside of SWT (i.e AWT, etc). It ensures that the current
+ * thread leaves the GTK lock acquired by the function above.
+ */
+ GDK.gdk_threads_leave();
+ display.sendPostExternalEventDispatchEvent ();
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) {
+ OS.g_signal_remove_emission_hook (signalId, hookId);
+ }
+ if (response == GTK.GTK_RESPONSE_ACCEPT) {
+ answer = computeResultChooserDialog ();
+ }
+ display.removeIdleProc ();
+ return answer;
}
String openChooserDialog () {
byte [] titleBytes = Converter.wcsToMbcs (title, true);

Back to the top