diff --git a/CHANGELOG.md b/CHANGELOG.md index 95581fcb..30492e45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # WIP +- Added `Window::setParentWindow` (macOS only for now): attach a window as a child of another, keeping it above its parent without floating above other applications - Bumped types in pom.xml to 0.2.0 - Windows, Linux: Window::setIconPixels (previously setIconData on Linux) #310 #135 via @chirontt - macOS: fixed incorrect app shutdown diff --git a/README.md b/README.md index e01c4a78..9b7601c0 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ Alpha. Expect API breakages. | setResizable | ❌ | ❌ | ❌ | | bringToFront | ✅ | ❌ | ❌ | | isFront | ✅ | ✅ | ❌ | +| setParentWindow | ❌ | ✅ | ❌ | ### Events diff --git a/linux/java/WindowX11.java b/linux/java/WindowX11.java index adfb64ef..1c5df1f5 100644 --- a/linux/java/WindowX11.java +++ b/linux/java/WindowX11.java @@ -220,6 +220,13 @@ public Window setZOrder(ZOrder order) { return this; } + @Override + public Window setParentWindow(Window parent) { + assert _onUIThread() : "Should be run on UI thread"; + // TODO implement (XSetTransientForHint) + return this; + } + @Override public float getProgressBar() { throw new UnsupportedOperationException("impl me!"); diff --git a/macos/cc/WindowMac.mm b/macos/cc/WindowMac.mm index acaac7ee..0cc54f02 100644 --- a/macos/cc/WindowMac.mm +++ b/macos/cc/WindowMac.mm @@ -600,6 +600,18 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt nsWindow.level = level; } +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowMac__1nSetParentWindow + (JNIEnv* env, jobject obj, jlong parentPtr) { + jwm::WindowMac* instance = reinterpret_cast(jwm::classes::Native::fromJava(env, obj)); + NSWindow* nsWindow = instance->fNSWindow; + if (nsWindow.parentWindow) + [nsWindow.parentWindow removeChildWindow:nsWindow]; + if (parentPtr) { + jwm::WindowMac* parent = reinterpret_cast(static_cast(parentPtr)); + [parent->fNSWindow addChildWindow:nsWindow ordered:NSWindowAbove]; + } +} + extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowMac__1nSetProgressBar (JNIEnv* env, jobject obj, jfloat value) { // Based on diff --git a/macos/java/WindowMac.java b/macos/java/WindowMac.java index 7b6e88d8..7faa6a3c 100644 --- a/macos/java/WindowMac.java +++ b/macos/java/WindowMac.java @@ -4,6 +4,7 @@ import java.util.concurrent.*; import java.util.function.*; import org.jetbrains.annotations.*; +import io.github.humbleui.jwm.impl.*; import io.github.humbleui.types.*; public class WindowMac extends Window { @@ -280,6 +281,13 @@ public Window setZOrder(ZOrder order) { return this; } + @Override + public Window setParentWindow(@Nullable Window parent) { + assert _onUIThread() : "Should be run on UI thread"; + _nSetParentWindow(Native.getPtr(parent)); + return this; + } + @Override public float getProgressBar() { assert _onUIThread() : "Should be run on UI thread"; @@ -366,6 +374,7 @@ public static boolean isPressAndHoldEnabledGlobally() { @ApiStatus.Internal public native void _nFocus(); @ApiStatus.Internal public native int _nGetZOrder(); @ApiStatus.Internal public native void _nSetZOrder(int zOrder); + @ApiStatus.Internal public native void _nSetParentWindow(long parentPtr); @ApiStatus.Internal public native void _nSetProgressBar(float value); @ApiStatus.Internal public native void _nClose(); @ApiStatus.Internal public native void _nSetPressAndHoldEnabled(boolean enabled); diff --git a/shared/java/Window.java b/shared/java/Window.java index e8520d21..59835fb8 100644 --- a/shared/java/Window.java +++ b/shared/java/Window.java @@ -390,11 +390,29 @@ public Window setVisible(boolean isVisible) { /** *

Makes window float always on top.

- * + * * @return this */ public abstract Window setZOrder(ZOrder order); + /** + *

Attaches this window as a child of {@code parent}: it stays ordered above the + * parent window, but — unlike {@link #setZOrder(ZOrder)} with a floating level — + * does not float above other applications' windows. The child moves together with + * its parent.

+ * + *

Pass {@code null} to detach. Attach after making this window visible: on macOS, + * attaching orders the window in, and hiding a child window detaches it + * automatically — so re-attach on every show.

+ * + *

Currently implemented on macOS only ({@code addChildWindow:ordered:}); no-op on + * Windows and X11.

+ * + * @param parent window to attach to, or {@code null} to detach + * @return this + */ + public abstract Window setParentWindow(@Nullable Window parent); + /** * @return The current progress bar value for this window */ diff --git a/windows/java/WindowWin32.java b/windows/java/WindowWin32.java index 1b748dd8..9231d79a 100644 --- a/windows/java/WindowWin32.java +++ b/windows/java/WindowWin32.java @@ -211,6 +211,13 @@ public Window setZOrder(ZOrder order) { return this; } + @Override + public Window setParentWindow(Window parent) { + assert _onUIThread() : "Should be run on UI thread"; + // TODO implement (owner window via GWLP_HWNDPARENT; see winSetParent) + return this; + } + @Override public float getProgressBar() { throw new UnsupportedOperationException("impl me!");