Compare commits

...

1 Commits

Author SHA1 Message Date
Maxim Kartashev
1c1122aa13 JBR-6025 Wayland: miscellaneous small improvements 2023-09-06 16:14:38 +04:00
7 changed files with 145 additions and 49 deletions

View File

@@ -363,23 +363,24 @@ public class WLComponentPeer implements ComponentPeer {
WLToolkit.postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_MOVED));
}
synchronized(sizeLock) {
final boolean sizeChanged = this.width != width || this.height != height;
if (sizeChanged) {
Rectangle oldBounds = getVisibleBounds();
final boolean sizeChanged = oldBounds.width != width || oldBounds.height != height;
if (sizeChanged) {
synchronized (sizeLock) {
this.width = width;
this.height = height;
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(String.format("%s is resizing its buffer to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), getBufferScale()));
}
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).revalidate(
getBufferWidth(), getBufferHeight(), getBufferScale());
updateWindowGeometry();
layout();
WLToolkit.postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_RESIZED));
}
postPaintEvent();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(String.format("%s is resizing its buffer to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), getBufferScale()));
}
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).revalidate(
getBufferWidth(), getBufferHeight(), getBufferScale());
updateWindowGeometry();
layout();
WLToolkit.postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_RESIZED));
}
postPaintEvent();
}
public Rectangle getVisibleBounds() {

View File

@@ -73,10 +73,9 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
@Override
public AffineTransform getNormalizingTransform() {
// TODO: may not be able to implement this fully, but we can try
// obtaining physical width/height from wl_output.geometry event.
// Those may be 0, of course.
return getDefaultTransform();
double xScale = device.getResolutionX(this) / 72.0;
double yScale = device.getResolutionY(this) / 72.0;
return new AffineTransform(xScale, 0.0, 0.0, yScale, 0.0, 0.0);
}
@Override

View File

@@ -31,6 +31,7 @@ import sun.java2d.vulkan.WLVKGraphicsConfig;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Window;
@@ -39,6 +40,7 @@ import java.awt.Window;
* in the multi-monitor setup. Whenever those change, this device is re-created.
*/
public class WLGraphicsDevice extends GraphicsDevice {
private static final double MM_IN_INCH = 25.4;
/**
* ID of the corresponding wl_output object received from Wayland.
*/
@@ -60,16 +62,21 @@ public class WLGraphicsDevice extends GraphicsDevice {
*/
private volatile int y; // only changes when the device gets invalidated
private final int widthMm;
private final int heightMm;
// Configs are always the same in size and scale
private volatile WLGraphicsConfig[] configs = null;
private volatile GraphicsConfiguration[] configs = null;
// The default config is an object from the configs array
private volatile WLGraphicsConfig defaultConfig = null;
private WLGraphicsDevice(int id, int x, int y) {
private WLGraphicsDevice(int id, int x, int y, int widthMm, int heightMm) {
this.wlID = id;
this.x = x;
this.y = y;
this.widthMm = widthMm;
this.heightMm = heightMm;
}
int getID() {
@@ -77,23 +84,30 @@ public class WLGraphicsDevice extends GraphicsDevice {
}
void updateConfiguration(String name, int width, int height, int scale) {
this.name = name == null ? "wl_output." + wlID : name;
this.name = name;
if (configs == null || configs[0].differsFrom(width, height, scale)) {
WLGraphicsConfig config = defaultConfig;
// Note that all configs are of equal size and scale
if (config == null || config.differsFrom(width, height, scale)) {
GraphicsConfiguration[] newConfigs;
WLGraphicsConfig newDefaultConfig;
// It is necessary to create a new object whenever config changes as its
// identity is used to detect changes in scale, among other things.
if (WLGraphicsEnvironment.isVulkanEnabled()) {
defaultConfig = WLVKGraphicsConfig.getConfig(this, width, height, scale);
configs = new WLGraphicsConfig[1];
configs[0] = defaultConfig;
newDefaultConfig = WLVKGraphicsConfig.getConfig(this, width, height, scale);
newConfigs = new GraphicsConfiguration[1];
newConfigs[0] = newDefaultConfig;
} else {
// TODO: Actually, Wayland may support a lot more shared memory buffer configurations, need to
// subscribe to the wl_shm:format event and get the list from there.
defaultConfig = WLSMGraphicsConfig.getConfig(this, width, height, scale, false);
configs = new WLGraphicsConfig[2];
configs[0] = defaultConfig;
configs[1] = WLSMGraphicsConfig.getConfig(this, width, height, scale, true);
newDefaultConfig = WLSMGraphicsConfig.getConfig(this, width, height, scale, false);
newConfigs = new GraphicsConfiguration[2];
newConfigs[0] = newDefaultConfig;
newConfigs[1] = WLSMGraphicsConfig.getConfig(this, width, height, scale, true);
}
configs = newConfigs;
defaultConfig = newDefaultConfig;
}
}
@@ -107,13 +121,17 @@ public class WLGraphicsDevice extends GraphicsDevice {
this.x = similarDevice.x;
this.y = similarDevice.y;
final int newScale = similarDevice.getScale();
final Rectangle newBounds = similarDevice.defaultConfig.getBounds();
int newScale = similarDevice.getScale();
Rectangle newBounds = similarDevice.defaultConfig.getBounds();
updateConfiguration(similarDevice.name, newBounds.width, newBounds.height, newScale);
}
public static WLGraphicsDevice createWithConfiguration(int id, String name, int x, int y, int width, int height, int scale) {
final WLGraphicsDevice device = new WLGraphicsDevice(id, x, y);
public static WLGraphicsDevice createWithConfiguration(int id, String name,
int x, int y,
int width, int height,
int widthMm, int heightMm,
int scale) {
WLGraphicsDevice device = new WLGraphicsDevice(id, x, y, widthMm, heightMm);
device.updateConfiguration(name, width, height, scale);
return device;
}
@@ -127,11 +145,17 @@ public class WLGraphicsDevice extends GraphicsDevice {
}
boolean hasSameNameAs(WLGraphicsDevice otherDevice) {
return name != null && otherDevice.name != null && name.equals(otherDevice.name);
var localName = name;
var otherName = otherDevice.name;
return localName != null && localName.equals(otherName);
}
boolean hasSameSizeAs(WLGraphicsDevice modelDevice) {
return defaultConfig != null && modelDevice.defaultConfig != null && defaultConfig.getBounds().equals(modelDevice.defaultConfig.getBounds());
var config = defaultConfig;
var modelConfig = modelDevice.defaultConfig;
return config != null
&& modelConfig != null
&& config.getBounds().equals(modelConfig.getBounds());
}
@Override
@@ -163,6 +187,27 @@ public class WLGraphicsDevice extends GraphicsDevice {
return defaultConfig.getScale();
}
int getResolution() {
Rectangle bounds = defaultConfig.getBounds();
if (bounds.width == 0 || bounds.height == 0) return 0;
double diagonalPixel = Math.sqrt(bounds.width * bounds.width + bounds.height * bounds.height);
double diagonalMm = Math.sqrt(widthMm * widthMm + heightMm * heightMm);
return (int) (diagonalPixel / diagonalMm * MM_IN_INCH);
}
int getResolutionX(WLGraphicsConfig config) {
Rectangle bounds = config.getBounds();
if (bounds.width == 0) return 0;
return (int)((double)bounds.width / widthMm * MM_IN_INCH);
}
int getResolutionY(WLGraphicsConfig config) {
Rectangle bounds = config.getBounds();
if (bounds.height == 0) return 0;
return (int)((double)bounds.height / heightMm * MM_IN_INCH);
}
@Override
public boolean isFullScreenSupported() {
return true;
@@ -211,8 +256,13 @@ public class WLGraphicsDevice extends GraphicsDevice {
@Override
public String toString() {
return String.format("WLGraphicsDevice: id=%d at (%d, %d) with %s",
wlID, x, y,
defaultConfig != null ? defaultConfig : "<no configs>");
var config = defaultConfig;
return String.format("WLGraphicsDevice: '%s' id=%d at (%d, %d) with %s",
name, wlID, x, y,
config != null ? config : "<no configs>");
}
public Insets getInsets() {
return new Insets(0, 0, 0, 0);
}
}

View File

@@ -59,6 +59,9 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
if (log.isLoggable(Level.FINE)) {
log.fine("Vulkan rendering enabled: " + (vulkanEnabled?"YES":"NO"));
}
// Make sure the toolkit is loaded because otherwise this GE is going to be empty
WLToolkit.isInitialized();
}
private static native boolean initVKWL();
@@ -100,7 +103,8 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
private final List<WLGraphicsDevice> devices = new ArrayList<>(5);
private void notifyOutputConfigured(String name, int wlID, int x, int y, int width, int height,
private void notifyOutputConfigured(String name, String make, String model, int wlID,
int x, int y, int width, int height, int widthMm, int heightMm,
int subpixel, int transform, int scale) {
// Called from native code whenever a new output appears or an existing one changes its properties
// NB: initially called during WLToolkit.initIDs() on the main thread; later on EDT.
@@ -108,6 +112,10 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
log.fine(String.format("Output configured id=%d at (%d, %d) %dx%d %dx scale", wlID, x, y, width, height, scale));
}
String humanID =
(name != null ? name + " " : "")
+ (make != null ? make + " " : "")
+ (model != null ? model : "");
synchronized (devices) {
boolean newOutput = true;
for (int i = 0; i < devices.size(); i++) {
@@ -115,9 +123,10 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
if (gd.getID() == wlID) {
newOutput = false;
if (gd.isSameDeviceAs(wlID, x, y)) {
gd.updateConfiguration(name, width, height, scale);
gd.updateConfiguration(humanID, width, height, scale);
} else {
final WLGraphicsDevice updatedDevice = WLGraphicsDevice.createWithConfiguration(wlID, name, x, y, width, height, scale);
final WLGraphicsDevice updatedDevice = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
x, y, width, height, widthMm, heightMm, scale);
devices.set(i, updatedDevice);
gd.invalidate(updatedDevice);
}
@@ -125,7 +134,8 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
}
}
if (newOutput) {
final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, name, x, y, width, height, scale);
final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, humanID, x, y,
width, height, widthMm, heightMm, scale);
devices.add(gd);
}
}

View File

@@ -35,7 +35,7 @@ public class WLKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
@Override
public void setCurrentFocusOwner(Component comp) {
if (comp != currentFocusedWindow) {
if (comp != null && comp != currentFocusedWindow) {
// In Wayland, only Window can be focused, not any widget in it.
focusLog.severe("Unexpected focus owner set in a Window: " + comp);
}

View File

@@ -234,7 +234,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
* the next click is considered separate and not part of multi-click event.
* @return maximum milliseconds between same mouse button clicks for them to be a multiclick
*/
static long getMulticlickTime() {
static int getMulticlickTime() {
/* TODO: get from the system somehow */
return AWT_MULTICLICK_DEFAULT_TIME_MS;
}
@@ -814,8 +814,8 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
@Override
public int getScreenResolution() {
// TODO
return 150;
var defaultScreen = (WLGraphicsDevice)WLGraphicsEnvironment.getSingleInstance().getDefaultScreenDevice();
return defaultScreen.getResolution();
}
/**
@@ -855,8 +855,14 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
protected void initializeDesktopProperties() {
super.initializeDesktopProperties();
desktopProperties.put("DnD.Autoscroll.initialDelay", 50);
desktopProperties.put("DnD.Autoscroll.interval", 50);
desktopProperties.put("DnD.Autoscroll.cursorHysteresis", 5);
desktopProperties.put("Shell.shellFolderManager", "sun.awt.shell.ShellFolderManager");
if (!GraphicsEnvironment.isHeadless()) {
desktopProperties.put("awt.mouse.numButtons", MOUSE_BUTTONS_COUNT);
desktopProperties.put("awt.multiClickInterval", getMulticlickTime());
desktopProperties.put("awt.mouse.numButtons", getNumberOfButtons());
}
}
@@ -996,6 +1002,17 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
flushImpl();
}
@Override
public Insets getScreenInsets(final GraphicsConfiguration gc) {
final GraphicsDevice gd = gc.getDevice();
if (gd instanceof WLGraphicsDevice device) {
Insets insets = device.getInsets();
return (Insets) insets.clone();
} else {
return super.getScreenInsets(gc);
}
}
private native int readEvents();
private native void dispatchEventsOnEDT();
private native void flushImpl();

View File

@@ -43,11 +43,15 @@ typedef struct WLOutput {
int32_t y;
int32_t width;
int32_t height;
int32_t width_mm;
int32_t height_mm;
uint32_t subpixel;
uint32_t transform;
uint32_t scale;
char * make;
char * model;
char * name;
} WLOutput;
@@ -79,6 +83,10 @@ wl_output_geometry(
output->y = y;
output->subpixel = subpixel;
output->transform = transform;
output->width_mm = physical_width;
output->height_mm = physical_height;
output->make = make != NULL ? strdup(make) : NULL;
output->model = model != NULL ? strdup(model) : NULL;
}
static void
@@ -138,16 +146,25 @@ wl_output_done(
JNIEnv *env = getEnv();
jobject obj = (*env)->CallStaticObjectMethod(env, geClass, getSingleInstanceMID);
JNU_CHECK_EXCEPTION(env);
CHECK_NULL_THROW_IE(env, obj, "WLGraphicsEnvironment.getSingleInstance() returned null");
jstring outputName = output->name ? JNU_NewStringPlatform(env, output->name) : NULL;
jstring name = output->name ? JNU_NewStringPlatform(env, output->name) : NULL;
JNU_CHECK_EXCEPTION(env);
jstring make = output->make ? JNU_NewStringPlatform(env, output->make) : NULL;
JNU_CHECK_EXCEPTION(env);
jstring model = output->model ? JNU_NewStringPlatform(env, output->model) : NULL;
JNU_CHECK_EXCEPTION(env);
(*env)->CallVoidMethod(env, obj, notifyOutputConfiguredMID,
outputName,
name,
make,
model,
output->id,
output->x,
output->y,
output->width,
output->height,
output->width_mm,
output->height_mm,
(jint)output->subpixel,
(jint)output->transform,
(jint)output->scale);
@@ -182,7 +199,7 @@ WLGraphicsEnvironment_initIDs
CHECK_NULL_RETURN(
notifyOutputConfiguredMID = (*env)->GetMethodID(env, clazz,
"notifyOutputConfigured",
"(Ljava/lang/String;IIIIIIII)V"),
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIII)V"),
JNI_FALSE);
CHECK_NULL_RETURN(
notifyOutputDestroyedMID = (*env)->GetMethodID(env, clazz,
@@ -221,6 +238,8 @@ WLOutputDeregister(struct wl_registry *wl_registry, uint32_t id)
wl_output_destroy(cur->wl_output);
WLOutput * next = cur->next;
free(cur->name);
free(cur->make);
free(cur->model);
free(cur);
cur = next;
} else {