1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 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.AWTEvent; 29 import java.awt.Container; 30 import java.awt.event.KeyAdapter; 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.Method; 34 35 import javax.swing.JComponent; 36 37 class SwingEventDispatcherHelper { 38 39 private static final long MOUSE_MASK = AWTEvent.MOUSE_EVENT_MASK | 40 AWTEvent.MOUSE_MOTION_EVENT_MASK | 41 AWTEvent.MOUSE_WHEEL_EVENT_MASK; 42 43 private static Field dispatcherField; 44 private static Constructor<?> newLightweightDispatcher; 45 private static Method dispatchMethod; 46 private static Method enableEvents; 47 48 // grab this idea from CacioCavallo 49 static void initReflection() { 50 try { 51 52 // lightweight dispatcher 53 dispatcherField = Container.class.getDeclaredField("dispatcher"); 54 dispatcherField.setAccessible(true); 55 56 Class<?> dispatcherCls = Class.forName("java.awt.LightweightDispatcher"); 57 newLightweightDispatcher = 58 dispatcherCls.getDeclaredConstructor(new Class[] { 59 Container.class 60 }); 61 newLightweightDispatcher.setAccessible(true); 62 63 dispatchMethod = dispatcherCls.getDeclaredMethod("dispatchEvent", 64 AWTEvent.class); 65 dispatchMethod.setAccessible(true); 66 67 enableEvents = dispatcherCls.getDeclaredMethod("enableEvents", 68 new Class[] { 69 long.class 70 }); 71 enableEvents.setAccessible(true); 72 73 } catch (Exception ex) { 74 75 System.err.println(ex); 76 77 InternalError err = new InternalError(); 78 err.initCause(ex); 79 throw err; 80 } 81 } 82 83 static void setLightweightDispatcher(JComponent component) { 84 if (dispatcherField == null) { 85 initReflection(); 86 } 87 try { 88 Object dispatcher = newLightweightDispatcher.newInstance(component); 89 enableEvents.invoke(dispatcher, MOUSE_MASK | AWTEvent.KEY_EVENT_MASK); 90 dispatcherField.set(component, dispatcher); 91 component.addKeyListener(new KeyAdapter(){}); 92 } catch (Exception e) { 93 e.printStackTrace(); 94 } 95 } 96 97 /** 98 * Performs lightweight dispatching for the specified event on this window. 99 * This only calls the lightweight dispatcher. We cannot simply 100 * call dispatchEvent() because that would also send the event to the 101 * Toolkit dispatching mechanism (AWTEventListener, etc), which has ugly 102 * side effects, like popups closing too early. 103 * 104 * @param e the event to be dispatched 105 */ 106 static void dispatchEvent(AWTEvent awtEvent, JComponent component) { 107 108 if (dispatcherField == null) { 109 initReflection(); 110 } 111 try { 112 Object dispatcher = dispatcherField.get(component); 113 if (dispatcher != null) { 114 dispatchMethod.invoke(dispatcher, awtEvent); 115 } 116 } catch (Exception ex) { 117 InternalError err = new InternalError(); 118 err.initCause(ex); 119 throw err; 120 } 121 122 123 } 124 }