Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Window] 'Maximise' button on undecorated Aurora window fullscreens rather than maximises #13

Closed
russellbanks opened this issue Jan 19, 2022 · 6 comments

Comments

@russellbanks
Copy link

When using an undecorated Aurora Window, the maximising button (square) makes the window fullscreen rather than maximising it. For reference, I am using Windows 11 so normally pressing a maximise button would make the window fill the screen whilst staying above the taskbar and keeping the taskbar visible.

@kirill-grouchnikov
Copy link
Owner

The relevant code is in the block that starts here which is asking the underlying JFrame to set its extended state to MAXIMIZED_BOTH.

Apparently it's a 20 (!!!) year old bug in Java, and the workaround is to explicitly compute and set maximized bounds on each undecorated frame.

@kirill-grouchnikov kirill-grouchnikov changed the title 'Maximise' button on undecorated Aurora window fullscreens rather than maximises [Window] 'Maximise' button on undecorated Aurora window fullscreens rather than maximises Jan 19, 2022
kirill-grouchnikov added a commit that referenced this issue Jan 19, 2022
kirill-grouchnikov added a commit that referenced this issue Jan 20, 2022
Account for changes that went into Java 15 around screen sizes under high-dpi settings. For #13
@kirill-grouchnikov
Copy link
Owner

There's more to it. There were multiple fixes that went into Java 15 that changed what needs to be passed to setMaximizedBounds. See:

On pre-Java 15, the result of GraphicsConfiguration.getBounds() needs to be scaled by the display's scale factor (obtained from GraphicsConfiguration.getDefaultTransform().getScaleX/Y() before applying the screen insets.

kirill-grouchnikov added a commit that referenced this issue Jan 20, 2022
Only apply that separate code path for pre-Java 15 on Windows. For #13.
@russellbanks
Copy link
Author

Just wondering, how come it can't be done like the Compose Window tutorial? Is there a limitation or a reason why using JFrame is preferable?

Changing the state

@kirill-grouchnikov
Copy link
Owner

The example you're linking to is not an undecorated window. You can see the OS-provided decorations (the title bar, the window border, etc). Now if you change it to undecorated mode, you'll get the same issue:

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Checkbox
import androidx.compose.material.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState

fun main() = application {
    val state = rememberWindowState(placement = WindowPlacement.Floating)

    Window(onCloseRequest = ::exitApplication, state, undecorated = true) {
        Column(modifier = Modifier.padding(16.dp).fillMaxSize()) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Checkbox(
                    state.placement == WindowPlacement.Fullscreen,
                    {
                        state.placement = if (it) {
                            WindowPlacement.Fullscreen
                        } else {
                            WindowPlacement.Floating
                        }
                    }
                )
                Text("isFullscreen")
            }

            Row(verticalAlignment = Alignment.CenterVertically) {
                Checkbox(
                    state.placement == WindowPlacement.Maximized,
                    {
                        state.placement = if (it) {
                            WindowPlacement.Maximized
                        } else {
                            WindowPlacement.Floating
                        }
                    }
                )
                Text("isMaximized")
            }

            Row(verticalAlignment = Alignment.CenterVertically) {
                Checkbox(state.isMinimized, { state.isMinimized = !state.isMinimized })
                Text("isMinimized")
            }

            Text(
                "Position ${state.position}",
                Modifier.clickable {
                    val position = state.position
                    if (position is WindowPosition.Absolute) {
                        state.position = position.copy(x = state.position.x + 10.dp)
                    }
                }
            )

            Text(
                "Size ${state.size}",
                Modifier.clickable {
                    state.size = state.size.copy(width = state.size.width + 10.dp)
                }
            )

            Box(modifier = Modifier.fillMaxSize().weight(1.0f, true).background(Color.Red))
        }
    }
}

@kirill-grouchnikov
Copy link
Owner

As for your other questions:

@russellbanks
Copy link
Author

Perfect explanation, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants