Giter Club home page Giter Club logo

kcef's Introduction

KCEF

Kotlin equivalent of jcefmaven with a more modern setup and depending on JetBrains/jcef

Visit the JCEF repo at JetBrains/jcef and the jcefmaven repo at jcefmaven/jcefmaven

Supports

Please take a look at JetBrains/JetBrainsRuntime for a full list of supported targets.

OS Arch
Linux amd64, aarch64
Windows amd64, aarch64
MacOS amd64, aarch64

Installation

Repository

This library is published to Maven Central.

repositories {
    mavenCentral()
    maven("https://jogamp.org/deployment/maven")
}

Version

The version depends on JetBrains/JetBrainsRuntime and JetBrains/jcef.

Take a look at the releases for more details.

Kotlin DSL

dependencies {
    implementation("dev.datlag:kcef:$version")
    
    // or with version catalog
    implementation(libs.kcef)
}

Version catalog

[versions]
kcef = "2023.10.11.1" # put your wanted version here

[libraries]
kcef = { group = "dev.datlag", name = "kcef", version.ref = "kcef" }

Usage

View Compose specific usage here COMPOSE

Initialize

It's recommended to initialize KCEF directly after starting the application.

This way users don't have to wait when the CefBrowser is used in another UI page.

Kotlin

This is recommended to be called in a Coroutine with IO scope.

KCEF.init(
    builder = {
        progress {
            onDownloading {
                println("Download progress: $it%")
            }
        }
        release(true)
    }
)
Java

This is recommended to be called in a IO Thread.

KCEF.initBlocking(
    new KCEFBuilder().progress(
        new KCEFBuilder.InitProgress.Builder().onDownloading(progress -> {
            System.out.println("Download progress: " + progress + "%");
        }).build()
    ).release(true),
    throwable -> {
        if (throwable != null) {
            throwable.printStackTrace();
        }
    },
    () -> {
        System.out.println("Restart required");
    }
);

Create client

Kotlin

If you listen to the onInitialized progress in the KCEF.init method, you can get the client blocking on the Main Thread.

if (initialized) {
    val client = KCEF.newClientBlocking()
}

Otherwise, you should run this in a Coroutine which is not using the Main scope.

KCEF.newClient()

The above methods may throw a CefException, you can use the nullable equivalent instead.

if (initialized) {
    val client: KCEFClient? = KCEF.newClientOrNullBlocking { throwable ->
        throwable?.printStackTrace()
    }
}
/** Needs to be called in  a coroutine */
val client: KCEFClient? = KCEF.newClientOrNull { throwable ->
    throwable?.printStackTrace()
}
Java

If you listen to the onInitialized progress in the KCEF.init method, you can get the client blocking on the Main Thread.

if (initialized) {
    KCEFClient client = KCEF.newClientBlocking();
}

Otherwise, you should run this in a new Thread.

/** Run in a new Thread */
KCEFClient client = KCEF.newClientBlocking();

The above methods may throw a CefException, you can use the nullable equivalent instead.

if (initialized) {
    KCEFClient client = KCEF.newClientOrNullBlocking(throwable -> {
        if (throwable != null) {
            throwable.printStackTrace();
        }
    });
}
/** Should be called in a new Thread */
KCEFClient client = KCEF.newClientOrNullBlocking(throwable -> {
    if (throwable != null) {
        throwable.printStackTrace();
    }
});

Dispose

If the CefClient is no longer used, make sure to dispose it.

client.dispose()

If you no longer need any CEF instance, cleanup up using the KCEF class.

KCEF.disposeBlocking()

or, if you're not sure if the KCEF.init process is finished

KCEF.dispose()

Flags

Some platforms require the addition of specific flags. To use on MacOSX, add the following JVM flags:

--add-opens java.desktop/sun.awt=ALL-UNNAMED
--add-opens java.desktop/sun.lwawt=ALL-UNNAMED
--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED

For gradle project, you can configure it in the build.gradle.kts like that:

afterEvaluate {
    tasks.withType<JavaExec> {
        if (System.getProperty("os.name").contains("Mac")) {
            jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
        }
    }
}

ProGuard

