diff options
author | Maxim Kartashev <maxim.kartashev@jetbrains.com> | 2023-08-24 15:41:47 +0400 |
---|---|---|
committer | Maxim Kartashev <maxim.kartashev@jetbrains.com> | 2023-08-29 10:48:18 +0400 |
commit | 8ff96bc79fc9a1799ed0f3c562f4874c8ac9d3d2 (patch) | |
tree | e79cd1f8443ab41d9877f35e25ebbe2623c6ec66 | |
parent | f600c73328574ae811710a29af7478f4c338ec76 (diff) | |
download | JetBrainsRuntime-8ff96bc79fc9a1799ed0f3c562f4874c8ac9d3d2.tar.gz |
JBR-5971 Wayland: support WindowMove JBR API
5 files changed, 95 insertions, 3 deletions
diff --git a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java index b7f21a1712d..e09275c1c9a 100644 --- a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java +++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java @@ -62,7 +62,7 @@ public class JBRApiModule { .withStatic("deriveFontWithFeatures", "deriveFont", "java.awt.Font") .withStatic("getFeaturesAsString", "getFeaturesAsString", "com.jetbrains.desktop.FontExtensions") .clientProxy("java.awt.Font$Features", "com.jetbrains.FontExtensions$Features") - .service("com.jetbrains.WindowMove", "sun.awt.X11.XWindowPeer$WindowMoveService") + .service("com.jetbrains.WindowMove", "java.awt.Window$WindowMoveService") ; } } diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index c2bf8a32e2d..21f5dde6003 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -59,6 +59,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.HashMap; +import java.util.Objects; import java.util.ResourceBundle; import java.util.Set; import java.util.Vector; @@ -4257,6 +4258,67 @@ public class Window extends Container implements Accessible { } } + private interface WindowMovePeer { + void startMovingWindowTogetherWithMouse(Window window, int mouseButton); + } + + private interface WindowMovePeerX11 extends WindowMovePeer { + WindowMovePeerX11 INSTANCE = (WindowMovePeerX11) JBRApi.internalServiceBuilder(MethodHandles.lookup()) + .withStatic("startMovingWindowTogetherWithMouse", + "startMovingWindowTogetherWithMouse", + "sun.awt.X11.XWindowPeer") + .build(); + } + + private interface WindowMovePeerWayland extends WindowMovePeer { + WindowMovePeerWayland INSTANCE = (WindowMovePeerWayland) JBRApi.internalServiceBuilder(MethodHandles.lookup()) + .withStatic("startMovingWindowTogetherWithMouse", + "startMovingWindowTogetherWithMouse", + "sun.awt.wl.WLComponentPeer") + .build(); + } + + private static class WindowMoveService { + WindowMovePeer windowMovePeer; + + WindowMoveService() { + var toolkit = Toolkit.getDefaultToolkit(); + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (toolkit == null || ge == null) { + throw new JBRApi.ServiceNotAvailableException("Supported only with a Toolkit present"); + } + + boolean isWayland = objectIsInstanceOf(toolkit, "sun.awt.wl.WLToolkit"); + if (isWayland) { + if (!objectIsInstanceOf(ge,"sun.awt.wl.WLGraphicsEnvironment")) { + throw new JBRApi.ServiceNotAvailableException("On Wayland, supported only with WLGraphicsEnvironment"); + } + } else { + if (!objectIsInstanceOf(toolkit, "sun.awt.X11.XToolkit") + || !objectIsInstanceOf(ge, "sun.awt.X11GraphicsEnvironment")) { + throw new JBRApi.ServiceNotAvailableException("Supported only with XToolkit and X11GraphicsEnvironment"); + } + } + + if (isWayland) { + windowMovePeer = WindowMovePeerWayland.INSTANCE; + } else { + // This will throw if the service is not supported by the underlying WM + windowMovePeer = WindowMovePeerX11.INSTANCE; + } + } + + boolean objectIsInstanceOf(Object o, String className) { + Objects.requireNonNull(o); + return o.getClass().getName().equals(className); + } + + void startMovingTogetherWithMouse(Window window, int mouseButton) { + Objects.requireNonNull(window); + windowMovePeer.startMovingWindowTogetherWithMouse(window, mouseButton); + } + } + // ************************** JBR stuff ******************************* private volatile boolean ignoreMouseEvents; diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java index 4139227145a..d8f18cb7392 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java @@ -2655,6 +2655,16 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, XWM.getWM().startMovingWindowTogetherWithMouse(getParentTopLevel().getWindow(), getLastButtonPressAbsLocation(), mouseButton); } + private static void startMovingWindowTogetherWithMouse(Window window, int mouseButton) { + final AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor(); + ComponentPeer peer = acc.getPeer(window); + if (peer instanceof XWindowPeer xWindowPeer) { + xWindowPeer.startMovingTogetherWithMouse(mouseButton); + } else { + throw new IllegalArgumentException("AWT window must have XWindowPeer as its peer"); + } + } + private static class WindowMoveService { WindowMoveService() { final var toolkit = Toolkit.getDefaultToolkit(); 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 bb7e3fbe41a..897fa6faaa3 100644 --- a/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java @@ -1132,4 +1132,15 @@ public class WLComponentPeer implements ComponentPeer { WLToolkit.awtLock(); } } + + private static void startMovingWindowTogetherWithMouse(Window window, int mouseButton) + { + final AWTAccessor.ComponentAccessor acc = AWTAccessor.getComponentAccessor(); + ComponentPeer peer = acc.getPeer(window); + if (peer instanceof WLComponentPeer wlComponentPeer) { + wlComponentPeer.startDrag(); + } else { + throw new IllegalArgumentException("AWT window must have WLComponentPeer as its peer"); + } + } } diff --git a/src/jetbrains.api/src/com/jetbrains/WindowMove.java b/src/jetbrains.api/src/com/jetbrains/WindowMove.java index 60d80c80c4d..72df125b643 100644 --- a/src/jetbrains.api/src/com/jetbrains/WindowMove.java +++ b/src/jetbrains.api/src/com/jetbrains/WindowMove.java @@ -33,7 +33,9 @@ public interface WindowMove { * The intended use is to facilitate the implementation of window management similar to the way * it is done natively on the platform. * - * Preconditions for calling this method: + * The service is implemented both for X11 and Wayland toolkits. + * + * Preconditions for calling this method with the X11 toolkit: * <ul> * <li>WM supports _NET_WM_MOVE_RESIZE (this is checked automatically when an implementation * of this interface is obtained).</li> @@ -41,13 +43,20 @@ public interface WindowMove { * <li>The mouse button specified by {@code mouseButton} is pressed.</li> * </ul> * + * Preconditions for calling this method with the Wayland toolkit: + * <ul> + * <li>Mouse pointer is within this window's bounds.</li> + * </ul> + * The {@code mouseButton} is ignored for Wayland; the latest mouse press event is used + * automatically; this is enforced by the Wayland protocol. + * * Calling this method will make the window start moving together with the mouse pointer until * the specified mouse button is released or Esc is pressed. The conditions for cancelling * the move may differ between WMs. * * @param mouseButton indicates the mouse button that was pressed to start moving the window; * must be one of {@code MouseEvent.BUTTON1}, {@code MouseEvent.BUTTON2}, - * or {@code MouseEvent.BUTTON3}. + * or {@code MouseEvent.BUTTON3}. This argument is ignored for Wayland. */ void startMovingTogetherWithMouse(Window window, int mouseButton); } |