Skip to content
Permalink
Browse files

Merge pull request #289 from scenerygraphics/swing-hidpi-fixes

Swing HiDPI fixes
  • Loading branch information
skalarproduktraum committed Dec 18, 2019
2 parents 476d3ff + 4e4ea7f commit 7d3b58ab709ec5054d494bbac0c9740e2ab6748d
@@ -31,8 +31,7 @@ import java.util.concurrent.CopyOnWriteArrayList
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicInteger
import javax.imageio.ImageIO
import javax.swing.JFrame
import javax.swing.SwingUtilities
import javax.swing.BorderFactory
import kotlin.collections.LinkedHashMap
import kotlin.math.max
import kotlin.math.roundToInt
@@ -203,6 +202,8 @@ open class OpenGLRenderer(hub: Hub,
(drawable as? GLOffscreenAutoDrawable)?.setSurfaceSize(window.width, window.height)
}

logger.debug("queryResize: $lastWidth/$lastHeight")

lastResize = -1L
}
}
@@ -393,17 +394,29 @@ open class OpenGLRenderer(hub: Hub,
canvas!!.glAutoDrawable
*/
drawable = if (panel is SceneryJPanel) {
val canvas = ClearGLWindow("", width, height, null)
val surfaceScale = hub.get<Settings>()?.get("Renderer.SurfaceScale", GLVector(1.0f, 1.0f)) ?: GLVector(1.0f, 1.0f)
this.window.width = (panel.width * surfaceScale.x()).toInt()
this.window.height = (panel.height * surfaceScale.y()).toInt()

panel.panelWidth = this.window.width
panel.panelHeight = this.window.height

logger.debug("Surface scale: $surfaceScale")
val canvas = ClearGLWindow("",
this.window.width,
this.window.height, null)
canvas.newtCanvasAWT.shallUseOffscreenLayer = true
panel.component = canvas.newtCanvasAWT
panel.cglWindow = canvas
panel.layout = BorderLayout()
panel.preferredSize = Dimension(
(window.width * surfaceScale.x()).toInt(),
(window.height * surfaceScale.y()).toInt())
canvas.newtCanvasAWT.preferredSize = panel.preferredSize

panel.border = BorderFactory.createEmptyBorder()
panel.add(canvas.newtCanvasAWT, BorderLayout.CENTER)
panel.preferredSize = Dimension(width, height)

val frame = SwingUtilities.getAncestorOfClass(JFrame::class.java, panel) as JFrame
frame.preferredSize = Dimension(width, height)
frame.pack()

cglWindow = canvas
canvas.glAutoDrawable
@@ -438,9 +451,10 @@ open class OpenGLRenderer(hub: Hub,
embedIn?.let { panel ->
panel.imageScaleY = -1.0f
window = panel.init(resizeHandler)
val surfaceScale = hub.get<Settings>()?.get("Renderer.SurfaceScale", GLVector(1.0f, 1.0f)) ?: GLVector(1.0f, 1.0f)

window.width = panel.panelWidth
window.height = panel.panelHeight
window.width = (panel.panelWidth * surfaceScale.x()).toInt()
window.height = (panel.panelHeight * surfaceScale.y()).toInt()
}

resizeHandler.lastWidth = window.width
@@ -758,7 +772,14 @@ open class OpenGLRenderer(hub: Hub,
this.joglDrawable = pDrawable

if (mustRecreateFramebuffers) {
logger.info("Recreating framebuffers (${window.width}x${window.height}")
val surfaceScale = hub?.get<Settings>()?.get("Renderer.SurfaceScale", GLVector(1.0f, 1.0f)) ?: GLVector(1.0f, 1.0f)
logger.info("Recreating framebuffers (${window.width}x${window.height})")

// FIXME: This needs to be done here in order to be able to run on HiDPI screens correctly
if(embedIn != null) {
cglWindow?.newtCanvasAWT?.setBounds(0, 0, window.width, window.height)
}

renderpasses = prepareRenderpasses(renderConfig, window.width, window.height)
flow = renderConfig.createRenderpassFlow()

@@ -2527,8 +2548,19 @@ open class OpenGLRenderer(hub: Hub,
lastResizeTimer = Timer()
lastResizeTimer.schedule(object : TimerTask() {
override fun run() {
window.width = newWidth
window.height = newHeight
val surfaceScale = hub?.get<Settings>()?.get("Renderer.SurfaceScale", GLVector(1.0f, 1.0f))
?: GLVector(1.0f, 1.0f)

val panel = embedIn

if(panel is SceneryJPanel && panel.width != (newWidth/surfaceScale.x()).toInt() && panel.height != (newWidth/surfaceScale.y()).toInt()) {
logger.debug("Panel is ${panel.width}x${panel.height} vs $newWidth x $newHeight")
window.width = (newWidth * surfaceScale.x()).toInt()
window.height = (newHeight * surfaceScale.y()).toInt()
} else {
window.width = newWidth
window.height = newHeight
}

logger.debug("Resizing window to ${newWidth}x$newHeight")
mustRecreateFramebuffers = true
@@ -22,7 +22,7 @@ import org.scijava.ui.behaviour.InputTriggerMap
* @author Ulrik Günther <hello@ulrik.is>
*/
@CanHandleInputFor([SceneryWindow.GLFWWindow::class])
open class GLFWMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerBase(), AutoCloseable, ExtractsNatives {
open class GLFWMouseAndKeyHandler(var hub: Hub?) : MouseAndKeyHandlerBase(), AutoCloseable, ExtractsNatives {
/** store os name */
private var os = ""

@@ -475,10 +475,11 @@ open class GLFWMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
scrollCallback.close()
}

override fun attach(window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
override fun attach(hub: Hub?, window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
val handler: MouseAndKeyHandlerBase
when(window) {
is SceneryWindow.GLFWWindow -> {
this.hub = hub
handler = this

handler.setInputMap(inputMap)
@@ -491,6 +492,7 @@ open class GLFWMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
}

is SceneryWindow.HeadlessWindow -> {
this.hub = hub
handler = this

handler.setInputMap(inputMap)
@@ -52,7 +52,7 @@ class InputHandler(scene: Scene, renderer: Renderer, override var hub: Hub?, for
init {
if(forceHandler != null) {
handler = forceHandler.getConstructor(Hub::class.java)?.newInstance(hub) as? MouseAndKeyHandlerBase
handler?.attach(window, inputMap, behaviourMap)
handler?.attach(hub, window, inputMap, behaviourMap)
} else {
when (window) {
is SceneryWindow.UninitializedWindow -> {
@@ -69,7 +69,7 @@ class InputHandler(scene: Scene, renderer: Renderer, override var hub: Hub?, for
logger.debug("Found potential input handlers: ${handlers.joinToString { "${it.simpleName} -> ${it.getAnnotation(CanHandleInputFor::class.java).windowTypes.joinToString()}" }}")
val candidate = handlers.find { it.getAnnotation(CanHandleInputFor::class.java).windowTypes.contains(window::class) }
handler = candidate?.getConstructor(Hub::class.java)?.newInstance(hub) as MouseAndKeyHandlerBase?
handler?.attach(window, inputMap, behaviourMap)
handler?.attach(hub, window, inputMap, behaviourMap)
}
}
}
@@ -3,6 +3,7 @@ package graphics.scenery.controls
import com.jogamp.newt.awt.NewtCanvasAWT
import com.jogamp.newt.event.*
import graphics.scenery.Hub
import graphics.scenery.Settings
import graphics.scenery.backends.SceneryWindow
import graphics.scenery.utils.ExtractsNatives
import net.java.games.input.ControllerListener
@@ -16,7 +17,7 @@ import org.scijava.ui.behaviour.InputTriggerMap
* @author Ulrik Günther <hello@ulrik.is>
*/
@CanHandleInputFor([SceneryWindow.ClearGLWindow::class, SceneryWindow.SwingWindow::class, SceneryWindow.JOGLDrawable::class])
open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerBase(), MouseListener, KeyListener, WindowListener, ControllerListener, ExtractsNatives {
open class JOGLMouseAndKeyHandler(var hub: Hub?) : MouseAndKeyHandlerBase(), MouseListener, KeyListener, WindowListener, ControllerListener, ExtractsNatives {
/** store os name */
private var os = ""

@@ -114,10 +115,12 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming MouseEvent
*/
override fun mouseMoved(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

mouseX = e.x
mouseY = e.y
mouseX = (e.x * supersamplingFactor).toInt()
mouseY = (e.y * supersamplingFactor).toInt()

for (drag in activeKeyDrags)
drag.behaviour.drag(mouseX, mouseY)
@@ -138,11 +141,13 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming MouseEvent
*/
override fun mouseClicked(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

val mask = getMask(e)
val x = e.x
val y = e.y
val x = (e.x * supersamplingFactor).toInt()
val y = (e.y * supersamplingFactor).toInt()

val clickMask = mask and InputTrigger.DOUBLE_CLICK_MASK.inv()
buttonClicks
@@ -156,11 +161,13 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming mouse event
*/
override fun mouseWheelMoved(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

val mask = getMask(e)
val x = e.x
val y = e.y
val x = (e.x * supersamplingFactor).toInt()
val y = (e.y * supersamplingFactor).toInt()
val wheelRotation = e.rotation

/*
@@ -190,10 +197,12 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming mouse event
*/
override fun mouseReleased(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

val x = e.x
val y = e.y
val x = (e.x * supersamplingFactor).toInt()
val y = (e.y * supersamplingFactor).toInt()

for (drag in activeButtonDrags)
drag.behaviour.end(x, y)
@@ -206,10 +215,12 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming mouse event
*/
override fun mouseDragged(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

val x = e.x
val y = e.y
val x = (e.x * supersamplingFactor).toInt()
val y = (e.y * supersamplingFactor).toInt()

for (drag in activeButtonDrags) {
drag.behaviour.drag(x, y)
@@ -231,11 +242,13 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
* @param[e] The incoming mouse event
*/
override fun mousePressed(e: MouseEvent) {
val supersamplingFactor = hub?.get<Settings>()?.get("Renderer.SupersamplingFactor", 1.0f) ?: 1.0f

update()

val mask = getMask(e)
val x = e.x
val y = e.y
val x = (e.x * supersamplingFactor).toInt()
val y = (e.y * supersamplingFactor).toInt()

for (drag in buttonDrags) {
if (drag.buttons.matches(mask, pressedKeys)) {
@@ -383,14 +396,15 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
winPressed = false
}

override fun attach(window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
override fun attach(hub: Hub?, window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
val handler: MouseAndKeyHandlerBase
when(window) {
is SceneryWindow.SwingWindow -> {
val component = window.panel.component
val cglWindow = window.panel.cglWindow

if(component is NewtCanvasAWT && cglWindow != null) {
this.hub = hub
handler = this

handler.setInputMap(inputMap)
@@ -399,7 +413,7 @@ open class JOGLMouseAndKeyHandler(protected var hub: Hub?) : MouseAndKeyHandlerB
cglWindow.addKeyListener(handler)
cglWindow.addMouseListener(handler)
} else {
handler = SwingMouseAndKeyHandler()
handler = SwingMouseAndKeyHandler(hub)

handler.setInputMap(inputMap)
handler.setBehaviourMap(behaviourMap)
@@ -2,6 +2,7 @@ package graphics.scenery.controls

import gnu.trove.map.hash.TIntLongHashMap
import gnu.trove.set.hash.TIntHashSet
import graphics.scenery.Hub
import graphics.scenery.backends.SceneryWindow
import graphics.scenery.controls.behaviours.GamepadBehaviour
import graphics.scenery.utils.ExtractsNatives
@@ -331,7 +332,7 @@ open class MouseAndKeyHandlerBase : ControllerListener, ExtractsNatives {
* Attaches this handler to a given [window], with input bindings and behaviours given in [inputMap] and
* [behaviourMap]. MouseAndKeyHandlerBase itself cannot be attached to any windows.
*/
open fun attach(window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
open fun attach(hub: Hub?, window: SceneryWindow, inputMap: InputTriggerMap, behaviourMap: BehaviourMap): MouseAndKeyHandlerBase {
throw UnsupportedOperationException("MouseAndKeyHandlerBase cannot be attached to a window.")
}

0 comments on commit 7d3b58a

Please sign in to comment.
You can’t perform that action at this time.