diff --git a/.github/workflows/build-jcef.yml b/.github/workflows/build-jcef.yml new file mode 100644 index 00000000..6af990db --- /dev/null +++ b/.github/workflows/build-jcef.yml @@ -0,0 +1,108 @@ +name: Build java-cef + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + java-cef-linux: + runs-on: [ubuntu-20.04] + strategy: + matrix: + platform: [amd64, arm64] + steps: + - name: Upload mask + run: echo "::add-mask::${{ secrets.UPLOAD_URL }}" + - uses: actions/checkout@v4 + - name: Setup JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + - name: Install deps and build + run: | + sudo apt update + sudo apt install build-essential g++ cmake ninja-build python3 libgtk2.0-dev s3cmd -y + mkdir jcef_build && cd jcef_build + cmake -G "Ninja" -DPROJECT_ARCH=${{ matrix.platform }} -DCMAKE_BUILD_TYPE=Release .. + ninja -j4 + mv native/Release linux_${{ matrix.platform }} + strip linux_${{ matrix.platform }}/libcef.so + tar -czf linux_${{ matrix.platform }}.tar.gz linux_${{ matrix.platform }} + sha256sum linux_${{ matrix.platform }}.tar.gz > linux_${{ matrix.platform }}.tar.gz.sha256 + - name: Copy s3cfg + run: echo "${{ secrets.S3_CFG }}" > ~/.s3cfg + - name: Upload java-cef build + run: | + s3cmd put -P /home/runner/work/java-cef/java-cef/jcef_build/linux_${{ matrix.platform }}.tar.gz s3://mcef-us-1/java-cef-builds/${{ github.sha }}/linux_${{ matrix.platform }}.tar.gz + s3cmd put -P /home/runner/work/java-cef/java-cef/jcef_build/linux_${{ matrix.platform }}.tar.gz.sha256 s3://mcef-us-1/java-cef-builds/${{ github.sha }}/linux_${{ matrix.platform }}.tar.gz.sha256 + java-cef-windows: + runs-on: [windows-2022] + strategy: + matrix: + platform: [amd64, arm64] + steps: + - name: Upload mask + run: echo "::add-mask::${{ secrets.UPLOAD_URL }}" + - uses: actions/checkout@v4 + - name: Setup JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + - uses: ilammy/msvc-dev-cmd@v1 + - name: Install s3cmd + run: | + pip install python-dateutil + Invoke-WebRequest -Uri "https://github.com/s3tools/s3cmd/archive/master.zip" -OutFile "D:\s3cmd.zip" + Expand-Archive -Path "D:\s3cmd.zip" -DestinationPath "D:\s3cmd" + - name: Build + run: | + mkdir jcef_build && cd jcef_build + cmake -G "Ninja" -DPROJECT_ARCH=${{ matrix.platform }} -DCMAKE_BUILD_TYPE=Release .. + ninja -j4 + cd native + ren Release windows_${{ matrix.platform }} + cd .. + move native/windows_${{ matrix.platform }} windows_${{ matrix.platform }} + tar -czf windows_${{ matrix.platform }}.tar.gz windows_${{ matrix.platform }} + Get-FileHash -Algorithm SHA256 -Path "windows_${{ matrix.platform }}.tar.gz" | Out-File "windows_${{ matrix.platform }}.tar.gz.sha256" + - name: Copy s3cfg + run: echo "${{ secrets.S3_CFG }}" > "$HOME\AppData\Roaming\s3cmd.ini" + - name: Upload java-cef build + run: | + python D:\s3cmd\s3cmd-master\s3cmd put -P D:\a\java-cef\java-cef\jcef_build\windows_${{ matrix.platform }}.tar.gz s3://mcef-us-1/java-cef-builds/${{ github.sha }}/windows_${{ matrix.platform }}.tar.gz + python D:\s3cmd\s3cmd-master\s3cmd put -P D:\a\java-cef\java-cef\jcef_build\windows_${{ matrix.platform }}.tar.gz.sha256 s3://mcef-us-1/java-cef-builds/${{ github.sha }}/windows_${{ matrix.platform }}.tar.gz.sha256 + java-cef-macos: + runs-on: [macos-12] + strategy: + matrix: + platform: [amd64, arm64] + steps: + - name: Upload mask + run: echo "::add-mask::${{ secrets.UPLOAD_URL }}" + - uses: actions/checkout@v4 + - name: Setup JDK + uses: actions/setup-java@v4 + with: + java-version: '8' + distribution: 'temurin' + - run: | + brew install ninja + brew install coreutils + brew install s3cmd + sudo xcode-select --switch /Applications/Xcode_13.1.app + mkdir jcef_build && cd jcef_build + cmake -G "Ninja" -DPROJECT_ARCH=${{ matrix.platform }} -DCMAKE_BUILD_TYPE=Release .. + ninja -j4 + mv native/Release macos_${{ matrix.platform }} + tar -czf macos_${{ matrix.platform }}.tar.gz macos_${{ matrix.platform }} + sha256sum macos_${{ matrix.platform }}.tar.gz > macos_${{ matrix.platform }}.tar.gz.sha256 + - name: Copy s3cfg + run: echo "${{ secrets.S3_CFG }}" > ~/.s3cfg + - name: Upload java-cef build + run: | + s3cmd put -P /Users/runner/work/java-cef/java-cef/jcef_build/macos_${{ matrix.platform }}.tar.gz s3://mcef-us-1/java-cef-builds/${{ github.sha }}/macos_${{ matrix.platform }}.tar.gz + s3cmd put -P /Users/runner/work/java-cef/java-cef/jcef_build/macos_${{ matrix.platform }}.tar.gz.sha256 s3://mcef-us-1/java-cef-builds/${{ github.sha }}/macos_${{ matrix.platform }}.tar.gz.sha256 diff --git a/.gitignore b/.gitignore index e7bc7d07..071b39d8 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ Thumbs.db /tools/buildtools/linux64/clang-format /tools/buildtools/mac/clang-format /tools/buildtools/win/clang-format.exe +.idea +*.iml +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d3db080..22d0fc06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,8 @@ cmake_minimum_required(VERSION 3.19) # Only generate Debug and Release configuration types. set(CMAKE_CONFIGURATION_TYPES Debug Release) +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") + # Project name. project(jcef) @@ -128,9 +130,14 @@ set_property(GLOBAL PROPERTY OS_FOLDERS ON) # CEF configuration. # +# Specify the CEF branch +if(NOT DEFINED CEF_BRANCH) + set(CEF_BRANCH "5845") +endif() + # Specify the CEF distribution version. if(NOT DEFINED CEF_VERSION) - set(CEF_VERSION "116.0.19+gc6a20bc+chromium-116.0.5845.141") + set(CEF_VERSION "116.0.27+gd8c85ac+chromium-116.0.5845.190") endif() # Determine the platform. @@ -165,7 +172,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Download and extract the CEF binary distribution (executes DownloadCEF.cmake). include(DownloadCEF) -DownloadCEF("${CEF_PLATFORM}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/third_party/cef") +DownloadCEF("${CEF_PLATFORM}" "${CEF_BRANCH}" "${CEF_VERSION}" "${CMAKE_SOURCE_DIR}/third_party/cef") # Add the CEF binary distribution's cmake/ directory to the module path. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake") diff --git a/README.md b/README.md index e2443d49..9cb0744f 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,2 @@ -The Java Chromium Embedded Framework (JCEF) is a simple framework for embedding Chromium-based browsers in other applications using the Java programming language. - -# Quick Links - -* Building JCEF - https://bitbucket.org/chromiumembedded/java-cef/wiki/BranchesAndBuilding -* Support Forum - http://magpcss.org/ceforum/viewforum.php?f=17 -* Issue Tracker - https://github.com/chromiumembedded/java-cef/issues -* Downloads - https://github.com/jcefmaven/jcefbuild -* Maven/Gradle Artifacts - https://github.com/jcefmaven/jcefmaven -* Donations - http://www.magpcss.org/ceforum/donate.php - -# Introduction - -CEF is a BSD-licensed open source project founded by Marshall Greenblatt in 2008 and based on the [Google Chromium](http://www.chromium.org/Home) project. Unlike the Chromium project itself, which focuses mainly on Google Chrome application development, CEF focuses on facilitating embedded browser use cases in third-party applications. CEF insulates the user from the underlying Chromium and Blink code complexity by offering production-quality stable APIs, release branches tracking specific Chromium releases, and binary distributions. Most features in CEF have default implementations that provide rich functionality while requiring little or no integration work from the user. There are currently over 100 million installed instances of CEF around the world embedded in products from a wide range of companies and industries. A partial list of companies and products using CEF is available on the [CEF Wikipedia page](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF). Some use cases for CEF include: - -* Embedding an HTML5-compliant Web browser control in an existing native application. -* Creating a light-weight native “shell” application that hosts a user interface developed primarily using Web technologies. -* Rendering Web content “off-screen” in applications that have their own custom drawing frameworks. -* Acting as a host for automated testing of existing Web properties and applications. - -CEF supports a wide range of programming languages and operating systems and can be easily integrated into both new and existing applications. It was designed from the ground up with both performance and ease of use in mind. The base framework includes C and C++ programming interfaces exposed via native libraries that insulate the host application from Chromium and Blink implementation details. It provides close integration between the browser and the host application including support for custom plugins, protocols, JavaScript objects and JavaScript extensions. The host application can optionally control resource loading, navigation, context menus, printing and more, while taking advantage of the same performance and HTML5 technologies available in the Google Chrome Web browser. - -This project provides a Java Wrapper for CEF (JCEF). - -# Building JCEF - -The JCEF project is an extension of the Chromium Embedded Framework (CEF) project hosted at https://bitbucket.org/chromiumembedded/cef/. JCEF maintains a development branch that tracks the most recent CEF3 release branch. JCEF source code can be downloaded, built and packaged into a binary distribution. Once you have created the binary distribution for your platform you can distribute it as a stand-alone package without further dependencies on the JCEF, CEF or Chromium source code. Visit the [BranchesAndBuilding](https://bitbucket.org/chromiumembedded/java-cef/wiki/BranchesAndBuilding) Wiki page for detailed instructions. - -# Helping Out - -JCEF is still very much a work in progress. Some ways that you can help out: - -\- Vote for issues in the [JCEF issue tracker](https://github.com/chromiumembedded/java-cef/issues) that are important to you. This helps with development prioritization. - -\- Report any bugs that you find or feature requests that are important to you. Make sure to first search for existing issues before creating new ones. Please use the [JCEF Forum](http://magpcss.org/ceforum/viewforum.php?f=17) and not the issue tracker for usage questions. Each JCEF issue should: - -* Include the JCEF revision, CEF revision or binary distribution version. -* Include information about your OS and compiler version. -* If the issue is a bug please provide detailed reproduction information. -* If the issue is a feature please describe why the feature is beneficial. - -\- Write unit tests for new or existing functionality. - -\- Pull requests and patches are welcome. View open issues in the [JCEF issue tracker](https://github.com/chromiumembedded/java-cef/issues) or search for TODO(cef) in the source code for ideas. - -If you would like to contribute source code changes to JCEF please follow the below guidelines: - -\- Create or find an appropriate issue for each distinct bug, feature or change. - -\- Submit a [pull request](https://bitbucket.org/chromiumembedded/java-cef/wiki/ContributingWithGit) or create a patch with your changes and attach it to the JCEF issue. Changes should: - -* Be submitted against the current [JCEF master branch](https://bitbucket.org/chromiumembedded/java-cef/src/?at=master) unless explicitly fixing a bug in a CEF release branch. -* Follow the style of existing JCEF source files. In general JCEF uses the [Chromium coding style](http://www.chromium.org/developers/coding-style). -* Include new or modified unit tests as appropriate to the functionality. -* Not include unnecessary or unrelated changes. \ No newline at end of file +# MCEF java-cef +Modified version of java-cef for use with MCEF diff --git a/cmake/DownloadCEF.cmake b/cmake/DownloadCEF.cmake index a64592bc..b2d11930 100644 --- a/cmake/DownloadCEF.cmake +++ b/cmake/DownloadCEF.cmake @@ -8,7 +8,7 @@ # Visit https://cef-builds.spotifycdn.com/index.html for the list of # supported platforms and versions. -function(DownloadCEF platform version download_dir) +function(DownloadCEF platform branch version download_dir) # Specify the binary distribution type and download directory. set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}") set(CEF_DOWNLOAD_DIR "${download_dir}") @@ -21,19 +21,19 @@ function(DownloadCEF platform version download_dir) set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2") set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}") if(NOT EXISTS "${CEF_DOWNLOAD_PATH}") - set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}") + set(CEF_DOWNLOAD_URL "https://mcef-download.cinemamod.com/cef-builds/${branch}/${CEF_DOWNLOAD_FILENAME}") string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL}) # Download the SHA1 hash for the binary distribution. - message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...") - file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1") - file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1) + # message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...") + # file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1") + # file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1) # Download the binary distribution and verify the hash. message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...") file( DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}" - EXPECTED_HASH SHA1=${CEF_SHA1} + # EXPECTED_HASH SHA1=${CEF_SHA1} SHOW_PROGRESS ) endif() diff --git a/java/org/cef/CefApp.java b/java/org/cef/CefApp.java index afd10f04..eff69e01 100644 --- a/java/org/cef/CefApp.java +++ b/java/org/cef/CefApp.java @@ -140,37 +140,13 @@ public enum CefAppState { private CefApp(String[] args, CefSettings settings) throws UnsatisfiedLinkError { super(args); if (settings != null) settings_ = settings.clone(); - if (OS.isWindows()) { - SystemBootstrap.loadLibrary("jawt"); - SystemBootstrap.loadLibrary("chrome_elf"); - SystemBootstrap.loadLibrary("libcef"); - // Other platforms load this library in CefApp.startup(). - SystemBootstrap.loadLibrary("jcef"); - } else if (OS.isLinux()) { - SystemBootstrap.loadLibrary("cef"); - } if (appHandler_ == null) { appHandler_ = this; } - // Execute on the AWT event dispatching thread. - try { - Runnable r = new Runnable() { - @Override - public void run() { - // Perform native pre-initialization. - if (!N_PreInitialize()) - throw new IllegalStateException("Failed to pre-initialize native code"); - } - }; - if (SwingUtilities.isEventDispatchThread()) - r.run(); - else - SwingUtilities.invokeAndWait(r); - } catch (Exception e) { - e.printStackTrace(); - } + if (!N_PreInitialize()) + throw new IllegalStateException("Failed to pre-initialize native code"); } /** @@ -381,97 +357,66 @@ protected final synchronized void clientWasDisposed(CefClient client) { * @return true on success. */ private final void initialize() { - // Execute on the AWT event dispatching thread. - try { - Runnable r = new Runnable() { - @Override - public void run() { - String library_path = getJcefLibPath(); - System.out.println("initialize on " + Thread.currentThread() - + " with library path " + library_path); - - CefSettings settings = settings_ != null ? settings_ : new CefSettings(); - - // Avoid to override user values by testing on NULL - if (OS.isMacintosh()) { - if (settings.browser_subprocess_path == null) { - Path path = Paths.get(library_path, - "../Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"); - settings.browser_subprocess_path = - path.normalize().toAbsolutePath().toString(); - } - } else if (OS.isWindows()) { - if (settings.browser_subprocess_path == null) { - Path path = Paths.get(library_path, "jcef_helper.exe"); - settings.browser_subprocess_path = - path.normalize().toAbsolutePath().toString(); - } - } else if (OS.isLinux()) { - if (settings.browser_subprocess_path == null) { - Path path = Paths.get(library_path, "jcef_helper"); - settings.browser_subprocess_path = - path.normalize().toAbsolutePath().toString(); - } - if (settings.resources_dir_path == null) { - Path path = Paths.get(library_path); - settings.resources_dir_path = - path.normalize().toAbsolutePath().toString(); - } - if (settings.locales_dir_path == null) { - Path path = Paths.get(library_path, "locales"); - settings.locales_dir_path = - path.normalize().toAbsolutePath().toString(); - } - } + String jcefPath = getJcefLibPath(); + System.out.println("initialize on " + Thread.currentThread() + " with library path " + jcefPath); - if (N_Initialize(appHandler_, settings)) setState(CefAppState.INITIALIZED); - } - }; - if (SwingUtilities.isEventDispatchThread()) - r.run(); - else - SwingUtilities.invokeAndWait(r); - } catch (Exception e) { - e.printStackTrace(); + CefSettings settings = settings_ != null ? settings_ : new CefSettings(); + + if (OS.isWindows()) { + Path jcefHelperPath = Paths.get(jcefPath, "jcef_helper.exe"); + settings.browser_subprocess_path = jcefHelperPath.normalize().toAbsolutePath().toString(); + } else if (OS.isMacintosh()) { + String basePath = Paths.get(jcefPath).getParent().getParent().toString(); + settings.main_bundle_path = basePath; + settings.framework_dir_path = basePath + + "/Contents/Frameworks/Chromium Embedded Framework.framework"; + settings.locales_dir_path = basePath + + "/Contents/Frameworks/Chromium Embedded Framework.framework/Resources"; + settings.resources_dir_path = basePath + + "/Contents/Frameworks/Chromium Embedded Framework.framework/Resources"; + settings.browser_subprocess_path = basePath + + "/Contents/Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"; + } else if (OS.isLinux()) { + settings.resources_dir_path = jcefPath; + Path jcefHelperPath = Paths.get(jcefPath, "jcef_helper"); + settings.browser_subprocess_path = jcefHelperPath.normalize().toAbsolutePath().toString(); + Path localesPath = Paths.get(jcefPath, "locales"); + settings.locales_dir_path = localesPath.normalize().toAbsolutePath().toString(); } + + if (N_Initialize(appHandler_, settings)) setState(CefAppState.INITIALIZED); } + /** + * CEF takes full control of Cmd+Q and doesn't allow our application to see that it has been pressed. + * This allows us to run our application's shutdown code, so we can have a graceful "Cmd+Q" exit. + */ + public Runnable macOSTerminationRequestRunnable = new Runnable() { + @Override + public void run() { + } + }; + /** * This method is invoked by the native code (currently on Mac only) in case * of a termination event (e.g. someone pressed CMD+Q). */ protected final void handleBeforeTerminate() { - System.out.println("Cmd+Q termination request."); - // Execute on the AWT event dispatching thread. Always call asynchronously - // so the call stack has a chance to unwind. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - CefAppHandler handler = - (CefAppHandler) ((appHandler_ == null) ? this : appHandler_); - if (!handler.onBeforeTerminate()) dispose(); - } - }); +// CefAppHandler handler = +// (CefAppHandler) ((appHandler_ == null) ? this : appHandler_); +// if (!handler.onBeforeTerminate()) dispose(); + macOSTerminationRequestRunnable.run(); } /** * Shut down the context. */ private final void shutdown() { - // Execute on the AWT event dispatching thread. Always call asynchronously - // so the call stack has a chance to unwind. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - System.out.println("shutdown on " + Thread.currentThread()); - - // Shutdown native CEF. - N_Shutdown(); + // Shutdown native CEF. + N_Shutdown(); - setState(CefAppState.TERMINATED); - CefApp.self = null; - } - }); + setState(CefAppState.TERMINATED); + CefApp.self = null; } /** @@ -479,49 +424,7 @@ public void run() { * Windows with windowed rendering. */ public final void doMessageLoopWork(final long delay_ms) { - // Execute on the AWT event dispatching thread. - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (getState() == CefAppState.TERMINATED) return; - - // The maximum number of milliseconds we're willing to wait between - // calls to DoMessageLoopWork(). - final long kMaxTimerDelay = 1000 / 30; // 30fps - - if (workTimer_ != null) { - workTimer_.stop(); - workTimer_ = null; - } - - if (delay_ms <= 0) { - // Execute the work immediately. - N_DoMessageLoopWork(); - - // Schedule more work later. - doMessageLoopWork(kMaxTimerDelay); - } else { - long timer_delay_ms = delay_ms; - // Never wait longer than the maximum allowed time. - if (timer_delay_ms > kMaxTimerDelay) timer_delay_ms = kMaxTimerDelay; - - workTimer_ = new Timer((int) timer_delay_ms, new ActionListener() { - @Override - public void actionPerformed(ActionEvent evt) { - // Timer has timed out. - workTimer_.stop(); - workTimer_ = null; - - N_DoMessageLoopWork(); - - // Schedule more work later. - doMessageLoopWork(kMaxTimerDelay); - } - }); - workTimer_.start(); - } - } - }); + // Do nothing, handled by custom game tick loop } /** @@ -532,11 +435,26 @@ public void actionPerformed(ActionEvent evt) { * @return True on successful startup. */ public static final boolean startup(String[] args) { - if (OS.isLinux() || OS.isMacintosh()) { - SystemBootstrap.loadLibrary("jcef"); - return N_Startup(OS.isMacintosh() ? getCefFrameworkPath(args) : null); + String jcefPath = getJcefLibPath(); + + if (OS.isWindows()) { + System.load(jcefPath + "/d3dcompiler_47.dll"); + System.load(jcefPath + "/libGLESv2.dll"); + System.load(jcefPath + "/libEGL.dll"); + System.load(jcefPath + "/chrome_elf.dll"); + System.load(jcefPath + "/libcef.dll"); + System.load(jcefPath + "/jcef.dll"); + return true; + } else if (OS.isMacintosh()) { + System.load(jcefPath + "/libjcef.dylib"); + return N_Startup(getCefFrameworkPath(args)); + } else if (OS.isLinux()) { + System.load(jcefPath + "/libcef.so"); + System.load(jcefPath + "/libjcef.so"); + return N_Startup(null); } - return true; + + return false; } /** @@ -544,21 +462,16 @@ public static final boolean startup(String[] args) { * @return The path to the jcef library */ private static final String getJcefLibPath() { - String library_path = System.getProperty("java.library.path"); - String[] paths = library_path.split(System.getProperty("path.separator")); - for (String path : paths) { - File dir = new File(path); - String[] found = dir.list(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return (name.equalsIgnoreCase("libjcef.dylib") - || name.equalsIgnoreCase("libjcef.so") - || name.equalsIgnoreCase("jcef.dll")); - } - }); - if (found != null && found.length != 0) return path; + Path librariesPath = Paths.get(System.getProperty("jcef.path")); + Path jcefPath; + + if (OS.isMacintosh()) { + jcefPath = librariesPath.resolve("jcef_app.app/Contents/Java"); + } else { + jcefPath = librariesPath; } - return library_path; + + return jcefPath.toAbsolutePath().toString(); } /** @@ -583,7 +496,7 @@ private static final String getCefFrameworkPath(String[] args) { private final native boolean N_PreInitialize(); private final native boolean N_Initialize(CefAppHandler appHandler, CefSettings settings); private final native void N_Shutdown(); - private final native void N_DoMessageLoopWork(); + public final native void N_DoMessageLoopWork(); private final native CefVersion N_GetVersion(); private final native boolean N_RegisterSchemeHandlerFactory( String schemeName, String domainName, CefSchemeHandlerFactory factory); diff --git a/java/org/cef/CefClient.java b/java/org/cef/CefClient.java index 7f87bc5c..d2d956de 100644 --- a/java/org/cef/CefClient.java +++ b/java/org/cef/CefClient.java @@ -21,37 +21,14 @@ import org.cef.callback.CefMenuModel; import org.cef.callback.CefPrintDialogCallback; import org.cef.callback.CefPrintJobCallback; -import org.cef.handler.CefClientHandler; -import org.cef.handler.CefContextMenuHandler; -import org.cef.handler.CefDialogHandler; -import org.cef.handler.CefDisplayHandler; -import org.cef.handler.CefDownloadHandler; -import org.cef.handler.CefDragHandler; -import org.cef.handler.CefFocusHandler; -import org.cef.handler.CefJSDialogHandler; -import org.cef.handler.CefKeyboardHandler; -import org.cef.handler.CefLifeSpanHandler; -import org.cef.handler.CefLoadHandler; -import org.cef.handler.CefPrintHandler; -import org.cef.handler.CefRenderHandler; -import org.cef.handler.CefRequestHandler; -import org.cef.handler.CefResourceHandler; -import org.cef.handler.CefResourceRequestHandler; -import org.cef.handler.CefScreenInfo; -import org.cef.handler.CefWindowHandler; -import org.cef.misc.BoolRef; -import org.cef.misc.CefPrintSettings; -import org.cef.misc.StringRef; +import org.cef.handler.*; +import org.cef.misc.*; import org.cef.network.CefRequest; import org.cef.network.CefRequest.TransitionType; import org.cef.network.CefResponse; import org.cef.network.CefURLRequest; -import java.awt.Component; -import java.awt.Container; import java.awt.Dimension; -import java.awt.FocusTraversalPolicy; -import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; @@ -68,13 +45,14 @@ */ public class CefClient extends CefClientHandler implements CefContextMenuHandler, CefDialogHandler, CefDisplayHandler, CefDownloadHandler, - CefDragHandler, CefFocusHandler, CefJSDialogHandler, CefKeyboardHandler, - CefLifeSpanHandler, CefLoadHandler, CefPrintHandler, CefRenderHandler, - CefRequestHandler, CefWindowHandler { + CefDragHandler, CefFocusHandler, CefJSDialogHandler, CefKeyboardHandler, + CefLifeSpanHandler, CefLoadHandler, CefPrintHandler, CefRenderHandler, + CefRequestHandler, CefWindowHandler, CefAudioHandler { private HashMap browser_ = new HashMap(); private CefContextMenuHandler contextMenuHandler_ = null; private CefDialogHandler dialogHandler_ = null; private CefDisplayHandler displayHandler_ = null; + private CefAudioHandler audioHandler_ = null; private CefDownloadHandler downloadHandler_ = null; private CefDragHandler dragHandler_ = null; private CefFocusHandler focusHandler_ = null; @@ -85,43 +63,15 @@ public class CefClient extends CefClientHandler private CefPrintHandler printHandler_ = null; private CefRequestHandler requestHandler_ = null; private boolean isDisposed_ = false; - private volatile CefBrowser focusedBrowser_ = null; - private final PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (focusedBrowser_ != null) { - Component browserUI = focusedBrowser_.getUIComponent(); - Object oldUI = evt.getOldValue(); - if (isPartOf(oldUI, browserUI)) { - focusedBrowser_.setFocus(false); - focusedBrowser_ = null; - } - } - } - }; /** * The CTOR is only accessible within this package. * Use CefApp.createClient() to create an instance of * this class. - * @see org.cef.CefApp.createClient() + * @see org.cef.CefApp#createClient() */ CefClient() throws UnsatisfiedLinkError { super(); - - KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener( - propertyChangeListener); - } - - private boolean isPartOf(Object obj, Component browserUI) { - if (obj == browserUI) return true; - if (obj instanceof Container) { - Component childs[] = ((Container) obj).getComponents(); - for (Component child : childs) { - return isPartOf(child, browserUI); - } - } - return false; } @Override @@ -133,15 +83,15 @@ public void dispose() { // CefClientHandler public CefBrowser createBrowser( - String url, boolean isOffscreenRendered, boolean isTransparent) { - return createBrowser(url, isOffscreenRendered, isTransparent, null); + String url, boolean isTransparent) { + return createBrowser(url, isTransparent, null); } - public CefBrowser createBrowser(String url, boolean isOffscreenRendered, boolean isTransparent, - CefRequestContext context) { + public CefBrowser createBrowser(String url, boolean isTransparent, + CefRequestContext context) { if (isDisposed_) throw new IllegalStateException("Can't create browser. CefClient is disposed"); - return CefBrowserFactory.create(this, url, isOffscreenRendered, isTransparent, context); + return CefBrowserFactory.create(this, url, isTransparent, context); } @Override @@ -172,6 +122,11 @@ protected CefDialogHandler getDialogHandler() { protected CefDisplayHandler getDisplayHandler() { return this; } + + @Override + protected CefAudioHandler getAudioHandler() { + return this; + } @Override protected CefDownloadHandler getDownloadHandler() { @@ -248,7 +203,7 @@ public void onBeforeContextMenu( @Override public boolean onContextMenuCommand(CefBrowser browser, CefFrame frame, - CefContextMenuParams params, int commandId, int eventFlags) { + CefContextMenuParams params, int commandId, int eventFlags) { if (contextMenuHandler_ != null && browser != null) return contextMenuHandler_.onContextMenuCommand( browser, frame, params, commandId, eventFlags); @@ -274,7 +229,7 @@ public void removeDialogHandler() { @Override public boolean onFileDialog(CefBrowser browser, FileDialogMode mode, String title, - String defaultFilePath, Vector acceptFilters, CefFileDialogCallback callback) { + String defaultFilePath, Vector acceptFilters, CefFileDialogCallback callback) { if (dialogHandler_ != null && browser != null) { return dialogHandler_.onFileDialog( browser, mode, title, defaultFilePath, acceptFilters, callback); @@ -322,7 +277,7 @@ public void onStatusMessage(CefBrowser browser, String value) { @Override public boolean onConsoleMessage(CefBrowser browser, CefSettings.LogSeverity level, - String message, String source, int line) { + String message, String source, int line) { if (displayHandler_ != null && browser != null) { return displayHandler_.onConsoleMessage(browser, level, message, source, line); } @@ -360,7 +315,7 @@ public void removeDownloadHandler() { @Override public void onBeforeDownload(CefBrowser browser, CefDownloadItem downloadItem, - String suggestedName, CefBeforeDownloadCallback callback) { + String suggestedName, CefBeforeDownloadCallback callback) { if (downloadHandler_ != null && browser != null) downloadHandler_.onBeforeDownload(browser, downloadItem, suggestedName, callback); } @@ -405,27 +360,6 @@ public void removeFocusHandler() { public void onTakeFocus(CefBrowser browser, boolean next) { if (browser == null) return; - browser.setFocus(false); - Container parent = browser.getUIComponent().getParent(); - if (parent != null) { - FocusTraversalPolicy policy = null; - while (parent != null) { - policy = parent.getFocusTraversalPolicy(); - if (policy != null) break; - parent = parent.getParent(); - } - if (policy != null) { - Component nextComp = next - ? policy.getComponentAfter(parent, browser.getUIComponent()) - : policy.getComponentBefore(parent, browser.getUIComponent()); - if (nextComp == null) { - policy.getDefaultComponent(parent).requestFocus(); - } else { - nextComp.requestFocus(); - } - } - } - focusedBrowser_ = null; if (focusHandler_ != null) focusHandler_.onTakeFocus(browser, next); } @@ -442,8 +376,6 @@ public boolean onSetFocus(final CefBrowser browser, FocusSource source) { public void onGotFocus(CefBrowser browser) { if (browser == null) return; - focusedBrowser_ = browser; - browser.setFocus(true); if (focusHandler_ != null) focusHandler_.onGotFocus(browser); } @@ -460,8 +392,8 @@ public void removeJSDialogHandler() { @Override public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType dialog_type, - String message_text, String default_prompt_text, CefJSDialogCallback callback, - BoolRef suppress_message) { + String message_text, String default_prompt_text, CefJSDialogCallback callback, + BoolRef suppress_message) { if (jsDialogHandler_ != null && browser != null) return jsDialogHandler_.onJSDialog(browser, origin_url, dialog_type, message_text, default_prompt_text, callback, suppress_message); @@ -470,7 +402,7 @@ public boolean onJSDialog(CefBrowser browser, String origin_url, JSDialogType di @Override public boolean onBeforeUnloadDialog(CefBrowser browser, String message_text, boolean is_reload, - CefJSDialogCallback callback) { + CefJSDialogCallback callback) { if (jsDialogHandler_ != null && browser != null) return jsDialogHandler_.onBeforeUnloadDialog( browser, message_text, is_reload, callback); @@ -584,11 +516,10 @@ private void cleanupBrowser(int identifier) { } if (browser_.isEmpty() && isDisposed_) { - KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener( - propertyChangeListener); removeContextMenuHandler(this); removeDialogHandler(this); removeDisplayHandler(this); + removeAudioHandler(this); removeDownloadHandler(this); removeDragHandler(this); removeFocusHandler(this); @@ -639,7 +570,7 @@ public void onLoadEnd(CefBrowser browser, CefFrame frame, int httpStatusCode) { @Override public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, - String errorText, String failedUrl) { + String errorText, String failedUrl) { if (loadHandler_ != null && browser != null) loadHandler_.onLoadError(browser, frame, errorCode, errorText, failedUrl); } @@ -677,7 +608,7 @@ public boolean onPrintDialog( @Override public boolean onPrintJob(CefBrowser browser, String documentName, String pdfFilePath, - CefPrintJobCallback callback) { + CefPrintJobCallback callback) { if (printHandler_ != null && browser != null) return printHandler_.onPrintJob(browser, documentName, pdfFilePath, callback); return false; @@ -745,7 +676,7 @@ public void onPopupSize(CefBrowser browser, Rectangle size) { @Override public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, - ByteBuffer buffer, int width, int height) { + ByteBuffer buffer, int width, int height) { if (browser == null) return; CefRenderHandler realHandler = browser.getRenderHandler(); @@ -783,7 +714,7 @@ public void removeRequestHandler() { @Override public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, - boolean user_gesture, boolean is_redirect) { + boolean user_gesture, boolean is_redirect) { if (requestHandler_ != null && browser != null) return requestHandler_.onBeforeBrowse( browser, frame, request, user_gesture, is_redirect); @@ -801,8 +732,8 @@ public boolean onOpenURLFromTab( @Override public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, CefFrame frame, - CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, - BoolRef disableDefaultHandling) { + CefRequest request, boolean isNavigation, boolean isDownload, String requestInitiator, + BoolRef disableDefaultHandling) { if (requestHandler_ != null && browser != null) { return requestHandler_.getResourceRequestHandler(browser, frame, request, isNavigation, isDownload, requestInitiator, disableDefaultHandling); @@ -812,7 +743,7 @@ public CefResourceRequestHandler getResourceRequestHandler(CefBrowser browser, C @Override public boolean getAuthCredentials(CefBrowser browser, String origin_url, boolean isProxy, - String host, int port, String realm, String scheme, CefAuthCallback callback) { + String host, int port, String realm, String scheme, CefAuthCallback callback) { if (requestHandler_ != null && browser != null) return requestHandler_.getAuthCredentials( browser, origin_url, isProxy, host, port, realm, scheme, callback); @@ -857,4 +788,41 @@ public void onMouseEvent( public boolean getScreenInfo(CefBrowser arg0, CefScreenInfo arg1) { return false; } + + // CefAudioHandler + + public CefClient addAudioHandler(CefAudioHandler handler) { + if (audioHandler_ == null) audioHandler_ = handler; + return this; + } + + public void removeAudioHandler() { + audioHandler_ = null; + } + + @Override + public boolean getAudioParameters(CefBrowser browser, CefAudioParameters params) { + if (audioHandler_ != null) return audioHandler_.getAudioParameters(browser, params); + return false; + } + + @Override + public void onAudioStreamStarted(CefBrowser browser, CefAudioParameters params, int channels) { + if (audioHandler_ != null) audioHandler_.onAudioStreamStarted(browser, params, channels); + } + + @Override + public void onAudioStreamPacket(CefBrowser browser, DataPointer data, int frames, long pts) { + if (audioHandler_ != null) audioHandler_.onAudioStreamPacket(browser, data, frames, pts); + } + + @Override + public void onAudioStreamStopped(CefBrowser browser) { + if (audioHandler_ != null) audioHandler_.onAudioStreamStopped(browser); + } + + @Override + public void onAudioStreamError(CefBrowser browser, String text) { + if (audioHandler_ != null) audioHandler_.onAudioStreamError(browser, text); + } } diff --git a/java/org/cef/CefSettings.java b/java/org/cef/CefSettings.java index 5d756d99..a094b355 100644 --- a/java/org/cef/CefSettings.java +++ b/java/org/cef/CefSettings.java @@ -75,6 +75,10 @@ public ColorType clone() { } } + // macOS specific settings + public String framework_dir_path = null; + public String main_bundle_path = null; + /** * The path to a separate executable that will be launched for sub-processes. * By default the browser process executable is used. See the comments on @@ -235,6 +239,8 @@ public CefSettings() {} @Override public CefSettings clone() { CefSettings tmp = new CefSettings(); + tmp.framework_dir_path = framework_dir_path; + tmp.main_bundle_path = main_bundle_path; tmp.browser_subprocess_path = browser_subprocess_path; tmp.windowless_rendering_enabled = windowless_rendering_enabled; tmp.command_line_args_disabled = command_line_args_disabled; diff --git a/java/org/cef/browser/CefBrowser.java b/java/org/cef/browser/CefBrowser.java index 43ae8f60..e73bae58 100644 --- a/java/org/cef/browser/CefBrowser.java +++ b/java/org/cef/browser/CefBrowser.java @@ -31,12 +31,6 @@ public interface CefBrowser { */ public void createImmediately(); - /** - * Get the underlying UI component (e.g. java.awt.Canvas). - * @return The underlying UI component. - */ - public Component getUIComponent(); - /** * Get the client associated with this browser. * @return The browser client. diff --git a/java/org/cef/browser/CefBrowserFactory.java b/java/org/cef/browser/CefBrowserFactory.java index 708d0f24..98a1678e 100644 --- a/java/org/cef/browser/CefBrowserFactory.java +++ b/java/org/cef/browser/CefBrowserFactory.java @@ -10,9 +10,8 @@ * Creates a new instance of CefBrowser according the passed values */ public class CefBrowserFactory { - public static CefBrowser create(CefClient client, String url, boolean isOffscreenRendered, + public static CefBrowser create(CefClient client, String url, boolean isTransparent, CefRequestContext context) { - if (isOffscreenRendered) return new CefBrowserOsr(client, url, isTransparent, context); - return new CefBrowserWr(client, url, context); + return new CefBrowserOsr(client, url, isTransparent, context); } } diff --git a/java/org/cef/browser/CefBrowserOsr.java b/java/org/cef/browser/CefBrowserOsr.java index 902bc862..cd80d9ba 100644 --- a/java/org/cef/browser/CefBrowserOsr.java +++ b/java/org/cef/browser/CefBrowserOsr.java @@ -4,87 +4,35 @@ package org.cef.browser; -import com.jogamp.nativewindow.NativeSurface; -import com.jogamp.opengl.GL; -import com.jogamp.opengl.GL2; -import com.jogamp.opengl.GLAutoDrawable; -import com.jogamp.opengl.GLCapabilities; -import com.jogamp.opengl.GLContext; -import com.jogamp.opengl.GLEventListener; -import com.jogamp.opengl.GLProfile; -import com.jogamp.opengl.awt.GLCanvas; -import com.jogamp.opengl.util.GLBuffers; - import org.cef.CefClient; -import org.cef.OS; import org.cef.callback.CefDragData; import org.cef.handler.CefRenderHandler; import org.cef.handler.CefScreenInfo; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.datatransfer.StringSelection; +import java.awt.*; import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceAdapter; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DropTarget; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; 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.geom.AffineTransform; -import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; -import java.lang.ClassNotFoundException; -import java.lang.IllegalAccessException; -import java.lang.IllegalArgumentException; -import java.lang.NoSuchMethodException; -import java.lang.SecurityException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.swing.MenuSelectionManager; -import javax.swing.SwingUtilities; /** * This class represents an off-screen rendered browser. * The visibility of this class is "package". To create a new * CefBrowser instance, please use CefBrowserFactory. */ -class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { - private CefRenderer renderer_; - private GLCanvas canvas_; - private long window_handle_ = 0; +public class CefBrowserOsr extends CefBrowser_N implements CefRenderHandler { private boolean justCreated_ = false; - private Rectangle browser_rect_ = new Rectangle(0, 0, 1, 1); // Work around CEF issue #1437. + protected Rectangle browser_rect_ = new Rectangle(0, 0, 1, 1); // Work around CEF issue #1437. private Point screenPoint_ = new Point(0, 0); private double scaleFactor_ = 1.0; private int depth = 32; private int depth_per_component = 8; private boolean isTransparent_; - CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) { + public CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context) { this(client, url, transparent, context, null, null); } @@ -92,8 +40,6 @@ private CefBrowserOsr(CefClient client, String url, boolean transparent, CefRequestContext context, CefBrowserOsr parent, Point inspectAt) { super(client, url, context, parent, inspectAt); isTransparent_ = transparent; - renderer_ = new CefRenderer(transparent); - createGLCanvas(); } @Override @@ -103,230 +49,14 @@ public void createImmediately() { createBrowserIfRequired(false); } - @Override - public Component getUIComponent() { - return canvas_; - } - @Override public CefRenderHandler getRenderHandler() { return this; } @Override - protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, - CefRequestContext context, CefBrowser_N parent, Point inspectAt) { - return new CefBrowserOsr( - client, url, isTransparent_, context, (CefBrowserOsr) this, inspectAt); - } - - private synchronized long getWindowHandle() { - if (window_handle_ == 0) { - NativeSurface surface = canvas_.getNativeSurface(); - if (surface != null) { - surface.lockSurface(); - window_handle_ = getWindowHandle(surface.getSurfaceHandle()); - surface.unlockSurface(); - assert (window_handle_ != 0); - } - } - return window_handle_; - } - - @SuppressWarnings("serial") - private void createGLCanvas() { - GLProfile glprofile = GLProfile.getMaxFixedFunc(true); - GLCapabilities glcapabilities = new GLCapabilities(glprofile); - canvas_ = new GLCanvas(glcapabilities) { - private Method scaleFactorAccessor = null; - private boolean removed_ = true; - - @Override - public void paint(Graphics g) { - createBrowserIfRequired(true); - if (g instanceof Graphics2D) { - GraphicsConfiguration config = ((Graphics2D) g).getDeviceConfiguration(); - depth = config.getColorModel().getPixelSize(); - depth_per_component = config.getColorModel().getComponentSize()[0]; - - if (OS.isMacintosh() - && System.getProperty("java.runtime.version").startsWith("1.8")) { - // This fixes a weird thing on MacOS: the scale factor being read from - // getTransform().getScaleX() is incorrect for Java 8 VMs; it is always - // 1, even though Retina display scaling of window sizes etc. is - // definitely ongoing somewhere in the lower levels of AWT. This isn't - // too big of a problem for us, because the transparent scaling handles - // the situation, except for one thing: the screenshot-grabbing - // code below, which reads from the OpenGL context, must know the real - // scale factor, because the image to be read is larger by that factor - // and thus a bigger buffer is required. This is why there's some - // admittedly-ugly reflection magic going on below that's able to get - // the real scale factor. - // All of this is not relevant for either Windows or MacOS JDKs > 8, - // for which the official "getScaleX()" approach works fine. - try { - if (scaleFactorAccessor == null) { - scaleFactorAccessor = getClass() - .getClassLoader() - .loadClass("sun.awt.CGraphicsDevice") - .getDeclaredMethod("getScaleFactor"); - } - Object factor = scaleFactorAccessor.invoke(config.getDevice()); - if (factor instanceof Integer) { - scaleFactor_ = ((Integer) factor).doubleValue(); - } else { - scaleFactor_ = 1.0; - } - } catch (InvocationTargetException | IllegalAccessException - | IllegalArgumentException | NoSuchMethodException - | SecurityException | ClassNotFoundException exc) { - scaleFactor_ = 1.0; - } - } else { - scaleFactor_ = ((Graphics2D) g).getTransform().getScaleX(); - } - } - super.paint(g); - } - - @Override - public void addNotify() { - super.addNotify(); - if (removed_) { - notifyAfterParentChanged(); - removed_ = false; - } - } - - @Override - public void removeNotify() { - if (!removed_) { - if (!isClosed()) { - notifyAfterParentChanged(); - } - removed_ = true; - } - super.removeNotify(); - } - }; - - // The GLContext will be re-initialized when changing displays, resulting in calls to - // dispose/init/reshape. - canvas_.addGLEventListener(new GLEventListener() { - @Override - public void reshape( - GLAutoDrawable glautodrawable, int x, int y, int width, int height) { - int newWidth = width; - int newHeight = height; - if (OS.isMacintosh()) { - // HiDPI display scale correction support code - // For some reason this does seem to be necessary on MacOS only. - // If doing this correction on Windows, the browser content would be too - // small and in the lower left corner of the canvas only. - newWidth = (int) (width / scaleFactor_); - newHeight = (int) (height / scaleFactor_); - } - browser_rect_.setBounds(x, y, newWidth, newHeight); - screenPoint_ = canvas_.getLocationOnScreen(); - wasResized(newWidth, newHeight); - } - - @Override - public void init(GLAutoDrawable glautodrawable) { - renderer_.initialize(glautodrawable.getGL().getGL2()); - } - - @Override - public void dispose(GLAutoDrawable glautodrawable) { - renderer_.cleanup(glautodrawable.getGL().getGL2()); - } - - @Override - public void display(GLAutoDrawable glautodrawable) { - renderer_.render(glautodrawable.getGL().getGL2()); - } - }); - - canvas_.addMouseListener(new MouseListener() { - @Override - public void mousePressed(MouseEvent e) { - sendMouseEvent(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - sendMouseEvent(e); - } - - @Override - public void mouseEntered(MouseEvent e) { - sendMouseEvent(e); - } - - @Override - public void mouseExited(MouseEvent e) { - sendMouseEvent(e); - } - - @Override - public void mouseClicked(MouseEvent e) { - sendMouseEvent(e); - } - }); - - canvas_.addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseMoved(MouseEvent e) { - sendMouseEvent(e); - } - - @Override - public void mouseDragged(MouseEvent e) { - sendMouseEvent(e); - } - }); - - canvas_.addMouseWheelListener(new MouseWheelListener() { - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - sendMouseWheelEvent(e); - } - }); - - canvas_.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - sendKeyEvent(e); - } - - @Override - public void keyPressed(KeyEvent e) { - sendKeyEvent(e); - } - - @Override - public void keyReleased(KeyEvent e) { - sendKeyEvent(e); - } - }); - - canvas_.setFocusable(true); - canvas_.addFocusListener(new FocusListener() { - @Override - public void focusLost(FocusEvent e) { - setFocus(false); - } - - @Override - public void focusGained(FocusEvent e) { - // Dismiss any Java menus that are currently displayed. - MenuSelectionManager.defaultManager().clearSelectedPath(); - setFocus(true); - } - }); - - // Connect the Canvas with a drag and drop listener. - new DropTarget(canvas_, new CefDropTargetListener(this)); + protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, CefRequestContext context, CefBrowser_N parent, Point inspectAt) { + return null; } @Override @@ -343,50 +73,18 @@ public Point getScreenPoint(CefBrowser browser, Point viewPoint) { @Override public void onPopupShow(CefBrowser browser, boolean show) { - if (!show) { - renderer_.clearPopupRects(); - invalidate(); - } } @Override public void onPopupSize(CefBrowser browser, Rectangle size) { - renderer_.onPopupSize(size); } @Override - public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, - ByteBuffer buffer, int width, int height) { - // 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; - } - - renderer_.onPaint(canvas_.getGL().getGL2(), popup, dirtyRects, buffer, width, height); - context.release(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - canvas_.display(); - } - }); + public void onPaint(CefBrowser browser, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, int width, int height) { } @Override public boolean onCursorChange(CefBrowser browser, final int cursorType) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - canvas_.setCursor(new Cursor(cursorType)); - } - }); - - // OSR always handles the cursor change. return true; } @@ -419,42 +117,21 @@ private static int getDndAction(int mask) { @Override public boolean startDragging(CefBrowser browser, CefDragData dragData, int mask, int x, int y) { - int action = getDndAction(mask); - MouseEvent triggerEvent = - new MouseEvent(canvas_, MouseEvent.MOUSE_DRAGGED, 0, 0, x, y, 0, false); - DragGestureEvent ev = new DragGestureEvent( - new SyntheticDragGestureRecognizer(canvas_, action, triggerEvent), action, - new Point(x, y), new ArrayList<>(Arrays.asList(triggerEvent))); - - DragSource.getDefaultDragSource().startDrag(ev, /*dragCursor=*/null, - new StringSelection(dragData.getFragmentText()), new DragSourceAdapter() { - @Override - public void dragDropEnd(DragSourceDropEvent dsde) { - dragSourceEndedAt(dsde.getLocation(), action); - dragSourceSystemDragEnded(); - } - }); return true; } @Override public void updateDragCursor(CefBrowser browser, int operation) { - // TODO: Consider calling onCursorChange() if we want different cursors based on - // |operation|. } private void createBrowserIfRequired(boolean hasParent) { long windowHandle = 0; - if (hasParent) { - windowHandle = getWindowHandle(); - } - if (getNativeRef("CefBrowser") == 0) { if (getParentBrowser() != null) { createDevTools(getParentBrowser(), getClient(), windowHandle, true, isTransparent_, - null, getInspectAt()); + getInspectAt()); } else { - createBrowser(getClient(), windowHandle, getUrl(), true, isTransparent_, null, + createBrowser(getClient(), windowHandle, getUrl(), true, isTransparent_, getRequestContext()); } } else if (hasParent && justCreated_) { @@ -480,159 +157,6 @@ public boolean getScreenInfo(CefBrowser browser, CefScreenInfo screenInfo) { @Override public CompletableFuture createScreenshot(boolean nativeResolution) { - int width = (int) Math.ceil(canvas_.getWidth() * scaleFactor_); - int height = (int) Math.ceil(canvas_.getHeight() * scaleFactor_); - - // In order to grab a screenshot of the browser window, we need to get the OpenGL internals - // from the GLCanvas that displays the browser. - GL2 gl = canvas_.getGL().getGL2(); - int textureId = renderer_.getTextureID(); - - // This mirrors the two ways in which CefRenderer may render images internally - either via - // an incrementally updated texture that is the same size as the window and simply rendered - // onto a textured quad by graphics hardware, in which case we capture the data directly - // from this texture, or by directly writing pixels into the OpenGL framebuffer, in which - // case we directly read those pixels back. The latter is the way chosen if there is no - // hardware rasterizer capability detected. We can simply distinguish both approaches by - // looking whether the textureId of the renderer is a valid (non-zero) one. - boolean useReadPixels = (textureId == 0); - - // This Callable encapsulates the pixel-reading code. After running it, the screenshot - // BufferedImage contains the grabbed image. - final Callable pixelGrabberCallable = new Callable() { - @Override - public BufferedImage call() { - BufferedImage screenshot = - new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - ByteBuffer buffer = GLBuffers.newDirectByteBuffer(width * height * 4); - - gl.getContext().makeCurrent(); - try { - if (useReadPixels) { - // If pixels are copied directly to the framebuffer, we also directly read - // them back. - gl.glReadPixels( - 0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer); - } else { - // In this case, read the texture pixel data from the previously-retrieved - // texture ID - gl.glEnable(GL.GL_TEXTURE_2D); - gl.glBindTexture(GL.GL_TEXTURE_2D, textureId); - gl.glGetTexImage( - GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer); - gl.glDisable(GL.GL_TEXTURE_2D); - } - } finally { - gl.getContext().release(); - } - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - // The OpenGL functions only support RGBA, while Java BufferedImage uses - // ARGB. We must convert. - int r = (buffer.get() & 0xff); - int g = (buffer.get() & 0xff); - int b = (buffer.get() & 0xff); - int a = (buffer.get() & 0xff); - int argb = (a << 24) | (r << 16) | (g << 8) | (b << 0); - // If pixels were read from the framebuffer, we have to flip the resulting - // image on the Y axis, as the OpenGL framebuffer's y axis starts at the - // bottom of the image pointing "upwards", while BufferedImage has the - // origin in the upper left corner. This flipping is done when drawing into - // the BufferedImage. - screenshot.setRGB(x, useReadPixels ? (height - y - 1) : y, argb); - } - } - - if (!nativeResolution && scaleFactor_ != 1.0) { - // HiDPI images should be resized down to "normal" levels - BufferedImage resized = - new BufferedImage((int) (screenshot.getWidth() / scaleFactor_), - (int) (screenshot.getHeight() / scaleFactor_), - BufferedImage.TYPE_INT_ARGB); - AffineTransform tempTransform = new AffineTransform(); - tempTransform.scale(1.0 / scaleFactor_, 1.0 / scaleFactor_); - AffineTransformOp tempScaleOperation = - new AffineTransformOp(tempTransform, AffineTransformOp.TYPE_BILINEAR); - resized = tempScaleOperation.filter(screenshot, resized); - return resized; - } else { - return screenshot; - } - } - }; - - if (SwingUtilities.isEventDispatchThread()) { - // If called on the AWT event thread, just access the GL API - try { - BufferedImage screenshot = pixelGrabberCallable.call(); - return CompletableFuture.completedFuture(screenshot); - } catch (Exception e) { - CompletableFuture future = new CompletableFuture(); - future.completeExceptionally(e); - return future; - } - } else { - // If called from another thread, register a GLEventListener and trigger an async - // redraw, during which we use the GL API to grab the pixel data. An unresolved Future - // is returned, on which the caller can wait for a result (but not with the Event - // Thread, as we need that for pixel grabbing, which is why there's a safeguard in place - // to catch that situation if it accidentally happens). - CompletableFuture future = new CompletableFuture() { - private void safeguardGet() { - if (SwingUtilities.isEventDispatchThread()) { - throw new RuntimeException( - "Waiting on this Future using the AWT Event Thread is illegal, " - + "because it can potentially deadlock the thread."); - } - } - - @Override - public BufferedImage get() throws InterruptedException, ExecutionException { - safeguardGet(); - return super.get(); - } - - @Override - public BufferedImage get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - safeguardGet(); - return super.get(timeout, unit); - } - }; - canvas_.addGLEventListener(new GLEventListener() { - @Override - public void reshape( - GLAutoDrawable aDrawable, int aArg1, int aArg2, int aArg3, int aArg4) { - // ignore - } - - @Override - public void init(GLAutoDrawable aDrawable) { - // ignore - } - - @Override - public void dispose(GLAutoDrawable aDrawable) { - // ignore - } - - @Override - public void display(GLAutoDrawable aDrawable) { - canvas_.removeGLEventListener(this); - try { - future.complete(pixelGrabberCallable.call()); - } catch (Exception e) { - future.completeExceptionally(e); - } - } - }); - - // This repaint triggers an indirect call to the listeners' display method above, which - // ultimately completes the future that we return immediately. - canvas_.repaint(); - - return future; - } + return null; } } diff --git a/java/org/cef/browser/CefBrowserWr.java b/java/org/cef/browser/CefBrowserWr.java deleted file mode 100644 index 583c4f41..00000000 --- a/java/org/cef/browser/CefBrowserWr.java +++ /dev/null @@ -1,424 +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 org.cef.browser; - -import org.cef.CefClient; -import org.cef.OS; -import org.cef.handler.CefWindowHandler; -import org.cef.handler.CefWindowHandlerAdapter; - -import java.awt.BorderLayout; -import java.awt.Canvas; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.MouseInfo; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.HierarchyBoundsListener; -import java.awt.event.HierarchyEvent; -import java.awt.event.HierarchyListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.image.BufferedImage; -import java.util.Date; -import java.util.concurrent.CompletableFuture; - -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.MenuSelectionManager; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.ToolTipManager; - -/** - * This class represents a windowed rendered browser. - * The visibility of this class is "package". To create a new - * CefBrowser instance, please use CefBrowserFactory. - */ -class CefBrowserWr extends CefBrowser_N { - private Canvas canvas_ = null; - private Component component_ = null; - private Rectangle content_rect_ = new Rectangle(0, 0, 0, 0); - private long window_handle_ = 0; - private boolean justCreated_ = false; - private double scaleFactor_ = 1.0; - private Timer delayedUpdate_ = new Timer(100, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (isClosed()) return; - - boolean hasCreatedUI = createBrowserIfRequired(true); - - if (hasCreatedUI) { - delayedUpdate_.restart(); - } else { - // If on Mac, this is needed due to the quirk described below - // (in org.cef.browser.CefBrowserWr.CefBrowserWr(...).new JPanel() - // {...}.paint(Graphics)). If on Linux, this is needed to invoke an - // XMoveResizeWindow call shortly after the UI was created. That seems to be - // necessary to actually get a windowed renderer to display something. - if (OS.isMacintosh() || OS.isLinux()) doUpdate(); - } - } - }); - } - }); - - private CefWindowHandlerAdapter win_handler_ = new CefWindowHandlerAdapter() { - private Point lastPos = new Point(-1, -1); - private long[] nextClick = new long[MouseInfo.getNumberOfButtons()]; - private int[] clickCnt = new int[MouseInfo.getNumberOfButtons()]; - - @Override - public Rectangle getRect(CefBrowser browser) { - synchronized (content_rect_) { - return content_rect_; - } - } - - @Override - public void onMouseEvent(CefBrowser browser, int event, final int screenX, - final int screenY, final int modifier, final int button) { - final Point pt = new Point(screenX, screenY); - if (event == MouseEvent.MOUSE_MOVED) { - // Remove mouse-moved events if the position of the cursor hasn't - // changed. - if (pt.equals(lastPos)) return; - lastPos = pt; - - // Change mouse-moved event to mouse-dragged event if the left mouse - // button is pressed. - if ((modifier & MouseEvent.BUTTON1_DOWN_MASK) != 0) - event = MouseEvent.MOUSE_DRAGGED; - } - - final int finalEvent = event; - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // Send mouse event to the root UI component instead to the browser UI. - // Otherwise no mouse-entered and no mouse-exited events would be fired. - Component parent = SwingUtilities.getRoot(component_); - if (parent == null) { - return; - } - SwingUtilities.convertPointFromScreen(pt, parent); - - int clickCnt = 0; - long now = new Date().getTime(); - if (finalEvent == MouseEvent.MOUSE_WHEEL) { - int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL; - int rotation = button > 0 ? 1 : -1; - component_.dispatchEvent(new MouseWheelEvent(parent, finalEvent, now, - modifier, pt.x, pt.y, 0, false, scrollType, 3, rotation)); - } else { - clickCnt = getClickCount(finalEvent, button); - component_.dispatchEvent(new MouseEvent(parent, finalEvent, now, modifier, - pt.x, pt.y, screenX, screenY, clickCnt, false, button)); - } - - // Always fire a mouse-clicked event after a mouse-released event. - if (finalEvent == MouseEvent.MOUSE_RELEASED) { - component_.dispatchEvent( - new MouseEvent(parent, MouseEvent.MOUSE_CLICKED, now, modifier, - pt.x, pt.y, screenX, screenY, clickCnt, false, button)); - } - } - }); - } - - public int getClickCount(int event, int button) { - // avoid exceptions by using modulo - int idx = button % nextClick.length; - - switch (event) { - case MouseEvent.MOUSE_PRESSED: - long currTime = new Date().getTime(); - if (currTime > nextClick[idx]) { - nextClick[idx] = currTime - + (Integer) Toolkit.getDefaultToolkit().getDesktopProperty( - "awt.multiClickInterval"); - clickCnt[idx] = 1; - } else { - clickCnt[idx]++; - } - // FALL THRU - case MouseEvent.MOUSE_RELEASED: - return clickCnt[idx]; - default: - return 0; - } - } - }; - - CefBrowserWr(CefClient client, String url, CefRequestContext context) { - this(client, url, context, null, null); - } - - @SuppressWarnings("serial") - private CefBrowserWr(CefClient client, String url, CefRequestContext context, - CefBrowserWr parent, Point inspectAt) { - super(client, url, context, parent, inspectAt); - delayedUpdate_.setRepeats(false); - - // Disabling lightweight of popup menu is required because - // otherwise it will be displayed behind the content of component_ - JPopupMenu.setDefaultLightWeightPopupEnabled(false); - ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); - - // We're using a JComponent instead of a Canvas now because the - // JComponent has clipping informations, which aren't accessible for Canvas. - component_ = new JPanel(new BorderLayout()) { - private boolean removed_ = true; - - @Override - public void setBounds(int x, int y, int width, int height) { - super.setBounds(x, y, width, height); - wasResized((int) (width * scaleFactor_), (int) (height * scaleFactor_)); - } - - @Override - public void setBounds(Rectangle r) { - setBounds(r.x, r.y, r.width, r.height); - } - - @Override - public void setSize(int width, int height) { - super.setSize(width, height); - wasResized((int) (width * scaleFactor_), (int) (height * scaleFactor_)); - } - - @Override - public void setSize(Dimension d) { - setSize(d.width, d.height); - } - - @Override - public void paint(Graphics g) { - // If the user resizes the UI component, the new size and clipping - // informations are forwarded to the native code. - // But on Mac the last resize information doesn't resize the native UI - // accurately (sometimes the native UI is too small). An easy way to - // solve this, is to send the last Update-Information again. Therefore - // we're setting up a delayedUpdate timer which is reset each time - // paint is called. This prevents the us of sending the UI update too - // often. - if (g instanceof Graphics2D) { - scaleFactor_ = ((Graphics2D) g).getTransform().getScaleX(); - } - doUpdate(); - delayedUpdate_.restart(); - } - - @Override - public void addNotify() { - super.addNotify(); - if (removed_) { - setParent(getWindowHandle(this), canvas_); - removed_ = false; - } - } - - @Override - public void removeNotify() { - if (!removed_) { - if (!isClosed()) { - setParent(0, null); - } - removed_ = true; - } - super.removeNotify(); - } - }; - - // On windows we have to use a Canvas because its a heavyweight component - // and we need its native HWND as parent for the browser UI. The same - // technique is used on Linux as well. - if (OS.isWindows() || OS.isLinux()) { - canvas_ = new Canvas(); - ((JPanel) component_).add(canvas_, BorderLayout.CENTER); - } - - // Initial minimal size of the component. Otherwise the UI won't work - // accordingly in panes like JSplitPane. - component_.setMinimumSize(new Dimension(0, 0)); - component_.setFocusable(true); - component_.addFocusListener(new FocusListener() { - @Override - public void focusLost(FocusEvent e) { - setFocus(false); - } - - @Override - public void focusGained(FocusEvent e) { - // Dismiss any Java menus that are currently displayed. - MenuSelectionManager.defaultManager().clearSelectedPath(); - setFocus(true); - } - }); - component_.addHierarchyBoundsListener(new HierarchyBoundsListener() { - @Override - public void ancestorResized(HierarchyEvent e) { - doUpdate(); - } - @Override - public void ancestorMoved(HierarchyEvent e) { - doUpdate(); - notifyMoveOrResizeStarted(); - } - }); - component_.addHierarchyListener(new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { - setWindowVisibility(e.getChanged().isVisible()); - } - } - }); - } - - @Override - public void createImmediately() { - justCreated_ = true; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // Create the browser immediately. It will be parented to the Java - // window once it becomes available. - createBrowserIfRequired(false); - } - }); - } - - @Override - public Component getUIComponent() { - return component_; - } - - @Override - public CefWindowHandler getWindowHandler() { - return win_handler_; - } - - @Override - protected CefBrowser_N createDevToolsBrowser(CefClient client, String url, - CefRequestContext context, CefBrowser_N parent, Point inspectAt) { - return new CefBrowserWr(client, url, context, (CefBrowserWr) this, inspectAt); - } - - private synchronized long getWindowHandle() { - if (window_handle_ == 0 && OS.isMacintosh()) { - window_handle_ = getWindowHandle(component_); - } - return window_handle_; - } - - private static long getWindowHandle(Component component) { - if (OS.isMacintosh()) { - try { - Class cls = Class.forName("org.cef.browser.mac.CefBrowserWindowMac"); - CefBrowserWindow browserWindow = (CefBrowserWindow) cls.newInstance(); - if (browserWindow != null) { - return browserWindow.getWindowHandle(component); - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - return 0; - } - - private void doUpdate() { - if (isClosed()) return; - - Rectangle vr = ((JPanel) component_).getVisibleRect(); - Rectangle clipping = new Rectangle((int) (vr.getX() * scaleFactor_), - (int) (vr.getY() * scaleFactor_), (int) (vr.getWidth() * scaleFactor_), - (int) (vr.getHeight() * scaleFactor_)); - - if (OS.isMacintosh()) { - Container parent = component_.getParent(); - Point contentPos = component_.getLocation(); - while (parent != null) { - Container next = parent.getParent(); - if (next != null && next instanceof Window) break; - Point parentPos = parent.getLocation(); - contentPos.translate(parentPos.x, parentPos.y); - parent = next; - } - contentPos.translate(clipping.x, clipping.y); - - Point browserPos = clipping.getLocation(); - browserPos.x *= -1; - browserPos.y *= -1; - - synchronized (content_rect_) { - content_rect_ = new Rectangle(contentPos, clipping.getSize()); - Rectangle browserRect = new Rectangle(browserPos, component_.getSize()); - updateUI(content_rect_, browserRect); - } - } else { - synchronized (content_rect_) { - Rectangle bounds = null != canvas_ ? canvas_.getBounds() : component_.getBounds(); - content_rect_ = new Rectangle((int) (bounds.getX() * scaleFactor_), - (int) (bounds.getY() * scaleFactor_), - (int) (bounds.getWidth() * scaleFactor_), - (int) (bounds.getHeight() * scaleFactor_)); - updateUI(clipping, content_rect_); - } - } - } - - private boolean createBrowserIfRequired(boolean hasParent) { - if (isClosed()) return false; - - long windowHandle = 0; - Component canvas = null; - if (hasParent) { - windowHandle = getWindowHandle(); - canvas = (OS.isWindows() || OS.isLinux()) ? canvas_ : component_; - } - - if (getNativeRef("CefBrowser") == 0) { - if (getParentBrowser() != null) { - createDevTools(getParentBrowser(), getClient(), windowHandle, false, false, canvas, - getInspectAt()); - return true; - } else { - createBrowser(getClient(), windowHandle, getUrl(), false, false, canvas, - getRequestContext()); - return true; - } - } else if (hasParent && justCreated_) { - setParent(windowHandle, canvas); - setFocus(true); - justCreated_ = false; - } - - return false; - } - - @Override - public CompletableFuture createScreenshot(boolean nativeResolution) { - throw new UnsupportedOperationException("Unsupported for windowed rendering"); - } -} diff --git a/java/org/cef/browser/CefBrowser_N.java b/java/org/cef/browser/CefBrowser_N.java index 406d0256..6c3749f9 100644 --- a/java/org/cef/browser/CefBrowser_N.java +++ b/java/org/cef/browser/CefBrowser_N.java @@ -11,6 +11,9 @@ import org.cef.callback.CefPdfPrintCallback; import org.cef.callback.CefRunFileDialogCallback; import org.cef.callback.CefStringVisitor; +import org.cef.event.CefKeyEvent; +import org.cef.event.CefMouseEvent; +import org.cef.event.CefMouseWheelEvent; import org.cef.handler.CefClientHandler; import org.cef.handler.CefDialogHandler.FileDialogMode; import org.cef.handler.CefRenderHandler; @@ -18,14 +21,10 @@ import org.cef.misc.CefPdfPrintSettings; import org.cef.network.CefRequest; -import java.awt.Canvas; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; import java.awt.event.WindowEvent; import java.util.Vector; @@ -37,7 +36,7 @@ * The visibility of this class is "package". To create a new * CefBrowser instance, please use CefBrowserFactory. */ -abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { +public abstract class CefBrowser_N extends CefNativeAdapter implements CefBrowser { private volatile boolean isPending_ = false; private final CefClient client_; private final String url_; @@ -105,18 +104,6 @@ public synchronized boolean doClose() { return false; } - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // Trigger close of the parent window. - Component parent = SwingUtilities.getRoot(getUIComponent()); - if (parent != null) { - parent.dispatchEvent( - new WindowEvent((Window) parent, WindowEvent.WINDOW_CLOSING)); - } - } - }); - // Cancel the close. return true; } @@ -152,11 +139,11 @@ protected abstract CefBrowser_N createDevToolsBrowser(CefClient client, String u * Create a new browser. */ protected void createBrowser(CefClientHandler clientHandler, long windowHandle, String url, - boolean osr, boolean transparent, Component canvas, CefRequestContext context) { + boolean osr, boolean transparent, CefRequestContext context) { if (getNativeRef("CefBrowser") == 0 && !isPending_) { try { N_CreateBrowser( - clientHandler, windowHandle, url, osr, transparent, canvas, context); + clientHandler, windowHandle, url, osr, transparent, context); } catch (UnsatisfiedLinkError err) { err.printStackTrace(); } @@ -174,12 +161,12 @@ private void notifyBrowserCreated() { * Create a new browser as dev tools */ protected final void createDevTools(CefBrowser_N parent, CefClientHandler clientHandler, - long windowHandle, boolean osr, boolean transparent, Component canvas, + long windowHandle, boolean osr, boolean transparent, Point inspectAt) { if (getNativeRef("CefBrowser") == 0 && !isPending_) { try { isPending_ = N_CreateDevTools( - parent, clientHandler, windowHandle, osr, transparent, canvas, inspectAt); + parent, clientHandler, windowHandle, osr, transparent, inspectAt); } catch (UnsatisfiedLinkError err) { err.printStackTrace(); } @@ -595,7 +582,7 @@ protected final void invalidate() { * Send a key event. * @param e The event to send. */ - protected final void sendKeyEvent(KeyEvent e) { + protected final void sendKeyEvent(CefKeyEvent e) { try { N_SendKeyEvent(e); } catch (UnsatisfiedLinkError ule) { @@ -607,7 +594,7 @@ protected final void sendKeyEvent(KeyEvent e) { * Send a mouse event. * @param e The event to send. */ - protected final void sendMouseEvent(MouseEvent e) { + protected final void sendMouseEvent(CefMouseEvent e) { try { N_SendMouseEvent(e); } catch (UnsatisfiedLinkError ule) { @@ -619,7 +606,7 @@ protected final void sendMouseEvent(MouseEvent e) { * Send a mouse wheel event. * @param e The event to send. */ - protected final void sendMouseWheelEvent(MouseWheelEvent e) { + protected final void sendMouseWheelEvent(CefMouseWheelEvent e) { try { N_SendMouseWheelEvent(e); } catch (UnsatisfiedLinkError ule) { @@ -729,16 +716,6 @@ protected final void updateUI(Rectangle contentRect, Rectangle browserRect) { } } - protected final void setParent(long windowHandle, Component canvas) { - if (isClosing_ || isClosed_) return; - - try { - N_SetParent(windowHandle, canvas); - } catch (UnsatisfiedLinkError ule) { - ule.printStackTrace(); - } - } - /** * Call this method if the browser frame was moved. * This fixes positioning of select popups and dismissal on window move/resize. @@ -752,10 +729,10 @@ protected final void notifyMoveOrResizeStarted() { } private final native boolean N_CreateBrowser(CefClientHandler clientHandler, long windowHandle, - String url, boolean osr, boolean transparent, Component canvas, + String url, boolean osr, boolean transparent, CefRequestContext context); private final native boolean N_CreateDevTools(CefBrowser parent, CefClientHandler clientHandler, - long windowHandle, boolean osr, boolean transparent, Component canvas, Point inspectAt); + long windowHandle, boolean osr, boolean transparent, Point inspectAt); private final native long N_GetWindowHandle(long surfaceHandle); private final native boolean N_CanGoBack(); private final native void N_GoBack(); @@ -801,9 +778,9 @@ private final native void N_Find( private final native void N_ReplaceMisspelling(String word); private final native void N_WasResized(int width, int height); private final native void N_Invalidate(); - private final native void N_SendKeyEvent(KeyEvent e); - private final native void N_SendMouseEvent(MouseEvent e); - private final native void N_SendMouseWheelEvent(MouseWheelEvent e); + private final native void N_SendKeyEvent(CefKeyEvent e); + private final native void N_SendMouseEvent(CefMouseEvent e); + private final native void N_SendMouseWheelEvent(CefMouseWheelEvent e); private final native void N_DragTargetDragEnter( CefDragData dragData, Point pos, int modifiers, int allowed_ops); private final native void N_DragTargetDragOver(Point pos, int modifiers, int allowed_ops); @@ -812,6 +789,5 @@ private final native void N_DragTargetDragEnter( private final native void N_DragSourceEndedAt(Point pos, int operation); private final native void N_DragSourceSystemDragEnded(); private final native void N_UpdateUI(Rectangle contentRect, Rectangle browserRect); - private final native void N_SetParent(long windowHandle, Component canvas); private final native void N_NotifyMoveOrResizeStarted(); } diff --git a/java/org/cef/browser/CefRenderer.java b/java/org/cef/browser/CefRenderer.java deleted file mode 100644 index 2a295465..00000000 --- a/java/org/cef/browser/CefRenderer.java +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (c) 2013 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 com.jogamp.opengl.GL2; - -import java.awt.Rectangle; -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; - -class CefRenderer { - private boolean transparent_; - private GL2 initialized_context_ = null; - private int[] texture_id_ = new int[1]; - private int view_width_ = 0; - private int view_height_ = 0; - private float spin_x_ = 0f; - private float spin_y_ = 0f; - private Rectangle popup_rect_ = new Rectangle(0, 0, 0, 0); - private Rectangle original_popup_rect_ = new Rectangle(0, 0, 0, 0); - private boolean use_draw_pixels_ = false; - - protected CefRenderer(boolean transparent) { - transparent_ = transparent; - } - - protected boolean isTransparent() { - return transparent_; - } - - protected int getTextureID() { - return texture_id_[0]; - } - - @SuppressWarnings("static-access") - protected void initialize(GL2 gl2) { - if (initialized_context_ == gl2) return; - - initialized_context_ = gl2; - - if (!gl2.getContext().isHardwareRasterizer()) { - // Workaround for Windows Remote Desktop which requires pot textures. - System.out.println( - "opengl rendering may be slow as hardware rendering isn't available"); - use_draw_pixels_ = true; - return; - } - - gl2.glHint(gl2.GL_POLYGON_SMOOTH_HINT, gl2.GL_NICEST); - - gl2.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - // Necessary for non-power-of-2 textures to render correctly. - gl2.glPixelStorei(gl2.GL_UNPACK_ALIGNMENT, 1); - - // Create the texture. - gl2.glGenTextures(1, texture_id_, 0); - assert (texture_id_[0] != 0); - - gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); - gl2.glTexParameteri(gl2.GL_TEXTURE_2D, gl2.GL_TEXTURE_MIN_FILTER, gl2.GL_NEAREST); - gl2.glTexParameteri(gl2.GL_TEXTURE_2D, gl2.GL_TEXTURE_MAG_FILTER, gl2.GL_NEAREST); - gl2.glTexEnvf(gl2.GL_TEXTURE_ENV, gl2.GL_TEXTURE_ENV_MODE, gl2.GL_MODULATE); - } - - protected void cleanup(GL2 gl2) { - if (texture_id_[0] != 0) gl2.glDeleteTextures(1, texture_id_, 0); - view_width_ = view_height_ = 0; - } - - @SuppressWarnings("static-access") - protected void render(GL2 gl2) { - if (use_draw_pixels_ || view_width_ == 0 || view_height_ == 0) return; - - assert (initialized_context_ != null); - - final float[] vertex_data = {// tu, tv, x, y, z - 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f}; - FloatBuffer vertices = FloatBuffer.wrap(vertex_data); - - gl2.glClear(gl2.GL_COLOR_BUFFER_BIT | gl2.GL_DEPTH_BUFFER_BIT); - - gl2.glMatrixMode(gl2.GL_MODELVIEW); - gl2.glLoadIdentity(); - - // Match GL units to screen coordinates. - gl2.glViewport(0, 0, view_width_, view_height_); - gl2.glMatrixMode(gl2.GL_PROJECTION); - gl2.glLoadIdentity(); - - // Draw the background gradient. - gl2.glPushAttrib(gl2.GL_ALL_ATTRIB_BITS); - gl2.glBegin(gl2.GL_QUADS); - gl2.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // red - gl2.glVertex2f(-1.0f, -1.0f); - gl2.glVertex2f(1.0f, -1.0f); - gl2.glColor4f(0.0f, 0.0f, 1.0f, 1.0f); // blue - gl2.glVertex2f(1.0f, 1.0f); - gl2.glVertex2f(-1.0f, 1.0f); - gl2.glEnd(); - gl2.glPopAttrib(); - - // Rotate the view based on the mouse spin. - if (spin_x_ != 0) gl2.glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f); - if (spin_y_ != 0) gl2.glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f); - - if (transparent_) { - // Alpha blending style. Texture values have premultiplied alpha. - gl2.glBlendFunc(gl2.GL_ONE, gl2.GL_ONE_MINUS_SRC_ALPHA); - - // Enable alpha blending. - gl2.glEnable(gl2.GL_BLEND); - } - - // Enable 2D textures. - gl2.glEnable(gl2.GL_TEXTURE_2D); - - // Draw the facets with the texture. - assert (texture_id_[0] != 0); - gl2.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); - gl2.glInterleavedArrays(gl2.GL_T2F_V3F, 0, vertices); - gl2.glDrawArrays(gl2.GL_QUADS, 0, 4); - - // Disable 2D textures. - gl2.glDisable(gl2.GL_TEXTURE_2D); - - if (transparent_) { - // Disable alpha blending. - gl2.glDisable(gl2.GL_BLEND); - } - } - - protected void onPopupSize(Rectangle rect) { - if (rect.width <= 0 || rect.height <= 0) return; - original_popup_rect_ = rect; - popup_rect_ = getPopupRectInWebView(original_popup_rect_); - } - - protected Rectangle getPopupRect() { - return (Rectangle) popup_rect_.clone(); - } - - protected Rectangle getPopupRectInWebView(Rectangle original_rect) { - Rectangle rc = original_rect; - // if x or y are negative, move them to 0. - if (rc.x < 0) rc.x = 0; - if (rc.y < 0) rc.y = 0; - // if popup goes outside the view, try to reposition origin - if (rc.x + rc.width > view_width_) rc.x = view_width_ - rc.width; - if (rc.y + rc.height > view_height_) rc.y = view_height_ - rc.height; - // if x or y became negative, move them to 0 again. - if (rc.x < 0) rc.x = 0; - if (rc.y < 0) rc.y = 0; - return rc; - } - - protected void clearPopupRects() { - popup_rect_.setBounds(0, 0, 0, 0); - original_popup_rect_.setBounds(0, 0, 0, 0); - } - - @SuppressWarnings("static-access") - protected void onPaint(GL2 gl2, boolean popup, Rectangle[] dirtyRects, ByteBuffer buffer, - int width, int height) { - initialize(gl2); - - if (use_draw_pixels_) { - gl2.glRasterPos2f(-1, 1); - gl2.glPixelZoom(1, -1); - gl2.glDrawPixels(width, height, GL2.GL_BGRA, GL2.GL_UNSIGNED_BYTE, buffer); - return; - } - - if (transparent_) { - // Enable alpha blending. - gl2.glEnable(gl2.GL_BLEND); - } - - // Enable 2D textures. - gl2.glEnable(gl2.GL_TEXTURE_2D); - - assert (texture_id_[0] != 0); - gl2.glBindTexture(gl2.GL_TEXTURE_2D, texture_id_[0]); - - if (!popup) { - int old_width = view_width_; - int old_height = view_height_; - - view_width_ = width; - view_height_ = height; - - gl2.glPixelStorei(gl2.GL_UNPACK_ROW_LENGTH, view_width_); - - if (old_width != view_width_ || old_height != view_height_) { - // Update/resize the whole texture. - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, 0); - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, 0); - gl2.glTexImage2D(gl2.GL_TEXTURE_2D, 0, gl2.GL_RGBA, view_width_, view_height_, 0, - gl2.GL_BGRA, gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); - } else { - // Update just the dirty rectangles. - for (int i = 0; i < dirtyRects.length; ++i) { - Rectangle rect = dirtyRects[i]; - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, rect.x); - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, rect.y); - gl2.glTexSubImage2D(gl2.GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, - rect.height, gl2.GL_BGRA, gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); - } - } - } else if (popup && popup_rect_.width > 0 && popup_rect_.height > 0) { - int skip_pixels = 0, x = popup_rect_.x; - int skip_rows = 0, y = popup_rect_.y; - int w = width; - int h = height; - - // Adjust the popup to fit inside the view. - if (x < 0) { - skip_pixels = -x; - x = 0; - } - if (y < 0) { - skip_rows = -y; - y = 0; - } - if (x + w > view_width_) w -= x + w - view_width_; - if (y + h > view_height_) h -= y + h - view_height_; - - // Update the popup rectangle. - gl2.glPixelStorei(gl2.GL_UNPACK_ROW_LENGTH, width); - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_PIXELS, skip_pixels); - gl2.glPixelStorei(gl2.GL_UNPACK_SKIP_ROWS, skip_rows); - gl2.glTexSubImage2D(gl2.GL_TEXTURE_2D, 0, x, y, w, h, gl2.GL_BGRA, - gl2.GL_UNSIGNED_INT_8_8_8_8_REV, buffer); - } - - // Disable 2D textures. - gl2.glDisable(gl2.GL_TEXTURE_2D); - - if (transparent_) { - // Disable alpha blending. - gl2.glDisable(gl2.GL_BLEND); - } - } - - protected void setSpin(float spinX, float spinY) { - spin_x_ = spinX; - spin_y_ = spinY; - } - - protected void incrementSpin(float spinDX, float spinDY) { - spin_x_ -= spinDX; - spin_y_ -= spinDY; - } -} diff --git a/java/org/cef/browser/mac/CefBrowserWindowMac.java b/java/org/cef/browser/mac/CefBrowserWindowMac.java index 3239edce..15cccff9 100644 --- a/java/org/cef/browser/mac/CefBrowserWindowMac.java +++ b/java/org/cef/browser/mac/CefBrowserWindowMac.java @@ -6,40 +6,11 @@ import org.cef.browser.CefBrowserWindow; -import java.awt.Component; -import java.awt.peer.ComponentPeer; - -import sun.awt.AWTAccessor; -import sun.lwawt.LWComponentPeer; -import sun.lwawt.PlatformWindow; -import sun.lwawt.macosx.CFRetainedResource; -import sun.lwawt.macosx.CPlatformWindow; +import java.awt.*; public class CefBrowserWindowMac implements CefBrowserWindow { @Override public long getWindowHandle(Component comp) { - final long[] result = new long[1]; - while (comp != null) { - if (comp.isLightweight()) { - comp = comp.getParent(); - continue; - } - ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(comp); - if (peer instanceof LWComponentPeer) { - @SuppressWarnings("rawtypes") - PlatformWindow pWindow = ((LWComponentPeer) peer).getPlatformWindow(); - if (pWindow instanceof CPlatformWindow) { - ((CPlatformWindow) pWindow).execute(new CFRetainedResource.CFNativeAction() { - @Override - public void run(long l) { - result[0] = l; - } - }); - break; - } - } - comp = comp.getParent(); - } - return result[0]; + return 0; } } diff --git a/java/org/cef/event/CefKeyEvent.java b/java/org/cef/event/CefKeyEvent.java new file mode 100644 index 00000000..eda2a84c --- /dev/null +++ b/java/org/cef/event/CefKeyEvent.java @@ -0,0 +1,40 @@ +package org.cef.event; + +public class CefKeyEvent { + /* id constants */ + public static final int KEY_PRESS = 1; + public static final int KEY_RELEASE = 0; + public static final int KEY_TYPE = 2; + + // intentionally leaving these public for now + // may remove the getters, or maybe add setters, or maybe move to private + // not sure yet + public int keyCode; + public int id; + public int modifiers; + public char keyChar; + public long scancode; + + public CefKeyEvent(int id, int keyCode, char keyChar, int modifiers) { + this.id = id; + this.keyCode = keyCode; + this.keyChar = keyChar; + this.modifiers = modifiers; + } + + public int getID() { + return id; + } + + public int getModifiers() { + return modifiers; + } + + public char getKeyChar() { + return keyChar; + } + + public int getKeyCode() { + return keyCode; + } +} diff --git a/java/org/cef/event/CefMouseEvent.java b/java/org/cef/event/CefMouseEvent.java new file mode 100644 index 00000000..23840478 --- /dev/null +++ b/java/org/cef/event/CefMouseEvent.java @@ -0,0 +1,54 @@ +package org.cef.event; + +public class CefMouseEvent { + /* id constants */ + public static final int MOUSE_MOVED = 503; + public static final int MOUSE_EXIT = 505; + /* modifier constants */ + public static final int BUTTON1_MASK = 0x10; + public static final int BUTTON2_MASK = 0x20; + public static final int BUTTON3_MASK = 0x40; + + // intentionally leaving these public for now + // may remove the getters, or maybe add setters, or maybe move to private + // not sure yet + public int id; + public int x; + public int y; + public int modifiers; + public int clickCount; + public int button; + + public CefMouseEvent(int id, int x, int y, int clickCount, int button, int modifiers) { + this.id = id; + this.x = x; + this.y = y; + this.clickCount = clickCount; + this.button = button; + this.modifiers = modifiers; + } + + public int getID() { + return id; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getModifiers() { + return modifiers; + } + + public int getClickCount() { + return clickCount; + } + + public int getButton() { + return button; + } +} diff --git a/java/org/cef/event/CefMouseWheelEvent.java b/java/org/cef/event/CefMouseWheelEvent.java new file mode 100644 index 00000000..bf9769c4 --- /dev/null +++ b/java/org/cef/event/CefMouseWheelEvent.java @@ -0,0 +1,49 @@ +package org.cef.event; + +public class CefMouseWheelEvent { + /* id constants */ + public static final int WHEEL_UNIT_SCROLL = 0; + public static final int WHEEL_BLOCK_SCROLL = 1; + + // intentionally leaving these public for now + // may remove the getters, or maybe add setters, or maybe move to private + // not sure yet + public int id; + public double delta; + public int x; + public int y; + public int modifiers; + public int amount = 32; // TODO: might want to make this change dependent on system? + + public CefMouseWheelEvent(int id, int x, int y, double delta, int modifiers) { + this.id = id; + this.x = x; + this.y = y; + this.delta = delta; + this.modifiers = modifiers; + } + + public int getScrollType() { + return id; + } + + public double getWheelRotation() { + return delta; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getModifiers() { + return modifiers; + } + + public double getUnitsToScroll() { + return amount * delta; + } +} diff --git a/java/org/cef/handler/CefAudioHandler.java b/java/org/cef/handler/CefAudioHandler.java new file mode 100644 index 00000000..5c2fcdd0 --- /dev/null +++ b/java/org/cef/handler/CefAudioHandler.java @@ -0,0 +1,25 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.misc.CefAudioParameters; +import org.cef.misc.DataPointer; + +/** + * Implement this interface to handle events related to audio playing. + * The methods of this class will be called on the UI thread. + */ +public interface CefAudioHandler { + boolean getAudioParameters(CefBrowser browser, CefAudioParameters params); + + void onAudioStreamStarted(CefBrowser browser, CefAudioParameters params, int channels); + + void onAudioStreamPacket(CefBrowser browser, DataPointer data, int frames, long pts); + + void onAudioStreamStopped(CefBrowser browser); + + void onAudioStreamError(CefBrowser browser, String text); +} diff --git a/java/org/cef/handler/CefAudioHandlerAdapter.java b/java/org/cef/handler/CefAudioHandlerAdapter.java new file mode 100644 index 00000000..14188ba7 --- /dev/null +++ b/java/org/cef/handler/CefAudioHandlerAdapter.java @@ -0,0 +1,31 @@ +// 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 org.cef.handler; + +import org.cef.browser.CefBrowser; +import org.cef.misc.CefAudioParameters; +import org.cef.misc.DataPointer; + +/** + * Implement this interface to handle events related to audio playing. + * The methods of this class will be called on the UI thread. + */ +public abstract class CefAudioHandlerAdapter implements CefAudioHandler { + public boolean getAudioParameters(CefBrowser browser, CefAudioParameters params) { + return false; + } + + public void onAudioStreamStarted(CefBrowser browser, CefAudioParameters params, int channels) { + } + + public void onAudioStreamPacket(CefBrowser browser, DataPointer data, int frames, long pts) { + } + + public void onAudioStreamStopped(CefBrowser browser) { + } + + public void onAudioStreamError(CefBrowser browser, String text) { + } +} diff --git a/java/org/cef/handler/CefClientHandler.java b/java/org/cef/handler/CefClientHandler.java index 6a263a8e..d819e6cf 100644 --- a/java/org/cef/handler/CefClientHandler.java +++ b/java/org/cef/handler/CefClientHandler.java @@ -80,13 +80,20 @@ protected void dispose() { * default implementation will be used. */ abstract protected CefDialogHandler getDialogHandler(); - + /** * Return the handler for browser display state events. * This method is a callback method and is called by * the native code. */ abstract protected CefDisplayHandler getDisplayHandler(); + + /** + * Return the handler for browser audio events. + * This method is a callback method and is called by + * the native code. + */ + abstract protected CefAudioHandler getAudioHandler(); /** * Return the handler for download events. @@ -198,8 +205,16 @@ protected void removeDisplayHandler(CefDisplayHandler h) { err.printStackTrace(); } } + + protected void removeAudioHandler(CefAudioHandler h) { + try { + N_removeAudioHandler(h); + } catch (UnsatisfiedLinkError err) { + err.printStackTrace(); + } + } - protected void removeDownloadHandler(CefDisplayHandler h) { + protected void removeDownloadHandler(CefDownloadHandler h) { try { N_removeDownloadHandler(h); } catch (UnsatisfiedLinkError err) { @@ -301,7 +316,8 @@ protected void removeWindowHandler(CefWindowHandler h) { private final native void N_removeContextMenuHandler(CefContextMenuHandler h); private final native void N_removeDialogHandler(CefDialogHandler h); private final native void N_removeDisplayHandler(CefDisplayHandler h); - private final native void N_removeDownloadHandler(CefDisplayHandler h); + private final native void N_removeAudioHandler(CefAudioHandler h); + private final native void N_removeDownloadHandler(CefDownloadHandler h); private final native void N_removeDragHandler(CefDragHandler h); private final native void N_removeFocusHandler(CefFocusHandler h); private final native void N_removeJSDialogHandler(CefJSDialogHandler h); diff --git a/java/org/cef/handler/CefResourceHandlerAdapter.java b/java/org/cef/handler/CefResourceHandlerAdapter.java index 9458bb2b..9c349f6e 100644 --- a/java/org/cef/handler/CefResourceHandlerAdapter.java +++ b/java/org/cef/handler/CefResourceHandlerAdapter.java @@ -7,7 +7,6 @@ import org.cef.callback.CefCallback; import org.cef.misc.IntRef; import org.cef.misc.StringRef; -import org.cef.network.CefCookie; import org.cef.network.CefRequest; import org.cef.network.CefResponse; diff --git a/java/org/cef/misc/CefAudioParameters.java b/java/org/cef/misc/CefAudioParameters.java new file mode 100644 index 00000000..87b65776 --- /dev/null +++ b/java/org/cef/misc/CefAudioParameters.java @@ -0,0 +1,13 @@ +package org.cef.misc; + +public class CefAudioParameters { + public final CefChannelLayout channelLayout; + public final int sampleRate; + public final int framesPerBuffer; + + public CefAudioParameters(CefChannelLayout channelLayout, int sampleRate, int framesPerBuffer) { + this.channelLayout = channelLayout; + this.sampleRate = sampleRate; + this.framesPerBuffer = framesPerBuffer; + } +} diff --git a/java/org/cef/misc/CefChannelLayout.java b/java/org/cef/misc/CefChannelLayout.java new file mode 100644 index 00000000..9d45c798 --- /dev/null +++ b/java/org/cef/misc/CefChannelLayout.java @@ -0,0 +1,129 @@ +package org.cef.misc; + +// https://cef-builds.spotifycdn.com/docs/109.1/cef__types_8h.html#adb8605711e30e1aec6031029c94e7904 +public enum CefChannelLayout { + CEF_CHANNEL_LAYOUT_NONE(0), + + CEF_CHANNEL_LAYOUT_UNSUPPORTED(1), + + /// Front C + CEF_CHANNEL_LAYOUT_MONO(2), + + /// Front L, Front R + CEF_CHANNEL_LAYOUT_STEREO(3), + + /// Front L, Front R, Back C + CEF_CHANNEL_LAYOUT_2_1(4), + + /// Front L, Front R, Front C + CEF_CHANNEL_LAYOUT_SURROUND(5), + + /// Front L, Front R, Front C, Back C + CEF_CHANNEL_LAYOUT_4_0(6), + + /// Front L, Front R, Side L, Side R + CEF_CHANNEL_LAYOUT_2_2(7), + + /// Front L, Front R, Back L, Back R + CEF_CHANNEL_LAYOUT_QUAD(8), + + /// Front L, Front R, Front C, Side L, Side R + CEF_CHANNEL_LAYOUT_5_0(9), + + /// Front L, Front R, Front C, LFE, Side L, Side R + CEF_CHANNEL_LAYOUT_5_1(10), + + /// Front L, Front R, Front C, Back L, Back R + CEF_CHANNEL_LAYOUT_5_0_BACK(11), + + /// Front L, Front R, Front C, LFE, Back L, Back R + CEF_CHANNEL_LAYOUT_5_1_BACK(12), + + /// Front L, Front R, Front C, Side L, Side R, Back L, Back R + CEF_CHANNEL_LAYOUT_7_0(13), + + /// Front L, Front R, Front C, LFE, Side L, Side R, Back L, Back R + CEF_CHANNEL_LAYOUT_7_1(14), + + /// Front L, Front R, Front C, LFE, Side L, Side R, Front LofC, Front RofC + CEF_CHANNEL_LAYOUT_7_1_WIDE(15), + + /// Stereo L, Stereo R + CEF_CHANNEL_LAYOUT_STEREO_DOWNMIX(16), + + /// Stereo L, Stereo R, LFE + CEF_CHANNEL_LAYOUT_2POINT1(17), + + /// Stereo L, Stereo R, Front C, LFE + CEF_CHANNEL_LAYOUT_3_1(18), + + /// Stereo L, Stereo R, Front C, Rear C, LFE + CEF_CHANNEL_LAYOUT_4_1(19), + + /// Stereo L, Stereo R, Front C, Side L, Side R, Back C + CEF_CHANNEL_LAYOUT_6_0(20), + + /// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC + CEF_CHANNEL_LAYOUT_6_0_FRONT(21), + + /// Stereo L, Stereo R, Front C, Rear L, Rear R, Rear C + CEF_CHANNEL_LAYOUT_HEXAGONAL(22), + + /// Stereo L, Stereo R, Front C, LFE, Side L, Side R, Rear Center + CEF_CHANNEL_LAYOUT_6_1(23), + + /// Stereo L, Stereo R, Front C, LFE, Back L, Back R, Rear Center + CEF_CHANNEL_LAYOUT_6_1_BACK(24), + + /// Stereo L, Stereo R, Side L, Side R, Front LofC, Front RofC, LFE + CEF_CHANNEL_LAYOUT_6_1_FRONT(25), + + /// Front L, Front R, Front C, Side L, Side R, Front LofC, Front RofC + CEF_CHANNEL_LAYOUT_7_0_FRONT(26), + + /// Front L, Front R, Front C, LFE, Back L, Back R, Front LofC, Front RofC + CEF_CHANNEL_LAYOUT_7_1_WIDE_BACK(27), + + /// Front L, Front R, Front C, Side L, Side R, Rear L, Back R, Back C. + CEF_CHANNEL_LAYOUT_OCTAGONAL(28), + + /// Channels are not explicitly mapped to speakers. + CEF_CHANNEL_LAYOUT_DISCRETE(29), + + /// Front L, Front R, Front C. Front C contains the keyboard mic audio. This + /// layout is only intended for input for WebRTC. The Front C channel + /// is stripped away in the WebRTC audio input pipeline and never seen outside + /// of that. + CEF_CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC(30), + + /// Front L, Front R, Side L, Side R, LFE + CEF_CHANNEL_LAYOUT_4_1_QUAD_SIDE(31), + + /// Actual channel layout is specified in the bitstream and the actual channel + /// count is unknown at Chromium media pipeline level (useful for audio + /// pass-through mode). + CEF_CHANNEL_LAYOUT_BITSTREAM(32), + + /// Front L, Front R, Front C, LFE, Side L, Side R, + /// Front Height L, Front Height R, Rear Height L, Rear Height R + /// Will be represented as six channels (5.1) due to eight channel limit + /// kMaxConcurrentChannels + CEF_CHANNEL_LAYOUT_5_1_4_DOWNMIX(33), + + /// Max value, must always equal the largest entry ever logged. + CEF_CHANNEL_LAYOUT_MAX(33); + + private final int id; + + CefChannelLayout(int id) { + this.id = id; + } + + // micro optimization: values() creates a new array every time it's called + // having this static final array allows me to not have to create that array more than once + private static final CefChannelLayout[] LAYOUTS = CefChannelLayout.values(); + + public static CefChannelLayout forId(int id) { + return LAYOUTS[id]; + } +} diff --git a/java/org/cef/misc/CefCursorType.java b/java/org/cef/misc/CefCursorType.java new file mode 100644 index 00000000..a014cc91 --- /dev/null +++ b/java/org/cef/misc/CefCursorType.java @@ -0,0 +1,59 @@ +package org.cef.misc; + +public enum CefCursorType { + POINTER(0), + CROSS(0x36003), // GLFW_CROSSHAIR_CURSOR + HAND(0x36004), // GLFW_HAND_CURSOR + IBEAM(0x36002), // GLFW_IBEAM_CURSOR + WAIT(0), + HELP(0), + EAST_RESIZE(0x36005), // GLFW_RESIZE_EW_CURSOR + NORTH_RESIZE(0x36006), // GLFW_RESIZE_NS_CURSOR + NORTH_EAST_RESIZE(0x36008), // GLFW_RESIZE_NESW_CURSOR + NORTH_WEST_RESIZE(0x36007), // GLFW_RESIZE_NWSE_CURSOR + SOUTH_RESIZE(0x36006), // GLFW_RESIZE_NS_CURSOR + SOUTH_EAST_RESIZE(0x36007), // GLFW_RESIZE_NWSE_CURSOR + SOUTH_WEST_RESIZE(0x36008), // GLFW_RESIZE_NESW_CURSOR + WEST_RESIZE(0x36005), // GLFW_RESIZE_EW_CURSOR + NORTH_SOUTH_RESIZE(0x36006), // GLFW_RESIZE_NS_CURSOR + EAST_WEST_RESIZE(0x36005), // GLFW_RESIZE_EW_CURSOR + NORTH_EAST_SOUTH_WEST_RESIZE(0x36008), // GLFW_RESIZE_NESW_CURSOR + NORTH_WEST_SOUTH_EAST_RESIZE(0x36007), // GLFW_RESIZE_NWSE_CURSOR + COLUMN_RESIZE(0), + ROW_RESIZE(0), + MIDDLE_PANNING(0), + EAST_PANNING(0), + NORTH_PANNING(0), + NORTH_EAST_PANNING(0), + NORTH_WEST_PANNING(0), + SOUTH_PANNING(0), + SOUTH_EAST_PANNING(0), + SOUTH_WEST_PANNING(0), + WEST_PANNING(0), + MOVE(0x36009), // GLFW_RESIZE_ALL_CURSOR + VERTICAL_IBEAM(0), // VERTICAL_TEXT + CELL(0), + CONTEXT_MENU(0), + ALIAS(0), + PROGRESS(0), + NO_DROP(0x3600A), // GLFW_NOT_ALLOWED_CURSOR + COPY(0), + NONE(0), + NOT_ALLOWED(0x3600A), // GLFW_NOT_ALLOWED_CURSOR + ZOOM_IN(0), + ZOOM_OUT(0), + GRAB(0), + GRABBING(0), + CUSTOM(0), + ; + + public final int glfwId; + + CefCursorType(int glfwId) { + this.glfwId = glfwId; + } + + public static CefCursorType fromId(int id) { + return values()[id]; + } +} diff --git a/java/org/cef/misc/DataPointer.java b/java/org/cef/misc/DataPointer.java new file mode 100644 index 00000000..19134fc6 --- /dev/null +++ b/java/org/cef/misc/DataPointer.java @@ -0,0 +1,85 @@ +package org.cef.misc; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.nio.ByteBuffer; + +public class DataPointer { + private final long address; + private ByteBuffer dataBuffer; + boolean initialized = false; + int alignment = 3; + + public DataPointer(long address) { + this.address = address; + } + + public DataPointer forCapacity(int capacity) { + try { + dataBuffer = (ByteBuffer) memByteBuffer.invoke(address, capacity); + initialized = true; + return this; + } catch (Throwable err) { + throw new RuntimeException("Failed to invoke memByteBuffer?", err); + } + } + + public DataPointer withAlignment(int alignment) { + this.alignment = alignment; + return this; + } + + public long getAddress() { + return address; + } + + public DataPointer getData(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return new DataPointer(dataBuffer.getLong(offset << alignment)); + } + + public long getLong(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.getLong(offset << alignment); + } + + public int getInt(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.getInt(offset << alignment); + } + + public short getShort(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.getShort(offset << alignment); + } + + public byte getByte(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.get(offset << alignment); + } + + public double getDouble(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.getDouble(offset << alignment); + } + + public float getFloat(int offset) { + if (!initialized) throw new RuntimeException("DataPoint#forCapacity must be called before the data can be accessed."); + return dataBuffer.getFloat(offset << alignment); + } + + // TODO: ideally we'd just directly depend on lwjgl, since we require it for GLFW anyway + private static final MethodHandle memByteBuffer; + + static { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + Class clz = Class.forName("org.lwjgl.system.MemoryUtil", false, lookup.lookupClass().getClassLoader()); + memByteBuffer = lookup.findStatic(clz, "memByteBuffer", MethodType.methodType(ByteBuffer.class, new Class[]{Long.TYPE, Integer.TYPE})); + } catch (Throwable err) { + System.err.println("Could not find LWJGL MemoryUtil's memByteBuffer method.\nAre you using LWJGL 3.x?"); + throw new RuntimeException(err); + } + } +} diff --git a/java/tests/detailed/BrowserFrame.java b/java/tests/detailed/BrowserFrame.java index dedcd1f8..25beacf3 100644 --- a/java/tests/detailed/BrowserFrame.java +++ b/java/tests/detailed/BrowserFrame.java @@ -125,10 +125,8 @@ public void onBeforeClose(CefBrowser browser) { public void removeBrowser(Runnable r) { System.out.println("BrowserFrame.removeBrowser"); afterParentChangedAction_ = r; - remove(browser_.getUIComponent()); // The removeNotify() notification should be sent as a result of calling remove(). // However, it isn't in all cases so we do it manually here. - browser_.getUIComponent().removeNotify(); browser_ = null; } diff --git a/java/tests/detailed/MainFrame.java b/java/tests/detailed/MainFrame.java index f13b321d..5b1efeb5 100644 --- a/java/tests/detailed/MainFrame.java +++ b/java/tests/detailed/MainFrame.java @@ -202,7 +202,7 @@ public void onLoadError(CefBrowser browser, CefFrame frame, ErrorCode errorCode, // Create the browser. CefBrowser browser = client_.createBrowser( - "http://www.google.com", osrEnabled, transparentPaintingEnabled, null); + "http://www.google.com", osrEnabled, null); setBrowser(browser); // Set up the UI for this example implementation. @@ -239,7 +239,6 @@ public void onTakeFocus(CefBrowser browser, boolean next) { if (createImmediately) browser.createImmediately(); // Add the browser to the UI. - contentPanel.add(getBrowser().getUIComponent(), BorderLayout.CENTER); MenuBar menuBar = new MenuBar( this, browser, control_pane_, downloadDialog, CefCookieManager.getGlobalManager()); diff --git a/java/tests/detailed/dialog/DevToolsDialog.java b/java/tests/detailed/dialog/DevToolsDialog.java index d1fb3d8d..74a3a766 100644 --- a/java/tests/detailed/dialog/DevToolsDialog.java +++ b/java/tests/detailed/dialog/DevToolsDialog.java @@ -29,7 +29,6 @@ public DevToolsDialog(Frame owner, String title, CefBrowser browser, Point inspe setLocation(owner.getLocation().x + 20, owner.getLocation().y + 20); devTools_ = browser.getDevTools(inspectAt); - add(devTools_.getUIComponent()); addComponentListener(new ComponentAdapter() { @Override diff --git a/java/tests/detailed/ui/MenuBar.java b/java/tests/detailed/ui/MenuBar.java index c69ae215..a6fe40bc 100644 --- a/java/tests/detailed/ui/MenuBar.java +++ b/java/tests/detailed/ui/MenuBar.java @@ -408,7 +408,6 @@ public void actionPerformed(ActionEvent e) { if (reparentButton.getText().equals("Reparent <")) { owner_.removeBrowser(new Runnable() { public void run() { - newFrame.add(browser_.getUIComponent(), BorderLayout.CENTER); newFrame.setBrowser(browser_); reparentButton.setText("Reparent >"); reparentPending_ = false; @@ -420,7 +419,6 @@ public void run() { JRootPane rootPane = (JRootPane) owner_.getComponent(0); Container container = rootPane.getContentPane(); JPanel panel = (JPanel) container.getComponent(0); - panel.add(browser_.getUIComponent()); owner_.setBrowser(browser_); owner_.revalidate(); reparentButton.setText("Reparent <"); diff --git a/java/tests/junittests/TestFrame.java b/java/tests/junittests/TestFrame.java index b789544c..bdbc26a9 100644 --- a/java/tests/junittests/TestFrame.java +++ b/java/tests/junittests/TestFrame.java @@ -105,10 +105,9 @@ public void windowClosing(WindowEvent e) { protected void createBrowser(String startURL) { assertNull(browser_); - browser_ = client_.createBrowser(startURL, false /* useOSR */, false /* isTransparent */); + browser_ = client_.createBrowser(startURL, false /* isTransparent */); assertNotNull(browser_); - getContentPane().add(browser_.getUIComponent(), BorderLayout.CENTER); pack(); setSize(800, 600); setVisible(true); diff --git a/java/tests/simple/MainFrame.java b/java/tests/simple/MainFrame.java index 7b2b21ab..822c4c8f 100644 --- a/java/tests/simple/MainFrame.java +++ b/java/tests/simple/MainFrame.java @@ -46,7 +46,6 @@ public class MainFrame extends JFrame { private final CefApp cefApp_; private final CefClient client_; private final CefBrowser browser_; - private final Component browerUI_; private boolean browserFocus_ = true; /** @@ -104,8 +103,7 @@ public void stateHasChanged(org.cef.CefApp.CefAppState state) { // by calling the method "getUIComponent()" on the instance of CefBrowser. // The UI component is inherited from a java.awt.Component and therefore // it can be embedded into any AWT UI. - browser_ = client_.createBrowser(startURL, useOSR, isTransparent); - browerUI_ = browser_.getUIComponent(); + browser_ = client_.createBrowser(startURL, isTransparent); // (4) For this minimal browser, we need only a text field to enter an URL // we want to navigate to and a CefBrowser window to display the content @@ -160,7 +158,6 @@ public void onTakeFocus(CefBrowser browser, boolean next) { // (5) All UI components are assigned to the default content pane of this // JFrame and afterwards the frame is made visible to the user. getContentPane().add(address_, BorderLayout.NORTH); - getContentPane().add(browerUI_, BorderLayout.CENTER); pack(); setSize(800, 600); setVisible(true); diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 7662405f..0368b692 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -87,6 +87,8 @@ set(JCEF_SRCS dialog_handler.h display_handler.cpp display_handler.h + audio_handler.cpp + audio_handler.h download_handler.cpp download_handler.h drag_handler.cpp diff --git a/native/CefBrowser_N.cpp b/native/CefBrowser_N.cpp index c3c08813..af6543b7 100644 --- a/native/CefBrowser_N.cpp +++ b/native/CefBrowser_N.cpp @@ -40,34 +40,104 @@ namespace { -int GetCefModifiers(JNIEnv* env, jclass cls, int modifiers) { - JNI_STATIC_DEFINE_INT_RV(env, cls, ALT_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON1_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON2_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, BUTTON3_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, CTRL_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, META_DOWN_MASK, 0); - JNI_STATIC_DEFINE_INT_RV(env, cls, SHIFT_DOWN_MASK, 0); +int GetCefModifiersGlfw(JNIEnv* env, jclass cls, int modifiers) { + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_MOD_ALT, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_MOD_CONTROL, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_MOD_SUPER, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_MOD_SHIFT, 0); int cef_modifiers = 0; - if (modifiers & JNI_STATIC(ALT_DOWN_MASK)) + if (modifiers & JNI_STATIC(GLFW_MOD_ALT)) cef_modifiers |= EVENTFLAG_ALT_DOWN; - if (modifiers & JNI_STATIC(BUTTON1_DOWN_MASK)) + if (modifiers & 0x10) // BUTTON1_MASK cef_modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON; - if (modifiers & JNI_STATIC(BUTTON2_DOWN_MASK)) + if (modifiers & 0x20) // BUTTON2_MASK cef_modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON; - if (modifiers & JNI_STATIC(BUTTON3_DOWN_MASK)) + if (modifiers & 0x40) // BUTTON3_MASK cef_modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON; - if (modifiers & JNI_STATIC(CTRL_DOWN_MASK)) + if (modifiers & JNI_STATIC(GLFW_MOD_CONTROL)) cef_modifiers |= EVENTFLAG_CONTROL_DOWN; - if (modifiers & JNI_STATIC(META_DOWN_MASK)) + if (modifiers & JNI_STATIC(GLFW_MOD_SUPER)) cef_modifiers |= EVENTFLAG_COMMAND_DOWN; - if (modifiers & JNI_STATIC(SHIFT_DOWN_MASK)) + if (modifiers & JNI_STATIC(GLFW_MOD_SHIFT)) cef_modifiers |= EVENTFLAG_SHIFT_DOWN; return cef_modifiers; } +#if defined(OS_WIN) +long MapScanCodeGLFW(JNIEnv* env, jclass cls, int key_char, int scanCode) { + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_DELETE, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_LEFT, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_DOWN, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_UP, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_RIGHT, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_PAGE_DOWN, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_PAGE_UP, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_END, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_HOME, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_ENTER, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_KP_ENTER, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_LEFT_CONTROL, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_RIGHT_CONTROL, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_BACKSPACE, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_KP_4, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_KP_8, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_KP_6, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_KP_2, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_PRINT_SCREEN, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_SCROLL_LOCK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_CAPS_LOCK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_NUM_LOCK, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_PAUSE, 0); + JNI_STATIC_DEFINE_INT_RV(env, cls, GLFW_KEY_INSERT, 0); + + if (key_char == JNI_STATIC(GLFW_KEY_BACKSPACE) || + key_char == JNI_STATIC(GLFW_KEY_KP_4) || + key_char == JNI_STATIC(GLFW_KEY_KP_8) || + key_char == JNI_STATIC(GLFW_KEY_KP_6) || + key_char == JNI_STATIC(GLFW_KEY_KP_2) || + key_char == JNI_STATIC(GLFW_KEY_PRINT_SCREEN) || + key_char == JNI_STATIC(GLFW_KEY_SCROLL_LOCK) || + key_char == JNI_STATIC(GLFW_KEY_CAPS_LOCK) || + key_char == JNI_STATIC(GLFW_KEY_NUM_LOCK) || + key_char == JNI_STATIC(GLFW_KEY_PAUSE) || + key_char == JNI_STATIC(GLFW_KEY_INSERT) + ) { + int code_out; + // these jni helpers make no sense to me + CallStaticJNIMethodII_V(env, cls, "glfwGetKeyScancode", &code_out, key_char); + return code_out; + } + + if (key_char == JNI_STATIC(GLFW_KEY_LEFT_CONTROL) || key_char == JNI_STATIC(GLFW_KEY_RIGHT_CONTROL)) + return 29; + if (key_char == JNI_STATIC(GLFW_KEY_DELETE)) + return 83; + if (key_char == JNI_STATIC(GLFW_KEY_LEFT)) + return 75; + if (key_char == JNI_STATIC(GLFW_KEY_DOWN)) + return 80; + if (key_char == JNI_STATIC(GLFW_KEY_UP)) + return 72; + if (key_char == JNI_STATIC(GLFW_KEY_RIGHT)) + return 77; + if (key_char == JNI_STATIC(GLFW_KEY_PAGE_DOWN)) + return 81; + if (key_char == JNI_STATIC(GLFW_KEY_PAGE_UP)) + return 73; + if (key_char == JNI_STATIC(GLFW_KEY_END)) + return 79; + if (key_char == JNI_STATIC(GLFW_KEY_HOME)) + return 71; + if (key_char == '\n' || + key_char == JNI_STATIC(GLFW_KEY_ENTER) || + key_char == JNI_STATIC(GLFW_KEY_KP_ENTER) + ) return 28; + return scanCode; +} +#endif // defined(OS_WIN) + #if defined(OS_LINUX) // From ui/events/keycodes/keyboard_codes_posix.h. @@ -896,7 +966,6 @@ struct JNIObjectsForCreate { ScopedJNIObjectGlobal jparentBrowser; ScopedJNIObjectGlobal jclientHandler; ScopedJNIObjectGlobal url; - ScopedJNIObjectGlobal canvas; ScopedJNIObjectGlobal jcontext; ScopedJNIObjectGlobal jinspectAt; @@ -905,7 +974,6 @@ struct JNIObjectsForCreate { jobject _jparentBrowser, jobject _jclientHandler, jstring _url, - jobject _canvas, jobject _jcontext, jobject _jinspectAt) : @@ -914,7 +982,6 @@ struct JNIObjectsForCreate { jparentBrowser(env, _jparentBrowser), jclientHandler(env, _jclientHandler), url(env, _url), - canvas(env, _canvas), jcontext(env, _jcontext), jinspectAt(env, _jinspectAt) {} }; @@ -935,42 +1002,7 @@ void create(std::shared_ptr objs, return; CefWindowInfo windowInfo; - if (osr == JNI_FALSE) { - CefRect rect; - CefRefPtr windowHandler = - (WindowHandler*)clientHandler->GetWindowHandler().get(); - if (windowHandler.get()) { - windowHandler->GetRect(objs->jbrowser, rect); - } -#if defined(OS_WIN) - CefWindowHandle parent = TempWindow::GetWindowHandle(); - if (objs->canvas != nullptr) { - parent = GetHwndOfCanvas(objs->canvas, env); - } else { - // Do not activate hidden browser windows on creation. - windowInfo.ex_style |= WS_EX_NOACTIVATE; - } - windowInfo.SetAsChild(parent, rect); -#elif defined(OS_MACOSX) - NSWindow* parent = nullptr; - if (windowHandle != 0) { - parent = (NSWindow*)windowHandle; - } else { - parent = TempWindow::GetWindow(); - } - CefWindowHandle browserContentView = - util_mac::CreateBrowserContentView(parent, rect); - windowInfo.SetAsChild(browserContentView, rect); -#elif defined(OS_LINUX) - CefWindowHandle parent = TempWindow::GetWindowHandle(); - if (objs->canvas != nullptr) { - parent = GetDrawableOfCanvas(objs->canvas, env); - } - windowInfo.SetAsChild(parent, rect); -#endif - } else { - windowInfo.SetAsWindowless((CefWindowHandle)windowHandle); - } + windowInfo.SetAsWindowless((CefWindowHandle)windowHandle); CefBrowserSettings settings; @@ -1035,23 +1067,25 @@ void getZoomLevel(CefRefPtr host, } } -void OnAfterParentChanged(CefRefPtr browser) { - if (!CefCurrentlyOn(TID_UI)) { - CefPostTask(TID_UI, base::BindOnce(&OnAfterParentChanged, browser)); - return; - } - - if (browser->GetHost()->GetClient()) { - CefRefPtr lifeSpanHandler = - (LifeSpanHandler*)browser->GetHost() - ->GetClient() - ->GetLifeSpanHandler() - .get(); - if (lifeSpanHandler) { - lifeSpanHandler->OnAfterParentChanged(browser); - } - } -} +// Removed because we don't care about when the native parent window changes. +// This fixes a compile issue on macOS - ds58 +//void OnAfterParentChanged(CefRefPtr browser) { +// if (!CefCurrentlyOn(TID_UI)) { +// CefPostTask(TID_UI, base::BindOnce(&OnAfterParentChanged, browser)); +// return; +// } +// +// if (browser->GetHost()->GetClient()) { +// CefRefPtr lifeSpanHandler = +// (LifeSpanHandler*)browser->GetHost() +// ->GetClient() +// ->GetLifeSpanHandler() +// .get(); +// if (lifeSpanHandler) { +// lifeSpanHandler->OnAfterParentChanged(browser); +// } +// } +//} jobject NewJNILongVector(JNIEnv* env, const std::vector& vals) { ScopedJNIObjectLocal jvector(env, "java/util/Vector"); @@ -1148,10 +1182,9 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv* env, jstring url, jboolean osr, jboolean transparent, - jobject canvas, jobject jcontext) { std::shared_ptr objs(new JNIObjectsForCreate( - env, jbrowser, nullptr, jclientHandler, url, canvas, jcontext, nullptr)); + env, jbrowser, nullptr, jclientHandler, url, jcontext, nullptr)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1169,11 +1202,10 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv* env, jlong windowHandle, jboolean osr, jboolean transparent, - jobject canvas, jobject inspect) { std::shared_ptr objs( new JNIObjectsForCreate(env, jbrowser, jparent, jclientHandler, nullptr, - canvas, nullptr, inspect)); + nullptr, inspect)); if (CefCurrentlyOn(TID_UI)) { create(objs, windowHandle, osr, transparent); } else { @@ -1600,66 +1632,67 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env, jobject obj, jobject key_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); - ScopedJNIClass cls(env, env->GetObjectClass(key_event)); - if (!cls) + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); + ScopedJNIClass objClass = ScopedJNIClass(env, env->GetObjectClass(key_event)); + if (!cls || !objClass) return; - JNI_STATIC_DEFINE_INT(env, cls, KEY_PRESSED); - JNI_STATIC_DEFINE_INT(env, cls, KEY_RELEASED); - JNI_STATIC_DEFINE_INT(env, cls, KEY_TYPED); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_PRESS); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_RELEASE); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_REPEAT); int event_type, modifiers; char16_t key_char; - if (!CallJNIMethodI_V(env, cls, key_event, "getID", &event_type) || - !CallJNIMethodC_V(env, cls, key_event, "getKeyChar", &key_char) || - !CallJNIMethodI_V(env, cls, key_event, "getModifiersEx", &modifiers)) { + if (!CallJNIMethodI_V(env, objClass, key_event, "getID", &event_type) || + !CallJNIMethodC_V(env, objClass, key_event, "getKeyChar", &key_char) || + !CallJNIMethodI_V(env, objClass, key_event, "getModifiers", &modifiers)) { return; } CefKeyEvent cef_event; - cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, modifiers); #if defined(OS_WIN) - jlong scanCode = 0; - GetJNIFieldLong(env, cls, key_event, "scancode", &scanCode); + GetJNIFieldLong(env, objClass, key_event, "scancode", &scanCode); + scanCode = MapScanCodeGLFW(env, cls, key_char, scanCode); BYTE VkCode = LOBYTE(MapVirtualKey(scanCode, MAPVK_VSC_TO_VK)); cef_event.native_key_code = (scanCode << 16) | // key scan code 1; // key repeat count #elif defined(OS_LINUX) || defined(OS_MACOSX) int key_code; - if (!CallJNIMethodI_V(env, cls, key_event, "getKeyCode", &key_code)) { + if (!CallJNIMethodI_V(env, objClass, key_event, "getKeyCode", &key_code)) { return; } - JNI_STATIC_DEFINE_INT(env, cls, VK_BACK_SPACE); - JNI_STATIC_DEFINE_INT(env, cls, VK_DELETE); - JNI_STATIC_DEFINE_INT(env, cls, VK_DOWN); - JNI_STATIC_DEFINE_INT(env, cls, VK_ENTER); - JNI_STATIC_DEFINE_INT(env, cls, VK_ESCAPE); - JNI_STATIC_DEFINE_INT(env, cls, VK_LEFT); - JNI_STATIC_DEFINE_INT(env, cls, VK_RIGHT); - JNI_STATIC_DEFINE_INT(env, cls, VK_TAB); - JNI_STATIC_DEFINE_INT(env, cls, VK_UP); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_BACKSPACE); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_DELETE); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_DOWN); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_ENTER); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_ESCAPE); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_LEFT); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_RIGHT); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_TAB); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_KEY_UP); #if defined(OS_LINUX) - if (key_code == JNI_STATIC(VK_BACK_SPACE)) + if (key_code == JNI_STATIC(GLFW_KEY_BACKSPACE)) cef_event.native_key_code = XK_BackSpace; - else if (key_code == JNI_STATIC(VK_DELETE)) + else if (key_code == JNI_STATIC(GLFW_KEY_DELETE)) cef_event.native_key_code = XK_Delete; - else if (key_code == JNI_STATIC(VK_DOWN)) + else if (key_code == JNI_STATIC(GLFW_KEY_DOWN)) cef_event.native_key_code = XK_Down; - else if (key_code == JNI_STATIC(VK_ENTER)) + else if (key_code == JNI_STATIC(GLFW_KEY_ENTER)) cef_event.native_key_code = XK_Return; - else if (key_code == JNI_STATIC(VK_ESCAPE)) + else if (key_code == JNI_STATIC(GLFW_KEY_ESCAPE)) cef_event.native_key_code = XK_Escape; - else if (key_code == JNI_STATIC(VK_LEFT)) + else if (key_code == JNI_STATIC(GLFW_KEY_LEFT)) cef_event.native_key_code = XK_Left; - else if (key_code == JNI_STATIC(VK_RIGHT)) + else if (key_code == JNI_STATIC(GLFW_KEY_RIGHT)) cef_event.native_key_code = XK_Right; - else if (key_code == JNI_STATIC(VK_TAB)) + else if (key_code == JNI_STATIC(GLFW_KEY_TAB)) cef_event.native_key_code = XK_Tab; - else if (key_code == JNI_STATIC(VK_UP)) + else if (key_code == JNI_STATIC(GLFW_KEY_UP)) cef_event.native_key_code = XK_Up; else cef_event.native_key_code = key_char; @@ -1688,31 +1721,31 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env, cef_event.character = cef_event.unmodified_character; } #elif defined(OS_MACOSX) - if (key_code == JNI_STATIC(VK_BACK_SPACE)) { + if (key_code == JNI_STATIC(GLFW_KEY_BACKSPACE)) { cef_event.native_key_code = kVK_Delete; cef_event.unmodified_character = kBackspaceCharCode; - } else if (key_code == JNI_STATIC(VK_DELETE)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_DELETE)) { cef_event.native_key_code = kVK_ForwardDelete; cef_event.unmodified_character = kDeleteCharCode; - } else if (key_code == JNI_STATIC(VK_DOWN)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_DOWN)) { cef_event.native_key_code = kVK_DownArrow; cef_event.unmodified_character = /* NSDownArrowFunctionKey */ 0xF701; - } else if (key_code == JNI_STATIC(VK_ENTER)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_ENTER)) { cef_event.native_key_code = kVK_Return; cef_event.unmodified_character = kReturnCharCode; - } else if (key_code == JNI_STATIC(VK_ESCAPE)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_ESCAPE)) { cef_event.native_key_code = kVK_Escape; cef_event.unmodified_character = kEscapeCharCode; - } else if (key_code == JNI_STATIC(VK_LEFT)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_LEFT)) { cef_event.native_key_code = kVK_LeftArrow; cef_event.unmodified_character = /* NSLeftArrowFunctionKey */ 0xF702; - } else if (key_code == JNI_STATIC(VK_RIGHT)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_RIGHT)) { cef_event.native_key_code = kVK_RightArrow; cef_event.unmodified_character = /* NSRightArrowFunctionKey */ 0xF703; - } else if (key_code == JNI_STATIC(VK_TAB)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_TAB)) { cef_event.native_key_code = kVK_Tab; cef_event.unmodified_character = kTabCharCode; - } else if (key_code == JNI_STATIC(VK_UP)) { + } else if (key_code == JNI_STATIC(GLFW_KEY_UP)) { cef_event.native_key_code = kVK_UpArrow; cef_event.unmodified_character = /* NSUpArrowFunctionKey */ 0xF700; } else { @@ -1786,19 +1819,19 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent(JNIEnv* env, #endif // defined(OS_MACOSX) #endif // defined(OS_LINUX) || defined(OS_MACOSX) - if (event_type == JNI_STATIC(KEY_PRESSED)) { + if (event_type == JNI_STATIC(GLFW_PRESS)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; #endif cef_event.type = KEYEVENT_RAWKEYDOWN; - } else if (event_type == JNI_STATIC(KEY_RELEASED)) { + } else if (event_type == JNI_STATIC(GLFW_RELEASE)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; // bits 30 and 31 should always be 1 for WM_KEYUP cef_event.native_key_code |= 0xC0000000; #endif cef_event.type = KEYEVENT_KEYUP; - } else if (event_type == JNI_STATIC(KEY_TYPED)) { + } else if (event_type == JNI_STATIC(GLFW_REPEAT)) { #if defined(OS_WIN) cef_event.windows_key_code = key_char; #endif @@ -1815,25 +1848,22 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent(JNIEnv* env, jobject obj, jobject mouse_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); - ScopedJNIClass cls(env, env->GetObjectClass(mouse_event)); - if (!cls) + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); + ScopedJNIClass objClass = ScopedJNIClass(env, env->GetObjectClass(mouse_event)); + if (!cls || !objClass) return; - JNI_STATIC_DEFINE_INT(env, cls, BUTTON1); - JNI_STATIC_DEFINE_INT(env, cls, BUTTON2); - JNI_STATIC_DEFINE_INT(env, cls, BUTTON3); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_DRAGGED); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_ENTERED); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_EXITED); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_MOVED); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_PRESSED); - JNI_STATIC_DEFINE_INT(env, cls, MOUSE_RELEASED); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_MOUSE_BUTTON_1); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_MOUSE_BUTTON_2); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_MOUSE_BUTTON_3); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_PRESS); + JNI_STATIC_DEFINE_INT(env, cls, GLFW_RELEASE); int event_type, x, y, modifiers; - if (!CallJNIMethodI_V(env, cls, mouse_event, "getID", &event_type) || - !CallJNIMethodI_V(env, cls, mouse_event, "getX", &x) || - !CallJNIMethodI_V(env, cls, mouse_event, "getY", &y) || - !CallJNIMethodI_V(env, cls, mouse_event, "getModifiersEx", &modifiers)) { + if (!CallJNIMethodI_V(env, objClass, mouse_event, "getID", &event_type) || + !CallJNIMethodI_V(env, objClass, mouse_event, "getX", &x) || + !CallJNIMethodI_V(env, objClass, mouse_event, "getY", &y) || + !CallJNIMethodI_V(env, objClass, mouse_event, "getModifiers", &modifiers)) { return; } @@ -1841,36 +1871,36 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendMouseEvent(JNIEnv* env, cef_event.x = x; cef_event.y = y; - cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, modifiers); - if (event_type == JNI_STATIC(MOUSE_PRESSED) || - event_type == JNI_STATIC(MOUSE_RELEASED)) { + if (event_type == JNI_STATIC(GLFW_PRESS) || + event_type == JNI_STATIC(GLFW_RELEASE)) { int click_count, button; - if (!CallJNIMethodI_V(env, cls, mouse_event, "getClickCount", + if (!CallJNIMethodI_V(env, objClass, mouse_event, "getClickCount", &click_count) || - !CallJNIMethodI_V(env, cls, mouse_event, "getButton", &button)) { + !CallJNIMethodI_V(env, objClass, mouse_event, "getButton", &button)) { return; } CefBrowserHost::MouseButtonType cef_mbt; - if (button == JNI_STATIC(BUTTON1)) + if (button == JNI_STATIC(GLFW_MOUSE_BUTTON_1)) cef_mbt = MBT_LEFT; - else if (button == JNI_STATIC(BUTTON2)) + else if (button == JNI_STATIC(GLFW_MOUSE_BUTTON_2)) cef_mbt = MBT_MIDDLE; - else if (button == JNI_STATIC(BUTTON3)) + else if (button == JNI_STATIC(GLFW_MOUSE_BUTTON_3)) cef_mbt = MBT_RIGHT; else return; browser->GetHost()->SendMouseClickEvent( - cef_event, cef_mbt, (event_type == JNI_STATIC(MOUSE_RELEASED)), + cef_event, cef_mbt, (event_type == JNI_STATIC(GLFW_RELEASE)), click_count); - } else if (event_type == JNI_STATIC(MOUSE_MOVED) || - event_type == JNI_STATIC(MOUSE_DRAGGED) || - event_type == JNI_STATIC(MOUSE_ENTERED) || - event_type == JNI_STATIC(MOUSE_EXITED)) { + } else if (event_type == 503 || // MOUSE_MOVED + event_type == 506 || // MOUSE_DRAGGED + event_type == 504 || // MOUSE_ENTERED + event_type == 505) { // MOUSE_EXITED browser->GetHost()->SendMouseMoveEvent( - cef_event, (event_type == JNI_STATIC(MOUSE_EXITED))); + cef_event, (event_type == 505)); // MOUSE_EXITED } } @@ -1880,20 +1910,22 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendMouseWheelEvent( jobject obj, jobject mouse_wheel_event) { CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); - ScopedJNIClass cls(env, env->GetObjectClass(mouse_wheel_event)); - if (!cls) + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); + ScopedJNIClass objClass = ScopedJNIClass(env, env->GetObjectClass(mouse_wheel_event)); + if (!cls || !objClass) return; - JNI_STATIC_DEFINE_INT(env, cls, WHEEL_UNIT_SCROLL); + JNI_STATIC_DEFINE_INT(env, objClass, WHEEL_UNIT_SCROLL); - int scroll_type, delta, x, y, modifiers; - if (!CallJNIMethodI_V(env, cls, mouse_wheel_event, "getScrollType", + int scroll_type, x, y, modifiers; + double delta; + if (!CallJNIMethodI_V(env, objClass, mouse_wheel_event, "getScrollType", &scroll_type) || - !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getWheelRotation", + !CallJNIMethodD_V(env, objClass, mouse_wheel_event, "getWheelRotation", &delta) || - !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getX", &x) || - !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getY", &y) || - !CallJNIMethodI_V(env, cls, mouse_wheel_event, "getModifiersEx", + !CallJNIMethodI_V(env, objClass, mouse_wheel_event, "getX", &x) || + !CallJNIMethodI_V(env, objClass, mouse_wheel_event, "getY", &y) || + !CallJNIMethodI_V(env, objClass, mouse_wheel_event, "getModifiers", &modifiers)) { return; } @@ -1902,11 +1934,11 @@ Java_org_cef_browser_CefBrowser_1N_N_1SendMouseWheelEvent( cef_event.x = x; cef_event.y = y; - cef_event.modifiers = GetCefModifiers(env, cls, modifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, modifiers); - if (scroll_type == JNI_STATIC(WHEEL_UNIT_SCROLL)) { + if (scroll_type == 0) { // WHEEL_UNIT_SCROLL // Use the smarter version that considers platform settings. - CallJNIMethodI_V(env, cls, mouse_wheel_event, "getUnitsToScroll", &delta); + CallJNIMethodD_V(env, objClass, mouse_wheel_event, "getUnitsToScroll", &delta); } double deltaX = 0, deltaY = 0; @@ -1929,13 +1961,13 @@ Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragEnter(JNIEnv* env, GetCefFromJNIObject(env, jdragData, "CefDragData"); if (!drag_data.get()) return; - ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); - cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDragEnter( @@ -1948,13 +1980,13 @@ Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDragOver(JNIEnv* env, jobject pos, jint jmodifiers, jint allowedOps) { - ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); - cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDragOver( @@ -1973,13 +2005,13 @@ Java_org_cef_browser_CefBrowser_1N_N_1DragTargetDrop(JNIEnv* env, jobject obj, jobject pos, jint jmodifiers) { - ScopedJNIClass cls(env, "java/awt/event/MouseEvent"); + ScopedJNIClass cls(env, "org/lwjgl/glfw/GLFW"); if (!cls) return; CefMouseEvent cef_event; GetJNIPoint(env, pos, &cef_event.x, &cef_event.y); - cef_event.modifiers = GetCefModifiers(env, cls, jmodifiers); + cef_event.modifiers = GetCefModifiersGlfw(env, cls, jmodifiers); CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); browser->GetHost()->DragTargetDrop(cef_event); @@ -2026,41 +2058,6 @@ Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI(JNIEnv* env, #endif } -JNIEXPORT void JNICALL -Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv* env, - jobject obj, - jlong windowHandle, - jobject canvas) { - CefRefPtr browser = JNI_GET_BROWSER_OR_RETURN(env, obj); - base::OnceClosure callback = base::BindOnce(&OnAfterParentChanged, browser); - -#if defined(OS_MACOSX) - util::SetParent(browser->GetHost()->GetWindowHandle(), windowHandle, - std::move(callback)); -#else - CefWindowHandle browserHandle = browser->GetHost()->GetWindowHandle(); - CefWindowHandle parentHandle = - canvas ? util::GetWindowHandle(env, canvas) : kNullWindowHandle; - if (CefCurrentlyOn(TID_UI)) { - util::SetParent(browserHandle, parentHandle, std::move(callback)); - } else { -#if defined(OS_LINUX) - CriticalLock lock; - CriticalWait waitCond(&lock); - lock.Lock(); - CefPostTask(TID_UI, - base::BindOnce(util::SetParentSync, browserHandle, parentHandle, - &waitCond, std::move(callback))); - waitCond.Wait(1000); - lock.Unlock(); -#else - CefPostTask(TID_UI, base::BindOnce(util::SetParent, browserHandle, - parentHandle, std::move(callback))); -#endif - } -#endif -} - JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1NotifyMoveOrResizeStarted(JNIEnv* env, jobject obj) { diff --git a/native/CefBrowser_N.h b/native/CefBrowser_N.h index 9e03d8ca..bd0fd0d0 100644 --- a/native/CefBrowser_N.h +++ b/native/CefBrowser_N.h @@ -21,7 +21,6 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateBrowser(JNIEnv*, jstring, jboolean, jboolean, - jobject, jobject); /* @@ -38,7 +37,6 @@ Java_org_cef_browser_CefBrowser_1N_N_1CreateDevTools(JNIEnv*, jlong, jboolean, jboolean, - jobject, jobject); /* @@ -501,16 +499,6 @@ JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1UpdateUI(JNIEnv*, jobject, jobject); -/* - * Class: org_cef_browser_CefBrowser_N - * Method: N_SetParent - * Signature: (JLjava/awt/Component;)V - */ -JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SetParent(JNIEnv*, - jobject, - jlong, - jobject); - /* * Class: org_cef_browser_CefBrowser_N * Method: N_NotifyMoveOrResizeStarted diff --git a/native/CefClientHandler.cpp b/native/CefClientHandler.cpp index 8abbaf6a..9ac33878 100644 --- a/native/CefClientHandler.cpp +++ b/native/CefClientHandler.cpp @@ -54,6 +54,15 @@ Java_org_cef_handler_CefClientHandler_N_1removeDisplayHandler( "CefDisplayHandler"); } +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeAudioHandler( + JNIEnv* env, + jobject clientHandler, + jobject audioHandler) { + SetCefForJNIObject(env, audioHandler, nullptr, + "CefAudioHandler"); +} + JNIEXPORT void JNICALL Java_org_cef_handler_CefClientHandler_N_1removeDownloadHandler( JNIEnv* env, diff --git a/native/CefClientHandler.h b/native/CefClientHandler.h index 9867c452..7b552958 100644 --- a/native/CefClientHandler.h +++ b/native/CefClientHandler.h @@ -56,6 +56,16 @@ Java_org_cef_handler_CefClientHandler_N_1removeDisplayHandler(JNIEnv*, jobject, jobject); +/* + * Class: org_cef_handler_CefClientHandler + * Method: N_removeAudioHandler + * Signature: (Lorg/cef/handler/CefAudioHandler;)V + */ +JNIEXPORT void JNICALL +Java_org_cef_handler_CefClientHandler_N_1removeAudioHandler(JNIEnv*, + jobject, + jobject); + /* * Class: org_cef_handler_CefClientHandler * Method: N_removeDownloadHandler diff --git a/native/audio_handler.cpp b/native/audio_handler.cpp new file mode 100644 index 00000000..045cda4a --- /dev/null +++ b/native/audio_handler.cpp @@ -0,0 +1,118 @@ +// 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. + +#include "audio_handler.h" + +#include "jni_util.h" + +//#include + +AudioHandler::AudioHandler(JNIEnv* env, jobject handler) + : handle_(env, handler) {} + +jobject jniParams(ScopedJNIEnv env, jclass clsProps, const CefAudioParameters& params) { + jclass cls = env->FindClass("org/cef/misc/CefChannelLayout"); + if (cls == nullptr) { +// std::cout << "Could not find class 0"; + return nullptr; + } + jmethodID getLayout = env->GetStaticMethodID(cls, "forId", "(I)Lorg/cef/misc/CefChannelLayout;"); + if (getLayout == 0) { +// std::cout << "Could not find method 0"; + return nullptr; + } + jobject layout = env->CallStaticObjectMethod(cls, getLayout, (int) params.channel_layout); + + cls = clsProps; + if (cls == nullptr) { +// std::cout << "Could not find class 1"; + return nullptr; + } + jmethodID constructor = env->GetMethodID(cls, "", "(Lorg/cef/misc/CefChannelLayout;II)V"); + if (constructor == 0) { +// std::cout << "Could not find constructor 1"; + return nullptr; + } + jobject parameters = env->NewObject(cls, constructor, layout, params.sample_rate, params.frames_per_buffer); + + return parameters; +} + +jobject jniParams(ScopedJNIEnv env, const CefAudioParameters& params) { + jclass cls = env->FindClass("org/cef/misc/CefAudioParameters"); + return jniParams(env, cls, params); +} + +bool AudioHandler::GetAudioParameters(CefRefPtr browser, + CefAudioParameters& params) { + ScopedJNIEnv env; + if (!env) + return true; + + ScopedJNIBrowser jbrowser(env, browser); + + jboolean jreturn = JNI_FALSE; + jclass cls = env->FindClass("org/cef/misc/CefAudioParameters"); + jobject paramsJni = jniParams(env, cls, params); + + JNI_CALL_METHOD(env, handle_, "getAudioParameters", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/misc/CefAudioParameters;)Z", Boolean, + jreturn, jbrowser.get(), paramsJni); + + return (jreturn != JNI_FALSE); +} + +void AudioHandler::OnAudioStreamStarted(CefRefPtr browser, + const CefAudioParameters& params, int channels) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onAudioStreamStarted", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/misc/CefAudioParameters;I)V", + jbrowser.get(), nullptr, channels); +} + +void AudioHandler::OnAudioStreamPacket(CefRefPtr browser, const float** data, int frames, int64_t pts) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + ScopedJNIObjectLocal dataPtr( + env, NewJNIObject(env, "org/cef/misc/DataPointer", "(J)V", (jlong) data)); + + JNI_CALL_VOID_METHOD(env, handle_, "onAudioStreamPacket", + "(Lorg/cef/browser/CefBrowser;Lorg/cef/misc/DataPointer;IJ)V", + jbrowser.get(), dataPtr.get(), frames, (long long) pts); +} + +void AudioHandler::OnAudioStreamStopped(CefRefPtr browser) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + + JNI_CALL_VOID_METHOD(env, handle_, "onAudioStreamStopped", + "(Lorg/cef/browser/CefBrowser;)V", + jbrowser.get()); +} + +void AudioHandler::OnAudioStreamError(CefRefPtr browser, + const CefString& text) { + ScopedJNIEnv env; + if (!env) + return; + + ScopedJNIBrowser jbrowser(env, browser); + ScopedJNIString jtext(env, text); + + JNI_CALL_VOID_METHOD(env, handle_, "onAudioStreamError", + "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;)V", + jbrowser.get(), jtext.get()); +} diff --git a/native/audio_handler.h b/native/audio_handler.h new file mode 100644 index 00000000..7df6c7ed --- /dev/null +++ b/native/audio_handler.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef JCEF_NATIVE_AUDIO_HANDLER_H_ +#define JCEF_NATIVE_AUDIO_HANDLER_H_ +#pragma once + +#include + +#include "include/cef_audio_handler.h" + +#include "jni_scoped_helpers.h" + +// https://github.com/chromiumembedded/cef/blob/master/include/cef_audio_handler.h +// AudioHandler implementation. +class AudioHandler : public CefAudioHandler { + public: + AudioHandler(JNIEnv* env, jobject handler); + + // CefAudioHandler methods: + bool GetAudioParameters(CefRefPtr browser, + CefAudioParameters& params) override; + void OnAudioStreamStarted(CefRefPtr browser, + const CefAudioParameters& params, int channels) override; + void OnAudioStreamPacket(CefRefPtr browser, const float** data, int frames, int64_t pts) override; + void OnAudioStreamStopped(CefRefPtr browser) override; + void OnAudioStreamError(CefRefPtr browser, const CefString& text) override; + + protected: + ScopedJNIObjectGlobal handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(AudioHandler); +}; + +#endif // JCEF_NATIVE_AUDIO_HANDLER_H_ diff --git a/native/client_handler.cpp b/native/client_handler.cpp index 9b5567fc..0318767e 100644 --- a/native/client_handler.cpp +++ b/native/client_handler.cpp @@ -15,6 +15,7 @@ #include "context_menu_handler.h" #include "dialog_handler.h" #include "display_handler.h" +#include "audio_handler.h" #include "download_handler.h" #include "drag_handler.h" #include "focus_handler.h" @@ -105,6 +106,10 @@ CefRefPtr ClientHandler::GetDisplayHandler() { return GetHandler("DisplayHandler"); } + CefRefPtr ClientHandler::GetAudioHandler() { + return GetHandler("AudioHandler"); + } + CefRefPtr ClientHandler::GetDownloadHandler() { return GetHandler("DownloadHandler"); } diff --git a/native/client_handler.h b/native/client_handler.h index db285828..5c59a041 100644 --- a/native/client_handler.h +++ b/native/client_handler.h @@ -27,6 +27,7 @@ class ClientHandler : public CefClient { CefRefPtr GetContextMenuHandler() override; CefRefPtr GetDialogHandler() override; CefRefPtr GetDisplayHandler() override; + CefRefPtr GetAudioHandler() override; CefRefPtr GetDownloadHandler() override; CefRefPtr GetDragHandler() override; CefRefPtr GetFocusHandler() override; diff --git a/native/context.cpp b/native/context.cpp index 7f894ad9..b47a3956 100644 --- a/native/context.cpp +++ b/native/context.cpp @@ -101,6 +101,16 @@ CefSettings GetJNISettings(JNIEnv* env, jobject obj) { CefString(&settings.locales_dir_path) = tmp; tmp.clear(); } + if (GetJNIFieldString(env, cls, obj, "framework_dir_path", &tmp) && + !tmp.empty()) { + CefString(&settings.framework_dir_path) = tmp; + tmp.clear(); + } + if (GetJNIFieldString(env, cls, obj, "main_bundle_path", &tmp) && + !tmp.empty()) { + CefString(&settings.main_bundle_path) = tmp; + tmp.clear(); + } GetJNIFieldBoolean(env, cls, obj, "pack_loading_disabled", &settings.pack_loading_disabled); GetJNIFieldInt(env, cls, obj, "remote_debugging_port", diff --git a/native/display_handler.cpp b/native/display_handler.cpp index cf088682..60874291 100644 --- a/native/display_handler.cpp +++ b/native/display_handler.cpp @@ -6,77 +6,6 @@ #include "jni_util.h" -namespace { - -int GetCursorId(cef_cursor_type_t type) { - ScopedJNIEnv env; - if (!env) - return 0; - - const char* cursorClassName = "java/awt/Cursor"; - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - CROSSHAIR_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - DEFAULT_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - E_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - HAND_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - MOVE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - N_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - NE_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - NW_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - S_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - SE_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - SW_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - TEXT_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - W_RESIZE_CURSOR, 0); - JNI_STATIC_DEFINE_INT_RV(env, ScopedJNIClass(env, cursorClassName), - WAIT_CURSOR, 0); - - switch (type) { - case CT_CROSS: - return JNI_STATIC(CROSSHAIR_CURSOR); - case CT_HAND: - return JNI_STATIC(HAND_CURSOR); - case CT_IBEAM: - return JNI_STATIC(TEXT_CURSOR); - case CT_WAIT: - return JNI_STATIC(WAIT_CURSOR); - case CT_EASTRESIZE: - return JNI_STATIC(E_RESIZE_CURSOR); - case CT_NORTHRESIZE: - return JNI_STATIC(N_RESIZE_CURSOR); - case CT_NORTHEASTRESIZE: - return JNI_STATIC(NE_RESIZE_CURSOR); - case CT_NORTHWESTRESIZE: - return JNI_STATIC(NW_RESIZE_CURSOR); - case CT_SOUTHRESIZE: - return JNI_STATIC(S_RESIZE_CURSOR); - case CT_SOUTHEASTRESIZE: - return JNI_STATIC(SE_RESIZE_CURSOR); - case CT_SOUTHWESTRESIZE: - return JNI_STATIC(SW_RESIZE_CURSOR); - case CT_WESTRESIZE: - return JNI_STATIC(W_RESIZE_CURSOR); - case CT_MOVE: - return JNI_STATIC(MOVE_CURSOR); - default: - return JNI_STATIC(DEFAULT_CURSOR); - } -} - -} // namespace - DisplayHandler::DisplayHandler(JNIEnv* env, jobject handler) : handle_(env, handler) {} @@ -191,7 +120,7 @@ bool DisplayHandler::OnCursorChange(CefRefPtr browser, return false; ScopedJNIBrowser jbrowser(env, browser); - const int cursorId = GetCursorId(type); + const int cursorId = (int) type; jboolean jreturn = JNI_FALSE; JNI_CALL_METHOD(env, handle_, "onCursorChange", diff --git a/native/jni_util.cpp b/native/jni_util.cpp index b71fc29e..957be41d 100644 --- a/native/jni_util.cpp +++ b/native/jni_util.cpp @@ -4,7 +4,6 @@ #include "jni_util.h" -#include #include #include "jni_scoped_helpers.h" @@ -930,6 +929,20 @@ bool GetJNIFieldStaticInt(JNIEnv* env, return false; } +bool CallStaticJNIMethodII_V(JNIEnv* env, + jclass cls, + const char* method_name, + int* value, + int arg) { + jmethodID methodID = env->GetStaticMethodID(cls, method_name, "(I)I"); + if (methodID) { + *value = env->CallStaticIntMethod(cls, methodID, arg); + return true; + } + env->ExceptionClear(); + return false; +} + bool CallJNIMethodI_V(JNIEnv* env, jclass cls, jobject obj, @@ -958,6 +971,20 @@ bool CallJNIMethodC_V(JNIEnv* env, return false; } +bool CallJNIMethodD_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + double* value) { + jmethodID methodID = env->GetMethodID(cls, method_name, "()D"); + if (methodID) { + *value = env->CallDoubleMethod(obj, methodID); + return true; + } + env->ExceptionClear(); + return false; +} + CefSize GetJNISize(JNIEnv* env, jobject obj) { CefSize size; diff --git a/native/jni_util.h b/native/jni_util.h index dd9ba18b..4b78b3f3 100644 --- a/native/jni_util.h +++ b/native/jni_util.h @@ -25,12 +25,6 @@ JavaVM* GetJVM(); void SetJavaClassLoader(JNIEnv* env, jobject javaClassLoader); jobject GetJavaClassLoader(); -#if defined(OS_WIN) -HWND GetHwndOfCanvas(jobject canvas, JNIEnv* env); -#elif defined(OS_LINUX) -unsigned long GetDrawableOfCanvas(jobject canvas, JNIEnv* env); -#endif - // Create a new JNI object and call the default constructor. jobject NewJNIObject(JNIEnv* env, jclass cls); jobject NewJNIObject(JNIEnv* env, const char* class_name); @@ -161,6 +155,13 @@ bool GetJNIFieldStaticInt(JNIEnv* env, const char* field_name, int* value); +// Call a JNI method that returns an int and accepts one int argument. +bool CallStaticJNIMethodII_V(JNIEnv* env, + jclass cls, + const char* method_name, + int* value, + int arg); + // Call a JNI method that returns an int and accepts no arguments. bool CallJNIMethodI_V(JNIEnv* env, jclass cls, @@ -175,6 +176,13 @@ bool CallJNIMethodC_V(JNIEnv* env, const char* method_name, char16_t* value); +// Call a JNI method that returns a double and accepts no arguments. +bool CallJNIMethodD_V(JNIEnv* env, + jclass cls, + jobject obj, + const char* method_name, + double* value); + // Rertieve the CefSize equivalent of a java.awt.Dimension. CefSize GetJNISize(JNIEnv* env, jobject obj); diff --git a/native/jni_util_linux.cpp b/native/jni_util_linux.cpp index acd28e1d..9ec2489e 100644 --- a/native/jni_util_linux.cpp +++ b/native/jni_util_linux.cpp @@ -3,51 +3,3 @@ // can be found in the LICENSE file. #include "jni_util.h" - -#include -#include -#include - -unsigned long GetDrawableOfCanvas(jobject canvas, JNIEnv* env) { - JAWT awt; - JAWT_DrawingSurface* ds; - JAWT_DrawingSurfaceInfo* dsi; - JAWT_X11DrawingSurfaceInfo* dsi_x11; - jint lock; - - // Get the AWT. - awt.version = JAWT_VERSION_1_4; - JAWT_GetAWT(env, &awt); - - // Get the drawing surface. - ds = awt.GetDrawingSurface(env, canvas); - assert(ds != nullptr); - - // Lock the drawing surface. - // May fail during shutdown. - lock = ds->Lock(ds); - if (lock & JAWT_LOCK_ERROR) { - return 0; - } - - // Get the drawing surface info. - dsi = ds->GetDrawingSurfaceInfo(ds); - if (dsi == nullptr) { - // Unlock the drawing surface - ds->Unlock(ds); - return 0; - } - - // Get the platform-specific drawing info. - dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo; - Drawable result = dsi_x11->drawable; - - // Free the drawing surface info - ds->FreeDrawingSurfaceInfo(dsi); - // Unlock the drawing surface - ds->Unlock(ds); - // Free the drawing surface - awt.FreeDrawingSurface(ds); - - return result; -} diff --git a/native/jni_util_win.cpp b/native/jni_util_win.cpp index a1fa5729..9ec2489e 100644 --- a/native/jni_util_win.cpp +++ b/native/jni_util_win.cpp @@ -3,53 +3,3 @@ // can be found in the LICENSE file. #include "jni_util.h" - -#include -#include -#include - -HWND GetHwndOfCanvas(jobject canvas, JNIEnv* env) { - JAWT awt; - JAWT_DrawingSurface* ds; - JAWT_DrawingSurfaceInfo* dsi; - JAWT_Win32DrawingSurfaceInfo* dsi_win; - jboolean bGetAwt; - jint lock; - - // Get the AWT. - awt.version = JAWT_VERSION_1_4; - bGetAwt = JAWT_GetAWT(env, &awt); - assert(bGetAwt != JNI_FALSE); - - // Get the drawing surface. - ds = awt.GetDrawingSurface(env, canvas); - assert(ds != nullptr); - - // Lock the drawing surface. - // May fail during shutdown. - lock = ds->Lock(ds); - if (lock & JAWT_LOCK_ERROR) { - return 0; - } - - // Get the drawing surface info. - dsi = ds->GetDrawingSurfaceInfo(ds); - if (dsi == nullptr) { - // Unlock the drawing surface - ds->Unlock(ds); - return 0; - } - - // Get the platform-specific drawing info. - dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; - HWND result = dsi_win->hwnd; - - // Free the drawing surface info - ds->FreeDrawingSurfaceInfo(dsi); - // Unlock the drawing surface - ds->Unlock(ds); - // Free the drawing surface - awt.FreeDrawingSurface(ds); - - return result; -} diff --git a/native/util.h b/native/util.h index eba07452..58f1cfca 100644 --- a/native/util.h +++ b/native/util.h @@ -93,31 +93,7 @@ void AddCefBrowser(CefRefPtr browser); // Called by CefBrowser.close(true) to destroy the native browser window. void DestroyCefBrowser(CefRefPtr browser); -#if defined(OS_MACOSX) - -// Set the parent of |browserHandle|. If the parent is nullptr the browser will -// be parented to the TempWindow. -void SetParent(CefWindowHandle browserHandle, - jlong parentHandle, - base::OnceClosure callback); - -#else // !defined(OS_MACOSX) - -// Return the window handle for the specified canvas. -CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas); - -// Set the parent of |browserHandle|. If the parent is nullptr the browser will -// be parented to the TempWindow. -void SetParent(CefWindowHandle browserHandle, - CefWindowHandle parentHandle, - base::OnceClosure callback); - -#if defined(OS_LINUX) -void SetParentSync(CefWindowHandle browserHandle, - CefWindowHandle parentHandle, - CriticalWait* waitCond, - base::OnceClosure callback); -#endif +#if !defined(OS_MACOSX) // Set the window bounds for |browserHandle|. void SetWindowBounds(CefWindowHandle browserHandle, const CefRect& contentRect); diff --git a/native/util_linux.cpp b/native/util_linux.cpp index e04e9f88..d63ae676 100644 --- a/native/util_linux.cpp +++ b/native/util_linux.cpp @@ -26,18 +26,6 @@ void X_XMoveResizeWindow(unsigned long browserHandle, XFlush(xdisplay); } -void X_XReparentWindow(unsigned long browserHandle, - unsigned long parentDrawable) { - ::Display* xdisplay = (::Display*)TempWindow::GetDisplay(); - XReparentWindow(xdisplay, browserHandle, parentDrawable, 0, 0); - XFlush(xdisplay); -} - -void X_XSync(bool discard) { - ::Display* xdisplay = (::Display*)TempWindow::GetDisplay(); - XSync(xdisplay, discard); -} - } // namespace // This function is called by LifeSpanHandler::OnAfterCreated(). @@ -53,36 +41,6 @@ void DestroyCefBrowser(CefRefPtr browser) { browser->GetHost()->CloseBrowser(true); } -CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas) { - return GetDrawableOfCanvas(canvas, env); -} - -void SetParent(CefWindowHandle browserHandle, - CefWindowHandle parentHandle, - base::OnceClosure callback) { - SetParentSync(browserHandle, parentHandle, nullptr, std::move(callback)); -} - -void SetParentSync(CefWindowHandle browserHandle, - CefWindowHandle parentHandle, - CriticalWait* waitCond, - base::OnceClosure callback) { - if (waitCond) { - waitCond->lock()->Lock(); - } - if (parentHandle == kNullWindowHandle) - parentHandle = TempWindow::GetWindowHandle(); - if (parentHandle != kNullWindowHandle && browserHandle != kNullWindowHandle) - X_XReparentWindow(browserHandle, parentHandle); - - if (waitCond) { - X_XSync(false); - waitCond->WakeUp(); - waitCond->lock()->Unlock(); - } - std::move(callback).Run(); -} - void SetWindowBounds(CefWindowHandle browserHandle, const CefRect& contentRect) { X_XMoveResizeWindow(browserHandle, contentRect.x, contentRect.y, diff --git a/native/util_mac.mm b/native/util_mac.mm index f7da32aa..527ad867 100644 --- a/native/util_mac.mm +++ b/native/util_mac.mm @@ -538,38 +538,4 @@ void DestroyCefBrowser(CefRefPtr browser) { } } -void SetParent(CefWindowHandle handle, - jlong parentHandle, - base::OnceClosure callback) { - base::RepeatingClosure* pCallback = new base::RepeatingClosure( - base::BindRepeating([](base::OnceClosure& cb) { std::move(cb).Run(); }, - OwnedRef(std::move(callback)))); - dispatch_async(dispatch_get_main_queue(), ^{ - g_browsers_lock_.Lock(); - bool browser_exists = g_browsers_.count(handle) > 0; - g_browsers_lock_.Unlock(); - if (!browser_exists) - return; - - CefBrowserContentView* browser_view = - (CefBrowserContentView*)[CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) - superview]; - [browser_view retain]; - [browser_view removeFromSuperview]; - - NSView* contentView; - if (parentHandle) { - NSWindow* window = (NSWindow*)parentHandle; - contentView = [window contentView]; - } else { - contentView = - CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(TempWindow::GetWindowHandle()); - } - [contentView addSubview:browser_view]; - [browser_view release]; - pCallback->Run(); - delete pCallback; - }); -} - } // namespace util diff --git a/native/util_win.cpp b/native/util_win.cpp index cd60ef7d..1754c6b4 100644 --- a/native/util_win.cpp +++ b/native/util_win.cpp @@ -306,20 +306,6 @@ void DestroyCefBrowser(CefRefPtr browser) { } } -CefWindowHandle GetWindowHandle(JNIEnv* env, jobject canvas) { - return GetHwndOfCanvas(canvas, env); -} - -void SetParent(CefWindowHandle browserHandle, - CefWindowHandle parentHandle, - base::OnceClosure callback) { - if (parentHandle == kNullWindowHandle) - parentHandle = TempWindow::GetWindowHandle(); - if (parentHandle != kNullWindowHandle && browserHandle != kNullWindowHandle) - ::SetParent(browserHandle, parentHandle); - std::move(callback).Run(); -} - void SetWindowBounds(CefWindowHandle browserHandle, const CefRect& contentRect) { HRGN contentRgn = CreateRectRgn(contentRect.x, contentRect.y, diff --git a/tools/buildtools/gsutil.py b/tools/buildtools/gsutil.py index cff91fa7..563398ed 100644 --- a/tools/buildtools/gsutil.py +++ b/tools/buildtools/gsutil.py @@ -34,7 +34,7 @@ IS_WINDOWS = os.name == 'nt' -VERSION = '4.68' +VERSION = '5.30' class InvalidGsutilError(Exception):