https://kotlinlang.org logo
Title
d

Dirk Hoffmann

05/25/2021, 6:41 PM
BTW I find it a bit "disturbing" that
LocalAppWindow.current.(width|height)
are of datatype
Int
but represent height|width in
Dp
... so if you wanna have e.g. the window width in Float to compare it to a
Size
or
Offset
you have to do
LocalAppWindow.current.width * LocalDensity.current.density
Even more at the "root" of all Apps:
fun main() = Window(title = "Compose for Desktop", size = IntSize(300, 300)) {
The window doesn't have an IntSize of 300, 300 ... in fact it has a DpSize of 300, 300 and an
IntSize(600, 600)
(if density == 2.0f)
👍 6
k

Kirill Grouchnikov

05/25/2021, 8:08 PM
It's a rather awkward seam between the density independent world of Compose and pixel world of Swing (which has very little to no API awareness of screen density, making it really cumbersome to do anything related to high-DPI displays). Unless the Desktop version of compose completely abstracts away those Swing/AWT APIs that work with the underlying windowing APIs, you'll still have that seam somewhere in either the API surface, or when you need to interact with the windowing APIs of Swing / AWT.
b

Brian G

05/25/2021, 8:25 PM
But since they represent dp, why not type them
Dp
? Everywhere else in the Compose API dimensions are given in
Dp
k

Kirill Grouchnikov

05/25/2021, 8:28 PM
If you are talking specifically about the
size
parameter in the
Window
composable, you'll probably want to make sure that the initial size matches the display size (percentage wise, or at least doesn't overflow the width and / or height). I don't think Compose has APIs to get the dp size of all the available screens, at least not in the desktop edition. So you'd still be doing dp to pixel conversion, just in a different place in your code.
b

Brian G

05/25/2021, 8:32 PM
Yes, sorry, I'm referring to the
Window
composable. Since it is treated as dp, why not type it
Dp
to make the API more self-documenting?
The developer doesn't need to do manual dp/pixel conversion unless they want specific window-screen ratios like you were saying.
u

uli

05/25/2021, 8:39 PM
@Kirill Grouchnikov if i understand right, it is about units / type safety / semantics. Compose has an inline class Dp. As I understand Dirk is disturbed by the fact, that the data type of `width`/`height`is
Int
but the semantics is
Dp
:yes: 1
k

Kirill Grouchnikov

05/25/2021, 9:04 PM
The
IntSize
values are passed directly to
java.awt.Window.setSize
in https://github.com/androidx/androidx/blob/androidx-main/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AppWindow.desktop.kt#L392 and that is one of the few places that https://openjdk.java.net/jeps/263 covered - the conversion to "real" pixels happens under the hood.
u

uli

05/25/2021, 9:18 PM
Understood that this is how it is implemented. But why? Why can't AppWindow accept Dp and pass it on as Int
k

Kirill Grouchnikov

05/25/2021, 9:21 PM
I'm not arguing either way. I'm saying that this is where it shows the seam between Compose (which is all in on Dp) and Swing / AWT (which is partway in on that, in some cases treating pixel values as real pixels, and in some cases treating pixel values as "abstracted" pixels which are kinda the same as Dp in Compose)
Run this:
fun main() {
    SwingUtilities.invokeLater {
        val appWindow = AppWindow(
            title = "My title",
            size = IntSize(400, 300),
            location = IntOffset.Zero,
            centered = true,
            icon = null,
            menuBar = null,
            undecorated = false,
            resizable = true,
            events = WindowEvents(),
            onDismissRequest = null
        )

        appWindow.show {
        }

        println("Requested compose window width was 400")

        val composeWindow = appWindow.window
        println("On-screen AWT window width is ${composeWindow.size.width}")
    }
}
The window width returned by
java.awt.Window.getSize()
is 400, even though the window on a 2x retina display is 800x600 pixels
It will need to be a very careful dance to make sure that the idiosyncrasy of the underlying APIs is abstracted away in a consistent fashion
For example, if you want to render Swing content offscreen to a bitmap, the
BufferedImage
that you create will need to account for the display density. So you essentially draw a
JFrame
that declares itself a 400x300 pixels into a
BufferedImage
that is 800x600 pixels. Because otherwise you lose all that detail.
d

Dirk Hoffmann

05/25/2021, 9:32 PM
the case where I stumbled over this thing was when trying to implement my own popup ... I get the offset where to place the popup via the
onGloballyPositioned()
callback of the component under which it should appear. THEN I have to determinine how much space I have for the popup ... that is windowWidth - offset and windowHeight - offset. And the calculations are just nasty if one of them is in Dp and the other in Float ... On top that I have to care for how heigh the window title is (which both is oh not so plain to see from when you're "said" that
LocalAppWindow.current.height
is your friend 🙂
k

Kirill Grouchnikov

05/25/2021, 9:34 PM
This where our early feedback is important to shape the APIs
👍 4
d

Dirk Hoffmann

05/25/2021, 9:37 PM
I'd a) change the
Window
parameter from IntSize to width: Dp, height: Dp (letting height be the content I as a developer will have available (= contentHeight in Dp) b) introduce additional fields in LocalAppWindow.current for • contentHeight: Float // height without the title • contentWidth: Float
b

Brian G

05/26/2021, 12:57 AM
Thanks for listening 😄 . I think everything in the androidx.compose namespace should use Compose types whenever applicable. When dropping down to calling Swing APIs directly, then handling density becomes the developer's problem (same as dealing with legacy Views/Bitmaps/etc. on Android). Makes sense to me.
i

Igor Demin

05/26/2021, 7:46 AM
change the 
Window
 parameter from IntSize to width: Dp, height: Dp
We done this in the new API (that is not available yet)
💚 2
b) introduce additional fields in LocalAppWindow.current for
variants without accessing window directly didn't work? Probably it is better to use them instead of
AppWindow
. Imagine, you have a "custom" window that is not a window at all, but some Box with shadow 🙂 .
1
m

Michael Paus

05/26/2021, 12:13 PM
I’d just like to add that Compose is not all in on Dp. All Canvas data is in pixels and not Dp.
d

Dirk Hoffmann

05/26/2021, 12:17 PM
but if you are down to canvas or Swing, then you (dev) should know what you do ... using pure compose should be as consistant and easy as possible also for the novice developer
m

Michael Paus

05/26/2021, 12:29 PM
Sure, no doubt about that. I just wanted to clarify the statement that “Compose is all in on Dp”. Canvas is a part of Compose and it only deals with pixels.