You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

157 lines
4.6 KiB

package org.jetbrains.compose.desktop.browser
import androidx.compose.ui.unit.IntOffset
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseMotionAdapter
import java.awt.KeyboardFocusManager
import java.nio.ByteBuffer
import org.cef.CefApp
import org.cef.CefClient
import org.cef.CefSettings
import org.cef.browser.CefBrowser
import org.cef.browser.BrowserView
import org.cef.handler.CefFocusHandlerAdapter
import org.jetbrains.skija.Bitmap
import org.jetbrains.skiko.HardwareLayer
class CefBrowserWrapper {
private var offset = IntOffset(0, 0)
private var isFocused = false
private var cefFocus = true
private val browser: BrowserView
public var onInvalidate: (() -> Unit)? = null
constructor(layer: HardwareLayer, startURL: String) {
if (!CefApp.startup(arrayOf(""))) {
throw Error("CEF initialization failed!")
}
val settings = CefSettings()
settings.windowless_rendering_enabled = true
val cefApp = CefApp.getInstance(settings)
val client = cefApp.createClient()
browser = object : BrowserView(layer, client, startURL, null) {
public override fun onBitmapChanged(popup: Boolean, buffer: ByteBuffer, width: Int, height: Int) {
super.onBitmapChanged(popup, buffer, width, height)
onInvalidate?.invoke()
}
}
client.addFocusHandler(object : CefFocusHandlerAdapter() {
public override fun onGotFocus(cefBrowser: CefBrowser) {
if (cefFocus) {
return
}
cefFocus = true
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner()
browser.onFocusGained()
}
public override fun onTakeFocus(cefBrowser: CefBrowser, next: Boolean) {
cefFocus = false
browser.onFocusLost()
}
})
layer.addMouseListener(object : MouseAdapter() {
override fun mousePressed(event: MouseEvent) {
if (isInLayer(event)) {
browser.onMouseEvent(event)
}
}
override fun mouseReleased(event: MouseEvent) {
if (isInLayer(event)) {
browser.onMouseEvent(event)
}
}
})
layer.addMouseMotionListener(object : MouseMotionAdapter() {
override fun mouseMoved(event: MouseEvent) {
if (isInLayer(event)) {
browser.onMouseEvent(event)
}
}
override fun mouseDragged(event: MouseEvent) {
if (isInLayer(event)) {
browser.onMouseEvent(event)
}
}
})
layer.addMouseWheelListener(object : MouseWheelListener {
override fun mouseWheelMoved(event: MouseWheelEvent) {
if (isInLayer(event)) {
browser.onMouseScrollEvent(event)
}
}
})
layer.addKeyListener(object : KeyAdapter() {
override fun keyPressed(event: KeyEvent) {
if (!isFocused) {
return
}
browser.onKeyEvent(event)
}
override fun keyReleased(event: KeyEvent) {
if (!isFocused) {
return
}
browser.onKeyEvent(event)
}
override fun keyTyped(event: KeyEvent) {
if (!isFocused) {
return
}
browser.onKeyEvent(event)
}
})
}
private fun isInLayer(event: MouseEvent): Boolean {
val x = event.x
val y = event.y
if (x > offset.x && y > offset.y) {
return true
}
return false
}
fun loadURL(url: String) {
browser.loadURL(url)
}
fun setFocused(value: Boolean) {
isFocused = value
}
fun getBitmap(): Bitmap {
return browser.getBitmap()
}
fun onLayout(x: Int, y: Int, width: Int, height: Int) {
offset = IntOffset(x, y)
browser.onResized(x, y, width, height)
}
fun onActive() {
browser.onStart()
}
fun onDismiss() {
CefApp.getInstance().dispose()
}
}