Skip to content

Commit c947902

Browse files
mkartashevjbrbot
authored andcommitted
JBR-7087 Wayland: Desktop support via GNOME
1 parent 651e677 commit c947902

File tree

7 files changed

+268
-122
lines changed

7 files changed

+268
-122
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2025, JetBrains s.r.o.. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package sun.awt.wl;
27+
28+
import sun.awt.SunToolkit;
29+
import sun.awt.UNIXToolkit;
30+
31+
import java.awt.Desktop;
32+
import java.io.File;
33+
import java.io.IOException;
34+
import java.net.MalformedURLException;
35+
import java.net.URI;
36+
37+
import java.awt.Desktop.Action;
38+
import java.awt.peer.DesktopPeer;
39+
import java.util.ArrayList;
40+
import java.util.Arrays;
41+
import java.util.List;
42+
43+
public class WLDesktopPeer implements DesktopPeer {
44+
45+
// supportedActions may be changed from native within the init() call
46+
private static final List<Desktop.Action> supportedActions
47+
= new ArrayList<>(Arrays.asList(Action.OPEN, Action.MAIL, Action.BROWSE));
48+
49+
private static boolean nativeLibraryLoaded = false;
50+
private static boolean initExecuted = false;
51+
52+
private static void initWithLock(){
53+
SunToolkit.awtLock();
54+
try {
55+
if (!initExecuted) {
56+
nativeLibraryLoaded = init(
57+
UNIXToolkit.getEnabledGtkVersion().getNumber(),
58+
UNIXToolkit.isGtkVerbose());
59+
}
60+
} finally {
61+
initExecuted = true;
62+
SunToolkit.awtUnlock();
63+
}
64+
}
65+
66+
WLDesktopPeer(){
67+
initWithLock();
68+
}
69+
70+
static boolean isDesktopSupported() {
71+
initWithLock();
72+
return nativeLibraryLoaded && !supportedActions.isEmpty();
73+
}
74+
75+
public boolean isSupported(Action type) {
76+
return supportedActions.contains(type);
77+
}
78+
79+
public void open(File file) throws IOException {
80+
try {
81+
launch(file.toURI());
82+
} catch (MalformedURLException e) {
83+
throw new IOException(file.toString());
84+
}
85+
}
86+
87+
public void edit(File file) throws IOException {
88+
throw new UnsupportedOperationException("The current platform " +
89+
"doesn't support the EDIT action.");
90+
}
91+
92+
public void print(File file) throws IOException {
93+
throw new UnsupportedOperationException("The current platform " +
94+
"doesn't support the PRINT action.");
95+
}
96+
97+
public void mail(URI uri) throws IOException {
98+
launch(uri);
99+
}
100+
101+
public void browse(URI uri) throws IOException {
102+
launch(uri);
103+
}
104+
105+
private void launch(URI uri) throws IOException {
106+
byte[] uriByteArray = ( uri.toString() + '\0' ).getBytes();
107+
boolean result = false;
108+
SunToolkit.awtLock();
109+
try {
110+
if (!nativeLibraryLoaded) {
111+
throw new IOException("Failed to load native libraries.");
112+
}
113+
result = gnome_url_show(uriByteArray);
114+
} finally {
115+
SunToolkit.awtUnlock();
116+
}
117+
if (!result) {
118+
throw new IOException("Failed to show URI:" + uri);
119+
}
120+
}
121+
122+
private native boolean gnome_url_show(byte[] url);
123+
private static native boolean init(int gtkVersion, boolean verbose);
124+
}