If your application build type uses ProGuard, commonly used for release builds in Java and Kotlin applications, you have to add ProGuard rules for KCEF to work.

-keep class org.cef.** { *; }
-keep class kotlinx.coroutines.swing.SwingDispatcherFactory

Support the project

Github-sponsors PayPal

This is a non-profit project!

Sponsoring to this project means sponsoring to all my projects! So the further text is not to be attributed to this project, but to all my apps and libraries.

Supporting this project helps to keep it up-to-date. You can donate if you want or contribute to the project as well. This shows that the library is used by people, and it's worth to maintain.

kcef's People

Contributors

bulletjet786 avatar datl4g avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

kcef's Issues

KCEF restart required when not running app as an administrator

Some Windows users are getting the restart required message every time they open the app and the KCEF download doesn't start

After some debug sessions we found that it works perfect when running app as an administrator, so I guess the issue is related with write permissions. Any idea on how to fix this?

Thanks in advance

Loading native library from incorrect path when using rendering = CefRendering.OFFSCREEN

When I use rendering = CefRendering.OFFSCREEN it is crashing
client.createBrowser(content, rendering = CefRendering.OFFSCREEN)

It try to load from /IdeaProjects/testapp/natives/macosx-universal/gluegen_rt but correct path is /IdeaProjects/testapp/kcef-bundle/gluegen_rt

kcef-bundle is the install dir for KCEF.init

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: Can't load library: /IdeaProjects/testapp/natives/macosx-universal/gluegen_rt at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2398) at java.base/java.lang.Runtime.load0(Runtime.java:755) at java.base/java.lang.System.load(System.java:1953) at gluegen.rt/com.jogamp.common.jvm.JNILibLoaderBase.loadLibraryInternal(JNILibLoaderBase.java:625) at gluegen.rt/com.jogamp.common.jvm.JNILibLoaderBase.access$000(JNILibLoaderBase.java:64) at gluegen.rt/com.jogamp.common.jvm.JNILibLoaderBase$DefaultAction.loadLibrary(JNILibLoaderBase.java:107) at gluegen.rt/com.jogamp.common.jvm.JNILibLoaderBase.loadLibrary(JNILibLoaderBase.java:488) at gluegen.rt/com.jogamp.common.os.DynamicLibraryBundle$GlueJNILibLoader.loadLibrary(DynamicLibraryBundle.java:427) at gluegen.rt/com.jogamp.common.os.Platform$1.run(Platform.java:321) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at gluegen.rt/com.jogamp.common.os.Platform.<clinit>(Platform.java:290) at jogl.all/com.jogamp.opengl.GLProfile.<clinit>(GLProfile.java:154) at jcef/org.cef.browser.CefBrowserOsr.createGLCanvas(CefBrowserOsr.java:140) at jcef/org.cef.browser.CefBrowserOsr.<init>(CefBrowserOsr.java:98) at jcef/org.cef.browser.CefBrowserOsr.<init>(CefBrowserOsr.java:90) at jcef/org.cef.browser.CefBrowserFactory.create(CefBrowserFactory.java:35) at jcef/org.cef.CefClient.createBrowser(CefClient.java:172) at jcef/org.cef.CefClient.createBrowser(CefClient.java:165) at dev.datlag.kcef.KCEFClient.createBrowser(KCEFClient.kt:70) at dev.datlag.kcef.KCEFClient.createBrowser$default(KCEFClient.kt:66) at ui.common.webview.WebViewLayoutV2Kt$WebViewLayoutV2$1.invoke(WebViewLayoutV2.kt:30) at ui.common.webview.WebViewLayoutV2Kt$WebViewLayoutV2$1.invoke(WebViewLayoutV2.kt:24) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33) at ui.common.webview.WebViewLayoutV2Kt.WebViewInit(WebViewLayoutV2.kt:68) at ui.common.webview.WebViewLayoutV2Kt.WebViewLayoutV2(WebViewLayoutV2.kt:24) at ui.screens.AboutScreenKt$AboutScreen$2.invoke(AboutScreen.kt:55) at ui.screens.AboutScreenKt$AboutScreen$2.invoke(AboutScreen.kt:32) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:116) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33) at androidx.compose.material.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:588) at androidx.compose.material.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:570) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:989) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:476) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:107) at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jb.kt:33) at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:33) at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3303) at androidx.compose.runtime.ComposerImpl.composeContent$runtime(Composer.kt:3236) at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:723) at androidx.compose.runtime.Recomposer.composeInitial$runtime(Recomposer.kt:1071) at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime(Composer.kt:3600) at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:631) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:617) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:499) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:471) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:462) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:446) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:871) at androidx.compose.material.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke-0kLqBqw(Scaffold.kt:570) at androidx.compose.material.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke(Scaffold.kt:452) at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:708) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1613) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596) at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126) at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1613) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:596) at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:122) at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126) at androidx.compose.foundation.layout.FillNode.measure-3p2s80s(Size.kt:699) at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:116) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:252) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:251) at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2304) at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:504) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:260) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:133) at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui(OwnerSnapshotObserver.kt:113) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1613) at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:36) at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620) at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui(LayoutNode.kt:1144) at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui$default(LayoutNode.kt:1135) at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356) at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:514) at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:491) at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:377) at androidx.compose.ui.node.RootNodeOwner$OwnerImpl.measureAndLayout(RootNodeOwner.skiko.kt:289) at androidx.compose.ui.node.RootNodeOwner.measureAndLayout(RootNodeOwner.skiko.kt:187) at androidx.compose.ui.scene.MultiLayerComposeSceneImpl.measureAndLayout(MultiLayerComposeScene.skiko.kt:246) at androidx.compose.ui.scene.BaseComposeScene.doLayout(BaseComposeScene.skiko.kt:211) at androidx.compose.ui.scene.BaseComposeScene.access$doLayout(BaseComposeScene.skiko.kt:51) at androidx.compose.ui.scene.BaseComposeScene.render(BaseComposeScene.skiko.kt:152) at androidx.compose.ui.scene.ComposeSceneMediator$DesktopSkikoView.onRender(ComposeSceneMediator.desktop.kt:490) at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:548) at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54) at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invokeSuspend(MetalRedrawer.kt:82) at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt) at org.jetbrains.skiko.redrawer.MetalRedrawer$frameDispatcher$1.invoke(MetalRedrawer.kt) at org.jetbrains.skiko.FrameDispatcher$job$1.invokeSuspend(FrameDispatcher.kt:33) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@128923f0, SwingDispatcher@51e6b362] JCEF_V(14:27:903): CefBrowser_N: org.cef.browser.CefBrowserOsr@1927a31e: native part of browser wasn't created yet, browser will be closed immediately after creation

