@@ -18,6 +18,10 @@ import javax.swing.JPanel
1818import javax.swing.SwingUtilities
1919import javax.swing.SwingUtilities.isEventDispatchThread
2020import javax.swing.UIManager
21+ import javax.swing.event.AncestorEvent
22+ import javax.swing.event.AncestorListener
23+ import kotlin.math.ceil
24+ import kotlin.math.floor
2125
2226actual open class SkiaLayer internal constructor(
2327 externalAccessibleFactory : ((Component ) -> Accessible )? = null ,
@@ -133,6 +137,16 @@ actual open class SkiaLayer internal constructor(
133137 @Suppress(" LeakingThis" )
134138 add(backedLayer)
135139
140+ addAncestorListener(object : AncestorListener {
141+ override fun ancestorAdded (event : AncestorEvent ? ) = Unit
142+
143+ override fun ancestorRemoved (event : AncestorEvent ? ) = Unit
144+
145+ override fun ancestorMoved (event : AncestorEvent ? ) {
146+ revalidate()
147+ }
148+ })
149+
136150 backedLayer.addHierarchyListener {
137151 if (it.changeFlags and HierarchyEvent .SHOWING_CHANGED .toLong() != 0L ) {
138152 checkShowing()
@@ -143,7 +157,7 @@ actual open class SkiaLayer internal constructor(
143157 addPropertyChangeListener(" graphicsContextScaleTransform" ) {
144158 Logger .debug { " graphicsContextScaleTransform changed for $this " }
145159 latestReceivedGraphicsContextScaleTransform = it.newValue as AffineTransform
146- redrawer?.syncSize ()
160+ revalidate ()
147161 notifyChange(PropertyKind .ContentScale )
148162
149163 // Workaround for JBR-5259
@@ -191,7 +205,7 @@ actual open class SkiaLayer internal constructor(
191205 redrawer?.setVisible(isShowing)
192206 }
193207 if (isShowing) {
194- redrawer?.syncSize ()
208+ redrawer?.syncBounds ()
195209 repaint()
196210 }
197211 }
@@ -252,7 +266,7 @@ actual open class SkiaLayer internal constructor(
252266 private val redrawerManager = RedrawerManager <Redrawer >(properties.renderApi) { renderApi, oldRedrawer ->
253267 oldRedrawer?.dispose()
254268 val newRedrawer = renderFactory.createRedrawer(this , renderApi, analytics, properties)
255- newRedrawer.syncSize ()
269+ newRedrawer.syncBounds ()
256270 newRedrawer
257271 }
258272
@@ -316,12 +330,16 @@ actual open class SkiaLayer internal constructor(
316330
317331 override fun doLayout () {
318332 Logger .debug { " doLayout on $this " }
319- backedLayer.setBounds(0 , 0 , roundSize(width), roundSize(height))
333+ backedLayer.setBounds(
334+ 0 ,
335+ 0 ,
336+ adjustSizeToContentScale(contentScale, width),
337+ adjustSizeToContentScale(contentScale, height)
338+ )
320339 backedLayer.validate()
321- redrawer?.syncSize ()
340+ redrawer?.syncBounds ()
322341 }
323342
324-
325343 override fun paint (g : java.awt.Graphics ) {
326344 Logger .debug { " Paint called on: $this " }
327345 checkContentScale()
@@ -338,7 +356,7 @@ actual open class SkiaLayer internal constructor(
338356 // Please note that calling redraw during layout might break software renderers,
339357 // so applying this fix only for Direct3D case.
340358 if (renderApi == GraphicsApi .DIRECT3D && isShowing) {
341- redrawer?.syncSize ()
359+ redrawer?.syncBounds ()
342360 tryRedrawImmediately()
343361 }
344362 }
@@ -579,18 +597,6 @@ actual open class SkiaLayer internal constructor(
579597 }
580598 }
581599
582- private fun roundSize (value : Int ): Int {
583- var rounded = value * contentScale
584- val diff = rounded - rounded.toInt()
585- // We check values close to 0.5 and edit the size to avoid white lines glitch
586- if (diff > 0.4f && diff < 0.6f ) {
587- rounded = value + 1f
588- } else {
589- rounded = value.toFloat()
590- }
591- return rounded.toInt()
592- }
593-
594600 fun requestNativeFocusOnAccessible (accessible : Accessible ? ) {
595601 backedLayer.requestNativeFocusOnAccessible(accessible)
596602 }
@@ -637,3 +643,28 @@ internal fun Canvas.clipRectBy(rectangle: ClipRectangle, scale: Float) {
637643 true
638644 )
639645}
646+
647+ // TODO Recheck this method validity in 2 cases - full Window content, and a Panel content
648+ // issue: https://youtrack.jetbrains.com/issue/CMP-5447/Window-white-line-on-the-bottom-before-resizing
649+ // suggestions: https://github.com/JetBrains/skiko/pull/988#discussion_r1763219300
650+ // possible issues:
651+ // - isn't obvious why 0.4/0.6 is used
652+ // - increasing it by one, we avoid 1px white line, but we cut the content by 1px
653+ // - it probably doesn't work correctly in a Panel content case - we don't need to adjust in this case
654+ /* *
655+ * Increases the value of width/height by one if necessary,
656+ * to avoid 1px white line between Canvas and the bounding window.
657+ * 1px white line appears when users resizes the window:
658+ * - it is resized in Px (125, 126, 127,...)
659+ * - the canvas is resized in Points (with 1.25 scale, it will be 100, 100, 101)
660+ * during converting Int AWT points to actual screen pixels.
661+ */
662+ private fun adjustSizeToContentScale (contentScale : Float , value : Int ): Int {
663+ val scaled = value * contentScale
664+ val diff = scaled - floor(scaled)
665+ return if (diff > 0.4f && diff < 0.6f ) {
666+ value + 1
667+ } else {
668+ value
669+ }
670+ }
0 commit comments