Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c122
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c8
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h8
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java119
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SessionManagerDBus.java480
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java27
7 files changed, 764 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 b1acaff1d0..16ae5c75c4 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
@@ -14766,6 +14766,18 @@ fail:
}
#endif
+#ifndef NO__1g_1dbus_1proxy_1get_1name_1owner
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1dbus_1proxy_1get_1name_1owner)
+ (JNIEnv *env, jclass that, jlong arg0)
+{
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1dbus_1proxy_1get_1name_1owner_FUNC);
+ rc = (jlong)g_dbus_proxy_get_name_owner((GDBusProxy *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1dbus_1proxy_1get_1name_1owner_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1dbus_1proxy_1new_1for_1bus_1sync
JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1dbus_1proxy_1new_1for_1bus_1sync)
(JNIEnv *env, jclass that, jint arg0, jint arg1, jlong arg2, jbyteArray arg3, jbyteArray arg4, jbyteArray arg5, jlong arg6, jlongArray arg7)
@@ -15028,6 +15040,22 @@ JNIEXPORT void JNICALL OS_NATIVE(_1g_1get_1current_1time)
}
#endif
+#ifndef NO__1g_1getenv
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1getenv)
+ (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+ jbyte *lparg0=NULL;
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1getenv_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ rc = (jlong)g_getenv((const gchar *)lparg0);
+fail:
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ OS_NATIVE_EXIT(env, that, _1g_1getenv_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1hash_1table_1get_1values
JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1hash_1table_1get_1values)
(JNIEnv *env, jclass that, jlong arg0)
@@ -16127,6 +16155,20 @@ fail:
}
#endif
+#ifndef NO__1g_1unsetenv
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1unsetenv)
+ (JNIEnv *env, jclass that, jbyteArray arg0)
+{
+ jbyte *lparg0=NULL;
+ OS_NATIVE_ENTER(env, that, _1g_1unsetenv_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ g_unsetenv((const gchar *)lparg0);
+fail:
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ OS_NATIVE_EXIT(env, that, _1g_1unsetenv_FUNC);
+}
+#endif
+
#ifndef NO__1g_1utf16_1offset_1to_1pointer
JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1utf16_1offset_1to_1pointer)
(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
@@ -16479,6 +16521,66 @@ JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1n_1children)
}
#endif
+#ifndef NO__1g_1variant_1new___3BZ_3B
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1new___3BZ_3B)
+ (JNIEnv *env, jclass that, jbyteArray arg0, jboolean arg1, jbyteArray arg2)
+{
+ jbyte *lparg0=NULL;
+ jbyte *lparg2=NULL;
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1new___3BZ_3B_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
+ rc = (jlong)g_variant_new((const gchar *)lparg0, (gboolean)arg1, (const gchar *)lparg2);
+fail:
+ if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, JNI_ABORT);
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1new___3BZ_3B_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1variant_1new___3B_3B
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1new___3B_3B)
+ (JNIEnv *env, jclass that, jbyteArray arg0, jbyteArray arg1)
+{
+ jbyte *lparg0=NULL;
+ jbyte *lparg1=NULL;
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1new___3B_3B_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+ rc = (jlong)g_variant_new((const gchar *)lparg0, (const gchar *)lparg1);
+fail:
+ if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, JNI_ABORT);
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1new___3B_3B_FUNC);
+ return rc;
+}
+#endif
+
+#ifndef NO__1g_1variant_1new___3B_3B_3B
+JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1new___3B_3B_3B)
+ (JNIEnv *env, jclass that, jbyteArray arg0, jbyteArray arg1, jbyteArray arg2)
+{
+ jbyte *lparg0=NULL;
+ jbyte *lparg1=NULL;
+ jbyte *lparg2=NULL;
+ jlong rc = 0;
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1new___3B_3B_3B_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetByteArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail;
+ if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
+ rc = (jlong)g_variant_new((const gchar *)lparg0, (const gchar *)lparg1, (const gchar *)lparg2);
+fail:
+ if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, JNI_ABORT);
+ if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, JNI_ABORT);
+ if (arg0 && lparg0) (*env)->ReleaseByteArrayElements(env, arg0, lparg0, JNI_ABORT);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1new___3B_3B_3B_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO__1g_1variant_1new_1boolean
JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1new_1boolean)
(JNIEnv *env, jclass that, jboolean arg0)
@@ -16571,6 +16673,16 @@ JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1new_1uint64)
}
#endif
+#ifndef NO__1g_1variant_1type_1free
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1variant_1type_1free)
+ (JNIEnv *env, jclass that, jlong arg0)
+{
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1type_1free_FUNC);
+ g_variant_type_free((GVariantType *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1type_1free_FUNC);
+}
+#endif
+
#ifndef NO__1g_1variant_1type_1new
JNIEXPORT jlong JNICALL OS_NATIVE(_1g_1variant_1type_1new)
(JNIEnv *env, jclass that, jbyteArray arg0)
@@ -16587,6 +16699,16 @@ fail:
}
#endif
+#ifndef NO__1g_1variant_1unref
+JNIEXPORT void JNICALL OS_NATIVE(_1g_1variant_1unref)
+ (JNIEnv *env, jclass that, jlong arg0)
+{
+ OS_NATIVE_ENTER(env, that, _1g_1variant_1unref_FUNC);
+ g_variant_unref((GVariant *)arg0);
+ OS_NATIVE_EXIT(env, that, _1g_1variant_1unref_FUNC);
+}
+#endif
+
#ifndef NO__1getpid
JNIEXPORT jint JNICALL OS_NATIVE(_1getpid)
(JNIEnv *env, jclass that)
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 ef46e89be3..40806b67d5 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
@@ -1223,6 +1223,7 @@ char * OS_nativeFunctionNames[] = {
"_1g_1dbus_1proxy_1call",
"_1g_1dbus_1proxy_1call_1finish",
"_1g_1dbus_1proxy_1call_1sync",
+ "_1g_1dbus_1proxy_1get_1name_1owner",
"_1g_1dbus_1proxy_1new_1for_1bus_1sync",
"_1g_1error_1free",
"_1g_1error_1get_1message",
@@ -1240,6 +1241,7 @@ char * OS_nativeFunctionNames[] = {
"_1g_1filename_1to_1utf8",
"_1g_1free",
"_1g_1get_1current_1time",
+ "_1g_1getenv",
"_1g_1hash_1table_1get_1values",
"_1g_1icon_1new_1for_1string",
"_1g_1icon_1to_1string",
@@ -1326,6 +1328,7 @@ char * OS_nativeFunctionNames[] = {
"_1g_1type_1parent",
"_1g_1type_1query",
"_1g_1type_1register_1static",
+ "_1g_1unsetenv",
"_1g_1utf16_1offset_1to_1pointer",
"_1g_1utf16_1offset_1to_1utf8_1offset",
"_1g_1utf16_1pointer_1to_1offset",
@@ -1352,6 +1355,9 @@ char * OS_nativeFunctionNames[] = {
"_1g_1variant_1get_1uint64",
"_1g_1variant_1is_1of_1type",
"_1g_1variant_1n_1children",
+ "_1g_1variant_1new___3BZ_3B",
+ "_1g_1variant_1new___3B_3B",
+ "_1g_1variant_1new___3B_3B_3B",
"_1g_1variant_1new_1boolean",
"_1g_1variant_1new_1byte",
"_1g_1variant_1new_1double",
@@ -1359,7 +1365,9 @@ char * OS_nativeFunctionNames[] = {
"_1g_1variant_1new_1string",
"_1g_1variant_1new_1tuple",
"_1g_1variant_1new_1uint64",
+ "_1g_1variant_1type_1free",
"_1g_1variant_1type_1new",
+ "_1g_1variant_1unref",
"_1getpid",
"_1glib_1major_1version",
"_1glib_1micro_1version",
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 7e6d144d0b..935e7d2522 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
@@ -1197,6 +1197,7 @@ typedef enum {
_1g_1dbus_1proxy_1call_FUNC,
_1g_1dbus_1proxy_1call_1finish_FUNC,
_1g_1dbus_1proxy_1call_1sync_FUNC,
+ _1g_1dbus_1proxy_1get_1name_1owner_FUNC,
_1g_1dbus_1proxy_1new_1for_1bus_1sync_FUNC,
_1g_1error_1free_FUNC,
_1g_1error_1get_1message_FUNC,
@@ -1214,6 +1215,7 @@ typedef enum {
_1g_1filename_1to_1utf8_FUNC,
_1g_1free_FUNC,
_1g_1get_1current_1time_FUNC,
+ _1g_1getenv_FUNC,
_1g_1hash_1table_1get_1values_FUNC,
_1g_1icon_1new_1for_1string_FUNC,
_1g_1icon_1to_1string_FUNC,
@@ -1300,6 +1302,7 @@ typedef enum {
_1g_1type_1parent_FUNC,
_1g_1type_1query_FUNC,
_1g_1type_1register_1static_FUNC,
+ _1g_1unsetenv_FUNC,
_1g_1utf16_1offset_1to_1pointer_FUNC,
_1g_1utf16_1offset_1to_1utf8_1offset_FUNC,
_1g_1utf16_1pointer_1to_1offset_FUNC,
@@ -1326,6 +1329,9 @@ typedef enum {
_1g_1variant_1get_1uint64_FUNC,
_1g_1variant_1is_1of_1type_FUNC,
_1g_1variant_1n_1children_FUNC,
+ _1g_1variant_1new___3BZ_3B_FUNC,
+ _1g_1variant_1new___3B_3B_FUNC,
+ _1g_1variant_1new___3B_3B_3B_FUNC,
_1g_1variant_1new_1boolean_FUNC,
_1g_1variant_1new_1byte_FUNC,
_1g_1variant_1new_1double_FUNC,
@@ -1333,7 +1339,9 @@ typedef enum {
_1g_1variant_1new_1string_FUNC,
_1g_1variant_1new_1tuple_FUNC,
_1g_1variant_1new_1uint64_FUNC,
+ _1g_1variant_1type_1free_FUNC,
_1g_1variant_1type_1new_FUNC,
+ _1g_1variant_1unref_FUNC,
_1getpid_FUNC,
_1glib_1major_1version_FUNC,
_1glib_1micro_1version_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index 6e605618d6..213b7d8e70 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -1741,6 +1741,18 @@ public static final void g_free(long mem) {
}
}
/**
+ * @param variable cast=(const gchar *),flags=no_out
+ */
+public static final native long _g_getenv(byte [] variable);
+public static final long g_getenv(byte [] variable) {
+ lock.lock();
+ try {
+ return _g_getenv(variable);
+ } finally {
+ lock.unlock();
+ }
+}
+/**
* @param table cast=(GHashTable *)
*/
public static final native long _g_hash_table_get_values(long table);
@@ -2791,7 +2803,18 @@ public static final long g_value_peek_pointer (long value) {
lock.unlock();
}
}
-
+/**
+ * @param variable cast=(const gchar *),flags=no_out
+ */
+public static final native void _g_unsetenv(byte [] variable);
+public static final void g_unsetenv(byte [] variable) {
+ lock.lock();
+ try {
+ _g_unsetenv(variable);
+ } finally {
+ lock.unlock();
+ }
+}
/** @method flags=const */
public static final native int _glib_major_version();
public static final int glib_major_version() {
@@ -4237,6 +4260,20 @@ public static final void g_dbus_proxy_call (long proxy, byte[] method_name, long
/**
* @param proxy cast=(GDBusProxy *)
+ * @category gdbus
+ */
+public static final native long _g_dbus_proxy_get_name_owner (long proxy);
+public static final long g_dbus_proxy_get_name_owner (long proxy) {
+ lock.lock();
+ try {
+ return _g_dbus_proxy_get_name_owner (proxy);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param proxy cast=(GDBusProxy *)
* @param res cast=(GAsyncResult *)
* @param error cast=(GError **)
* @category gdbus
@@ -4374,6 +4411,21 @@ public static final void g_variant_builder_add_value (long builder, long value)
}
/**
+ * @param type cast=(GVariantType *)
+ * @category gdbus
+ */
+public static final native void _g_variant_type_free (long type);
+/** @category gdbus */
+public static final void g_variant_type_free (long type) {
+ lock.lock();
+ try {
+ _g_variant_type_free(type);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
* @param type cast=(const gchar *)
* @category gdbus
*/
@@ -4419,6 +4471,56 @@ public static final void g_variant_builder_unref (long builder) {
}
/**
+ * @param format_string cast=(const gchar *),flags=no_out
+ * @param arg0 cast=(const gchar *),flags=no_out
+ * @category gdbus
+ */
+public static final native long _g_variant_new (byte[] format_string, byte[] arg0);
+/** @category gdbus */
+public static final long g_variant_new (byte[] format_string, byte[] arg0) {
+ lock.lock();
+ try {
+ return _g_variant_new(format_string, arg0);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param format_string cast=(const gchar *),flags=no_out
+ * @param arg0 cast=(gboolean)
+ * @param arg1 cast=(const gchar *),flags=no_out
+ * @category gdbus
+ */
+public static final native long _g_variant_new (byte[] format_string, boolean arg0, byte[] arg1);
+/** @category gdbus */
+public static final long g_variant_new (byte[] format_string, boolean arg0, byte[] arg1) {
+ lock.lock();
+ try {
+ return _g_variant_new(format_string, arg0, arg1);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
+ * @param format_string cast=(const gchar *),flags=no_out
+ * @param arg0 cast=(const gchar *),flags=no_out
+ * @param arg1 cast=(const gchar *),flags=no_out
+ * @category gdbus
+ */
+public static final native long _g_variant_new (byte[] format_string, byte[] arg0, byte[] arg1);
+/** @category gdbus */
+public static final long g_variant_new (byte[] format_string, byte[] arg0, byte[] arg1) {
+ lock.lock();
+ try {
+ return _g_variant_new(format_string, arg0, arg1);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
* @param intval cast=(gint32)
* @category gdbus
*/
@@ -4692,6 +4794,21 @@ public static final long g_variant_new_string (byte[] string) {
}
/**
+ * @param value cast=(GVariant *)
+ * @category gdbus
+ */
+public static final native void _g_variant_unref (long value);
+/** @category gdbus */
+public static final void g_variant_unref (long value) {
+ lock.lock();
+ try {
+ _g_variant_unref (value);
+ } finally {
+ lock.unlock();
+ }
+}
+
+/**
* @param object cast=(GObject *)
*/
public static final native long _g_object_ref_sink(long object);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
index 1d2d9edae9..64aa8a5bcc 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebkitGDBus.java
@@ -380,6 +380,7 @@ class WebkitGDBus {
long finalGVariant = OS.g_variant_new_tuple(variants, 1);
OS.g_dbus_method_invocation_return_value(invocation, finalGVariant);
OS.g_variant_builder_unref(builder);
+ OS.g_variant_type_free(type);
return;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SessionManagerDBus.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SessionManagerDBus.java
new file mode 100644
index 0000000000..02b67d4fd0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/SessionManagerDBus.java
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Syntevo 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:
+ * Syntevo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+import org.eclipse.swt.internal.gtk.OS;
+
+import java.util.ArrayList;
+
+/**
+ * Communicates with session manager to receive logoff/shutdown events.
+ *
+ * GTK also has an implementation (see gtk_application_impl_dbus_startup)
+ * However, it requires GtkApplication, and SWT doesn't use that.
+ *
+ * Current session manager clients can be seen in:
+ * dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.GetClients
+ *
+ * If you know clientObjectPath, you can send Stop signal with:
+ * dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager/ClientXX org.gnome.SessionManager.Client.Stop
+ */
+public class SessionManagerDBus {
+ public interface IListener {
+ /**
+ * Are you ready to exit?
+ *
+ * Time limit imposed by session manager is 1 second.
+ * Final cleanup should happen in stop().
+ * @return false to hint that you're not ready. Session manager can ignore the hint.
+ */
+ boolean isReadyToExit();
+
+ /**
+ * Perform final cleanup here.
+ *
+ * Please note that time limit imposed by session manager is 10 seconds.
+ */
+ void stop();
+ }
+
+ private static class ShutdownHook extends Thread {
+ private SessionManagerDBus parent;
+
+ public ShutdownHook(SessionManagerDBus parent) {
+ this.parent = parent;
+ }
+
+ public void run() {
+ parent.stop();
+ }
+
+ public void install() {
+ try {
+ Runtime.getRuntime().addShutdownHook(this);
+ } catch (IllegalArgumentException ex) {
+ // Shouldn't happen
+ ex.printStackTrace();
+ } catch (IllegalStateException ex) {
+ // Shouldn't happen
+ ex.printStackTrace();
+ } catch (SecurityException ex) {
+ // That's pity, but not too much of a problem.
+ // Client will stay registered, contributing to clutter a little bit.
+ }
+ }
+
+ public void remove() {
+ try {
+ Runtime.getRuntime().removeShutdownHook(this);
+ } catch (IllegalStateException ex) {
+ // The virtual machine is already in the process of shutting down.
+ // That's expected.
+ } catch (SecurityException ex) {
+ // Shouldn't happen if 'addShutdownHook' worked.
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ private ArrayList<IListener> listeners = new ArrayList<IListener>();
+ private Callback g_signal_callback;
+ private ShutdownHook shutdownHook = new ShutdownHook(this);
+ private long sessionManagerProxy;
+ private long clientProxy;
+ private String clientObjectPath;
+ private boolean isGnome;
+
+ private static int dbusTimeoutMsec = 10000;
+
+ public SessionManagerDBus() {
+ // Allow to disable session manager, for example in case it conflicts with
+ // session manager connection implemented in application itself.
+ boolean isDisabled = System.getProperty("org.eclipse.swt.internal.SessionManagerDBus.disable") != null;
+ if (isDisabled) return;
+
+ start();
+ }
+
+ /**
+ * Subscribes display for session manager events.
+ *
+ * Display will receive SWT.Close and will be able to hint that the session should not end.
+ * Please note that time limit imposed by session manager is 1 second.
+ * Final cleanup should happen at Display.dispose().
+ *
+ * Display will be disposed before session ends, allowing final cleanup to happen.
+ * Please note that time limit imposed by session manager is 10 seconds.
+ */
+ public void addListener(IListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeListener(IListener listener) {
+ listeners.remove(listener);
+ }
+
+ private boolean start() {
+ if (!connectSessionManager() || !registerClient() || !connectClientSignal()) {
+ stop();
+ return false;
+ }
+
+ // Both XFCE and Gnome will automatically unregister client on exit.
+ // However, to be on the correct side, we should also do it.
+ // Shutdown hook is used, because there's no other exit callback in SWT.
+ // Display.dispose() isn't good because there could be many displays.
+ // Also, in theory Displays can be created and disposed multiple times.
+ shutdownHook.install();
+
+ return true;
+ }
+
+ private void stop() {
+ if ((sessionManagerProxy != 0) && (clientObjectPath != null)) {
+ long args = OS.g_variant_new(
+ Converter.javaStringToCString("(o)"), //$NON-NLS-1$
+ Converter.javaStringToCString(clientObjectPath));
+
+ long [] error = new long [1];
+ OS.g_dbus_proxy_call_sync(
+ sessionManagerProxy,
+ Converter.javaStringToCString("UnregisterClient"), //$NON-NLS-1$
+ args,
+ OS.G_DBUS_CALL_FLAGS_NONE,
+ dbusTimeoutMsec,
+ 0,
+ error);
+
+ if (error[0] != 0) {
+ System.err.format(
+ "SWT SessionManagerDBus: Failed to UnregisterClient: %s%n",
+ extractFreeGError(error[0]));
+ }
+
+ clientObjectPath = null;
+ }
+
+ if (clientProxy != 0) {
+ OS.g_object_unref(clientProxy);
+ clientProxy = 0;
+ }
+
+ if (sessionManagerProxy != 0) {
+ OS.g_object_unref(sessionManagerProxy);
+ sessionManagerProxy = 0;
+ }
+
+ if (g_signal_callback != null) {
+ g_signal_callback.dispose();
+ g_signal_callback = null;
+ }
+
+ shutdownHook.remove();
+ }
+
+ private void sendEndSessionResponse(boolean is_ok, String reason) {
+ long args = OS.g_variant_new(
+ Converter.javaStringToCString("(bs)"), //$NON-NLS-1$
+ is_ok,
+ Converter.javaStringToCString(reason));
+
+ long [] error = new long [1];
+ OS.g_dbus_proxy_call(
+ clientProxy,
+ Converter.javaStringToCString("EndSessionResponse"), //$NON-NLS-1$
+ args,
+ OS.G_DBUS_CALL_FLAGS_NONE,
+ dbusTimeoutMsec,
+ 0,
+ 0,
+ error);
+
+ if (error[0] != 0) {
+ System.err.format(
+ "SWT SessionManagerDBus: Failed to EndSessionResponse: %s%n",
+ extractFreeGError(error[0]));
+ }
+ }
+
+ private boolean isReadyToExit() {
+ boolean isReady = true;
+
+ // Inform everyone even if someone is not ready.
+ for (int i = 0; i < listeners.size(); i++) {
+ IListener listener = listeners.get(i);
+ isReady = isReady && listener.isReadyToExit();
+ }
+
+ return isReady;
+ }
+
+ private void handleStop() {
+ for (int i = 0; i < listeners.size(); i++) {
+ IListener listener = listeners.get(i);
+ listener.stop();
+ }
+ }
+
+ /**
+ * Receives events from session manager.
+ *
+ * Docs: https://developer.gnome.org/gio/stable/GDBusProxy.html#GDBusProxy-g-signal
+ * NOTE: Will be called through native callback.
+ * @see this.g_signal_callback
+ * @return Error string in case of error, null if successful.
+ */
+ @SuppressWarnings("unused")
+ private long g_signal_handler(long proxy, long sender_name, long signal_name, long parameters, long user_data) {
+ String signalName = Converter.cCharPtrToJavaString(signal_name, false);
+
+ switch (signalName) {
+ case "QueryEndSession": //$NON-NLS-1$
+ sendEndSessionResponse(isReadyToExit(), "");
+ break;
+ case "EndSession": //$NON-NLS-1$
+ handleStop();
+ // Only respond after we've done, or session can end while we're still working.
+ // Even if we don't want the session to end, I don't think sending 'false' here can be of any help.
+ sendEndSessionResponse(true, "");
+ break;
+ case "Stop":
+ handleStop();
+ break;
+ }
+
+ // DBus expects 'void', but to make it easier to use with 'Callback' I return 'long'.
+ return 0;
+ }
+
+ private static String extractVariantTupleS(long variant) {
+ long childVariant = OS.g_variant_get_child_value(variant, 0);
+ long childString = OS.g_variant_get_string(childVariant, null);
+
+ String result = Converter.cCharPtrToJavaString(childString, false);
+
+ OS.g_variant_unref(childVariant);
+ return result;
+ }
+
+ private static String extractFreeGError(long errorPtr) {
+ long errorMessageC = OS.g_error_get_message(errorPtr);
+ String errorMessageStr = Converter.cCharPtrToJavaString(errorMessageC, false);
+ OS.g_error_free(errorPtr);
+ return errorMessageStr;
+ }
+
+ /**
+ * Creates a connection to the session manager.
+ *
+ * Saves result to member variable when successful.
+ * @return Error string in case of error, null if successful.
+ */
+ private String connectSessionManager(String dbusName, String objectPath, String interfaceName) {
+ int sessionManagerFlags =
+ OS.G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
+ OS.G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ OS.G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
+
+ long [] error = new long [1];
+ long proxy = OS.g_dbus_proxy_new_for_bus_sync(
+ OS.G_BUS_TYPE_SESSION,
+ sessionManagerFlags,
+ 0,
+ Converter.javaStringToCString(dbusName),
+ Converter.javaStringToCString(objectPath),
+ Converter.javaStringToCString(interfaceName),
+ 0,
+ error);
+
+ // Proxy is usually created even for non-existent service names.
+ if (proxy == 0) return extractFreeGError(error[0]);
+
+ // Is the service actually present?
+ long owner = OS.g_dbus_proxy_get_name_owner(proxy);
+ if (owner == 0) {
+ OS.g_object_unref(proxy);
+ return "Service not present";
+ }
+ OS.g_free(owner);
+
+ // Success
+ sessionManagerProxy = proxy;
+ return null;
+ }
+
+ private boolean connectSessionManager() {
+ String errorGnome = connectSessionManager(
+ "org.gnome.SessionManager", //$NON-NLS-1$
+ "/org/gnome/SessionManager", //$NON-NLS-1$
+ "org.gnome.SessionManager"); //$NON-NLS-1$
+
+ if (errorGnome == null) {
+ isGnome = true;
+ return true;
+ }
+
+ String errorXCFE = connectSessionManager(
+ "org.xfce.SessionManager", //$NON-NLS-1$
+ "/org/xfce/SessionManager", //$NON-NLS-1$
+ "org.xfce.Session.Manager"); //$NON-NLS-1$
+
+ if (errorXCFE == null) {
+ isGnome = false;
+ return true;
+ }
+
+ System.err.format(
+ "SWT SessionManagerDBus: Failed to connect to SessionManager (gnome: %s, xcfe: %s)%n",
+ errorGnome,
+ errorXCFE);
+
+ return false;
+ }
+
+ /**
+ * Gets the value of 'DESKTOP_AUTOSTART_ID'.
+ *
+ * This environment variable is set by session manager if the
+ * application was auto started (because it is configured to run
+ * automatically for every session). The variable helps session
+ * manager to match autostart settings with actual applications.
+ *
+ * For applications that were not started automatically, the
+ * variable is expected to be absent.
+ *
+ * Once used, 'DESKTOP_AUTOSTART_ID' must not leak into child
+ * processes, or they will fail to 'RegisterClient'.
+ */
+ private String claimDesktopAutostartID() {
+ byte[] DESKTOP_AUTOSTART_ID = Converter.javaStringToCString("DESKTOP_AUTOSTART_ID"); //$NON-NLS-1$
+
+ // NOTE: the returned pointer is not valid after g_unsetenv()
+ long valueC = OS.g_getenv(DESKTOP_AUTOSTART_ID);
+ if (valueC == 0) return null;
+ String result = Converter.cCharPtrToJavaString(valueC, false);
+
+ // Unset value, so it doesn't leak into child processes
+ OS.g_unsetenv(DESKTOP_AUTOSTART_ID);
+
+ return result;
+ }
+
+ /**
+ * Issues 'RegisterClient' dbus request to register with session manager.
+ *
+ * Saves result to member variable when successful.
+ * @return Error string in case of error, null if successful.
+ */
+ private String registerClient(String appID, String clientStartupID) {
+ long args = OS.g_variant_new(
+ Converter.javaStringToCString("(ss)"), //$NON-NLS-1$
+ Converter.javaStringToCString(appID),
+ Converter.javaStringToCString(clientStartupID));
+
+ long [] error = new long [1];
+ long clientInfo = OS.g_dbus_proxy_call_sync(
+ sessionManagerProxy,
+ Converter.javaStringToCString("RegisterClient"), //$NON-NLS-1$
+ args,
+ OS.G_DBUS_CALL_FLAGS_NONE,
+ dbusTimeoutMsec,
+ 0,
+ error);
+
+ if (clientInfo == 0) return extractFreeGError(error[0]);
+
+ // Success
+ clientObjectPath = extractVariantTupleS(clientInfo);
+ OS.g_variant_unref(clientInfo);
+ return null;
+ }
+
+ private boolean registerClient() {
+ // This ID doesn't matter much, at least according to what I know.
+ // Still, I decided to make it customizable for those who love identity.
+ String appID = System.getProperty("org.eclipse.swt.internal.SessionManagerDBus.appID"); //$NON-NLS-1$
+ if (appID == null) appID = "org.eclipse.swt.Application"; //$NON-NLS-1$
+
+ // Applications are expected to register using value of
+ // 'DESKTOP_AUTOSTART_ID' environment if it's present.
+ String desktopAutostartID = claimDesktopAutostartID();
+ if (desktopAutostartID != null) {
+ String errorText = registerClient(appID, desktopAutostartID);
+ if (errorText == null) return true;
+
+ // Bugged launchers use their 'DESKTOP_AUTOSTART_ID', but forget to unset it.
+ // This leaks a value that can't be used.
+ // The workaround is to retry with empty ID below.
+ // This pretends that parent's bug is already fixed.
+ boolean parentLeakedID = errorText.startsWith("GDBus.Error:org.gnome.SessionManager.AlreadyRegistered:"); //$NON-NLS-1$
+ if (!parentLeakedID) return false;
+ }
+
+ // In absence of 'DESKTOP_AUTOSTART_ID' just use empty ID.
+ String errorText = registerClient(appID, "");
+ if (errorText == null) return true;
+
+ // On XFCE 'RegisterClient' is only available since 4.13.0.
+ // Don't print this error since it's expected.
+ if (!isGnome && errorText.startsWith("GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: ")) //$NON-NLS-1$
+ return false;
+
+ System.err.format(
+ "SWT SessionManagerDBus: Failed to RegisterClient: %s%n",
+ errorText);
+
+ return false;
+ }
+
+ private boolean connectClientSignal() {
+ String dbusName;
+ String interfaceName;
+ if (isGnome) {
+ dbusName = "org.gnome.SessionManager"; //$NON-NLS-1$
+ interfaceName = "org.gnome.SessionManager.ClientPrivate"; //$NON-NLS-1$
+ } else {
+ dbusName = "org.xfce.SessionManager"; //$NON-NLS-1$
+ interfaceName = "org.xfce.Session.Client"; //$NON-NLS-1$
+ }
+
+ long [] error = new long [1];
+ clientProxy = OS.g_dbus_proxy_new_for_bus_sync(
+ OS.G_BUS_TYPE_SESSION,
+ 0,
+ 0,
+ Converter.javaStringToCString(dbusName),
+ Converter.javaStringToCString(clientObjectPath),
+ Converter.javaStringToCString(interfaceName),
+ 0,
+ error);
+
+ if (clientProxy == 0) {
+ System.err.format(
+ "SWT SessionManagerDBus: Failed to connect to Client: %s%n",
+ extractFreeGError(error[0]));
+ return false;
+ }
+
+ // The rest of the code makes this key call possible
+ g_signal_callback = new Callback(this, "g_signal_handler", 5); //$NON-NLS-1$
+ OS.g_signal_connect(
+ clientProxy,
+ Converter.javaStringToCString("g-signal"), //$NON-NLS-1$
+ g_signal_callback.getAddress(),
+ 0);
+
+ return true;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
index 506106abeb..5c7fd36499 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
@@ -192,6 +192,26 @@ public class Display extends Device {
Thread thread;
/* Display Shutdown */
+ private class SessionManagerListener implements SessionManagerDBus.IListener {
+ Display parent;
+
+ public SessionManagerListener(Display parent) {
+ this.parent = parent;
+ }
+
+ public boolean isReadyToExit() {
+ Event event = new Event ();
+ parent.sendEvent(SWT.Close, event);
+ return event.doit;
+ }
+
+ public void stop() {
+ parent.dispose();
+ }
+ }
+
+ static SessionManagerDBus sessionManagerDBus = new SessionManagerDBus();
+ SessionManagerListener sessionManagerListener;
Runnable [] disposeList;
/* Deferred Layout list */
@@ -3567,6 +3587,7 @@ protected void init () {
initializeSystemSettings ();
initializeWidgetTable ();
initializeWindowManager ();
+ initializeSessionManager ();
}
void initializeCallbacks () {
@@ -3960,6 +3981,11 @@ void initializeWindowManager () {
}
}
+void initializeSessionManager() {
+ sessionManagerListener = new SessionManagerListener(this);
+ sessionManagerDBus.addListener(sessionManagerListener);
+}
+
/**
* Invokes platform specific functionality to dispose a GC handle.
* <p>
@@ -4692,6 +4718,7 @@ protected void release () {
disposeList = null;
synchronizer.releaseSynchronizer ();
synchronizer = null;
+ sessionManagerDBus.removeListener(sessionManagerListener);
releaseDisplay ();
super.release ();
}

Back to the top