Initialization fails on Ubuntu (23.10)

Expected behavior:

Initializing as per the example would download and initialize on Ubuntu (23.10) / OpenJDK 17:

e.g.

KCEF.init(builder = {
                                installDir(File("kcef-bundle"))
                                progress {
                                    onDownloading {
                                        println("KCEF downloading: $it to ${File("kcef-bundle").absolutePath}")
                                        downloading = max(it, 0F)
                                    }
                                    onInitialized {
                                        println("KCEF initialized!")
                                        initialized = true
                                    }
                                }
                                settings {
                                    cachePath = File("cache").absolutePath
                                }
                            }, onError = {
                                println("KCEF - ERROR!")
                                it?.printStackTrace()
                            }, onRestartRequired = {
                                restartRequired = true
                            })

Observed behavior:

KCEF downloading: 100.0 to /home/mike/StudioProjects/UstadMobile/app-desktop/kcef-bundle
JCEF(04:51:619): initialized stderr logger, severity=LOGSEVERITY_DEFAULT
JCEF_I(04:51:619): CefApp: set state NEW
JCEF_I(04:51:621): CefApp: set state INITIALIZING
JCEF_V(04:51:621): Initialize CefApp on Thread[CefInitialize-thread,5,main]
[0131/100451.688536:WARNING:policy_logger.cc(151)] :components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc(88) Could not create policy manager as CBCM is not enabled.
[0131/100451.699364:ERROR:browser_main_loop.cc(276)] GLib-GObject: cannot register existing type 'GdkDisplayManager'
[0131/100451.699388:ERROR:browser_main_loop.cc(276)] GLib: g_once_init_leave: assertion 'result != 0' failed
[0131/100451.699396:ERROR:browser_main_loop.cc(276)] GLib-GObject: g_object_new_with_properties: assertion 'G_TYPE_IS_OBJECT (object_type)' failed
libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[0131/100451.868560:WARNING:gpu_memory_buffer_support_x11.cc(49)] dri3 extension not supported.

