aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Kartashev <maxim.kartashev@jetbrains.com>2023-08-24 15:41:47 +0400
committerMaxim Kartashev <maxim.kartashev@jetbrains.com>2023-08-29 10:48:18 +0400
commit8ff96bc79fc9a1799ed0f3c562f4874c8ac9d3d2 (patch)
treee79cd1f8443ab41d9877f35e25ebbe2623c6ec66
parentf600c73328574ae811710a29af7478f4c338ec76 (diff)
downloadJetBrainsRuntime-8ff96bc79fc9a1799ed0f3c562f4874c8ac9d3d2.tar.gz
JBR-5971 Wayland: support WindowMove JBR API
-rw-r--r--src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java2
-rw-r--r--src/java.desktop/share/classes/java/awt/Window.java62
-rw-r--r--src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java10
-rw-r--r--src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java11
-rw-r--r--src/jetbrains.api/src/com/jetbrains/WindowMove.java13
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);
}