compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

Maximizing undecorated windows seems to result in full-screen behavior

Open AtriusX opened this issue 3 years ago • 4 comments

If a window is undecorated, setting the window placement to Maximized seems to make the window cover the entire screen including the taskbar. I don't know if I'm doing anything wrong to result in this behavior, but this occurred in a small test project I was working on and again in a new project I made to test the problem after I noticed it.

The following program should demonstrate the problem:

import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.singleWindowApplication

fun main() = singleWindowApplication(
    undecorated = true
) {
    Button(
        onClick = {
            window.placement = WindowPlacement.Maximized
        }
    ) {
        Text("Maximize")
    }
}

Please let me know if there is a work-around, or if I'm approaching this the wrong way.

AtriusX avatar Dec 07 '21 02:12 AtriusX

is a work-around,

Workaround is to use window.setLocation and window.setSize. The size can be calculated via window.graphicsConfiguration.bounds and Toolkit.getDefaultToolkit().getScreenInsets(window.graphicsConfiguration) see example

As for the issue, it seems either Swing or the system window manager maximizes this way. Intuitively this looks wrong. We probably can use the same workaround inside Compose, not sure yet. Or maybe we should set some parameter directly for the native window.

igordmn avatar Dec 08 '21 07:12 igordmn

I can confirm that this workaround does indeed work. I was able to use the following code to get the window to fit the proper area without issue:

val mode = remember { mutableStateOf(window.placement) }
val size = remember { mutableStateOf(window.size) }
val pos = remember { mutableStateOf(window.position) }
// Lower down in a button
onClick = {
    mode.value = if (mode.value == WindowPlacement.Floating) {
        size.value = window.size
        pos.value = window.position
        val insets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration)
        val bounds = graphicsConfiguration.bounds
        setSize(bounds.width, bounds.height - insets.bottom)
        setLocation(0, 0)
        WindowPlacement.Maximized
    } else {
        window.size = size.value
        window.position = pos.value
        WindowPlacement.Floating
    }
}

This is a fairly messy solution but it does otherwise seem to work as expected. I'll probably continue experimenting with it to see if I can improve it at all.

AtriusX avatar Dec 08 '21 22:12 AtriusX

This also seems to remove the possibility to open the Taskbar, if set to autohiding, just with mouse. It forces to use the super key to acces the Taskbar. This makes the maximize option pretty much useless. I hope this gets fixed soon.

Selemba1000 avatar Nov 03 '23 19:11 Selemba1000

Also when used with WindowDragabbleArea to simulate windows toolbar and un-maximizing window by dragging, if you reset window size with window.setSize, then window.setLocation does nothing and you end up holding "nothing" under the mouse (if you drag the right part of the window, floating window will be at the left of the screen instead). Maybe its get updated every onDrag event with positions of the original maximized window, but it should be adjusted with proportions formula probably.

If you use WindowPlacement setter instead, the size of the window is also not reverting back to old size

UPD: solved my problem with that code:

    WindowDraggableArea(
        modifier = Modifier.pointerInput(Unit) {
            awaitEachGesture {
                awaitFirstDown(pass = PointerEventPass.Initial)
                if (mode == WindowPlacement.Maximized) {
                    mode = WindowPlacement.Floating
                    val x = when {
                        window.mousePosition.x < oldSize.width / 2 -> 0
                        window.mousePosition.x > windowState.size.width - oldSize.width / 2 -> windowState.size.width - oldSize.width
                        else -> window.mousePosition.x - oldSize.width / 2
                    }
                    windowState.size = oldSize
                    window.setLocation(x.toInt(), 0)
                }
            }
        }
    )

And i also think that the general support of windows docking feature should be addressed instead. Got used to that feature that much, that forgot, how deep is the rabbit hole.

Melodeiro avatar Jun 19 '24 19:06 Melodeiro

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

okushnikov avatar Aug 26 '24 15:08 okushnikov