It seems like "GLib-GObject: cannot register existing type 'GdkDisplayManager'" is the important one. I have found discussion about this affecting Python JuliaGraphics/Gtk.jl#192 .

When I attempt to use the browser (via the compose multiplatform webview), I get this:

JCEF_V(06:10:809): CefMessageRouter_N: org.cef.browser.CefMessageRouter_N@287b174: add delayed action addHandler
JCEF_E(06:10:830): CefBrowser_N: org.cef.browser.CefBrowserWr@2297a5f8: can't invoke native method 'setWindowVisibility' before native context initialized
JCEF_W(06:10:831): failed to retrieve platform window handle
JCEF_E(06:10:831): CefBrowser_N: org.cef.browser.CefBrowserWr@2297a5f8: can't invoke native method 'setParent' before native context initialized
JCEF_E(06:10:832): CefBrowser_N: org.cef.browser.CefBrowserWr@2297a5f8: can't invoke native method 'wasResized' before native context initialized
JCEF_V(06:10:834): CefMessageRouter_N: org.cef.browser.CefMessageRouter_N@3ecbb34a: add delayed action addHandler
JCEF_E(06:10:835): CefBrowser_N: org.cef.browser.CefBrowserWr@aac3d3a: can't invoke native method 'setWindowVisibility' before native context initialized
J

packageDmg and install run init KCEF error

InstallationDirectory
at dev.datlag.kcef.KCEFException$installationDirectory.<clinit>(KCEFException.kt)at dev.datlag.kcef.KCEFBuilder.install$kcef(KCEFBuilder.kt:192)at dev.datlag.kcef.KCEF$init$installResult$1.invokeSuspend(KCEF.kt:105)at dev.datlag.kcef.KCEF$init$installResult$1.invoke(KCEF.kt)at dev.datlag.kcef.KCEF$init$installResult$1.invoke(KCEF.kt)at dev.datlag.kcef.common.ExtendCoroutineKt$suspendCatching$2.invokeSuspend(ExtendCoroutine.kt:19)at dev.datlag.kcef.common.ExtendCoroutinekt$suspendCatching$2.invoke(ExtendCoroutine.kt)at dev.datlag.kcef.common.ExtendCoroutineKt$suspendCatching$2.invokelExtendCoroutine.ktat kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)at dev.datlag.kcef.common.ExtendCoroutinekt.suspendCatching(ExtendCoroutine.kt:16)at dev.datlag.kcef.KCEF.init(KCEF.kt:104)
at dev.datlag.kcef.KCEF.init(KCEF.kt:45)at ComposableSingletons$MainKt$lambda-1$1$1$1$1.invokeSuspend(main.kt:43)at kotlin.coroutines.ivm.internal.BaseContinuationlmpl.resumeWith(Continuationlmpl.kt:33)at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)at kotlinx.coroutines.scheduling.Tasklmpl.run(Tasks.kt:103)at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793at kotlinx.coroutines,scheduling,CoroutineScheduler$Worker,runWorkerlCoroutineScheduler.kt:697)at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)

build release dmg ,install and run KCEF.init error

this is my KCEF Init

