From cb34500d68fecdf53e671f8dea9521038703c1c9 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 03:01:32 +0200 Subject: [PATCH 1/6] feat: accelerated paint --- java/org/cef/CefBrowserSettings.java | 19 +++++ java/org/cef/CefClient.java | 10 +++ java/org/cef/browser/CefBrowser.java | 9 +++ java/org/cef/browser/CefBrowserOsr.java | 6 ++ java/org/cef/browser/CefBrowser_N.java | 9 +++ .../cef/handler/CefAcceleratedPaintInfo.java | 43 ++++++++++++ .../cef/handler/CefOsrRendererSettings.java | 69 +++++++++++++++++++ java/org/cef/handler/CefRenderHandler.java | 11 +++ .../cef/handler/CefRenderHandlerAdapter.java | 4 ++ native/CefBrowser_N.cpp | 14 +++- native/CefBrowser_N.h | 9 +++ native/jni_util.cpp | 14 ++++ native/jni_util.h | 5 ++ native/render_handler.cpp | 42 +++++++++++ native/render_handler.h | 4 ++ 15 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 java/org/cef/handler/CefAcceleratedPaintInfo.java create mode 100644 java/org/cef/handler/CefOsrRendererSettings.java diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java index 8733a418..67a184b3 100644 --- a/java/org/cef/CefBrowserSettings.java +++ b/java/org/cef/CefBrowserSettings.java @@ -4,6 +4,8 @@ package org.cef; +import org.cef.handler.CefOsrRendererSettings; + /** * Browser initialization settings. Specify NULL or 0 to get the recommended * default values. The consequences of using custom values may not be well @@ -20,12 +22,29 @@ public class CefBrowserSettings { */ public int windowless_frame_rate = 0; + /** + * Set to true to enable shared texture rendering. When enabled, the browser + * will render to a shared texture that can be accessed by the host application + * for hardware-accelerated compositing. This is supported on Windows via D3D11, + * macOS via Metal/OpenGL, and Linux via native buffers. + */ + public boolean shared_texture_enabled = false; + + /** + * Set to true to enable external begin frame scheduling. When enabled, the + * client must call CefBrowserHost::SendExternalBeginFrame to trigger frame + * rendering at the specified frame rate. + */ + public boolean external_begin_frame_enabled = false; + public CefBrowserSettings() {} @Override public CefBrowserSettings clone() { CefBrowserSettings tmp = new CefBrowserSettings(); tmp.windowless_frame_rate = windowless_frame_rate; + tmp.shared_texture_enabled = shared_texture_enabled; + tmp.external_begin_frame_enabled = external_begin_frame_enabled; return tmp; } } diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 687be93d..b9fc4559 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -17,6 +17,7 @@ import org.cef.callback.CefMenuModel; import org.cef.callback.CefPrintDialogCallback; import org.cef.callback.CefPrintJobCallback; +import org.cef.handler.CefAcceleratedPaintInfo; import org.cef.handler.CefClientHandler; import org.cef.handler.CefContextMenuHandler; import org.cef.handler.CefDialogHandler; @@ -768,6 +769,15 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, realHandler.onPaint(browser, popup, dirtyRects, buffer, width, height); } + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { + if (browser == null) return; + + CefRenderHandler realHandler = browser.getRenderHandler(); + if (realHandler != null) + realHandler.onAcceleratedPaint(browser, popup, dirtyRects, info); + } + @Override public void addOnPaintListener(Consumer listener) {} diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index 96f8e1ab..16e22749 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -405,6 +405,15 @@ public void runFileDialog(FileDialogMode mode, String title, String defaultFileP */ public void setWindowlessFrameRate(int frameRate); + /** + * Send an external begin frame to trigger frame rendering when external begin frame + * scheduling is enabled. This method should be called at the desired frame rate when + * CefBrowserSettings.external_begin_frame_enabled is set to true. + * + * @throws UnsupportedOperationException if not supported + */ + public void sendExternalBeginFrame(); + /** * Returns the maximum rate in frames per second (fps) that {@code CefRenderHandler::onPaint} * will be called for a windowless browser. The actual fps may be lower if the browser cannot diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index b999b6ba..907271b1 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -19,6 +19,7 @@ import org.cef.CefClient; import org.cef.OS; import org.cef.callback.CefDragData; +import org.cef.handler.CefAcceleratedPaintInfo; import org.cef.handler.CefRenderHandler; import org.cef.handler.CefScreenInfo; @@ -409,6 +410,11 @@ public void run() { } } + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { + // TODO: Implement example for accelerated paint + } + @Override public boolean onCursorChange(CefBrowser browser, final int cursorType) { SwingUtilities.invokeLater(new Runnable() { diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index e46327f1..8df594f6 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -799,6 +799,14 @@ public void setWindowlessFrameRate(int frameRate) { } } + public void sendExternalBeginFrame() { + try { + N_SendExternalBeginFrame(); + } catch (UnsatisfiedLinkError ule) { + ule.printStackTrace(); + } + } + public CompletableFuture getWindowlessFrameRate() { final CompletableFuture future = new CompletableFuture<>(); try { @@ -882,5 +890,6 @@ private final native void N_DragTargetDragEnter( private final native void N_SetParent(long windowHandle, Component canvas); private final native void N_NotifyMoveOrResizeStarted(); private final native void N_SetWindowlessFrameRate(int frameRate); + private final native void N_SendExternalBeginFrame(); private final native void N_GetWindowlessFrameRate(IntCallback frameRateCallback); } diff --git a/java/org/cef/handler/CefAcceleratedPaintInfo.java b/java/org/cef/handler/CefAcceleratedPaintInfo.java new file mode 100644 index 00000000..bd8aeedc --- /dev/null +++ b/java/org/cef/handler/CefAcceleratedPaintInfo.java @@ -0,0 +1,43 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Structure representing shared texture info for accelerated painting. + */ +public class CefAcceleratedPaintInfo { + /** + * Shared texture handle. The meaning depends on the platform: + * - Windows: HANDLE to a texture that can be opened with D3D11 OpenSharedResource + * - macOS: IOSurface pointer that can be opened with Metal or OpenGL + * - Linux: Contains several planes, each with an fd to the underlying system native buffer + */ + public long shared_texture_handle = 0; + + /** + * Format of the shared texture. + */ + public int format = 0; + + /** + * Size information for the shared texture. + */ + public int width = 0; + public int height = 0; + + public CefAcceleratedPaintInfo() {} + + public CefAcceleratedPaintInfo(long shared_texture_handle, int format, int width, int height) { + this.shared_texture_handle = shared_texture_handle; + this.format = format; + this.width = width; + this.height = height; + } + + @Override + public CefAcceleratedPaintInfo clone() { + return new CefAcceleratedPaintInfo(shared_texture_handle, format, width, height); + } +} diff --git a/java/org/cef/handler/CefOsrRendererSettings.java b/java/org/cef/handler/CefOsrRendererSettings.java new file mode 100644 index 00000000..a417f03d --- /dev/null +++ b/java/org/cef/handler/CefOsrRendererSettings.java @@ -0,0 +1,69 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Settings for off-screen rendering (OSR) configuration. + * Based on CEF's OsrRendererSettings structure. + */ +public class CefOsrRendererSettings { + + /** + * If true draw a border around update rectangles. + */ + public boolean show_update_rect = false; + + /** + * If true return real screen bounds from GetRootScreenRect/GetScreenInfo. + * - Allows window.outerWidth/Height and window.screenX/Y to return correct values. + * - Allows JavaScript window.moveTo/By() and window.resizeTo/By() to provide + * bounds that include the window frame. + * - Causes HTML select popups to be cropped (limitation of implementation). + */ + public boolean real_screen_bounds = true; + + /** + * Background color. Enables transparency if the alpha component is 0. + * 32-bit ARGB color value, not premultiplied. + */ + public int background_color = 0; + + /** + * Render using shared textures. Supported on Windows only via D3D11. + * When enabled, the browser will render to a shared texture that can be + * accessed by the host application for hardware-accelerated compositing. + */ + public boolean shared_texture_enabled = false; + + /** + * Client implements a BeginFrame timer by calling + * CefBrowserHost::SendExternalBeginFrame at the specified frame rate. + */ + public boolean external_begin_frame_enabled = false; + + /** + * Frame rate for external begin frame when external_begin_frame_enabled is true. + */ + public int begin_frame_rate = 0; + + public CefOsrRendererSettings() {} + + /** + * Copy constructor. + */ + public CefOsrRendererSettings(CefOsrRendererSettings other) { + this.show_update_rect = other.show_update_rect; + this.real_screen_bounds = other.real_screen_bounds; + this.background_color = other.background_color; + this.shared_texture_enabled = other.shared_texture_enabled; + this.external_begin_frame_enabled = other.external_begin_frame_enabled; + this.begin_frame_rate = other.begin_frame_rate; + } + + @Override + public CefOsrRendererSettings clone() { + return new CefOsrRendererSettings(this); + } +} diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 258df884..68b5de6a 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -67,6 +67,17 @@ public interface CefRenderHandler { public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height); + /** + * Called when an element has been rendered to the shared texture handle. + * This method is only called when CefWindowInfo::shared_texture_enabled is set to true. + * @param browser The browser generating the event. + * @param popup True if painting a popup window. + * @param dirtyRects Array of dirty regions. + * @param info Contains the shared handle and texture information. + */ + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo info); + /** * Add provided listener. * @param listener Code that gets executed after a frame was rendered. diff --git a/java/org/cef/handler/CefRenderHandlerAdapter.java b/java/org/cef/handler/CefRenderHandlerAdapter.java index ea782830..9ff45419 100644 --- a/java/org/cef/handler/CefRenderHandlerAdapter.java +++ b/java/org/cef/handler/CefRenderHandlerAdapter.java @@ -42,6 +42,10 @@ public void onPopupSize(CefBrowser browser, Rectangle size) {} public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) {} + @Override + public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo info) {} + @Override public boolean onCursorChange(CefBrowser browser, int cursorType) { return false; diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index 0e5f8118..ffc6fb8f 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -505,7 +505,7 @@ KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { return VKEY_OEM_7; case XK_ISO_Level5_Shift: return VKEY_OEM_8; - case XK_Shift_L: + case XK_Shift_L: case XK_Shift_R: return VKEY_SHIFT; case XK_Control_L: @@ -1010,6 +1010,10 @@ void create(std::shared_ptr objs, objs->jbrowserSettings != nullptr) { // Dev-tools settings are null GetJNIFieldInt(env, cefBrowserSettings, objs->jbrowserSettings, "windowless_frame_rate", &settings.windowless_frame_rate); + GetJNIFieldBoolean(env, cefBrowserSettings, objs->jbrowserSettings, + "shared_texture_enabled", &windowInfo.shared_texture_enabled); + GetJNIFieldBoolean(env, cefBrowserSettings, objs->jbrowserSettings, + "external_begin_frame_enabled", &windowInfo.external_begin_frame_enabled); } CefRefPtr browserObj; @@ -2170,6 +2174,14 @@ Java_org_cef_browser_CefBrowser_1N_N_1SetWindowlessFrameRate(JNIEnv* env, host->SetWindowlessFrameRate(frameRate); } +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendExternalBeginFrame(JNIEnv* env, + jobject jbrowser) { + CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, jbrowser); + CefRefPtr host = browser->GetHost(); + host->SendExternalBeginFrame(); +} + void getWindowlessFrameRate(CefRefPtr host, CefRefPtr callback) { callback->onComplete((jint)host->GetWindowlessFrameRate()); diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index b0348d5d..780dbefb 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -567,6 +567,15 @@ Java_org_cef_browser_CefBrowser_1N_N_1GetWindowlessFrameRate(JNIEnv*, jobject, jobject); +/* + * Class: org_cef_browser_CefBrowser_N + * Method: N_SendExternalBeginFrame + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_org_cef_browser_CefBrowser_1N_N_1SendExternalBeginFrame(JNIEnv*, + jobject); + #ifdef __cplusplus } #endif diff --git a/native/jni_util.cpp b/native/jni_util.cpp index 9d948330..32120195 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -895,6 +895,20 @@ bool SetJNIFieldBoolean(JNIEnv* env, return false; } +bool SetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong value) { + jfieldID field = env->GetFieldID(cls, field_name, "J"); + if (field) { + env->SetLongField(obj, field, value); + return true; + } + env->ExceptionClear(); + return false; +} + bool GetJNIFieldStaticInt(JNIEnv* env, jclass cls, const char* field_name, diff --git a/native/jni_util.h b/native/jni_util.h index dd9ba18b..2c1c9d1f 100644 --- a/native/jni_util.h +++ b/native/jni_util.h @@ -154,6 +154,11 @@ bool SetJNIFieldBoolean(JNIEnv* env, jobject obj, const char* field_name, int value); +bool SetJNIFieldLong(JNIEnv* env, + jclass cls, + jobject obj, + const char* field_name, + jlong value); // Retrieve the static int value stored in the |field_name| field of |cls|. bool GetJNIFieldStaticInt(JNIEnv* env, diff --git a/native/render_handler.cpp b/native/render_handler.cpp index dee74281..cedb72ef 100644 --- a/native/render_handler.cpp +++ b/native/render_handler.cpp @@ -270,6 +270,48 @@ void RenderHandler::OnPaint(CefRefPtr browser, jdirectBuffer.get(), width, height); } +void RenderHandler::OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + jboolean jtype = type == PET_VIEW ? JNI_FALSE : JNI_TRUE; + ScopedJNIObjectLocal jrectArray(env, NewJNIRectArray(env, dirtyRects)); + + // Create CefAcceleratedPaintInfo Java object + ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfo"); + if (!cls) + return; + ScopedJNIObjectLocal jpaintInfo(env, NewJNIObject(env, cls)); + if (!jpaintInfo) + return; + + // Get view rect to determine width and height + CefRect viewRect; + GetViewRect(browser, viewRect); + // Set the fields of the paint info object +#if defined(OS_WIN) + SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", + reinterpret_cast(info.shared_texture_handle)); +#else + // On non-Windows platforms, shared_texture_handle is not available + SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", 0); +#endif + SetJNIFieldInt(env, cls, jpaintInfo, "format", info.format); + SetJNIFieldInt(env, cls, jpaintInfo, "width", viewRect.width); + SetJNIFieldInt(env, cls, jpaintInfo, "height", viewRect.height); + + JNI_CALL_VOID_METHOD(env, handle_, "onAcceleratedPaint", + "(Lorg/cef/browser/CefBrowser;Z[Ljava/awt/" + "Rectangle;Lorg/cef/handler/CefAcceleratedPaintInfo;)V", + jbrowser.get(), jtype, jrectArray.get(), + jpaintInfo.get()); +} + bool RenderHandler::StartDragging(CefRefPtr browser, CefRefPtr drag_data, DragOperationsMask allowed_ops, diff --git a/native/render_handler.h b/native/render_handler.h index 27379d6e..55352392 100644 --- a/native/render_handler.h +++ b/native/render_handler.h @@ -40,6 +40,10 @@ class RenderHandler : public CefRenderHandler { const void* buffer, int width, int height) override; + virtual void OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) override; virtual bool StartDragging(CefRefPtr browser, CefRefPtr drag_data, DragOperationsMask allowed_ops, From 8219703221226f17daf2b10e56f322e15dc7d6b4 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 03:18:56 +0200 Subject: [PATCH 2/6] refactor: remove unused CefOsrRendererSettings --- java/org/cef/CefBrowserSettings.java | 2 - .../cef/handler/CefOsrRendererSettings.java | 69 ------------------- 2 files changed, 71 deletions(-) delete mode 100644 java/org/cef/handler/CefOsrRendererSettings.java diff --git a/java/org/cef/CefBrowserSettings.java b/java/org/cef/CefBrowserSettings.java index 67a184b3..36e09598 100644 --- a/java/org/cef/CefBrowserSettings.java +++ b/java/org/cef/CefBrowserSettings.java @@ -4,8 +4,6 @@ package org.cef; -import org.cef.handler.CefOsrRendererSettings; - /** * Browser initialization settings. Specify NULL or 0 to get the recommended * default values. The consequences of using custom values may not be well diff --git a/java/org/cef/handler/CefOsrRendererSettings.java b/java/org/cef/handler/CefOsrRendererSettings.java deleted file mode 100644 index a417f03d..00000000 --- a/java/org/cef/handler/CefOsrRendererSettings.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package org.cef.handler; - -/** - * Settings for off-screen rendering (OSR) configuration. - * Based on CEF's OsrRendererSettings structure. - */ -public class CefOsrRendererSettings { - - /** - * If true draw a border around update rectangles. - */ - public boolean show_update_rect = false; - - /** - * If true return real screen bounds from GetRootScreenRect/GetScreenInfo. - * - Allows window.outerWidth/Height and window.screenX/Y to return correct values. - * - Allows JavaScript window.moveTo/By() and window.resizeTo/By() to provide - * bounds that include the window frame. - * - Causes HTML select popups to be cropped (limitation of implementation). - */ - public boolean real_screen_bounds = true; - - /** - * Background color. Enables transparency if the alpha component is 0. - * 32-bit ARGB color value, not premultiplied. - */ - public int background_color = 0; - - /** - * Render using shared textures. Supported on Windows only via D3D11. - * When enabled, the browser will render to a shared texture that can be - * accessed by the host application for hardware-accelerated compositing. - */ - public boolean shared_texture_enabled = false; - - /** - * Client implements a BeginFrame timer by calling - * CefBrowserHost::SendExternalBeginFrame at the specified frame rate. - */ - public boolean external_begin_frame_enabled = false; - - /** - * Frame rate for external begin frame when external_begin_frame_enabled is true. - */ - public int begin_frame_rate = 0; - - public CefOsrRendererSettings() {} - - /** - * Copy constructor. - */ - public CefOsrRendererSettings(CefOsrRendererSettings other) { - this.show_update_rect = other.show_update_rect; - this.real_screen_bounds = other.real_screen_bounds; - this.background_color = other.background_color; - this.shared_texture_enabled = other.shared_texture_enabled; - this.external_begin_frame_enabled = other.external_begin_frame_enabled; - this.begin_frame_rate = other.begin_frame_rate; - } - - @Override - public CefOsrRendererSettings clone() { - return new CefOsrRendererSettings(this); - } -} From c5d269e70c42153441fa9630de51a6dab1bd68b5 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Thu, 26 Jun 2025 06:22:07 +0200 Subject: [PATCH 3/6] feat: CefAcceleratedPaintEvent --- java/org/cef/CefClient.java | 9 ++++ .../cef/browser/CefAcceleratedPaintEvent.java | 48 ++++++++++++++++++ java/org/cef/browser/CefBrowserOsr.java | 50 ++++++++++++++++++- java/org/cef/handler/CefRenderHandler.java | 19 +++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 java/org/cef/browser/CefAcceleratedPaintEvent.java diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index b9fc4559..cfd1d87b 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -787,6 +787,15 @@ public void setOnPaintListener(Consumer listener) {} @Override public void removeOnPaintListener(Consumer listener) {} + @Override + public void addOnAcceleratedPaintListener(Consumer listener) {} + + @Override + public void setOnAcceleratedPaintListener(Consumer listener) {} + + @Override + public void removeOnAcceleratedPaintListener(Consumer listener) {} + @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { if (browser == null) return false; diff --git a/java/org/cef/browser/CefAcceleratedPaintEvent.java b/java/org/cef/browser/CefAcceleratedPaintEvent.java new file mode 100644 index 00000000..4b840b10 --- /dev/null +++ b/java/org/cef/browser/CefAcceleratedPaintEvent.java @@ -0,0 +1,48 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.browser; + +import org.cef.handler.CefAcceleratedPaintInfo; + +import java.awt.*; + +public class CefAcceleratedPaintEvent { + private final CefBrowser browser; + private final boolean popup; + private final Rectangle[] dirtyRects; + private final CefAcceleratedPaintInfo acceleratedPaintInfo; + + public CefAcceleratedPaintEvent(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, + CefAcceleratedPaintInfo acceleratedPaintInfo) { + this.browser = browser; + this.popup = popup; + this.dirtyRects = dirtyRects; + this.acceleratedPaintInfo = acceleratedPaintInfo; + } + + public CefBrowser getBrowser() { + return browser; + } + + public boolean getPopup() { + return popup; + } + + public Rectangle[] getDirtyRects() { + return dirtyRects; + } + + public CefAcceleratedPaintInfo getAcceleratedPaintInfo() { + return acceleratedPaintInfo; + } + + public int getWidth() { + return acceleratedPaintInfo.width; + } + + public int getHeight() { + return acceleratedPaintInfo.height; + } +} diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 907271b1..1cd45040 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -91,6 +91,9 @@ class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private CopyOnWriteArrayList> onPaintListeners = new CopyOnWriteArrayList<>(); + private CopyOnWriteArrayList> onAcceleratedPaintListeners = + new CopyOnWriteArrayList<>(); + CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, CefBrowserSettings settings) { this(client, url, transparent, context, null, null, settings); @@ -379,6 +382,22 @@ public void removeOnPaintListener(Consumer listener) { onPaintListeners.remove(listener); } + @Override + public void addOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.add(listener); + } + + @Override + public void setOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.clear(); + onAcceleratedPaintListeners.add(listener); + } + + @Override + public void removeOnAcceleratedPaintListener(Consumer listener) { + onAcceleratedPaintListeners.remove(listener); + } + @Override public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { @@ -412,7 +431,36 @@ public void run() { @Override public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info) { - // TODO: Implement example for accelerated paint + // If window is closing, canvas_ or opengl context could be null + final GLContext context = canvas_ != null ? canvas_.getContext() : null; + + if (context == null) { + return; + } + + // This result can occur due to GLContext re-initialization when changing displays. + if (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT) { + return; + } + + // TODO: Implement renderer handling for accelerated paint + // On Windows, convert the D3D11 shared texture handle using ImportMemoryWin32HandleEXT + // through OpenGL's EXT_external_objects_win32. LWJGL supports it, but I am not familiar with JOGL's API. + // renderer_.onAcceleratedPaint(canvas_.getGL().getGL2(), popup, dirtyRects, info); + + context.release(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + canvas_.display(); + } + }); + if (!onAcceleratedPaintListeners.isEmpty()) { + CefAcceleratedPaintEvent paintEvent = + new CefAcceleratedPaintEvent(browser, popup, dirtyRects, info); + for (Consumer l : onAcceleratedPaintListeners) { + l.accept(paintEvent); + } + } } @Override diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 68b5de6a..47754504 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -4,6 +4,7 @@ package org.cef.handler; +import org.cef.browser.CefAcceleratedPaintEvent; import org.cef.browser.CefBrowser; import org.cef.browser.CefPaintEvent; import org.cef.callback.CefDragData; @@ -78,6 +79,24 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info); + /** + * Add provided listener for accelerated paint events. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void addOnAcceleratedPaintListener(Consumer listener); + + /** + * Remove existing accelerated paint listeners and replace with provided listener. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void setOnAcceleratedPaintListener(Consumer listener); + + /** + * Remove provided accelerated paint listener. + * @param listener Code that gets executed after a frame was rendered with accelerated painting. + */ + public void removeOnAcceleratedPaintListener(Consumer listener); + /** * Add provided listener. * @param listener Code that gets executed after a frame was rendered. From 077d0ea9fa3643cbd64f2751d06a0cd069237577 Mon Sep 17 00:00:00 2001 From: Sander van den Berg Date: Wed, 13 Aug 2025 15:16:27 +0000 Subject: [PATCH 4/6] Update to 139.0.17+g6c347eb+chromium-139.0.7258.31 --- CMakeLists.txt | 2 +- java/org/cef/network/CefPostDataElement.java | 2 +- .../tests/detailed/dialog/DevToolsDialog.java | 47 ------------------- java/tests/detailed/ui/MenuBar.java | 29 +++++------- native/CefPostDataElement_N.cpp | 2 +- native/jni_util.cpp | 2 - 6 files changed, 16 insertions(+), 68 deletions(-) delete mode 100644 java/tests/detailed/dialog/DevToolsDialog.java diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b65a374..580fee5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "135.0.20+ge7de5c3+chromium-135.0.7049.85") + set(CEF_VERSION "139.0.17+g6c347eb+chromium-139.0.7258.31") endif() # Determine the platform. diff --git a/java/org/cef/network/CefPostDataElement.java b/java/org/cef/network/CefPostDataElement.java index 2d32219a..576e940d 100644 --- a/java/org/cef/network/CefPostDataElement.java +++ b/java/org/cef/network/CefPostDataElement.java @@ -16,7 +16,7 @@ public static enum Type { PDE_TYPE_EMPTY, PDE_TYPE_BYTES, PDE_TYPE_FILE, - PDF_TYPE_NUM_VALUES, // probably should be PDE_TYPE, but wrong in CEF too + PDE_TYPE_NUM_VALUES, } // This CTOR can't be called directly. Call method create() instead. diff --git a/java/tests/detailed/dialog/DevToolsDialog.java b/java/tests/detailed/dialog/DevToolsDialog.java deleted file mode 100644 index 07a61809..00000000 --- a/java/tests/detailed/dialog/DevToolsDialog.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -package tests.detailed.dialog; - -import org.cef.browser.CefBrowser; - -import java.awt.BorderLayout; -import java.awt.Frame; -import java.awt.Point; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; - -import javax.swing.JDialog; - -@SuppressWarnings("serial") -public class DevToolsDialog extends JDialog { - private final CefBrowser browser_; - public DevToolsDialog(Frame owner, String title, CefBrowser browser) { - this(owner, title, browser, null); - } - - public DevToolsDialog(Frame owner, String title, CefBrowser browser, Point inspectAt) { - super(owner, title, false); - browser_ = browser; - - setLayout(new BorderLayout()); - setSize(800, 600); - setLocation(owner.getLocation().x + 20, owner.getLocation().y + 20); - - browser.openDevTools(inspectAt); - - addComponentListener(new ComponentAdapter() { - @Override - public void componentHidden(ComponentEvent e) { - dispose(); - } - }); - } - - @Override - public void dispose() { - browser_.closeDevTools(); - super.dispose(); - } -} diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java index 0ed8bf1a..79ecc095 100644 --- a/java/tests/detailed/ui/MenuBar.java +++ b/java/tests/detailed/ui/MenuBar.java @@ -22,8 +22,6 @@ import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.File; @@ -52,7 +50,6 @@ import tests.detailed.BrowserFrame; import tests.detailed.MainFrame; import tests.detailed.dialog.CookieManagerDialog; -import tests.detailed.dialog.DevToolsDialog; import tests.detailed.dialog.DownloadDialog; import tests.detailed.dialog.SearchDialog; import tests.detailed.dialog.ShowTextDialog; @@ -62,7 +59,7 @@ @SuppressWarnings("serial") public class MenuBar extends JMenuBar { class SaveAs implements CefStringVisitor { - private PrintWriter fileWriter_; + private final PrintWriter fileWriter_; public SaveAs(String fName) throws FileNotFoundException, UnsupportedEncodingException { fileWriter_ = new PrintWriter(fName, "UTF-8"); @@ -367,15 +364,7 @@ public void actionPerformed(ActionEvent e) { showDevTools.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - DevToolsDialog devToolsDlg = new DevToolsDialog(owner_, "DEV Tools", browser_); - devToolsDlg.addComponentListener(new ComponentAdapter() { - @Override - public void componentHidden(ComponentEvent e) { - showDevTools.setEnabled(true); - } - }); - devToolsDlg.setVisible(true); - showDevTools.setEnabled(false); + browser.openDevTools(); } }); testMenu.add(showDevTools); @@ -431,11 +420,14 @@ public void actionPerformed(ActionEvent e) { reparentButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (reparentPending_) return; + if (reparentPending_) { + return; + } reparentPending_ = true; if (reparentButton.getText().equals("Reparent <")) { owner_.removeBrowser(new Runnable() { + @Override public void run() { newFrame.add(browser_.getUIComponent(), BorderLayout.CENTER); newFrame.setBrowser(browser_); @@ -445,6 +437,7 @@ public void run() { }); } else { newFrame.removeBrowser(new Runnable() { + @Override public void run() { JRootPane rootPane = (JRootPane) owner_.getComponent(0); Container container = rootPane.getContentPane(); @@ -540,12 +533,16 @@ public void run() { } public void addBookmark(String name, String URL) { - if (bookmarkMenu_ == null) return; + if (bookmarkMenu_ == null) { + return; + } // Test if the bookmark already exists. If yes, update URL Component[] entries = bookmarkMenu_.getMenuComponents(); for (Component itemEntry : entries) { - if (!(itemEntry instanceof JMenuItem)) continue; + if (!(itemEntry instanceof JMenuItem)) { + continue; + } JMenuItem item = (JMenuItem) itemEntry; if (item.getText().equals(name)) { diff --git a/native/CefPostDataElement_N.cpp b/native/CefPostDataElement_N.cpp index 63f4e695..414e7a55 100644 --- a/native/CefPostDataElement_N.cpp +++ b/native/CefPostDataElement_N.cpp @@ -99,7 +99,7 @@ Java_org_cef_network_CefPostDataElement_1N_N_1GetType(JNIEnv* env, JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", PDE_TYPE_FILE, jtype); JNI_CASE(env, "org/cef/network/CefPostDataElement$Type", - PDF_TYPE_NUM_VALUES, jtype); + PDE_TYPE_NUM_VALUES, jtype); } return jtype; } diff --git a/native/jni_util.cpp b/native/jni_util.cpp index 32120195..00468999 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -519,8 +519,6 @@ jobject NewJNIErrorCode(JNIEnv* env, cef_errorcode_t errorCode) { ERR_CERT_VALIDITY_TOO_LONG, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERTIFICATE_TRANSPARENCY_REQUIRED, jerrorCode); - JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", - ERR_CERT_SYMANTEC_LEGACY, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERT_KNOWN_INTERCEPTION_BLOCKED, jerrorCode); JNI_CASE(env, "org/cef/handler/CefLoadHandler$ErrorCode", ERR_CERT_END, From 2f54801bc797fd4ed3a430d8c226af051a47757e Mon Sep 17 00:00:00 2001 From: Izuna Date: Sun, 25 Jan 2026 16:01:05 +0100 Subject: [PATCH 5/6] feat(accelerated-paint): multi platform support (#21) It now passes dmabuf planes on Linux, as well as IOSurface pointer on macOS. It has also been refactored into multiple classes for each platform. --- .../cef/handler/CefAcceleratedPaintInfo.java | 26 +++----- .../handler/CefAcceleratedPaintInfoLinux.java | 62 ++++++++++++++++++ .../handler/CefAcceleratedPaintInfoMac.java | 27 ++++++++ .../handler/CefAcceleratedPaintInfoWin.java | 27 ++++++++ java/org/cef/handler/CefRenderHandler.java | 6 +- native/render_handler.cpp | 64 +++++++++++++++++-- 6 files changed, 190 insertions(+), 22 deletions(-) create mode 100644 java/org/cef/handler/CefAcceleratedPaintInfoLinux.java create mode 100644 java/org/cef/handler/CefAcceleratedPaintInfoMac.java create mode 100644 java/org/cef/handler/CefAcceleratedPaintInfoWin.java diff --git a/java/org/cef/handler/CefAcceleratedPaintInfo.java b/java/org/cef/handler/CefAcceleratedPaintInfo.java index bd8aeedc..505a8921 100644 --- a/java/org/cef/handler/CefAcceleratedPaintInfo.java +++ b/java/org/cef/handler/CefAcceleratedPaintInfo.java @@ -5,39 +5,31 @@ package org.cef.handler; /** - * Structure representing shared texture info for accelerated painting. + * Base structure representing accelerated paint info. Platform-specific + * details are provided by subclasses. */ -public class CefAcceleratedPaintInfo { - /** - * Shared texture handle. The meaning depends on the platform: - * - Windows: HANDLE to a texture that can be opened with D3D11 OpenSharedResource - * - macOS: IOSurface pointer that can be opened with Metal or OpenGL - * - Linux: Contains several planes, each with an fd to the underlying system native buffer - */ - public long shared_texture_handle = 0; - +public class CefAcceleratedPaintInfo implements Cloneable { /** * Format of the shared texture. */ public int format = 0; - + /** * Size information for the shared texture. */ public int width = 0; public int height = 0; - + public CefAcceleratedPaintInfo() {} - - public CefAcceleratedPaintInfo(long shared_texture_handle, int format, int width, int height) { - this.shared_texture_handle = shared_texture_handle; + + protected CefAcceleratedPaintInfo(int format, int width, int height) { this.format = format; this.width = width; this.height = height; } - + @Override public CefAcceleratedPaintInfo clone() { - return new CefAcceleratedPaintInfo(shared_texture_handle, format, width, height); + return new CefAcceleratedPaintInfo(format, width, height); } } diff --git a/java/org/cef/handler/CefAcceleratedPaintInfoLinux.java b/java/org/cef/handler/CefAcceleratedPaintInfoLinux.java new file mode 100644 index 00000000..9c4d7d70 --- /dev/null +++ b/java/org/cef/handler/CefAcceleratedPaintInfoLinux.java @@ -0,0 +1,62 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Linux-specific accelerated paint info (dmabuf planes). + */ +public class CefAcceleratedPaintInfoLinux extends CefAcceleratedPaintInfo { + /** + * dmabuf plane count. + */ + public int plane_count = 0; + + /** + * dmabuf plane file descriptors. + */ + public int[] plane_fds = null; + + /** + * dmabuf plane strides (bytes per row). + */ + public int[] plane_strides = null; + + /** + * dmabuf plane offsets. + */ + public long[] plane_offsets = null; + + /** + * dmabuf plane sizes. + */ + public long[] plane_sizes = null; + + /** + * dmabuf modifier. + */ + public long modifier = 0; + + public CefAcceleratedPaintInfoLinux() {} + + public CefAcceleratedPaintInfoLinux(int format, int width, int height) { + super(format, width, height); + } + + public boolean hasDmaBufPlanes() { + return plane_count > 0 && plane_fds != null && plane_strides != null && plane_offsets != null; + } + + @Override + public CefAcceleratedPaintInfoLinux clone() { + CefAcceleratedPaintInfoLinux clone = new CefAcceleratedPaintInfoLinux(format, width, height); + clone.plane_count = plane_count; + clone.modifier = modifier; + clone.plane_fds = plane_fds != null ? plane_fds.clone() : null; + clone.plane_strides = plane_strides != null ? plane_strides.clone() : null; + clone.plane_offsets = plane_offsets != null ? plane_offsets.clone() : null; + clone.plane_sizes = plane_sizes != null ? plane_sizes.clone() : null; + return clone; + } +} diff --git a/java/org/cef/handler/CefAcceleratedPaintInfoMac.java b/java/org/cef/handler/CefAcceleratedPaintInfoMac.java new file mode 100644 index 00000000..738924a9 --- /dev/null +++ b/java/org/cef/handler/CefAcceleratedPaintInfoMac.java @@ -0,0 +1,27 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * macOS-specific accelerated paint info. + */ +public class CefAcceleratedPaintInfoMac extends CefAcceleratedPaintInfo { + /** + * IOSurface handle that can be opened with Metal or OpenGL. + */ + public long shared_texture_io_surface = 0; + + public CefAcceleratedPaintInfoMac() {} + + public CefAcceleratedPaintInfoMac(long shared_texture_io_surface, int format, int width, int height) { + super(format, width, height); + this.shared_texture_io_surface = shared_texture_io_surface; + } + + @Override + public CefAcceleratedPaintInfoMac clone() { + return new CefAcceleratedPaintInfoMac(shared_texture_io_surface, format, width, height); + } +} diff --git a/java/org/cef/handler/CefAcceleratedPaintInfoWin.java b/java/org/cef/handler/CefAcceleratedPaintInfoWin.java new file mode 100644 index 00000000..f87bbc91 --- /dev/null +++ b/java/org/cef/handler/CefAcceleratedPaintInfoWin.java @@ -0,0 +1,27 @@ +// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +package org.cef.handler; + +/** + * Windows-specific accelerated paint info. + */ +public class CefAcceleratedPaintInfoWin extends CefAcceleratedPaintInfo { + /** + * HANDLE to a texture that can be opened with D3D11 OpenSharedResource. + */ + public long shared_texture_handle = 0; + + public CefAcceleratedPaintInfoWin() {} + + public CefAcceleratedPaintInfoWin(long shared_texture_handle, int format, int width, int height) { + super(format, width, height); + this.shared_texture_handle = shared_texture_handle; + } + + @Override + public CefAcceleratedPaintInfoWin clone() { + return new CefAcceleratedPaintInfoWin(shared_texture_handle, format, width, height); + } +} diff --git a/java/org/cef/handler/CefRenderHandler.java b/java/org/cef/handler/CefRenderHandler.java index 47754504..bbe529c7 100644 --- a/java/org/cef/handler/CefRenderHandler.java +++ b/java/org/cef/handler/CefRenderHandler.java @@ -74,7 +74,11 @@ public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, * @param browser The browser generating the event. * @param popup True if painting a popup window. * @param dirtyRects Array of dirty regions. - * @param info Contains the shared handle and texture information. + * @param info Platform-specific info instance. Expect one of + * {@link CefAcceleratedPaintInfoWin}, + * {@link CefAcceleratedPaintInfoMac}, + * {@link CefAcceleratedPaintInfoLinux}, or a base + * {@link CefAcceleratedPaintInfo} on unsupported platforms. */ public void onAcceleratedPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, CefAcceleratedPaintInfo info); diff --git a/native/render_handler.cpp b/native/render_handler.cpp index cedb72ef..d1c6a363 100644 --- a/native/render_handler.cpp +++ b/native/render_handler.cpp @@ -4,6 +4,8 @@ #include "render_handler.h" +#include + #include "client_handler.h" #include "jni_util.h" @@ -282,8 +284,16 @@ void RenderHandler::OnAcceleratedPaint(CefRefPtr browser, jboolean jtype = type == PET_VIEW ? JNI_FALSE : JNI_TRUE; ScopedJNIObjectLocal jrectArray(env, NewJNIRectArray(env, dirtyRects)); - // Create CefAcceleratedPaintInfo Java object + // Create platform-specific CefAcceleratedPaintInfo Java object +#if defined(OS_WIN) + ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfoWin"); +#elif defined(OS_MACOSX) + ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfoMac"); +#elif defined(OS_LINUX) + ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfoLinux"); +#else ScopedJNIClass cls(env, "org/cef/handler/CefAcceleratedPaintInfo"); +#endif if (!cls) return; ScopedJNIObjectLocal jpaintInfo(env, NewJNIObject(env, cls)); @@ -297,14 +307,60 @@ void RenderHandler::OnAcceleratedPaint(CefRefPtr browser, #if defined(OS_WIN) SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", reinterpret_cast(info.shared_texture_handle)); -#else - // On non-Windows platforms, shared_texture_handle is not available - SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_handle", 0); +#elif defined(OS_MACOSX) + SetJNIFieldLong(env, cls, jpaintInfo, "shared_texture_io_surface", + reinterpret_cast(info.shared_texture_io_surface)); #endif SetJNIFieldInt(env, cls, jpaintInfo, "format", info.format); SetJNIFieldInt(env, cls, jpaintInfo, "width", viewRect.width); SetJNIFieldInt(env, cls, jpaintInfo, "height", viewRect.height); +#if defined(OS_LINUX) + SetJNIFieldInt(env, cls, jpaintInfo, "plane_count", info.plane_count); + SetJNIFieldLong(env, cls, jpaintInfo, "modifier", + static_cast(info.modifier)); + + const int plane_count = info.plane_count; + if (plane_count > 0) { + std::vector fds(plane_count); + std::vector strides(plane_count); + std::vector offsets(plane_count); + std::vector sizes(plane_count); + + for (int i = 0; i < plane_count; ++i) { + fds[i] = info.planes[i].fd; + strides[i] = static_cast(info.planes[i].stride); + offsets[i] = static_cast(info.planes[i].offset); + sizes[i] = static_cast(info.planes[i].size); + } + + jclass paintInfoClass = cls.get(); + jfieldID fdsField = env->GetFieldID(paintInfoClass, "plane_fds", "[I"); + jfieldID stridesField = env->GetFieldID(paintInfoClass, "plane_strides", "[I"); + jfieldID offsetsField = env->GetFieldID(paintInfoClass, "plane_offsets", "[J"); + jfieldID sizesField = env->GetFieldID(paintInfoClass, "plane_sizes", "[J"); + + if (fdsField && stridesField && offsetsField && sizesField) { + jintArray fdsArray = env->NewIntArray(plane_count); + jintArray stridesArray = env->NewIntArray(plane_count); + jlongArray offsetsArray = env->NewLongArray(plane_count); + jlongArray sizesArray = env->NewLongArray(plane_count); + + if (fdsArray && stridesArray && offsetsArray && sizesArray) { + env->SetIntArrayRegion(fdsArray, 0, plane_count, fds.data()); + env->SetIntArrayRegion(stridesArray, 0, plane_count, strides.data()); + env->SetLongArrayRegion(offsetsArray, 0, plane_count, offsets.data()); + env->SetLongArrayRegion(sizesArray, 0, plane_count, sizes.data()); + + env->SetObjectField(jpaintInfo.get(), fdsField, fdsArray); + env->SetObjectField(jpaintInfo.get(), stridesField, stridesArray); + env->SetObjectField(jpaintInfo.get(), offsetsField, offsetsArray); + env->SetObjectField(jpaintInfo.get(), sizesField, sizesArray); + } + } + } +#endif + JNI_CALL_VOID_METHOD(env, handle_, "onAcceleratedPaint", "(Lorg/cef/browser/CefBrowser;Z[Ljava/awt/" "Rectangle;Lorg/cef/handler/CefAcceleratedPaintInfo;)V", From 80bab7ec6dd07a473e164debffd48ae17e6474a2 Mon Sep 17 00:00:00 2001 From: Izuna Seikatsu Date: Mon, 26 Jan 2026 14:25:14 +0100 Subject: [PATCH 6/6] fix: correct indentation --- native/CefBrowser_N.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index 0f8e6f8d..28b91b5e 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -505,7 +505,7 @@ KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { return VKEY_OEM_7; case XK_ISO_Level5_Shift: return VKEY_OEM_8; - case XK_Shift_L: + case XK_Shift_L: case XK_Shift_R: return VKEY_SHIFT; case XK_Control_L: