All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cef.browser.CN1CefBrowser Maven / Gradle / Ivy

/*
 * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Codename One designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *  
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Codename One through http://www.codenameone.com/ if you 
 * need additional information or have any questions.
 */
package org.cef.browser;

/*
import com.codename1.impl.javase.JavaSEPort;
import com.codename1.impl.javase.JavaSEPort.CN1JPanel;
import com.codename1.impl.javase.PeerComponentBuffer;
import com.codename1.ui.CN;
*/
import org.cef.CefClient;
import org.cef.callback.CefDragData;
import org.cef.handler.CefRenderHandler;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.IllegalComponentStateException;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.DropTarget;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import javax.swing.*;

import org.cef.OS;
import org.cef.handler.CefScreenInfo;

/**
 * This class represents an off-screen rendered browser.
 * The visibility of this class is "package". To create a new
 * CefBrowser instance, please use CefBrowserFactory.
 */
public class CN1CefBrowser extends CefBrowser_N implements CefRenderHandler {
    //private CefRenderer renderer_;
    //private GLCanvas canvas_;
    private long window_handle_ = 0;
    private Rectangle browser_rect_ = new Rectangle(0, 0, 1, 1); // Work around CEF issue #1437.
    private Point screenPoint_ = new Point(0, 0);
    private boolean isTransparent_;
    private JPanel component_;
    //private BufferedImage bufferedImage_;
    private WeakReference bufferRef;
    private byte[] buf_;
    

    CN1CefBrowser(CefClient client, String url, boolean transparent, CefRequestContext context) {
        this(client, url, transparent, context, null, null);
    }

    private CN1CefBrowser(CefClient client, String url, boolean transparent,
            CefRequestContext context, CN1CefBrowser parent, Point inspectAt) {
        super(client, url, context, parent, inspectAt);
        isTransparent_ = transparent;
        createComponent();
    }
    
    /**
     * Sets the buffer to which the browser should draw to.
     * @param buf 
     */
    public void setPeerComponentBuffer(PixelBuffer buf) {
        bufferRef = new WeakReference(buf);
    }
   
    @Override
    public void createImmediately() {
        // Create the browser immediately.
        createBrowserIfRequired(false);
    }

    /**
     * Gets the swing component that the CEF browser uses for receiving events.
     * @return 
     */
    @Override
    public Component getUIComponent() {
        return component_;
    }

    @Override
    public CefRenderHandler getRenderHandler() {
        return this;
    }

    @Override
    protected CefBrowser_N createDevToolsBrowser(CefClient client, String url,
            CefRequestContext context, CefBrowser_N parent, Point inspectAt) {
        return new CN1CefBrowser(
                client, url, isTransparent_, context, (CN1CefBrowser) this, inspectAt);
    }
    
    private synchronized long getWindowHandle() {
        if (window_handle_ == 0 && OS.isMacintosh()) {
            window_handle_ = getWindowHandle(component_);
        }
        return window_handle_;
    }

    /**
     * Pulled this straight from the CEF examples.  Looks like on Mac, it needs to keep the window
     * handle.
     * @param component
     * @return 
     */
    private static long getWindowHandle(Component component) {
        try {
            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;
        } catch (Throwable t) {
            System.out.println("Exception in thread "+Thread.currentThread().getName());
            t.printStackTrace();
            return 0;
        }
    }

    /*
    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_;
    }
    */

    private static ComponentFactory componentFactory;
    private static UIPlatform platform;
    
    
    