src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -973,18 +973,12 @@ public void ungrab(Window w) {
973973
*/
974974
@Override
975975
public boolean isDesktopSupported() {
976-
if (log.isLoggable(PlatformLogger.Level.FINE)) {
977-
log.fine("Not implemented: WLToolkit.isDesktopSupported()");
978-
}
979-
return false;
976+
return WLDesktopPeer.isDesktopSupported();
980977
}
981978

982979
@Override
983980
public DesktopPeer createDesktopPeer(Desktop target) {
984-
if (log.isLoggable(PlatformLogger.Level.FINE)) {
985-
log.fine("Not implemented: WLToolkit.createDesktopPeer()");
986-
}
987-
return null;
981+
return new WLDesktopPeer();
988982
}
989983

990984
@Override
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2025, JetBrains s.r.o.. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
27+
#ifdef HEADLESS
28+
#error This file should not be included in headless library
29+
#endif
30+
31+
#include <dlfcn.h>
32+
33+
#include <jni.h>
34+
#include <jvm_md.h>
35+
36+
#include "Trace.h"
37+
#include "jni_util.h"
38+
#include "gtk_interface.h"
39+
40+
typedef gboolean (GNOME_URL_SHOW_TYPE)(const char *, void **);
41+
typedef gboolean (GNOME_VFS_INIT_TYPE)(void);
42+
43+
static GNOME_URL_SHOW_TYPE *gnome_url_show = NULL;
44+
45+
static gboolean gnome_load(void) {
46+
void *vfs_handle;
47+
void *gnome_handle;
48+
const char *errmsg;
49+
GNOME_VFS_INIT_TYPE *gnome_vfs_init;
50+
51+
vfs_handle = dlopen(VERSIONED_JNI_LIB_NAME("gnomevfs-2", "0"), RTLD_LAZY);
52+
if (vfs_handle == NULL) {
53+
vfs_handle = dlopen(JNI_LIB_NAME("gnomevfs-2"), RTLD_LAZY);
54+
if (vfs_handle == NULL) {
55+
J2dTraceLn(J2D_TRACE_ERROR, "can not load libgnomevfs-2.so");
56+
return FALSE;
57+
}
58+
}
59+
dlerror(); /* Clear errors */
60+
gnome_vfs_init = dlsym(vfs_handle, "gnome_vfs_init");
61+
if (gnome_vfs_init == NULL){
62+
J2dTraceLn(J2D_TRACE_ERROR, "dlsym( gnome_vfs_init) returned NULL");
63+
return FALSE;
64+
}
65+
if ((errmsg = dlerror()) != NULL) {
66+
J2dTraceLn1(J2D_TRACE_ERROR, "can not find symbol gnome_vfs_init %s", errmsg);
67+
return FALSE;
68+
}
69+
// call gonme_vfs_init()
70+
(*gnome_vfs_init)();
71+
72+
gnome_handle = dlopen(VERSIONED_JNI_LIB_NAME("gnome-2", "0"), RTLD_LAZY);
73+
if (gnome_handle == NULL) {
74+
gnome_handle = dlopen(JNI_LIB_NAME("gnome-2"), RTLD_LAZY);
75+
if (gnome_handle == NULL) {
76+
J2dTraceLn(J2D_TRACE_ERROR, "can not load libgnome-2.so");
77+
return FALSE;
78+
}
79+
}
80+
dlerror(); /* Clear errors */
81+
gnome_url_show = dlsym(gnome_handle, "gnome_url_show");
82+
if ((errmsg = dlerror()) != NULL) {
83+
J2dTraceLn(J2D_TRACE_ERROR, "can not find symble gnome_url_show");
84+
return FALSE;
85+
}
86+
return TRUE;
87+
}
88+
89+
static gboolean gtk_has_been_loaded = FALSE;
90+
static gboolean gnome_has_been_loaded = FALSE;
91+
92+
JNIEXPORT jboolean JNICALL Java_sun_awt_wl_WLDesktopPeer_init
93+
(JNIEnv *env, jclass cls, jint version, jboolean verbose)
94+
{
95+
if (gtk_has_been_loaded || gnome_has_been_loaded) {
96+
return JNI_TRUE;
97+
}
98+
99+
if (gtk_load(env, version, verbose) && gtk->show_uri_load(env)) {
100+
gtk_has_been_loaded = TRUE;
101+
return JNI_TRUE;
102+
} else if (gnome_load()) {
103+
gnome_has_been_loaded = TRUE;
104+
return JNI_TRUE;
105+
}
106+
107+
return JNI_FALSE;
108+
}
109+
110+
JNIEXPORT jboolean JNICALL Java_sun_awt_wl_WLDesktopPeer_gnome_1url_1show
111+
(JNIEnv *env, jobject obj, jbyteArray url_j)
112+
{
113+
gboolean success = FALSE;
114+
const gchar* url_c = (gchar*)(*env)->GetByteArrayElements(env, url_j, NULL);
115+
if (url_c == NULL) {
116+
JNU_ThrowOutOfMemoryError(env, 0);
117+
return JNI_FALSE;
118+
}
119+
120+
if (gtk_has_been_loaded) {
121+
gtk->gdk_threads_enter();
122+
success = gtk->gtk_show_uri_on_window(NULL, url_c, GDK_CURRENT_TIME, NULL);
123+
gtk->gdk_threads_leave();
124+
} else if (gnome_has_been_loaded) {
125+
success = (*gnome_url_show)(url_c, NULL);
126+
}
127+
128+
(*env)->ReleaseByteArrayElements(env, url_j, (jbyte*)url_c, 0);
129+
130+
return success ? JNI_TRUE : JNI_FALSE;
131+
}
132+

0 commit comments

Comments
 (0)