Window(
        title = "玩 Android",
        icon = painterResource("android_studio.png"),
        state = rememberWindowState(width = 350.dp, height = 700.dp),
        onCloseRequest = ::exitApplication,
    ) {
        window.minimumSize = Dimension(350, 700)
        var restartRequired by remember { mutableStateOf(false) }
        var downloading by remember { mutableStateOf(0f) }
        var initialized by remember { mutableStateOf(false) }
        var failedMsg by remember { mutableStateOf("") }
        LaunchedEffect(Unit) {
            withContext(Dispatchers.IO) {
                KCEF.init(builder = {
                    progress {
                        onDownloading {
                            downloading = max(it, 0f)
                        }
                        onInitialized {
                            initialized = true
                        }
                    }
                }, onError = {
                    failedMsg = it?.stackTraceToString().orEmpty()
                    it?.printStackTrace()
                }, onRestartRequired = {
                    restartRequired = true
                })
            }
        }
        if (restartRequired) {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center, content = {
                Text(text = failedMsg)
            })
        } else {
            if (initialized) {
                App()
            } else {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center,
                    content = {
                        Text(text = "Downloading $downloading%")
                    })
            }
        }
        DisposableEffect(Unit) {
            onDispose {
                KCEF.disposeBlocking()
            }
        }
    }

this is my build.gradle

compose.desktop {
    application {
        buildTypes.release.proguard {
            configurationFiles.from("compose-desktop.pro")
        }
        mainClass = "MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "玩 Android"
            packageVersion = "1.0.0"
            macOS {
                dockName = "玩 Android"
                setDockNameSameAsPackageName = true
                bundleID = "org.liupack.wanandroid"
                iconFile.set(project.file("launcher/icon.icns"))
            }
            linux {
                iconFile.set(project.file("launcher/icon.png"))
            }
            windows {
                iconFile.set(project.file("launcher/icon.ico"))
            }
        }
    }
}

afterEvaluate {
    tasks.withType<JavaExec> {
        jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
        jvmArgs(
            "--add-opens", "java.desktop/java.awt.peer=ALL-UNNAMED"
        )

        if (System.getProperty("os.name").contains("Mac")) {
            jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
        }
    }
}

Does TarGzExtractor download and bundle only what is needed

I was just wondering if the TarGzExtractor is downloading only what is needed for JCEF to be started.

It looks like its including most of the files from JetBrainsRuntime but I was not 100% sure if it actually needs all this.

For mac I am able to reduce this to just the following and its starting fine

  • /Contents/Frameworks
  • /Contents/Home/lib/libjcef.dylib

Cannot clone submodule

I'd like to fork and potentially contribute to this library. However, it seems to depend on a submodule here. When I tried to git clone --recursive I got an error for the submodule:

Please make sure you have the correct access rights
and the repository exists.

Bug: Unable to add app handler?

It is possible to call KCEF.init with a builder that has an app handler supplied, like:

KCEF.init(
    builder = {
        addAppHandler(myAppHandler)
    }
)

However, none of the overridden methods of myAppHandler appear to be called.

This appears to be because of the line at line 93 of KCEF.kt:

currentBuilder.addAppHandler(AppHandler)

While the name of addAppHandler seems to suggest that multiple app handlers can be added, by looking at its implementation in CefAppHandler.java it seems that this is not true, and any subsequent call to it will remove any previously set app handler.
So it looks like the issue may be that this call in KCEF.kt removes any app handler that is added in the builder.

Creatting KCEFClient failing

OS: Mac M1 13.6.4 (22G513)
JDK: correto-17.0.10

When i try to create KCEFClient after successful initialization of KCEF an error occurs

Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: 'void org.cef.browser.CefMessageRouter_N.N_Initialize(org.cef.browser.CefMessageRouter$CefMessageRouterConfig)'
	at org.cef.browser.CefMessageRouter_N.N_Initialize(Native Method)
	at org.cef.browser.CefMessageRouter_N.stateHasChanged(CefMessageRouter_N.java:30)
	at org.cef.CefApp.onInitialization(CefApp.java:213)
	at org.cef.browser.CefMessageRouter_N.<init>(CefMessageRouter_N.java:24)
	at org.cef.browser.CefMessageRouter.create(CefMessageRouter.java:212)
	at org.cef.browser.CefMessageRouter.create(CefMessageRouter.java:197)

It happens due to creating of CefMessageRouter in KCEFClient init block

val router = CefMessageRouter.create(
            CefMessageRouter.CefMessageRouterConfig("cefQueryEvaluate", "cefQueryEvaluateCancel")
)

but CefClient creating without CefMessageRouter finishes successful

How to solve the problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.