    private void createComponent() {
        component_ = componentFactory.createComponent(new ComponentDelegate() {
            @Override
            public void boundsChanged(int x, int y, int w, int h) {
                if (browser_rect_.getX() == x && browser_rect_.getY() == y && browser_rect_.getWidth() == w && browser_rect_.getHeight() == h) {
                    return;
                }
                browser_rect_.setBounds(x, y, w, h);
                try {
                    Point p = new Point(0, 0);
                    SwingUtilities.convertPointToScreen(p, component_);
                    screenPoint_ = p;
                } catch (IllegalComponentStateException ex) {
                    System.err.println("Failed to get location on screen:"+ex.getMessage());
                    screenPoint_ = new Point(0,0);
                }
                wasResized(w, h);
            }

            @Override
            public void wasResized(int width, int height) {
                CN1CefBrowser.this.wasResized(width, height);
            }

            @Override
            public void createBrowserIfRequired(boolean b) {
                CN1CefBrowser.this.createBrowserIfRequired(b);
            }
            
        });
        
        component_.addHierarchyListener(new HierarchyListener() {
            @Override
            public void hierarchyChanged(HierarchyEvent e) {
                try {
                    Point p = new Point(0, 0);
                    SwingUtilities.convertPointToScreen(p, component_);
                    screenPoint_ = p;
                } catch (IllegalComponentStateException ex) {
                    System.err.println("Failed to get location on screen:"+ex.getMessage());
                    screenPoint_ = new Point(0,0);
                }
            }
        });
        
        component_.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);
            }
        });

        component_.addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseMoved(MouseEvent e) {
                sendMouseEvent(e);
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                sendMouseEvent(e);
            }
        });

        component_.addMouseWheelListener(new MouseWheelListener() {
            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                final int units = platform.convertToPixels(e.getUnitsToScroll(), true) * -1;

                
                if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
                    MouseWheelEvent e2 = new MouseWheelEvent(
                            e.getComponent(),
                            e.getID(),
                            e.getWhen(),
                            e.getModifiers(),
                            e.getX(),
                            e.getY(),
                            e.getClickCount(),
                            e.isPopupTrigger(),
                            MouseWheelEvent.WHEEL_BLOCK_SCROLL,
                            e.getScrollAmount(),
                            units
                    );
                    sendMouseWheelEvent(e2);
                    return;
                }
                
                sendMouseWheelEvent(e);
            }
        });

        component_.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);
            }
        });

        component_.setFocusable(true);
        component_.addFocusListener(new FocusListener() {
            private boolean inFocusGained, inFocusLost;
            @Override
            public void focusLost(FocusEvent e) {
                if (inFocusLost) return;
                inFocusLost = true;
                try {
                    setFocus(false);
                } finally {
                    inFocusLost = false;
                }
            }

            @Override
            public void focusGained(FocusEvent e) {
                if (inFocusGained) {
                    return;
                }
                inFocusGained = true;
                try {
                    // Dismiss any Java menus that are currently displayed.
                    MenuSelectionManager.defaultManager().clearSelectedPath();
                    setFocus(true);
                } finally {
                    inFocusGained = false;
                }
                
            }
        });

        // Connect the Canvas with a drag and drop listener.
        new DropTarget(component_, new CN1CefDropTargetListener(this));
    }

    private boolean inSetFocus;
    
    @Override
    public void setFocus(boolean enable) {
        if (inSetFocus) {
            return;
        }
        inSetFocus = true;
        try {
            super.setFocus(enable);
        } finally {
            inSetFocus = false;
        }
    }
    
    
    
    
    @Override
    public Rectangle getViewRect(CefBrowser browser) {
        return browser_rect_;
    }

    @Override
    public Point getScreenPoint(CefBrowser browser, Point viewPoint) {
        try {
            Point screenPoint = new Point(screenPoint_);
            screenPoint.translate(viewPoint.x, viewPoint.y);
            return screenPoint;
        } catch (Throwable t) {
            System.out.println("Exception in thread "+Thread.currentThread().getName());
            t.printStackTrace();
            return new Point(screenPoint_);
        }
    }

    @Override
    public void onPopupShow(CefBrowser browser, boolean show) {
        try {
            if (!show) {
                //renderer_.clearPopupRects();
                invalidate();
            }
        } catch (Throwable t) {
            System.out.println("Exception in thread "+Thread.currentThread().getName());
            t.printStackTrace();
        }
    }

    @Override
    public void onPopupSize(CefBrowser browser, Rectangle size) {
        try {
            //renderer_.onPopupSize(size);
        } catch (Throwable t) {
            System.out.println("Exception in thread "+Thread.currentThread().getName());
            t.printStackTrace();
        }
    }

    private boolean firstPaint=true;
    
    @Override
    public void onPaint(final CefBrowser browser, final boolean popup, final Rectangle[] dirtyRects,
            final ByteBuffer buffer, final int width, final int height) {
        try {
            _onPaint(browser, popup, dirtyRects, buffer, width, height);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
    public void _onPaint(final CefBrowser browser, final boolean popup, final Rectangle[] dirtyRects,
            final ByteBuffer buffer, final int width, final int height) {    
        final PixelBuffer buffer_ = bufferRef.get();
        if (buffer_ == null) {
            return;
        }
        BufferedImage img = buffer_.getBufferedImage();
        boolean imgUpdated = false;
         if (img == null || img.getWidth() != width || img.getHeight() != height) {
            img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
            imgUpdated = true;
        }
        if (buf_ == null || buf_.length != width * height * 4) {
            buf_ = new byte[width * height * 4];
        }
        final BufferedImage fImg = img;
        final boolean fImgUpdated = imgUpdated;
        if (imgUpdated || firstPaint ) {
            firstPaint = false;
            buffer_.modifyBuffer(new Runnable() {
                public void run() {
                    WritableRaster raster = fImg.getRaster();
                    buffer.get(buf_);
                    int len = width * height * 4;
                    for (int i=0; i= 9) {
                // JDK9 Doesn't like the old hack for getting the scale via reflection.
                // https://bugs.openjdk.java.net/browse/JDK-8172962
                GraphicsConfiguration graphicsConfig = graphicsDevice 
                        .getDefaultConfiguration(); 

                AffineTransform tx = graphicsConfig.getDefaultTransform(); 
                double scaleX = tx.getScaleX(); 
                double scaleY = tx.getScaleY(); 
                return Math.max(1.0, Math.min(scaleX, scaleY));
            } else {

                Field field = graphicsDevice.getClass().getDeclaredField("scale");
                if (field != null) {
                    field.setAccessible(true);
                    Object scale = field.get(graphicsDevice);
                    if (scale instanceof Integer && ((Integer) scale).intValue() >= 2) {
                        return ((Integer)scale).doubleValue();
                    }
                }
            }
        } catch (Throwable e) {
            //e.printStackTrace();
        }
        return 1.0;
    }
    
    private static int cachedJavaVersion=-1;
    /**
     * Returns the Java version as an int value.
     *
     * @return the Java version as an int value (8, 9, etc.)
     * @since 12130
     */
    private static int getJavaVersion() {
        if (cachedJavaVersion < 0) {

            String version = System.getProperty("java.version");
            if (version.startsWith("1.")) {
                version = version.substring(2);
            }
            // Allow these formats:
            // 1.8.0_72-ea
            // 9-ea
            // 9
            // 9.0.1
            int dotPos = version.indexOf('.');
            int dashPos = version.indexOf('-');
            if (dotPos < 0 && dashPos < 0) {
                cachedJavaVersion = Integer.parseInt(version);
                return cachedJavaVersion;
            }
            cachedJavaVersion = Integer.parseInt(version.substring(0,
                    dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
            return cachedJavaVersion;
        }
        return cachedJavaVersion;
    }
    
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy