Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Alpha. Expect API breakages.
| setResizable | ❌ | ❌ | ❌ |
| bringToFront | ✅ | ❌ | ❌ |
| isFront | ✅ | ✅ | ❌ |
| setParentWindow | ❌ | ✅ | ❌ |

### Events

Expand Down
7 changes: 7 additions & 0 deletions linux/java/WindowX11.java
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand Down
12 changes: 12 additions & 0 deletions macos/cc/WindowMac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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::WindowMac*>(jwm::classes::Native::fromJava(env, obj));
NSWindow* nsWindow = instance->fNSWindow;
if (nsWindow.parentWindow)
[nsWindow.parentWindow removeChildWindow:nsWindow];
if (parentPtr) {
jwm::WindowMac* parent = reinterpret_cast<jwm::WindowMac*>(static_cast<uintptr_t>(parentPtr));
[parent->fNSWindow addChildWindow:nsWindow ordered:NSWindowAbove];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Set fullscreen auxiliary behavior for child windows

When parent is already in macOS fullscreen, this attaches the child while it still has the initialization-time NSWindowCollectionBehaviorFullScreenPrimary used for every WindowMac. Secondary windows need NSWindowCollectionBehaviorFullScreenAuxiliary to appear in the same fullscreen Space as their parent; otherwise the child is ordered on another Space/desktop and setParentWindow does not keep it above the fullscreen parent. Set the auxiliary behavior before attaching, and restore the top-level behavior on detach if needed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@claude fix in current branch

}
}

extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_jwm_WindowMac__1nSetProgressBar
(JNIEnv* env, jobject obj, jfloat value) {
// Based on
Expand Down
9 changes: 9 additions & 0 deletions macos/java/WindowMac.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 19 additions & 1 deletion shared/java/Window.java
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,29 @@ public Window setVisible(boolean isVisible) {

/**
* <p>Makes window float always on top.</p>
*
*
* @return this
*/
public abstract Window setZOrder(ZOrder order);

/**
* <p>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.</p>
*
* <p>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.</p>
*
* <p>Currently implemented on macOS only ({@code addChildWindow:ordered:}); no-op on
* Windows and X11.</p>
*
* @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
*/
Expand Down
7 changes: 7 additions & 0 deletions windows/java/WindowWin32.java
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand Down