KevinnZou / compose-webview-multiplatform

WebView for JetBrains Compose Multiplatform
https://kevinnzou.github.io/compose-webview-multiplatform/
Apache License 2.0
318 stars 40 forks source link

Use CEF Browser on Desktop #7

Closed DatL4g closed 8 months ago

DatL4g commented 8 months ago

This PR get's rid of the JavaFX Browser (and all it's problems).

It comes with a breaking change for desktop, as it needs at least an install dir. This can (should) be called in the app init process, not sure how we document this in the README.

It needs to be called once (on app start), it can be called multiple times (executes once only).

LaunchedEffect(Unit) {
    Cef.init(builder = {
        installDir = File("jcef-bundle")
    })
}

Adding the Composable remains the same

KevinnZou commented 8 months ago

Awesome! I will review it soon and merge the PR if nothing goes wrong. Thanks again!

KevinnZou commented 8 months ago

I really appreciate your documentation!

DatL4g commented 8 months ago

I added the execution method without calling the callback.

If you want you can pin me as maintainer, since you're not that familiar with CEF (or desktop development in general) I'm willing to maintain that part.

KevinnZou commented 8 months ago

I added the execution method without calling the callback.

If you want you can pin me as maintainer, since you're not that familiar with CEF (or desktop development in general) I'm willing to maintain that part.

Great! I have invited you!

KevinnZou commented 8 months ago

Hello, I just ran your code locally and encountered the following issue. Is there any configuration that needs to be done? I have already run the initialization code once to download the CEF module, but when I ran it for the second time, I encountered this problem.

Stacktrace

9月 22, 2023 9:55:09 下午 me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
信息: LOCATING |> In progress...
9月 22, 2023 9:55:10 下午 me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
信息: INITIALIZING |> In progress...
9月 22, 2023 9:55:10 下午 me.friwi.jcefmaven.impl.progress.ConsoleProgressHandler handleProgress
信息: INITIALIZED |> In progress...
initialize on Thread[AWT-EventQueue-0,6,main] with library path /Users/KMM/compose-webview-multiplatform/desktopApp/jcef-bundle
[0922/215510.659231:ERROR:iopm_power_source_sampling_event_source.cc(31)] IOPMPowerSource service not found
Exception in thread "AWT-EventQueue-0" java.lang.IllegalAccessError: class org.cef.browser.mac.CefBrowserWindowMac (in unnamed module @0x447a70b2) cannot access class sun.awt.AWTAccessor (in module java.desktop) because module java.desktop does not export sun.awt to unnamed module @0x447a70b2
    at org.cef.browser.mac.CefBrowserWindowMac.getWindowHandle(CefBrowserWindowMac.java:27)
    at org.cef.browser.CefBrowserWr.getWindowHandle(CefBrowserWr.java:337)
    at org.cef.browser.CefBrowserWr.access$600(CefBrowserWr.java:49)
    at org.cef.browser.CefBrowserWr$3.addNotify(CefBrowserWr.java:232)
    at java.desktop/java.awt.Container.addNotify(Unknown Source)
    at java.desktop/javax.swing.JComponent.addNotify(Unknown Source)
    at java.desktop/java.awt.Container.addImpl(Unknown Source)
    at java.desktop/javax.swing.JLayeredPane.addImpl(Unknown Source)
    at java.desktop/java.awt.Container.add(Unknown Source)
    at androidx.compose.ui.awt.ComposeWindowDelegate$_pane$1.add(ComposeWindowDelegate.desktop.kt:74)
    at androidx.compose.ui.awt.SwingPanel_desktopKt$SwingPanel$3.invoke(SwingPanel.desktop.kt:139)
    at androidx.compose.ui.awt.SwingPanel_desktopKt$SwingPanel$3.invoke(SwingPanel.desktop.kt:100)
    at androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:81)
    at androidx.compose.runtime.CompositionImpl$RememberEventDispatcher.dispatchRememberObservers(Composition.kt:1137)
    at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:828)
    at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:849)
    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:625)
    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:537)
    at androidx.compose.runtime.BroadcastFrameClock$FrameAwaiter.resume(BroadcastFrameClock.kt:42)
    at androidx.compose.runtime.BroadcastFrameClock.sendFrame(BroadcastFrameClock.kt:71)
    at androidx.compose.ui.ComposeScene.render(ComposeScene.skiko.kt:456)
    at androidx.compose.ui.awt.ComposeBridge$skikoView$1$onRender$1.invoke(ComposeBridge.desktop.kt:153)
    at androidx.compose.ui.awt.ComposeBridge$skikoView$1$onRender$1.invoke(ComposeBridge.desktop.kt:152)
    at androidx.compose.ui.awt.ComposeBridge.catchExceptions(ComposeBridge.desktop.kt:126)
    at androidx.compose.ui.awt.ComposeBridge.access$catchExceptions(ComposeBridge.desktop.kt:59)
    at androidx.compose.ui.awt.ComposeBridge$skikoView$1.onRender(ComposeBridge.desktop.kt:152)
    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:83)
    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(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Unknown Source)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
    Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.awt.ComposeBridge$coroutineExceptionHandler$1@2262b04b, androidx.compose.runtime.BroadcastFrameClock@6f791fc, StandaloneCoroutine{Cancelling}@23472b07, FlushCoroutineDispatcher@1de9eaa]
