Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 52 additions & 41 deletions jme3-core/src/main/java/com/jme3/system/JmeSystem.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2025 jMonkeyEngine
* Copyright (c) 2009-2026 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -31,9 +31,9 @@
*/
package com.jme3.system;

import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer;
import com.jme3.input.SoftTextDialogInput;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer;
import com.jme3.input.SoftTextDialogInput;

import java.io.File;
import java.io.IOException;
Expand All @@ -48,11 +48,11 @@
import java.util.logging.Logger;

/**
* Utility class to access platform-dependant features.
*/
public class JmeSystem {

private static final Logger logger = Logger.getLogger(JmeSystem.class.getName());
* Utility class to access platform-dependant features.
*/
public class JmeSystem {
private static final Logger logger = Logger.getLogger(JmeSystem.class.getName());

public enum StorageFolderType {
Internal,
Expand All @@ -67,10 +67,10 @@ public enum StorageFolderType {
private JmeSystem() {
}

public static void setSystemDelegate(JmeSystemDelegate systemDelegate) {
JmeSystem.systemDelegate = systemDelegate;
}

public static void setSystemDelegate(JmeSystemDelegate systemDelegate) {
JmeSystem.systemDelegate = systemDelegate;
}
public static synchronized File getStorageFolder() {
return getStorageFolder(StorageFolderType.External);
}
Expand Down Expand Up @@ -120,34 +120,34 @@ public static void setSoftTextDialogInput(SoftTextDialogInput input) {
*
* @param show If true, the keyboard is displayed, if false, the screen is hidden.
*/
public static void showSoftKeyboard(boolean show) {
checkDelegate();
systemDelegate.showSoftKeyboard(show);
}

public static boolean isDeviceRumbleSupported() {
checkDelegate();
return systemDelegate.isDeviceRumbleSupported();
}

public static void rumble(float amount) {
checkDelegate();
systemDelegate.rumble(amount);
}

public static void rumble(float amountHigh, float amountLow, float duration) {
checkDelegate();
systemDelegate.rumble(amountHigh, amountLow, duration);
}

public static void stopRumble() {
checkDelegate();
systemDelegate.stopRumble();
}

public static SoftTextDialogInput getSoftTextDialogInput() {
checkDelegate();
return systemDelegate.getSoftTextDialogInput();
public static void showSoftKeyboard(boolean show) {
checkDelegate();
systemDelegate.showSoftKeyboard(show);
}
public static boolean isDeviceRumbleSupported() {
checkDelegate();
return systemDelegate.isDeviceRumbleSupported();
}
public static void rumble(float amount) {
checkDelegate();
systemDelegate.rumble(amount);
}
public static void rumble(float amountHigh, float amountLow, float duration) {
checkDelegate();
systemDelegate.rumble(amountHigh, amountLow, duration);
}
public static void stopRumble() {
checkDelegate();
systemDelegate.stopRumble();
}
public static SoftTextDialogInput getSoftTextDialogInput() {
checkDelegate();
return systemDelegate.getSoftTextDialogInput();
}

/**
Expand Down Expand Up @@ -190,6 +190,17 @@ public static Platform getPlatform() {
return systemDelegate.getPlatform();
}

/**
* Detects if you are in a Wayland session.
*
* @return {@code true} if you are in a Wayland session, otherwise it will
* be {@code false}
*/
Comment thread
JNightRider marked this conversation as resolved.
public static boolean isWaylandSession() {
checkDelegate();
return systemDelegate.isWaylandSession();
}

public static JmeContext newContext(AppSettings settings, JmeContext.Type contextType) {
checkDelegate();
return systemDelegate.newContext(settings, contextType);
Expand Down
24 changes: 16 additions & 8 deletions jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2021 jMonkeyEngine
* Copyright (c) 2009-2026 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -159,13 +159,13 @@ public boolean isDeviceRumbleSupported() {
return false;
}

@Override
public void rumble(float amountHigh, float amountLow, float duration) {
}

public final AssetManager newAssetManager(URL configFile) {
return new DesktopAssetManager(configFile);
}
@Override
public void rumble(float amountHigh, float amountLow, float duration) {
}
public final AssetManager newAssetManager(URL configFile) {
return new DesktopAssetManager(configFile);
}

public final AssetManager newAssetManager() {
return new DesktopAssetManager(null);
Expand Down Expand Up @@ -309,6 +309,14 @@ public Platform getPlatform() {
}
}

public boolean isWaylandSession() {
// The following matches the test GLFW does to enable the Wayland backend.
if ("wayland".equalsIgnoreCase(System.getenv("XDG_SESSION_TYPE")) && System.getenv("WAYLAND_DISPLAY") != null) {
return true;
}
return false;
}
Comment on lines +312 to +318
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The isWaylandSession() method should be restricted to Linux/FreeBSD platforms to avoid false positives on other platforms (e.g., Windows/macOS where these environment variables might be set in certain environments like WSL or custom shells). Additionally, accessing environment variables via System.getenv() can throw a SecurityException in environments with restricted permissions (such as applets or custom security managers). Wrapping the platform check and environment lookup in a try-catch block makes the detection robust and safe.

    public boolean isWaylandSession() {
        try {
            Platform platform = getPlatform();
            if (platform == Platform.Linux64 || platform == Platform.Linux_ARM64) {
                return "wayland".equalsIgnoreCase(System.getenv("XDG_SESSION_TYPE"))
                        && System.getenv("WAYLAND_DISPLAY") != null;
            }
        } catch (SecurityException | UnsupportedOperationException e) {
            // Safe fallback for restricted environments or unsupported platforms
        }
        return false;
    }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users must first determine which platform they are on and then use this method:

if (JmeSystem.getPlatform().getOs() == Platform.Os.Linux) {
    if (JmeSystem.isWaylandSession()) {
        ...
    }
}

Since isWaylandSession() is not designed to detect the operating system


public String getBuildInfo() {
StringBuilder sb = new StringBuilder();
sb.append("Running on ").append(getFullName()).append("\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.jme3.system.AppSettings;
import com.jme3.system.Displays;
import com.jme3.system.JmeCanvasContext;
import com.jme3.system.JmeSystem;
import com.jme3.system.lwjglx.LwjglxGLPlatform;

import java.awt.AWTException;
Expand Down Expand Up @@ -465,7 +466,7 @@ protected String getCurrentVideoDriver() {
.append('.')
.append(canvas.data.minorVersion);

String driver = isWayland() ? "(XWayland|X11) GLX" : "X11 GLX";
String driver = JmeSystem.isWaylandSession() ? "(XWayland|X11) GLX" : "X11 GLX";

Platform platform = Platform.get();
if (null == platform) {
Expand Down Expand Up @@ -703,14 +704,16 @@ protected void destroyContext() {
*/
@Override
protected void createContext(AppSettings settings) {
if (!settings.isX11PlatformPreferred() && isWayland()) {
boolean linux = Platform.get() == Platform.LINUX ||
Platform.get() == Platform.FREEBSD;
if (!settings.isX11PlatformPreferred() && linux && JmeSystem.isWaylandSession()) {
LOGGER.log(Level.WARNING, "LWJGLX and AWT/Swing only work with X11, so XWayland will be used for GLX.");
}

// HACK: For LWJGLX to work in Wyland, it is necessary to use GLX via
// XWayland, so LWJGL must be forced to load GLX as a native API.
// This is because LWJGLX does not provide an EGL context.
if (isWayland()) {
if (linux && JmeSystem.isWaylandSession()) {
Configuration.OPENGL_CONTEXT_API.set("native");
}

Expand Down
11 changes: 8 additions & 3 deletions jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,15 @@ private int[] getDisplayOrigin() {

private void configureVideoDriverHints(AppSettings settings) {
if (org.lwjgl.system.Platform.get() == org.lwjgl.system.Platform.LINUX) {
boolean isWaylandSession = "wayland".equalsIgnoreCase(System.getenv("XDG_SESSION_TYPE"));

/*
* Determine whether you want to use X11 or Wayland platform drivers.
* This only works if you are in a Wayland session and want to force
* the use of X11 drivers through XWayland.
*/
if (settings.isX11PlatformPreferred()) {
SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "x11");
} else if (isWaylandSession) {
} else if (JmeSystem.isWaylandSession()) {
SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "wayland");
}
}
Expand Down Expand Up @@ -498,7 +503,7 @@ private void configureGLAttributes(AppSettings settings) {
if (org.lwjgl.system.Platform.get() == org.lwjgl.system.Platform.LINUX) {
if (settings.isX11PlatformPreferred()) {
SDL_GL_SetAttribute(SDL_GL_EGL_PLATFORM, EGL_PLATFORM_X11_EXT);
} else if ("wayland".equalsIgnoreCase(System.getenv("XDG_SESSION_TYPE"))) {
} else if (JmeSystem.isWaylandSession()) {
SDL_GL_SetAttribute(SDL_GL_EGL_PLATFORM, EGL_PLATFORM_WAYLAND_EXT);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ public final class LwjglxDefaultGLPlatform {
/**
* Detects if you are in a Wayland session.
*
* @deprecated Use {@link com.jme3.system.JmeSystem#isWaylandSession() }
*
* @return boolean
*/
@Deprecated
public static boolean isWayland() {
Platform platform = Platform.get();
if (platform == LINUX || platform == FREEBSD) {
Expand Down
Loading