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

Print this page




  30 import javafx.beans.value.ChangeListener;
  31 import javafx.beans.value.ObservableValue;
  32 import javafx.event.EventHandler;
  33 import javafx.event.EventType;
  34 import javafx.geometry.Point2D;
  35 import javafx.scene.Node;
  36 import javafx.scene.Scene;
  37 import javafx.scene.input.KeyCode;
  38 import javafx.scene.input.KeyEvent;
  39 import javafx.scene.input.MouseButton;
  40 import javafx.scene.input.MouseEvent;
  41 import javafx.scene.input.ScrollEvent;
  42 import javafx.stage.Screen;
  43 import javafx.stage.Window;
  44 import javax.swing.JComponent;
  45 import java.awt.AWTEvent;
  46 import java.awt.Component;
  47 import java.awt.Cursor;
  48 import java.awt.EventQueue;
  49 import java.awt.Toolkit;







  50 import java.awt.event.InputEvent;
  51 import java.awt.event.MouseWheelEvent;
  52 import java.awt.event.WindowEvent;
  53 import java.awt.event.WindowFocusListener;
  54 import java.lang.reflect.InvocationTargetException;
  55 import java.lang.reflect.Method;
  56 import java.nio.IntBuffer;
  57 import java.security.AccessController;
  58 import java.security.PrivilegedAction;
  59 import java.util.ArrayList;
  60 import java.util.HashSet;
  61 import java.util.List;
  62 import java.util.Set;
  63 import java.util.concurrent.locks.ReentrantLock;
  64 import com.sun.javafx.geom.BaseBounds;
  65 import com.sun.javafx.geom.transform.BaseTransform;
  66 import com.sun.javafx.jmx.MXNodeAlgorithm;
  67 import com.sun.javafx.jmx.MXNodeAlgorithmContext;
  68 import com.sun.javafx.scene.DirtyBits;
  69 import com.sun.javafx.sg.prism.NGExternalNode;


 115  *             launch(args);
 116  *         }
 117  *     }
 118  * </pre>
 119  * @since JavaFX 8.0
 120  */
 121 public class SwingNode extends Node {
 122 
 123     private double width;
 124     private double height;
 125     
 126     private double prefWidth;
 127     private double prefHeight;
 128     private double maxWidth;
 129     private double maxHeight;
 130     private double minWidth;
 131     private double minHeight;
 132 
 133     private volatile JComponent content;
 134     private volatile JLightweightFrame lwFrame;

 135 
 136     private volatile NGExternalNode peer;
 137 
 138     private final ReentrantLock paintLock = new ReentrantLock();
 139 
 140     private boolean skipBackwardUnrgabNotification;
 141     private boolean grabbed; // lwframe initiated grab
 142     
 143     private volatile int scale = 1;
 144 
 145     /**
 146      * Constructs a new instance of {@code SwingNode}.
 147      */
 148     public SwingNode() {
 149         setFocusTraversable(true);
 150         setEventHandler(MouseEvent.ANY, new SwingMouseEventHandler());
 151         setEventHandler(KeyEvent.ANY, new SwingKeyEventHandler());
 152         setEventHandler(ScrollEvent.SCROLL, new SwingScrollEventHandler());
 153 
 154         focusedProperty().addListener((observable, oldValue, newValue) -> {


 619                     jlfNotifyDisplayChanged.invoke(lwFrame, scale);
 620                 }
 621             }
 622         });        
 623     }
 624 
 625     @Override
 626     public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
 627         bounds.deriveWithNewBounds(0, 0, 0, (float)width, (float)height, 0);
 628         tx.transform(bounds, bounds);
 629         return bounds;
 630     }
 631 
 632     @Override
 633     public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 634         return alg.processLeafNode(this, ctx);
 635     }
 636 
 637     private class SwingNodeContent implements LightweightContent {
 638         private JComponent comp;


 639         public SwingNodeContent(JComponent comp) {
 640             this.comp = comp;
 641         }
 642         @Override
 643         public JComponent getComponent() {
 644             return comp;
 645         }
 646         @Override
 647         public void paintLock() {
 648             paintLock.lock();
 649         }
 650         @Override
 651         public void paintUnlock() {
 652             paintLock.unlock();
 653         }
 654 
 655         // Note: we skip @Override annotation and implement both pre-hiDPI and post-hiDPI versions
 656         // of the method for compatibility.

 657         public void imageBufferReset(int[] data, int x, int y, int width, int height, int linestride) {
 658             imageBufferReset(data, x, y, width, height, linestride, 1);
 659         }

 660         public void imageBufferReset(int[] data, int x, int y, int width, int height, int linestride, int scale) {
 661             SwingNode.this.setImageBuffer(data, x, y, width, height, linestride, scale);
 662         }
 663         @Override
 664         public void imageReshaped(int x, int y, int width, int height) {
 665             SwingNode.this.setImageBounds(x, y, width, height);
 666         }
 667         @Override
 668         public void imageUpdated(int dirtyX, int dirtyY, int dirtyWidth, int dirtyHeight) {
 669             SwingNode.this.repaintDirtyRegion(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
 670         }
 671         @Override
 672         public void focusGrabbed() {
 673             SwingFXUtils.runOnFxThread(() -> {
 674                 // On X11 grab is limited to a single XDisplay connection,
 675                 // so we can't delegate it to another GUI toolkit.
 676                 if (PlatformUtil.isLinux()) return;
 677 
 678                 if (getScene() != null &&
 679                         getScene().getWindow() != null &&


 697                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 698             });
 699         }
 700         @Override
 701         public void maximumSizeChanged(final int width, final int height) {
 702             SwingFXUtils.runOnFxThread(() -> {
 703                 SwingNode.this.maxWidth = width;
 704                 SwingNode.this.maxHeight = height;
 705                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 706             });
 707         }
 708         @Override
 709         public void minimumSizeChanged(final int width, final int height) {
 710             SwingFXUtils.runOnFxThread(() -> {
 711                 SwingNode.this.minWidth = width;
 712                 SwingNode.this.minHeight = height;
 713                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 714             });
 715         }
 716 

 717         public void setCursor(Cursor cursor) {
 718             SwingFXUtils.runOnFxThread(() -> {
 719                 SwingNode.this.setCursor(SwingCursors.embedCursorToCursor(cursor));
 720             });






































 721         }
 722     }
 723 
 724     private void ungrabFocus(boolean postUngrabEvent) {
 725         // On X11 grab is limited to a single XDisplay connection,
 726         // so we can't delegate it to another GUI toolkit.
 727         if (PlatformUtil.isLinux()) return;
 728 
 729         if (grabbed &&
 730             getScene() != null &&
 731             getScene().getWindow() != null &&
 732             getScene().getWindow().impl_getPeer() != null)
 733         {
 734             skipBackwardUnrgabNotification = !postUngrabEvent;
 735             getScene().getWindow().impl_getPeer().ungrabFocus();
 736             skipBackwardUnrgabNotification = false;
 737             grabbed = false;
 738         }
 739     }
 740 




  30 import javafx.beans.value.ChangeListener;
  31 import javafx.beans.value.ObservableValue;
  32 import javafx.event.EventHandler;
  33 import javafx.event.EventType;
  34 import javafx.geometry.Point2D;
  35 import javafx.scene.Node;
  36 import javafx.scene.Scene;
  37 import javafx.scene.input.KeyCode;
  38 import javafx.scene.input.KeyEvent;
  39 import javafx.scene.input.MouseButton;
  40 import javafx.scene.input.MouseEvent;
  41 import javafx.scene.input.ScrollEvent;
  42 import javafx.stage.Screen;
  43 import javafx.stage.Window;
  44 import javax.swing.JComponent;
  45 import java.awt.AWTEvent;
  46 import java.awt.Component;
  47 import java.awt.Cursor;
  48 import java.awt.EventQueue;
  49 import java.awt.Toolkit;
  50 import java.awt.dnd.DragGestureEvent;
  51 import java.awt.dnd.DragGestureListener;
  52 import java.awt.dnd.DragGestureRecognizer;
  53 import java.awt.dnd.DragSource;
  54 import java.awt.dnd.DropTarget;
  55 import java.awt.dnd.InvalidDnDOperationException;
  56 import java.awt.dnd.peer.DragSourceContextPeer;
  57 import java.awt.event.InputEvent;
  58 import java.awt.event.MouseWheelEvent;
  59 import java.awt.event.WindowEvent;
  60 import java.awt.event.WindowFocusListener;
  61 import java.lang.reflect.InvocationTargetException;
  62 import java.lang.reflect.Method;
  63 import java.nio.IntBuffer;
  64 import java.security.AccessController;
  65 import java.security.PrivilegedAction;
  66 import java.util.ArrayList;
  67 import java.util.HashSet;
  68 import java.util.List;
  69 import java.util.Set;
  70 import java.util.concurrent.locks.ReentrantLock;
  71 import com.sun.javafx.geom.BaseBounds;
  72 import com.sun.javafx.geom.transform.BaseTransform;
  73 import com.sun.javafx.jmx.MXNodeAlgorithm;
  74 import com.sun.javafx.jmx.MXNodeAlgorithmContext;
  75 import com.sun.javafx.scene.DirtyBits;
  76 import com.sun.javafx.sg.prism.NGExternalNode;


 122  *             launch(args);
 123  *         }
 124  *     }
 125  * </pre>
 126  * @since JavaFX 8.0
 127  */
 128 public class SwingNode extends Node {
 129 
 130     private double width;
 131     private double height;
 132     
 133     private double prefWidth;
 134     private double prefHeight;
 135     private double maxWidth;
 136     private double maxHeight;
 137     private double minWidth;
 138     private double minHeight;
 139 
 140     private volatile JComponent content;
 141     private volatile JLightweightFrame lwFrame;
 142     final JLightweightFrame getLightweightFrame() { return lwFrame; }
 143 
 144     private volatile NGExternalNode peer;
 145 
 146     private final ReentrantLock paintLock = new ReentrantLock();
 147 
 148     private boolean skipBackwardUnrgabNotification;
 149     private boolean grabbed; // lwframe initiated grab
 150     
 151     private volatile int scale = 1;
 152 
 153     /**
 154      * Constructs a new instance of {@code SwingNode}.
 155      */
 156     public SwingNode() {
 157         setFocusTraversable(true);
 158         setEventHandler(MouseEvent.ANY, new SwingMouseEventHandler());
 159         setEventHandler(KeyEvent.ANY, new SwingKeyEventHandler());
 160         setEventHandler(ScrollEvent.SCROLL, new SwingScrollEventHandler());
 161 
 162         focusedProperty().addListener((observable, oldValue, newValue) -> {


 627                     jlfNotifyDisplayChanged.invoke(lwFrame, scale);
 628                 }
 629             }
 630         });        
 631     }
 632 
 633     @Override
 634     public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
 635         bounds.deriveWithNewBounds(0, 0, 0, (float)width, (float)height, 0);
 636         tx.transform(bounds, bounds);
 637         return bounds;
 638     }
 639 
 640     @Override
 641     public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 642         return alg.processLeafNode(this, ctx);
 643     }
 644 
 645     private class SwingNodeContent implements LightweightContent {
 646         private JComponent comp;
 647         private volatile FXDnD dnd;
 648 
 649         public SwingNodeContent(JComponent comp) {
 650             this.comp = comp;
 651         }
 652         @Override
 653         public JComponent getComponent() {
 654             return comp;
 655         }
 656         @Override
 657         public void paintLock() {
 658             paintLock.lock();
 659         }
 660         @Override
 661         public void paintUnlock() {
 662             paintLock.unlock();
 663         }
 664 
 665         // Note: we skip @Override annotation and implement both pre-hiDPI and post-hiDPI versions
 666         // of the method for compatibility.
 667         //@Override
 668         public void imageBufferReset(int[] data, int x, int y, int width, int height, int linestride) {
 669             imageBufferReset(data, x, y, width, height, linestride, 1);
 670         }
 671         //@Override
 672         public void imageBufferReset(int[] data, int x, int y, int width, int height, int linestride, int scale) {
 673             SwingNode.this.setImageBuffer(data, x, y, width, height, linestride, scale);
 674         }
 675         @Override
 676         public void imageReshaped(int x, int y, int width, int height) {
 677             SwingNode.this.setImageBounds(x, y, width, height);
 678         }
 679         @Override
 680         public void imageUpdated(int dirtyX, int dirtyY, int dirtyWidth, int dirtyHeight) {
 681             SwingNode.this.repaintDirtyRegion(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
 682         }
 683         @Override
 684         public void focusGrabbed() {
 685             SwingFXUtils.runOnFxThread(() -> {
 686                 // On X11 grab is limited to a single XDisplay connection,
 687                 // so we can't delegate it to another GUI toolkit.
 688                 if (PlatformUtil.isLinux()) return;
 689 
 690                 if (getScene() != null &&
 691                         getScene().getWindow() != null &&


 709                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 710             });
 711         }
 712         @Override
 713         public void maximumSizeChanged(final int width, final int height) {
 714             SwingFXUtils.runOnFxThread(() -> {
 715                 SwingNode.this.maxWidth = width;
 716                 SwingNode.this.maxHeight = height;
 717                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 718             });
 719         }
 720         @Override
 721         public void minimumSizeChanged(final int width, final int height) {
 722             SwingFXUtils.runOnFxThread(() -> {
 723                 SwingNode.this.minWidth = width;
 724                 SwingNode.this.minHeight = height;
 725                 SwingNode.this.impl_notifyLayoutBoundsChanged();
 726             });
 727         }
 728 
 729         //@Override
 730         public void setCursor(Cursor cursor) {
 731             SwingFXUtils.runOnFxThread(() -> {
 732                 SwingNode.this.setCursor(SwingCursors.embedCursorToCursor(cursor));
 733             });
 734         }
 735 
 736         private void initDnD() {
 737             // This is a part of AWT API, so the method may be invoked on any thread
 738             synchronized (SwingNodeContent.this) {
 739                 if (this.dnd == null) {
 740                     this.dnd = new FXDnD(SwingNode.this);
 741                 }
 742             }
 743         }
 744 
 745         //@Override
 746         public synchronized <T extends DragGestureRecognizer> T createDragGestureRecognizer(
 747                 Class<T> abstractRecognizerClass,
 748                 DragSource ds, Component c, int srcActions,
 749                 DragGestureListener dgl)
 750         {
 751             initDnD();
 752             return dnd.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl);
 753         }
 754 
 755         //@Override
 756         public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException
 757         {
 758             initDnD();
 759             return dnd.createDragSourceContextPeer(dge);
 760         }
 761 
 762         //@Override
 763         public void addDropTarget(DropTarget dt) {
 764             initDnD();
 765             dnd.addDropTarget(dt);
 766         }
 767 
 768         //@Override
 769         public void removeDropTarget(DropTarget dt) {
 770             initDnD();
 771             dnd.removeDropTarget(dt);
 772         }
 773     }
 774 
 775     private void ungrabFocus(boolean postUngrabEvent) {
 776         // On X11 grab is limited to a single XDisplay connection,
 777         // so we can't delegate it to another GUI toolkit.
 778         if (PlatformUtil.isLinux()) return;
 779 
 780         if (grabbed &&
 781             getScene() != null &&
 782             getScene().getWindow() != null &&
 783             getScene().getWindow().impl_getPeer() != null)
 784         {
 785             skipBackwardUnrgabNotification = !postUngrabEvent;
 786             getScene().getWindow().impl_getPeer().ungrabFocus();
 787             skipBackwardUnrgabNotification = false;
 788             grabbed = false;
 789         }
 790     }
 791