< prev index next >

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java

Print this page




  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.embed.swing;
  27 
  28 import java.awt.AlphaComposite;
  29 import java.awt.AWTEvent;
  30 import java.awt.Component;
  31 import java.awt.Cursor;
  32 import java.awt.Dimension;
  33 import java.awt.Graphics;
  34 import java.awt.Graphics2D;
  35 import java.awt.KeyboardFocusManager;
  36 import java.awt.Point;
  37 import java.awt.Window;
  38 import java.awt.Insets;
  39 import java.awt.EventQueue;
  40 import java.awt.SecondaryLoop;

  41 import java.awt.event.AWTEventListener;
  42 import java.awt.event.ComponentEvent;
  43 import java.awt.event.FocusEvent;
  44 import java.awt.event.HierarchyEvent;
  45 import java.awt.event.InputEvent;
  46 import java.awt.event.InputMethodEvent;
  47 import java.awt.event.KeyEvent;
  48 import java.awt.event.MouseEvent;
  49 import java.awt.event.MouseWheelEvent;
  50 import java.awt.event.FocusAdapter;
  51 import java.awt.event.FocusListener;
  52 import java.awt.im.InputMethodRequests;
  53 import java.awt.image.BufferedImage;
  54 import java.awt.image.DataBufferInt;
  55 import java.awt.datatransfer.Clipboard;
  56 import java.nio.IntBuffer;
  57 import java.security.AccessController;
  58 import java.security.PrivilegedAction;
  59 import java.util.concurrent.CountDownLatch;
  60 
  61 import javafx.application.Platform;
  62 import javafx.scene.Scene;
  63 
  64 import javax.swing.JComponent;
  65 import javax.swing.SwingUtilities;
  66 
  67 import com.sun.javafx.application.PlatformImpl;
  68 import com.sun.javafx.cursor.CursorFrame;
  69 import com.sun.javafx.embed.AbstractEvents;
  70 import com.sun.javafx.embed.EmbeddedSceneInterface;
  71 import com.sun.javafx.embed.EmbeddedStageInterface;
  72 import com.sun.javafx.embed.HostInterface;
  73 import com.sun.javafx.stage.EmbeddedWindow;
  74 import com.sun.javafx.tk.Toolkit;
  75 import com.sun.javafx.PlatformUtil;
  76 import java.awt.event.InvocationEvent;
  77 
  78 import java.lang.reflect.Method;
  79 import java.util.concurrent.atomic.AtomicInteger;
  80 import sun.awt.AppContext;
  81 import sun.awt.SunToolkit;
  82 import sun.java2d.SunGraphics2D;
  83 import sun.java2d.SurfaceData;
  84 import com.sun.javafx.logging.PlatformLogger;
  85 import com.sun.javafx.logging.PlatformLogger.Level;
  86 






  87 /**
  88 * {@code JFXPanel} is a component to embed JavaFX content into
  89  * Swing applications. The content to be displayed is specified
  90  * with the {@link #setScene} method that accepts an instance of
  91  * JavaFX {@code Scene}. After the scene is assigned, it gets
  92  * repainted automatically. All the input and focus events are
  93  * forwarded to the scene transparently to the developer.
  94  * <p>
  95  * There are some restrictions related to {@code JFXPanel}. As a
  96  * Swing component, it should only be accessed from the event
  97  * dispatch thread, except the {@link #setScene} method, which can
  98  * be called either on the event dispatch thread or on the JavaFX
  99  * application thread.
 100  * <p>
 101  * Here is a typical pattern how {@code JFXPanel} can used:
 102  * <pre>
 103  *     public class Test {
 104  *
 105  *         private static void initAndShowGUI() {
 106  *             // This method is invoked on Swing thread


 168     private volatile int pPreferredHeight = -1;
 169 
 170     // Cached copy of this component's location on screen to avoid
 171     // calling getLocationOnScreen() under the tree lock on FX thread
 172     private volatile int screenX = 0;
 173     private volatile int screenY = 0;
 174 
 175     // Accessed on EDT only
 176     private BufferedImage pixelsIm;
 177 
 178     private volatile float opacity = 1.0f;
 179 
 180     // Indicates how many times setFxEnabled(false) has been called.
 181     // A value of 0 means the component is enabled.
 182     private AtomicInteger disableCount = new AtomicInteger(0);
 183 
 184     private boolean isCapturingMouse = false;
 185 
 186     private static boolean fxInitialized;
 187 












 188     private synchronized void registerFinishListener() {
 189         if (instanceCount.getAndIncrement() > 0) {
 190             // Already registered
 191             return;
 192         }
 193         // Need to install a finish listener to catch calls to Platform.exit
 194         finishListener = new PlatformImpl.FinishListener() {
 195             @Override public void idle(boolean implicitExit) {
 196             }
 197             @Override public void exitCalled() {
 198             }
 199         };
 200         PlatformImpl.addListener(finishListener);
 201     }
 202 
 203     private synchronized void deregisterFinishListener() {
 204         if (instanceCount.decrementAndGet() > 0) {
 205             // Other JFXPanels still alive
 206             return;
 207         }


 433 
 434     /**
 435      * Overrides the {@link java.awt.Component#processMouseEvent(MouseEvent)}
 436      * method to dispatch the mouse event to the JavaFX scene attached to this
 437      * {@code JFXPanel}.
 438      *
 439      * @param e the mouse event to dispatch to the JavaFX scene
 440      */
 441     @Override
 442     protected void processMouseEvent(MouseEvent e) {
 443         if ((e.getID() == MouseEvent.MOUSE_PRESSED) &&
 444             (e.getButton() == MouseEvent.BUTTON1)) {
 445             if (!hasFocus()) {
 446                 requestFocus();
 447                 // this focus request event goes to eventqueue and will be
 448                 // asynchronously handled so MOUSE_PRESSED event will not be
 449                 // honoured by FX immediately due to lack of focus in fx
 450                 // component. Fire the same MOUSE_PRESSED event after
 451                 // requestFocus() so that 2nd mouse press will be honoured
 452                 // since now fx have focus
 453                 AppContext context = SunToolkit.targetToAppContext(this);
 454                 if (context != null) {
 455                     SunToolkit.postEvent(context, e);
 456                 }
 457             }
 458         }
 459 
 460         sendMouseEventToFX(e);
 461         super.processMouseEvent(e);
 462     }
 463 
 464     /**
 465      * Overrides the {@link java.awt.Component#processMouseMotionEvent(MouseEvent)}
 466      * method to dispatch the mouse motion event to the JavaFX scene attached to
 467      * this {@code JFXPanel}.
 468      *
 469      * @param e the mouse motion event to dispatch to the JavaFX scene
 470      */
 471     @Override
 472     protected void processMouseMotionEvent(MouseEvent e) {
 473         sendMouseEventToFX(e);
 474         super.processMouseMotionEvent(e);
 475     }
 476 


 553         }
 554         super.processComponentEvent(e);
 555     }
 556 
 557     // called on EDT only
 558     private void updateComponentSize() {
 559         int oldWidth = pWidth;
 560         int oldHeight = pHeight;
 561         // It's quite possible to get negative values here, this is not
 562         // what JavaFX embedded scenes/stages are ready to
 563         pWidth = Math.max(0, getWidth());
 564         pHeight = Math.max(0, getHeight());
 565         if (getBorder() != null) {
 566             Insets i = getBorder().getBorderInsets(this);
 567             pWidth -= (i.left + i.right);
 568             pHeight -= (i.top + i.bottom);
 569         }
 570         double newScaleFactorX = scaleFactorX;
 571         double newScaleFactorY = scaleFactorY;
 572         Graphics g = getGraphics();
 573         if (g instanceof SunGraphics2D) {
 574             SurfaceData sd = ((SunGraphics2D) g).surfaceData;
 575             newScaleFactorX = sd.getDefaultScaleX();
 576             newScaleFactorY = sd.getDefaultScaleY();
 577         }

 578         if (oldWidth != pWidth || oldHeight != pHeight ||
 579             newScaleFactorX != scaleFactorX || newScaleFactorY != scaleFactorY)
 580         {
 581             createResizePixelBuffer(newScaleFactorX, newScaleFactorY);
 582             if (scenePeer != null) {
 583                 scenePeer.setPixelScaleFactors((float) newScaleFactorX,
 584                                                (float) newScaleFactorY);
 585             }
 586             scaleFactorX = newScaleFactorX;
 587             scaleFactorY = newScaleFactorY;
 588             sendResizeEventToFX();
 589         }
 590     }
 591 
 592     // This methods should only be called on EDT
 593     private boolean updateScreenLocation() {
 594         synchronized (getTreeLock()) {
 595             if (isShowing()) {
 596                 Point p = getLocationOnScreen();
 597                 screenX = p.x;


 748         if (!scenePeer.getPixels(buf, pWidth, pHeight)) {
 749             // In this case we just render what we have so far in the buffer.
 750         }
 751 
 752         Graphics gg = null;
 753         try {
 754             gg = g.create();
 755             if ((opacity < 1.0f) && (gg instanceof Graphics2D)) {
 756                 Graphics2D g2d = (Graphics2D)gg;
 757                 AlphaComposite c = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
 758                 g2d.setComposite(c);
 759             }
 760             if (getBorder() != null) {
 761                 Insets i = getBorder().getBorderInsets(this);
 762                 gg.translate(i.left, i.top);
 763             }
 764             gg.drawImage(pixelsIm, 0, 0, pWidth, pHeight, null);
 765 
 766             double newScaleFactorX = scaleFactorX;
 767             double newScaleFactorY = scaleFactorY;
 768             if (g instanceof SunGraphics2D) {
 769                 SurfaceData sd = ((SunGraphics2D)g).surfaceData;
 770                 newScaleFactorX = sd.getDefaultScaleX();
 771                 newScaleFactorY = sd.getDefaultScaleY();
 772             }

 773             if (scaleFactorX != newScaleFactorX || scaleFactorY != newScaleFactorY) {
 774                 createResizePixelBuffer(newScaleFactorX, newScaleFactorY);
 775                 // The scene will request repaint.
 776                 scenePeer.setPixelScaleFactors((float) newScaleFactorX,
 777                                                (float) newScaleFactorY);
 778                 scaleFactorX = newScaleFactorX;
 779                 scaleFactorY = newScaleFactorY;
 780             }
 781         } catch (Throwable th) {
 782             th.printStackTrace();
 783         } finally {
 784             if (gg != null) {
 785                 gg.dispose();
 786             }
 787         }
 788     }
 789 
 790     /**
 791      * Returns the preferred size of this {@code JFXPanel}, either
 792      * previously set with {@link #setPreferredSize(Dimension)} or


 811         if (!enabled) {
 812             if (disableCount.incrementAndGet() == 1) {
 813                 if (dnd != null) {
 814                     dnd.removeNotify();
 815                 }
 816             }
 817         } else {
 818             if (disableCount.get() == 0) {
 819                 //should report a warning about an extra enable call ?
 820                 return;
 821             }
 822             if (disableCount.decrementAndGet() == 0) {
 823                 if (dnd != null) {
 824                     dnd.addNotify();
 825                 }
 826             }
 827         }
 828     }
 829 
 830     private transient  AWTEventListener ungrabListener = event -> {
 831         if (event instanceof sun.awt.UngrabEvent) {
 832             SwingFXUtils.runOnFxThread(() -> {
 833                 if (JFXPanel.this.stagePeer != null &&
 834                         getScene() != null &&
 835                         getScene().getFocusOwner() != null &&
 836                         getScene().getFocusOwner().isFocused()) {
 837                     JFXPanel.this.stagePeer.focusUngrab();
 838                 }
 839             });
 840         }
 841         if (event instanceof MouseEvent) {
 842             // Synthesize FOCUS_UNGRAB if user clicks the AWT top-level window
 843             // that contains the JFXPanel.
 844             if (event.getID() == MouseEvent.MOUSE_PRESSED && event.getSource() instanceof Component) {
 845                 final Window jfxPanelWindow = SwingUtilities.getWindowAncestor(JFXPanel.this);
 846                 final Component source = (Component)event.getSource();
 847                 final Window eventWindow = source instanceof Window ? (Window)source : SwingUtilities.getWindowAncestor(source);
 848 
 849                 if (jfxPanelWindow == eventWindow) {
 850                     SwingFXUtils.runOnFxThread(() -> {
 851                         if (JFXPanel.this.stagePeer != null) {


 860                         }
 861                     });
 862                 }
 863             }
 864         }
 865     };
 866 
 867     /**
 868      * Notifies this component that it now has a parent component. When this
 869      * method is invoked, the chain of parent components is set up with
 870      * KeyboardAction event listeners.
 871      */
 872     @Override
 873     public void addNotify() {
 874         super.addNotify();
 875 
 876         registerFinishListener();
 877 
 878         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 879             JFXPanel.this.getToolkit().addAWTEventListener(ungrabListener,
 880                 SunToolkit.GRAB_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
 881             return null;
 882         });
 883         updateComponentSize(); // see RT-23603
 884         SwingFXUtils.runOnFxThread(() -> {
 885             if ((stage != null) && !stage.isShowing()) {
 886                 stage.show();
 887                 sendMoveEventToFX();
 888             }
 889         });
 890     }
 891 
 892     @Override
 893     public InputMethodRequests getInputMethodRequests() {
 894         EmbeddedSceneInterface scene = scenePeer;
 895         if (scene == null) {
 896             return null;
 897         }
 898         return new InputMethodSupport.InputMethodRequestsAdapter(scene.getInputMethodRequests());
 899     }
 900 


 911         });
 912 
 913         pixelsIm = null;
 914         pWidth = 0;
 915         pHeight = 0;
 916 
 917         super.removeNotify();
 918 
 919         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 920             JFXPanel.this.getToolkit().removeAWTEventListener(ungrabListener);
 921             return null;
 922         });
 923 
 924         /* see CR 4867453 */
 925         getInputContext().removeNotify(this);
 926 
 927         deregisterFinishListener();
 928     }
 929 
 930     private void invokeOnClientEDT(Runnable r) {
 931         AppContext context = SunToolkit.targetToAppContext(this);
 932         if (context == null) {
 933             if (log.isLoggable(Level.FINE)) log.fine("null AppContext encountered!");
 934             return;
 935         }
 936         SunToolkit.postEvent(context, new InvocationEvent(this, r));
 937     }
 938 
 939     private class HostContainer implements HostInterface {
 940 
 941         @Override
 942         public void setEmbeddedStage(EmbeddedStageInterface embeddedStage) {
 943             stagePeer = embeddedStage;
 944             if (stagePeer == null) {
 945                 return;
 946             }
 947             if (pWidth > 0 && pHeight > 0) {
 948                 stagePeer.setSize(pWidth, pHeight);
 949             }
 950             invokeOnClientEDT(() -> {
 951                 if (stagePeer != null && JFXPanel.this.isFocusOwner()) {
 952                     stagePeer.setFocused(true, AbstractEvents.FOCUSEVENT_ACTIVATED);
 953                 }
 954             });
 955             sendMoveEventToFX();
 956         }


1037                 return cachedPlatformCursor;
1038             }
1039 
1040             // platform cursor not cached yet
1041             final Cursor platformCursor =
1042                     SwingCursors.embedCursorToCursor(cursorFrame);
1043             cursorFrame.setPlatforCursor(Cursor.class, platformCursor);
1044 
1045             return platformCursor;
1046         }
1047 
1048         @Override
1049         public boolean grabFocus() {
1050             // On X11 grab is limited to a single XDisplay connection,
1051             // so we can't delegate it to another GUI toolkit.
1052             if (PlatformUtil.isLinux()) return true;
1053 
1054             invokeOnClientEDT(() -> {
1055                 Window window = SwingUtilities.getWindowAncestor(JFXPanel.this);
1056                 if (window != null) {
1057                     if (JFXPanel.this.getToolkit() instanceof SunToolkit) {
1058                         ((SunToolkit)JFXPanel.this.getToolkit()).grab(window);
1059                     }
1060                 }
1061             });
1062 
1063             return true; // Oh, well...
1064         }
1065 
1066         @Override
1067         public void ungrabFocus() {
1068             // On X11 grab is limited to a single XDisplay connection,
1069             // so we can't delegate it to another GUI toolkit.
1070             if (PlatformUtil.isLinux()) return;
1071 
1072             invokeOnClientEDT(() -> {
1073                 Window window = SwingUtilities.getWindowAncestor(JFXPanel.this);
1074                 if (window != null) {
1075                     if (JFXPanel.this.getToolkit() instanceof SunToolkit) {
1076                         ((SunToolkit)JFXPanel.this.getToolkit()).ungrab(window);
1077                     }
1078                 }
1079             });
1080         }
1081     }
1082 }


  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.embed.swing;
  27 
  28 import java.awt.AlphaComposite;
  29 import java.awt.AWTEvent;
  30 import java.awt.Component;
  31 import java.awt.Cursor;
  32 import java.awt.Dimension;
  33 import java.awt.Graphics;
  34 import java.awt.Graphics2D;
  35 import java.awt.KeyboardFocusManager;
  36 import java.awt.Point;
  37 import java.awt.Window;
  38 import java.awt.Insets;
  39 import java.awt.EventQueue;
  40 import java.awt.SecondaryLoop;
  41 import java.awt.GraphicsEnvironment;
  42 import java.awt.event.AWTEventListener;
  43 import java.awt.event.ComponentEvent;
  44 import java.awt.event.FocusEvent;
  45 import java.awt.event.HierarchyEvent;
  46 import java.awt.event.InputEvent;
  47 import java.awt.event.InputMethodEvent;
  48 import java.awt.event.KeyEvent;
  49 import java.awt.event.MouseEvent;
  50 import java.awt.event.MouseWheelEvent;
  51 import java.awt.event.FocusAdapter;
  52 import java.awt.event.FocusListener;
  53 import java.awt.im.InputMethodRequests;
  54 import java.awt.image.BufferedImage;
  55 import java.awt.image.DataBufferInt;
  56 import java.awt.datatransfer.Clipboard;
  57 import java.nio.IntBuffer;
  58 import java.security.AccessController;
  59 import java.security.PrivilegedAction;
  60 import java.util.concurrent.CountDownLatch;
  61 
  62 import javafx.application.Platform;
  63 import javafx.scene.Scene;
  64 
  65 import javax.swing.JComponent;
  66 import javax.swing.SwingUtilities;
  67 
  68 import com.sun.javafx.application.PlatformImpl;
  69 import com.sun.javafx.cursor.CursorFrame;
  70 import com.sun.javafx.embed.AbstractEvents;
  71 import com.sun.javafx.embed.EmbeddedSceneInterface;
  72 import com.sun.javafx.embed.EmbeddedStageInterface;
  73 import com.sun.javafx.embed.HostInterface;
  74 import com.sun.javafx.stage.EmbeddedWindow;
  75 import com.sun.javafx.tk.Toolkit;
  76 import com.sun.javafx.PlatformUtil;
  77 import java.awt.event.InvocationEvent;
  78 
  79 import java.lang.reflect.Method;
  80 import java.util.concurrent.atomic.AtomicInteger;
  81 



  82 import com.sun.javafx.logging.PlatformLogger;
  83 import com.sun.javafx.logging.PlatformLogger.Level;
  84 
  85 import com.sun.javafx.embed.swing.InteropFactory;
  86 import com.sun.javafx.embed.swing.SwingDnD;
  87 import com.sun.javafx.embed.swing.SwingEvents;
  88 import com.sun.javafx.embed.swing.SwingCursors;
  89 import com.sun.javafx.embed.swing.JFXPanelInterop;
  90 
  91 /**
  92 * {@code JFXPanel} is a component to embed JavaFX content into
  93  * Swing applications. The content to be displayed is specified
  94  * with the {@link #setScene} method that accepts an instance of
  95  * JavaFX {@code Scene}. After the scene is assigned, it gets
  96  * repainted automatically. All the input and focus events are
  97  * forwarded to the scene transparently to the developer.
  98  * <p>
  99  * There are some restrictions related to {@code JFXPanel}. As a
 100  * Swing component, it should only be accessed from the event
 101  * dispatch thread, except the {@link #setScene} method, which can
 102  * be called either on the event dispatch thread or on the JavaFX
 103  * application thread.
 104  * <p>
 105  * Here is a typical pattern how {@code JFXPanel} can used:
 106  * <pre>
 107  *     public class Test {
 108  *
 109  *         private static void initAndShowGUI() {
 110  *             // This method is invoked on Swing thread


 172     private volatile int pPreferredHeight = -1;
 173 
 174     // Cached copy of this component's location on screen to avoid
 175     // calling getLocationOnScreen() under the tree lock on FX thread
 176     private volatile int screenX = 0;
 177     private volatile int screenY = 0;
 178 
 179     // Accessed on EDT only
 180     private BufferedImage pixelsIm;
 181 
 182     private volatile float opacity = 1.0f;
 183 
 184     // Indicates how many times setFxEnabled(false) has been called.
 185     // A value of 0 means the component is enabled.
 186     private AtomicInteger disableCount = new AtomicInteger(0);
 187 
 188     private boolean isCapturingMouse = false;
 189 
 190     private static boolean fxInitialized;
 191 
 192     private static JFXPanelInterop jfxPaneliop;
 193 
 194     static {
 195         InteropFactory instance = null;
 196         try {
 197             instance = InteropFactory.getInstance();
 198         } catch (Exception e) {
 199             throw new ExceptionInInitializerError(e);
 200         }
 201         jfxPaneliop = instance.createJFXPanelImpl();
 202     }
 203 
 204     private synchronized void registerFinishListener() {
 205         if (instanceCount.getAndIncrement() > 0) {
 206             // Already registered
 207             return;
 208         }
 209         // Need to install a finish listener to catch calls to Platform.exit
 210         finishListener = new PlatformImpl.FinishListener() {
 211             @Override public void idle(boolean implicitExit) {
 212             }
 213             @Override public void exitCalled() {
 214             }
 215         };
 216         PlatformImpl.addListener(finishListener);
 217     }
 218 
 219     private synchronized void deregisterFinishListener() {
 220         if (instanceCount.decrementAndGet() > 0) {
 221             // Other JFXPanels still alive
 222             return;
 223         }


 449 
 450     /**
 451      * Overrides the {@link java.awt.Component#processMouseEvent(MouseEvent)}
 452      * method to dispatch the mouse event to the JavaFX scene attached to this
 453      * {@code JFXPanel}.
 454      *
 455      * @param e the mouse event to dispatch to the JavaFX scene
 456      */
 457     @Override
 458     protected void processMouseEvent(MouseEvent e) {
 459         if ((e.getID() == MouseEvent.MOUSE_PRESSED) &&
 460             (e.getButton() == MouseEvent.BUTTON1)) {
 461             if (!hasFocus()) {
 462                 requestFocus();
 463                 // this focus request event goes to eventqueue and will be
 464                 // asynchronously handled so MOUSE_PRESSED event will not be
 465                 // honoured by FX immediately due to lack of focus in fx
 466                 // component. Fire the same MOUSE_PRESSED event after
 467                 // requestFocus() so that 2nd mouse press will be honoured
 468                 // since now fx have focus
 469                 jfxPaneliop.postEvent(this, e);



 470             }
 471         }
 472 
 473         sendMouseEventToFX(e);
 474         super.processMouseEvent(e);
 475     }
 476 
 477     /**
 478      * Overrides the {@link java.awt.Component#processMouseMotionEvent(MouseEvent)}
 479      * method to dispatch the mouse motion event to the JavaFX scene attached to
 480      * this {@code JFXPanel}.
 481      *
 482      * @param e the mouse motion event to dispatch to the JavaFX scene
 483      */
 484     @Override
 485     protected void processMouseMotionEvent(MouseEvent e) {
 486         sendMouseEventToFX(e);
 487         super.processMouseMotionEvent(e);
 488     }
 489 


 566         }
 567         super.processComponentEvent(e);
 568     }
 569 
 570     // called on EDT only
 571     private void updateComponentSize() {
 572         int oldWidth = pWidth;
 573         int oldHeight = pHeight;
 574         // It's quite possible to get negative values here, this is not
 575         // what JavaFX embedded scenes/stages are ready to
 576         pWidth = Math.max(0, getWidth());
 577         pHeight = Math.max(0, getHeight());
 578         if (getBorder() != null) {
 579             Insets i = getBorder().getBorderInsets(this);
 580             pWidth -= (i.left + i.right);
 581             pHeight -= (i.top + i.bottom);
 582         }
 583         double newScaleFactorX = scaleFactorX;
 584         double newScaleFactorY = scaleFactorY;
 585         Graphics g = getGraphics();
 586         newScaleFactorX = GraphicsEnvironment.getLocalGraphicsEnvironment().
 587                           getDefaultScreenDevice().getDefaultConfiguration().
 588                           getDefaultTransform().getScaleX();
 589         newScaleFactorY = GraphicsEnvironment.getLocalGraphicsEnvironment().
 590                           getDefaultScreenDevice().getDefaultConfiguration().
 591                           getDefaultTransform().getScaleY();
 592         if (oldWidth != pWidth || oldHeight != pHeight ||
 593             newScaleFactorX != scaleFactorX || newScaleFactorY != scaleFactorY)
 594         {
 595             createResizePixelBuffer(newScaleFactorX, newScaleFactorY);
 596             if (scenePeer != null) {
 597                 scenePeer.setPixelScaleFactors((float) newScaleFactorX,
 598                                                (float) newScaleFactorY);
 599             }
 600             scaleFactorX = newScaleFactorX;
 601             scaleFactorY = newScaleFactorY;
 602             sendResizeEventToFX();
 603         }
 604     }
 605 
 606     // This methods should only be called on EDT
 607     private boolean updateScreenLocation() {
 608         synchronized (getTreeLock()) {
 609             if (isShowing()) {
 610                 Point p = getLocationOnScreen();
 611                 screenX = p.x;


 762         if (!scenePeer.getPixels(buf, pWidth, pHeight)) {
 763             // In this case we just render what we have so far in the buffer.
 764         }
 765 
 766         Graphics gg = null;
 767         try {
 768             gg = g.create();
 769             if ((opacity < 1.0f) && (gg instanceof Graphics2D)) {
 770                 Graphics2D g2d = (Graphics2D)gg;
 771                 AlphaComposite c = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
 772                 g2d.setComposite(c);
 773             }
 774             if (getBorder() != null) {
 775                 Insets i = getBorder().getBorderInsets(this);
 776                 gg.translate(i.left, i.top);
 777             }
 778             gg.drawImage(pixelsIm, 0, 0, pWidth, pHeight, null);
 779 
 780             double newScaleFactorX = scaleFactorX;
 781             double newScaleFactorY = scaleFactorY;
 782             newScaleFactorX = GraphicsEnvironment.getLocalGraphicsEnvironment().
 783                               getDefaultScreenDevice().getDefaultConfiguration().
 784                               getDefaultTransform().getScaleX();
 785             newScaleFactorY = GraphicsEnvironment.getLocalGraphicsEnvironment().
 786                               getDefaultScreenDevice().getDefaultConfiguration().
 787                               getDefaultTransform().getScaleY();
 788             if (scaleFactorX != newScaleFactorX || scaleFactorY != newScaleFactorY) {
 789                 createResizePixelBuffer(newScaleFactorX, newScaleFactorY);
 790                 // The scene will request repaint.
 791                 scenePeer.setPixelScaleFactors((float) newScaleFactorX,
 792                                                (float) newScaleFactorY);
 793                 scaleFactorX = newScaleFactorX;
 794                 scaleFactorY = newScaleFactorY;
 795             }
 796         } catch (Throwable th) {
 797             th.printStackTrace();
 798         } finally {
 799             if (gg != null) {
 800                 gg.dispose();
 801             }
 802         }
 803     }
 804 
 805     /**
 806      * Returns the preferred size of this {@code JFXPanel}, either
 807      * previously set with {@link #setPreferredSize(Dimension)} or


 826         if (!enabled) {
 827             if (disableCount.incrementAndGet() == 1) {
 828                 if (dnd != null) {
 829                     dnd.removeNotify();
 830                 }
 831             }
 832         } else {
 833             if (disableCount.get() == 0) {
 834                 //should report a warning about an extra enable call ?
 835                 return;
 836             }
 837             if (disableCount.decrementAndGet() == 0) {
 838                 if (dnd != null) {
 839                     dnd.addNotify();
 840                 }
 841             }
 842         }
 843     }
 844 
 845     private transient  AWTEventListener ungrabListener = event -> {
 846         if (jfxPaneliop.isUngrabEvent(event)) {
 847             SwingFXUtils.runOnFxThread(() -> {
 848                 if (JFXPanel.this.stagePeer != null &&
 849                         getScene() != null &&
 850                         getScene().getFocusOwner() != null &&
 851                         getScene().getFocusOwner().isFocused()) {
 852                     JFXPanel.this.stagePeer.focusUngrab();
 853                 }
 854             });
 855         }
 856         if (event instanceof MouseEvent) {
 857             // Synthesize FOCUS_UNGRAB if user clicks the AWT top-level window
 858             // that contains the JFXPanel.
 859             if (event.getID() == MouseEvent.MOUSE_PRESSED && event.getSource() instanceof Component) {
 860                 final Window jfxPanelWindow = SwingUtilities.getWindowAncestor(JFXPanel.this);
 861                 final Component source = (Component)event.getSource();
 862                 final Window eventWindow = source instanceof Window ? (Window)source : SwingUtilities.getWindowAncestor(source);
 863 
 864                 if (jfxPanelWindow == eventWindow) {
 865                     SwingFXUtils.runOnFxThread(() -> {
 866                         if (JFXPanel.this.stagePeer != null) {


 875                         }
 876                     });
 877                 }
 878             }
 879         }
 880     };
 881 
 882     /**
 883      * Notifies this component that it now has a parent component. When this
 884      * method is invoked, the chain of parent components is set up with
 885      * KeyboardAction event listeners.
 886      */
 887     @Override
 888     public void addNotify() {
 889         super.addNotify();
 890 
 891         registerFinishListener();
 892 
 893         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 894             JFXPanel.this.getToolkit().addAWTEventListener(ungrabListener,
 895             jfxPaneliop.setMask());
 896             return null;
 897         });
 898         updateComponentSize(); // see RT-23603
 899         SwingFXUtils.runOnFxThread(() -> {
 900             if ((stage != null) && !stage.isShowing()) {
 901                 stage.show();
 902                 sendMoveEventToFX();
 903             }
 904         });
 905     }
 906 
 907     @Override
 908     public InputMethodRequests getInputMethodRequests() {
 909         EmbeddedSceneInterface scene = scenePeer;
 910         if (scene == null) {
 911             return null;
 912         }
 913         return new InputMethodSupport.InputMethodRequestsAdapter(scene.getInputMethodRequests());
 914     }
 915 


 926         });
 927 
 928         pixelsIm = null;
 929         pWidth = 0;
 930         pHeight = 0;
 931 
 932         super.removeNotify();
 933 
 934         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 935             JFXPanel.this.getToolkit().removeAWTEventListener(ungrabListener);
 936             return null;
 937         });
 938 
 939         /* see CR 4867453 */
 940         getInputContext().removeNotify(this);
 941 
 942         deregisterFinishListener();
 943     }
 944 
 945     private void invokeOnClientEDT(Runnable r) {
 946         jfxPaneliop.postEvent(this, new InvocationEvent(this, r));





 947     }
 948 
 949     private class HostContainer implements HostInterface {
 950 
 951         @Override
 952         public void setEmbeddedStage(EmbeddedStageInterface embeddedStage) {
 953             stagePeer = embeddedStage;
 954             if (stagePeer == null) {
 955                 return;
 956             }
 957             if (pWidth > 0 && pHeight > 0) {
 958                 stagePeer.setSize(pWidth, pHeight);
 959             }
 960             invokeOnClientEDT(() -> {
 961                 if (stagePeer != null && JFXPanel.this.isFocusOwner()) {
 962                     stagePeer.setFocused(true, AbstractEvents.FOCUSEVENT_ACTIVATED);
 963                 }
 964             });
 965             sendMoveEventToFX();
 966         }


1047                 return cachedPlatformCursor;
1048             }
1049 
1050             // platform cursor not cached yet
1051             final Cursor platformCursor =
1052                     SwingCursors.embedCursorToCursor(cursorFrame);
1053             cursorFrame.setPlatforCursor(Cursor.class, platformCursor);
1054 
1055             return platformCursor;
1056         }
1057 
1058         @Override
1059         public boolean grabFocus() {
1060             // On X11 grab is limited to a single XDisplay connection,
1061             // so we can't delegate it to another GUI toolkit.
1062             if (PlatformUtil.isLinux()) return true;
1063 
1064             invokeOnClientEDT(() -> {
1065                 Window window = SwingUtilities.getWindowAncestor(JFXPanel.this);
1066                 if (window != null) {
1067                     jfxPaneliop.grab(JFXPanel.this.getToolkit(), window);


1068                 }
1069             });
1070 
1071             return true; // Oh, well...
1072         }
1073 
1074         @Override
1075         public void ungrabFocus() {
1076             // On X11 grab is limited to a single XDisplay connection,
1077             // so we can't delegate it to another GUI toolkit.
1078             if (PlatformUtil.isLinux()) return;
1079 
1080             invokeOnClientEDT(() -> {
1081                 Window window = SwingUtilities.getWindowAncestor(JFXPanel.this);
1082                 if (window != null) {
1083                     jfxPaneliop.ungrab(JFXPanel.this.getToolkit(), window);


1084                 }
1085             });
1086         }
1087     }
1088 }
< prev index next >