diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java b/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java index cbbe43c12dfe..1ff5a1b411ef 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java @@ -76,6 +76,8 @@ import java.util.Objects; import java.util.function.Supplier; +import static sun.awt.wl.WLGraphicsConfig.SCALE120; + public class WLComponentPeer implements ComponentPeer { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLComponentPeer"); private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.wl.focus.WLComponentPeer"); @@ -119,9 +121,12 @@ public class WLComponentPeer implements ComponentPeer { boolean visible = false; private final Object dataLock = new Object(); - int width; // in native pixels, protected by dataLock - int height; // in native pixels, protected by dataLock - int wlBufferScale; // protected by dataLock + int javaWidth; // in java coordinates, protected by dataLock + int javaHeight; // in java coordinates, protected by dataLock + int surfaceWidth; // in surface coordinates, protected by dataLock + int surfaceHeight; // in surface coordinates, protected by dataLock + long scale120; // protected by dataLock + Long preferredScale120 = null; // protected by dataLock double effectiveScale; // protected by dataLock static { @@ -135,31 +140,33 @@ public class WLComponentPeer implements ComponentPeer { this.target = target; this.background = target.getBackground(); Dimension size = constrainSize(target.getBounds().getSize()); - width = size.width; - height = size.height; + javaWidth = size.width; + javaHeight = size.height; final WLGraphicsConfig config = (WLGraphicsConfig)target.getGraphicsConfiguration(); - wlBufferScale = config.getWlScale(); + scale120 = config.getWlScale120(); effectiveScale = config.getEffectiveScale(); surfaceData = config.createSurfaceData(this); nativePtr = nativeCreateFrame(); paintArea = new WLRepaintArea(); + surfaceWidth = Math.max(javaUnitsToSurfaceUnits(javaWidth), 1); + surfaceHeight = Math.max(javaUnitsToSurfaceUnits(javaHeight), 1); if (log.isLoggable(Level.FINE)) { - log.fine("WLComponentPeer: target=" + target + " with size=" + width + "x" + height); + log.fine("WLComponentPeer: target=" + target + " with size=" + javaWidth + "x" + javaHeight); } // TODO // setup parent window for target } - public int getWidth() { + public int getJavaWidth() { synchronized (dataLock) { - return width; + return javaWidth; } } - public int getHeight() { + public int getJavaHeight() { synchronized (dataLock) { - return height; + return javaHeight; } } @@ -181,7 +188,7 @@ public void postPaintEvent(int x, int y, int w, int h) { void postPaintEvent() { if (isVisible()) { - postPaintEvent(0, 0, getWidth(), getHeight()); + postPaintEvent(0, 0, getJavaWidth(), getJavaHeight()); } } @@ -268,8 +275,11 @@ protected void wlSetVisible(boolean v) { if (v) { String title = getTitle(); boolean isWlPopup = targetIsWlPopup(); - int thisWidth = javaUnitsToSurfaceUnits(getWidth()); - int thisHeight = javaUnitsToSurfaceUnits(getHeight()); + int thisWidth, thisHeight; + synchronized (dataLock) { + thisWidth = surfaceWidth; + thisHeight = surfaceHeight; + } boolean isModal = targetIsModal(); int state = (target instanceof Frame frame) @@ -354,14 +364,15 @@ private boolean targetIsModal() { } void updateSurfaceData() { + // The scale parameter is ignored. SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).revalidate( - getBufferWidth(), getBufferHeight(), getBufferScale()); + getBufferWidth(), getBufferHeight(), 1); updateWindowGeometry(); } void configureWLSurface() { if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine(String.format("%s is configured to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), getBufferScale())); + log.fine(String.format("%s is configured to %dx%d with %fx scale", this, getBufferWidth(), getBufferHeight(), getWlScale())); } updateSurfaceData(); } @@ -471,8 +482,8 @@ public void setBounds(int newX, int newY, int newWidth, int newHeight, int op) { if (sizeChanged) { setSizeTo(newSize.width, newSize.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())); + log.fine(String.format("%s is resizing its buffer to %dx%d with %fx scale", + this, getBufferWidth(), getBufferHeight(), getWlScale())); } updateSurfaceData(); layout(); @@ -485,18 +496,25 @@ public void setBounds(int newX, int newY, int newWidth, int newHeight, int op) { private void setSizeTo(int newWidth, int newHeight) { Dimension newSize = constrainSize(newWidth, newHeight); + final int surfaceWidth = Math.max(javaUnitsToSurfaceUnits(newSize.width), 1); + final int surfaceHeight = Math.max(javaUnitsToSurfaceUnits(newSize.height), 1); performLocked(() -> { - nativeSetSurfaceSize(nativePtr, javaUnitsToSurfaceUnits(newSize.width), javaUnitsToSurfaceUnits(newSize.height)); + nativeSetSurfaceSize(nativePtr, surfaceWidth, surfaceHeight); }); synchronized (dataLock) { - this.width = newSize.width; - this.height = newSize.height; + this.javaWidth = newSize.width; + this.javaHeight = newSize.height; + this.surfaceWidth = surfaceWidth; + this.surfaceHeight = surfaceHeight; } } private void repositionWlPopup(int newX, int newY) { - final int thisWidth = getWidth(); - final int thisHeight = getHeight(); + final int thisWidth, thisHeight; + synchronized (dataLock) { + thisWidth = surfaceWidth; + thisHeight = surfaceHeight; + } performLocked(() -> { Window popup = (Window) target; final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup); @@ -523,32 +541,28 @@ private void repositionWlPopup(int newX, int newY) { public Rectangle getVisibleBounds() { synchronized(dataLock) { - return new Rectangle(0, 0, width, height); + return new Rectangle(0, 0, javaWidth, javaHeight); } } - /** - * Represents the scale ratio of Wayland's backing buffer in pixel units - * to surface units. Wayland events are generated in surface units, while - * painting should be performed in pixel units. - * The ratio is enforced with nativeSetSize(). - */ - int getBufferScale() { + private double getWlScale() { synchronized(dataLock) { - return wlBufferScale; + return (double)scale120 / SCALE120; } } - public int getBufferWidth() { + private int getBufferSize(int size) { synchronized (dataLock) { - return (int)(width * effectiveScale); + return (int)((size * scale120 + SCALE120 / 2) / SCALE120); } } + public int getBufferWidth() { + return getBufferSize(surfaceWidth); + } + public int getBufferHeight() { - synchronized (dataLock) { - return (int)(height * effectiveScale); - } + return getBufferSize(surfaceHeight); } public Rectangle getBufferBounds() { @@ -566,8 +580,8 @@ private void updateWindowGeometry() { Rectangle nativeVisibleBounds = getVisibleBounds(); nativeVisibleBounds.x = javaUnitsToSurfaceUnits(nativeVisibleBounds.x); nativeVisibleBounds.y = javaUnitsToSurfaceUnits(nativeVisibleBounds.y); - nativeVisibleBounds.width = javaUnitsToSurfaceUnits(nativeVisibleBounds.width); - nativeVisibleBounds.height = javaUnitsToSurfaceUnits(nativeVisibleBounds.height); + nativeVisibleBounds.width = Math.max(javaUnitsToSurfaceUnits(nativeVisibleBounds.width), 1); + nativeVisibleBounds.height = Math.max(javaUnitsToSurfaceUnits(nativeVisibleBounds.height), 1); performLocked(() -> nativeSetWindowGeometry(nativePtr, nativeVisibleBounds.x, nativeVisibleBounds.y, nativeVisibleBounds.width, nativeVisibleBounds.height)); @@ -831,7 +845,7 @@ private void updateCursorImmediately(WLInputState inputState) { WLComponentPeer peer = inputState.getPeer(); if (peer == null) return; Cursor cursor = peer.getCursor(inputState.getPointerX(), inputState.getPointerY()); - setCursor(cursor, getGraphicsDevice() != null ? getGraphicsDevice().getWlScale() : 1); + setCursor(cursor, (int)((scale120 + SCALE120 - 1) / SCALE120)); } Cursor getCursor(int x, int y) { @@ -942,16 +956,16 @@ public void applyShape(Region shape) { @Override public boolean updateGraphicsData(GraphicsConfiguration gc) { - final int newWlScale = ((WLGraphicsConfig)gc).getWlScale(); + final long newScale120 = ((WLGraphicsConfig)gc).getWlScale120(); WLGraphicsDevice gd = ((WLGraphicsConfig) gc).getDevice(); gd.addWindow(this); synchronized (dataLock) { - if (newWlScale != wlBufferScale) { - wlBufferScale = newWlScale; + if (newScale120 != scale120) { + scale120 = newScale120; effectiveScale = ((WLGraphicsConfig)gc).getEffectiveScale(); if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine(String.format("%s is updating buffer to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), wlBufferScale)); + log.fine(String.format("%s is updating buffer to %dx%d with %fx scale", this, getBufferWidth(), getBufferHeight(), getWlScale())); } updateSurfaceData(); postPaintEvent(); @@ -1185,7 +1199,7 @@ int surfaceUnitsToJavaUnits(int value) { return value; } else { synchronized (dataLock) { - return (int)(value * wlBufferScale / effectiveScale); + return (int)(value * scale120 / (effectiveScale * SCALE120)); } } } @@ -1199,7 +1213,7 @@ int javaUnitsToSurfaceUnits(int value) { return value; } else { synchronized (dataLock) { - return (int)(value * effectiveScale / wlBufferScale); + return (int)(value * effectiveScale * SCALE120 / scale120); } } } @@ -1285,8 +1299,17 @@ void notifyPopupDone() { WLToolkit.postEvent(new WindowEvent((Window) target, WindowEvent.WINDOW_CLOSING)); } + void notifyPreferredScale(long scale120) { + synchronized (dataLock) { + if (preferredScale120 == null || preferredScale120 != scale120) { + preferredScale120 = scale120; + checkIfOnNewScreen(); + } + } + } + private WLGraphicsDevice getGraphicsDevice() { - int scale = 0; + long scale120 = 0; WLGraphicsDevice theDevice = null; // AFAIK there's no way of knowing which WLGraphicsDevice is displaying // the largest portion of this component, so choose the first in the ordered list @@ -1295,8 +1318,8 @@ private WLGraphicsDevice getGraphicsDevice() { // Wayland's output and are removed as soon as we have left. synchronized (devices) { for (WLGraphicsDevice gd : devices) { - if (gd.getWlScale() > scale) { - scale = gd.getWlScale(); + if (gd.getWlScale120() > scale120) { + scale120 = gd.getWlScale120(); theDevice = gd; } } @@ -1308,7 +1331,7 @@ private WLGraphicsDevice getGraphicsDevice() { private void checkIfOnNewScreen() { final WLGraphicsDevice newDevice = getGraphicsDevice(); if (newDevice != null) { // could be null when screens are being reconfigured - final GraphicsConfiguration gc = newDevice.getDefaultConfiguration(); + final WLGraphicsConfig gc = (WLGraphicsConfig) newDevice.getDefaultConfiguration(); if (log.isLoggable(Level.FINE)) { log.fine(this + " is on (possibly) new device " + newDevice); } @@ -1318,8 +1341,12 @@ private void checkIfOnNewScreen() { newDevice.addWindow(this); } performUnlocked(() -> { + WLGraphicsConfig gcEffective = gc; + if (preferredScale120 != null) { + gcEffective = gc.withScale120(preferredScale120); + } var acc = AWTAccessor.getComponentAccessor(); - acc.setGraphicsConfiguration(target, gc); + acc.setGraphicsConfiguration(target, gcEffective); }); } } diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLFrameDecoration.java b/src/java.desktop/unix/classes/sun/awt/wl/WLFrameDecoration.java index f459160a5291..27d06482a04a 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLFrameDecoration.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLFrameDecoration.java @@ -102,7 +102,7 @@ public Insets getInsets() { public Rectangle getBounds() { return isUndecorated ? new Rectangle(0, 0, 0, 0) - : new Rectangle(0, 0, peer.getWidth(), HEIGHT); + : new Rectangle(0, 0, peer.getJavaWidth(), HEIGHT); } public Dimension getMinimumSize() { @@ -120,19 +120,19 @@ private boolean hasMaximizeButton() { } private Point getCloseButtonCenter() { - int width = peer.getWidth(); + int width = peer.getJavaWidth(); return width >= HEIGHT ? new Point(width - HEIGHT / 2, HEIGHT / 2) : null; } private Point getMaximizeButtonCenter() { if (!hasMaximizeButton()) return null; - int width = peer.getWidth(); + int width = peer.getJavaWidth(); return width >= 2 * HEIGHT ? new Point(width - HEIGHT * 3 / 2, HEIGHT / 2) : null; } private Point getMinimizeButtonCenter() { if (!hasMinimizeButton()) return null; - int width = peer.getWidth(); + int width = peer.getJavaWidth(); int buttonSpaceWidth = getButtonSpaceWidth(); return width >= buttonSpaceWidth ? new Point(width - buttonSpaceWidth + HEIGHT / 2, HEIGHT / 2) : null; } @@ -147,8 +147,8 @@ private int getButtonSpaceWidth() { public void paint(final Graphics g) { if (isUndecorated) return; - int width = peer.getWidth(); - int height = peer.getHeight(); + int width = peer.getJavaWidth(); + int height = peer.getJavaHeight(); if (width <= 0 || height <= 0) return; Graphics2D g2d = (Graphics2D) g.create(0, 0, width, HEIGHT); try { @@ -160,7 +160,7 @@ public void paint(final Graphics g) { } private void doPaint(Graphics2D g) { - int width = peer.getWidth(); + int width = peer.getJavaWidth(); String title = peer.getTitle(); Color foregroundColor = active ? ACTIVE_FOREGROUND : INACTIVE_FOREGROUND; @@ -265,7 +265,7 @@ private boolean pressedInDragStartArea() { pressedLocation.y >= 0 && pressedLocation.y < HEIGHT && pressedLocation.x >= 0 && - pressedLocation.x < peer.getWidth() - getButtonSpaceWidth(); + pressedLocation.x < peer.getJavaWidth() - getButtonSpaceWidth(); } boolean processMouseEvent(MouseEvent e) { @@ -334,12 +334,12 @@ private int getResizeEdges(int x, int y) { int edges = 0; if (x < RESIZE_EDGE_THICKNESS) { edges |= XDG_TOPLEVEL_RESIZE_EDGE_LEFT; - } else if (x > peer.getWidth() - RESIZE_EDGE_THICKNESS) { + } else if (x > peer.getJavaWidth() - RESIZE_EDGE_THICKNESS) { edges |= XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; } if (y < RESIZE_EDGE_THICKNESS) { edges |= XDG_TOPLEVEL_RESIZE_EDGE_TOP; - } else if (y > peer.getHeight() - RESIZE_EDGE_THICKNESS) { + } else if (y > peer.getJavaHeight() - RESIZE_EDGE_THICKNESS) { edges |= XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; } return edges; diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java b/src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java index 292a46c6574d..09caa68c597a 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java @@ -152,8 +152,8 @@ public void toBack() { @Override void notifyConfigured(int newXNative, int newYNative, int newWidthNative, int newHeightNative, boolean active, boolean maximized) { - int widthBefore = getWidth(); - int heightBefore = getHeight(); + int widthBefore = getJavaWidth(); + int heightBefore = getJavaHeight(); super.notifyConfigured(newXNative, newYNative, newWidthNative, newHeightNative, active, maximized); diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsConfig.java b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsConfig.java index 9358f813c2fd..aef033d2fc2c 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsConfig.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsConfig.java @@ -36,22 +36,24 @@ import sun.java2d.loops.SurfaceType; public abstract class WLGraphicsConfig extends GraphicsConfiguration { - private final WLGraphicsDevice device; - private final int width; - private final int height; - private final int wlScale; // as reported by Wayland + public final static long SCALE120 = 120; + + protected final WLGraphicsDevice device; + protected final int width; + protected final int height; + private final long wlScale120; // as reported by Wayland private final double effectiveScale; // as enforced by Java - protected WLGraphicsConfig(WLGraphicsDevice device, int width, int height, int wlScale) { + protected WLGraphicsConfig(WLGraphicsDevice device, int width, int height, long scale120) { this.device = device; this.width = width; this.height = height; - this.wlScale = wlScale; - this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom(wlScale); + this.wlScale120 = scale120; + this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom((double)scale120 / SCALE120); } - boolean differsFrom(int width, int height, int scale) { - return width != this.width || height != this.height || scale != this.wlScale; + boolean differsFrom(int width, int height, long scale120) { + return width != this.width || height != this.height || scale120 != this.wlScale120; } @Override @@ -89,14 +91,14 @@ public Rectangle getBounds() { } /** - * Returns the preferred Wayland buffer scale for this display configuration. + * Returns the wayland scale in base 1/120. */ - public int getWlScale() { - return wlScale; + public long getWlScale120() { + return wlScale120; } /** - * Returns the effective scale, which can differ from the buffer scale + * Returns the effective scale, which can differ from the wayland scale * if overridden with the sun.java2d.uiScale system property. */ public double getEffectiveScale() { @@ -105,9 +107,10 @@ public double getEffectiveScale() { public abstract SurfaceType getSurfaceType(); public abstract SurfaceData createSurfaceData(WLComponentPeer peer); + public abstract WLGraphicsConfig withScale120(long scale120); @Override public String toString() { - return String.format("%dx%d %dx scale", width, height, wlScale); + return String.format("%dx%d %fx scale", width, height, (double) wlScale120 / SCALE120); } } diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsDevice.java index 608f8a5cc012..5c3fb08658f7 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsDevice.java @@ -89,27 +89,27 @@ int getID() { return wlID; } - void updateConfiguration(String name, int width, int height, int scale) { + void updateConfiguration(String name, int width, int height, long scale120) { this.name = name; WLGraphicsConfig config = defaultConfig; // Note that all configs are of equal size and scale - if (config == null || config.differsFrom(width, height, scale)) { + if (config == null || config.differsFrom(width, height, scale120)) { 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()) { - newDefaultConfig = WLVKGraphicsConfig.getConfig(this, width, height, scale); + newDefaultConfig = WLVKGraphicsConfig.getConfig(this, width, height, scale120); 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. - newDefaultConfig = WLSMGraphicsConfig.getConfig(this, width, height, scale, false); + newDefaultConfig = WLSMGraphicsConfig.getConfig(this, width, height, scale120, false); newConfigs = new GraphicsConfiguration[2]; newConfigs[0] = newDefaultConfig; - newConfigs[1] = WLSMGraphicsConfig.getConfig(this, width, height, scale, true); + newConfigs[1] = WLSMGraphicsConfig.getConfig(this, width, height, scale120, true); } configs = newConfigs; @@ -145,18 +145,18 @@ void invalidate(WLGraphicsDevice similarDevice) { this.x = similarDevice.x; this.y = similarDevice.y; - int newScale = similarDevice.getWlScale(); + long newScale120 = similarDevice.getWlScale120(); Rectangle newBounds = similarDevice.defaultConfig.getBounds(); - updateConfiguration(similarDevice.name, newBounds.width, newBounds.height, newScale); + updateConfiguration(similarDevice.name, newBounds.width, newBounds.height, newScale120); } public static WLGraphicsDevice createWithConfiguration(int id, String name, int x, int y, int width, int height, int widthMm, int heightMm, - int scale) { + long scale120) { WLGraphicsDevice device = new WLGraphicsDevice(id, x, y, widthMm, heightMm); - device.updateConfiguration(name, width, height, scale); + device.updateConfiguration(name, width, height, scale120); return device; } @@ -207,8 +207,8 @@ public GraphicsConfiguration getDefaultConfiguration() { return defaultConfig; } - int getWlScale() { - return defaultConfig.getWlScale(); + long getWlScale120() { + return defaultConfig.getWlScale120(); } int getResolution() { diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsEnvironment.java b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsEnvironment.java index d7c3fe1639c2..fb68a07484a7 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsEnvironment.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLGraphicsEnvironment.java @@ -128,11 +128,11 @@ public boolean isDisplayLocal() { 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) { + int subpixel, int transform, long scale120) { // 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. if (log.isLoggable(Level.FINE)) { - log.fine(String.format("Output configured id=%d at (%d, %d) %dx%d %dx scale", wlID, x, y, width, height, scale)); + log.fine(String.format("Output configured id=%d at (%d, %d) %dx%d %fx scale", wlID, x, y, width, height, scale120 / 120.0)); } String humanID = @@ -147,10 +147,10 @@ private void notifyOutputConfigured(String name, String make, String model, int newOutput = false; if (gd.isSameDeviceAs(wlID, x, y)) { // These coordinates and the size are not scaled. - gd.updateConfiguration(humanID, width, height, scale); + gd.updateConfiguration(humanID, width, height, scale120); } else { final WLGraphicsDevice updatedDevice = WLGraphicsDevice.createWithConfiguration(wlID, humanID, - x, y, width, height, widthMm, heightMm, scale); + x, y, width, height, widthMm, heightMm, scale120); devices.set(i, updatedDevice); gd.invalidate(updatedDevice); } @@ -159,7 +159,7 @@ private void notifyOutputConfigured(String name, String make, String model, int } if (newOutput) { final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, humanID, x, y, - width, height, widthMm, heightMm, scale); + width, height, widthMm, heightMm, scale120); devices.add(gd); } } @@ -253,7 +253,7 @@ private void updateTotalDisplayBounds() { } } - static double effectiveScaleFrom(int displayScale) { + static double effectiveScaleFrom(double displayScale) { return debugScaleEnabled ? SunGraphicsEnvironment.getDebugScale() : displayScale; } diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLInputState.java b/src/java.desktop/unix/classes/sun/awt/wl/WLInputState.java index c5904eac617f..15dfd6c891ef 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLInputState.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLInputState.java @@ -266,9 +266,9 @@ public boolean isPointerOverPeer() { WLComponentPeer peer = getPeer(); if (peer != null) { return x >= 0 - && x < peer.getWidth() + && x < peer.getJavaWidth() && y >= 0 - && y < peer.getHeight(); + && y < peer.getJavaHeight(); } } return true; diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLSMGraphicsConfig.java b/src/java.desktop/unix/classes/sun/awt/wl/WLSMGraphicsConfig.java index b02009716d1b..0f8235e5aea9 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLSMGraphicsConfig.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLSMGraphicsConfig.java @@ -55,9 +55,9 @@ public class WLSMGraphicsConfig extends WLGraphicsConfig { private WLSMGraphicsConfig(WLGraphicsDevice device, int width, int height, - int scale, + long scale120, boolean translucencyCapable) { - super(device, width, height, scale); + super(device, width, height, scale120); this.translucencyCapable = translucencyCapable; this.colorModel = colorModelFor(translucencyCapable ? Transparency.TRANSLUCENT : Transparency.OPAQUE); // Note: GNOME Shell definitely expects alpha values to be pre-multiplied @@ -67,9 +67,9 @@ private WLSMGraphicsConfig(WLGraphicsDevice device, public static WLSMGraphicsConfig getConfig(WLGraphicsDevice device, int width, int height, - int scale, + long scale120, boolean translucencyCapable) { - var newConfig = new WLSMGraphicsConfig(device, width, height, scale, translucencyCapable); + var newConfig = new WLSMGraphicsConfig(device, width, height, scale120, translucencyCapable); if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("New shared memory config " + newConfig); } @@ -110,6 +110,11 @@ public SurfaceData createSurfaceData(WLComponentPeer peer) { return WLSMSurfaceData.createData(peer, this); } + @Override + public WLGraphicsConfig withScale120(long scale120) { + return new WLSMGraphicsConfig(device, width, height, scale120, translucencyCapable); + } + public int getWlShmFormat() { // The value is one of enum wl_shm_format from wayland-client-protocol.h return translucencyCapable ? WL_SHM_FORMAT_ARGB8888 : WL_SHM_FORMAT_XRGB8888; diff --git a/src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java index dc6b239ec3ea..946bd12a1f12 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLWindowPeer.java @@ -33,6 +33,7 @@ import java.awt.Insets; import java.awt.SystemColor; import java.awt.Window; +import java.awt.event.InvocationEvent; import java.awt.event.WindowEvent; import java.awt.peer.ComponentPeer; import java.awt.peer.WindowPeer; diff --git a/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKGraphicsConfig.java b/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKGraphicsConfig.java index 9be494986468..58af7fc904c4 100644 --- a/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKGraphicsConfig.java +++ b/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKGraphicsConfig.java @@ -74,8 +74,8 @@ public final class WLVKGraphicsConfig extends WLGraphicsConfig private static native long getVKConfigInfo(); - public WLVKGraphicsConfig(WLGraphicsDevice device, int width, int height, int scale, ContextCapabilities vkCaps) { - super(device, width, height, scale); + public WLVKGraphicsConfig(WLGraphicsDevice device, int width, int height, long scale120, ContextCapabilities vkCaps) { + super(device, width, height, scale120); this.vkCaps = vkCaps; context = new VKContext(VKRenderQueue.getInstance()); } @@ -85,13 +85,13 @@ public Object getProxyKey() { return this; } - public static WLVKGraphicsConfig getConfig(WLGraphicsDevice device, int width, int height, int scale) + public static WLVKGraphicsConfig getConfig(WLGraphicsDevice device, int width, int height, long scale120) { ContextCapabilities caps = new VKContext.VKContextCaps( CAPS_PS30 | CAPS_PS20 | CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE | CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 | CAPS_TEXNONSQUARE, null); - return new WLVKGraphicsConfig(device, width, height, scale, caps); + return new WLVKGraphicsConfig(device, width, height, scale120, caps); } /** @@ -212,6 +212,11 @@ public SurfaceData createSurfaceData(WLComponentPeer peer) { return WLVKSurfaceData.createData(peer); } + @Override + public WLGraphicsConfig withScale120(long scale120) { + return new WLVKGraphicsConfig(device, width, height, scale120, vkCaps); + } + /** * {@inheritDoc} * diff --git a/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKSurfaceData.java b/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKSurfaceData.java index ace52d86058f..c2fd70ad803d 100644 --- a/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKSurfaceData.java +++ b/src/java.desktop/unix/classes/sun/java2d/vulkan/WLVKSurfaceData.java @@ -60,8 +60,8 @@ protected WLVKSurfaceData(WLComponentPeer peer, WLVKGraphicsConfig gc, final int backgroundRGB = peer.getBackground() != null ? peer.getBackground().getRGB() : 0; - int scale = ((WLGraphicsConfig)peer.getGraphicsConfiguration()).getWlScale(); - initOps(peer.getBufferWidth(), peer.getBufferHeight(), scale, backgroundRGB); + // scale parameter is unused + initOps(peer.getBufferWidth(), peer.getBufferHeight(), 1, backgroundRGB); } @Override diff --git a/src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c b/src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c index a9d36483c993..92f1cc749fc3 100644 --- a/src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c +++ b/src/java.desktop/unix/native/libawt_wlawt/WLComponentPeer.c @@ -44,6 +44,7 @@ static jmethodID notifyConfiguredMID; static jmethodID notifyEnteredOutputMID; static jmethodID notifyLeftOutputMID; static jmethodID notifyPopupDoneMID; +static jmethodID notifyPreferredScaleMID; struct activation_token_list_item { struct xdg_activation_token_v1 *token; @@ -91,6 +92,7 @@ struct WLFrame { jobject nativeFramePeer; // weak reference struct wl_surface *wl_surface; struct wp_viewport *wp_viewport; + struct wp_fractional_scale_v1 *wp_fractional_scale; struct xdg_surface *xdg_surface; struct gtk_surface1 *gtk_surface; struct WLFrame *parent; @@ -308,6 +310,28 @@ static const struct xdg_activation_token_v1_listener xdg_activation_token_v1_lis .done = xdg_activation_token_v1_done, }; +static void wp_fractional_scale_preferred_scale(void *data, + struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + uint32_t scale) { + J2dTrace2(J2D_TRACE_INFO, "WLComponentPeer: wp_fractional_scale_preferred_scale(%p, %u)\n", + wp_fractional_scale_v1, scale); + + struct WLFrame *wlFrame = data; + assert(wlFrame); + + JNIEnv *env = getEnv(); + const jobject nativeFramePeer = (*env)->NewLocalRef(env, wlFrame->nativeFramePeer); + if (nativeFramePeer) { + (*env)->CallVoidMethod(env, nativeFramePeer, notifyPreferredScaleMID, (int64_t)scale); + (*env)->DeleteLocalRef(env, nativeFramePeer); + JNU_CHECK_EXCEPTION(env); + } +} + +static const struct wp_fractional_scale_v1_listener wp_fractional_scale_listener = { + .preferred_scale = wp_fractional_scale_preferred_scale, +}; + JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_initIDs (JNIEnv *env, jclass clazz) @@ -324,6 +348,9 @@ Java_sun_awt_wl_WLComponentPeer_initIDs CHECK_NULL_THROW_IE(env, notifyPopupDoneMID = (*env)->GetMethodID(env, clazz, "notifyPopupDone", "()V"), "Failed to find method WLComponentPeer.notifyPopupDone"); + CHECK_NULL_THROW_IE(env, + notifyPreferredScaleMID = (*env)->GetMethodID(env, clazz, "notifyPreferredScale", "(J)V"), + "Failed to find method WLComponentPeer.notifyPreferredScale"); } JNIEXPORT void JNICALL @@ -454,6 +481,11 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLSurface CHECK_NULL(frame->wl_surface); frame->wp_viewport = wp_viewporter_get_viewport(wp_viewporter, frame->wl_surface); CHECK_NULL(frame->wp_viewport); + if (wp_fractional_scale_manager) { + frame->wp_fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(wp_fractional_scale_manager, frame->wl_surface); + CHECK_NULL(frame->wp_fractional_scale); + wp_fractional_scale_v1_add_listener(frame->wp_fractional_scale, &wp_fractional_scale_listener, frame); + } frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface); CHECK_NULL(frame->xdg_surface); if (gtk_shell1 != NULL) { @@ -534,6 +566,11 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup CHECK_NULL(frame->wl_surface); frame->wp_viewport = wp_viewporter_get_viewport(wp_viewporter, frame->wl_surface); CHECK_NULL(frame->wp_viewport); + if (wp_fractional_scale_manager) { + frame->wp_fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(wp_fractional_scale_manager, frame->wl_surface); + CHECK_NULL(frame->wp_fractional_scale); + wp_fractional_scale_v1_add_listener(frame->wp_fractional_scale, &wp_fractional_scale_listener, frame); + } frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface); CHECK_NULL(frame->xdg_surface); @@ -590,6 +627,9 @@ DoHide(JNIEnv *env, struct WLFrame *frame) gtk_surface1_destroy(frame->gtk_surface); } wp_viewport_destroy(frame->wp_viewport); + if (frame->wp_fractional_scale) { + wp_fractional_scale_v1_destroy(frame->wp_fractional_scale); + } xdg_surface_destroy(frame->xdg_surface); wl_surface_destroy(frame->wl_surface); delete_all_tokens(frame->activation_token_list); @@ -601,6 +641,7 @@ DoHide(JNIEnv *env, struct WLFrame *frame) frame->xdg_toplevel = NULL; frame->xdg_popup = NULL; frame->wp_viewport = NULL; + frame->wp_fractional_scale = NULL; frame->toplevel = JNI_FALSE; } } diff --git a/src/java.desktop/unix/native/libawt_wlawt/WLGraphicsEnvironment.c b/src/java.desktop/unix/native/libawt_wlawt/WLGraphicsEnvironment.c index 4d8a361352a4..c2d1b61b8687 100644 --- a/src/java.desktop/unix/native/libawt_wlawt/WLGraphicsEnvironment.c +++ b/src/java.desktop/unix/native/libawt_wlawt/WLGraphicsEnvironment.c @@ -165,7 +165,7 @@ wl_output_done( output->height_mm, (jint)output->subpixel, (jint)output->transform, - (jint)output->scale); + (jlong)output->scale * 120); JNU_CHECK_EXCEPTION(env); } @@ -197,7 +197,7 @@ WLGraphicsEnvironment_initIDs CHECK_NULL_RETURN( notifyOutputConfiguredMID = (*env)->GetMethodID(env, clazz, "notifyOutputConfigured", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIII)V"), + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIIJ)V"), JNI_FALSE); CHECK_NULL_RETURN( notifyOutputDestroyedMID = (*env)->GetMethodID(env, clazz, diff --git a/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c b/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c index a66e92f3e2b2..4de8007b0e84 100644 --- a/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c +++ b/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.c @@ -65,6 +65,7 @@ struct wl_shm *wl_shm = NULL; struct wl_compositor *wl_compositor = NULL; struct xdg_wm_base *xdg_wm_base = NULL; struct wp_viewporter *wp_viewporter = NULL; +struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager = NULL; struct xdg_activation_v1 *xdg_activation_v1 = NULL; struct gtk_shell1* gtk_shell1 = NULL; struct wl_seat *wl_seat = NULL; @@ -527,6 +528,8 @@ registry_global(void *data, struct wl_registry *wl_registry, zwp_selection_dm = wl_registry_bind(wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1); } else if (strcmp(interface, wp_viewporter_interface.name) == 0) { wp_viewporter = wl_registry_bind(wl_registry, name, &wp_viewporter_interface, 1); + } else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { + wp_fractional_scale_manager = wl_registry_bind(wl_registry, name, &wp_fractional_scale_manager_v1_interface, 1); } #ifdef WAKEFIELD_ROBOT diff --git a/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h b/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h index 4b01194e2ef3..ec549c5a3fe8 100644 --- a/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h +++ b/src/java.desktop/unix/native/libawt_wlawt/WLToolkit.h @@ -29,6 +29,7 @@ #include "xdg-activation-v1-client-protocol.h" #include "primary-selection-client-protocol.h" #include "viewporter-client-protocol.h" +#include "fractional-scale-v1-client-protocol.h" #include "jvm_md.h" #include "jni_util.h" @@ -56,6 +57,7 @@ extern struct wl_pointer *wl_pointer; extern struct wl_compositor *wl_compositor; extern struct xdg_wm_base *xdg_wm_base; extern struct wp_viewporter *wp_viewporter; +extern struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager; extern struct xdg_activation_v1 *xdg_activation_v1; extern struct gtk_shell1* gtk_shell1; // optional, check for NULL before use diff --git a/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.c b/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.c new file mode 100644 index 000000000000..090166bcf301 --- /dev/null +++ b/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.c @@ -0,0 +1,73 @@ +/* Generated by wayland-scanner 1.22.0 */ + +/* + * Copyright © 2022 Kenny Levinsen + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wp_fractional_scale_v1_interface; + +static const struct wl_interface *fractional_scale_v1_types[] = { + NULL, + &wp_fractional_scale_v1_interface, + &wl_surface_interface, +}; + +static const struct wl_message wp_fractional_scale_manager_v1_requests[] = { + { "destroy", "", fractional_scale_v1_types + 0 }, + { "get_fractional_scale", "no", fractional_scale_v1_types + 1 }, +}; + +WL_PRIVATE const struct wl_interface wp_fractional_scale_manager_v1_interface = { + "wp_fractional_scale_manager_v1", 1, + 2, wp_fractional_scale_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message wp_fractional_scale_v1_requests[] = { + { "destroy", "", fractional_scale_v1_types + 0 }, +}; + +static const struct wl_message wp_fractional_scale_v1_events[] = { + { "preferred_scale", "u", fractional_scale_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface wp_fractional_scale_v1_interface = { + "wp_fractional_scale_v1", 1, + 1, wp_fractional_scale_v1_requests, + 1, wp_fractional_scale_v1_events, +}; + diff --git a/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.h b/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.h new file mode 100644 index 000000000000..4bb28da48b9d --- /dev/null +++ b/src/java.desktop/unix/native/libawt_wlawt/fractional-scale-v1-client-protocol.h @@ -0,0 +1,264 @@ +/* Generated by wayland-scanner 1.22.0 */ + +#ifndef FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H +#define FRACTIONAL_SCALE_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client-core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_fractional_scale_v1 The fractional_scale_v1 protocol + * Protocol for requesting fractional surface scales + * + * @section page_desc_fractional_scale_v1 Description + * + * This protocol allows a compositor to suggest for surfaces to render at + * fractional scales. + * + * A client can submit scaled content by utilizing wp_viewport. This is done by + * creating a wp_viewport object for the surface and setting the destination + * rectangle to the surface size before the scale factor is applied. + * + * The buffer size is calculated by multiplying the surface size by the + * intended scale. + * + * The wl_surface buffer scale should remain set to 1. + * + * If a surface has a surface-local size of 100 px by 50 px and wishes to + * submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should + * be used and the wp_viewport destination rectangle should be 100 px by 50 px. + * + * For toplevel surfaces, the size is rounded halfway away from zero. The + * rounding algorithm for subsurface position and size is not defined. + * + * @section page_ifaces_fractional_scale_v1 Interfaces + * - @subpage page_iface_wp_fractional_scale_manager_v1 - fractional surface scale information + * - @subpage page_iface_wp_fractional_scale_v1 - fractional scale interface to a wl_surface + * @section page_copyright_fractional_scale_v1 Copyright + *
+ *
+ * Copyright © 2022 Kenny Levinsen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ */ +struct wl_surface; +struct wp_fractional_scale_manager_v1; +struct wp_fractional_scale_v1; + +#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE +#define WP_FRACTIONAL_SCALE_MANAGER_V1_INTERFACE +/** + * @page page_iface_wp_fractional_scale_manager_v1 wp_fractional_scale_manager_v1 + * @section page_iface_wp_fractional_scale_manager_v1_desc Description + * + * A global interface for requesting surfaces to use fractional scales. + * @section page_iface_wp_fractional_scale_manager_v1_api API + * See @ref iface_wp_fractional_scale_manager_v1. + */ +/** + * @defgroup iface_wp_fractional_scale_manager_v1 The wp_fractional_scale_manager_v1 interface + * + * A global interface for requesting surfaces to use fractional scales. + */ +extern const struct wl_interface wp_fractional_scale_manager_v1_interface; +#endif +#ifndef WP_FRACTIONAL_SCALE_V1_INTERFACE +#define WP_FRACTIONAL_SCALE_V1_INTERFACE +/** + * @page page_iface_wp_fractional_scale_v1 wp_fractional_scale_v1 + * @section page_iface_wp_fractional_scale_v1_desc Description + * + * An additional interface to a wl_surface object which allows the compositor + * to inform the client of the preferred scale. + * @section page_iface_wp_fractional_scale_v1_api API + * See @ref iface_wp_fractional_scale_v1. + */ +/** + * @defgroup iface_wp_fractional_scale_v1 The wp_fractional_scale_v1 interface + * + * An additional interface to a wl_surface object which allows the compositor + * to inform the client of the preferred scale. + */ +extern const struct wl_interface wp_fractional_scale_v1_interface; +#endif + +#ifndef WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM +#define WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM +enum wp_fractional_scale_manager_v1_error { + /** + * the surface already has a fractional_scale object associated + */ + WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS = 0, +}; +#endif /* WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_ENUM */ + +#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY 0 +#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE 1 + + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + */ +#define WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + */ +#define WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE_SINCE_VERSION 1 + +/** @ingroup iface_wp_fractional_scale_manager_v1 */ +static inline void +wp_fractional_scale_manager_v1_set_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1, user_data); +} + +/** @ingroup iface_wp_fractional_scale_manager_v1 */ +static inline void * +wp_fractional_scale_manager_v1_get_user_data(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_manager_v1); +} + +static inline uint32_t +wp_fractional_scale_manager_v1_get_version(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1); +} + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + * + * Informs the server that the client will not be using this protocol + * object anymore. This does not affect any other objects, + * wp_fractional_scale_v1 objects included. + */ +static inline void +wp_fractional_scale_manager_v1_destroy(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1, + WP_FRACTIONAL_SCALE_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_wp_fractional_scale_manager_v1 + * + * Create an add-on object for the the wl_surface to let the compositor + * request fractional scales. If the given wl_surface already has a + * wp_fractional_scale_v1 object associated, the fractional_scale_exists + * protocol error is raised. + */ +static inline struct wp_fractional_scale_v1 * +wp_fractional_scale_manager_v1_get_fractional_scale(struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager_v1, struct wl_surface *surface) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_manager_v1, + WP_FRACTIONAL_SCALE_MANAGER_V1_GET_FRACTIONAL_SCALE, &wp_fractional_scale_v1_interface, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_manager_v1), 0, NULL, surface); + + return (struct wp_fractional_scale_v1 *) id; +} + +/** + * @ingroup iface_wp_fractional_scale_v1 + * @struct wp_fractional_scale_v1_listener + */ +struct wp_fractional_scale_v1_listener { + /** + * notify of new preferred scale + * + * Notification of a new preferred scale for this surface that + * the compositor suggests that the client should use. + * + * The sent scale is the numerator of a fraction with a denominator + * of 120. + * @param scale the new preferred scale + */ + void (*preferred_scale)(void *data, + struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + uint32_t scale); +}; + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +static inline int +wp_fractional_scale_v1_add_listener(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + const struct wp_fractional_scale_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) wp_fractional_scale_v1, + (void (**)(void)) listener, data); +} + +#define WP_FRACTIONAL_SCALE_V1_DESTROY 0 + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +#define WP_FRACTIONAL_SCALE_V1_PREFERRED_SCALE_SINCE_VERSION 1 + +/** + * @ingroup iface_wp_fractional_scale_v1 + */ +#define WP_FRACTIONAL_SCALE_V1_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_wp_fractional_scale_v1 */ +static inline void +wp_fractional_scale_v1_set_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wp_fractional_scale_v1, user_data); +} + +/** @ingroup iface_wp_fractional_scale_v1 */ +static inline void * +wp_fractional_scale_v1_get_user_data(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wp_fractional_scale_v1); +} + +static inline uint32_t +wp_fractional_scale_v1_get_version(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1); +} + +/** + * @ingroup iface_wp_fractional_scale_v1 + * + * Destroy the fractional scale object. When this object is destroyed, + * preferred_scale events will no longer be sent. + */ +static inline void +wp_fractional_scale_v1_destroy(struct wp_fractional_scale_v1 *wp_fractional_scale_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) wp_fractional_scale_v1, + WP_FRACTIONAL_SCALE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wp_fractional_scale_v1), WL_MARSHAL_FLAG_DESTROY); +} + +#ifdef __cplusplus +} +#endif + +#endif