objc[66825]: Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x7ffb56c75378) and /Users/kevinnzou/NetEase/KMM/compose-webview-multiplatform/desktopApp/jcef-bundle/Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib (0x109d00220). One of the two will be used. Which one is undefined.
DatL4g commented 8 months ago

MacOS and AWT is always a bit tricky.

If you want to just run it, add this 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

If you package it add this in the build.gradle.kts:

compose {
    desktop {
        ...
        nativeDistributions {
            ...
            includeAllModules = true
        }
    }
}
KevinnZou commented 8 months ago

MacOS and AWT is always a bit tricky.

If you want to just run it, add this 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

If you package it add this in the build.gradle.kts:

compose {
  desktop {
      ...
      nativeDistributions {
          ...
          includeAllModules = true
      }
  }
}

Thank you for your help! The basic sample is currently functioning properly. However, I am experiencing issues when attempting to test the LoadHtml Sample, as it only displays a blank screen. Can you confirm whether it is functioning correctly on your end?

By the way, there is another error. It will not crash the app but will be logged each time it runs.

[0923/095304.768528:ERROR:iopm_power_source_sampling_event_source.cc(31)] IOPMPowerSource service not found
objc[93200]: Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x7ffb56c75378) and /Users/KMM/compose-webview-multiplatform/desktopApp/jcef-bundle/Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib (0x10afcd220). One of the two will be used. Which one is undefined.
DatL4g commented 8 months ago

Fixed loading and seemed like the html style was somewhat incorrect.

KevinnZou commented 8 months ago

Fixed loading and seemed like the html style was somewhat incorrect.

Yes, it appears to be related to the color value format. I have resolved the issue and made the necessary updates to the ReadMe. I believe it is now ready for merging. Is there anything else you would like to include? If not, I intend to merge the pull request and proceed with the release of the new version.

DatL4g commented 8 months ago

I'm ready for merging.

I'll (try) work on new and improved features, as Jetbrains CEF is even better and could solve problems like the css thing and evaluateJavascript but I have to get in touch with the Jetbrains Team first.

KevinnZou commented 8 months ago

I'm ready for merging.

I'll (try) work on new and improved features, as Jetbrains CEF is even better and could solve problems like the css thing and evaluateJavascript but I have to get in touch with the Jetbrains Team first.

Cool! I will merge it soon.

For JetBrains CEF, I also saw many developers recommend it when I was researching JCEF. Feel free to do it if you think it is a better option. Thank you for your contribution!